OmniAICreator/Qiita-1.07M huggingface dataset:
openSUSE Leap15.3 から 15.4 への更新でDNS Serverが起動しなくなる

# createNamedConfInclude ファイルが存在しない

'systemctl status'で状況を確認する。

![createNamedConfInclude.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729778/32b35813-b018-090f-178c-303bc3340114.jpeg)

'/usr/share/bind/createNamedConfInclude'ファイルがないか、実行可能でない、と表示される。

![sysconfig_named.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729778/455b206b-f2c9-bbc0-38c5-712d9f7b16da.jpeg)

'/etc/sysconfig/named'にcreateNamedConfIncludeファイルの記述がある。ここを削除したり、""(空欄)を設定しても、自動で修復されるので、ダミーの空ファイルを作成し、chmodで実行権を設定する。

# named-checkconf 実行エラー

![NotConfigured.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729778/ae24dedc-3e53-7ed1-8e4c-6977d5af411e.jpeg)

'systemctl start'で起動するが、引き続き失敗する。'/usr/lib/bind/named.prep'スクリプトがエラー終了している。

![named-checkconf.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729778/81adafdd-d597-3d03-3632-3b8662518491.jpeg)

エラーになっているのは、'/usr/sbin/named-checkconf'(バイナリ実行ファイル)。手動実行すると、'/etc/named.conf.include'が存在しない、と表示される。

ここもダミーの空ファイルを作成する。

# 対処終了

'systemctl start'で起動する。今度は、無事に起動する。

[関連すると思われるopenSUSEメーリングリストへのリンク[Bug 1186278]](https://lists.opensuse.org/archives/list/bugs@lists.opensuse.org/thread/5NLGPWT2GWRGILDD4C7WZGE6AZFLYUOM/)
データクレンジングをしてみよう！ 欠損値を削除する方法 

## １．データクレンジングとは
データクレンジングとは、破損したデータ、不正確なデータ、無関係のデータを特定して解決する手法を指します。 データ処理におけるこの重要な段階は、データスクラビングと呼ばれます。

## ２．データクレンジングの必要性
１番でも説明した通り、無関係のデータなどがあった場合、正しい予測結果を得られなくなることや、回帰分析においては、強い相関がみられる２変数のデータなどがある場合、※多重共線性などが発生してしまったりと、とても都合がよろしくありません。
分析業務においてもデータクレンジングはほどんどの業務を占めており、実際企業が保有しているデータは汚れているデータがほとんどなどでとても欠かせない作業になります。

### ３．実際にデータを見てみよう

```Python
#必要なライブラリのインストール
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
%matplotlib inline
```
```Python
len(df)
# 637351
df.isnull().sum()
```
![スクリーンショット (36).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/6deb206c-970b-cdc3-fce4-94b73237327d.png)

※修正：０のデータは欠損値がないということなので、消す必要がありません。

データフレームの行が６３７５１個に対して、何個か欠損値が６３７５１個あります
つまり、そのカラムにはなにもデータが入っていないことになります。

### ４．欠損値を削除しよう
カラムの中に完全にデータが入っていない場合、削除する必要があります。
ここでは欠損値をまとめて消す方法について説明していきます。
では実際にコードを書いていきます
```Python
non_null_list = []

for col in df.columns:　#カラム名を順番に取り出す
    non_null = df[col].count() #あるカラムのデータの個数をカウントします
    if non_null == 0 : #もし、カウント数が０の場合
        non_null_list.append(col) #そのカラム名を抽出し、空のリストに順に加える

non_null_list
['地域', '土地の形状', '間口', '延床面積（㎡）', '前面道路：方位', '前面道路：種類', '前面道路：幅員（ｍ）']        
```
完全に欠損しているカラム名が出ました


次に、作成したリストを活用し、欠損値データをまとめて消していくよ
```Python
df = df.drop(non_null_list , axis=1)
# データが入っていないカラムを一斉に削除する。axis=0の場合はすべて消えてしまう。
```
### ５．まとめ
これで無事に完全に欠損があるカラムを消すことができました。
今回行った処理はあくまでもデータクレンジングの一つに過ぎませんので、また別の手法を解説します。
それでは！
技術メモ：Salesforce Field Service Appから翌日予定未表示対応

# Salesforce Field Service Appから翌日予定未表示対応
Field Service Appから翌日の予定より、デフォルトの設定すれば、未表示になります、対応方法は下記です。
［設定］→［機能設定］→［サービス］→［Field Service］→［Field Service Mobile］→［Field Service Mobile Settings］
変更内容：
Future Days in the Date Picker：［45］→［0］
Past Days in the Date Picker：［45］→［0］

変更前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/925f1a56-9d44-f5fc-530f-52e45b822ddc.png)
変更後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/521e861f-e3f1-856e-00c8-2085e0335e8e.png)
Goの「クロージャ」とは

## はじめに

Goを触り始めてクロージャというものに遭遇しました。

どういう機能なのか、理解した内容を書きます。

## 結論

関数内で状態を保持する機能

## 詳細

### docsでは

