OmniAICreator/Qiita-1.07M huggingface dataset:
google colabのpythonとcudaのバージョンを変更する

# はじめに
tensorflow-gpu 1.13.2環境でモデルを動かすためにgoogle colabのpythonとcudaのバージョンを変更した時のメモです。  

変更前
python: 3.8.16
cuda: 11.2

変更後
python: 3.6.9
cuda: 10.0

# pythonのバージョンの変更
以下のコマンドで現在のバージョンを確認する。
```
!python3 -V
```
```
Python 3.8.16
```
以下のコマンドを実行する。
```
!sudo update-alternatives --config python3
```
このような出力が出てくるので、python3.6に変更したい場合は、「Press <enter> to keep the current choice[*], or type selection number:」の後に1を入力する。
```
There are 2 choices for the alternative python3 (providing /usr/bin/python3).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.8   2         auto mode
  1            /usr/bin/python3.6   1         manual mode
  2            /usr/bin/python3.8   2         manual mode

Press <enter> to keep the current choice[*], or type selection number: 1
```
バージョンが変更されたことを確認する。
```
!python3 -V
```
```
Python 3.6.9
```

pipをインストールする。
```
!sudo apt install python3-pip
!wget https://bootstrap.pypa.io/pip/3.6/get-pip.py
!python3 get-pip.py
```

# cudaのバージョンの変更
以下のコマンドで現在のバージョンを確認する。
```
!nvcc -V
```
```
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Sun_Feb_14_21:12:58_PST_2021
Cuda compilation tools, release 11.2, V11.2.152
Build cuda_11.2.r11.2/compiler.29618528_0
```

以下のページを参考にしてcuda 10.0をインストールする。
https://qiita.com/jun40vn/items/0cba2cde743f3f21e2db

以下のコマンドを実行し、cuda 10.0がインストールされたことを確認する。
```
!ls -d /usr/local/cuda-*
```
```
/usr/local/cuda-10.0  /usr/local/cuda-11  /usr/local/cuda-11.2
```

以下のコマンドを実行し、バージョンを変更する。
```
import os
p = os.getenv('PATH')
ld = os.getenv('LD_LIBRARY_PATH')
os.environ['PATH'] = f"/usr/local/cuda-10.0/bin:{p}"
os.environ['LD_LIBRARY_PATH'] = f"/usr/local/cuda-10.0/lib64:{ld}"
```
バージョンが変更されたことを確認する。
```
!nvcc -V
```
```
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:01_CDT_2018
Cuda compilation tools, release 10.0, V10.0.130
```
# tensorflow-gpu 1.13.2のインストール
```
!pip3 install tensorflow-gpu==1.13.2
!pip3 install numpy==1.18.4
!pip3 install pandas==1.0.3
```
バージョンを確認する。
```
!pip3 show tensorflow-gpu
```
```
Name: tensorflow-gpu
Version: 1.13.2
Summary: TensorFlow is an open source machine learning framework for everyone.
Home-page: https://www.tensorflow.org/
Author: Google Inc.
Author-email: opensource@google.com
License: Apache 2.0
Location: /usr/local/lib/python3.6/dist-packages
Requires: absl-py, astor, gast, grpcio, keras-applications, keras-preprocessing, numpy, protobuf, six, tensorboard, tensorflow-estimator, termcolor, wheel
Required-by: 
```
パスを追加する。
```
import sys
sys.path.insert(0,'/usr/local/lib/python3.6/dist-packages')
print(sys.path)
```
```
['/usr/local/lib/python3.6/dist-packages', '/content', '/env/python', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages', '/usr/local/lib/python3.8/dist-packages/IPython/extensions', '/root/.ipython']

```

tensorflowをインポートする。
```
import tensorflow
```

# 参考記事
- https://qiita.com/jun40vn/items/0cba2cde743f3f21e2db
バッチ ジョブを終了しますか (Y/N)? を回避して強制的に終了させる

Windows10にて、あるプログラムにSIGINTを送って、強制終了させたかったが、しがらみだらけだった。
事情があって、SIGKILLではなくSIGINT,もしくはSIGTERMにて、自動的に正常終了させたかった。

まず、Windows環境にはSIGINT, SIGTERMは存在しないので以下のツールを使った。

https://qiita.com/hatt_takumi/items/17377a843e14fb6a6acb

SINGINTに関しては送信することに成功したが、今度はコマンドプロンプトに以下の表示が出て先に進まなくなった。
**バッチ ジョブを終了しますか (Y/N)?**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467051/f8444396-0387-1dc2-45fb-c3921ebb1841.png)

なんでだよ。。。

これもかなり時間かかったが、ユーザーに入力させずに強制的にYで進行する方法があったので記載しておく。
結論から言うと、以下のように目的のコマンドを `start cmd /c` と、`<nul` で挟んでやればよい。

```bat
start cmd /c <目的のコマンド> <nul
```

詳細は以下を参照のこと

https://zenn.dev/zetamatta/books/c84cbe23093eee1b5830/viewer/4f29a0

https://stackoverflow.com/questions/1234571/how-can-i-suppress-the-terminate-batch-job-in-cmd-exe
iOSで簡単に容量不足をエミュレートする方法

# 概要

iOS開発をしている際に容量不足になった場合の動作を確認したい場合の方法です。
エミュレーターで少ない容量でマウントするだけです。

# やり方

## エミュレーターを用意する

XCodeを起動し、メニューの「Window」 -> 「Devices And Simulators」 を選択

左下の「+」を選択して、エミュレーターを作ります。`Identifier` はあとでパスで使います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/bb6d78a0-8277-0def-918c-21976fd6bafc.png" width=450>

## Macにイメージを作り、マウントする

以下のように `/tmp/iosDummy.dmg` にイメージを作ります。
`-size`で、iOSで利用する容量を指定します。この例では1GBの容量を作ってます。OSとアプリが入る大きさの容量は指定しておきましょう。

```zsh
$ hdiutil create -size 1g -fs APFS /tmp/iosDummy.dmg
```

エミュレーターのMac上のパスに移動し、そこに上で作ったイメージをマウントします。

```zsh
$ cd ~/Library/Developer/CoreSimulator/Devices/<上の画像のidentifier>
$ hdiutil attach /tmp/iosDummy.dmg -mountpoint .
```

## アプリをインストール

対象のアプリをインストールします

## 確認する

Settingsアプリ起動 -> 「General」 -> 「About」 -> Capacityが役1GBであれば成功

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/ea40249e-fae2-f89b-82a9-e706f26113c3.png" width=250>


## 上記のエミュレーターに埋め尽くしたい容量のファイルを置く

`dd`コマンドでファイルを作り、エミュレーター上に配置します。bsで容量を指定できます。この場合は200Mです。

```zsh
$ cd data/Downloads
$ dd if=/dev/zero of=a.dummy bs=200M count=1
```

`dd: a.dummy: No space left on device` と出た場合は容量が足りない。少なめにして指定すると成功する。その後、少しづつ容量を増やしていくと成功することがある。

テキスト入力レベルで試したい場合は、data/Documents内にファイルを作れば、その分容量を使うので、細かい単位で調整できると思います。

## マウント解除など

マウント解除します。`df`コマンドでマウントされている箇所を探し、それをunmountします。

```zsh
$ df -H
・・・
/dev/disk5s1     839M    47M   789M     6%     102    7701520    0%   ~/Library/Developer/CoreSimulator/Devices/<上の画像のidentifier>

$ diskutil unmount /dev/disk5s1
Volume untitled on disk5s1 unmounted
```

イメージファイルを削除しときます。

```zsh
$ rm -rf /tmp/iosDummy.dmg
```

　使わなくなったエミュレーターを削除

```zsh
$ rm -rf ~/Library/Developer/CoreSimulator/Devices/<上の画像のidentifier>
```

## トラブルシューティング

### アプリをインストールしようとしたら、「Unable to boot device because it cannot be located on disk.」と表示された

```
$ xcrun simctl erase all
```
ldappasswdコマンドについて

●ldappasswdコマンド
LDAPサーバで管理されているユーザのパスワードを変更するためのコマンド。

ldappasswdコマンドの書式

ldappasswd [-x] [-h LDAPサーバ] -D 認証に利用する識別名 [-w 認証ユーザのパスワード] -s 新パスワード 変更するユーザ名

・-xオプションはldapaddコマンドと同様に、SASL（暗号化したパスワードをネットワーク上に送信するなど、安全な認証を提供する仕組み）を使用せずに簡易認証を行う。

・-wオプションは認証ユーザのパスワードをコマンドラインで指定。省略した場合、または-Wオプションで、コマンド実行後に表示されるプロンプトで対話的にパスワードを入力。

・-sオプションは変更するユーザの新パスワードをコマンドラインで指定。コマンドラインではなくコマンド実行後に表示されるプロンプトで対話的に新パスワードを入力したい場合は、-Sオプションのみを指定。

