OmniAICreator/Qiita-1.07M huggingface dataset:
Webサーバでソースポート(送信元ポート番号)を取得する


# 背景
昨今のアドレス共有技術(DS-Lite/MAP-Eなど)に関わる問題として「IP アドレスだけではユーザが特定できなくなること」が指摘されており、通信先のサーバなどでアクセスしてきた送信元ポート番号、正確なタイムスタンプを取ることを[RFC6302](https://datatracker.ietf.org/doc/html/rfc6302)では推奨しています
もちろん、記録されたログが保全（改ざんされていないなど）されることも重要ですね

# で、本題
どうやるか？
（アドレス共有技術の適用はIPv6とセットにされることが多いので、サーバのIPv6化すればいいのですが、ここではおいておいて）

## apache httpdの場合
こんなconfigを設定可能です
%{remote}p　の部分ですね


```httpd.conf
LogFormat "[%h]:%{remote}p %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "[%h]:%{remote}p %l %u %t \"%r\" %>s %b" common
```

### 出力

```
[xxx.xxx.xxx.xxx]:47716 - - [08/May/2013:10:26:10 +0900] "GET / HTTP/1.1" 200 4658 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)"
```


## AWS ELBの場合
[X-Forwarded-Port](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/x-forwarded-headers.html#x-forwarded-port)を使えればいいのですが、これはサーバ側（送信先ポート番号）です
なので、ALB/ELBでアクセスログを取得するしかありません。

方法は、ALB/ELBの属性の編集から、アクセスログを有効化します。指定のS3バケットに保存されます。
![Screen Shot 2021-09-13 at 22.01.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/942a07a7-3d70-673f-cb24-85a95e1f37cd.png)
![Screen Shot 2021-09-13 at 22.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/e6ad73f1-404c-253c-e6af-5b50e844d61c.png)

このログのclient:portに保存されます

AWSLogs/xxxxxxxxxxxx/elasticloadbalancing/ap-northeast-1/2021/MM/DD/xxxxxxxxxxxx_elasticloadbalancing_ap-northeast-1_app.ELB01.xxxxxxxxxxxxxxxx_2021MMDDT0000Z_xx.xxx.xx.xx_xxxxxxxx.log.gz

```
http 2021-MM-DDTHH:MM:SS.nnnnnnZ app/ELB01/xxxxxxxxxxxx xx.xx.xx.xx:1614 172.xx.xx.xx:80 0.002 0.003 0.000 200 200 433 4288 "GET http://xxxxxxxxxxxxxxxx:80/hogehoge.txt HTTP/1.1" "Mozilla/5.0 (Linux; Android 7.0;) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible)" - - arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxxxxxxxx:targetgroup/TG01/xxxxxxxxxxxx "Root=1-xxxxxxxxxxxx "-" "-" 2 2021-MM-DDTHH:MM:SS.nnnnnnZ "forward" "-" "-" "172.xx.xx.xx:80" "200" "-" "-"
```

詳細は公式ドキュメント　[AWS Application Load Balancer のアクセスログ](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html?icmpid=docs_elbv2_consol) 　をご確認ください
SnowPro Core Certificationを2週間で１発合格する方法


##なぜ本記事書くか
クラウドDWHであるSnowflakeの認定試験「**SnowPro Core Certification**（日本語試験）」を受けてきました。
試験勉強始めるに当たって日本語の受験ガイド的なものをいくつか拝見しましたが、役に立った情報もあればそれらの記事執筆当時とは状況が変化しているなと思った内容もあったので、改めて試験情報とおすすめの勉強方法を書き残します。

##筆者の戦績と勉強時間
私は2回受験しました。
つまり１回目の受験では華麗に落ちて２回目の受験で合格しました。
1回目：77%
2回目：85%

業務後１日3時間ペースで1回目で2週間程度、２回目で１週間ほど勉強しましたが、１回目の最初の１週間は振り返ると無駄な労力を使ったなと感じているので以下に記載する方法で勉強すれば**２週間程度の勉強で合格できます**。
エンジニアリングや英語に弱い私でもこれくらいの勉強時間で合格できたので、それらに明るい方ならもっと短い学習時間でも受かるでしょう。

## 合格点
英語試験と日本語試験を受けられますがどちらも合格ラインは80%です。
2021年7月頃までは日本語試験が整備されて間もなかったこともあり救済措置として日本人向け英語試験の合格率が70%になっていたようですが、2021年9月現在はこの救済措置は消滅しています（サポートに確認済み）。

##試験範囲

Snowflake公式のコミュニティサイトである[Snowflake Community](https://community.snowflake.com/s/)に登録すると公式の受験ガイドを入手することができますので学習ガイドを入手しましょう(Home→Get Certified→Download the Core Exam Study Guide) 。
この**Download the Core Exam Study Guide**に記載されている範囲のドキュメントだけ読んで基本的な内容を理解できれば**80%は間違いなく取れます(重要)**。
機械翻訳風味ではあるものの日本語資料も各項目ごとに用意されているので英語資料の意味がわからない場合でも安心です。

出題範囲が記載されているので確認します。
![スクリーンショット 2021-09-13 17.04.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006590/b7703260-63a8-87fb-36b7-6f4ad5369ded.png)

- **Snowflakeの基本設計**や**仮想ウェアハウス**、**データのロード・アンロード**、**Editionごとのサービスの違い**、**権限**等に関しての基本的な設問が非常に多く出題されました。こういったsnowflakeの基本的概念に関わる項目のドキュメントは隅々まで読んでおくと良いです。
- COPY INTO, PUT, GET, SNOWPIPEコマンド等のパラメータ等もざっと見ておきましょう。
- 「マイクロパーティションのサイズは○MBである」といった数値、設定値を問う設問も頻出するのでこれらも覚えておくと点が稼げます。

##教材は全部公式ドキュメントでOK

1. **勉強の基本は試験範囲の公式ドキュメントをひたすら読むだけ**  
これが一番大事です。
私はドキュメントを読みまくるのが苦手なので問題集とかやりたいなーと思って最初は[Quizlet](https://quizlet.com/380510774/snowflake-certification-flash-cards/)とか[Udemy](https://www.udemy.com/topic/snowflake-snowpro-core-certification/)とかで問題を解いてましたがこれら外部教材には問題があります。
  - Quizletは問題がしばらく更新されていないので情報が古い
  - Udemyはかなり沢山コースがあるが試験対策としては効率が悪いコースが存在する  
  私は評価4.3ついているコースを購入して試験５つの内２つ取り組みましたが、TaskやStreamなど試験でほぼ出題されない項目についての出題が無視できないほど出たので残り３つは解かずに返金申請しました。  
  外部教材共通の問題点ですが、クラウドサービスは週次単位でサービスが更新されていくので更新頻度が甘い外部教材を使うと間違った知識をインプットしてしまうことになる恐れがある部分もネックです。  
  その点公式ドキュメントは情報の正確性が高いのでこれを中心に勉強するのが良いと感じました。  
  （余談ですがudemyの試験教材は英語版しかないが、解説をコピペできないために和訳コストがでかくなるのは英語力貧弱マンにとっては痛い）

2. 同じくSnowflake CommunityのLEVEL UPを解く  
公式の問題集なので答えが違うとかはないと思います。
これを一通り解いて間違えた項目、あやふやな項目のドキュメントを隈なく読みます。
**本番の問題レベルは正にLEVEL UPで出題される内容程度**なのでレベル感の獲得にもなります

3. [トライアルアカウント](https://signup.snowflake.com/?utm_source=google&utm_medium=paidsearch&utm_content=go-eta-ld-free-trial&utm_term=c-g-snowflake-p&utm_campaign=ap-jp-jp-Branded&_bt=538251928506&_bk=snowflake&_bm=p&_bn=g&_bg=125245403653&gclid=CjwKCAjw7fuJBhBdEiwA2lLMYZMoeMzXXEgYxZ_R7aqBl38tXkhfUDSUuwdb1VPamzPBx-TDQIDlkBoCgF8QAvD_BwE&gclsrc=aw.ds)を作ってWEB UIを１度は眺めたりしておく
「WEB UIの上部にあるメニューを選べ」といった問題が２回中２回出たのでトライアルアカウントを作って最低限UIを眺めたりDBやQuery History等各メニューの遷移先を確認しておきます。

4. 一通り理解して時間が余ったら外部教材に取り組んでも良い
体系的な知識を獲得した後ならもし問題や答えに間違いがあっても気づくことができるのでUdemyなりに取り組むのも良いです。


勉強時間の比重としては**公式ドキュメント読み込みで7割**、その他（LEVEL UP・トライアルアカウント・外部教材）で3割といったイメージです。

## さいごに
本記事は2021年9月に受験した所感を踏まえての内容ですが、公式ドキュメントをしっかり読むという攻略法は普遍的に有効な試験対策法になり得ますので面倒くさくても重点的に取り組んでいくことをおすすめします。
gitでエラーメモ書き Windows

#いつもと違うPCのときに遭遇したエラー
```
git push リモートリポジトリ名 master
fatal: 'リモートリポジトリ名' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

###リモートリポジトリの指定

```
git remote add リモートリポジトリ名 リモートリポジトリのURL
```

###公開鍵を作成
```
ssh-keygen -t rsa -C "アカウントのメールアドレス"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/PCユーザー名/.ssh/id_rsa): /Users/PCユーザー名/.ssh/鍵の名前（なんでもOK）
Enter passphrase (empty for no passphrase):"パスを入力"
Enter same passphrase again:"パスを再入力"
Your identification has been saved in /Users/PCユーザー名/.ssh/鍵の名前.
Your public key has been saved in /Users/PCユーザー名/.ssh/鍵の名前.pub.
The key fingerprint is:
以下省略
```

###作成した公開鍵の中身をコピー（Windows）
```clip < ~/.ssh/鍵の名前.pub```

###github上で登録
使用したいレポジトリ＞Settings＞Deploykeys
Title：任意
Key：コピーした公開鍵の中身を張り付ける
Add keyを押す

###git bashでpush
```
git push リモートリポジトリ名 master
```

（うまくいかなかったら-fオプションで強制的にpush）


#gut push時に遭遇した（error: 403）
```
remote: Permission to ユーザ名/リポジトリ名.git denied to
fatal: unable to access 'https://github.com/ユーザ名/リポジトリ名.git/': The requested URL returned error: 403
```

###URLにユーザ名
```
git remote set-url origin https://<ユーザ名>@github.com/<ユーザ名>/<リポジトリ名>.git
```

#gut commit時に遭遇した
```git commit -m 'first commit'
error: pathspec 'commit'' did not match any file(s) known to git
```

###ダブルクォーテーションで
```git commit -m "first commit"```


#git remote add時に（fatal: remote origin already exists.）
```
git remote add origin https://github.com/ユーザ名/リポジトリ名.git
error: remote origin already exists.
```

一度originを削除し
```
git remote rm origin
```
```
git remote add origin git@github.com:ユーザ名/リポジトリ名.git
```



#そのほか困ったら
```
git status
```
```
git log
```
```
git show
```
```
git remote
```
ラズパイOSインストール後の初回起動からWi-Fi経由でSSH接続する

#本記事の内容
- ラズパイのOSインストール完了後、初回起動時にWi-Fi経由でSSH接続するために必要な設定とSSHの接続確認を行う。
※Raspberry piのOSインストールの方法は、[前記事]
(https://qiita.com/kanamekun/items/c3c6d4ce0bf073cba570)を参照。


#本記事のポイント
- SSH接続に必要な設定ファイルをSDカードのbootディレクトリにあらかじめ格納することで、ラズパイの初回起動直後からWi-Fi経由でWindows等からSSH接続できる。
- ラズパイ設定向けにキーボードやディスプレイの用意は不要！

#実施環境
- Windows 10
- TeraTarm Version 4.9.4
- Raspberry Pi 2 Model B
- PLANEX 無線LAN子機 GW-USNANO2A ※Raspberry Pi 2はWi-Fi通信モジュールがないため、無線LAN子機をUSBに接続しWi-Fi通信を行う。
- 家庭内の無線LANネットワーク環境にて実施

#手順の流れ 
1. ssh設定ファイルの用意
2. Wi-Fi接続用設定ファイルの用意
3. Raspberry Piの起動
4. Raspberry Piに割り当てられたIPの確認
5. TeraTarmでのSSHログイン

## 1. ssh設定ファイルの用意
ラズパイのssh接続を有効にするため、OSをインストールしたSDカードのbootディレクトリ直下に空の"ssh"ファイルを作成する。
bootディレクトリに配置することで、ラズパイの起動時に自動で適切な場所に配置される。

マウスの右クリックのコンテキストメニューから"新規作成"→"テキストドキュメント"をクリックする。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/39f187cf-b2e5-85da-70e2-5eac555f5511.png)

![02 - コピー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/efefc70f-6a68-eb18-f907-3bab9c628142.png)
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/32f45ee0-5e2d-1360-60ba-1fa3fe3b9863.png)

作成した"新しいテキストドキュメント.txt"のファイル名を"ssh"に変更する。ファイルの拡張子は不要なため、ファイル名から".txt"は削除する。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/a1d4a9e0-be70-5432-0f0a-1af7c7238c39.png)

## 2. Wi-Fi接続用設定ファイルの用意
ラズパイの初回起動時からWi-Fi接続を可能にするため、予めbootディレクトリに設定ファイルを配置しておく。

マウスの右クリックのコンテキストメニューから"新規作成"→"テキストドキュメント"をクリックし、作成されたテキストファイルのファイル名を"wpa_supplicant.conf"に変更する。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/1b79a712-7f38-7888-bb4d-3889656002fe.png)
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/39f8220f-38d4-c5df-f6a0-02426f6e9954.png)

"wpa_supplicant.conf"ファイルをテキストエディタで開き以下の内容を書き込む。

	ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
	country=JP
	update_config=1

	network={
	    ssid="XXXXXXXX"
	    psk="YYYYYYYY"
	}
XXXXXXXXには、接続するWi-FiのSSIDを記載する。
YYYYYYYYには、接続するWi-Fiのパスワードを記載する。

## 3. Raspberry Piの起動
Raspberry Piに無線LAN子機を差し込み、OSを書き込んだSDカードを入れて電源を入れる。
赤と緑のLEDが点灯し、緑のLEDが点滅するのでしばらく待つ。1～2分ほど。

## 4. Raspberry Piに割り当てられたIPの確認
Windowsにてコマンドプロントを起動し`ping raspberrypi.local -4`を実行する。
※同一ネットワークにラズパイが一台しか存在しない前提です。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/73a8865e-e7b5-0300-5961-b716bfdbe69c.png)

表示されたIPアドレスがラズパイに割り当てられたIPアドレスである。
このIPアドレスに対してSSH接続する。


## 5. TeraTarmでのSSHログイン
TeraTarmを起動し、表示されたIPアドレスを入力する。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/5bc672eb-e054-960d-67b1-c334b28f2264.png)

セキュリティ警告が表示された場合は、確認の上"続行"をクリックする。
ユーザ名：pi、パスフレーズは、raspberryを入力し"OK"をクリックする。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/c481a3f5-882c-344e-6e44-096e9d901440.png)

TeraTarmのコンソールにて、SSHログイン出来ることを確認できた。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/8400cb39-5d25-e956-1b3b-97263131d17a.png)

手順は以上。

## 参考文献
本記事の作成に当たり、以下の情報を参考にさせて頂きました。
- [Raspberry Pi 初期設定](https://qiita.com/HeRo/items/c1c30d7267faeb304538)
2.1 Chromeデベロッパーツールの使い方

# Chromeデベロッパーツールとは

Google Chromeに標準搭載されている開発者用の検証ツールです。
Webサイトのパフォーマンス向上などを目的とした多くの機能がありますが、

主に、

- <font color="red">HTML、CSSの検証</font>
- <font color="red">スマートフォン表示(デバイスモード)の検証</font>

に焦点を当てて説明します。

# Chromeデベロッパーツールの起動方法


Google Chromeの右上の3点リーダーアイコン（・・・）から、[その他のツール] > [デベロッパーツール]をクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/c5819cd5-072f-9f5b-c9b5-a1893cad49a2.png" width="50%" />


ショートカット(Windows)

```
Ctrl + Shift + i
```

ショートカット(mac)

```
command + option + i
```

# Chromeデベロッパーツールの表示位置の変更

表示位置は、画面下側の他に、画面の左側／右側／別ウィンドウ表示の4つのパターンに変更することが可能です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/458de5f0-b54f-1b07-1a1e-0de6b656e360.png" width="50%" />

# Chromeデベロッパーツール内の説明

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/18c078c8-bdcf-e865-3b73-05fd64f7c96a.png)


#### ①セレクタモード

セレクタモードアイコンをクリックし、青色にした状態でWebページの要素をクリックし、HTMLやCSSを確認します。

#### Elementsパネル

HTML、CSSを確認、<font color="red">仮編集＆確認</font>するパネルです。
※現在の<font color="red">表示ページを仮編集するのみ</font>で、ページを再表示すると仮編集は破棄されます。

#### ②デバイスモード

スマートフォン表示を確認したり、レスポンシブの確認などに使用します。

#### ➂解像度

解像度を細かく指定する場合に使用します。

#### ④デバイスイメージ

デバイスイメージで表示する場合に使用します。

#### ⑤表示向き（縦・横）

縦表示、横表示を切り替える場合に使用します。

# 参考（詳細）

https://willcloud.jp/knowhow/dev-tools-01/
【PowerShell】Csvファイルを指定行数ごとに分割してExportする 



#【PowerShell】Csvファイルを指定行数ごとに分割してExportする 
初めての投稿です
忘れないようにメモ程度に、、、
##行数の多いCSVを分割したい


研究などで大きなデータをを扱うことがあり、csvファイルを分割して複数の端末に処理させたい。

以下のファイルを分割させたい。

```powershell:Sample.csv&#x20;
性別,数字,URL
女,8363,http://test.net
男,2471,http://example.co.jp
男,7325,http://test.net
女,7682,http://example.co.jp
男,1005,http://sample.com
男,5318,http://test.org
男,3636,http://example.jp
男,6869,http://test.jp
女,7139,http://sample.co.jp
男,9930,http://test.jp
女,2933,http://example.co.jp
男,892,http://test.jp
男,8262,http://sample.com
女,6455,http://test.jp
男,4707,http://sample.co.jp
男,5199,http://example.org
女,251,http://test.com
女,5001,http://example.co.jp
男,7719,http://test.org
女,582,http://test.net
男,3598,http://example.co.jp
女,8149,http://sample.com
男,9911,http://example.net
女,5329,http://test.net
女,3368,http://test.net
女,38,http://example.jp
男,1927,http://example.jp
男,3636,http://sample.com
女,4759,http://test.com
女,3441,http://example.net
```
ファイルを分割するために以下の記事を参考にしてみた。

https://www.sukerou.com/2021/02/powershell.html


```powershell:PowerShell&#x20;分割参考
$i=0; Get-Content Sample.csv -Encoding UTF8 -ReadCount 3 | % {$_ | Out-File "sub_$i.csv" -Encoding UTF8 -Append; $i++}
```

こちらは Get-Contentでcsvを読み込んでおり、-ReadCount　オプションで何行ごとに処理をするのかを指定している。パイプで繋げ% (ForEach-Object)でOut-Fileで出力をしている。
3行処理するごとに$iに1足して書き出すファイル名を変えている。

1行目から3行目までは`sub_0.csv`に書き込まれ、
次に4行目から6行目までは`sub_1.csv`に書き込まれていきます。
こういったようにある行数で切って出力することができます。

しかしこのやり方では少し困ったことが出てくる。

##sub_1.csv以降のファイルにはヘッダーが付かない！！！

```powershell:sub_1.csv&#x20;
男,7325,http://test.net
女,7682,http://example.co.jp
男,1005,http://sample.com

```
`sub_1.csv`以降のファイルにヘッダーが付かないため、ヘッダーが必要な際にヘッダーをつける必要がある。
また、Importしてヘッダーを無理やりつける方法もあるがスマートではない。

##ヘッダーもつけて出力させる方法
先にやり方を書くと以下になる。

```powershell:PowerShell&#x20;example.ps1
#ファイルパス
$Path = "./Sample.csv"
#3行ずつ処理させるための数字
$div = 3
#csv読み込み
$csv = Import-Csv $Path -Encoding UTF8
#csvの行数カウント
$count_rows = Get-Content Sample.csv  | Measure-Object

#出力されるファイル数分ループ
for($i=0;$i -lt $count_rows.Count/$div;$i++){
    #開始位置
    $a = $i*$div
    #終了位置
    $b = $i*$div+$div-1
    
    #指定の行数範囲をファイルへ出力
    $csv[$a..$b] | Export-Csv -NoTypeInformation "./Divided/Data${i}.csv" -Encoding UTF8 
}

```
この出力方法だと配列に入っているcsvが呼ばれるため出力する際にはヘッダーが付与されて出力される。

今回は3行ごとにファイルを分けて出力するするため元の`Sample.csv`の行数(`$count_rows.Count`)から3で割ることによって必要な出力ファイルの数が分かる。
必要なファイル数分のforループ処理を作ってあげる。
`$csv[$a..$b]`この方法でcsvの何行目から何行目まで抜き出すのかを指定し、出力処理を行う。

これで分割してファイルを出力できる。
motioneye for x64 install ubuntu20.04LTS

先に最新verにしときます
 
apt update && sudo apt upgrade -y

motioneyeのベースのもとをインストールしていきます

```
apt install curl motion ffmpeg v4l-utils -y
```

そして次にmotioneyeを動かすpipをインストールしていきます

```
apt-get install python2 -y
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
python2 get-pip.py
```
```
apt install libffi-dev libzbar-dev libzbar0 -y
apt install python2-dev libssl-dev libcurl4-openssl-dev libjpeg-dev -y
apt install python-pil -y
```

motioneyeをインストールしていきます

```
pip2 install motioneye
mkdir -p /etc/motioneye
cp /usr/local/share/motioneye/extra/motioneye.conf.sample /etc/motioneye/motioneye.conf
mkdir -p /var/lib/motioneye
cp /usr/local/share/motioneye/extra/motioneye.systemd-unit-local /etc/systemd/system/motioneye.service
```
motioneyeの自動起動設定

```
systemctl daemon-reload
systemctl enable motioneye
systemctl start motioneye
```
motioneyeの単体アップデート

```
pip2 install motioneye --upgrade
motioneye 再起動
systemctl restart motioneye
```
SystemVerilogの4値型をRustから扱う

# はじめに
以前「[SystemVerilogのDPIでRustを使ってみた](https://qiita.com/dalance/items/3ab71174a829380628ff)」という記事を書きましたが、この時は主にRustのプリミティブ型で扱える範囲内の記述をざっと試しただけでした。
その後、SystemVerilogで書いたRTLの検証モデルをRustで書くことが増えてきて、SystemVerilogの4値型を扱いたくなってきました。SystemVerilogの4値型はそのままRustのプリミティブ型としては扱えないので、そのために作成したライブラリと併せてご紹介します。

# 4値型とは
一般的にソフトウェアでいうビットとは0か1かの2通りの値を取ります。すなわち2値型です。
これを実現するデジタル回路においても同様に、ある配線の電圧が示す値を0か1であるとして設計するのですが、デジタル回路設計においては0/1以外の値も考える必要があり、それを扱うのが4値型です。
SystemVerilogにおける4値型は以下のように定義されています。

* 0: 0またはfalse
* 1: 1またはtrue
* x: 不定値
* z: ハイ・インピーダンス

0と1はそのままですが、x/zという2つが追加されています。xすなわち不定値は「0か1か分からない」という意味です。例えば、電源投入直後のメモリの値は、そのメモリを構成する半導体素子の個体差によってビット毎に0だったり1だったりします。このような場合、0か1かを事前に決めて設計することはできないので「xという特別な値が入っている」として設計・検証します。同様にzは「配線がどこにもつながっていないので0でも1でもない」といった状況を示すのに使われます。

この4値型をDPI（SystemVerilogとC言語間のFFIみたいなもの）経由でSystemVerilogからRustへ受け渡すことを考えます。

# DPIから見た4値型

DPIによって4値型をどのように受け渡すかは、SystemVerilogの言語仕様（IEEE 1800-2017）で以下のように決まっています。

```c
/*
* DPI representation of packed arrays.
* 2-state and 4-state vectors, exactly the same as PLI's avalue/bvalue.
*/
#ifndef VPI_VECVAL
#define VPI_VECVAL
typedef struct t_vpi_vecval {
uint32_t aval;
uint32_t bval;
} s_vpi_vecval, *p_vpi_vecval;
#endif
/* (a chunk of) packed logic array */
typedef s_vpi_vecval svLogicVecVal;
```

`svLogicVecVal`が32ビットの4値を表す型で、DPIからはこの`svLogicVecVal`の配列がRustに渡されます。すなわち

```rust
#[repr(C)]
pub struct svLogicVecVal {
    pub aval: u32,
    pub bval: u32,
}

#[no_mangle]
pub extern "C" fn get_data(data: &[svLogicVecVal; 4]) {
}
```

というような`get_data`をCの関数としてエクスポートすれば、SystemVerilogから4値型を受け取ることができます。
ここで`&[svLogicVecVal; 4]`と長さ4の配列にしているのでSystemVerilog側は 32 * 4 = 128 ビットを渡します。

```verilog
import "DPI-C" function void get_data(
  input logic [127:0] data
);
```

# Sv4State

規格上定義されている`svLogicVecVal`のままでは扱いにくいので、Rustから扱いやすいように `Sv4State` という型を用意しました。

https://github.com/dalance/sv4state

例えば

```rust
#[no_mangle]
pub extern "C" fn get_data(data: &[svLogicVecVal; 4]) {
    let sv_u32 = Sv4State::<u32>::from_dpi(data);
    println!("{:x}", sv_u32[0]);
    println!("{:x}", sv_u32[1]);
    println!("{:x}", sv_u32[2]);
    println!("{:x}", sv_u32[3]);
}
```

のように使います。
`Sv4State`は [`std::fmt::LowerHex`](https://doc.rust-lang.org/std/fmt/trait.LowerHex.html)を実装しているので `{:x}` でいい感じに16進数表示できます。

また、`Sv4State`の`v`で32bitの値（x/zのビットは0としたもの）を、`x`と`z`でそれぞれx/zのビットフラグを得ることができます。

```rust
#[no_mangle]
pub extern "C" fn get_data(data: &[svLogicVecVal; 4]) {
    let sv_u32 = Sv4State::<u32>::from_dpi(data);
    println!("{:x}", sv_u32[0].v);
    println!("{:x}", sv_u32[0].x);
    println!("{:x}", sv_u32[0].z);
}
```

# サンプル

以前の記事で紹介したサンプルに `Sv4State` を使ったものも追加しました。

https://github.com/dalance/rust-dpi-sample
【Rails】gemのアンインストールの仕方

### 1.背景
Rubyを使用して個人開発を行っています。
使用を検討していたgem(ActiveRecord)をインストールしたものの結局使わなかったのでアンインストールしたところ、
~~別プロジェクトのデータベースが消えてしまい、**「慎重にやっておけば良かった...」**と思いました。~~
データベースは削除されていませんでした。なのでアンインストールの仕方を備忘録としてまとめます。

### 2.環境
- mac.os バージョン10.15.6
- Ruby 2.7.3
- Rails 6.1.3.1
- psql (PostgreSQL) 12.6

### 3.アンインストールを実行
下記のコマンドを実行し、Gemfileからも削除、`bundle install`を行いました。

```ruby
project_name % bundle exec gem uninstall ActiveRecord
```

#### 補足:bundle execコマンドについて
bundle execコマンドとは、アプリのGemfile.lockに記載されているgemを使用するコマンドを言います。今回の場合だと該当プロジェクト内のGemfile.lockに沿ってアンインストールが実行されていることになります。

### 4.gemとは

gemをまとめると下記のようになります。

- ライブラリのうち、外部ライブラリに該当する
- インストールと読み込みで使用することができる
- 外部ライブラリのファイルやフォルダを1つのgem形式のファイルにパッケージングされたもの


### 5.インストール時とアンインストール時の違い

インストールを行うと`gem list`に追加され、アンインストールを行うと`gem list`から削除されます。

```Ruby
# project_name % gem list　　（--local） gem名
project_name % gem list　　Activerecord

*** LOCAL GEMS ***

# gem名 (カッコ内はバージョン名) が表示される
# アンインストールするとブランクになる
activerecord (6.1.3.2, 6.1.3.1, 6.1.3, 6.1.2.1, 6.0.3.4)
activerecord-import (1.0.8)
kaminari-activerecord (1.2.1)
...
```

#### 補足:アンインストールの使用例

- （本当に）不要になったとき
- 古いバージョンのものを削除したいとき

※アップデートした結果、残った古いバージョンのgemを削除する場合は
`gem cleanup`というコマンドもあります。


### 6.参考
1.[【Rails】gemのアンインストール・バージョン変更](https://qiita.com/manbolila/items/f412a29782e4352d1168)
2.[library rubygems](https://docs.ruby-lang.org/ja/latest/library/rubygems.html)
3.[【Ruby】 gemの仕組みを図解形式で学ぼう](https://pikawaka.com/ruby/how-gem-works)
4.[【Rails】gemとbundleについてまとめてみた](https://qiita.com/mihooo24/items/8c3689bea4e89f613c65)
5.[【Rails】 結局bundlerって何？bundlerの仕組みを図解形式で徹底解説](https://pikawaka.com/rails/bundler)
6.[RubyGemsの使い方](https://zenn.dev/kunosu/articles/5b94459899e70582ae61)

### 7.最後に
記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。
読んでいただき、ありがとうございました。
torchvizで計算グラフを可視化

## Torchvizのインストール

```
$ pip install torchviz
```

## ネットワークの定義

* 可視化したいネットワークを定義する
* 本稿では，ニューラルネットワークを可視化する


```python:NeuralNet.py
import torch
import torch.nn as nn
import torch.nn.functional as F

INPUT_SIZE = 10

class NeuralNet(nn.Module):
    def __init__(self):
        super(NeuralNet, self).__init__()
        self.fc1 = nn.Linear(INPUT, 256)
        self.fc2 = nn.Linear(256, 128)
        self.fc3 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.fc3(x)
        x = F.softamx(x)

        return x
```

## torchvizによる計算グラフの可視化
* torchviz.make_dotにより可視化
* 入力サイズに合わせたデータを用意し，モデルに流す
* その出力と，モデルのパラメータを指定して画像を出力する

```python:visualize_NeuralNet.py
import torch

from torchviz import make_dot
from NeuralNet import NeuralNet

INPUT_SIZE = 28*28

model = NeuralNet()
data = torch.randn(1, INPUT_SIZE)

y = model(data)

image = make_dot(y, params=dict(model.named_parameters()))
image.format = "png"
image.render("NeuralNet")
```

![NeuralNet_784.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359849/e4e648c5-b25d-052b-fa75-06b8cfd4dc78.png)
ABC218 C - Shapes から学んだ 

https://atcoder.jp/contests/abc218/tasks/abc218_c

![218C_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/b09baf36-ee78-6000-ced9-d8f9baabe22e.png)

時間一杯つかったが、time out。

![218C_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/55794413-7cd5-f8d7-881d-c33921723393.png)

納得いったものをコンテスト後に入力したが WA だった。

##改善点1 配列の回転に Append は不向き

```rotated_bad.py
def one(S,T):
    lis = []
    for _ in range(N):
        lis.append([])
 
    for w in range(N):
        for h in range(N-1,-1,-1):
            lis[w].append(T[h][w])
 
    S = make(S)
    lis = make(lis)
    #print(S)
    #print(lis)
    try:
        if check(S,lis):
            return True
    except:
        pass
```

良く書いたな、俺。
**append を使う場合、4 回転、それぞれの場合における
def を用意する必要があり、非効率**

有識者の知恵を借りると
**空欄の配列を用意し、S(orT) を 90 度回転させて代入する関数があれば
関数は一つで済む**事が分かった。

```rotated_good.py
def rotated(S):
    lis = [[" "] * N for _ in range(N)]
    for h in range(N):
        for w in range(N):
           lis[w][N-1-h] = S[h][w]
           #lis[i][j] = S[j][N-1-i]

    #for h in range(N):
    #    print("".join(lis[h]))
    #print()
    return lis
```

##改善点2 平行移動と言われたら素直に平行移動しよう

当初考えたのは、
図形を含む最小の四角形を切り抜き、
S と T で行い、比較した。
しかし、Wa x 5 が残ってしまった。

平行移動のイメージ、以下の赤線の交点を左上に持っていく。
残りのセルは "." とし、N x N の構成。

![218_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/798a1862-e8eb-0720-1e38-6a7732fcb48e.png)

とりあえず。。赤線の交点を探す。
つまり、"#" が配置されている最小の (i,j) を探す。

```make.py
def make(S,T):

    s_min_i = N
    s_min_j = N
    t_min_i = N
    t_min_j = N

    for h in range(N):
        for w in range(N):
            if S[h][w] == "#":
                s_min_i = min(s_min_i,h)
                s_min_j = min(s_min_j,w)
            if T[h][w] == "#":
                t_min_i = min(t_min_i,h)
                t_min_j = min(t_min_j,w)
```

更に、あまり枠には "." としつつ、
T,S を比較していく。

```make.py
def make(S,T):

    s_min_i = N
    s_min_j = N
    t_min_i = N
    t_min_j = N

    for h in range(N):
        for w in range(N):
            if S[h][w] == "#":
                s_min_i = min(s_min_i,h)
                s_min_j = min(s_min_j,w)
            if T[h][w] == "#":
                t_min_i = min(t_min_i,h)
                t_min_j = min(t_min_j,w)

    Schar = ""
    Tchar = ""
    for h in range(N):
        for w in range(N):
            si = s_min_i + h
            sj = s_min_j + w
            if (si < N and sj < N):
                Schar = S[si][sj]
            else:
                Schar = "."

            ti = t_min_i + h
            tj = t_min_j + w
            if (ti < N and tj < N):
                Tchar = T[ti][tj]
            else:
                Tchar = "."

            if Tchar != Schar:
                #print(False)
                return False
    return True
```

##あとは、4回転して試すだけ

```check.py
for _ in range(4):
    S = rotated(S)
    if make(S,T):
        print("Yes")
        exit()
print("No")
```
【Swift】アプリ内でダークモード/ライトモードを設定したい 


## やりたいこと

アプリ内で、OS設定によらずライトモード/ダークモードを設定したい。


##設定方法

1行加えるだけで、即時にアプリ全体に反映されます。

* ダークモードに設定する場合

```swift:ViewController.swift
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .dark
```

* ライトモードに設定する場合

```swift:ViewController.swift
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .light
```

* OS設定に従う場合

```swift:ViewController.swift
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
```

起動時に設定する場合は、initial view controllerの viewDidLoad() 内に書くと良いでしょう。
なお、AppDelegate内の application(_:didFinishLaunchingWithOptions:) 内に記載しても、うまく動作しません。（詳しく調べてはいませんが、おそらく、UIWindowオブジェクトがまだ構成されていないからではないかと思います。）



##動作確認環境

Xcode: 12.5
iOS: 14.7.1
Swiftバージョン: Swift 5.4


以上
[React]onClickするたびに配列に要素を追加する

<h2>はじめに</h2>

ラジオボタンを押すと、押した選択肢のvalueが配列に追加するようにしたかった。
方法がわからず、記事を探しても中々見つからず苦労したので、こちらに記録しておきます。

<h2>実現したい事</h2>
２つのラジオボタングループがある。
それぞれ３つずつ選択肢があり、ユーザーがクリックした選択肢を配列に追加したい。


![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890970/ade23a9f-d336-1047-ba2f-3eb768aec83b.png)

<h2>解決策</h2>

```typescript
const initialValue = Array(selections.length).fill('0');
const [formData, setFormData] = useState<string[]>(initialValue);

	const updateSelections = (index: number, value: string) => {
		const newFormData = formData.slice();
		newFormData[index] = value;
		setFormData(newFormData);
	};

///...
return (
		<div>
			<FormLabel>{data.formLabel}</FormLabel>
			<RadioGroup onChange={(e) => updateSelections(index, e.target.value)}>
				{data.options.map((option) => (
					<FormControlLabel
						key={option.value}
						control={<Radio />}
						label={option.label}
						value={option.value}
						id={option.value}
					/>
				))}
			</RadioGroup>
		</div>
	);

```

①formDataを用意
②formDataの初期値を0にする(initialValue)
③onChangeにupdateSelectionsを実行し、index,選択肢のvalueを渡す
　updateSelectionsでは、
　(1)newFormDataによってformDataのコピーを作る。（本物を破壊したくないため）
　(2)newFormData[index]によって、配列・newFormDataのindexの位置にvlue(選択肢の値)を挿入する。
 (3)(2)の値をsetFormDataに入れる
④formDataにonClickごとに選択肢の値が追加されるようになる


　
indexを渡すことで、要素を判別できるようになり、複数個追加できるようになった。
view内でif文を用いた条件分岐のスマートな書き方[Ruby, Rails]

## はじめに

今回の記事はとても局所的なテーマを扱います

Rubyの構文において、以下のようなif文を用いた冗長的な書き方を、よりスマートにまとめます

`app/views/announcement.html.erb`

```html:Before
<th>配信元</th>
<td>
	<% if @announcement.user_id %>
		<%= @announcement.user.name %>
	<% else %>
		管理者
	<% end %>
</td>
```

## 結論

三項演算子を用いて、かつ文字列の部分はStringオブジェクトにします

```html:After
<th>配信元</th>
<td><%= @announcement.user_id ? @announcement.user.name : "管理者" %></td>
```

## 想定状況

announcementインスタンスはuserインスタンスに紐づく、もしくは紐づいていない、状況です

```ruby:app/models/user.rb
class User < ApplicationRecord
  has_many :announcements, dependent: :destroy
end
```

```ruby:app/models/announcement.rb
class Announcement < ApplicationRecord
  belongs_to :client, optional: true
end
```

## ポイント

### 文字列の部分をStringクラスにしていること

以下の場合、`Encountered a syntax error while rendering template`のエラーが発生し、失敗します。理由は、Railsが`<%=  %>`のなかに、存在しない変数もしくはメソッドを探してしまうからです(`管理者`の部分)。

なので、ただの文字列の場合でもクオテーションで囲んであげることで、ただの文字列を文字列オブジェクトにする必要があります。

```html:失敗例
<th>配信元</th>
<td><%= @announcement.user_id ? @announcement.user.name : 管理者 %></td>
# 管理者 → "管理者" こうしないとだめ
```

## さいごに

とても小さなテーマですが、5行が1行になったことは感動しました（知識不足なだけやん

最後までお読み頂きありがとうございました！
Excel VBAからWEB APIを叩くときの注意点

##主旨
ExcelVBAでWEB APIを用いてhttp通信する場合にハマったところをメモ

##概要
Windows10の場合は

```
CreateObject("MSXML2.XMLHTTP")
```
で問題なく通信できたのですが、

Windows7の場合は

```
CreateObject("MSXML2.ServerXMLHTTP")
```
と記述しないとエラーになります。

どうやらTLSのバージョンによるものだという記事も見つけたので、敬意を表してリンクを貼っておきます。
>
https://qiita.com/nkojima/items/c11f6369f4c32b06c90b


ですので、OSなどの環境によらずどんな場合でも

```
CreateObject("MSXML2.ServerXMLHTTP")
```
を使っておくのが無難だと思われます。
【Rails】bulletを使ってN + 1問題解決

#N + 1問題とは

N+1問題とは、データベースからデータを取り出す際に、大量のSQLが発行されてパフォーマンスが低下してしまう問題のことです。以前にN + 1問題について配信してありますので気になった方はご参照ください。

https://qiita.com/kinoshitaken123/items/fb67f7de37c2ff4f0ba2

#bulletとは

N + 1問題がどこに発生しているかお知らせしてくれるgemです。

https://github.com/flyerhzm/bullet

>公式のドキュメント

#導入方法

以下のコードをGemfileに追記。

```gem:Gemfile
group :development do
  gem 'bullet'
end
```

```
$ bundle install
```

#デフォルト設定

```ruby:config/environments/development.rb
Rails.application.configure do
  # ここから
  config.after_initialize do
    Bullet.enable        = true
    Bullet.alert         = true
    Bullet.bullet_logger = true
    Bullet.console       = true
  # Bullet.growl         = true デフォルトでコメントアウト
    Bullet.rails_logger  = true
    Bullet.add_footer    = true
  end
  # ここまでが追加。
end
```
（解説）
* Bullet.enable...Bulletのgemを利用可能
* Bullet.alert...ブラウザにJSのアラート表示
* Bullet.bullet_logger...bulletのログファイルを表示
* Bullet.console...console.logに警告
* Bullet.growl...Growlがインストールされているときに、ポップアップの警告を表示
* Bullet.rails_logger...railsのログに警告を表示
* Bullet.add_footer...画面左下にメッセージを表示

#N + 1問題検出
実際に使用すると、下記の感じで警告が表示。
![スクリーンショット 2021-09-12 14.11.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572216/c4c30092-c774-ec23-12dc-17d61b574915.png)

ご丁寧に修正方法まで記載:grin:

表示の通りコントローラーにincludes[:user])に修正

```
#before
@chats = Chat.all

#after
@chats = Chat.includes(:user)
```

[Before]
![スクリーンショット 2021-09-12 14.37.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572216/be45722b-960d-2659-882a-ae97042edd5e.png)

[After]
![スクリーンショット 2021-09-12 14.57.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572216/b4b6e2a9-466e-6512-14a5-b489e66ca3d8.png)

includesを指定することで関連をまとめて取得し、最小限のクエリ回数を減らせました。

#最後に
N+1問題に自分で気づけない人のために便利だと思いますが、やはり設計、開発でN＋1問題が生じない為にもSQLに強くなる必要があると感じました。今回、SQLのクエリの画像を残すべきところを失念しており申し訳ございません:bow:
Rails6で、An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.が出た時、の対処

Rails6で、下記が出た時の対処

```
An error occurred while installing mysql2 (0.5.3), and Bundler cannot
continue.
```

下記を実行する。

```
$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl/include"
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
```

再度bundle installをする

```
$ bundle install
```
エラー：Routing Error_Uninitialized constant HomesControllerにつまづいた話

Ruby on Rails ver.５．２．５にて通販サイトの作成をするにあたり、namespaceとscope moduleの使い分けができておらず発生したエラー。
初心者ゆえの初歩的なミスですが、備忘録として記しておきます。


■エラー内容
devise　にて管理者側と顧客側を定義し、namespaceによりcontrollerをそれぞれ[controllers/admin]と[controllers/public]に棲み分けて作成しました。
そしてrutes.erbを以下のように記載

![スクリーンショット 2021-09-13 20.34.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2019141/99da92bd-ce8b-107d-1397-74b61a022598.png)

各controllerにアクション名を定義し、いざサーバー起こしてページ確認しようと思ったら、、

Routing Error
Uninitialized Constant HomeController

というエラーが発生。

エラーの内容は、namespaceにて定義されているadmin側のルーティングは辿れるけど、それより前のルーティングは一体どこの階層のコントローラを呼んでんの？分からないよ？というエラーでした。


■解決方法
scope moduleでpublic側も設定してあげないといけなかったようです。
![スクリーンショット 2021-09-13 20.50.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2019141/f574cecd-9114-d7b1-16bf-19d7f576c696.png)

ここで使用した
scope module: 'public' do 〜　end
ですが、namespaceとは異なり、URLに/publicを追加せず、controller#actionにだけpublic/を追加することができるようです。

public側はURLに/publicを表示しないという仕様のため、namespaceで指定しなければいいのか〜と思っていたのですが、コントローラアクションはちゃんとpublicフォルダ内のコントローラを使うよ！と設定してあげないといけなかったんですね。
勉強になりました...。
xamppでローカルにWebサーバを構築する(Windows)


WordPress以外のCMSを利用してみたく
そのためにいちいち
Webサーバに構築するのはめんどうなのでローカルで簡単にできないかと思い
やってみた。（Dockerでもできるよって聞こえてきそうですが）

こちらをインストールする
https://www.apachefriends.org/jp/index.html

フォルダ（C:、D:、F:）はどこでも可
私は`F:`にいれた

`\xampp\htdocs\`に構築したいプロジェクトのフォルダを作成する。
今回は、`50001-test`とする。

`\xampp\apache\conf\extra\httpd-vhosts.conf`に下記を追記する

```
Listen 50001
<VirtualHost *:50001>
    DocumentRoot "F:\xampp\htdocs\50001-test"
</VirtualHost>
```

XAMPPのApasheをSTART

Webサーバー構築完了

参考文献

https://cbc-study.com/

https://miya-system-works.com/blog/detail/104

https://www.javadrive.jp/xampp/mysql/index2.html#section1
VS Code Remote SSHで、could not to connection to エラーの解決方法

#解決までの経緯

![スクリーンショット 2021-09-13 20.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536974/34a562b5-198e-bdb1-3fbc-adac172923aa.png)

大前提として、
**写真下部（写っていませんが出力欄）にLogが出力されていますので、そちらの内容を読み取れば答えが書いていました。**

見方としては、写真の一番下```More Actions...```のボタンを押せば出力の画面が見れます。

##💡解決方法(私の場合)
```
[20:40:57.919] Received install output: /Users/ユーザー名/.ssh/config line 5: garbage at end of line; "#".
[20:40:57.920] Failed to parse remote port from server output
[20:40:57.921] Resolver error: Error: 
```

"#"でコメントをいれていたので、それが原因でparseエラーになっていました。

そのため、```.ssh/config```のコメントを削除すると解決しました。

```config
Host 任意の名前
  HostName [該当のIPアドレス]
  User root
  Port 22
  IdentityFile ~/.ssh/xxxxxxxxxxxxxxx # 秘密鍵が置いてあるパス　←　こちらのコメント削除
```

この後、権限系のエラー

```
Could not establish connection to "OFLog-dev-env": Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
```

が出たので後述します。

その前にその他、試した事です。

##試した事1：remotePlatformを指定

https://www.ei.fukui-nct.ac.jp/2020/05/21/remote-ssh-could-not-to-establish/

## 試した事2：「Remote.SSH: Config File」の設定

https://hidelog.site/vscode_remotessh_connect

私はmacだったので、パスの部分```C:\Users\<PCのユーザー名>\.ssh\config```は

```
User/<PCのユーザー名>/.ssh/config
```

と記載


## 試した事3：remote.SSH.useLocalServer を false に。

https://teratail.com/questions/281897

#（番外）権限エラーの解決

別記事に記載しました。

https://qiita.com/baby-0105/items/a6ead876739906feec75
デベロッパのためのDevSecOpsとは?


##DevSecOpsの関わったきっかけとは？
数ヶ月前のこと、、、数年ぶりにシリコンバレーの友人から連絡があり、devsecops事情について尋ねられました。仕事でdevops開発について触れる機会があり、開発サイクルにおけるセキュリティについて少し調べてみたところ、devsecops関連についてデベロッパ寄りの情報がまだあまりないことに気づきました。
友人と、信頼性が高く実用的なdevsecopsについての記事を一緒に紹介して、devsecopsについてのコミュニティを広げていきたいね、、、ということになりました。

セキュリティというと、重要なのはわかってはいるけれど、面倒で、お固い感じではあるのですが、ITにおけるセキュリティ分野はより重要になってきています。

身の回りで考えてみた場合、例えば、ホームセキュリティを頼んでいても、家族それぞれが自分で鍵を気をつける必要があり、スマホだって、盗まれたり、落とさないようにするのは自分自身。
DevSecOpsに関わらず、調べれば、調べるほど、ITセキュリティは、もう専門家や専門部隊だけの問題ではなく、ユーザーも含めたITに関わる全ての人が意識すべき問題であることがよくわかります。

仮に、自分がデベロッパだとしたら、自分が書いたコードがセキュリティの脆弱性になり被害にあったと聞けば、いい気分ではないだろうし、場合によっては責任を問われることもありそうです。、、、かといって、そこを気にすると、開発の時間がいくらあっても足りなさそう。

デベロッパ、一人ひとりが、セキュリティを意識しつつコードを書くことは重要で、できるだけ努力をしたとしても、知識も時間も限りがあり、自分一人」が気をつけても、チームメンバーが気をつけてくれなければなんだか割に合わないい気がしてきます。
ITのセキュリティに関しては、いろんなレイヤーがあり情報も膨大で、何をやるか、やらないか、時間やお金をかけるか、かけないか、、、なかなか難しい問題です。

##突然の質問ですが、、、鶏肉の食中毒対策ってどうしてますか？
料理をつくる人ならわかると思うのですが、私自身は、食材について、大丈夫かなーと思いつつ、料理をすることが多々あります。例えば、鶏肉。鶏肉のカンピロバクターついてないと思うけど、、、とりあえず、カンピロバクターがついていることを前提に、しっかり加熱すれば大丈夫、、、と、十分な加熱に気をつけつつも、ちょっと不安を抱えつつ料理をしています。

本当は、手軽なカンピロバクターチェッカーのようなものがあり、カンピロバクターがついてない鶏肉であれば一番。そんなものが家庭にあるわけもなく。家庭で、できるのは、カンピロバクターがついているとして、加熱調理を徹底。プロの鶏肉専門店などでは、もっと徹底した管理が必要なのは明らかですよね。


##デベロッパのためのDevSecOpsを一緒に考えたい。
devsecopsを考えることで、より早く、より安心して、より楽しく、開発ができることにつながり、創造の作業に打ち込める環境をつくれるとしたら、、、、ただでさえ、忙しいデベロッパの日々の仕事にセキュリティまで考えるのは、難しそうだけど、開発スピードを落とさずセキュリティ対策もできる方法もあります。

ITに関わらず、より安心して創造に集中できるという環境があることはとても大切なこと。
それが、ツールなのか、ちょっとしたやり方なのか、、、考え方なのか。
私自身は開発者ではないのですが、みなさんと試行錯誤しつつ、一緒に取り組み、考えていけたら嬉しいです。

デベロッパにすぐ役立つ内容を中心に、devsecopsに関連するコンテンツを紹介していく予定です。どうぞよろしくお願いします！！

フォロー、ご質問やフィードバックいただけると嬉しいです。
【Python】整数を16進数に変えるプログラム！

　前回、整数を2進数に変えるプログラムを作成しました。その時の反省点も踏まえつつ、今回は整数を16進数に変えるプログラムを作ってみました。

https://qiita.com/kim-shun/items/db4611e42d7ca7849124

```python
def cal_hexa(num):
    nums = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
    hexa = ""
    while num:
        remainder = num % 16
        hexa = nums[remainder] + hexa
        num //= 16
    return hexa

num = int(input("整数を入力してください："))
result = cal_hexa(num)
print(result)

#Python標準機能の場合
print(hex(num))
```

　出力結果は以下のようになります。

```
整数を入力してください：7770
1E5A
0x1e5a (Python標準機能の場合)
```

　前回は、余りをString型に変えて、配列に入れて、「reverse」で逆順にして、「join」でさらに結合させるという回りくどいやり方をしてしまったので、その辺を修正しました。
　その際に、さまざまなご意見をいただきましたが、自分の中でまだ理解しきれていないやり方は使っていません。これから理解を深めていきます。

<br>
Electronで複数のショートカットに同じ動作を割り当てる

Electronのメニューで拡大 `(Ctrl + プラス)` や縮小 `(Ctrl + マイナス)` を通常のキーでもテンキーでも動作させたかった時のメモ

## 試したバージョン

Electron 13.1.5


## ダメな例

acceleratorに配列で指定できたら素敵、とか思ったけど甘かった。
[issue][issue]にはそれっぽいのが上がっていたが、解決策は↓の例と同じ。

```ts
let template: { label: string; submenu: any }[] = [
  {
    label: "表示",
    submenu: [
      {
        label: "拡大率を戻す",
        accelerator: ["CmdOrCtrl+0", "CmdOrCtrl+num0"],
        role: "resetZoom",
      },
      {
        label: "拡大",
        accelerator: ["CmdOrCtrl+Plus", "CmdOrCtrl+numadd"],
        role: "zoomIn",
      },
      {
        label: "縮小",
        accelerator: ["CmdOrCtrl+-", "CmdOrCtrl+numsub"],
        role: "zoomOut",
      },
    ],
  },
]
```

## 上手くいった例

1. 同じ動作でacceleratorの違うメニューを複数登録
2. 表示したくないメニューに以下を指定する
  - `visible: false` : 項目を非表示にする
  - `acceleratorWorksWhenHidden: true` : 非表示でもacceleratorは動作させる

```ts
let template: { label: string; submenu: any }[] = [
  {
    label: "表示",
    submenu: [
      {
        label: "拡大率を戻す",
        accelerator: "CmdOrCtrl+0",
        role: "resetZoom",
      },
      {
        label: "拡大率を戻す",
        accelerator: "CmdOrCtrl+num0",
        role: "resetZoom",
        visible: false,
        acceleratorWorksWhenHidden: true,
      },
      {
        label: "拡大",
        accelerator: "CmdOrCtrl+Plus",
        role: "zoomIn",
      },
      {
        label: "拡大",
        accelerator: "CmdOrCtrl+numadd",
        role: "zoomIn",
        visible: false,
        acceleratorWorksWhenHidden: true,
      },
      {
        label: "縮小",
        accelerator: "CmdOrCtrl+-",
        role: "zoomOut",
      },
      {
        label: "縮小",
        accelerator: "CmdOrCtrl+numsub",
        role: "zoomOut",
        visible: false,
        acceleratorWorksWhenHidden: true,
      },
    ],
  },
]
```

## 終わりに

メニューにバインドするのやめてイベントハンドラで拾う手もあったかもしれない。
きったないけど動かないより全然良いので我慢。

[issue]: https://github.com/electron/electron/issues/5256
aptでTomcat をインストール

##update
```
sudo apt update
```

##Tomcatのインストール
```
sudo apt install tomcat9 tomcat9-admin
```

##Tomcatを自動起動するように設定。
```
sudo systemctl enable tomcat9
```

##ファイアウォールポートを開く
```
sudo ufw allow from any to any port 8080 proto tcp
```

##Tomcat起動確認
ブラウザで下記アクセス
自身のipアドレス:8080

##tomcat「tomcat-users.xml」を開く
```
sudo vi /etc/tomcat9/tomcat-users.xml 
```

##「tomcat-users.xml」に追加記述
```
<role rolename="admin-gui" />
<role rolename="manager-gui" />
<user username="tomcat" password="pass" roles="admin-gui,manager-gui" />
```

元ネタブログの記述が「\<role username=・・・」となっているが、<br>正しくは「\<user username=・・・」。<br>記述を間違うとログインできない。
https://postgresweb.com/ubuntu-20-04-install-tomcat

##Tomcat再起動
```
sudo systemctl restart tomcat9
```
##Tomcat Webアプリケーションマネージャを開く
自身のipアドレス:8080/manager/html

##webapp場所
```
/var/lib/Tomcat8/webapps
```
##アプリケーションの起動確認
```
http://＜Tomcatが動いているマシンのIP＞:8080/<アプリケーション名>
```
`例）http://192.168.●●.●●:8080/●●●-●.●.●-SNAPSHOT`

参考
https://postgresweb.com/ubuntu-20-04-install-tomcat
PythonでXGBoost

公式

https://xgboost.readthedocs.io/en/latest/parameter.html

https://htomblog.com/python-xgboost

pandas型で説明変数/被説明変数、学習/テスト、データを用意する。
x_train, y_train
x_valid, y_valid

モデルを作成して予測値を計算する。

```python
import pandas as pd
import xgboost as xgb

dtrain = xgb.DMatrix(x_train,y_train)
dvalid = xgb.DMatrix(x_valid,y_valid)

params = {
    "objective" : "reg:squarederror",
    "eval_metric" : "rmse"
}

model = xgb.train(
    params = params,
    dtrain = dtrain,
    evals = [(dtrain, "train"), (dvalid, "valid")],
    num_boost_round = 100
)

pred = model.predict(xgb.DMatrix(x_valid))
```

プロットする。

```python
import matplotlib.pyplot as plt
import numpy as np

plt.scatter(y_valid, pred, alpha = 0.5)
plt.plot(np.linspace(0, 200, 400), np.linspace(0, 200, 400), "red")
plt.show()
```

誤差を調べる。

```python
from sklearn.metrics import mean_squared_error

mse = mean_squared_error(y_valid, pred)
rmse = np.sqrt(mse)
print(rmse)
```
php-fpm再起動手順

# php-fpm再起動手順

## 目的
初心者でもphp-fpmサービスを再起動できる手順書であること。

## 前提
rootに変更する為のパスワードを把握できていること。

## 手順

### 1. rootユーザになる

以降の操作は全てrootユーザで行いますので、必ずrootに変わってください。

```
su -
```

### 2. パスワードの入力
パスワードの入力を求められるので入力する。

### 3. php-fpmのプロセスが実行中である事を確認する。
以下のコマンドを投入します。

```
ps -ef | grep php-fpm
```

以下の画像のように、「php-fpm: pool www」という記載が複数見られればOK。
![01. php-fpm-01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/44a650d8-0a85-88b5-68ff-96ac08532965.png)


### 4. php-fpmのサービスが正常に起動している事を確認
以下のコマンドを投入します。

```
systemctl status php-fpm.service
```

以下のように、「Active: active (running)」という緑色の表記であればOK。

![02. php-fpm-02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/3d4eb976-2739-01db-3636-bb513ab05779.png)


### 5. サービスのステータス確認を終了
[ctrl]+[c]で抜ける。

### 6. php-fpmサービスを再起動
以下のコマンドを投入します。

```
systemctl restart php-fpm.service
```

コマンド投入後は何も起こらず、改行されたかのように、以下画像のように表示されていればOK。

![03. php-fpm-03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/8e93992e-03ff-56c7-48a4-2822ab2d5c68.png)


### 7. php-fpmのステータスを確認
4と同じコマンドを投入。

```
systemctl status php-fpm.service
```

以下のように、「Active: active (running)」という緑色の表記であればOK。

![04. php-fpm-04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/d76cb85b-fd36-1016-8bbb-a02bb392765f.png)


### 8. サービスのステータス確認を終了
[ctrl]+[c]で抜ける。

以上です。
【Linux】無理矢理ログのアーカイブ【Shell】

ローテ設定を使わずにログのアーカイブ(力業)
logディレクトリに「yyyymmdd.log」というログが吐かれているとして、
シェル実行のタイミングで前月のログが存在するかどうか判定し、存在する場合は月ごとにアーカイブせぇ！！
な時のメモ。

```shell
##ログアーカイブ処理
THIS_MONTH=`date +'%Y%m01'`
TARGET_MONTH=`date -d "${THIS_MONTH} 1 month ago" +'%Y%m'`
cd /work/log/
ls |grep "${TARGET_MONTH}" |grep log >/dev/null 2>&1
if [ $? = 0 ]; then
  ls |grep "${TARGET_MONTH}" |grep ".log" |tar -cvz -T - --null -f ${TARGET_MONTH}.tar.gz --remove-files
  echo "Create_Archive_Log : ${TARGET_MONTH}.tar.gz"
else
  echo "NO_Archive_Log"
fi
```

・TARGET_MONTH変数にはスクリプトを実行した時点からみて前月のyyyymmが入ります。
・lsはファイルがあると0、ないと1を返すのでそれで判定。grep2つでyyyymmかつ、.logで当てはまるファイルを検索検索ぅ！※ここはfindとかでもOK
・0を返した場合は同じようにlsして出てきたファイルをまとめてtar.gzにした後、削除する
といった感じです。

以上お。


参考↓

https://qiita.com/C_HERO/items/f451549bf91951d7ae6e

https://qiita.com/ryskiwt/items/2dba11ab37412b6be5e9
【Rails6 コメント機能でよくある問題の解決方法】

#実装内容
`以前に投稿したコメント機能実装の記事`では、お伝えできなかったコメント機能で**起こりうる問題点**とその**解決方法**をまとめてみました。

https://qiita.com/taddy_korokoro/items/4d75e33ceb5c7a5124a8

https://qiita.com/taddy_korokoro/items/6faf37702dccb2c7ca32

#解決する問題一覧
- 改行問題
- 半英数字の連続文字によるはみ出し問題

##改行問題（プレビュー）

###before
[![Image from Gyazo](https://i.gyazo.com/8ae6430be65f90358be48e9ad3e067fb.gif)](https://gyazo.com/8ae6430be65f90358be48e9ad3e067fb)

###after
[![Image from Gyazo](https://i.gyazo.com/3f6216e2401e140443700bead78c5169.gif)](https://gyazo.com/3f6216e2401e140443700bead78c5169)

##半英数字の連続文字によるはみ出し問題（プレビュー）

###before
[![Image from Gyazo](https://i.gyazo.com/242da065236f7690dbbd97d5d1852123.gif)](https://gyazo.com/242da065236f7690dbbd97d5d1852123)

###after
[![Image from Gyazo](https://i.gyazo.com/e8ca3abbe112e94d4d4ce0c67a0b3825.gif)](https://gyazo.com/e8ca3abbe112e94d4d4ce0c67a0b3825)

#環境
`macOS Big Sur 11.2.3`
`ruby: 2.7.2`
`rails: 6.1.3`
`jQuery`
`テンプレートエンジン: slim`
`レイアウト: bootstrap4`

#改行問題の解決法
改行しても反映されず、文字が続いて表示されてしまう問題から解決していきます。

```app/views/comments.hide_comments.html.slim
 = comment.comment # before

 = simple_format(comment.comment) # after
```
**Railsのヘルパーメソッド**である`simple_format`を使用することで、コメントを以下の条件で整形し、改行されるようになります。

- 文字列を`<p>`で囲む
- 改行には`<br />`を付与
- 連続した改行は、`</p><p>`を付与

#英数字の連続文字によるはみ出し解決法
**日本語**の場合、`単語の途中でも自動で改行される`のですが、**英数字**の場合、表示範囲を超える連続する長いものは`改行されずはみ出してしまいます`。

```app/assets/stylesheets/application.scss
body {
  // 半角英数折返しの設定
  word-wrap: break-word;
  overflow-wrap: break-word;
}
```

**CSS**の`word-breakプロパティ`を使用し、値を`break-word `とすることで、枠内に収まらない英単語の場合は単語の途中でも折り返しますが、枠内に収まる限り、単語の途中では折り返さないようにしてくれます。また、`overflow-wrap`は`word-wrap`の**古い名称**で、サポートされていないブラウザもあるため、**併記**した方がいいようです。

#最後に
以上でコメント機能でよくある問題の解決方法でした！

実はポートフォリオ完成後にレビュー会を行なったのですが、その時指摘してもらい、初めて気づいた感じでした^^;


間違っている箇所や分かりづらい箇所が多々あるかと思います。
その際は、気軽にコメントいただけれると幸いです。

最後までご覧いただき、ありがとうございました!

https://qiita.com/t_oginogin/items/0164ad76b753fdff9902

https://accelboon.com/tn/css-%E5%8D%8A%E8%A7%92%E8%8B%B1%E6%95%B0%E3%81%AE%E9%80%A3%E7%B6%9A%E6%96%87%E5%AD%97%E3%81%8C%E6%8A%98%E3%82%8A%E8%BF%94%E3%81%99%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B/
RGB to RAW(Bayer)変換の解説

## RGB to RAW変換概要
## 初めに
RGBをRAWのデータに変換する方法として、RGBデータを間引く方法を説明します。
今回は例として256x256x3のRGBデータを128 x 128 x 4のRAWデータに変換するものを図として以下に示します。

 ※一般的なベイヤ配列を想定していますので、ダブルベイヤやクアッドベイヤなどの説明は省かせていただきます。

データサイズは  
$ RGB = [h , w , 3 ]  &rarr;  RAW = [h/2 , w/2 , 4]$
となります。
また、RAWをベイヤ形式に並べると
$ Bayer = [h,w, 1] $
となります。

前述したとおり、データを間引くだけの単純な処理となるが、$G$チャネルと残りの $R,B$チャネルで少しだけ処理が違うことに注意する。　$G$チャネルはRAWに変換する際に奇数行と偶数行で分けて処理をしますが、最終的なベイヤ配列にする際に$R$チャネルと隣り合うものを$Gr$,$B$チャネルと隣り合うものを$Gb$とします。

### R
![RGB2RAW_R.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319778/c7c852af-695b-8e87-ad4f-9909548905f8.png)

```math
RAW_R= \left(
\begin{align}

& R_{0,0}        &  R_{0,2}      & &\cdots  &  &  R_{0,even}     &&   \cdots &   &  R_{0,254}  \\ 
& R_{2,0}        &  R_{2,2}      &  &\cdots    &&  R_{2,even}     &  & \cdots    &&  R_{2,254}  \\
&    \vdots       &                       &  &                  &&                               &&               &  &               \vdots       \\
& R_{252,0}  &  R_{252,2} & &  \cdots  & & R_{252,even}& & \cdots  & &  R_{252,254}  \\ 
&R_{254,0} & R_{254,2} &  &\cdots    && R_{254,even} &&  \cdots   && R_{254,254}  \\
\end{align}
\right)
```
のように、偶数行の偶数列を抽出してRAWデータのRチャネルとします。
### B
![RGB2RAW_B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319778/4eeb42ad-e9ca-f933-4b5e-13e5e6084712.png)


```math
RAW_B= \left(
\begin{align}
& R_{1,1}        &  R_{1,3}      & &\cdots  &  &  R_{1,odd}     &&   \cdots &   &  R_{1,255}  \\ 
& R_{3,1}        &  R_{3,3}      &  &\cdots    &&  R_{3,odd}     &  & \cdots    &&  R_{3,255}  \\
&    \vdots       &                       &  &                  &&                               &&               &  &               \vdots       \\
& R_{253,1}  &  R_{253,3} & &  \cdots  & & R_{253,odd}& & \cdots  & &  R_{253,255}  \\ 
&R_{255,1} & R_{255,5} &  &\cdots    && R_{255,odd} &&  \cdots   && R_{255,255}  \\
\end{align}
\right)
```

$R$の時の逆で、$B$は奇数行の奇数列を抽出します。


### G
![RGB2RAW_G.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319778/ad0050ab-cb1f-71f4-0549-6bbe54d0ef12.png)

$G$チャネルはベイヤ配列にする際に$R,B$と隣り合うものをそれぞれ$G_r,G_b$として抽出します。
$RAW_{G_r} = G_{even,odd}$
$RAW_{G_b} = G_{odd,even}$

## ベイヤ配列 Bayer Array
上の処理で得られたRAWデータを並べ替えることによってベイヤ配列が得られる。
![BayerFilterArray.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319778/66c017bc-5638-e320-53d4-4449e6da85b0.png)




$ RGB = [256 , 256 , 3]  &rarr;  Bayer = [256 , 256 ,1 ] $
という感じにサイズが変わります。
Google DomainsのDNSのMXレコードの記述説明がほんの少しだけ不親切だったので備忘録

普段カスタムレコードを入力する縁が無い人にはわからないだろうなと。
私も含めて

タイプMXを選んだ際、
データの中身には

優先度を数字で入力＋半角スペース＋メールサーバー
と入力すればOK
getStaticPropsで、Apollo Clientを使うと出たエラーへの対処

# 前提
Next.js, Auth0, Hasura, Apolloを使用しています。

# 問題
```TypeScript:[quizId].tsx
export const getStaticProps: GetStaticProps = async (context) => {
  const apolloClient = initializeApollo()
  const { data } = await apolloClient.query<GetQuizByIdQuery>({
    query: GET_QUIZ_BY_ID,
    variables: { id: context.params.quizId },
  })

  return {
    props: { data: data.quiz_by_pk },
    revalidate: 1,
  }
}
```
getStaticProps内で、Apolloの初期化を行うとエラーがでました。
Auth0を使用してない場合は、エラーは出ませんでした。

![スクリーンショット 2021-09-13 19.36.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568465/87d67831-b186-84d0-27e8-c22116ee1d2f.png)



# 解決策
こちらに解決策がありました。
https://github.com/apollographql/apollo-client/issues/6765

get~propsのnode-fetchにパッチを当てることで、解決できるようです。
具体的には、_document.tsx内に下記を追記で解消できました。

```TypeScript:_document.tsx
import fetch from 'node-fetch'
import { abortableFetch } from 'abortcontroller-polyfill/dist/cjs-ponyfill'

global.fetch = abortableFetch(fetch).fetch
```

Auth0を使っていないAppでは出なかったエラーなので、@auth0/auth0-react辺りが怪しいと思いつつ、
いまいち原因がわかりませんでした。。。
[Ruby] AtCoder 過去問 B - Collatz Problem

##はじめに
AtCoder過去問B問題をRubyで解いてみました。
他の方々の解き方を見ていると自分の解き方をしている人は見かけなかったので考え方少し変なのかなと思いながら、ACいただいているからいっかと思ったりしています。

それではよろしくお願いします。
問題はこちらから確認してください。↓

https://atcoder.jp/contests/abc116/tasks/abc116_b

##B - Collatz Problem

まずは入力を受け取ります、今回はシンプルですね。
integerで受け取ります。


```ruby
s = gets.to_i
```

aを配列で管理します。
入力値が初期値となるので配列aに入れておきます。

```ruby
s = gets.to_i

a = [s]
```

問題文に従って条件分岐をして、配列aに追加するif文を作ります。

```ruby
s = gets.to_i

a = [s]

if s % 2 == 0
  s = s/2
  a << s
else 
  s = 3*s +1
  a << s
end
```

このifの処理を繰り返すのですが、uniqメソッドを使って条件式を作成します。

配列aの要素が重複したらuniqメソッドで重複している要素を取り除きます。
uniqメソッドを使用した配列aと何もメソッドを使っていない配列aが同じ間はifの処理を繰り返すようにします。

要素が重複したらこの条件から外れるので処理が終わります。

```ruby
s = gets.to_i
 
a = [s]
 
while a.uniq == a
  if s % 2 == 0
    s = s/2
    a << s
  else 
    s = 3*s +1
    a << s
  end
end
```

処理が終わった時点の配列aの要素の数=答えですのでlengthメソッドで出力して完成です。

```ruby
s = gets.to_i
 
a = [s]
 
while a.uniq == a
  if s % 2 == 0
    s = s/2
    a << s
  else 
    s = 3*s +1
    a << s
  end
end

puts a.length
```