>Closure occurs when an anonymous function in Go has access to its surroundings. Then it can hold a unique state of its own. The state then becomes isolated as we create new instances of the function.  
  クロージャは、Goの無名関数がその周囲にアクセスできるようになったときに発生します。そうすると、それ自身のユニークな状態を保持できるようになります。そして、その状態は、関数の新しいインスタンスを作成するときに分離されます。  
  [Closures in GoLang - GoLang Docs](https://golangdocs.com/closures-in-golang)より

イメージとしては「クラスのインスタンスを作って、フィールドの値を保持する」に近そうです。


### 具体例

サンプルコード）

```
package main

import (
	"fmt"
)

func intSeq() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

func main() {
	nextInt := intSeq()
	fmt.Println(nextInt())
	fmt.Println(nextInt())
	fmt.Println(nextInt())

	newInts := intSeq()
	fmt.Println(newInts())
}

```

[Go Playground - The Go Programming Language](https://go.dev/play/p/W7fuxEInVMH)より
※コメントアウトは消しています


上記を実行すると、以下が出力されます

```
1
2
3
1
```

この場合状態が保持されるのはintSeq()内のiですね

nextInt内ではi++する無名関数が実行されて、intSeq()のiが1ずつ足されていきます。

intSeq()を別の変数（newInts）に代入すると、
そちらは別の状態が保持されるので、最後は1が出力されています。

## 終わりに

JSにもあるらしいですが、使ったこともみたこともないなあ。。  
  JSはクラスが導入されたからかな。

## 参考文献

[Closures in GoLang - GoLang Docs](https://golangdocs.com/closures-in-golang)

[Go Playground - The Go Programming Language](https://go.dev/play/p/W7fuxEInVMH)
KotlinのSealed classがファイル外からアクセスできてしまう

# はじめに
KotlinのSealed classとはなんぞやということで調べてみると、
「ファイル内ならSealedClassにアクセスが可能」という情報が出てくるものの、実際に動かしてみるとファイル外からアクセスできてしまいます。原因がよくわかからなかったので調べました。

----
SealedClassは[AndroidDeveloperの動画](https://www.youtube.com/watch?v=OyIRuxjBORY)の中では以下のコードで説明されています。

```Result.kt
sealed class Result<out T: Any> {
    data class Success<out T: Any>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
}
```

「Sealed claassは同じファイル内であれば継承可能であり、この例だとResult.kt内にあるクラスであれば継承可能。なのでSuccessとErrorはResultを継承できる」と説明されています。

「ではどこからは継承不可なのかというと、ファイル外からだと継承できません」
とのことで、以下のコードが紹介され、実際にエラーが発生している様子が紹介されています。
SealedClassはResult.kt内にあるが、InProgressはNoReslt.kt内にあるので継承できない、ということです。

```NoResult.kt
object InProgress:Result<Nothing>()
```
![SealedClassError.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599060/726a019b-300b-3026-d4d3-638bb8c37498.jpeg)


しかし、実際に全く同じコードを書いてみるとエラーは発生せず、問題なく継承できる。なぜか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599060/25ea0b0c-e617-5686-7074-5941303366b4.png)


ちなみに「ファイル内ならSealedClassにアクセスが可能」という説明はこの動画に限ったものではなく、
多くの国内外のブログ、動画で同じように説明されています。


## 公式はどう書いてある？
よく分からんので[公式ドキュメント](https://kotlinlang.org/docs/sealed-classes.html#location-of-direct-subclasses)を確認しました。
同じファイルではなく「同じパッケージに定義する必要がある」と書かれています。
**Direct subclasses of sealed classes and interfaces must be declared in the same package.**
[参照元](https://kotlinlang.org/docs/sealed-classes.html#location-of-direct-subclasses)



さらに[公式文章の改定履歴](https://github.com/JetBrains/kotlin-web-site/commit/0999a56225398a425def2a1b2e2ea7f78c300e24)を確認したところ以下の修正がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599060/d939b371-baa1-0767-0ef3-9395365bedc7.png)

変更前は「サブクラスはSealed Classと同じファイル内に定義せよ」と書かれています。
**All direct subclasses of a sealed class must be declared in the same file as this class itself.**

変更後は「Sealed Classのコンストラクタはprotectedとprivateの2つのどちらかで定義される」となっていて、デフォルトはprotectedとなっています。
**Constructors of sealed classes can have one of two visibilities: protected (by default) or private**


## まとめ
ドキュメントの変更履歴を見る限りでは、

**以前はSealed Classのコンストラクタはデフォルトでprivateだったが、現状はデフォルトではprotectedとなっているのでファイル外でもアクセスできる。**
ということっぽいです。（なんか変なこと言ってましたら、ご指摘くださいませ）

※Kotlin1.5.0から変更になったようです
https://kotlinlang.org/docs/whatsnew15.html#package-wide-sealed-class-hierarchies
winget で windowsアプリを管理する

macOSでは [Homebrewとmacsli](https://qiita.com/kopug/items/aa65f73c5fcdce85461f)でアプリの管理をしていたので、[windowsアプリはMicrosoft公式のWindowsパッケージマネージャー winget](https://github.com/microsoft/winget-cli)を使って管理をしてみます。

## wingetのインストールと設定
[**アプリインストーラー**](https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab)を入れることで、wingetコマンドが利用できるのですが、Windows 11 と最新バージョンの Windows 10 にバンドルされているようです。コマンドプロンプト等で winget と入力すると以下の用に表示されれば利用できる状態になっております。
表示されない場合は、[アプリインストーラー](https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab)が入っていないか、バージョンが古い可能性があるのでアップデートを試してみてください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34731/0f27ecff-dde6-5e81-eb80-59602ccb1cbf.png" width="100%">

## 設定方法

以下のコマンドを実行することで、JSON形式の設定ファイルが既定のテキスト エディターで開かれます。
```
winget settings
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34731/cfaed4cc-5f7f-9396-94aa-209275fd6e53.png)


デフォルトでは上記の設定がされておりますが、どのような設定項目があるかは以下を参考に。
- [settings コマンド (winget)](https://docs.microsoft.com/ja-jp/windows/package-manager/winget/settings)

winget v1.3 からは ポータブルアプリ（インストーラーを持たないアプリ）がサポートされるようになったので、そちらに関してはデフォルトのCドライブ以外を私は指定しています。（Cドライブは消えても良い状態にしているため）

- [portablePackageUserRoot の設定](https://docs.microsoft.com/ja-jp/windows/package-manager/winget/settings#portablepackageuserroot-setting)
- [portablePackageMachineRoot の設定](https://docs.microsoft.com/ja-jp/windows/package-manager/winget/settings#portablepackagemachineroot-setting)

## よく使うコマンド

ここでは例として Chromeブラウザーのインストール等をおこなってみます

### パッケージを探す

```
winget search `パッケージ名`
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34731/24ed5343-3909-43af-e91e-f14987f193ab.png)

上記の様に候補となるリストが表示をされるので、入れたいパッケージをみつけたら ID をコピーしておきます。

### インストールする

```
winget install --id Google.Chrome -e
```

-e は 大文字小文字を区別させたい時に利用します。
versionを指定したい場合は、 --version オプションを利用します。

### アンインストールする

#### アプリを指定してアップグレードする場合
```
winget uninstall --id Google.Chrome -e
```
### アップグレードする
```
winget upgrade --id Google.Chrome -e
```

#### インストールしているパッケージをまとめて全てアップグレードする場合
```
winget upgrade --all
```

### インストール済みのパッケージを確認する

```
winget list
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34731/fd8c9316-b2a7-a74e-54c9-4458b4a1501e.png)
--name chrome を削除するとインストールされている全てのパッケージが表示されます

### インストール済みのパッケージをファイルに出力する

```
winget export C:\demo\winget-export.json
```
PATHは環境に合わせて変更してください。
JSON形式で出力されるので、importで戻したいアプリ以外はエディタ等で削除しておきます。


### ファイル中のすべてのパッケージをインストールする

```
winget import C:\demo\winget-export.json
```

## 最後に

今回はよく使うシンプルなコマンドのみを紹介しておりますので、もっと詳しく知りたい場合は、以下のドキュメントをご覧ください。
* [winget ツールを使用したアプリケーションのインストールと管理](https://docs.microsoft.com/ja-jp/windows/package-manager/winget/)
Ubuntu22.04LTSをインストール後、RDP(リモートデスクトップ接続サーバ)を有効にする

# 概要
Ubuntu22.04LTSをインストールした後、Windows端末からリモートデスクトップ接続を可能とするために、RDPをインストールする手順をまとめた。

# 手順
## RDPのインストール状況を確認
Ubuntuで、「端末」を起動し、以下のコマンドを実行
```
apt list | grep xrdp
```
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/3f4666ff-8863-7197-4513-5ec80f0cec59.png)

[インストール済み]と表示されていないので、未インストールであることを確認。

## RDPのインストール
以下のコマンドを実行
```
sudo apt install xrdp
```

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/b4d427e2-1703-c892-d70a-cb59802e17aa.png)

続行しますか？[Y/n]と表示されたら、Yを入力し、Enterキーを押下。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/2c3c4cd4-0612-5f5f-b760-406c73691b24.png)

## RDPの有効化
以下のコマンドを実行
```
systemctl -a | grep xrdp
```
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/0129a2a9-821b-aea3-6353-1274634a4874.png)

xrdpのサービスが設定されていることを確認。

以下のコマンドを実行
```
sudo systemctl start xrdp
sudo systemctl enable xrdp
```

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/25912cc7-29b9-5770-a36e-d5addcb289cb.png)

## IPアドレスの確認
以下のコマンドを実行
```
ip address
```
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/cf0da919-d663-840a-0fb3-2dbafacd23b1.png)

IPアドレスを確認する。
上記の例では、192.168.2.103。

# 動作確認
同じネットワーク内の任意のWindows機から、動作確認を行う。
(Ubuntuに同一ユーザがログインしていると、動作確認できないのでログオフしておく。)

[Windowキー]+[R]で「ファイル名を指定して実行」を起動。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/2bc9f997-91b0-9490-168e-9510d77eeaaa.png)

mstscを入力して[OK]ボタンを押下。

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/3251c1f7-657a-60b9-0160-d011059d522f.png)

先ほど確認したIPアドレスを入力し、[接続(N)]ボタンを押下。

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/dc090155-0f99-a6e1-1582-099274115194.png)

[はい(Y)]ボタンを押下。

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/52e169de-f7cf-e35b-e66a-7eaafb915bf4.png)

[Session]はXorgのまま。
[username]にUbuntuのユーザ、[password]にパスワードを入力し、[OK]ボタンを押下。

![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321153/ecb072ca-36e5-b67a-c10b-c77d65b73acf.png)

リモートデスクトップ接続を使用して、Ubuntuにログインできることを確認する。
CakePHP2のUnitTestで発生する(Declaration of PHPUnit_Framework_Comparator_DOMDocument::assertEquals)エラーの対応方法

## 現象
PHP7.3、PHPUnit3.7をインストールした環境で、CakePHP2のユニットテストを実行すると下記のようなエラーが発生しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/b4701f9b-3dbb-0ac0-8967-3e82e4bd8b84.png)


```
Error: Declaration of PHPUnit_Framework_Comparator_DOMDocument::assertEquals($expected, $actual, $delta = 0, $canonicalize = false, $ignoreCase = false) must be compatible with PHPUnit_Framework_Comparator_Object::assertEquals($expected, $actual, $delta = 0, $canonicalize = false, $ignoreCase = false, array &$processed = Array)
File: /var/www/html/blogTutorial/vendors/phpunit/phpunit/PHPUnit/Framework/Comparator/DOMDocument.php
Line: 259
```

### 原因

PHPUnitのバグ
`assertEquals`をオーバーライドする際、引数の数が間違っているため。

* PHPUnit_Framework_Comparator_Object(親)の`assertEquals`定義
  /approot/vendors/phpunit/phpunit/PHPUnit/Framework/Comparator/Object.php
```php
class PHPUnit_Framework_Comparator_Object extends PHPUnit_Framework_Comparator_Array
{
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE, array &$processed = array())
    {
```

* PHPUnit_Framework_Comparator_DOMDocument(子)の`assertEquals`
/approot/vendors/phpunit/phpunit/PHPUnit/Framework/Comparator/DOMDocument.php
```php
class PHPUnit_Framework_Comparator_DOMDocument extends PHPUnit_Framework_Comparator_Object
{
    // ～～ 途中略 ～～
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
```
### 対応方法

* ①安直な方法(あまり褒められたやり方ではないですが・・・・)

引数を親に合わせるため、直接書き換える

/approot/vendors/phpunit/phpunit/PHPUnit/Framework/Comparator/DOMDocument.php
```php
class PHPUnit_Framework_Comparator_DOMDocument extends PHPUnit_Framework_Comparator_Object
{
    // ～～ 途中略 ～～
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE, array &$processed = array())
```
* ②PHPUnitのバージョンを新しくする方法もあるようです。参考ページをご確認ください。

### 参考ページ

https://medium.com/@xyluz/phpunit-cakephp-error-25757ea9469d
【Docker】【MySQL】ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)解消法

## 状況
`docker compose run db bash`を実行したところ以下のようにエラーが発生しました。
```:ターミナル
＄　docker compose run db bash
docker compose run db bash
bash-4.4$  mysql -u root -p
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
```

## 解消法
以下の手順で実行することで解消できました。
```:ターミナル
$ docker compose up -d
[+] Running 3/3
 ⠿ Container rails-gitlint-test2-db-1   Healthy                                                       4.6s
 ⠿ Container rails-gitlint-test2-api-1  Started                                                       5.1s
 ⠿ Container rails-gitlint-test2-web-1  Started                                                       5.4s

$ docker compose exec db bash
bash-4.4$ mysql -u root -p
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 44
Server version: 8.0.29 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
```
codeをpowerpointに貼り付けたいんだ

# 概要
コードをクールにpowerpointに貼り付けたかった。

# 環境
Python 3.10.0
Mac OS Catalina

# 内容
`pygmentize`を使う。
*(いつインストールしたか覚えていないが、おそらくpygmentをpip installしたときか、jupyterlabでインストールされたか。)*
```bash
$ pygmentize -f rtf samply.py | pbocpy
```

そして、Powerpointで、Ctrl-Vすれば良い。
![Screen Shot 2022-08-13 at 14.31.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1166238/ec9f18fe-8b54-9daf-6cf4-9682f4f75e09.png)

先人に感謝。

# 蛇足
スタイルを指定したり
```bash
$ pygmentize -O style=paraiso-dark -f rtf sample.py | pbcopy
```
fileに出力したりもできる
```bash
$ pygmentize -f rtf -o sample.rtf sample.py
```

# 参考文献
* https://superuser.com/questions/85948/how-can-i-embed-programming-source-code-in-powerpoint-slide-and-keep-code-highli
* https://pygments.org/docs/cmdline/
Javascript ArrayBuffer 個人まとめ

# ArrayBuffer

>一般的な固定長のバイナリーデータのバッファを示すために使用するデータ型です。ArrayBuffer の内容物を直接操作することはできません。

```typescript: ArrayBuffer操作
// 操作できない
const buffer = new ArrayBuffer(10);
hoge[5] = 987;
// 表示のbufferに変化起きない
console.log(hoge);


// 操作できる
// Bufferを生成
const buffer = new ArrayBuffer(10);
// Bufferを操作できるような形式を生成
const hoge = new Uint8Array(buffer);
hoge[0] = 3;
hoge[2] = 254;
console.log(hoge);
// 表示のbufferに変化起きる
console.log(buffer);
```

- [型付き配列オブジェクトの種類: MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Typed_arrays)
  - Array
  - Int8Array
  - Uint8Array
  - Uint8ClampedArray
  - Int16Array
  - Uint16Array
  - Int32Array
  - Uint32Array
  - Float32Array
  - Float64Array
  - BigInt64Array
  - BigUint64Array

### [Buffer](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/buffer)

https://ja.javascript.info/arraybuffer-binary-arrays

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer


https://javascript.keicode.com/newjs/arraybuffer.php
Vue CLI 5からvue serveがzero configではなくなった件

Vue CLIのバージョンが4から5にアップデートされたら、vue serveコマンドがnpm run serveへのエイリアスに変更された（以下を参照）。

https://cli.vuejs.org/migrations/migrate-from-v4.html#the-vue-command-the-global-vue-cli-package

＜Vue CLI 4の簡易ヘルプより抜粋＞
```
Commands:
  serve [options] [entry]       serve a .js or .vue file in development mode with zero config
  build [options] [entry]       build a .js or .vue file in production mode with zero config
```

＜Vue CLI 5の簡易ヘルプより抜粋＞
```
Commands:
  serve                         alias of "npm run serve" in the current project
  build                         alias of "npm run build" in the current project
```

これにより、Vue CLI 4までは使用できたzero configのvue serveコマンドが実質的に削除された。

Vueを学習するためには、zero configの環境は大変有り難いものだったので、非常に残念である。

それなら、バージョンを指定してVue CLI 4を使用しようと考え、本日（2022/08/13現在）Windowsマシンに新規にNode.js 16.16.0をインストールし、以下の手順でVue CLIをインストールしたところ、vue serveコマンドがエラーを発生するようになった。

```
> npm install -g @vue/cli@4
> npm install -g @vue/cli-service-global@4
> vue serve hoge.vue
...
Error: Cannot find module 'vue-template-compiler'
...
```

以前（2022/06/25）Raspberry Pi 4にインストールしたVue CLI 4（Node.js 14.17.3, @vue/cli@4.5.13, @vue/cli-service-global@4.5.18）では、現在もvue serveコマンドが正常動作するので、Windows上でも同じバージョンに合わせるようにインストールして見たが、変わらず上記のエラーが発生した。
Linuxマシンでも同様に試したが、結果は同じだった。

Raspberry Pi 4とLinuxマシンでVue CLIのインストール先ディレクトリ以下に存在するファイル／ディレクトリを比較すると、多くの違いがあることが確認されたが、これらの違いを無くすことは困難なので、zero configのvue serveコマンドは諦めることにした。

## 代替手段

非推奨となっているが、vue initコマンドがまだ使えるので、最小のテンプレートを指定して、限りなくzero configに近い状態にできる。

```
> npm install -g @vue/cli
> npm install -g @vue/cli-init
> vue init webpack-simple hoge

? Project name hoge
? Project description A Vue.js project
? Author
? License MIT
? Use sass? No

   vue-cli · Generated "hoge".

   To get started:

     cd hoge
     npm install
     npm run dev
```

上記の結果、hoge\src\App.vueと言う唯一のVUEファイルが作成されるので、これを上書きするなどで、割りと楽に単一ファイルコンポーネントの学習を始められると思う。

App.vueを別のファイルに差し替える場合は、以下の例に倣ってmain.jsを変更すれば良い。

例）App.vueをhello.vueに差し替える場合
```src\main.js
import Vue from 'vue'
// import App from './App.vue'
import hello from './hello.vue'

new Vue({
  el: '#app',
//  render: h => h(App)
  render: h => h(hello)
})
```

なお、vue initコマンドで指定できるテンプレートは以下に存在する。

https://github.com/vuejs-templates

## あとがき

それにしても、なぜもっと騒ぎにならないのだろうか。
便利と言っている人は存在するものの、あまり使われなかったと言うことなのだろうか。

Vue CLI 5でもzero configな環境についてご存じの方は、お知らせいただけると幸いである。
Javascript Blob個人まとめ

# JacascriptのBlobとは

Blobは0や1で表すバイナリーデータをもとにファイル(Blob)を作成することができる。
そのおかげで、PDFや画像を保存してダウンロードできるようにする。

- いろいろな形式のファイルを扱うことができる

> 不変の生データであるファイルのようなオブジェクト

>テキストやバイナリーデータとして読み込んだり、ReadableStream に変換してそのメソッドを使ったデータ処理ができる

```typescript: blob 例(テキストをダウンロード)
// 形式を指定してBlobを作成。第一引数に[data],第二引数に形式
const blob = new Blob(['hello world'],{type:"text/plain"});

// ダウンロード用のリンクを作成
const link = document.createElement('a');
// BlobをもとにURLを作成
const url = URL.createObjectURL(blob);
link.href = url
// ダウンロード実行
link.click()
link.download = 'hoge.txt';
link.parentNode?.removeChild;
```

URLの作成は`FileReader` クラスでも作成可能だが、`URL.createObjectURL`の方がシンプルではやいよう

> blob の URL を作成する方法は両方とも使用可能です。しかし、通常は URL.createObjectURL(blob) がよりシンプルで速いです。
>https://ja.javascript.info/blob
>``` typescript
>let link = document.createElement('a');
>link.download = 'hello.txt';
>let blob = new Blob(['Hello, world!'], {type: 'text/plain'});
>let reader = new FileReader();
>reader.readAsDataURL(blob); // blob を base64 へ変換し onload を呼び出します
>reader.onload = function() {
>  link.href = reader.result; // data url
>  link.click();
>};
>```


[Stream](https://qiita.com/kosuke-17/items/4f44503d937d9ba1d583)

https://ja.javascript.info/blob

https://developer.mozilla.org/ja/docs/Web/API/Blob

https://www.sejuku.net/blog/67735

https://techacademy.jp/magazine/28210#:~:text=Blob%E3%81%A8%E3%81%AF,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82
ATEM mini ISOのマルチカム録画をffmpegで一括コンバートする

ATEM mini Extream ISOで各カメラの一括録画をするんですが、1.5時間程度で50GBくらいのファイルサイズになるので、1.5時間ライブで4カメラだと、200GBのファイルサイズになります。

クライアントにデータ納品するには大きすぎる場合があるので、ファイルサイズを縮小したいことが良くあります。

なので、ffmpegを使って一括コンバートをするシェルスクリプトを作りました。

1.5時間程度でファイル分割されるので、01と02を結合する処理を入れましたが、結合したときにプツッとノイズが乗ってしまうことが分かってます。ご利用にはご注意下さい。

CRFは、18としていますが、小さいほどクオリティが高く、6小さくするとファイルサイズが2倍に増えるそうです。逆に6小さくするとファイルサイズが半分程度になります。18にするとで約25％程度のサイズに縮小されます。希望のクオリティに調整して実行してください。

コーデックはlibx264を指定しています。libx265を指定するとエンコードは遅くなりますがファイルサイズは小さくなります。

```sh
#!/bin/sh

TEXT="<録画名に書き換えます>"
CRF=18
# Cordec : libx265 / libx264
CODEC=libx264

for i in `seq 1 8`; do 
    echo "######################################################";
    filelist="$TEXT-CAM-$i-01-crf$CRF.txt";
	file2all="$TEXT-CAM-$i-all-crf$CRF.mp4";
	echo > $filelist;

	# 01
    file11="$TEXT CAM $i 01.mp4";
    file21="$TEXT-CAM-$i-01-crf$CRF.mp4";
	echo " $file11 $file21";
	echo "file $file21" >> $filelist;
    date
	ffmpeg -i "$file11" -c:v $CODEC -crf $CRF "$file21";
	date;


    # 02
    file12="$TEXT CAM $i 02.mp4";
    file22="$TEXT-CAM-$i-02-crf$CRF.mp4";
	echo "###### $file12 $file22";
	echo "file $file22" >> $filelist;
    date
	ffmpeg -i "$file12" -c:v $CODEC -crf $CRF "$file22";
	date;

    # 結合
	ffmpeg -f concat -i "$filelist" -c copy $file2all;

done


```

PGOUTの動画が複数に分割されたときのffmpegで結合手順

```shell
# ファイル名の空白をハイフンへ変換
mv -v "20221106-live-pm 01.mp4" "20221106-live-pm-01.mp4"
mv -v "20221106-live-pm 02.mp4" "20221106-live-pm-02.mp4"
# ファイル名のテキストに書き込む
echo  20221106-live-pm-01.mp4 > filelist.txt
echo  20221106-live-pm-02.mp4 >> filelist.txt
# 結合
ffmpeg -f concat -i filelist.txt -c copy 20221106-live-pm-all.mp4
# ファイル名を元に戻す
mv -v "20221106-live-pm-01.mp4" "20221106-live-pm 01.mp4"
mv -v "20221106-live-pm-02.mp4" "20221106-live-pm 02.mp4"
```
CloudWatchのログでメールアドレスをキーに検索する

「Aws::CloudWatchLogs::Errors::InvalidParameterException (Invalid filter pattern)」って出るだけで、なんかうまくいかないなーと思ったんですが、なんてことはなくて、コンソールで「**"test@sample.co.jp"**」とするように、「"」で囲むだけで出来ました。

これより難しいfilter_patternの書き方については色々情報が出てくるんですが、こういう初歩的な情報が思うように見つからず（もしくは読み解けず）結構苦労しました。

start_time、end_timeの方も微妙に詰まって、「UNIX時間の**ミリ秒**」と書いてあったのを「秒」で指定していただけでした。
1000倍すればよかったんですね。

以下、コードはrubyです。

```
    client = Aws::CloudWatchLogs::Client.new({credentials: Aws::Credentials.new(API_KEY, API_SECRET)})
    resp = client.filter_log_events({
      log_group_name: "/path/to/log_group",
      start_time: 1659884400000, # 2022/8/8 00:00:00のJST
      end_time: 1659920400000, # 2022/8/8 10:00:00のJST
      filter_pattern: '"test@sample.co.jp"',
      limit: 10,
    })
    if resp.events.length == 0 
      p 'ログなし'
    else 
      resp.events.each do |r|
        # ログの本文を表示
        p r.message
      end
    end  
```

## 参考URL
公式のAPI文書：https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_FilterLogEvents.html
日付→UNIX時間の変換：https://keisan.casio.jp/exec/system/1526003938
インストール作業に関連する、色々なまとめ

# はじめに
インストール作業に関連する、色々なまとめ。

# 最終更新日
2022年8月13日

# 環境の情報
OS
Ubuntu20.04

# 注意
最新の状態を確認して下さい。

# 参考さまはこちら
https://gnupg.org/
https://www.gnupg.org/
https://wiki.archlinux.jp/index.php/GnuPG#.E9.8D.B5.E3.83.9A.E3.82.A2.E3.81.AE.E4.BD.9C.E6.88.90
https://atmarkit.itmedia.co.jp/ait/spv/1606/20/news024.html
https://www.debian.org/doc/manuals/debian-faq/pkgtools.ja.html


# はじめに

なんとなく理解した気になっていた、
インストール作業に関連するコマンドや、ファイルなどをまとめました。


# apt

・Advanced Package Tool
・コマンド。
・ソフトウェアのインストールとアンインストールを自動的に行う。
・ソフトウェアの管理を簡単に行える。


# curl

・client for URL
・コマンド。
・様々なプロトコルと呼ばれる通信する手順を使い、
URLで示されるネットワーク上の場所との間で
データを送りあったり、受け取ったりするもの。


# wget

・GNU Wget
・コマンド。
・URLを指定して、ファイルをダウンロードする。


# .deb
・ソフトウェアのパッケージ。
・gzipやbzip2、LZMAで圧縮された、2つのアーカイブで作られている。


# GPG キー

公開鍵。
暗号化ソフトで作られる。
apt-getコマンドやyumコマンドを使って、
インターネットから入手できる
パッケージが、正しい配布する先のものかどうかのチェックなどに、使われている。


# GnuPG

GNU Privacy Guard
暗号化ソフト。
RFC4880というドキュメントで定義されている。


# dpkg

Debian Package
コマンド。
パッケージ管理システムのベースを作る。


# 終わり

何か思いつきましたら、追記します。
Dockerって何なの？

インターン先でDockerの導入を提案したところ、「やってみて」と言ってもらえたのでDockerの導入をしています。
そこで今回は、そもそもDockerって何なの？何ができるの？どんな仕組みなの？という方向けの記事を書いていきます。

## Dockerって何？
よくある説明としては、「Dockerとはコンテナ仮想化環境でアプリケーションを管理したり、実行したりするためのプラットフォーム」と言われます。
でもこれだけ言われたらよくわかんないですよね。

ここで理解しないといけないのが、
1. 仮想化とは何か
2. コンテナとは何か

この２つを理解しないと訳がわからないと思います

### 仮想化とは何か？
そもそも「仮想」という言葉はどういう意味を持っているでしょうか？よく仮想化サーバーのようによく使われる単語ですよね。仮想という言葉は英単語で言うと、***virtual***と呼ばれます。この英単語には、「実質的に」、「事実上の」と言う意味があります。つまり、例えば仮想化サーバーというと、物理的なサーバーではないんだけど、実質的には物理的なサーバーと同じように扱えるサーバーのことを言うんです。

もっと抽象化して言うと、仮想化とは実際に目に見えるものではないんだけど、あたかもそこに存在しているかのように動いてくれるものを言うんですね。

### コンテナとは何か？
コンテナは実世界でも色々使われています。
こんな感じですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/5bf4d371-ceae-05f9-6fb3-abe27d04d070.png)
コンテナは中身にいろいろな商品等が含まれています。
そのコンテナの中身にアプリケーションやプログラム、OSやミドルウェア等が入っていて、それらが動作しているようなイメージを持ってもらえると理解しやすいとおもいます。

このコンテナのメリットは何かというと、***コンテナを一度作っちゃえば、特段変更をせずに違う環境でも動作する***ということです。例えば、コンテナを作成してしまえば、windows環境だろうが、Macであろうが、そのアプリケーションが動作するということです。
また、コンテナは動作が軽いというのもメリットの１つです。

## あらためてDockerって何？
「Dockerとはコンテナ仮想化環境でアプリケーションを管理したり、実行したりするためのプラットフォーム」
このようにDockerはこのように言われるわけですが、理解できるでしょうか？
コンテナ仮想環境とは、アプリケーションやプログラムやOSやミドルウェア等が入っている***コンテナ***が、***実際には目には見えないけど、あたかも存在しているかのように動いている環境***のことです。
そのような環境でアプリケーションを管理したり、実行したりするためのプラットフォームのことです。

## Dockerの何がいいのか
Dockerのメリットはなんと言っても***環境の差異を消してくれる***というものです。先ほどコンテナのメリットは、***コンテナを一度作っちゃえば、特段変更をせずに違う環境でも動作する***というのがあります。
例えば、Dockerを導入せずに、Railsのチーム開発していた場合を考えてみましょう。
AさんはRails5で開発をしていて、BさんはRails6で開発をしていて、CさんはRails7で開発をしていたらどうでしょう。バージョンによるバグが存在してしまうかもしれません。そうすると開発が滞ってしまいますよね。それはあまり良くないですね。
ですが、Dockerを導入しておけば、１つのバージョンに設定できるので、そのようなバグは生まれる確率はほぼ0でしょう。

このように環境の差異は無くなるのが、Dockerのメリットです。

以上です。Dockerを導入していない方は導入するのを検討してみてくださいね！

何か間違いがありましたら、ご教示いただけると幸いです
[Spring]ObjectProvider<T>をコンストラクタインジェクションする

## ObjectProvider<T>
`ObjectFactory<T>`の拡張バリアントで、`ObjectProvider<T>`を宣言することで、
`getIfAvailable`や`getIfUnique`を含むいくつかの追加のアクセスバリアントを提供できる。

cf. :
[ObjectProvider (Spring Framework API) - Javadoc](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/ObjectProvider.html)
[Using Spring's ObjectProvider](http://rahulsh1.github.io/tech/2018/12/20/Using-Spring-ObjectProvider)

## ObjectFactory<T>
`ObjectFactory<T>`として宣言することで、`getObject()`呼び出しが必要になるたびに、
インスタンスを保持したり個別に格納したりすることなく、現在のインスタンスをオンデマンドに取得できるようになる。

cf. [ObjectFactory (Spring Framework API) - Javadoc](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/ObjectFactory.html)

## ObjectProvider<T>をコンストラクタインジェクションする
1クラス内で、大量のクラスをコンストラクタインジェクションするとコストが高いことがある。
必要なときに`ContextLoader.getCurrentWebApplicationContext().getBean(beanName)`を呼び出すと、クラスの生成が遅延されるため、
コンポーネント生成の責務をになう`ObjectProvider<T>`をコンストラクタインジェクションしておき、必要なときにクラスを生成するようにする。

また、`ObjectProvider<T>`を経由してコンポーネントを取得することで、SingletonにDIされるべきでないコンポーネント(e.g. Requestスコープ)がDIされる危険性を除外できる。

cf. [Spring Framework コアテクノロジー - リファレンス](https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#beans)
アクセス権限を設定

# AWS IAMとは
AWS IAMとは「Identity Access Manegement(IDとアクセス管理)」の略でAWSの認証機能のこと。
AWSアカウントは契約を管理するアカウントであるのに対し、
**IAMは各種サービスへのアクセルを管理する機能**。
人に対して与えるIAMは**IAMユーザー**という。
一方、サービスやプログラムに与えるIAMを**IAMロール**という。
IAM自体は追加料金なしで利用でき、作成したユーザーが使用したAWSサービスに課金がさせる。なお、ユーザー認証に、**MFA**（Muti-Factor Authentication）の使用を推奨している。
# IAMグループとIAMポリシー
**IAMユーザー・IAMロールともに、必要最低限の機能をつけて、必要な人に渡すのが基本**。あらかじめたくさんの機能や権限をつけて渡すのはセキュリティ的に良くない。また、何かがあったときに誰が行ったかわからなくなるので、ひとつのアカウントを複数の人が使い回すのも良くない。
一方で、AWSでは複数のEC2インスタンスやS3バケットを扱うことがよくある。
そのような状況で、ひとりひとりに権限を設定していくのは大変。
そのため、**ユーザーやロールの設定を効率的に管理する仕組み**が用意されている。
ユーザーは**IAMグループ**として、グループにまとめられる。**グループ化しておくと、同じ権限を与えたいユーザーを一括管理できる。**
**IAMポリシー**は**実行者(ユーザー・ロール・グループ)がどのサービスにアクセスできるのかを決まりごとに設定する機能。**個別に設定するのではなく、ポリシーで適応する形に設定する。
権限の設定を変えたい時は、ポリシーを変更・付け替えするだけで、結びつく全てのユーザーやロールの設定を変更できる。ポリシーは１実行者に対しても設定でき、１つのポリシーを複数のユーザーやロールに設定できる。
# IAMポリシーで設定すること
IAMポリシーは何に対して（Amazon EC2サーバーやAmazon S3のフォルダなど）、どのような作業（起動や停止、ファイルの書き込みや読み込み、削除）を、許可するかしないかを設定する。
## アイデンディティベースのポリシー
実行者（ユーザー、ロール、グループ）が「何をできるのか」の形で設定
## リソースベースのポリシー
操作される側(サーバーやフォルダ)に対し、「何を許可するか」の形で設定
ex)S3の場合、「読み込み」「追加」「上書き」「削除」などの細かい設定に加え、特定の場所(IPアドレス)からだけ許可することもできる
IAMポリシーはオリジナルのものを作成することもできる（**カスタマーポリシ**ー）。
しかし、決める項目が多く、設定ミスが起きやすいので、すでに用意された**AWS管理ポリシー**を使う。
※アイデンティティポリシーとリソースポリシーでは設定できる内容が若干異なる。
## 設定する主な項目
|項目|内容|
|-|-|
|Statement|設定値。Effectや対象などを記録する|
|Sid|ポリシードキュメントに与える任意の識別子|
|Effect|有効にするかどうか|
|Action|許可または拒否される特定の操作|
|NotAction|指定されたアクションリスト以外の全てを明示的に照合|
|Resource|操作する対象|
|NotResource|指定されたリソースリスト以外の全てを明示的に照合|
|Condition|ポリシーを実行するタイミングの条件|

# 余談
## 多段階認証・多要素認証
IAMでは多段階認証と多要素認証を導入できる。パスワードだけでなく、専用のハードウェアを使って生体認証を使うなど、別の種類の認証を用意する。
AWSでは、IDやパスワードの他に、MFA（Multi-Factor Authentication）デバイスを使う。MFAデバイスには専用のハードウェアを使うケースもありますが、手軽なのは、iPhoneやAndroidのアプリを使う方法。アプリを起動すると、画面に一定時間ごとに変わる数字が表示され、ログイン時に入力して認証する。
### 多段階認証
種類は問わず2回以上認証する
### 多要素認証
２種類以上の認証を使う
Linux RPM形式のパッケージ管理ツールRPM、YUMについて（自分用メモ

Red Hat系ディストリビューションで使用されるパッケージにRPM(Red Hat Package Manager)形式があります。
RPM形式のパッケージファイル名は以下のような形式です。

パッケージ名_バージョン番号-リリース番号_アーキテクチャ名.rpm

RPM形式のパッケージ管理ツールには以下の2つがあります。

●RPMツール
RPM系パッケージを管理する基本的なツールです。設定ファイルは「/usr/lib/rpm/rpmrc」です。
RPMツールの主なコマンドは以下のとおりです。

・rpmコマンド
パッケージのインストール・アンインストールなど、基本的なパッケージ管理を行うコマンド
（Debian系Linuxでは、dpkgがほぼ同等のコマンドにあたる）

●YUM(Yellowdog Updater Modified)ツール
YUMツールはRPMツールを拡張したツール群です。インターネット上ないしはメディア上のパッケージ情報のデータベースを使い、依存関係を調整しながらパッケージ管理を行うことができます。設定ファイルは「/etc/yum.conf」、パッケージの取得元(リポジトリ)は「/etc/yum.repos.d」ディレクトリ内のファイルで設定します。
なお、リポジトリ情報を追加するには、「/etc/yum.repos.d」にリポジトリの情報を記述した拡張子.repoのファイルを配置します。「/etc/yum.conf」の[repository]セクションにもリポジトリ情報を設定できますが、「/etc/yum.repos.d」のファイルで個々のリポジトリを設定する方法が推奨されています。

YUMツールの主なコマンドは以下のとおりです。

●yumコマンド
パッケージのインストール・アンインストールなどを行うコマンド
（Debian系Linuxでは、apt-getがほぼ同等のコマンドにあたる）

yum [-y] サブコマンド

■サブコマンド
・install パッケージ名　パッケージのインストール
・update [パッケージ名]　パッケージのアップデート
・remove パッケージ名　パッケージのアンインストール
・info [パッケージ名]　パッケージの詳細情報の表示
・list [パッケージ名]　パッケージの一覧表示（バージョンとインストール済みかどうか） 
・search キーワード　指定したキーワードでパッケージの検索
・check-update [パッケージ名]　アップデート可能なパッケージの表示
・grouplist パッケージグループの一覧表示
・groupinstall グループ　パッケージグループのインストール
・deplist パッケージ名　指定したパッケージが依存しているパッケージの一覧表示

※「update」コマンドをパッケージを指定せずに実行した場合は、アップデート可能な全てのパッケージをアップデートします


●yumdownloader
パッケージファイルのダウンロードのみを行うコマンド
Select2でプログラム的にタグを削除する

# はじめに
以前「Select2でプログラム的にタグを設定する」というネタをやったが、今回はその削除版。

# 環境
- Select2 4.0.X

# 方法
全てのタグを削除するには、以下のように、設定されている全てのタグのidを取得し、それらに対してunselectイベントを設定すればよい。

```javascript
function remove_data(){
    const selections = $("js-example-basic-multiple1").select2('data').map((element) => element.id);
	for(var i =0; i<selections.length;i++){
		$("." + id).select2("trigger", "unselect", {data: { id: selections[i] } });					
	}
}		
```

また、特定のタグのみを消したい場合、タグに対応するidに対してのみunselectイベントを設定すればよい。
プロフィール画像の大きさを指定して、丸くする

調べていてなかなか出てこなかったので、少し時間かかりましたが備忘録までに。

# やりたいこと
プロフィールのアバター画像の大きさを指定して、形を丸くしたい。
```.html
<% if @user.avatar? %>
  <%= image_tag @user.avatar.url %>
<% else %>
  <%= image_tag ("default-avatar.png") %>
<% end %>
```

このままだとアバター画像の大きさが```avatar/uploader.rb```で指定されている値で表示されてしまう。
また、画像が四角なのでアイコンっぽくない。

↓
```.html
<% if @user.avatar? %>
  <%= image_tag @user.avatar.url, class: "rounded-circle", size: "150x150" %>
<% else %>
  <%= image_tag ("default-avatar.png"), class: "rounded-circle", size: "150x150" %>
<% end %>
```

viewで```class: "rounded-circle"```と```size: "150x150"```を指定してあげればOK。

これだけでもかわいいアイコンになります。

参考：https://qiita.com/moru0606/items/a7a581bcf2069389af4e
Node.js Stream 個人的まとめ

# ストリーム(Stream)とは

- ストリームとはファイルのデータ(Buffer等)を読み込んだり、読み込んだデータを別のファイルに書き込むことができるインターフェースのこと
「インターフェース」とは複数のものをつなぐ技術や方法

>A stream is an abstract interface for working with streaming data in Node.js. The node:stream module provides an API for implementing the stream interface.
>There are many stream objects provided by Node.js. For instance, a request to an HTTP server and process.stdout are both stream instances.
>Streams can be readable, writable, or both. All streams are instances of EventEmitter.

## Readable Stream
- データ入力元のこと
- fs.createReadStreamで返されるストリーム

## Writable Stream
- データ出力先のこと
- fs.createReadStreamで返されるストリーム


```typescript: stream
// 必要なモジュールを読み込む
import * as fs from 'fs';

// 読み込み用のStreamを作成(拡張子がcsvでも可能)
const rs = fs.createReadStream('hoge.pdf');

// 書き込み用のStreamを作成
const ws = fs.createWriteStream('huga.odf');

// 読み込んだpdfのBefferをWritableStreamに書き込む
rs.pipe(ws)

```

### 例 : gzipの圧縮

```typescript: gzip
import * as fs from 'fs';
import * as zlib from 'zlib';

// gzipの圧縮1
const gzip = zlib.createGzip();
const rs = fs.createReadStream('hoge.txt');
const ws = fs.createWriteStream('huga.txt.gz');
rs.pipe(gzip).pipe(ws);

// gzipの圧縮2(レスポンスにpipe)
fs.createReadStream('hoge.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('huga.txt.gz'))
  .pipe(res)
```


参考記事

https://qiita.com/masakura/items/5683e8e3e655bfda6756

https://nodejs.org/api/stream.html

https://qiita.com/takaaki7/items/fbc33dff1e17fe6a3d38

https://qiita.com/Hiroki_M/items/6045f7f0b14930aeaa40
CloudwatchLogsへ出力設定を行った後に必ず確認すること

# はじめに
CloudwatchLogsへログの出力設定ができるサービスは数多く存在し、
どれもそれぞれのサービス設定上より出力の有効化が可能かと思います。

出力設定後にログの**有効期限**を設定しなければ、
CloudwatchLogsにて自動でログが削除されず永遠とログを貯めこんでしまうため注意が必要です。

# CloudwatchLogsでログの有効期限設定
①[コンソール](https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logsV2:log-groups)を開く
②ロググループを選択する
![2022-08-13_12h06_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/a06ac2ef-7885-ad4d-9df8-7527c46de6df.png)
③アクション ＞ 「保持設定を編集」を選択する
![2022-08-13_12h09_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/1ed1ce77-5ced-5af8-e213-417566f5ef56.png)
④お好みの保持期間を選択する。
⑤「保存」を選択する
⑥CloudwatchLogsの一覧に戻り、「保持」欄に設定した値が表示されていればOK
![2022-08-13_12h11_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/bcfbcdb3-c739-8b1f-d4b8-d6d044d17985.png)

# 最後に
単純ですが見落としがちなポイントを共有させていただきました。
本番運用が始まってから設定漏れが発覚するとリカバリが大変なので、
初期段階での気づきになれば幸いです。
仮想通貨の現在価格をLineに通知したい

# はじめに
特定の仮想通貨の現在価格を定期的に知りたいなと思い色々調べていたら  
[Line Notify](https://notify-bot.line.me/ja/) と [CoinMarketCap](https://coinmarketcap.com/api/) を使えばできることが判明！！  
しかもどちらも無料で使えるという。。。(リクエスト回数?とか縛りはありそう)  
~~これで億万長者...~~  

# 目次
1. [事前準備](#事前準備)
2. [実装](#実装)
3. [参考](#参考)

# 事前準備
[Line Notify](https://notify-bot.line.me/ja/) と [CoinMarketCap](https://coinmarketcap.com/api/) へ登録しAPIキーを取得する

#### Line Notifyの登録
すでに色々な方が記載しているのでこちらは割愛。。。
>参考：[PythonでLINE Notifyへ通知を送る
](https://qiita.com/akeome/items/e1e0fecf2e754436afc8)

#### CoinMarketCapの登録
① [CoinMarketCap](https://coinmarketcap.com/api/) の「GET YOUR API KEY NOW」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/42d19d0b-fb4a-d3d4-fc5b-d65cabd6d8fb.png)

② 項目を埋めて「CREATE MY ACCOUNT」をクリック  
※無料で使用枠は初期設定のBasicのみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/be3db174-c2a8-7277-2ffd-a24eb18e0f62.png)
③ ログイン後APIキーをコピー  
API KEYにカーソルをもっていけばコピーできます  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/4fee13e0-9098-f104-7fda-a3333679e621.png)

API詳細については画面左下のAPI DOCUMNETATIONから確認可能  
今回は特定の通貨の値段を知りたいので/cryptocurrency/*を使う  
![SnapCrab_NoName_2022-8-13_11-2-39_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/7d352a42-f89b-160b-f0ad-2baa812f6d0b.png)

# 実装
```python
#!/usr/bin/env python3
import requests
import json
import numpy as np

# CoinMarketCap API
COIN_API_KEY = 'hogehogehogehogehogehogehogehogehogehoge'
COIN_URL = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest'

# Line Notify API
LINE_API_KEY = 'hagehagehagehagehagehagehagehagehagehage'
LINE_URL = 'https://notify-api.line.me/api/notify'

def get_coin_data():
    targe = {'GMT,SOL'}

    # CoinMarketCapリクエスト情報
    parameters = {
        # 取得時の法定通貨
        'convert': 'USD',
        # 取得対
        'symbol': 'GMT,SOL' # todo target
    }
    headers = {
        'Accepts': 'application/json',
        'X-CMC_PRO_API_KEY': COIN_API_KEY,
    }

    # CoinMarketCapから通貨情報を取得
    session = requests.Session()
    session.headers.update(headers)
    try:
        response = session.get(COIN_URL, params=parameters)
        # response = requests.get(COIN_URL, headers=headers)
        resp = json.loads(response.text)
        data = resp['data']
    except (ConnectionError, Timeout, TooManyRedirects) as e:
        print(e)
    
    # とりあえず必要な情報のみ拾う
    line_message=''
    for key in data:
        symbol = key
        price = np.round(data[key]['quote']['USD']['price'],decimals=3)
        line_message+=f'\n{key} -> price: {price}$'

    # Lineに通知
    headers = {'Authorization': f'Bearer {LINE_API_KEY}'}
    data = {'message': f'message: {line_message}'}
    requests.post(LINE_URL, headers=headers, data=data)

if __name__ == '__main__':
    get_coin_data()


```

### 結果
![S__13393927.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295610/0257fb5d-c65e-485a-c4e5-50049ceceed9.jpeg)

# 参考

[PythonでLINE Notifyへ通知を送る](https://qiita.com/akeome/items/e1e0fecf2e754436afc8)  
[CoinMarketCap APIを使ってみる](https://zenn.dev/maepu/articles/6a435e7eccbd92)
Java→Kotlin化メモ

# 起動時エラー

> kotlin_module is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.4/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.

## 対応
```build.gradle.kts
jar {
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
```

# gradle build error
> xecution failed for task ':compileJava'.
> java.lang.IllegalAccessError: class lombok.javac.apt.LombokProcessor (in unnamed module @0xa5488cf) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module @0xa5488cf



## build.gradle.kts
```build.gradle.kts
application {
    tasks.jar {
        duplicatesStrategy = DuplicatesStrategy.INCLUDE
    }
}
```

# `@Slf4j`が効かない
未サポート

## 対応
```logger.kt
import org.slf4j.Logger
import org.slf4j.LoggerFactory

val Any.log: Logger
    get() = LoggerFactory.getLogger(this.javaClass)
```

# `@RequireArgsController`で用意したコンストラクタインジェクションが効かない
## code
```kotlin
@RequireArgsController
class XYZ {
    private val context: ApplicationContext? = null
}
```
## 対応
アノテーションを削除。
手組みのコンストラクタへ引っ越し。
```kotlin
constructor(private val context: ApplicationContext)
```
【JavaScript】非同期処理① 〜同期処理・非同期処理〜

# 概要
JavaScriptを学習、理解を深めるため「[JavaScript Primer 迷わないための入門書](https://jsprimer.net/)」を読み、
理解した内容等を記載していく。

「[【JavaScript】JavaScript入門一覧](https://qiita.com/andota05/items/22fae452225b785fd405)」に他の記事をまとめています。

# この記事で理解できること
* 同期処理と非同期処理について
* 非同期処理における例外発生時の挙動

多くのプログラミング言語にはコードの評価の方法として
「**同期処理（sync）**」「**非同期処理（async）**」という大きな分類がある。

# 同期処理
* コードを上から順番に処理する(処理1 -> 処理2 -> 処理3...)
* 一つの処理が終わるまで次の処理は行われない。

```js
// 同期的な処理
console.log("処理1");
console.log("処理2");
console.log("処理3");
// => 処理1
// => 処理2
// => 処理3
```

# JavaScriptにおける同期的処理の懸念点
* JavaScriptは基本的にブラウザのメインスレッド（UIスレッドとも呼ばれる）で処理が実行される。
* メインスレッドは`表示の更新`といった`UIに関する処理`などを行なっている。
* その為、メインスレッドが何らかの処理で専有されると、表示がフリーズしたかのような現象が起こる。

※以下のサンプルコードの内容を「index.html」のようなファイル名で保存し、ブラウザで開いてみてください。
※ボタン押下前はホバー時の色の変化が確認が可能ですが、ボタン押下後、3秒間フリーズしたかのような状態になります。

<details><summary>サンプルコード</summary>

```html
<html>
  <style>
    button {
      padding: 25px;
      border: none;
      background: #e5b6e2;
    }
    button:hover {
      background: #dec8dd;
    }
  </style>
<body>
  <button type="button" onclick="block()">ボタン</button>

  <script>
    // ボタンをクリックした際に呼び出される関数
    function block() {
      console.log("clickButton");
      blockFunc(3000);
    }

    // 処理を指定時間ブロックする処理
    function blockFunc(time) {
      const startTime = Date.now();

      while (true) {
        const diffTime = Date.now() - startTime;
        if (diffTime >= time) {
          return;
        }
      }
    }
  </script>
</body>
</html>
```
</details>

# 非同期処理
* 同期処理とは異なり、`一つの処理が終わるのを待たずに`次の処理も実行する。
* つまり、非同期処理では`同時に実行している処理`が複数ある。

```js
// 非同期処理の代表的な関数、setTimeout関数を使用する

function asyncFunc() {
  console.log('処理1を始めます');

  // 仮想的に処理1を5秒かかることにする
  setTimeout(() => {
    console.log('処理1が終わりました');
  }, 5000);

  // 並行して処理2を開始
  console.log('処理2を始めます');
   // 仮想的に処理2を3秒かかることにする
  setTimeout(() => {
    console.log('処理2が終わりました');
  }, 3000);
}

asyncFunc();
// => 処理1を始めます
// => 処理2を始めます
// ...3秒後
// => 処理2が終わりました
// その2秒後(計5秒後)
// => 処理1が終わりました
```

上記が同期的処理であった場合は、以下のように上から順に処理が行われていたはず。

```js
// ...省略

asyncFunc();
// => 処理1を始めます
// => 処理1が終わりました
// => 処理2を始めます
// => 処理2が終わりました
```

# 非同期処理と例外処理
* 非同期処理では、`try...catch構文`を使っても`非同期的に発生した例外`をキャッチできない。
* また、非同期処理の外からは`非同期処理の中で例外が発生したかがわからない`。
* そのため、非同期処理の中で例外が発生したことを`非同期処理の外へ伝える`方法が必要。

```js
// 同期処理と例外処理
function syncErrorFunc() {
  try {
    console.log("同期処理を開始します");

    console.log("処理1");
    console.log("処理2");
    
    throw new Error("同期処理中にエラーが発生しました");
  } catch(error) {
    console.log(error.message);
  }
}

syncErrorFunc();
// => 同期処理を開始します
// => 処理1
// => 処理2
// => 同期処理中にエラーが発生しました(キャッチできている)
```

```js
// 非同期処理と例外処理
function asyncErrorFunc() {
  try {
    console.log("非同期処理を開始します");
  
    console.log("処理1");
    console.log("処理2");
  
    // 非同期処理を仮定
    setTimeout(() => {
        throw new Error("非同期処理中にエラーが発生しました");
    }, 1000);
  } catch (error) {
    // 非同期エラーはキャッチできないため、この行は実行されない
    console.log(error.message);
  }
}
asyncErrorFunc();
// => 非同期処理を開始します
// => 処理1
// => 処理2
// ...
// => Uncaught Error: 非同期的処理中にエラーが発生しました(キャッチできていない)
```

以降の関連記事②③④では主要な非同期処理および例外の扱い方として
② コールバックを用いた非同期処理
③ Promise
④ Async Function
について記載する。
セキュリティキャンプ 2022 感想

## 始めに
2022/8/9~2022/8/12 でセキュリティキャンプに参加したのでその感想を参加記録として記事にしました。本記事では講義内容に焦点をあてるため、応募課題や事前課題についてはかなり省いております。

## セキュリティキャンプとは
>「セキュリティ・キャンプ」は、学生に対して情報セキュリティに関する高度な技術教育を実施し、次代を担う情報セキュリティ人材を発掘・育成する事業です。
引用先：https://www.ipa.go.jp/jinzai/camp/index.html

IPAが主催されているイベントで、今年はオンラインで5日間集中的に講義が行われました。セキュリティに興味のある方はぜひおすすめします！
## キーワード
 - 多層防御
 - サプライチェーン
 - 歴史的事情
## 講義内容
セキュリティキャンプの中でもハードウェアやIoT、AIなどいくつかテーマがあります。自分はその中でも今回Webセキュリティコースを選択し、それぞれ以下の「学んだこと」で紹介する6つの講義を受講しました。

## 学んだこと
- #### B1 作って学ぶWebブラウザ
    ブラウザの仕組みを学びつつ、ブラウザの事前課題ではRustで講師の方が用意してくださったプログラムを改変したりしました。そしてそこからブラウザに潜む脆弱性などに関して学びました。
- #### B2 マイクロサービス・分散モノリス的アーキテクチャへの攻撃手法
    ハンズオンでのアクティビティがメインでした。そしてマイクロサービスシステムに対してどのように攻撃が行われるかを見ました。講義後半ではそれらに対してどのように防御できるかを学びました。
- #### B3 Policy as Code入門
    「Rego を使ってポリシーをコードでまとめてみよう」をコンセプトにしたハンズオン形式の講義でした。ポリシー策定の重要性からAWSキーのポリシー策定をテーマにした実用的な内容まで幅広く学びました。
- #### B4 モダンな開発環境のセキュリティ及びCI/CDパイプラインのセキュア化
    Google cloud と GitHub を使った CI/CDパイプラインに対して攻撃をハンズオンで行い、それに対する対策を考える講義でした。チームで開発するときに今まではソフトの脆弱性のことだけでCI/CDについてはあまり考えてこなかったので「気を付けないと」と思わされました。
- #### B5&B7 ソフトウェアサプライチェーンセキュリティのこれから
     2回に分けて講義がありました。1回目はSigstoreについてどのような仕組みなのか、またサプライチェーンにどのように攻撃者は攻撃するかを学びました。その後2回目で実際に手を動かしてみて Docker イメージに署名をかけて、自分がそのファイルを編集したことを確認しました。
- #### B6 実践Linuxコンテナ実行基盤セキュリティ
    Container と Kubernetes それぞれについて学んだ後、それらに対してどのように攻撃が行われているのか、これもまたハンズオン形式で学びました。そしてそれらの攻撃に対してどのように対処できるかを最後に教えて頂きました。

## これから
 - 学ぶ量が多く消化不良を起こしているので、今後公開された資料をよく見直して理解を深めていくことが目標です。
 - B1 でのブラウザの改良や B5, B7 で学んだことを自分の開発環境にも組み込みたいです。
 - グループワークで CTF に取り組むことになったのでそれの準備もします。

## まとめ
全体を通してとても濃い5日間でした。高レイヤだけでなく、コンテナなどの低レイヤを触る良いきっかけになり、参加して良かったなとすごく思いました。
別のイベントにもぜひ参加していき、様々な技術を学んでいきたいです。
この場で改めてIPAの方々や講師陣、その他大勢の関係者の皆様に感謝を申し上げます。
コマンドでIMEの状態を変更する（im-select）（Win/Mac/Linux）

[im-select](https://github.com/daipeihust/im-select)をインストール。

Macの場合：

```
$ brew tap daipeihust/tap && brew install im-select
```

切り替え：
```
$ /usr/local/bin/im-select com.apple.inputmethod.Kotoeri.RomajiTyping.Roman
```

Vimで下記のようにしておけばインサートモードを抜けたときにIMEをオフにできる：
```
autocmd InsertLeave * :silent !/usr/local/bin/im-select 
com.apple.keylayout.ABC
```
【BladeOne】CSRF対策

# はじめに
Laravel感覚で途中まで実装できていましたが、CSRF対策のところで躓きました。
実装するのに少し時間がかかってしまいました。
同じように悩む方の参考になればと思います。

## インストールがまだの方
下記記事を参考にしてください。

https://qiita.com/Shogongon/items/80ae1a2183d0fb2d1c02

## 注意
追記　8月15日
「ログイン済み」であることが条件と記載しておりましたがそのような条件はありません。
注意の内容自体が間違った内容でした。
取り消し線で消させて頂きます。
注意自体が間違っているとは...本当にすみません...
~~下記内容は「厳密なCSRFの用語の定義」を満たしていません。~~
~~CSRFの前提条件として「ログイン済み」であることが条件のためです。~~
~~あくまでもサンプルソースであることのご理解願います。~~

# 結論
※注意：session_start();でセッションの処理を開始しておく必要があります。
- CSRFトークンの送信側
```php:form.php
<?php
require_once __DIR__."/vendor/autoload.php";
use eftec\bladeone\BladeOne;

// getCsrfToken内でsessionにtokenを格納しているため必要。
session_start();

// 読み込みを行いたいテンプレートパス記述
$views = __DIR__.'/views';
$cache = __DIR__.'/cache';
$blade = new BladeOne($views,$cache,BladeOne::MODE_AUTO);

// この記述がないとCSRFトークンのvalueがHTMLに出力されない。
$blade->getCsrfToken();

echo $blade->run("form");
```

```html:form.blade.php
<form action="catch.php" method="POST">
  @csrf
  <button>送信</button>
</form>
```

- CSRFトークンの受信側
```php:catch.php
<?php
require_once __DIR__."/vendor/autoload.php";
use eftec\bladeone\BladeOne;

// csrfIsValid内でsessionからtokenを取得しているため必要。
session_start();

$blade = new BladeOne();
if($blade->csrfIsValid() !== true) var_dump("エラー");
```

# 参考文献
[EFTEC/BladeOne](https://github.com/EFTEC/BladeOne#php-5x-support)
Reactでグラフ描画(react-chartjs-2)

## 背景
reactでグラフを描きたくなりまして、いくつかmoduleがあるのですが、一番人気がありそうなreact-chartjs-2を選択しました。
参考記事を参照してサンプルコードをそのまま走らせてもうまくできなかったので、備忘録代わりに投稿します。

## 環境

* Macbook Air (M1, 2020)
* Docker 20.10.16
* Docker Compose 2.5.1
* node v18.7.0
* react 18.1.0
* react-dom 18.1.0
* chart.js 3.9.1
* react-chartjs-2 4.3.1

コンテナで作業しています。

## 参考記事の検証
参考記事は腐るほどみつかります。

https://fwywd.com/tech/react-chartjs-2

https://px-wing.hatenablog.com/entry/2020/12/30/084916

でも、コピペして実行してみるとブラウザには真っ白な画面。デベロッパーツールでなにやらエラーがたくさん。はてはて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152192/39a197a5-c1b7-f4da-f3fa-099e45fc9f8e.png)

## 解決方法

エラーメッセージの「Uncaught Error: "category" is not a registered scale」でgoogle検索してみると見つかりました。

https://zenn.dev/rinda_1994/articles/7e04702247f3e2

結果、こちらの二行を追記することで解消。

```
import { Chart, registerables } from "chart.js"
Chart.register(...registerables)
```

こんな感じになりました。めでたしめでたし。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152192/87e91118-8108-c309-8bf1-87f0c7c1277c.png)