※ユーザの情報を検索する際、「/etc/passwd」ファイルよりLDAPサーバを優先して利用するには、「/etc/nsswitch.conf」ファイルに以下のように記述。
passwd: ldap files
ソニースピーカ CMT-X5CD/CMT-X7CD RM-AMU196 のリモコンコード

ソニースピーカ CMT-X5CD/CMT-X7CD RM-AMU196 のリモコンコードを調べました。
[Arduino IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote)を用いて取得しました。

再生操作の自動化、紛失リモコンの代替としてお使いください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60150/a7792c33-986d-60bf-b02f-ba7508e0dd62.png)

|名称         |Address|Command|Raw-Data(LSB)|bit配列            |Repeat|Raw-Data(MSB for `sendSony`)|
|-----------|------:|------:|------------:|-----------------|-----:|------------:|
|表示切換       |   0x10|   0x4B|        0x84B|12 bits LSB first|     2|        0xD21|
|電源         |   0x10|   0x15|        0x815|12 bits LSB first|     2|        0xA81|
|ファンクション-   |   0x90|   0x6A|       0x486A|15 bits LSB first|     2|       0x2B01|
|ファンクション+   |   0x90|   0x69|       0x4869|15 bits LSB first|     2|       0x4B01|
|サウンド       |   0x10|   0x70|        0x870|12 bits LSB first|     2|        0x0E1|
|メニュー       |      -|      -|      0x39D73|20 bits LSB first|     0|      0xCEB9C|
|up         |      -|      -|      0x20847|20 bits LSB first|     0|      0xE2104|
|消音         |      -|      -|      0x39D78|20 bits LSB first|     0|      0x1EB9C|
|left       |      -|      -|      0x39D2E|20 bits LSB first|     0|      0x74B9C|
|center     |      -|      -|      0x39D7C|20 bits LSB first|     0|      0x3EB9C|
|right      |      -|      -|      0x39D2F|20 bits LSB first|     0|      0xF4B9C|
|down       |      -|      -|      0x39D79|20 bits LSB first|     0|      0x9EB9C|
|戻る         |      -|      -|      0x39D7D|20 bits LSB first|     0|      0xBEB9C|
|曲削除        |      -|      -|      0x39D0F|20 bits LSB first|     0|      0xF0B9C|
|プリセット - / 前|      -|      -|      0x39D30|20 bits LSB first|     0|      0x0CB9C|
|再生         |      -|      -|      0x39D3A|20 bits LSB first|     0|      0x5CB9C|
|プリセット+ / 次 |      -|      -|      0x39D31|20 bits LSB first|     0|      0x8CB9C|
|選曲 - / 巻き戻し|      -|      -|      0x39D33|20 bits LSB first|     0|      0xCCB9C|
|停止         |      -|      -|      0x39D38|20 bits LSB first|     0|      0x1CB9C|
|選曲 + / 早送り |      -|      -|      0x39D34|20 bits LSB first|     0|      0x2CB9C|
|音量 +       |   0x10|   0x12|        0x812|12 bits LSB first|     2|        0x481|
|音量 -       |   0x10|   0x13|        0x813|12 bits LSB first|     2|        0xC81|


### Arduino IRRemoteを用いる例

```C
// 電源
IrSender.sendSony(0x10, 0x15, 2);
// 再生
IrSender.sendSony(0x5CB9C, 20);
```


## 背景

CMT-X5CD/CMT-X7CDは一昔前の製品ながら、BluetoothやUSBメモリからの再生ができる点が評価できるスピーカです。
CDドライブの寿命が短いこともあり、CD再生不能品がジャンクとしてメルカリ等で販売されていますが、それ以外の機能を使う分には全く問題有りません。

しかしながら、惜しい点がいくつか。

- 起動時、再生可能になるまでに30秒程度待たされる
- USBメモリの再生位置が保存されない

この2点を解決するために、Arduinoで自動操作装置を自作することにしました。
その成果物としてここに共有します。
MySQL カラム　エラー

# はじめに
deviseを用いてユーザー管理機能の実装中にエラーが発生しました。

# エラー内容
`migrateファイル`にてテーブル作成中。
↓以下のようにカラムの設定を実装した。
~~~ruby
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :name,               null: false, default: ""
      t.text   :profile,            null: false, default: ""
      t.text   :occupation,         null: false, default: ""
      t.text   :position,           null: false, default: ""
~~~
↓`rails db:migrate`実行後
~~~ruby
Error: BLOB, TEXT, GEOMETRY or JSON column 'profile' can't have a default value
~~~

上記のエラー文がターミナル上に表示された。

# 問題解決の過程

ネットで調べたところ
`MySQL`でBLOB/text型にはデフォルト設定ができないとのこと。

そのためtext型のデフォルト設定を削除し
↓以下のコーティングで再実行
~~~ruby
 create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :name,               null: false, default: ""
      t.text   :profile,            null: false
      t.text   :occupation,         null: false
      t.text   :position,           null: false
~~~

以上でテーブルの設定が完了した。

# まとめ

MySQLではtext型でデフォルト設定ができない。



最後まで閲覧して頂きありがとうございました。
キャッシュサーバー、コンテンツサーバー

# DNSサーバーの役割
IPアドレスは```数字の羅列```です。何を表しているかわからない。そこでインターネットでは```IPアドレスにドメイン名という名前をつけて```わかりやすくしています。
IPアドレスとドメイン名を相互に変換する仕組みを```DNS(Domain Name System)```という。

## ドメイン名は木構造になっている
ドメイン名とは```www.example.co.jp```のようにドットで区切られた文字列で構成されています。
この一つ一つの文字列のことを```ラベル```と言います。
右から順にトップレベルドメイン、第二レベルドメイン、第三レベルドメイン、...と言います。

## DNSサーバーの種類
DNSサービスを提供するサーバーのことを```DNSサーバー```といいます。DNSサーバーは、```キャッシュサーバー```、```コンテンツサーバー```に大別されます。

### キャッシュサーバーとは？
LAN内にいるクライアントから問い合わせを受け、代わりに```インターネットに問い合わせる```DNSサーバー　です。

### コンテンツサーバーとは？
コンテンツサーバーは、外部のホストから```自分が管理するドメインに関する問い合わせを受ける```DNSサーバーです。
自ドメイン内のホスト名を```ゾーンファイル```というデータベースで管理しています。

## 名前解決の流れ
クライアントから問い合わせを受けたキャッシュサーバーは、受け取ったドメイン名を右から順に検索していき、そのドメイン名を管理しているコンテンツサーバーを辿っていきます。
そこまで辿り着いたら、そのコンテンツサーバーに対して、```ホスト名+ドメイン名```に対応するIPアドレスを教えてもらいます。
このような動作を```名前解決```と言います。

### ホスト名とは？
```www.example.co.jp```の```www```の部分。

### ドメイン名とは？
```www```以外の部分

# 出典
https://www.sbcr.jp/product/4797386660/

* ```ユーザに提供するコンテンツ（情報）を自ら保有・管理しているサーバ```を意味します。
これと対比されるのがキャッシュ サーバです。キャッシュ サーバはコンテンツ サーバが管理するコンテンツの複製を保存し、ユーザからの要求があった場合に、コンテンツ サーバに代わってコンテンツを配信します。
### 出典
https://www.f5.com/ja_jp/services/resources/glossary/content-server#:~:text=%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%20%E3%82%B5%E3%83%BC%E3%83%90%E3%81%A8%E3%81%AF%E3%80%81%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%AB%E6%8F%90%E4%BE%9B%E3%81%99%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%EF%BC%88%E6%83%85%E5%A0%B1%EF%BC%89%E3%82%92%E8%87%AA%E3%82%89%E4%BF%9D%E6%9C%89%E3%83%BB%E7%AE%A1%E7%90%86%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E6%84%8F%E5%91%B3%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%E3%81%93%E3%82%8C%E3%81%A8%E5%AF%BE%E6%AF%94%E3%81%95%E3%82%8C%E3%82%8B%E3%81%AE%E3%81%8C%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%20%E3%82%B5%E3%83%BC%E3%83%90%E3%81%A7%E3%81%99%E3%80%82%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%20%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AF%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%20%E3%82%B5%E3%83%BC%E3%83%90%E3%81%8C%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%81%AE%E8%A4%87%E8%A3%BD%E3%82%92%E4%BF%9D%E5%AD%98%E3%81%97%E3%80%81%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%8B%E3%82%89%E3%81%AE%E8%A6%81%E6%B1%82%E3%81%8C%E3%81%82%E3%81%A3%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AB%E3%80%81%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%20%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AB%E4%BB%A3%E3%82%8F%E3%81%A3%E3%81%A6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E9%85%8D%E4%BF%A1%E3%81%97%E3%81%BE%E3%81%99%E3%80%82
お役立ちリンク集〜アイコン・写真編〜


個人的な感想ですが、そこまでこだわりがなければ、いくつものサイトを探し回ってとびきりいい素材が見つかることは少なく、お気に入りの2,3のサイトで検索する方が作業効率が上がると思っています。

