OmniAICreator/Qiita-1.07M huggingface dataset:
Certified Kubernetes Application Developer (CKAD) 受験記録

#はじめに
[CKA](https://qiita.com/dingtianhongjie/items/de245ca7978266ae4a96)に続いて、Certified Kubernetes Application Developer（CKAD）を取得できましたので、受験記録を書きたいと思います。
これからCKADを受験される方の参考になれば幸いです。

#試験内容
[こちら](https://training.linuxfoundation.org/ja/certification/certified-kubernetes-application-developer-ckad/)にか書かれています。
私が受験したときのバージョンは1.20で、時間は2時間でした。

また、CKAと同様にマニュアルを見ながら受験ができます。

#事前準備
##学習
CKAのときにKubernetesは一通り勉強しましたので、今回はCKADの受験対策として以下を繰り返し練習しました。

[Kubernetes Certified Application Developer (CKAD) with Tests](https://www.udemy.com/course/certified-kubernetes-application-developer/)

講座を一通り実施した後、最後にある模擬試験を全部できるように練習しました。
CKADは2時間では時間がギリギリでしたので、内容を理解するのはもちろんですが、早く解けるように繰り返し練習しました。

内容的には模擬試験は参考になりますが、本番はより実践に近いと感じました。
Udemyの模擬試験は、設定するパラメーターが指定されていてそれを設定する感じですが、本番は要件が指定されて、その要件に沿った設定をする感じです。

##申し込み
Linux Foundationのサイトから申し込みます。私が申し込んだときは、登録画面では\$300となっていたのにレジに行ったら\$330になってました。
受験費用を会社に\$300で申請していたので困ったのですが、15%割り引きのコードがありましたので予算内で収まりました。
今日見たら、レジでも\$300でした。なんでだろう？？

#受験当日
##会場準備
CKAと同様に自宅の寝室で受験しました。
寝室の離れた場所（手が届かない範囲）に物が置いてありますが、それは何も言われなかったです。

RedHatのリモート試験では、Webカメラで手元を映すように言われますが、今回は顔を映す場所に置けと言われました。CKAの時は手元だった気がします。

また、今回は試験官とのやり取りが日本語でした。機械翻訳のような感じでしたが、特に困ることはありませんでした。

##PC
Windows10の端末を使用しました。
試験はChromeブラウザで行います。開いていいタブは試験環境とマニュアルの2つだけです。試験中に間違えて3つ目のタブを開いてしまいましたが、何も言われず失格にもなりませんでした。3つ目のタブはすぐに閉じました。

##受験
試験環境で特に困ることはありませんでした。私が気を付けた方がいいと思ったのは以下になります。

- 設問毎にコンテキストを設定します。前の設問と同じときには設定する必要はありませんが、同じかどうか確認する時間がもったいないので、全ての設問でコンテキストを設定しました。
- 明らかに問題がないはずの操作でエラーになることがありました（きっとどこかで見落としがあるのでしょうけど）。悩んでても時間がもったいないので、そういう問題は飛ばしてとにかく最後までやり切ることを目指しました。実際、時間はギリギリでした。
- 各設問毎に部分点があるのかはわかりませんが、全部はできなくてもできること（例えばNamespaceを作るとか）だけでもやっておきました。

#結果
CKAのときは当日の夜に結果が来たのですが、今回は翌日のお昼ごろに来ました。遅いのでダメかなと思ったのですが、合格できてよかったです。

https://www.credly.com/badges/87f3f9e7-8587-46d5-913c-36b70eaa143a
Selenium inputかbuttonか分からないボタンをクリック

画面のマニュアルしか持っていなくてHTMLソースをまだ見れないうちに、ボタンクリック動作を書く方法です。ボタンがinputかbuttonか分からないので「|」で結合しています。idやnameがあるかどうかも分からないのでボタン名での記述です。
「|」の前後の半角スペースはあってもなくても動きます。

```HTML.html
    <input type="submit" value="登録" />
または
    <button type="submit">登録</button>
```

```C#.cs
    driver.FindElement(By.XPath("//input[@value='登録'] | //button[text()='登録']")).Click();
```

```Java.java
    driver.findElement(By.xpath("//input[@value='登録'] | //button[text()='登録']")).click();
```

```Python.py
    driver.find_element_by_xpath("//input[@value='登録'] | //button[text()='登録']").click()
```

2021/05/19追記：HTMLソースが見れるようになって見てみたらaタグだった…。
【Linux】Linuxにおけるディレクトリの構成について

#はじめに
LinuxのFHSの構造について曖昧だったので、自分用にまとめました。
Linuxの勉強を始めた初心者の方にも参考にしていただければと思います。

#FHSの構造
Linuxにおけるディレクトリ構成の基本ルールをFile Hierarchy Standard(FHS)と呼びます。
FHSにおいて、`/`ディレクトリ直下のディレクトリ構造は以下のように定義されています。

| ディレクトリ名 | 用途 | 静的 | 共有可能 |
|:-|:-|:-:|:-:|
| /  | ルートディレクトリ |||
| /bin | 基本コマンド |||
| /boot  | システムを起動するために必要なファイル ||×|
| /dev  | デバイスファイル ||×|
| /etc  | システムやミドルウェアに関する設定ファイル |○|×|
| /home  | ユーザのホームディレクトリ ||○|
| /lib  | /binや/sbinにあるコマンドを実行するのに必要なライブラリ |||
| /media  | リムーバブルメディアのマウント場所 |||
| /mnt  | 一時的なファイルシステムのマウント場所 |||
| /opt  | パッケージ管理システムでインストールされたプログラム |○||
| /proc  | プロセスの実行状況(CPU, メモリ, FSの使用状況など)を記載したファイル |||
| /root  | rootユーザのホームディレクトリ |||
| /run  | 実行中プロセスのデータ |||
| /sbin  | システム管理者用のコマンド(起動・停止・再起動) |||
| /srv  | システムで動くサーバ用のデータ |||
| /sys  | カーネル・システム情報の疑似ファイルシステム  |||
| /tmp  | 仮想メモリ上の一時ファイル  |||
| /usr  | 第2の階層、ユーザが共通的に利用するプログラムやライブラリ |○|○|
| /var  | 可変データ(ログ /var/log、ロックファイル /var/lock、キャッシュ /var/cacheなど) |×|△|

ディレクトリによって、以下の性質が異なります。

- ディレクトリ下の階層が静的(書き換わらない)かどうか
- ディレクトリを複数のマシン間で共有できるかどうか

また、`/usr`には、`/`と同様に`/bin` `/sbin` `lib`のディレクトリがあり、コマンドやライブラリが置かれます。
FHSの定義では、`/`直下のディレクトリ側には、システムの起動・復元・復旧・修復するのに必要なコマンド群を置くべきだとされているみたいです。
W3C準拠のカメラ呼び出し機能をAngular上でシンプルに書いてみる

まずはテンプレート部分。とてもシンプルです。

```app.component.html
<video autoplay></video>

```
<hr>

続きましてts部分。
video.srcObject = stream
のvideo部分がオブジェクトは 「'null' である可能性があります。ts(2531)エラー」で怒られてしまうので
let video = document.querySelector('video')!
というようにvideo の初期化時に!を付けてnullにはなりませんよということを明示的に書く必要がtypescriptだと必要です。W3Cのカメラについて調べるとjs前提の記事しかなかったので地味にこけました。

```app.component.ts
import { Component } from '@angular/core';
import { Subject } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent  {
  ngOnInit(): void {
    let video = document.querySelector('video')!

    const options = {
      video: true
    }
    navigator.mediaDevices.getUserMedia(options)
    .then(stream => {
      video.srcObject = stream
    })
    .catch((error) =>{
      console.log(error)
    })
  }
}

```
<hr>
下記はライブデモです。(stackblitの仕様上？PCからの起動のみ)
https://stackblitz.com/edit/angular-ivy-vfwkzg?file=src%2Fapp%2Fapp.component.ts
<br>

何故か再起動がstackblitzの場合必要なのでお試しの際はお手数ですが再起動してください。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630191/99dfece6-9fa0-6923-c3cc-087a1e534649.png)
JavaScriptのイベントドリブン

##イベント

イベント：Userが何かすること
イベントドリブン：イベントに対するJavaScriptの動作

イベントの書き方↓

```Javascript
document.getElementById('ID名').addEventListener('click',function(){ .. });
```

解説

```Javascript
document.getElementById('ID名')
//まずはIDでエレメントを取得する
```

```Javascript
.addEventListener('click',function(){ .. });
//addEventListenerでイベントを発火
```

**addEventListenerには２つパラメーターが必要**
①イベントの種類（今回はクリックしたとき）
②動かすプログラム

②に関しては無名関数やらなんやらとあるみたいですが、
ひとまず、function(){}と書き方を覚えておけば良い。

以上
Cloud9でenvironment is running out of disk spaceが出た時の解決方法

# 概要
RailsチュートリアルをCloud9で開発していたところ、下記のエラーが出るようになり、ファイルの編集やターミナル等が使用できなくなりました。

`our environment is running out of disk space. Please free up space or resize your EBS volume (see how)`

## 原因

原因はAmazon EBS ボリュームの容量不足です。容量を空ければ解決できます。

## 解決手順

### 1. EBS ボリュームの確認

ターミナルで`df -h`コマンドで容量を確認します。

```
$ df -h
```

`/dev/xvda1`の使用容量を減らします。現在は99%です。

![スクリーンショット 2021-05-02 21.06.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264073/12825912-6e61-a552-568b-d13d055241f6.png)

### 2. EBS ボリュームを増やす

[EC2](https://console.aws.amazon.com/ec2/)にアクセスし、Name列がcloud9のインスタンスID列の値をコピーします。

![スクリーンショット 2021-05-02 21.03.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264073/3b604f04-6997-e4cf-4694-633074af2efd.png)


Elastic Block Storeのボリュームにアクセスし、コピーした値で検索をかけます。

![スクリーンショット 2021-05-02 21.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264073/3eae9222-1fca-9b87-e7a8-e6acb762d9ad.png)

ボリュームを選択した状態で上部の「アクション」ボタンをクリックし、ボリュームのサイズを30に変更します。（本記事を書いた時点では30は[無料枠](https://aws.amazon.com/jp/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&all-free-tier.q=ec2&all-free-tier.q_operator=AND)ですが、ご自身でご確認ください）

![スクリーンショット 2021-05-02 21.04.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264073/291a0b92-f9c8-b05f-3e35-b709fe5bf248.png)

[EC2](https://console.aws.amazon.com/ec2/)にアクセスし、、Name列がcloud9のインスタンスを選択し、「インスタンスの状態」ボタンをクリックし、インスタンスを再起動します。

Cloud9にアクセスし、ターミナルで`df -h`コマンドで容量を確認します。`/dev/xvda1`の使用容量が大幅に減っていれば成功です。

## 参考

https://railstutorial.jp/help#volume-up-aws-ebs
【docker】docker上でrails コマンドを使う【rails】

# 前提
docker でrails アプリを立ち上げて、
`Yay! You’re on Rails!`を表示できている。

# とりあえず"docker compose run web"をつける

例えば、userモデルをdocker上で作りたい場合、

```
docker compose run web rails g model User user_name:string{64}
```

# おまけ

こんな記述の仕方だと見やすいかも。

```
% docker compose run web rails g model Product \
product_name:string{64} \
category_id:bigint \
price:integer \
description:string{256} \
sale_status_id:bigint \
product_status_id:bigint \
regist_date:timestamp \
user_id:bigint \
delete_flag:boolean
```

 `\ + enterキー`で、ターミナル上での改行ができる。
migrationファイル作るときは見やすい。

`docker compose run web rails g model モデル名`はタイポしないようにしよう。
間違えた名前のファイルができて面倒な事になる。

他は、適宜migrationファイルをいじれば良いのでタイポしてもそこまで影響はない。
【実習】Dockerを利用したJenkinsのインストール

今回はDockerを使ってJenkinsのインストールを試してみたいと思います。

#jenkinsイメージの取得
まずは以下のコマンドを実行してjenkinsのイメージをダウンロードします。

```
docker pull jenkins/jenkins:latest
docker images #中にjenkinsのイメージが存在していればOK
```

#Jenkinsの起動
Jenkinsを起動するには以下のコマンドを実行します。
起動時にport番号を指定しています。

```
docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:latest
```

上記コマンドでも起動は可能ですが、再起動のたびに設定が全て消えてしまいます。
設定を保存する場合は、事前に設定保存用のディレクトリを作成してから以下のコマンドを実行します。

```
mkdir <設定保存先パス>/jenkins_home
chown -R 1000:1000 <設定保存先パス>/jenkins_home #これを実行しないと権限拒否のエラーが発生する
docker run -p 8080:8080 -p 50000:50000 -v <設定保存先パス>/jenkins_home:/var/jenkins_home jenkins/jenkins:latest
```

上記コマンド実行後、以下のメッセージでフリーズしますが、`http://<サーバーIP>:8080`へアクセス出来れば問題ありません。
フォアグラウンドで実行しているため、`ctrl + c`を入力するとjenkinsのタスクを強制終了します。
バックグラウンドで起動する場合（デタッチド）、コマンドに`-d`オプションを追加して実行します。

```
INFO    hudson.WebAppMain$3#run: Jenkins is fully up and running
```

`http://<サーバーIP>:8080`へアクセスすると、以下のような画面が表示されます。
ここで入力するパスワードは、コマンドラインの`Please use the following password to proceed to installation:`というメッセージの下の行に出力されています。
![jks01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/5eb30c49-603b-721b-3944-4d27779a7464.png)
次に以下の画面が表示されます。
左のボタンは選択可能なプラグインを全てインストールし、右のボタンは必要なプラグインのみ選択してインストールするようです。
特にプラグインを選択する必要が無ければ左の「Install suggested plugins」をクリックします。
![jks02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/2eed9362-9110-7e09-f7b9-23d66dddb188.png)
プラグイン選択後は以下のような画面に移ります。
ちなみにフォアグラウンドで起動している場合、この画面の状態でコマンドラインを確認するとインストールの処理が流れている事がわかります。
![jks03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/b4526f09-812a-a39a-b523-714d4a5323f7.png)
インストール完了後、管理者アカウントの作成画面が表示されます。
![jks04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/66bc3322-14bb-4cf4-efed-a2f921ae91df.png)
管理者アカウント作成または「Skip and continue as admin」押下後(？)、以下の画面が表示されますので、「Start using Jenkins」をクリックします。
![jks05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/c78825ab-d466-839f-0fd4-9ebe8747c376.png)
すると以下のJenkinsのトップ画面が表示されます。
以上でJenkinsの起動が完了です。
![jks06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858317/d743fc45-e3af-171f-cdf6-b52568599f7a.png)
今回はここまでです。
次回移行どこかでdockerfileやdocker-composeを使ったjenkinsの構築を試してみたいと思います。
JavaScriptの関数

##関数の定義

JavaScriptの関数（Function）を定義する

```JavaScript
const addZero = function(value){
   if (value > 10) {
     value = '0' + value ;
 
   return value;
}

let now = new.Date();
let seconds = now.getSeconds();
seconds = addZero(seconds);
```

解説します↓

```JavaScript
const addZero = function(value){
//　定数の定義　=functionで関数として扱われる
//　（）は関数を適用する対象
   if (value > 10) {
     value = '0' + value ;
 
   return value;
//returnの記述は必ずする（＝戻り値、返り値）
}

let now = new.Date();
//オブジェクトのインスタンス化
let seconds = now.getSeconds();
//それに対して秒を取得するメソッド
seconds = addZero(seconds);
//secondsを持たせたaddZeroを呼び出し、戻り値をsecondsに代入
```

という感じ。

戻り値は1つだけしか指定できないので、
複数戻り値が欲しい場合はオブジェクトを作る形で対応するらしい（やり方はまだ知らない）

それから、関数の定義の仕方は

```javascript
funciton addZero (value){  }
```

でもいいらしい。
（どちらかというと先述した方が一般的っぽい）


ふむ〜。
戻り値の考え方と、最後の関数呼び出しで代入らへんが
なんかモヤモヤとしちゃう。

以上
【TP転職市場PJ日記その１】環境構築編 wsl2+docker+laravel構築まで

#プロジェクト企画書
勢いで作ったのでクオリティとか終わっているかと思いますがまぁプライベートの一ヘタレ技術者の戯言なので
許してくださいｗ
というわけで早速、let's環境構築

#前提環境
PC環境は↓
![キャプチャ.123.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/db83e6ed-1c11-a29d-e0ce-52fc698fd676.png)

#環境構築
といっても、先人の大先輩方の手順をなぞるだけ。というわけで参考になったURLを記載
[Windows 10 Home で WSL 2 + Docker を使う]
https://qiita.com/KoKeCross/items/a6365af2594a102a817b
※ちなみにwsl2入れたらもういきなりlinuxコマンド使えて本当に感動した。macいらんっぽい。ここまではdockerが使える準備が完了

続いてlaravelの環境構築を行う
[【超入門】20分でLaravel開発環境を爆速構築するDockerハンズオン]
https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4
※この記事書いてる方からTwitterでいいね貰ってたな…すげー人だったんだ(；ﾟдﾟ)ｺﾞｸﾘ…あざます＾＾

ただ記事を進める中でgit hubのssh設定があったが以下の設定は要らなかった様子。
`UseKeychain yes`
あと、パーミッションの問題もあったので以下を追加した
`Users git`

そんなこんなであっという間にLaravel環境構築が完了してしまった。
あとでルートユーザーのパスワードとか変えておこう＾＾

※Windows Terminalも入れておくとより便利
https://www.microsoft.com/ja-jp/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab

#次回は
DB設計周りとログインとか何がサクッとできそうか当たり付けをするところをやっていこうと思います。＾＾
ランクマもしよ＾＾
リストの追加方法を学ぼう (今日のPython Day2)

##0. はじめに
　2日目ですね。記事を書いている当人が3日坊主にならないか心配しています。一緒に頑張っていきましょう。　
　毎日1問、Pythonの問題を出題します。出題範囲は特に定めていませんがはじめの1ヶ月くらいは『入門Python3　第2版』の第1～11章までのことが分かれば解ける問題にしたいと思います。

##1. 問題
リストcに仲間はずれにされているNobitaを追加しましょう。

```python
c = ["Gian", "Suneo"]
```


##2. 解答

```python
c = ["Gian", "Suneo"]
c.append("Nobita")
print(c)
```

別解

```python
c = ["Gian", "Suneo"]
c = c + ["Nobita"]
print(c)
```

「Python リスト 追加」と検索するとまずappendが出たのでこれを解答にしました。自分もよくこれを使います。実は他にも方法があって単純に「リスト＋リスト」でこっちの出来ます。こっちの方が簡単だと思うのですが、なぜかよく忘れます。ちなみに別解の2行目は代入演算子「+=」を用いた方がより良いですね。

```python
c = ["Gian", "Suneo"]
c += ["Nobita"]
print(c)
```

##4. おまけトーク
　ジャイアンを英語で表記するとGianになるんですね。そのままZyaianかと思いました。あともっとどうでも良いのですが、アメリカで放送されているドラえもんではジャイアンはBig Gだそうです。
開発テスト用にダミーメールアドレスを使用して送受信の確認をする

###環境
java8
Spring Boot2.4.0
Eclipse2020-12

###目的
受発注システムを開発していて、発注の際に「システムメールを送信して通知する機能」を実装しようとしたけど、ユーザーのメールアドレスはどれもダミーのメールアドレス。動作確認できるように本当は有効なアドレスを使用したほうが良いのかもしれませんが、メールの送信自体はシステムからオンリーになるので、受信の確認はしなくて良い。設定諸々送信側で良いはずなので、テキトーなアドレス宛に「システムからのお知らせです！」みたいなメッセージを送りたい。さあどうする？？ってなって迷走していました。

とりあえずメールサーバー付きのレンタルサーバを契約してシステムメールのアカウントは作ったけど、

「ダミーのメールアドレス宛に送ってもエラーだよなぁ・・・」

って思いながら実行すると当然エラー。

そんな折に見つけたのがFakeSMTPでした。


###使用したツール
FakeSMTP
http://nilhcem.com/FakeSMTP/# からダウンロード。
[ダウンロード](http://nilhcem.com/FakeSMTP/#)

Cドライブ直下に展開して、java -jarで実行。
これでFakeSMTPが立ち上がる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/dfe9f87c-72db-9fc8-e6b8-3291faf59711.png)

###設定

```
ホスト名: localhost
ポート番号: 25
```

ポート番号は「リスニングポート」をいじれば変えられるとは思います（自分はやってませんけど、まあできるでしょうね。）

ロリポップのSMTPサーバの設定だと、管理画面には465と書いてあるけど、587じゃ無いとうまく送信できませんでした。どういうこと？？

TLSとかSSLとかが関係してくるのかもしれませんが、そこまで私はわかりませんm(__)mが、同様のエラーがネットに落ちていてポートをいじればできるとあったので587に変更すれば送信できました。どういう・・・？？

###実装

```java:application.properties
spring.mail.port=25
spring.mail.host=localhost
```

```java:EmailConfig.java
package com.example.home.mail;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import lombok.Data;

@Component
@Data
public class EmailConfig {
	@Value("${spring.mail.host}")
	private String host; // ここにプロパティファイルのホストの値が格納される

	@Value("${spring.mail.port}")
	private String port; // ここにプロパティファイルのポート番号の値が格納される
}
```

```java:MailUtil.java
package com.example.home.mail;

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MailUtil {

	@Autowired
	private EmailConfig emailConfig;

	public void sendEmail(String to) {

		Properties props = new Properties();
		props.setProperty("mail.smtp.host", emailConfig.getHost());
		props.setProperty("mail.smtp.port", emailConfig.getPort());
		Session session = Session.getInstance(props, new javax.mail.Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(emailConfig.getUsername(), emailConfig.getPassword());
			}
		});
		try {
			// Messageオブジェクト作成
			Message msg = new MimeMessage(session);
			// Fromヘッダーフィールドを設定
			msg.setFrom(new InternetAddress(emailConfig.getUsername()));
			msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false));
			// 件名を設定
			msg.setSubject("Javax.Mail test");
			// 送信された日付を取得
			msg.setSentDate(new Date());
			// text/plainのmimeタイプをコンテンツとして設定
			msg.setText("MimeMessageのテストです");

			Transport.send(msg);

		} catch (AddressException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}
}
```

これでsendEmailメソッドをどこかで呼び出せばちゃんとFakeSMTPにログが出力されたので、ダミーアドレス宛に送信を試みているのがわかりました。
JavaScriptで数値を操作する

#本記事の内容
本記事ではJavaScriptを用いて数値に対して手を加えます。
間違い等ある場合、お手数ですがご連絡いただけますと幸いです。

#Math.floor/Math.ceil/Math.round/toFixed/Math.random

####Math.floorは小数点以下を切り捨てるメソッド。
####Math.ceilは小数点以下を切り上げるメソッド。
####Math.roundは四捨五入するメソッド。
####num.toFixedは指定した小数点まで表示するメソッド。


以下で実際に確認していきます。
以下コード
デベロッパーツールにて表示確認
（option + command + I で表示可能。Chromeを使用していることとする。）

```ruby:index.html
const num = 9.333333
console.log(Math.floor(num)); #9と表示される
console.log(Math.ceil(num));  #10と表示される
console.log(Math.round(num)); #9と表示される
console.log(num.toFixed(5)); #9.33333と表示される

```
#Math.randomメソッド
####Math.random()*Xは指定した範囲内で数値をランダムに得るメソッド。
例えばデベロッパーツールにてc`onsole.log(Math.random()*3)`と記述すると、0~2までの範囲で数値をランダムに表示する。では、指定した範囲で整数値を取得するにはどの様にすれば良いのか？
範囲をmin~maxの範囲で整数値を取得するとするならば、以下の式が成り立つ。

```ruby:index.html
Math.floor(Math.random(max+1-min))+min
```
順序立てて考えていく
~範囲~
5(min)~10(max)までの範囲で整数値を取得するとする。

・Math.random(11)で0~10までの数値をランダムに取得する。
・しかし、今回は5~10までの範囲で考えているため、このままでは0~4までの整数値が含まれてしまう。
・一度0~6((10+1)-5)の範囲で整数値を取得し、後からminとなる整数値を足せば良い！
・よって上記に記述した式が成り立つ(ただし、上記の式はMath.floorと記述していることから整数値を求めていることに注意)。

※わかりにくければ、定規の様なものを意識するといいかもしれない。

#最後に
最後までお付き合いいただきありがとうございました。
Flutter 再利用可能なウィジェットを作る方法

#はじめに
Flutterでウィジェットを再利用するには２つのパターンがあります（もっとあったら教えてください:relieved:）

①別のファイルからウィジェットをimportする
②同じファイル内でウィジェットを再利用する

**今回の記事は②のパターンを実現するやり方となります。**

#こんな場面で使える
下記のコードは`SliverAppBar`の部分です。
##SliverAppBarを再利用していないパターン
**`backdropPath`という値がない場合の処理も必要だとすると、`SliverAppBar`のウィジェットを2回もほぼ同じ内容で書くことになります。。。。**


```dart
 // 省略
Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          if (backdropPath != null)
            SliverAppBar(
              expandedHeight: 250,
              flexibleSpace: FlexibleSpaceBar(
                title: Container(
                  decoration: BoxDecoration(color: Colors.black.withOpacity(0.4)),
                  padding: EdgeInsets.symmetric(horizontal: 20, vertical: 2),
                  child: Text(
                    movieTitle,
                  ),
                ),
                background: Image.network(
                  'https://image.tmdb.org/t/p/w780/${backdropPath}',
                  fit: BoxFit.fitHeight,
                ),
              ),
            );
          if (backdropPath == null)
                SliverAppBar(
                  expandedHeight: 250,
                  flexibleSpace: FlexibleSpaceBar(
                    title: Container(
                      decoration: BoxDecoration(color: Colors.black.withOpacity(0.4)),
                      padding: EdgeInsets.symmetric(horizontal: 20, vertical: 2),
                      child: Text(
                        movieTitle,
                      ),
                    ),
                    background: Image.network(
                      'https://image.tmdb.org/t/p/w780/inJjDhCjfhh3RtrJWBmmDqeuSYC.jpg',
                      fit: BoxFit.fitHeight,
                    ),
                  ),
                );
          SliverList(
            delegate: SliverChildListDelegate(
              <Widget>[
          // 省略
```

##SliverAppBarを再利用しているパターン

```dart
// 省略
 return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          if (backdropPath != null)
            buildSliverAppBar(context, title, backdropPath),
          if (backdropPath == null)
            buildSliverAppBar(
                context, title, 'inJjDhCjfhh3RtrJWBmmDqeuSYC.jpg'),
          SliverList(
            delegate: SliverChildListDelegate(
              <Widget>[
// 省略

Widget buildSliverAppBar(
  BuildContext context,
  String movieTitle,
  String backdropPathUrl,
) {
  return SliverAppBar(
    expandedHeight: 250,
    flexibleSpace: FlexibleSpaceBar(
      title: Container(
        decoration: BoxDecoration(color: Colors.black.withOpacity(0.4)),
        padding: EdgeInsets.symmetric(horizontal: 20, vertical: 2),
        child: Text(
          movieTitle,
        ),
      ),
      background: Image.network(
        'https://image.tmdb.org/t/p/w780/${backdropPathUrl}',
        fit: BoxFit.fitHeight,
      ),
    ),
  );
}
```

`buildSliverAppBar`というオリジナルのウィジェット？を作成して、それが`SliverAppBar`になります・

こうすることで、無駄にウィジェットのネストが深くなるのを回避できます:thumbsup:
JavaScriptのメソッドとプロパティ


##Javascriptの基礎知識

**オブジェクトとメソッドとプロパティ**

```
document.write
```
意）画面に表示する（documentオブジェクトにwriteメソッド）

JavaScriptは「.」を使って、
オブジェクトとメソッドを数珠繋ぎのように表記していく


```
document.getElementById('ID名').innerHTML = 'あいうえお';
```
意）ID名のエレメントを取得して、HTMLの内容を　あいうえお　に書き換える

ひとつずつ解説↓

**document.getElementById('ID名')**
documentオブジェクトに.getElementById（IDでエレメントを取得する）メソッド

**getElementById('ID名').innerHTML = 'あいうえお';**　
getElementByIdはエレメントオブジェクトというオブジェクトになり、そこに.innnerHTMLというプロパティを繋いでいる

---
**メソッドとプロパティの考え方**

* 動きを表す　→　メソッド
* 見た目を表す　→　プロパティ

というイメージでとりあえずOK

innerHTMLはHTMLのinner、つまりHTMLの中身（内容）を表すプロパティ


以上
【技術書まとめ】RDBMSを作ろう  WEB+DB PRESS Vol.122 をやったまとめ

ゴールデンウィークに読んでみた

## 第１章

- RDBMSのアーキテクチャ
    1. 構文解析器（クエリをパースする）
    1. クエリプランナ&実行計画（アクセスメソッドの順序などを決める）
    1. ================↓を実装
    1. クエリエクスキュータ（実行計画どおりアクセスメソッドを呼び出す）
    1. アクセスメソッド（ディスクのデータ構造を扱う）
    1. パッファプールマネージャ（データの塊をメモリにキャッシュする）
    1. ディスクマネージャ（データの塊をディスクに読み書きする）

## 第２章

- ディスクマネージャ
    - ヒープファイルからページIDで読み書きする
        - array[1]に似ている
        - ページサイズは大体4,096バイト
            - 必ずページ単位で読み出される
                - HDDやSSDがブロック単位だから
                - Linuxのext4のブロックサイズが4,096バイト
            - ページはブロックとも呼ばれる
- 新しいページを作る
    - ページIDを採番するだけ
        - 採番するたびにページIDのカウンタをインクリメントする


## 第３章

- バッファプールマネージャ
    - ディスクの遅さを隠蔽する
        - ページの内容をメモリにキャッシュする
            - CDNのようなもの
- 内部構造
    - フレーム
        - usage_count
    - バッファ
        - is_dirty page_id
    - ページ
        - data
            - ただの4,096バイトの列
- フレームがたくさん集まってバッファプールになる
- ページテーブル
    - どのバッファにどのページが入っているかわかる
- 実装
    - Clock-sweep
        - 定期巡回して`usage_count`が0のものや、使われてないものを消していく


## 第４章

- B+Tree
    - B-Treeの亜種
    - リーフノード
        - key-valueのペアを持つ
    - 中間ノード
        - 分割キー
            - 5であれば、5以下か以上かで分けられるようになっている
- 検索の流れ
    - 中間ノードを再帰的に二分探索する
        - 分割キーを使う
    - リーフノードに到達したら中を二分探索する


## 第５章

- クラスタードインデックス
    - テーブルすらもB+Treeに入れる手法
        - B+Treeはキー・バリューだがどうするか
            - 行をプライマリキーの列（idなど）とそれ以外の2つに分ける
                - idをキーに、それ以外を全てバリューに入れる
                    - プライマリキーが複合キーの場合は？
                        - ソート可能なエンコーディングを使う
- クエリエクスキュータ
    - 呼び出すたびに1行ずつ返してくれるメソッドがある構造体


## 第６章

- セカンダリインデックスとは
    - 検索しやすい形に変形されたデータ構造
        - フルスキャンを高速化したい
            - 検索しやすい形で書き込むというアイデア
                - 新しいB+Treeのキーにセカンダリキーを入れて、バリューにプライマリキーを入れる
                    - `id: x, first_name: Bob, last_name: Johnson`
                        - B+Treeはキーが`Bob`でバリューが`x`
                            - 値が一意になるとユニークインデックス
                                - `Johnson`を見つけたい
                                    - まずはB+Treeのキーを検索して、見つけたらバリューのプライマリーキーからテーブルを見つける
                                    - 検索を2回することでフルスキャンせずに見つけられる
dockerコンテナ内でGPUが使用できない際のトラブルシューティング

## 概要
dockerコンテナ内でGPUが使用できず、下記のようなエラーが出た。
docker-container-runtimeのエラーのよう。

コンテナでGPUが使用できるか下記コマンドで確認を行なった。
```docker run --gpus all nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04 nvidia-smi```
結果としては、下記のエラー

```
 Error response from daemon: could not select device driver "" with capabilities: [[gpu]].
```

## 解決法
docker-container-runtimeのエラーは下記三つで解決を図る
①/etc/docker/daemon.jsonへの記載
②デーモンの再起動(```sudo systemctl restart docker```)
③docker-container-runtimeの再インストール

しかし、今回の場合は解決できない。

→dockerを再インストールすることで解決できた。

## 参考までに
機械学習では、dockerコンテナ内でjupyterを使ったり、スクリプトを使用したりする。
tensorflowとcudaには互換性があるので、tensorflowのバージョンによってcudaのバージョンを下げたい時等に便利だ。
docker内でGPUを使用する方法を簡単に記載する。
1. dockeを公式を参考にインストール(Qiita等を利用しても良いが、公式のやり方と照らし合わせよう)
2. nvidia-cuda-toolkitを公式からインストール（過去のも出てくる、nvidia-uninstallで削除）
3. cudaのパスを通す(/usr/local/cuda-**.*←削除すれば消える)
※再インストールする時は再起動が必要
4. cudnnファイルをダウンロード（登録必要）
5. 解凍後、/usr/local/cuda以下に移動する(lib64はlib64以下、includeはinclude以下) 
6. nvidia-container-toolkitとnvidia-container-runtimeをインストール
7. docker-composeをインストール(※version3指定はruntimeオプションが使えない)
8. /etc/docker/daemon.jsonを編集
9. dockerの立ち上げ
10. ```nvidia-smi```で確認(cudaは```nvcc -V```)
GCS上のgz圧縮ファイルを解凍する

# 動機
GCS上に存在するcsv.gzファイルをBigQueryにtable形式でインポートしようとしたら、以下のようなエラーが発生。
> Input CSV files are not splittable and at least one of the files is larger than the maximum allowed size.

どうやら4GB以上の圧縮済みCSVファイルは取り込めない様子。

なら解凍すればよくね？　と思うものの、実は gsutilコマンドにはgzファイルの解凍コマンドがない。
当然、コンソール画面でも解凍は不可能。

まさか、わざわざローカルにダウンロードしてきて解凍したうえで再アップロードしろと言うことか？
流石に時間がかかりすぎるし、そもそも巨大なファイルをローカルで展開するのには無理がある......


ということで全部GCP上で完結する方法を調べてみた。




# 解決策
結論、ローカルじゃなくてGCEで仮想マシン使って解凍&アップロードをすればよい。

###Step.1 Google Compute Engine でVMインスタンスを立てる
作成の仕方は公式ドキュメント参照。
基本デフォルトでいい。
https://cloud.google.com/compute/docs/instances/create-start-instance?hl=ja

インスタンスを作成したらSSHをクリックして起動する。
起動時間に応じて課金が発生するので注意。
（デフォルトだと e2-medium, 2vCPU, メモリ4GBで $0.03351/hour）
https://cloud.google.com/compute/vm-instance-pricing?hl=ja


###Step2. アカウント認証
デフォルトのサービスアカウントでは権限が足りずコピーできない場合があるので、自分のアカウントでログインする。

`gcloud init`と入力し、あとは案内に沿って自分のアカウントを認証。


###Step.3 ファイル解凍
ファイルのコピー → 解凍 → アップロードを一括で行う。

~~~
gsutil cp gs://入力バケット名/入力ファイル名.csv.gz - | gunzip | gsutil cp - gs://出力バケット名/出力ファイル名.csv
~~~
4GBギリギリオーバーのファイルでも数分かかる。


###Step4. インスタンスを終了する
お金がかかるので忘れずに。
この後はBigQueryに取り込むなりなんなりお好みで。
Androidのインストール

## はじめに  
Windows10におけるAndroid開発の導入についてまとめる  

## 導入の流れ
1. Android Studioのダウンロード
    [サイト](https://developer.android.com/studio)に移動して`DOWNLOAD ANDROID STUDIO`を選択  
    ![2021-04-13-14-57-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/e99f577c-d376-43a5-d9d5-77e3baebcd41.png)

1. インストール  
    1. ダウンロードしたファイルを実行  
        ![2021-04-13-16-04-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/74ccf17c-f780-852c-9966-d7b68c84e86f.png)

    1. Nextを選択  

       ![2021-04-13-16-05-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/a3440190-bb30-ca75-8b89-fdf95c48950e.png)


    1. インストールするコンポーネントを選択  
        実機を使用するため、AVDを使用する想定はしていないが使用することができるように選択しておく  

       ![2021-04-13-16-05-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/d90103cf-5a51-5773-b369-beae97374a51.png)


    1. インストール先のパスを選択  
        任意のパスを選択する  

       ![2021-04-13-16-06-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/89fe1a9e-3e8a-97eb-183c-e6a41df5bd01.png)


    1. スタートメニューの選択  

       ![2021-04-13-16-06-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/f3e7fa0d-a528-8e7e-8205-84bf8fb52bb9.png)

    
    1. 完了ボタンの選択  

       ![2021-04-13-16-07-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/3ed312be-22b3-709a-f001-93504f833408.png)


1. Android Studioの初回起動時の設定  
    1. 設定のインポート  
    
        ![2021-04-13-16-08-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/a9537371-1f22-3577-19f2-6369cd452918.png)


    1. Googleへのデータ共有設定  

        ![2021-04-13-16-09-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/e8713165-081b-c22a-2077-5015ea3ae3e4.png)


    1. Nextを選択  
        
        ![2021-04-13-16-10-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/5d36ba1d-2ac1-2817-4356-f36e3153f4e8.png)


    1. インストールするコンポーネントなどの設定  
        一般的な環境で開発できればよいのでスタンダードを選択  

        ![2021-04-13-16-10-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/a700bf63-cae7-c252-a78f-e74afd9262c4.png)

    
    1. UIテーマを選択  
        個人的には黒が好き  

        ![2021-04-13-16-10-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/221dac94-7c0d-b5c0-528e-0ce6a7e4ff70.png)


    1. 設定の確認  
        誤りがあれば修正  

        ![2021-04-13-16-11-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/900c7ac7-f69e-bfdd-93a1-ef82fc2d2275.png)
【RSpec】モデル単体テスト実行時の「MissingAttributeError」を解決する

# はじめに
RSpecを用いたテスト時のエラーでつまずいたので、備忘録としてまとめます。

# 環境
Ruby 2.6.5
Rails 6.0.3.6

# 状況
Twitterのような投稿アプリを作成中です。FactoryBotを用いて、投稿に関するPostモデルの単体テストを実行したところ、「MissingAttributeError」が出ました。以下に詳細を記します。

## FactoryBot

```ruby:posts.rb
FactoryBot.define do
  factory :post do
    # 省略
    association :user 
　　 # 省略
  end
end
```

association :userは、users.rbのFactoryBotとアソシエーションがあることを意味しています。つまり、Postのインスタンスが生成したと同時に、関連するUserのインスタンスも生成されます。

## exampleを書き出し、試しにテストを実行するとエラー発生

```ターミナル
ActiveModel::MissingAttributeError:
       can't write unknown attribute `user_id`
```

「user_idという属性は知らないよ」という内容です。

## postsテーブルを確認
テーブルのカラムを確認していくと、user_idカラムがありませんでした。
![スクリーンショット 2021-05-02 19.55.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402996/28c7e22f-a7b6-52e7-95a1-4542fd0e2774.png)

## マイグレーションファイルを確認
t.references :user の記述を忘れており、テーブル作成時にuser_idカラムが作られなかったことがわかりました。

## user_idカラムを追加し、エラー解決
カラムの追加方法は、他の方の分かりやすい記事がありますので、ご参考ください。
私はこちらを参考にさせていただきました。
https://qiita.com/kurawo___D/items/e3694f7a870a1cc4738e

![スクリーンショット 2021-05-02 19.57.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402996/e73b2151-c3f6-3d2b-4538-77f7fbb1b041.png)


## まとめ
postはuserに紐付いているため、FactoryBotでassociation :userと記述し、紐付くuserデータを同時生成しようとしました。
しかし、postテーブルにuser_idカラムがなかったため、紐付かせることができず、エラーが出てしましました。

## 最後に
初めての投稿で分かりづらい部分が多々あるかと思いますが、どなたかの参考になれば幸いです。
ホストネームからIPアドレス(ipv4)を取得する方法

#はじめに
アプリ開発をしている際に、サーバーとのネットワークを接続状態をチェックする必要がありましたが、サーバー名(ホストネーム)からIPアドレスを取得しなければいけませんでした。
マイクロソフトのドキュメントに[Dns.GetHostEntry メソッド](https://docs.microsoft.com/ja-jp/dotnet/api/system.net.dns.gethostentry?view=net-5.0)がありそれを参考に作成しました。
そこにこんなサンプルがありました。

```C#
// ホストネームからアドレスを取得する
public static void DoGetHostEntry(string hostname)
{
    IPHostEntry host = Dns.GetHostEntry(hostname);

    Console.WriteLine($"GetHostEntry({hostname}) returns:");

    foreach (IPAddress address in host.AddressList)
    {
        Console.WriteLine($"    {address}");
    }
}
```

#問題点
このサンプルだと、ホストネームからアドレスを取得した際に、ipv6とipv4の両方を取得してしまいました。
自分が作成していたアプリでは、取得したアドレスをもとにpingでネットワークを確認するようにしていましたが、ipv6は時間がかかり、パフォーマンスに問題が起きてしまいました。

```C#
/// <summary>
/// 指定されたIPアドレスのPingを確認する
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
private bool CheckPing(object arg)
{
    Ping pingSender = new Ping();
    PingOptions options = new PingOptions();

    // Use the default Ttl value which is 128,
    // but change the fragmentation behavior.
    options.DontFragment = true;

    // Create a buffer of 32 bytes of data to be transmitted.
    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    byte[] buffer = Encoding.ASCII.GetBytes(data);
    int timeout = 25;
    PingReply reply = pingSender.Send(arg.ToString(), timeout, buffer, options);
    if (reply.Status == IPStatus.Success)
    {
        return true;
    }
    return false;
}
```

#解決方法
サンプルで取得できたhost.AddressListのうち、どれがipv4か確認する方法がわかればいいです。
調べると[IPAddress.AddressFamily プロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.net.ipaddress.addressfamily?view=net-5.0#System_Net_IPAddress_AddressFamily)というものがありました。それを見ると、「IPv4 の場合は InterNetwork、IPv6 の場合は InterNetworkV6 を返します」とありました。
これを参考にして以下のようにサンプルを書き換えました。

```C#
private IPAddress DoGetHostEntry(string hostname)
{
    IPHostEntry host = Dns.GetHostEntry(hostname);

    foreach (IPAddress address in host.AddressList)
    {
        if (address.AddressFamily == AddressFamily.InterNetwork)
            return address;
    }

    return null;
}
```

これで問題なくipv4のアドレスを取得して、ping確認することができるようになりました。
ROS2(Foxy)でYD-LiDARを動かす(Jetson AGX Xavier)

Jetson AGX Xavierを用いて、ROS2(Foxy)でYD-LiDARを動かした時のメモ

![ydlidar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/b245f2cf-c05e-c1c1-a65d-c54697f701ca.png)


## YDLidar-SDKのインストール

```
cd ~/
git clone https://github.com/YDLIDAR/YDLidar-SDK
cd YDLidar-SDK
mkdir build
cd build
cmake ..
make
sudo make install
```

## YDLiDAR ROS2のインストール

```
cd ~/ros_ws/src
git clone https://github.com/YDLIDAR/ydlidar_ros2_driver
```

`~/ros_ws/src/ydlidar_ros2_driver/params/`から、使用する機種のyamlを`~/ros_ws/src/ydlidar_ros2_driver/params/ydlidar.yaml`にコピー。接続しているUSBポートを修正。`frame_id`の`laser_frame`を`base_scan`に修正。

```
ydlidar_ros2_driver_node:
  ros__parameters:
    port: /dev/ttyUSB0
    frame_id: base_scan
    ignore_array: ""
    baudrate: 128000
    lidar_type: 1
    device_type: 0
    sample_rate: 5
    abnormal_check_count: 4
    resolution_fixed: true
    reversion: true
    inverted: true
    auto_reconnect: true
    isSingleChannel: false
    intensity: false
    support_motor_dtr: true
    angle_max: 180.0
    angle_min: -180.0
    range_max: 64.0
    range_min: 0.01
    frequency: 10.0
    invalid_range_is_inf: false
```

```
cd ~/ros_ws/
colcon build --symlink-install --base-paths src/ydlidar_ros2_driver
source install/setup.bash
```
## ROS2 Nav2連携(Turtlebot3側)

標準LiDARの記述をLaunchファイルでコメントアウト。

robot.launch.py

```
...
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource(
                [ThisLaunchFileDir(), '/turtlebot3_state_publisher.launch.py']),
            launch_arguments={'use_sim_time': use_sim_time}.items(),
        ),

        #IncludeLaunchDescription(
        #    PythonLaunchDescriptionSource([lidar_pkg_dir, '/hlds_laser.launch.py']),
        #    launch_arguments={'port': '/dev/ttyUSB0', 'frame_id': 'base_scan'}.items(),
        #),

        Node(
            package='turtlebot3_node',
            executable='turtlebot3_ros',
            parameters=[tb3_param_dir],
            arguments=['-i', usb_port],
            output='screen'),
    ])
...
```

```
ros2 launch turtlebot3_bringup robot.launch.py
ros2 launch ydlidar_ros2_driver ydlidar_launch.py
```
LeetCodeWeekly 239C 1850. Minimum Adjacent Swaps to Reach the Kth Smallest Number next_permutaion と 隣接swapする回数


https://leetcode.com/contest/weekly-contest-239/problems/minimum-adjacent-swaps-to-reach-the-kth-smallest-number/

# 題意
- 最大1000桁のある数値$num$が与えられる。いま、この数を並び替えて作れる数字を考えたときに、$num$よりも厳密に大きい数字のみを考える。
- このような$k$番目を考えると、$num$の<b>隣接した数字を</b>最小で何回入れ替えればいいか。

# こう考えた

この問題は2つのステップに分かれる。

- STEP1: $k$個大きな数字を求める。これを$target$とする
- STEP2: $num$の隣接数字を何回入れ替えると$target$にできるかを判定する

## STEP1 1つ目に大きな数値

C++ならnext_permutationを使う。next_permutaionはhttps://cpprefjp.github.io/reference/algorithm/next_permutation.html 
にある。通常は、ソートした配列からスタートして、<b>辞書順に</b>すべての順列を得ることに使われる。ここで、next_permutationは毎回、配列を並び替える。つまり、${1,2,3}$を与えると、配列が${1,3,2}$に並び替えられる。この性質を使い、$nums$を配列として$k$回next_permutaionに渡すことで、$target$を求められる。

## STEP2 隣接した要素を並び替える回数

$num$が高々1000桁なので愚直にシミュレーションする。STEP1で元の$nums$は並び替えられてしまうので、これを保持してき、$ind=i$の文字が次に出現する位置$j$を探索して、位置$i$まで実際にswapすればよい。

# 実装

```C++
class Solution {
public:
    int getMinSwaps(string num, int k) {
        int sl = num.size();
        int res = 0, j;
        vector<int> dat(sl), odat(sl);
        REP(i, sl) odat.at(i) = num[i] - 0x30;
        REP(i, sl) dat.at(i) = num[i] - 0x30;
        REP(i, k) next_permutation(dat.begin(), dat.end()); // k個先を探索する
        REP(i, sl){ // すべての文字をチェック
            if(dat[i] == odat[i]) continue; // 入れ替える必要がない
            j = i + 1;
            while(dat[j] != odat[i]) j++; // 文字がある場所jを探す
            while(j > i) { // swapをシミュレーション
                swap(dat[j-1], dat[j]);
                --j;
                ++res;
            }
        }
        return res;
    }
};
```
https://leetcode.com/contest/weekly-contest-239/submissions/detail/487698395/
React hook 一覧①

Reactのフックについて説明していきます。

Hookとは接続という意味です。

①useState
更新の時に使う。
例えば、ボタンを押す度に数字が+１になるときなどは、
ボタンを押すたびに更新をしなきゃなりません。
このような更新をする時に使います。

```react
const [state, setState] = useState()
```

②useEffect
第二引数の依存している値が変更される度に第一引数が実行される。
この他にも使い方はありますが今回は理解できるように細かい使い方は割愛しています。

```react
const hookFunction = () => {

  const [count, setCount] = useState(0)

  useEffect(
     () => {
        console.log(count);
     },
     [count]
   );

return(
    <div>
       <p>{count}</p>
       <button onClick={() => setCount(count + 1)}>プラス１する</button>
    </div>
);
}
```

③useContext
これを使うにはまずは下記のように入力する必要があります。

```react
export const UserCount = React.createContext()
```
これを親コンポーネントで使用したら、valueをいれることができて、そのvalueを子のコンポーネントでも使えるようになります。

```react
const value = useContext(MyContext);
```
下記の記事が非常にわかりやすいです

https://reffect.co.jp/react/react-usecontext-understanding

④useReducer
useStateの代替品です。
useStateを使う時はシンプルなロジックで更新をしたいときに使います。
useReducerはロジックが複数あり複雑だったり、複数のロジックを分かり易くしたいときに使います。ボタンを押したら初期値に戻るなどのアクションをするときも便利です。
公式サイトがわかりやすいです。

https://ja.reactjs.org/docs/hooks-reference.html#usestate
Jetson AGX Xavier上でPointCloud2のデータを生成してRviz2に表示


Jetson AGX Xavier上でPointCloud2のデータを生成してRVIz2に表示するためのメモ

![picture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/45ba30b1-a478-cdce-1a6f-0684ba8b4a7b.png)


## CmakeのUpdate

Open3DのBuildにCMake 3.18以降が必要なので、CMake 3.19.5をインストール。

```
sudo apt -y remove cmake
wget https://github.com/Kitware/CMake/releases/download/v3.19.5/cmake-3.19.5.tar.gz
tar xvf cmake-3.19.5.tar.gz
cd  cmake-3.19.5
./bootstrap && make -j6 && sudo make install
```

## Open3DのBuildに必要なパッケージをインストール 

```
sudo apt install python3-colcon-common-extensions
sudo apt-get install -y libsdl2-dev libc++-7-dev libc++abi-7-dev libxi-dev
sudo apt-get install -y clang-7
```

## Open3DをBuild

```
git clone --recursive https://github.com/intel-isl/Open3D
cd Open3D
git submodule update --init --recursive
mkdir build
cd build
```

```
cmake \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_SHARED_LIBS=ON \
    -DBUILD_CUDA_MODULE=ON \
    -DBUILD_GUI=ON \
    -DBUILD_TENSORFLOW_OPS=OFF \
    -DBUILD_PYTORCH_OPS=OFF \
    -DBUILD_UNIT_TESTS=ON \
    -DCMAKE_INSTALL_PREFIX=~/open3d_install \
    -DPYTHON_EXECUTABLE=/usr/bin/python3 \
    ..
```

このままBuildするとエラーがでるので、`Open3D/cpp/open3d/core/linalg/BlasWrapper.h` を修正。 `#include "/usr/include/aarch64-linux-gnu/cblas-netlib.h"
`を追加。

>Open3D/cpp/open3d/core/linalg/BlasWrapper.h

```
#pragma once

#include "/usr/include/aarch64-linux-gnu/cblas-netlib.h"
#include "open3d/core/linalg/LinalgHeadersCPU.h"
#include "open3d/core/linalg/LinalgHeadersCUDA.h"
#include "open3d/utility/Console.h"
```

```
make -j6 & sudo make install-pip-package
```

```
ls /home/jetson/Open3D/build/lib/python_package/pip_package/
```
```
total 25268
  759703     4 ./
  758262     4 ../
19136964 25260 open3d-0.12.0+3ca4d62c0-cp36-cp36m-linux_aarch64.whl
```

```
sudo pip3 install /home/jetson/Open3D/build/lib/python_package/pip_package/open3d-0.12.0+3ca4d62c0-cp36-cp36m-linux_aarch64.whl 
```

## ROS2-Point-Cloud-DemoをBuild

ROS2-Point-Cloud-Demoでply形式のファイルからPointCloud2Dのデータを生成

```
cd ~/ros_ws/src/
git clone https://github.com/SebastianGrans/ROS2-Point-Cloud-Demo
cd ~/ros_ws/
colcon build --symlink-install --packages-select pcd_demo
source install/setup.bash
```

## 実行

RVIz2を起動

```
ros2 run rviz2 rviz2
```

ply形式のデータからPointCloud2D形式のデータを生成。

```
ros2 run pcd_demo pcd_publisher_node ~/ros_ws/src/ROS2-Point-Cloud-Demo/resource/teapot.ply    
```

## Rviz2でPointCloud2形式のデータを表示

![pd00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/128ba700-79aa-9ebc-3e3e-f995c256e649.png)

![pd2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/3422430f-beea-5f72-cc06-80e6516371ad.png)

![pd02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/ae3743a7-0da3-b8e8-892d-7f4a453d3be7.png)


![picture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/45ba30b1-a478-cdce-1a6f-0684ba8b4a7b.png)
RailsのJSで.envファイルに書いた環境変数を呼び出す方法

#手順

① gem 'dotenv'をDL(dotenv-railsでも可。どっちか)
② `config/webpack/environments.jsにdotenv呼び出すロジックを追記
③ .envファイルに呼び出したい環境変数を設置
④ JSで環境変数を呼び出す


#大前提

・Railsに限らず、.envファイルで設定した環境変数をJSで呼び出すには、webpackとの連携が必要になるみたいです。
Vue.jsでも、なんでも。


・API連携などで、連携の為に発行されるIDなどを、.envファイルに記述し、dotenvで管理する、という手法もRailsに限らずの話です。
わからない方は調べてみてください。

#やり方

###STEP1 Gemfileに`gem 'dotenv'`を追記

###STEP2 `config/webpack/environments.js`を以下のように編集

```config/webpack/environments.js

const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
const dotenv = require('dotenv')

const dotenvFiles = [
  '.env'
]
dotenvFiles.forEach((dotenvFile) => {
  dotenv.config({ path: dotenvFile, silent: true })
})

environment.plugins.prepend('Environment',
  new webpack.EnvironmentPlugin(
    JSON.parse(JSON.stringify(process.env))
  )
)

module.exports = environment
```
###STEP3 .envに環境変数を設定

```.env.
NANTKA_ID = xxxxxxxx
```

###STEP4 

```example.js

process.env.NANTKA_ID

```
②CUDA-PCL評価用のROS2(Foxy) Realsense Nodeの構築

CUDA-PCL評価用にJetson AGX Xavierを使用し、ROS2(Foxy)でRealsense L515, D435等を動かすための構築です。(RealsenseのROS2 Foxy nodeとlibrealsenseでバージョンの不一致は常に発生するので要注意。2022年6月16日時点で動作確認)

## 事前作業

https://qiita.com/akira-sasaki/items/58ac9f5915a557882d4f

## realsense_rosとLibRealSense2バージョン表対応表

|Realsense_rosのBrach| 必要なLibRealsense2のバージョン|
|:--|:--|
|develop | v2.45.0以降 |
|foxy| v2.42.0以降 |
|ros2| v2.43.0以降 |

[Intel Official](https://dev.intelrealsense.com/docs/nvidia-jetson-tx2-installation)の方法で、構築するとlibrealsense v2.41.0がインストールされてしまうので、ROS2 Foxyで動かすためにはlibrealsense2は、自前でBuildをおこなう。

## librealsense2のインストール

```
git clone https://github.com/IntelRealSense/librealsense/
cd librealsense
./scripts/setup_udev_rules.sh
mkdir build && cd build
cmake ../
sudo make uninstall && make clean && make && sudo make install
```

## 動作確認

realsense-viewerを動かし、動作確認する。

Dockerに直接ログインしている場合　

```
realsense-viewer
```

DockerにSSH経由でログインしている場合　

```
export DISPLAY=:0
realsense-viewer
```



## realsense-rosのインストール

```
cd ~/data/ros2_ws/src
git clone -b foxy https://github.com/IntelRealSense/realsense-ros
```

```
cd ~/data/ros2_ws/
colcon build --base-paths src/realsense-ros
source install/setup.bash
```

## rviz2の起動

2つTerminalを起動するか、&をつけて起動し、使い終わったらプロセスをkillする。

```
rviz2 &
```

## realsense2_camera Nodeの起動

```
ros2 launch realsense2_camera rs_launch.py filters:=pointcloud
```

## rviz2の設定

![lidar1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/9a4d3d01-78ff-5b48-849c-4a4ea8f3e669.png)

![lidar3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/def02bfa-aaba-840b-cbc8-02d00b4e984d.png)

![lidar4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63450/fe8c052d-3c32-dea4-ff8b-6ec68ef15d12.png)
PointCloud2 フォーマットに対応しているLiDAR, Depth Camera

# PointCloud2 フォーマットに対応しているLiDAR, Depth Camera

ROS2 FoxyでPointCloud2 フォーマットで値を取得できるLiDAR, Depth Cameraメモ。

## Realsense

|ハードウェア|Topic名|Format|Github|
|--|--|--|--|
| D400シリーズ | /camera/aligned_depth_to_color/color/points|[PointCloud2](https://github.com/ros2/common_interfaces/blob/master/sensor_msgs/msg/PointCloud2.msg) |https://github.com/IntelRealSense/realsense-ros|
| L515シリーズ | /camera/aligned_depth_to_color/color/points|[PointCloud2](https://github.com/ros2/common_interfaces/blob/master/sensor_msgs/msg/PointCloud2.msg) |https://github.com/IntelRealSense/realsense-ros|

```
ros2 launch realsense2_camera rs_launch.py filters:=pointcloud
```

## Azure Kinect DK

|ハードウェア|Topic名|Format|Github|
|--|--|--|--|
| Azure Kinect DK | |[PointCloud2](https://github.com/ros2/common_interfaces/blob/master/sensor_msgs/msg/PointCloud2.msg) |https://github.com/microsoft/Azure_Kinect_ROS_Driver|


## Velodyne 

|ハードウェア|Topic名|Format|Github|
|--|--|--|--|
| VLP16 | /velodyne_points |[PointCloud2](https://github.com/ros2/common_interfaces/blob/master/sensor_msgs/msg/PointCloud2.msg) |https://github.com/ros-drivers/velodyne|

VLP-16の固定IPを10.0.0.2に変更

```
git clone -b ros2 https://github.com/ros-drivers/velodyne
```

```
ros2 run velodyne_driver velodyne_driver_node
ros2 launch velodyne_pointcloud velodyne_convert_node-VLP16-launch.py
```


## LIVOX

|ハードウェア|Topic名|Format|Github|
|--|--|--|--|
| AVIA | /livox/lidar |[PointCloud2](https://github.com/ros2/common_interfaces/blob/master/sensor_msgs/msg/PointCloud2.msg) |https://github.com/Livox-SDK/livox_ros2_driver|
Amazon Linux 2 AMI 　OpenSSL1.1.1kソースからビルドしてインストールする

linux初心者の為、勉強の為にソースからビルドしてインストールしてみました。

#参考記事
https://qiita.com/DQNEO/items/3613cc1d87c01121a9e2
https://qiita.com/knutpb1205/items/24326ff0e7b886354898

#環境
Amazon Linux 2 AMI
OpenSSL1.1.1k
（最新バージョン確認　https://www.openssl.org/）
/opt/openssl/ にopensslをインストールする

#手順

コンパイルとビルドに必要なパッケージをインストール

```
# yum install -y gcc make
# yum install perl zlib-devel
```

OpenSSLのソースをビルドしてインストール

```
URLを指定してファイルをダウンロード
# wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz

解凍して展開
# tar xvfz openssl-1.1.1k.tar.gz

openssl-1.1.1kディレクトリに移動
# cd openssl-1.1.1k/

/opt/opensslディレクトリにインストール、シェアードライブラリとしてビルド、zlib使用
# ./config --prefix=/opt/openssl shared zlib

ビルド
# make

インストール
# make install
```

ちゃんと出来たか、バージョン確認してみる

```
# /opt/openssl/bin/openssl version
```

エラーが出るｗ

```
/opt/openssl/bin/openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
```

#対策
まず「libssl.so.1.1」があるか確認

```
find -name "libssl.so.1.1"
./home/ec2-user/openssl-1.1.1k/libssl.so.1.1
./opt/openssl/lib/libssl.so.1
```

/opt/openssl/lib/にちゃんといてくれたので、以下を実行
★(2021/5/5追記)/etc/ld.so.conf.d/lib64.confに/opt/openssl/lib/のパスを記述し、OSにldconfigで情報を伝える

```
echo "/opt/openssl/lib/" > /etc/ld.so.conf.d/lib64.conf
ldconfig
```

★(2021/5/5追記)/etc/ld.so.conf.d/のlib64.confに「/opt/openssl/lib/」のパスが記述されたか確認

```
cd /etc/ld.so.conf.d/
cat lib64.conf
/opt/openssl/lib/
```
今度こそ！バージョン確認

```
/opt/openssl/bin/openssl version
OpenSSL 1.1.1k  25 Mar 2021
```

♡できたみたい♡

libsslが/opt/openssl/lib/libssl.so.1.1にあるものとリンクしている
libcryptが/opt/openssl/lib/libcrypto.so.1.1にあるものとリンクしている
libzがリンクしていることを確認


```
ldd /opt/openssl/bin/openssl
        linux-vdso.so.1 (0x00007ffec31cb000)
        libssl.so.1.1 => /opt/openssl/lib/libssl.so.1.1 (0x00007f6f2f1c7000)
        libcrypto.so.1.1 => /opt/openssl/lib/libcrypto.so.1.1 (0x00007f6f2ece7000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f6f2ead2000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f6f2e8ce000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6f2e6b0000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f6f2e305000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f6f2f456000)
```


できてるみたい
【随時更新】作りたいものが無ければ見てほしい！個人開発のアイデアをさらしていく

# アプリのβ版完成

＼β版ユーザー募集！／

https://www.ideee.tech/about?utm_source=qiita&utm_medium=article&utm_id=demo_idea_post

```
こちらのアイデアはアプリに移行しました🙇‍♂️
```



## 個人開発のアイデアを晒していく(コメントお待ちしております😇)

### ターゲット🎯
- 個人開発を通してもっと成長していきたいエンジニア
- 自分の身の回りを見回してもアイデアが浮かばない人
- 少しでもソーシャルグッドなアプリをつくり、多くの人に見てもらいたい人

### 実現したい状態
```
マネタイズはできないけどあったらいいなを作る
個人開発をやってる人は多いのに社会にとって活用されて無いのがもったいない
```
世の中（私の周り）にはエンジニアでレベルの個人開発をやろうとしているが
アイデアが無くて手を止めているエンジニアがたくさんいます！
はたまた、世の中（私の周り）にはこんなサービスがあったら良いのにな〜
と考えながら作れないという障壁で手を止めている人がたくさんいます。。

**MOTTAINAI**

そこで
ソーシャルグッドなサービスを集めて
カッコいいエンジニアが多いQiitaでアイデアを晒しています！

ソーシャルグッド:
地球環境や地域コミュニティなどの「社会」に対して良いインパクトを与える活動や製品、サービスの総称
なんだかスゴイいことを言っているが
面白そうと思ったアイデアは全てあげていく💡

### 実現しやすいアイデアの例🚀
- 日頃あったら良いなと妄想すること
- ニッチな業界の無駄を無くすサービス
- マッチング関連

例） 一風変わった趣味のマッチングアプリなど

### 実現しにくいアイデアの例🤢
- 物作りが必要なもの（ソフトエンジニア想定なので）
- 莫大な資金がかかるもの
- AIやブロックチェーンなどの労力がかかりすぎるもの

### お願い🙏
- アイデア・開発も全てボランティアでの想定です
    - 権限などの問題は無いように気をつけてください
- アイデアを参考にしたいときにはコメントください
 - こちらでも後押しするためシェア致します
- アイデアを思いついた人と繋がりたい時はコメントかTwitterでご連絡ください！
 - 彼らもアイデアを形作ってくれる人に興味があります
- 逆にアイデアがあればコメント or Twitterでメッセください！
- 「もう他のサービスであるくない？」など、ご意見もお待ちしております！

## アイデアの出し方もさらしています🔥
https://qiita.com/naruqiita/items/65d3560e3bf8a88e80ac

誰でもアイデアを出せるように
方法をまとめましたのでぜひチェックください👀

## 世の中に欲しいものを晒していく

**フォーマット**

```
世の中にある需要

BG = 'バックグラウンド'

補足：（あれば）

サービスを一言で
```

## 過去アイデア例

### 動画コンテンツの媒体が増えているので管理がしたい

BG:
NetflixとかU-NEXT、AmazonPrimeなど
どこで視聴ができるかを探すときに
全て一々サイトに飛んで探さないといけない
それを一つのサイトでできるようにしたい

**類似のサービスあり!**
@1129-tame さんのコメントにより
[Filmarks](https://filmarks.com)にて、映画がどの見放題サービスで視聴できるかがわかるようです！🙇‍♂️

```
動画視聴サイトを横断した掲示板サイト
```


### 仮想通貨で大きな失敗をしたくない

BG：
仮想通貨の練習サイトは現在ある
けども英語のサイトでわかりにくさが残っている
日本語で日本に特化した機能が備わったものが欲しい

現在はたくさんありそう
https://jp.cointelegraph.com/news/demo-trading-of-bitcoin

```
仮想通貨の練習のサイト
```


# アプリのβ版完成

＼β版ユーザー募集！／

https://www.ideee.tech/about?utm_source=qiita&utm_medium=article&utm_id=demo_idea_post

```
こちらのアイデアはアプリに移行しました🙇‍♂️
```


## 自己紹介

なる
https://twitter.com/1026NT
- 個人開発好き
- 自分でサービスを作りたいからエンジニアになった
- サービス開発やスタートアップにも興味あり

個人開発で発信中！フォローください！👏

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/3db40e7d-3213-be1f-8650-c6ad5dff69c9.jpeg" width="300px">