また、フリー素材を使う場合でも以下の点には十分にご注意ください
・二次利用、商用利用可否
・クレジット表記の要否
・サイトごとの利用規約
 
注意：フリー画像でも著作物が写っている場合があり、写真に写っている著作物の管理者へ許諾申請を行うことを推奨します。

それでは、アイコン・写真のおすすめサイトを紹介していきます！

# アイコン
## ICOOON MONO
6000以上のフリーアイコンがダウンロード可能です。
シンプルなアイコンも数多くあり、非常にお世話になっています。
なんといっても会員登録なしで無制限にダウンロード可能なところが魅力的です！

https://icooon-mono.com/

## ヒューマンピクトグラム
人型のアイコンの種類が豊富です！
人が何かしている、特定の職業のアイコンを探すならこちらがおすすめです。

https://pictogram2.com/

## FLAT ICON DESIGN
他のデザインとは一味違うおしゃれさを出したいならこちら。


http://flat-icon-design.com/

# 写真
## Photo AC
フリー写真の王道サイト。ここで探せばなんでも見つかるでしょう。
※建造物など個別に利用許可が必要な場合があります。不安に思ったら写っている建物のサイトで確認しましょう。

https://www.photo-ac.com/

## Pakutaso (パクタソ)
こちらはサイトに登録したカメラマンが撮影した写真ですので、安心して利用できます。登録不要な点もおすすめです。

https://www.pakutaso.com/

最後に、個別に商用利用許可やクレジット表記が必要な場合があるので、十分に気をつけて利用しましょう！


# 旅行アプリ、Tig Travelをリリースしました
おすすめの旅行プランを多数掲載。旅行プランをカスタマイズし、自分だけのプランを簡単に作成できます！

https://play.google.com/store/apps/details?id=com.dig.travelrehack&utm_source=qiita

# イベント管理アプリ、「イツシタ？」をリリースしました
あの遊園地いつ行ったっけ？カレーいつ食べたっけ？友達といつ会ったっけを簡単に記録できるイベント管理アプリです！

https://play.google.com/store/apps/details?id=com.dighack.itsushita&utm_source=qiita
Cognito x Amplify x Swift で認証

### 概要
`Cognito`, `Amplify`を使って認証機能を実装するメモです。

### 環境
`amplify-swift v2`

### 前提
今回はアプリ側の実装や設定にフォーカスします。
また、メールアドレスとパスワードで認証する想定です。
`Cognito`の設定情報はプロジェクトのルートに`amplifyconfigure.json`を設置することにしました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/5b452b5b-9464-c087-9486-6346a1bfe4a8.png" width="400" />

#### 初期設定
Swift Package Managerを使って[amplify-swift](https://github.com/aws-amplify/amplify-swift)を導入します。

その後、`amplifyconfigure.json`に必要情報を記載します。

```json:amplifyconfigure.json
{
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "IdentityManager": {
                    "Default": {}
                },
                "CredentialsProvider": {
                    "CognitoIdentity": {
                        "Default": {
                            "PoolId": "[COGNITO IDENTITY POOL ID]",
                            "Region": "[REGION]"
                        }
                    }
                },
                "CognitoUserPool": {
                    "Default": {
                        "PoolId": "[COGNITO USER POOL ID]",
                        "AppClientId": "[COGNITO USER POOL APP CLIENT ID]",
                        "Region": "[REGION]"
                    }
                },
                "Auth": {
                    "Default": {
                        "authenticationFlowType": "USER_SRP_AUTH"
                    }
                }
            }
        }
    }
}
```

### `AppDelegate.swift`
`AppDelegate`で`Amplify`の初期化を行います。

```swift:AppDelegate.swift
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    do {
        try Amplify.add(plugin: AWSCognitoAuthPlugin())
        try Amplify.configure()
    } catch {
        print(error)
    }
    
    return true
}
```

#### ユーザ作成
サインアップを処理する関数です。

```swift
func signUp(email: String, password: String) async throws {
    let userAttributes = [AuthUserAttribute(.email, value: email)]
    let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
    
    let result = try await Amplify.Auth.signUp(username: email, password: password, options: options)
    if case let .confirmUser(details, _, userID) = result.nextStep {
        print("details: \(details), userID: \(userID)")
    }
}
```

#### 検証
テストします。
`UIViewController`の`viewDidLoad`でサインアップ処理を実施し、AWSマネジメントコンソールにユーザが追加されるか確認します。

確認したところ画像のようにユーザが追加されてました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/418eec80-2ba6-19ee-edf9-1ba5ea622863.png" width="600" />

また、入力したメールアドレスにはCognitoから認証コードが届いてました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/2803f990-185a-f476-4716-8c43672a7019.png" width="400" />

届いた認証コードを使ってユーザを認証する、
サインアップしたユーザでサインインするのが、次のステップになるかと思います。
`Amplify`のSDKを使うことで認証処理を簡単に実装することができました。

### 参考
https://docs.amplify.aws/lib/auth/getting-started/q/platform/ios/#initialize-amplify-auth
ExcelでCSVを取り込んだとき、テーブルデータになった

## やったこと
CSVデータをExcelで取り込んだとき、「テーブル」に変換されました。それを、通常のセルデータに変換しました。

#### 注意事項
- Excelのバージョン: 2211
- 使用データ: 全国の郵便番号と住所のデータ(日本郵便)

## 動機
Excelで「データ」→「テキストまたはCSVから」で、CSVを読み込みます。Power Query経由で読み込むと、以下の画像のようなデータ形式になります。
![table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291591/05039276-44c0-336c-afde-ce66f3d5afdb.png)
1行目に「Column」というデータが追加され、行が色分けされています。
上部のリボンタグに「テーブル デザイン」が追加されている通り、このデータはテーブルとして扱われています。
これはこれで使えるようですが、通常のセルデータとして扱いたかったので、変換方法を調べました。

## 変換方法
必要な操作は上部の「テーブルデザイン」から行えます。
- 「見出し行」をオフにする
- 「縞模様」をオフにする
- 全選択して、「範囲に変換する」

以上の操作を全選択して行うことで、見出し行と装飾が削除し、セルデータに変換できます。
1行目を削除すれば、余分なデータはなくなります。

変換後の画像
![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291591/b6092865-4810-0076-4b22-56aadf52eb9a.png)


## 参考にしたサイト
[エクセルのテーブルを解除する方法｜書式設定の戻し方も紹介](https://litera.app/blog/excel-table-release/)
[郵便番号データダウンロード](https://www.post.japanpost.jp/zipcode/download.html)
Rails(6系)のマイナーバージョンを上げる手法(メモ)

# はじめに
筆者の環境は以下のとおりです。(テンプレート)
　・VSCodeを使用(CLIでWindows Terminalを利用する場合があります)
　・Windows10にてWSL2でUbuntu20.04LTSを使用
　・Bash、Git、asdfを使用

Rails6.0系からRails6.1系にマイグレーションする際、職場の先輩から教わった
Ruby(+bundler再インストール)及びNode.js(+yarn再インストール)のアップデート
＋Railsマイグレーションの流れをメモ書きします。

あくまで __メモ書き__ なので過度な期待はしないでください。

■バージョンの呼称方法例
　・〇〇(ツール名) XX(メジャー).XX(マイナー).XX(パッチ)

■バージョン読み方参考サイト

 https://dev.classmethod.jp/articles/versoning-with-pictures/

## 共通する注意点
 ・「環境の変更」というリスクが高い作業を行うため、gitで管理している場合に
　　main(master)ブランチやdevelopブランチではなく
　　feature-refacter-yyyymmddなどの一時ブランチを作成し作業すること

・上記ブランチをpush時にpull-requestを作成すること

・一気に実行せず各アップデート単位で実施し```git add```及び```git commit```すること

・アップデートしたら```bin/rails s```でRailsサーバを起動し、
　　ローカル動作確認すること(小規模な場合)
　
　__※他のあらゆるバージョンアップでも同じ方法での実施を心がけること__

## Rails及び各種パッケージのアップデート方法

■バージョンアップの手法(例としてnode.js)

 :::note info
メモ
・Node.jsは偶数番号がLTSに相当する
・パッチバージョン含め最新にする
:::
　
　__例：RailsでのNode.jsが14.17.0だった場合__

　(1)現環境と同じメジャーバージョン内での最新マイナーバージョンを入れる。
　　※モノによっては相性などもあるかもしれないので、
　　　不安な方は各種documentationを読んでください。
　
　参考：教わった時点の現バージョン```14.21.1```
　
　(2)動作確認が取れたらメジャーバージョンを上げる。
　
　参考：教わった時点の安定バージョン：16.18.1 
　　※この時点で18.XX.XX～が存在したが影響範囲が分からない(検証時間が無い)為、
　　　今回は既に職場で適用実績がある上記バージョンを採用。
　
■各種パッケージの更新コマンド

 :::note info
アドバイスメモ
・複数回体験することによって実行するコマンドの順番を習熟できる
・手動ではなく、コマンドに対応して特定の処理を自動実行する設定をできるが
　定期的にやらないと忘却する可能性があるため手動にしたほうが良い箇所もある
:::

* Node.jsのバージョンを上げる(asdf利用)
　=> asdf install nodejs xx.xx.xx
　=> asdf local nodejs xx.xx.xx
　=> npm install -g yarn(Node.jsのパッケージマネージャであるyarnのバージョンを上げる)
　
* rubyのバージョンを上げる(asdf利用)
　=> asdf install ruby xx.xx.xx
　=> asdf local ruby xx.xx.xx(※ここでバージョンが変わらない方はググってください)
　=> gem install bundler(Node.jsの流れと同じRuby版)
　=> gem install solargraph(仮にsolargraphを利用している場合)

◇solargraph参考1(導入方法)

https://qiita.com/hideki0145/items/d6a18095f95d57eebe96

◇solargraph参考2(gemのdoc)

https://rubygems.org/gems/solargraph/versions/0.38.0?locale=ja

■Railsのバージョンをマイグレーションする
　
　railsの6.0系の最新パッチバージョンに上げる
　=> そこからrails6.1に上げる(メジャーバージョンを上げる)
　
　(1)Rails6.1の新規アプリケーションを作成する(rails new sample_appなど)
　　=> wslの場合windowsのローカル環境に落とす
　
　(2)マイグレーション前Railsアプリ(6.0最新パッチバージョン)をローカルに落とす

　(3)上記(1)と(2)のソースをWinMergeなどのツールで比較し、
　　自分が実装したModelなどの差分は勿論、手動で書き換えた
　　configの設定以外の差分を目視で確認しながら修正する。

　※上記の方法はあくまで差分が少ない
　　(利用しているgemが10個以内など)場合に利用するべきであり
　　差分が多くなった場合には下記Rails標準のマイグレーション手順を検討すべし。
　
　(4)6.0のソースの方に6.1の方の差分を被せていく(新しい方から旧にコピペなどで移行していく)
　　=> 完了後、GemfileのRailsバージョンを上げる
　　=> 手動でやらなくてもマイグレーションしてくれる標準機能がRailsには存在するようだが
　　　～.yml等、上記機能を利用した際にコンバート用に
　　　自動作成される設定ファイル(手動では生成されない無駄なファイル)が存在するらしい。
　　　(詳しくは要調査)

# さいごに
　・最初にも記述しましたがあくまでメモです
　・読み辛い箇所が多々あるかもしれませんが、ここまで読んでいただければ幸いです
　・今後、読み直して修正する場合があります
【Shell】指定した行のみ取得する方法

## 1行目のみ取得する

ファイルの1行目のみ取得するには以下のように実行します。

```zsh
head -n 1 対象ファイルパス
```

## 指定した行のみ取得する

指定した行のみ取得するには以下のようにします。

```zsh
sed -n 行数p 対象ファイルパス
```

`./sample.txt`の5行目を取得する場合には以下のように実行します。

```zsh
sed -n 5p ./sample.txt
```
レンダリングとは


# レンダリングとは


レンダリングとは、指定したリソースをブラウザに表示することです。
Webでいうリソースとは、URIによって一意に得られるデータ（主にHTMLなど）のことです。


ブラウザの中のレンダリングエンジンというモジュールがレンダリングを担当します。
具体的には以下の作業を行います。


```
①パース（HTMLファイルをパース(解析)してDOMツリーを作る。CSSファイルをパースしてCSSOMツリーをつくる。）
②レンダーツリー構築（DOMとCSSOMを合わせてレンダーツリーを構築する）
③レイアウト（ブラウザ画面にどのように表示するかを計算する）
④ペインティング（画面に描画して表示する）
```


## パースとは

ブラウザはWebサーバからHTMLをダウンロードし、それをパース(解析)してブラウザに割り当てられたメモリ上にDOMツリーとして配置します。

CSSも同じようにCSSOMツリーとしてメモリ上に配置します。


## DOMとは

DOMはDocument Object Model(ドキュメントオブジェクトモデル)の略。

DOMはHTMLに含まれる要素や要素をオブジェクトとして扱います。HTMLをオブジェクトが階層的に組み合わされたものとして識別します。そしてDOMではJavaScriptなどのプログラミング言語などから、オブジェクトを扱うためのAPIを提供しています。

つまり、DOMはHTMLを階層構造のオブジェクトとして扱い、JavaScriptによって操作できる状態を提供するということです。


## まとめ


レンダリングとは、ブラウザがリソースを画面に表示することです。
（ブラウザがHTMLを解析して表示すること）

HTMLをパースしてDOMツリーが形成される。
DOMはHTMLを階層構造のオブジェクトとして扱い、JavaScriptで操作できるようにしている。

## 参考

https://milestone-of-se.nesuke.com/sv-basic/web-tech-basic/html-javascript-dom-parse-rendering/

https://eng-entrance.com/what-is-dom
Stripe 決済にApple Payを用いた場合

# Stripe 決済にApple Payを用いた場合
Stripe決済にはクレジットカードの他にApple Payで支払うという方法があります。

登録後にどのような表記になるかというと、クレジットカード情報が登録されているかのような見た目になります。
登録経路の確認はApple Payの場合、支払方法のクレジットカードの詳細を見ると、住所などが一般的に登録されています。

## 顧客詳細の見た目
![スクリーンショット 2023-01-11 23.21.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65992/74b8cbf9-648c-753e-4beb-e12e6f63b797.png)

## カスタマーポータル起動時の見た目
![スクリーンショット 2023-01-11 23.21.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65992/2cb97e91-b4e3-e352-eddf-182f9bade540.png)


そういえば、Apple Payで支払いをした方の見た目ってどうなるのかなと思って、備忘録程度に載せておきます。
コンピュータ基礎技術①

■情報を処理する仕組(コンピュータ)：
コンピュータは物理的装置であるハードウェアと、ハードウェアを制御して動作させる為のソフトウェアで構成されている。

ソフトウェアはオペレーティングシステム(OS)とアプリケーションの2種類に分類される。
OSは通常、ハードウェア購入時に標準でインストールされている。

アプリケーションは目的に応じて利用者がインターネットからダウンロードなどで入手してインストールし利用する。

■情報を伝達する仕組み（ネットワーク）：多くの情報システムではネットワークを利用し複数のコンピュータが相互に通信することで機能やサービスを提供している。

■情報を蓄積する仕組み（データベース）：情報システムでは情報を効率よく利用・管理する仕組みとしてデータベースが用いられている。様々な目的をもったソフトウェアから情報を利用するため、データベースには情報の検索や追加、更新、削除などの命令を共通のルールとして定義されている。

■2進数
コンピューター内での情報は全て「1」と「0」のみ。

■2進数以外の表し方
コンピューターが扱う2進数を4桁ごとに区切り0~Fの文字を当てはめて見やすく表現した16進数などがある。

■大きな数値を扱う単位
情報量が多くなるとバイトだけでは量が把握しづらくなるため、補助単位を使用する。

Kilo byte(KB): 1000B
Mega byte(MB): 1,000,000B
Giga byte(GB): 1,000,000,000B
Tera byte(TB): 1,000,000,000,000B

■ハードウェアとは：物理的な装置。入力、記憶、演算、出力の役割を担う5大装置。

■コンピュータの5大装置とマザーボード
5大装置はマザーボードと呼ばれる基盤に接続する。

・マザーボード：コンピュータの本体にあたる装置で、CPUを取り付けるためのソケット、ハードディスク（補助記憶装置）を取り付けるコネクターなどを持つ。

・入力装置：マウス、キーボード、タッチパネル、カメラ

・出力装置：ディスプレイ、スピーカー、プリンター

・記憶装置：下記

▼主記憶装置（メモリ。演算装置から情報の読み書きを行う）：演算・制御装置が使用するデータを一時的に保管する役割がある。電気的にデータを保持している為、電源が切断されればデータが失われる性質を持つ（揮発性）。主記憶装置のほうがコストがかかる

▼補助記憶装置（ハードディスク。情報の保存機能）：電源が切断されてもデータは保持可能（不揮発性）だが、処理速度は遅い。

▼半導体記憶装置：半導体の回路を電気的に制御し情報を記録する。RAMとROMに分けられる。
RAM：Random Access Memory。情報を読み書き可能なメモリ。
ROM：Read Only Memory。情報の読み取りのみ可能なメモリ。

■磁気記憶装置：ハードディスク、テープメディアなど。ビットの1を0を、N、S極で表現する記憶装置。

■光学記憶装置：CD、DVD、BDなど。ビットの1を0を「ピット」と呼ばれる突起の有無で表現し、レーザー光でデータを読み取る。

■演算装置、制御装置
CPU（中央処理装置）に組み込まれている。集積化されワンチップ化されている。
現在では演算装置と制御装置のコアを複数搭載したマルチコアのCPUが一般的。

■CPUの命令処理の仕組み
CPU内の制御装置がメモリー内にある命令を読み込み解読し、演算装置で実行し、その結果を制御装置がメモリーに書き込む。読み取り→解読→実行→書き込みの順に繰り返す。

■ハードウェアの能力を示す指標
・入出力装置のデータ転送速度：ビット毎秒(Bit/Secまたはbps)で表す。この値が大きいほど高速なデータ送受信が可能となる。

・記憶装置の格納可能な情報量：Byteで表す。この値が大きいほど、大容量のデータを記憶できる。

・演算、制御装置の処理速度を表す単位：Hz(ヘルツ)で表す。この値が大きいほど1秒ごとに多くの演算が可能になる。
　

■ソフトウェアとは：ハードウェアを動作させるために必要なプログラムに加えデータやマニュアルを含めたもの。osとアプリケーションの2種類に分けられる。

・OS（基本ソフトウェア）：ハードウェアに対する基本的な処理を担う。

・アプリケーション（応用ソフトウェア）：

■ソフトウェアとプログラム：ソフトウェアはプログラムの集合であり、プログラムは命令を集合であり、コンピュータは命令に従って処理を行う。

■プログラム：コンピュータに対する命令（コード）の集合であり、一連の処理手順についてまとめたもの。

■インターフェース：2つのものが接続・接触する箇所や、両者間で情報や信号をやりとりするための手順や規約を定めたものを意味する。「ハードウェアインターフェース」「ソフトウェアインターフェース」「ユーザーインターフェース」の3つに大別できる。

・ハードウェアインターフェース：複数の装置を接続して通信する際の仕様で、コネクタの形状や電気信号の形式などを定めている。

・ソフトウェアインターフェース：プログラム間でデータや指示をやりとりする手順や形式を定めたもの。代表的なものとして、OSやミドルウェア、ライブラリなどの機能を外部から呼び出して利用するための規約であるAPI(Application Binary Interface)がある。

・ユーザーインターフェース：コンピュータが利用者に対して情報を表示する方式や、逆に利用者が情報を入力するための方式を定めたもの。代表的なものとして、GUIやCUIがある。

・GUI(Graphical User Interface):キーボードやマウス、タッチパネルを使いグラフィカルな画面でコンピュータを操作する。

・CUI(Character User Interface):キーボードから文字やコマンドを入力してコンピュータを操作する。

■OSの役割：ユーザーにコンピュータを操作するインターフェースを提供する機能とコンピュータ（ハード・ソフトウェア）を管理・制御する機能をもつ基本的なソフトウェア。

■拡張子：ファイル名の末尾にある「.」の後に続く文字列のことを拡張子と呼び、OSはこの情報に基づき各ファイルに対応するアプリケーションを区別している。

■階層構造における場所の指定：ファイルやフォルダ―が保存されている場所を指定するには、階層構造を「￥」で区切って表現したパスによって表す。

・絶対パス：ルートフォルダ/ディレクトリから目的のファイルまでの位置を、フォルダ/ディレクトリを一階層ずつ下にたどって表現する方法。

・相対パス：カレントフォルダ/ディレクトリから目的のファイルまでの位置を、フォルダ/ディレクトリを一階層ずつ上下にたどって表現する方法。
React + TypeScript - onClickイベントでクリックされた要素のテキストを得る

# コード例

`e.target.textContent` が要素のテキストだ
次の例でいうと `Click me` が得られる

```tsx

const Example = () => {

  const handleOnclick = (e: any) => {
    console.log(e.target.textContent )
  }

  return (
    <>
      <div>
        <button onClick={handleOnclick}>Click me</button>
      </div>
    </>
  );
}
export default Example;
```



# チャットメンバー募集


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

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


# Twitter

https://twitter.com/YumaInaura
Amazonで販売しているVisual Basic .NET（VB.NET）本まとめ

今日はVisual Basic .NET（VB.NETという）について、Amazonで販売している本をざっくりまとめていきたいと思います。　

# VB.NETとは？今までどんな履歴があったか？　
VB.NETはWikipediaによると、　
「Visual Basic .NET はマイクロソフトが開発したプログラミング言語およびその処理系。VB.NETとも呼ばれる。Visual Basicの後継である。マイクロソフトが推進している.NETで開発された言語である。」と書いてあります。　

1991年、MicrosoftがリリースしたVisual Basicから始め、2002年にVB → VB.NETに変更しました。　
その後、バージョンアップしていて、直近の最新版はVisual Basic 2019となりました。　

# 日本AmazonでVisual Basic .NETに関する本をまとめ　
Amazon.co.jp にアクセスして、「visual basic」というキーワードを検索したら、一杯結果が出てきます。　
ただ、全部見るのが結構時間かかるので、以下の条件で絞り込みました。　

・カスタマーレビュー：⭐️⭐️⭐️⭐️
・Kindleストア　

![C2546CB3-E0FB-4A77-A53D-FF788BB2F114.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92345/6ffc645e-e697-f850-613b-ac2804b85d9d.jpeg)


そこで結構評価が高い3本があります。　
・基礎Visual Basic 2022 基礎シリーズ
・Visual Basic 2019パーフェクトマスター
・基礎Visual Basic 2019 基礎シリーズ
※ 初心者向けの他の本もあります。
※ Kindle Unlimitedを対象となった本もあります（2023年1月時点）　

＃アメリアAmazonでVB NETに関する本をまとめ　
結論から言うと、
・数の方が多いです。　
・高評価する本の数も多くなりますが、全部英語で書いてあります。　

![1A071EE0-5692-4530-BBF8-3EC00525C281.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92345/aec2cbbb-5ded-30a8-7e17-8f5ce0742cc0.jpeg)

例）
・Visual Basic in easy steps: Updated for Visual Basic 2019
・Learn Visual Basic 2019 Edition: A Step-By-Step Programming Tutorial
・Visual Basic and Databases 2019 Edition: A Step-By-Step Database Programming Tutorial
・Learning Visual Basic .Net

英語が得意の方はアメリアAmazonにもご参考ください。　

以上となります。　
ありがとうございました

詳しくはこちらの[VB NET](http://miichisoft.com/2023-lastest-features-scalability-applicability-of-vb-net/ "【2023】VB.NETとは？特徴、将来性と活用シーンを徹底解説")記事をご参考ください。　

Website: https://miichisoft.com/
LinuxのIntel x86のIntrinsic関数をRISC-VやARM用にポートする（６）

さて、IntelからRISC-Vにポートする際、ポインターリファレンスキャストが必要になることがある。これは一般的には危険と言われているらしいが、ポートの作業においては必要な作業のようである。
では、どのように行うのか。コードを見ていこうと思う。

```c
/* The Intel API is flexible enough that we must allow aliasing with other
vector types, and their scalar components. */
typedef struct __m256i
{
__vector long long vdi0;
__vector long long vdi1;
} __m256i;
/* Internal data types for implementing the AVX in PowerISA intrinsics.
typedef struct __v16hi
{
__vector short vhi0;
__vector short vhi1;
} __v16hi;


extern __inline __m256i __attribute__((__gnu_inline__, __always_inline__,
__artificial__))
_mx256_add_epi16 (__m256i __A, __m256i __B)
{
    __m256i result;
    __v16hi a = *((__v16hi *)&__A);
    __v16hi b = *((__v16hi *)&__B);
    __v16hi c;
    c.vhi0 = a.vhi0 + b.vhi0;
    c.vhi1 = a.vhi1 + b.vhi1;
    result = *((__m256i *)&c);
    return (result);
}
```

以上のコードにおいて

```C
    __v16hi a = *((__v16hi *)&__A);
    __v16hi b = *((__v16hi *)&__B);
```

この部分にポインターリファレンスキャストが使用されている。C言語においては、構造体間の直接的なキャストは許容されていないため、ポインターリファレンスキャストを行う。Intrinsicインターフェースタイプは、キャスト演算するのに正しい型ではない。

これと関連する例がインラインされているため、僕たちは、コンパイラがこれを”nop cast”として認識して、追加的な命令の生成を避けることを期待している。

さて、ポインター参照キャストを解剖していくと、&__Aこれによって__Aのアドレスを得ることができる。で、アドレスを(__v16hi *)によってキャストし、*で値に戻している。

（続きは後で）

以下のPDFからコードとアイディアを拝借しました。

https://openpowerfoundation.org/specifications/vectorintrinsicportingguide/
【Ruby】reduceメソッド（injectメソッド）の簡単なまとめ

使い所が掴めなかったので、簡単にreduceメソッドについてまとめます。
別名でinjectメソッドとしても使えますが、今回はreduceメソッドとして統一しておきます。

# reduceメソッドとは
たたみ込み演算を行うメソッドです。
初期値と最初の要素をブロックに渡して実行します。

# 使い方
先頭の要素と引数の値をブロック内で処理して、繰り返し処理することで結果を返します。
```ruby
p [2,3,4,5].reduce(0) { |sum, i| sum + i } #=> 14
```
この場合では、sumに引数の`0`が入り、iに最初の要素`2`が入ります。
その後、sumに最初の処理した結果が入り、iには次の要素`3`が入ります。
これを繰り返すことで結果の`14`が出力されます。

```
((((2) +3) +4) +5)
```
というイメージです。


また、初期値が`0`である場合は省略が可能です。

※追加
>初期値が0の時は少し挙動が異なります。
最初に先頭の要素と 2 番目の要素をブロックに渡します。
詳しくは@nodai2h_ITCさんのコメントを参照ください。


```ruby
p [2,3,4,5].reduce { |sum, i| sum + i } #=> 14
```
さらに、シンボルと演算子で省略して定義することもできます。

```ruby
p [2,3,4,5].reduce(:+) #=> 14
```
ですが、この定義はRuby2.4以降は`sum`で定義することもできるようになりました

```ruby
p [2,3,4,5].sum #=> 14
```
また、sum以外でもmapやselectでもreduceで表現することができます。

# 初期値は何でも良い
先の例では初期値を`0`で設定しましたが、それ以外のオブジェクトを設定することもできます。
例えば`arry`を設定した場合です。
```ruby
def map(list, &fn)
  list.reduce([]) { |a, i| a.push(fn[i]) }
end

p map([2,3,4]) { |i| i * 2 } # => [4, 6, 8]

# 引用：https://techracho.bpsinc.jp/hachi8833/2021_02_03/57968
```
この例ではmapメソッドで示していますが、selectメソッドやfindメソッドでも定義することができます。

# まとめてみて
使い方によってはmapメソッドなどと同じような使い方ができるのがわかりましたが、その分まだ応用的に使えそうです。

繰り返し行う処理ではreduceメソッドを使用した方が端的にかける場合があるので、活用していきたい。

# 参照
[何度見てもよく分からないreduceメソッドをマスターする！](https://www.uosansatox.biz/entry/2018/07/30/070000)
[Enumerable#inject](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html)
[Ruby の inject(reduce) メソッドを使いこなす
](https://blog.toshimaru.net/ruby-inject/)[Ruby: Enumerableをreduceで徹底理解する#1 基本編（翻訳）
](https://techracho.bpsinc.jp/hachi8833/2021_02_03/57968)[Ruby Enumerableモジュールを理解して繰り返し処理を書く際の選択肢を増やす
](https://bagelee.com/programming/ruby-on-rails/ruby-enumerable/)
非同期処理

 ### 非同期処理とは
前の処理が終わっていない状態でも後ろの処理を行うこと。



### async awaitでの記述方法とPromiseでの記述方法(同義)
```js
// 5秒待つ関数
const wait5Seconds = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("finish!");
      resolve({result: "ok"});
    }, 5000)
  })
};
// Promise版
const onClickBtn = () => {
  wait5Seconds() // Promise
    .then((response) => {
      console.log("wait finish!");
      console.log(response.result); // "ok"
    });
};
// async/await版
const onClickBtn2 = async () => {
  const response = await wait5Seconds();
  console.log("wait finish!");
  console.log(response.result); // "ok"
};
```
SSHログインできずに詰まった話

# ■前提条件
さくらVPSを利用してcentOS7環境でサーバ構築の勉強中です。
「ネコでもわかるさくらVPS講座」で学習中に詰まったので同じ境遇の方向けに書いてます。
[ネコでもわかる！さくらのVPS講座](https://knowledge.sakura.ad.jp/7938/)

# ■SSHログインできなくなった経緯
SSHログインができなくなった経緯と解決法を以下記載します。
## ■firewalldを有効にしてSSHログインができなくなる
firewalldを有効化するため下のコマンドを実行しました。
```
    # firewall-cmd --add-service=http --zone=public --permanent
```
その後、ファイアウォールが有効化されたことで強制ログアウトとなり何度かSSHログインを試みるも、、、
```
    ssh: connect to host 〇〇〇.〇〇〇.〇〇〇.〇〇〇 port 〇〇: Connection refused
```
上のエラーが出てサーバーにログインできず...
[様々な記事を参照すると](https://zenn.dev/kirk3110/articles/064040d60ca5e3)、デフォルトの設定だとfirewalldでは２２番ポートの通信のみ許可しているようです（筆者はSSHサーバの初期設定を２２番ポートから変更していた）。これが原因のようですね。

## ■対応方法
さくらVPSのVNCコンソールを開き、rootユーザでログインしてください。
firewalldを有効します。
```
# systemctl enable firewalld
```
下記コマンドでポート番号を変更します。
```
# firewall-cmd --add-port=〇〇/tcp --zone=public --permanent
```
また、fierwalldの設定を有効化し、設定内容を確認するとポートが変更されているのがわかります。
```
# firewall-cmd --reload
# firewall-cmd --list-all --zone=public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: dhcpv6-client ssh
  ports: 〇〇/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:
```

## ■OS再インストールを行ったことでSSHログイン時にWARNING！が出るようになる
筆者は早まりがちなため、OS再インストールをしょっちゅうしてしまいます。。。再インストール時、以下のようなWARNING!が出てSSHログインができなくなりました。
```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:04+kuW8/mIxvvD8+q0lXSL/tOs27tLPEDcXzEzTSuiM.
Please contact your system administrator.
Add correct host key in /Users/ユーザ名/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/ユーザ名/.ssh/known_hosts:2
Host key for 133.167.78.37 has changed and you have requested strict checking.
Host key verification failed.
```
すごい剣幕で怒られたのでびっくりしましたが、これはなんとなくknown_hostsファイルに原因がありそうと推測できますね、、
SSHで接続する際には接続先毎にローカルにRSA公開鍵のフィンガープリントなるものが保管されるため、SSH接続時には、以前保存したこの情報と、いままさに接続しようとしているサーバの情報が一致しているかを確認しているようです。そうすることで、ユーザ（クライアント）が別のサーバへ接続してしまうことを防いでいるとのことでした。そのため、IPアドレスの振り直しやOS再インストールなどでホスト鍵が変わってしまった場合、エラーが出ます。
## 対応方法
以下コマンドでknown_hostsファイルにあるIPアドレスの行を削除します。
```
    #ssh-keygen -R [ホストIPアドレス]
```

以上SSHログインできなくなった時の対処法２選でした！
最後に引用記事をまとめておきますのでご参考までに！！
筆者が初学者のため表現や知識の誤り等ございましたらコメント頂けますと幸いです！

## 引用した記事
・[さくらのVPS(CentOS7)でnginxサーバを建てる](https://zenn.dev/kirk3110/articles/064040d60ca5e3)
・[AWS上でssh接続時の[WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!]エラー](https://cloud5.jp/ssh-host-id-changed-error/)
・[第23回 実行してはいけないLinuxコマンド-Linuxサーバにおいてsshで締め出される恐怖 - その3](https://news.mynavi.jp/techplus/article/dont_run_on_linux-23/)
WindowsでSIGINTとSIGBREAKを送信するツール

以下を参考にさせていただいた。
PIDを引数に取るため若干扱いが面倒だが、SIGINT, SIGBREAKに相当するシグナルを送信できる。
ちなみにSIGTERMを使うのは難しい(Windowsにはない)らしい。

https://tadaoyamaoka.hatenablog.com/entry/2019/07/03/200708

https://github.com/ElyDotDev/windows-kill
Git管理しているCF2の関数をJestでテストする

## 結論

rewire という package を使うと `module.exports` していない関数を Jest でテストできます。
https://github.com/jhnns/rewire

## 背景

CF2 の関数を Git 管理しています。
その関数を Jest でテストしたいと思いましたが、CF2 では `module.exports` が使えません。
よって `module.exports` をせずに、Jest でテストを書く方法が知りたいと思いました。

## 前提

この記事では、例として下記の関数を想定します。

```javascript:index.js
function handler(event) {
  var response = event.response;
  var headers = response.headers;

  if (!headers["access-control-allow-origin"]) {
    headers["access-control-allow-origin"] = { value: "*" };
  }

  return response;
}
```

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-cors-header-response.html

## 方法

まず rewire を install します。

```terminal
$ npm install -D rewire
```

続いて rewire を使ってテストを書きます。

```javascript:index.spec.js
const rewire = require("rewire");
const handler = rewire("../path/to/index.js").__get__("handler");

describe("handler", () => {
  describe("access-control-allow-origin に値が設定されている場合", () => {
    test("何もしない", () => {
      const event = {
        response: {
          headers: {
            "access-control-allow-origin": "https://example.com",
          },
        },
      };

      expect(
        handler(event).headers["access-control-allow-origin"].value.toMatch(
          "https://example.com"
        )
      );
    });
  });

  describe("access-control-allow-origin に値が設定されていない場合", () => {
    test("'*'を設定する", () => {
      const event = {
        response: {
          headers: {
            "access-control-allow-origin": "",
          },
        },
      };

      expect(
        handler(event).headers["access-control-allow-origin"].value.toMatch("*")
      );
    });
  });
});
```

下記の内容さえ書いてしまえば、通常の方法と同様にテストを書くことができます。

```javascript
const rewire = require("rewire");
const handler = rewire("../path/to/index.js").__get__("handler");
```

## 通常の方法との差分

```diff
- const handler = require("../path/to/index.js")
+ const rewire = require("rewire");
+ const handler = rewire("../path/to/index.js").__get__("handler");
```

## 参考

https://matsuoshi.hatenablog.com/entry/2021/06/05/000000
WSLで名前解決ができない時の対処法

# 概要
WSL単体で使うのならよいが、外部と通信しようとした際に名前解決ができなかった。
その対処法について。

# WSLで起きていたこと
通信できない様子を見ると、名前解決ができていない様子。
ファイル等を確認してみると、自動生成される `/etc/resolve.conf` のnameserverがよくわからないIPアドレスをさしていた。
ホストPCでも無いしLANのnameserverでもないし…。
最初に気が付いたときは手動で書き換えて通信できたが、PC再起動するとまた`resolve.conf`が書き換わってしまうために通信できなくなっていた。

# 対応方法
`/etc/resolv.conf`の自動生成を止めて、自作したものを使うようにする。

## `/etc/resolv.conf`の自動生成停止

`/etc/wsl.conf`に設定を設定を書くと自動生成が止まるらしい。
```/etc/wsl.conf
[network]
generateResolvConf = false
```

## wslの再起動
wsl立ち上げ時に上記の設定がされていないと、wsl終了時に`wsl.conf`が削除されてしまうので、上記設定をしたらwslの再起動をする。


## `/etc/resolv.conf`の作成
これは普通に作ればOK。

```/etc/resolv.conf
nameserver 8.8.8.8
```

# 参考

https://blog.jp.square-enix.com/iteng-blog/posts/00015-wsl-dns-custom/
Java springとspringbootの違いをまとめてみた

## そもそもフレームワークとは
- アプリ開発をする際に、開発の効率を上げるために便利な機能がたくさん詰まっているツール。

## Spring Framework
javaのWEBフレームワークで、WEBアプリを作成することができる。
フレームワークの集合体　

## Spring Boot
spring bootはspring Frameworkの機能の使い分けが困難という欠点を解消するために作られたフレームワーク。
主な機能として、複数のフレームワークを使用する際に発生する、Bean定義やXML設定などを、可能な限り自動設定する機能が搭載されている。そのほか、コードを書かなくてもプログラム処理ができるように「、Javadocと同じくアノテーションが記述できる点も特徴です。Spring MVCのフレームワークの仕様を踏襲して作成しており、Spring Frameworkを構成するフレームワークの一つとして組み込まれている。

## spring frameworkとspring bootの違い
- spring framework：Java言語のアプリケーション開発のために作られたフレームワークの集合体
- spring boot：集合体となった機能を使いやすくするためのフレームワーク
InfluxDBから取得するCSVファイルのデータ前処理について

InfluxDBから取得されるデータのフォーマットがPythonでグラフ作成を行うには利便性が低いため，データの前処理を行う
以下に現在出力されるCSVファイルのフォーマット例と理想のフォーマット例を示す．
現在のフォーマット
| 日付 | CPU使用量 | Pod名 |
| ---- | ---- | ---- |
| YYYY-MM-DD-HH-MM-SS | num | pod1 |
| YYYY-MM-DD-HH-MM-SS | num | pod1 |
| YYYY-MM-DD-HH-MM-SS | num | pod2 |
| YYYY-MM-DD-HH-MM-SS | num | pod2 |
| YYYY-MM-DD-HH-MM-SS | num | pod3 |
| YYYY-MM-DD-HH-MM-SS | num | pod3 |

理想のフォーマット
| 日付 | Pod1 | Pod2 | Pod3 |
| ---- | ---- | ---- | ---- |
| YYYY-MM-DD-HH-MM-SS | CPU使用量1 | CPU使用量1 | CPU使用量1 |
| YYYY-MM-DD-HH-MM-SS | CPU使用量2 | CPU使用量2 | CPU使用量2 |
| YYYY-MM-DD-HH-MM-SS | CPU使用量3 | CPU使用量3 | CPU使用量3 |

理想のフォーマットのようにCSVファイルを新規書き込みを行うのではなく，CPU使用量をPodごとにまとめることにした．
作成イメージを以下に示す．
{Pod1:[CPU使用量1，CPU使用量2，CPU使用量3]，Pod2:[CPU使用量1，CPU使用量2，CPU使用量3]，Pod3:[CPU使用量1，CPU使用量2，CPU使用量3]}
上記のようにすることで，理想のフォーマットで考えていたようにデータを扱えるようになった．

これらを実装した処理を以下に記載する
```
def data_preprocessing(csv):
    Pods_dic = {}
    with open(csv) as f:
        r = reader(f)
        for i,row in enumerate(r):
            #最初の4行をスキップする
            if i < 4:
                continue
            #Pod名をリストにappend
            try:
                pod = row[len(row)-1]
                if pod not in Pods_dic:
                    Pods_dic[pod] = []
            except:
                pass
    
            #CPU使用量をリストにappend
            try:
                amount = int(float(row[6]))/ 1000000000
                Pods_dic[pod].append(int(float(row[6]))/ 1000000000)
                
            except:
                pass
    for i in Pods_dic:
        print(f"Pod名:{i} CPU使用量:{Pods_dic[i][:5]},,,")
```
実行結果を一部記載する
![Screenshot 2023-01-13 at 11.56.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747713/137dfb7b-593f-bf2b-efbe-bd025597b877.png)


PodごとのCPU使用量の時間推移のグラフを作成する際にこの前処理を行うことでPythonのmatplotlibのみで可能となる．
テーブルのレコード内でNULLではないレコードの列名のみ取得する

# 問題の概要
Azure Synapase Analytics 専用SQLプール（SQL Serverと互換性の高いAzureのDWH向けPaaSサービス）で運用を行っておりまして、以下のようなテーブル構造を持っていました。
| id | col1 | col2 | col3 | col4 | col5 |
| :--: | :-: | :--: | :--: | :--: | :--: |
|1|AA|**NULL**|D|G|**NULL**|
|2|BB|A|E|**NULL**|I|
|3|CC|**NULL**|F|**NULL**|J|
|4|DD|B|**NULL**|H|**NULL**|
|5|EE|C|**NULL**|**NULL**|K|

実際には200以上のカラムがあったのですが、記事の関係上`id`列~`col5`列までの6列で記載します。この時に、`id=1`のレコード内に、`NULL`が格納されていない列の列名をSQLで取得します。
**id=1の場合：col1,col3,col4**

また、その他の`id`の値でも同様に各レコードの中で`NULL`が格納されていない列の列名をSQLで取得し出力させます。イメージは以下の通りです。

| 条件 | 取得したい結果 |
| :-- | :-- |
| id=1 | col1,col3,col4 |
| id=2 | col1,col2,col3,col5 |
| id=3 | col1,col3,col5 |
| id=4 | col1,col2,col4 |
| id=5 | col1,col2,col5 |

と言う事がやりたかったのですが、実現するのに時間がかかったので、同じように困っている人もいる（？）かと思い、解決方法をこちらに記載させていただきます。

# 解決方法
ざっと検証するテーブルとデータの準備をします。
```SQL:検証用テーブルとデータの準備
create table test
(
	 id int
	 ,col1 nvarchar(10)
	 ,col2 nvarchar(10)
	 ,col3 nvarchar(10)
	 ,col4 nvarchar(10)
	 ,col5 nvarchar(10)
)
GO

insert into test(id,col1,col2,col3,col4,col5) values(1	,'AA'	,NULL	,'D'	,'G'	,NULL)
insert into test(id,col1,col2,col3,col4,col5) values(2	,'BB'	,'A'	,'E'	,NULL	,'I')
insert into test(id,col1,col2,col3,col4,col5) values(3	,'CC'	,NULL	,'F'	,NULL	,'J')
insert into test(id,col1,col2,col3,col4,col5) values(4	,'DD'	,'B'	,NULL	,'H'	,NULL)
insert into test(id,col1,col2,col3,col4,col5) values(5	,'EE'	,'C'	,NULL	,NULL	,'K')
GO
```
## UNPIVOTはNULL値を返さない
`UNPIVOT`は入力に含まれるNULL値が出力されません。これをうまく使うといい感じの出力ができました。

```SQL:UNPIVOTを使ってNULLではない列名を取得
select
	 id
	,STRING_AGG(col,',') AS col_names
from
	test
unpivot
	(val for col in (col1,col2,col3,col4,col5)) as up
group by
	id
order by id
GO
```
結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697647/e1f8f1a6-50ae-6c91-f993-135e6bbb5a3f.png)

## 動的に`UNPIVOT`を生成
今回の検証用テーブルは6列しかありませんが、実際は200列以上のテーブルだったため、SQLで`UNPIVOT`を手で書くのが大変だったので、動的に`UNPIVOT`を生成するように上記SQLを改造しました。

```SQL:UNPIVOTを使ってNULLではない列名を取得（動的にUNPIVOTを生成）
DECLARE @column_list varchar(max)
DECLARE @sql nvarchar(max)
DECLARE @table_name nvarchar(max)

--取得する対象のテーブル
SET @table_name = 'test'

--動的にカラムを取得する
SET @column_list = null
select
    @column_list = STRING_AGG(c.name,',')
from
	sys.tables t inner join sys.columns c on 
	t.object_id = c.object_id
where
	t.name = @table_name
	and c.name != 'id'

--SQL（UNPIVOT）を生成
SET @sql =
	'select '									+
	'	 id	'									+
	'	,STRING_AGG(col,'','') AS col_names '	+
	'from '										+
		@table_name + ' '						+
	'unpivot '									+
	'	(val for col in (' + @column_list +')) as up ' +
	'group by id '								+
	'order by id'

--生成したSQLを実行
EXEC sp_executesql @sql
GO
```
結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697647/9e1ab18a-44ec-e38a-41c7-510fffcb56ad.png)

`UNPIVOT`/`PIVOT`は使いこなせばなかなか便利かもしれません！！！
コンサルタント（システム監査）の２０か条

### その１
　コンサルタントが成果を上げてはいけない、成果を上げるのは当事者
### その２
　問題点を指摘するのではなく、気付かせること
### その３
　個別最適化ではなく、全体最適化を目指すこと
### その４
　感と度胸より数値化、見える化を目指すこと
### その５
　行き当たりばったりより、予測できる計画できる組織を目指すこと
### その６
　方針を決めたら、細かな改善は当事者にゆだねること
### その７
　ゆだねた後は、方針からずれないよう見守ること
### その８
　全体最適化の第1歩は標準化
### その９
　個別最適化事項は標準に包含しテーラリングすること
### その１０
　依頼者を信じてはいけない、依頼者は要求内容を完璧に伝えることはできない
### その１１
　複雑な問題は分割し、単純化せよ
### その１２
　まずは用語を定義せよ、話す言語（意味解釈）が違うと意思疎通ができない
### その１３
　コミュニケーションを大事にせよ、問題のほとんどはコミュニケーションの不備にあり
### その１４
　手順より情報（５W1H）を重視せよ
### その１５
　問題の本質は「人」ではなく、「環境」にあり
### その１６
　手段より目的を伝えよ
### その１７
　結果よりプロセスを見よ、正しいプロセスで正しい結果が得られる
### その１８
　答えを言う前に、相手の話を聞き、自ら正解に気づかせるべし
### その１９
　システム開発はシステムを作るのではなく情報と便益（ベネフィット）を作ることと心得よ
### その２０
　標準は多くの経験と失敗から導かれたベストプラクティス
Java  アクセス修飾子の使い方とカプセル化

## アクセス修飾子
クラスやフィールド、メソッドヘのアクセスを制御するための修飾子をアクセス修飾子という。アクセス修飾子には、public 、protected、privateの３種類がある。
これらをクラス、フィールド、またはメソッドの宣言の前につけることで、次の表 のようなアクセス制御を行える。（○アクセス制御を行える範囲）
| アクセス修飾子 | 同クラス | 同パッケージ | サブクラス | 他 |
| --- | --- | --- | --- | --- |
| public | ○ | ○ | ○ | ○ |
| protected | ○ | ○ | ○ |  |
| （なし） | ○ | ○ |  |  |
| private | ○ |  |  |  |

クラスにつけられる修飾子はpublicのみ。また、複数のクラスの宣言を１つのファイルの中に記述する場合、public修飾子をつけられるクラスは１つだけ。

```:例文
　class Student{
   private int score;
   public void setScore(int s){
       :
   score = s;
  }
}
```
```:別のクラス
stu　setScore(８０)；
//上記のクラスではsetScoreメソッドはpublicを指定しているので使える

stu.score = 80;
//メンバ変数scoreはprivateを指定しているのでエラーになる
```
###  よく使われる修飾子と使いわけ
主に使われるのはpublic（公開）とprivate（隠蔽）
**・クラスとメソッドはpublic**
**・メンバ変数はprivate**
をする事が一般的に多い
（理由は外部クラスから直接アクセスできないようにする、変数への直接代入をprivateで禁止してメソッドを通してのみ値が代入できるようにして不正な値が入るのを防ぐ事ができる為）

## カプセル化
上記の様にアクセス修飾子でクラス、メンバ変数、メソッドの公開範囲を指定出来るようにする事を**カプセル化**と言う。

**カプセル化の要件**
① メンバ変数を「private」にして隠す。（他のクラスから利用できないようにする）
② メンバ変数の値を取得・設定する「public」のメソッドを用意する。

**メリット**
①private修飾子を利用して外部からの、直接アクセスでメンバ変数の変更を防ぐことができる。
②専用のアクセサメソッド（特定のオブジェクト内のクラスやフィールドを操作する際に、直接書き換えるのではなく専用のメソッドを通して操作を行うこと）を利用することで、外部からの間違ったアクセスを未然に防ぐことができる。
③使用者が内部構造を理解していなくても使用できる。
④アクセス修飾子で公開範囲が一目で分かる様になるのでメソッドの追加やプログラムの修正をどこまですれば良いのかが分かりやすくなる。


### 例文２
```:実行用クラス
class StuSample5{
  public static void main(String[] args){
    Student5 stu1 = new Student5("菅原");
    stu1.setScore(80);
    stu1.display();
    
    Student5 stu2 = new Student5("田仲");

    stu2.setScore(-50);
    //stu2.score = -50;　　←Student5クラスでメンバ変数scoreはprivate指定されているのでエラーになる

    stu2.display();
  }
}
```
```:設計図クラス
public class Student5{
  private String name;
  private int score;

  public Student5(String n){
    name = n;
  }
  public void setScore(int s){
    if(0 <= s && s <= 100){
      score = s;
    } else {
      System.out.println(name + "さんの点数が範囲外です");
      score = 0;
    }
  }
  void display(){
    System.out.println(name + "さん" + score + "点");
  }
}
```
```:出力結果
菅原さん80点
田仲さんの点数が範囲外です
田仲さん0点
```
Student5クラスではsetScoreメソッドで0~100点以外の点数があれば"さんの点数が範囲外です"と出力されるようになっている。
もしint score;のprivate指定が無かったら実行用クラスのstu2.score = -50;が出力出来てしまう。
```:int score;のprivate指定が無くして「stu2.score = -50;」の方を実行した場合
菅原さん80点
田仲さん-50点
```
private指定することでsetScoreメソッドを通してのみ値を代入させる事が出来る様になる。

## 参考記事
https://www.youtube.com/watch?v=AAHWf_yqEyY

https://kanda-it-school-kensyu.com/java-basic-contents/jb_ch03/jb_0303/
[小ネタ] OpenSUSE15.3で、snapのリポジトリが追加できないときの対処方法

# 序
OpenSUSE15.3にsnapアプリを使用しようと思い、[このサイト](https://snapcraft.io/docs/installing-snap-on-opensuse)の通りに、snapのリポジトリを追加を企むもうまくできない人（自分・・・）のための対処方法解説

# 起きたトラブル
[このサイト](https://snapcraft.io/docs/installing-snap-on-opensuse)の内容を順にやっても、2番目の
`$ sudo zypper --gpg-auto-import-keys refresh
`のコマンドを実行すると、「そんなリポジトリはないよ」と怒られる。

# 対処方法
かんたん
サポート中の15.4のリポジトリをそのまま流用する。

:::note alert
いかに述べる方法によって、システムに不具合が出る可能性があるかもしれません。実行する際は、慎重に。筆者は、責任を負いません。
:::

 まず、追加してしまった失敗リポジトリを削除（失敗リポジトリを追加していない場合は、このコマンドは実行する必要はありません。）
`sudo zypper rr snappy`

次に、リポジトリのURLを変更
最初に実行するコマンドを、
`$ sudo zypper addrepo --refresh \
https://download.opensuse.org/repositories/system:/snappy/openSUSE_Leap_15.3 
snappy`
から
`$ sudo zypper addrepo --refresh \ https://download.opensuse.org/repositories/system:/snappy/openSUSE_Leap_15.4 snappy`
に変更する。
あとは、同サイトの通りにやれば、snapアプリが利用できるようになります。（ただし、この場合でも、執筆時点では、GPG鍵の期限が切れていました。特に問題はなさそうですが。）
# おわりに
openSUSE15.3は、すでにサポート切れみたいですね。

参考にしたもの

https://snapcraft.io/docs/installing-snap-on-opensuse

https://download.opensuse.org/repositories/system:/snappy/openSUSE_Leap_15.4/

https://ja.wikipedia.org/wiki/OpenSUSE