OmniAICreator/Qiita-1.07M huggingface dataset:
時刻グリッドコードの構想

# 直面している問題
計算機関係で時刻を扱う場合に、ISO 8601 (W3CDTF)　で表記を統一したとしても、把握が難しいです。

# 考えている解決策
タイルの知見を活用し、**時刻を扱いやすい粒に離散化する**時刻グリッドコードを構想しています。

英語名は、Temporal Grid Code にしてみます。

# 具体的なアイディア
UNIX Time の総秒を 1800 秒で割って、商と余りに分けます。基本的には商を使って、時刻あるいは時間の経過を簡単に把握します。仮用語として次のとおり定義しておきましょう。

- 時刻グリッド上位コード： UNIX 秒を 1800 で割った商
- 時刻グリッド下位コード： UNIX 秒を 1800 で割った余り

1800 秒は30分であり1ポモドーロであって、人間の感覚に近いです。また、上位の単位である時間、日、週、月、年等の境目からずれることがありません。

MGRS の用法をヒントにすれば、商部分の下4桁でも使えば、おおむね通常の処理範囲での時刻表現としては十分でしょう。

## Ruby 実装

- 時刻グリッド上位コード： `Time.now.to_i / 1800`
- 時刻グリッド下位コード： `Time.now.to_i % 1800`

## 数値例

- 時刻グリッド上位コード： 905999
- 時刻グリッド下位コード： 1672
- 時刻グリッドコード: 905999/1672
- 時刻をざっくり理解するための表現 「時刻 5999」 （時刻グリッド上位コード下4桁）

# モチベーション
国連ベクトルタイルツールキットを用いたベクトルタイル生産では、時刻との付き合いがあります。時刻についてより線形に把握をし、生産時間をより推定しやすくしたいと思っています。

# See also
- [モデュロール](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%87%E3%83%A5%E3%83%AD%E3%83%BC%E3%83%AB)

# タグライン
> What time *in two numbers* is it now?

# 特徴
- 時刻グリッド上位コードが偶数なら0分はじまり、奇数なら30分はじまりです。
- タイムゾーン独立です。時刻グリッドコード 5999 であれば、世界中で 5999 です。時刻グリッドコードは日付が埋もれてわかりにくいという特徴がありましたが、その裏でタイムゾーン独立という特徴を手に入れた感じです。
- 四桁の時刻グリッドコード（時刻グリッド上位コード下4桁)を使った場合に、同じコードに回帰してくる日数は208 + 1/3日です。ちなみに金星の公転周期は225日なのだそうです。

# 実装
https://hfu.github.io/tgc/ で実装してみました。
vimの操作について

#vimについて
ファイル→テキストファイルとバイナリファイルに分類される
テキストファイルを編集するためのアプリ→エディタ
Linuxでのエディタ→vim

vimが使えると
テキスト編集の効率が上がり、 Linux内での作業効率の上昇

##vimのモード
###モードの種類
vimには複数のモードが存在し、それらを使い分けることで編集を行う
**よく使われるモード**
ノーマルモード:vimのコマンドの実行を行う
インサートモード:文字の入力を行う
ビジュアルモード:範囲を選択して、その範囲に対してなにか操作を行う

###モードの変更方法
i,a,Kなど　ノーマル→インサートに移る
ctrl＋v ビジュアルモードに移る
インサートモードの場合```--insert--```という表示が出る


ノーマルモード移る方法→esc



##vimのコマンド
###終了と保存
:q 終了
:w 上書き保存
:w＜ファイル名＞　名前をつけて保存
:q! 強制終了

###カーソルの移動
h 左
j 下
k 上
l 右

この４つは横並びになっている
→少ない動作で移動できるようにしたいから


###文字の追加・削除
x カーソル位置の文字の削除
i カーソル位置に文字を追加
a カーソル右に文字を追加

i,aにより文字を追加する際→インサートモードになる（文字を編集するモード）
escにより通常モードに戻る

###単語単位での移動
w 前から後ろへ単語一つ分移動
b 後ろから前へ単語一つ分移動
W スペース区切りでwの移動を行う
B スペース区切りでbの移動を行う

###行の頭、末端への移動
０　行の頭へ移動
＄　行の末へ移動

###指定の行への移動
gg 最初の行に移動（１行目）
G　最後の行に移動
数字(n)＋G n行目に移動


###デリート、ヤンク、プット（削除、コピー、ペースト）
他の用語ではコピー、ペーストの作業はそのままそう呼ばれるが、
Linuxではコピーはヤンク(yank)、ペーストはプット(put)と呼ばれる
d　削除
y　コピー
p　ペースト(putの頭文字をとったもの）

####デリートの種類
dと他のコマンドを組み合わせることで様々な削除を行うことができる。
d$　行末
d0　行頭
x,dl　一文字削除
dw 単語一つ削除
dgg カーソル位置から最初の行まで削除
dG カーソル位置から最後の行まで削除

また、dの部分をyに置き換えることで同じような操作を行うことができる。

####プット
デリート(削除)したもの、ヤンク(コピー)したものはプットすることでペーストすることができる
p プット(コピーしたものを貼り付ける)

###元に戻す
u 入力した後の編集を取り消して元に戻す
u→アンドゥ(undo)という機能の略

Ctrl＋r アンドゥ(undo)の取り消し
###行間を埋める
J 行間を埋める

```
hogehogehoge
fugafugafuga
```

ここにJを記入すると

```
hogehogehogefugafugafuga
```
となる

###検索
ファイル内の文字列を検索したいときに使用される
/＋文字列　文字列の検索（カーソル位置から下に向かって）
?＋文字列　文字列の検索（カーソル位置から下に向かって）


###置換
ある文字列を別の文字列に置き換えたいときは
%s/＜置換したい部分の文字列＞/＜新しく置換したい文字列＞/g
とする

```
hoge hoge hoge
```
これに対してこのようなコマンドを打つと

```
$%s/hoge/fuga/g
```
このようなコマンドを打つと

```
fuga fuga guga
```
このような結果となる

###行の数字を確認する
:set number→行の数字を確認できる

```
hogehoge
fugafuga
```

ここに:set numberを入力すると

```
1 hogehoge
2 fugafuga
```

と現在の行数を確認することができる

###矩形処理
縦列のものを編集する場合は矩形(くけい)処理を行う

＜矩形処理による編集の仕方＞
①ノーマルモード(ESCキー)にて、文字を挿入したい位置へカーソルを移動する。
②矩形選択をするため、ctrl＋vキーを押下する。（このとき--VISUAL BLOCK--と表示される）、
③↑または↓で範囲を指定する。
④Shift＋iキーでインサートモードになる（このとき--INSERT--と表示される）
⑤挿入したい文字を入力した後、ESCキーで通常モードに戻る

＜編集前＞

```
12345
12345
12345
```

①〜⑤のような矩形処理を使用して１行目にABCを挿入すると

＜編集後＞

```vim
ABC12345
ABC12345
ABC12345
```

となる

##パスのオファー(パスのレコメンデーション)の操作について
パスの後のディレクトリやファイルの入力を省略したい際に
パス後の候補を出すやり方です。

例えば
insert(i)モードして、~/を打った後にcontrol＋x＋fを押します。

実際にやってみるとこのようにパスの後の候補が出てきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790932/609463b2-d3d7-d971-4e58-5badd3af7639.png)
[エラー]EC2からRDSに接続できない　ERROR 2003 (HY000): Can't connect to MySQL server

<h2>初めに</h2>
先日からAWSの学習を始めましたが、非常に苦戦しております。
とにかくひとつずつ学んだこと理解したことをアウトプットしていきたいと思います。

<h2>エラーの内容</h2>
EC2からRDSに接続しようとしたところ、以下のようなエラーが出ました。

```ERROR 2003 (HY000): Can't connect to MySQL server on 〜〜' (110)```

<h2>解決策</h2>
RDSのセキュリティグループの設定を変更します。

![スクリーンショット 2021-09-05 8.34.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/c32d0102-5529-ab5d-c238-d9ef8722652a.png)

![スクリーンショット 2021-09-05 8.34.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/c425c57e-8eb2-be0d-b603-8ce727568378.png)

![スクリーンショット 2021-09-05 8.35.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/b141e3b7-ca8b-9d49-29ee-149d9efda2db.png)

<h3>インバウンドルールを以下のように修正します</h3>

![スクリーンショット 2021-09-05 8.35.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/f6bec1de-c4e7-e730-1bc8-71b43950be27.png)

当初、二行目のものしか書いていなかったので、
外からのアクセスを受け付けておらず、接続ができなかったようです。

アクセスできない場合、セキュリティグループの設定を疑えば良さそうです。
検索してみると、結構記事がヒットしてきたので、
間違えがち、忘れがちな箇所なのかなと思いました。

<h2>参考にした記事</h2>

https://teleporter.hateblo.jp/entry/2019/03/27/155537

https://casualdevelopers.com/tech-tips/how-to-fix-2003-error-when-connecting-to-mysql-server/
Linux（64bit）でSquid構築してみた

#背景
案件でSquidを使用することになったため、事前検証のために自分で構築してみました

#環境
プラットフォーム：AWS
OS：Linux/UNIX
AMI:amzn2-ami-hvm-2.0.20210721.2-x86_64-gp2

#手順
##①Squidインストール
`[root@ip-******* ~]#yum -y install squid`

##②conf修正
自分自身の環境に合わせてconfを修正していく

###②-1 confの場所
`vi /etc/squid/squid.conf`

###②-2 修正前


###②-3 修正後

##③サービスの再起動

##④動作確認


#ポイント
##Squidアクセスログの場所
画面遷移時に画像を渡す方法

ソースが長くなってしまうので、画面遷移時に画像を渡す方法だけ記載しています。

画像の表示方法やフォトライブラリから画像を選ぶといった工程は全て省いています。
　
それを踏まえた上で書いていきます。

　
ソースコードは、遷移前と遷移後の二つのクラスがあります。
ViewController1は遷移前、ViewController2は遷移後のクラスとなってます。
　
まず遷移前のクラス(ViewController1)はこちら。

    class ViewController1: UIViewController {

        @IBOutlet weak var imageView1: UIImageView!

        override func viewDidLoad() {
            super.viewDidLoad()

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let nextVC = storyboard.instantiateViewController(withIdentifier: "ViewController2") as! ViewController

            //ViewController1のimage(画像データ)をViewController2のimage(変数)に渡す
            nextVC.image = imageView1.image!
            
            //画面遷移
            present(nextVC, animated: true, completion: nil)
        }
    }
　

CustomClassとIdentityは、ViewController2となっている想定です。
![スクリーンショット 2021-09-05 7.37.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/f1b445e2-6e51-6486-5b27-8a9eb5887e68.png)

クラス名はViewController2
storyboard名はMainとしています(必要に応じて変更してください。)
![スクリーンショット 2021-09-05 7.40.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/091e3238-7533-367f-af81-904269507496.png)

そして遷移先(ViewController2)のクラスはこちら。

    class ViewController2: UIViewController {

    　　　　　　　　@IBOutlet weak var imageView2: UIImageView!

    　　　　　　　　var image: UIImage?

    　　　　　　　　override func viewDidLoad() {
      　　　　　　　　  super.viewDidLoad()

        　　　　　　　　//遷移元から取得したimage(画像データ)をimageView2のimageに渡す
        　　　　　　　　imageView2.image = image

    　　　　　　　　}
    }

もしimageViewの大きさの分だけ大きくしたいという方はこちらを加えてください。

        //　↓自分で付けたUIImageViewの名前に変更
        imageView2.modalPresentationStyle = .fullScreen // ★この行追加


　
今回やっていることは二つだけです。

　
1.まずViewController1のimageView1のimageを遷移先(ViewController2)の変数(image)に渡します

        nextVC.image = imageView1.image!
　

2.そしてViewController2のimageView2のimageに変数(image)の値を渡します

    　　　　　　　　imageView2.image = image

　
ViewController2のimageという変数を使って、二つのViewControllerの橋渡しをしています。
　

ViewControler1のimageView1.image　→ image → ViewControler2のimageView2.image
　
　
Outlet接続のやり方がわからないという方はこちらを参考にどうぞ。

https://capibara1969.com/1253/

　

imageViewにボタンアクションをつけたいという方はこちらをどうぞ。

https://qiita.com/celcior0913/items/d3da46fbbc60ded6db51

　　
　
フォトライブラリから画像を選ぶ方法を知りたいという方はこちらを参考にどうぞ。

https://qiita.com/takoikatakotako/items/22a29c3992b6e643245a

　
画像を表示させたいだけの方はこちらをどうぞ。

https://qiita.com/kanae_/items/9df6076a6ab94949439b

　
余談

imageという変数はもしかしたら必要ないかもしれません
Pandasの欠損値処理（他の列の値で埋める）

# はじめに
Pandasで欠損値がある時に他の列の値を使って補完したい時があります。
今回はその手段に加えて、手段を思いつかずに回り道をしたパターンを
忘備録として掲載します。

# サンプルパターン
次のデータフレームで、col2の欠損値をcol1の日付を3日足した値で埋める
ことを考えます。

```python
import pandas as pd
import datetime

df = pd.DataFrame({'col1': ["2021/05/08", "2021/05/08", "2021/05/08"], 
'col2': ["2021/05/09", "2021/05/11", None]},
index=['row1', 'row2', 'row3'])
```

この時、各列は次のようにdatetime変換されているとします。

```python
df["col1"] = pd.to_datetime(df["col1"])
df["col2"] = pd.to_datetime(df["col2"])
```

#1:fillna

```python
df["col2"].fillna(df["col1"]+ datetime.timedelta(days=3), inplace=True)
```

欠損値補完といったらfillnaになります。
これで解決なのですが、これが思いつきませんでした。

#2:lambda関数

```python
df["col2"] = df.apply(lambda x: x["col1"]+ datetime.timedelta(days=3) if pd.isnull(x["col2"]) else x["col2"]  ,axis=1)
```
fillnaを思いつかずに私が取った方法になります。
lambda関数と三項演算子の組み合わせで補完しました。

#3:mask関数

```python
df["col2"].mask(pd.isnull(df["col2"]),df["col1"]+ datetime.timedelta(days=3), inplace=True)
```
2の後に思いついた方法になります。
lambda関数を書かなくてもこれですみます。

# どうして回り道をしたのか
まず初めは別途defで関数を作成して補完しようとしたため、
apply関数を使った手段しか思いつかず、試行錯誤した結果が2番になります。
試行錯誤の結果、関数を作成する必要がなくなったので、
振り返ってみれば1番で解けたというオチです。

#終わりに
今回の結果は徒労に終わりましたが、
例えば、col2列が欠損値ではなく、ある一定の値をとる場合に変更したい場合は
3番を使用すれば1行で変換できます。
また、複雑な処理をしたい場合は関数を作成する場合は2番が採用候補になります。
データをどう変換したいかはその時によって変わります。
その都度調べていたら時間の無駄だよね、ということでまとめました。
自分の忘備録として書きましたが、誰かの役に立てば幸いです。

#更新情報
2021.9.6 lambda関数の記述で

```python
+ datetime.timedelta(days=3)
```
が抜けていたので追記
【Python】emojiモジュールについて

##インストール

```
pip install emoji
```

##動作環境

```
python3 --version
# Python 3.9.6

pip3 show emoji 
# Version: 1.4.2
```


##絵文字の正規表現の取得 - get_emoji_regexp()
get_emoji_regexp()メソッドで絵文字判別のための正規表現を取得することができます。
これを利用することで文章中の🤔みたいな絵文字を消し去ることができます。

```python
import re
import emoji

faces = '😢🥺🤮ლ(´ڡ`ლ)🙂😱😸( ◜ω◝ )🤔😛😾'
print(re.sub(emoji.get_emoji_regexp(), '', faces))

# ლ(´ڡ`ლ)( ◜ω◝ )
```

YouTubeやTwitterなどから取得してきたテキストを色々いじくる前の処理として使うことができます。

##文字列内の絵文字の個数をカウント - emoji_count()

```python
print(emoji.emoji_count('🍰🍔🌭おなかすいた〜🍳🍄🍫'))

# 6
```

##説明テキストを絵文字へと変換 - emojize()

```python
print(emoji.emojize('Python is :thumbs_up:'))

# Python is 👍
```

このモジュールでは通常のテキストと絵文字を指すテキストを区切り文字で判断しています。
デフォルトではコロンを両端に添えることで他と区別しています。

##絵文字を説明テキストへ変換 - demojize()

```python
pien = emoji.demojize('🥺')
print(pien)

# :pleading_face:
```

絵文字が表示できない環境への対応に利用できる。

##絵文字のセット
emojiモジュールは絵文字と説明テキストの辞書（英語版やスペイン語版など６言語対応）を提供しています。他の方が記事で紹介しているemoji.UNICODE_EMOJIは今は各言語の辞書が入った辞書へと変わってしまっているので，今はemoji.UNICODE_EMOJI_ENGLISHを使うのがいいかも。

```python
print(emoji.UNICODE_EMOJI_ENGLISH)
# {'🥇': ':1st_place_medal:', '🥈': ':2nd_place_medal:', '🥉': ':3rd_place_medal:', ...}

print(emoji.UNICODE_EMOJI_ENGLISH['😾'])
# :pouting_cat:

is_emoji = '🤮' in emoji.UNICODE_EMOJI_ENGLISH
print(is_emoji)
# True

is_emoji = 'あ' in emoji.UNICODE_EMOJI_ENGLISH
print(is_emoji)
# False
```

emoji.EMOJI_UNICODE_ENGLISHはキーとバリューを逆転させたもの。

```python
print(emoji.EMOJI_UNICODE_ENGLISH)
# {':1st_place_medal:': '🥇', ':2nd_place_medal:': '🥈', ':3rd_place_medal:': '🥉', ...}
NITIC-CTF 入門の巻

# Welcome to nitic-ctf!!!
nitic-ctfにようこそ!  
ここでは初めてCTFに参加する人のために、CTFとは何なのか、CTFの始め方を解説していきます！

このチュートリアルを読破すれば、今回のnitic-ctf2の☆1~2の問題をクリアすることができるレベルの物となっています。  
ちなみに私はCTF初心者です。誤った文章等ございましたらコメント等で教えていただけると幸いです。

nitic-ctf-2は[こちら](https://ctf.waku-waku-club.com)
公式Discordは[こちら](https://discord.gg/Rp5C9xNDxY)

### 目次
1. イントロダクション
2. 各カテゴリの解説
    1. Crypto
    2. Pwn
    3. Rev
    4. Web
    5. Misc
3. 手の動かし方
4. 例題
5. まとめ

## 1.イントロダクション
CTFとは、 **Capture The Flag** の略であり、セキュリティに関する問題を解く競技です。多くのCTFでは、Flagと呼ばれる文字列を入手し、それを入力することで点数を得ることができるルールとなっています。今回のnitic-ctfでは、nitic_ctf{**Flag**}の形式で指定される文字列を見つけることが目標です。
問題は、それぞれカテゴリに分かれています。今回は、カテゴリごとにそのカテゴリの簡単な説明と、いくつかの簡単な例題を示していきます。

## 2.各カテゴリの解説

### 1.Crypto
このカテゴリでは、主に暗号についての問題が出題されます。
暗号と一口に言っても、メモ書きを用いれば解けるレベルからRSA暗号などのより解読が難しいものまで多岐にわたります。


### 2.Pwn
このカテゴリでは、バイナリの脆弱性を付くような問題が出題されます。
問題としては、例えばプログラムが配布され、そのプログラムのソースコードなどから脆弱性を発見し、その脆弱性を付くことでFlagを得るといった問題があります。

### 3.Reverse
このカテゴリでは、与えられたファイルを解析することでFlagを得る問題が出題されます。
解析というのは、例えばファイルの種類を解析したり、リバースエンジニアリングを行ってソースコードを入手し、Flagを得るといったものが挙げられます。

### 4.Web
このカテゴリでは、Webに関する問題が出題されます。Web上の脆弱性をついたり、ソースコードからFlagにつながるポイントを見つけて正解を導きます。

### 5.Misc
このカテゴリでは、名前の通りここまでのカテゴリに当てはまらない問題が出題されます。
問題文に記載されているキーワードなどから解法を推測し、正解を導いていきましょう！

## 3.手の動かし方
まず、問題文とジャンルをみて、解き方を推測していきましょう。
次に、それをどうやって行うかを調べましょう。

解法を推測し、実行していく、これを繰り返し行うことで、Flagを見つけていきます。

例として、暗号化されたFlagが提示されているとします。

まず、その文字列をどう処理するかを考えます。
今回は、何らかの形式で暗号化されていることがわかっているので、これを復号すればFlagを見つけることができます。
また、この文字列はなんの形式で暗号化されているのかということを推測する必要があります。
多くの場合、問題の名前や問題文にヒントとなる単語が記載されていたり、暗号文からその特徴を読み取って推測することができます。

次に、どのように処理するかを調査します。
先程得たヒントをもとに、Googleなどを用いて解読方法を探します。
その解読方法に基づいて、解読を行います。

ここで、Flagらしい文字列が見つかれば、それを入力してみます。
ここで正解できれば、クリアです！
もし正解できなかった場合は、また最初に戻って、推測→調査→処理を繰り返して正解を見つけましょう。

## 4.例題

### 1.Crypto
以下は、暗号化されたFlagです。
```－・－・　・－・　－・－－　・－－・　－　－－－```
Flagは、英語アルファベットの小文字のみで記述されていることがわかっています。
sample_flag{復号したFlag}を提出してください。

<details><summary>解答</summary><div>

暗号化されたFlagを見ると、モールス信号のように見えます。
そこで、モールス信号を英文に変換してくれるサイトを見つけましょう。
もしくは、アルファベットとモールス信号の変換表を見て、自力で変換します。

すると、cryptoという文字列が浮かび上がります。
答えは、sample_flag{crypto}となります。

</div></details>

### 2.Web
以下のページを見て、Flagを見つけてください。
[Here](https://you-can-see-flag.netlify.app)
sample_flag{Flag}を提出してください。

<details><summary>解答</summary><div>

ページに有るように、Flagは ****************.netlify.app の * の部分です。
つまり、このページのURLの該当部分であることがわかります。
つまり答えは、sample_flag{you-can-see-flag}です。

また、別解として、先程のページを開いて、F12キー（ブラウザによって変わる場合があります）を押すと、開発者モードに入ることができます。
そこを見ると、ページのソースコードをみることができます。
そこにはなんと、答えはsample_flag{you-can-see-flag}と書いてあります！

</div></details>

## 5.まとめ
いかがだったでしょうか。
今回が初めてのCTFだという方の手助けになれば幸いです！
今回のnitic_ctf_2では、難易度が低いものから高いものまで幅広く出題されます。
ぜひ、解けそうな問題を解いてみて、CTFの世界に踏み込んでみてください。

また、今回のような期間指定型のCTF大会の他にも、常設CTFと呼ばれる、常に開催しているCTFがあります。
もしもっと様々な問題に触れてみたい！という人は、ぜひこちらも試してみてください。
以下に、有名な常設CTF大会を掲載させていただきます。

- [CpawCTF](https://ctf.cpaw.site/index.php)
- [ksnctf](https://ksnctf.sweetduet.info)

【追記】
また、今後予定されているCTFなどについての情報は、
[CTFtime.org](https://ctftime.org)
というサイトに記載されています！
もっと他のCTFにも参加してみたい！という方は、ぜひこちらもチェックしてみてください！
USB接続した実機を用いてAndroid Studioでデバッグ

## 環境

Android Studio: Arctic Fox 2021.3.1

## 実機（スマホ等）での事前設定

- 設定 > システム > 端末情報 を選択
- ビルド番号を7回タップする。これで、開発者向けオプションが有効となる
- 設定 > システム > 開発者向けオプション を選択
- USBデバッグ を有効にする

- 注
  - 設定メニュー構成は機種によって異なる場合がある。異なる場合は機種毎のマニュアル等を参照

## デバッグ

- PCと実機（スマホ等）をUSBケーブルで接続
- Android Studioでプロジェクトを開く
- Run > Debug
IBM Cloud: Power Systems Virtual Server(AIX)でyumを導入する方法


2021/10/12追記
最近のPower Systems Virtual Server(AIX)では、yumが導入済みでプロビジョニングされてくるようです。

#1. 手順概要
[AIX toolbox for Linux Applications](https://www.ibm.com/support/pages/node/883796)に記載されている、`yum.sh`を実行すれば良い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/d0b11e7c-96c5-d575-8599-5c0c2c09e241.png)

（参考）
https://developer.ibm.com/articles/configure-yum-on-aix/
https://www.ibm.com/support/pages/tips-installing-python-or-other-aix-toolbox-linux-applications

#2. 詳細手順

```
(/optの容量が足りなければ増やしておく)
# chfs -a size=+1G /opt

# curl -ksL https://ftp.software.ibm.com/aix/freeSoftware/aixtoolbox/ezinstall/ppc/yum.sh | sh

# yum --version
3.4.3
  Installed: yum-3.4.3-8.noarch at 2021-09-04 20:36
  Built    : IBM AIX Toolbox <https://ibm.biz/AIXToolbox> at 2020-12-04 12:33
  Committed: Sangamesh Mallayya <<sangamesh.swamy@in.ibm.com> at 2020-11-30
```

# 参考: python3及びawscliの導入例

yumさえ導入されていれば、x86系と変わらない。
例えば、python3を導入してawscliを導入する場合は、[ここ](https://qiita.com/testnin2/items/8c2bf7990ef55b4abf7d)などを参考に、以下のようにやれば良い。

```
(/varの容量が足りなければ増やしておく)
# chfs -a size=+1G /var


# yum install -y python3
# export PATH=/opt/freeware/bin:$PATH
# python3 -V
Python 3.7.10

# mkdir python3710
# python3 -mvenv python3710
# . python3710/bin/activate
(python3710) # pip install --upgrade pip
(python3710) # pip install awscli
```
Azure Container Registry を使用してコンテナー イメージをビルドして保存する

#はじめに

AZ-304取得に向けてMicrosoftのラーニングパスでAzure Container Registryの演習しました。

https://docs.microsoft.com/ja-jp/learn/modules/build-and-store-container-images/

#作業環境

```
Azure CLI
Azure Container Registry
```

#作業結果
![acr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1949705/37e2ad30-e162-2246-174f-eae1c621814e.png)
コンテナーのデプロイを含めこれまでの作業が問題ないことを確認

![acr2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1949705/6e18bd8d-fe12-3a09-b91d-d068aaba4312.png)

Azure リージョン間でのレジストリが出来ていることを確認。

#作業工程　
・Azure コンテナー レジストリをデプロイする
・Azure Container Registry Tasks を使用してコンテナー イメージをビルドする
・コンテナーを Azure コンテナー インスタンスにデプロイする
・コンテナー イメージを複数の Azure リージョンにレプリケートする
※上記ラーニングパスより引用しますが、作成途中で特につまづくところはなかったです。
[2021Sep] docker の debian:buster に openjdk をインストールする

# はじめに

docker の debian:buster で `apt install openjdk-11-jre-headless` 等とやっても失敗します。なぜ？

調べました。


# 結論

### 原因と現象

debian:buster も image サイズ削減のため man page インストールを回避する設定が成されている。
ただし、この設定は Alternatives System をカバーするには不十分で、openjdk-11 の postinst スクリプトがエラー終了してしまい、apt install も失敗する。


### 対処

openjdk-11 専用に man page インストール回避の設定を加えると、無事にインストールが完了する。


# 詳細

### man page インストール回避の設定

dpkg への指示により実現されています。

```:/etc/dpkg/dpkg.cfg.d/docker
(略)
path-exclude /usr/share/man/*
(略)
```

結果 /usr/share/man/man1 などが作成されません。


### openjdk-11-jre-headless の実ファイルの所在

Alternatives System がリンクを張る `java` コマンドや man page などの実体は /usr/lib/jvm/java-11-openjdk-amd64 にあります。

```:/var/lib/dpkg/info/openjdk-11-jre-headless&#x3a;amd64.postinst
(略)
basedir=/usr/lib/jvm/java-11-openjdk-amd64
mandir=$basedir/man
(略)
```

### update-alternatives コマンドの失敗

上述の postinst スクリプトは、もし所定のディレクトリに man page が存在したら `update-alternatives` に処理させる、という仕組みになっています。ただし、前述の設定で /usr/share/man/man1 などが存在していないため、リンクを張る処理が失敗します。

なので、dpkg への指示で openjdk-11 の man page も存在させないようにしてしまえば、リンクを張る処理が実施されず失敗もしない、ということになります。


### Dockerfile 例

都合、下記のようにすれば、openjdk-11-jre-headless をインストールした debian:buster ベースのイメージが作成できます。

```:Dockerfile
FROM debian:10.10-slim

RUN echo "path-exclude /usr/lib/jvm/java-11-openjdk-amd64/man/*" > /etc/dpkg/dpkg.cfg.d/openjdk-11 && \
    apt update && \
    apt -y install --no-install-recommends openjdk-11-jre-headless
```


# おわりに

centos:centos7 で /usr/share/doc が空っぽなのは、/etc/yum.conf に nodocs 指示が書かれているから、でした。yum への設定なので、直接 rpm コマンドを利用すればこの設定の影響は回避されます。

他方 debian は dpkg への設定なので、apt を利用した場合も同じ結果になります。

このあたり、思想の違いが感じられて、面白いです。
elm327の研究 その9

# 概要

elm327を調べてみた。
arduino unoでobd_simやってみた。

# 参考にしたページ

https://qiita.com/covao/items/f3b7491db7fbb45b2d46

# 写真

![DSCN0540.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b46c1bf0-4e6b-e0b7-2c4a-1e7d54ff007f.jpeg)


# 配線図

|arduino uno|mcp2515 モジュール|
|:--|:--|
|2|int|
|13|sck|
|11|si|
|12|so|
|10|cs|
|gnd|gnd|
|+5.0V|vcc|

# 実行結果

```
atz


ELM327 v1.5

>atrv
11.7V

>atsp8
OK

>atdp
ISO 15765-4 (CAN 11/250)

>010c
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C 40
41 0C 9C
BUFFER FULL

>010d
41 0C 9C 40
41 0C 9C 40
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D FA
41 0D F
BUFFER FULL

>0105
41 0D FA
41 0D FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05
BUFFER FULL

>
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05 FA
41 05
BUFFER FULL

>010f
41 05 FA
41 05 FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F FA
41 0F
BUFFER FULL

```

以上。
メソッドについて

メソッドとは、rubyにおける関数を指す。
メソッドには、①関数型メソッド、②インスタンスメソッド、③クラスメソッドの３つの分類がある。
それぞれの使用は、
①メソッド（引数１,引数２,....）
②オブジェクト.メソッド(引数１,引数２,....)
③クラス.メソッド(引数１,引数２,....)
である。
railsを使用していると、このこの形が頻発しているが、特に、ドットの利用はメソッドの呼び出しであると考える。
elm327の研究 その8

#概要

elm327を調べてみた。
取得できる、プロトコルを列挙してみた。

#対応プロトコル

|コマンド|プロトコル|
|:--|:--|
|atsp0 | Automatic
|atsp1 | SAE J1850 PWM (41.6 kbaud)
|atsp2 | SAE J1850 VPW (10.4 kbaud)
|atsp3 | ISO 9141-2 (5 baud init, 10.4 kbaud)
|atsp4 | ISO 14230-4 KWP (5 baud init, 10.4 kbaud)
|atsp5 | ISO 14230-4 KWP (fast init, 10.4 kbaud)
|atsp6 | ISO 15765-4 CAN (11 bit ID, 500 kbaud)
|atsp7 | ISO 15765-4 CAN (29 bit ID, 500 kbaud)
|atsp8 | ISO 15765-4 CAN (11 bit ID, 250 kbaud)
|atsp9 | ISO 15765-4 CAN (29 bit ID, 250 kbaud)
|atspA | SAE J1939 CAN (29 bit ID, 250* kbaud)
|atspB | USER1 CAN (11* bit ID, 125* kbaud)
|atspC | USER2 CAN (11* bit ID, 50* kbaud)


以上。
Zabbix Agent2をroot権限で起動できるようにする(AllowRoot代替)

Zabbix Agent2でroot権限のファイルなどを監視する場合、以下のようなエラーが発生し監視が出来ません。
そのため、Zabbix Agent2をroot権限で起動しroot権限が必要な操作を実行可能とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/779b1470-6aa5-61df-ff01-f52eb7c3a4ec.png)

```text:error_example
Cannot open file "/var/log/messages": [13] Permission denied
```

</br>
</br>

#1. NG:zabbix_agent2.confでAllowRootを設定する
Zabbix Agent1でroot権限操作を行う際には、`zabbix_agent.conf`内の`AllowRoot`を`1`とすることで、Zabbix Agnetをルート権限で起動することが出来ましたが、Zabbix Agent2ではこのオプションがオミットされているため、旧来通りの対策は出来ません。

:::note warn
zabbix_agent2.conf に AllowRoot=1を追記した場合、zabbix_agent2 プロセスが起動に失敗します。
:::

Dropped parameters | Description
--- | ---
AllowRoot, User | Not supported because daemonization is not supported.

https://www.zabbix.com/documentation/5.0/manual/concepts/agent2



</br>
</br>

#2. OK:zabbix_agent2のユニットサービスを変更する
以下を参考に、zabbix_agent2のユニットサービス内のユーザ/グループ指定を変更して対応します。

https://www.zabbix.com/documentation/5.0/manual/appendix/install/run_agent_as_root

対象のファイルは`/etc/systemd/system/multi-user.target.wants/zabbix-agent2.service`です。

設定変更箇所は`[Service]`内の`User`と`Group`です。もともとは`User=zabbix`となっているため、`root`に変更します。

```c:zabbix-agent2.service_edit
[Unit]
Description=Zabbix Agent 2
After=syslog.target
After=network.target

[Service]
Environment="CONFFILE=/etc/zabbix/zabbix_agent2.conf"
EnvironmentFile=-/etc/sysconfig/zabbix-agent2
Type=simple
Restart=on-failure
PIDFile=/run/zabbix/zabbix_agent2.pid
KillMode=control-group
ExecStart=/usr/sbin/zabbix_agent2 -c $CONFFILE
ExecStop=/bin/kill -SIGTERM $MAINPID
RestartSec=10s
User=root
Group=root

[Install]
WantedBy=multi-user.target
```
</br>
設定変更前は`zabbix`ユーザで起動しているため、`daemon-reload`の後にプロセス再起動を行います。

```terminal:service_restart
[root@cent79-02 ~]# ps -aux | grep zabbix
zabbix    8902  0.1  1.1 509240 21972 ?        Ssl  05:40   0:01 /usr/sbin/zabbix_agent2 -c /etc/zabbix/zabbix_agent2.conf

[root@cent79-02 ~]# systemctl daemon-reload
[root@cent79-02 ~]# systemctl restart zabbix-agent2

[root@cent79-02 ~]# ps -aux | grep zabbix
root      8967  0.5  1.0 508028 19648 ?        Ssl  05:58   0:00 /usr/sbin/zabbix_agent2 -c /etc/zabbix/zabbix_agent2.conf
```

ZabbixAgent2が`root`ユーザで起動していることが確認できました。
ZabbixServer側のアイテムステータスも正常になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/676d6cc8-92c6-8282-70bd-308941147493.png)

</br>
</br>

#後記
今回のエラー原因は`/var/log/message`のパーミッションにちなむので、ファイル権限とローテーション権限を修正する方法もあったのですが、汎用性の話となんだか負けた気がするのでこちらの方法で行いました。


</br>
</br>

#参考

https://www.zabbix.com/documentation/5.0/manual/concepts/agent2

https://www.zabbix.com/documentation/5.0/manual/appendix/install/run_agent_as_root

https://tex2e.github.io/blog/linux/create-my-systemd-service

https://qiita.com/keita0322/items/13583701b4a3de331d0c
【Rails】プロフィール画像丸くサイズや形（メモ）

#目標
#### 円or丸の中に画像を表示する。

![スクリーンショット 2021-09-05 4.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927584/27d1d816-799b-73f9-9f66-669ba4402013.png)

#前提
* 画像投稿機能実装済み
* CarrierWaveは導入済み

#実装
cssは使用せず今回はimage_tagの後に円形の指定`"rounded-circle"`とサイズを指定しています。
これだけです。
あとif文で画像を指定した場合と指定されなっかた場合でで分けて指定してない場合はデフォルト画像になるように指定しています。

```erb:app/views/users/show.html.erb
   <h1><%= @user.name %>詳細ページ</h1>
 
    <% if @user.image? %>                                                              
      <%= image_tag @user.image.url, class: "rounded-circle", size: "150x150" %>
    <!--##画像が設定されてない場合-->
    <% else %>
      <%= image_tag "default.png", size: "150x150" %>
    <% end %>

```

画像を指定しなかった場合です。
`app/assets/images`ディレクトリ配下に自分の指定したデフォルト画像を配置します。



![スクリーンショット 2021-09-05 5.15.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927584/f21f95cb-1ef5-82f9-e998-2e071c9eced6.png)

ざっくりとはしていますがこれで円形に画像を指定することができました。
簡単な指定なのですが方法がいくつかあって、調べるのに時間がかかって大変だった思い出があるので、備忘録として残しておきます。
もし、同じように悩んでる方の参考になれば幸いです。
画像投稿機能も投稿してるのでもし参考程度に良ければ見てみてください。
https://qiita.com/moru0606/items/ae7b1742787f50b4e254

#参考リンク
cssで画像丸く:https://qiita.com/mam-e/items/1d2be069a5d2190ec505
画像投稿機能：https://qiita.com/k19911848/items/a082cc4e0c0103f935b1
デフォルト画像指定：https://qiita.com/Toshimatu/items/a6382efd410fe5544406
KDE neonでGRUBテーマを変更する方法

今回はKDE neonでGRUBのテーマを変更する方法について書きます。
KDE neonのGRUBはカスタマイズされているので、他のディストリと同じように変更するだけでは動作しないようです。

# まずはテーマを入れる
今回は[このテーマ](https://www.pling.com/p/1414997)を入れます。
インストールの方法はどのテーマも共通だと思うが一応書いておきます。
予め解答し、install.shがあるディレクトリへ移行してください。

```bash
sudo ./install.sh
```

# [本編]テーマの適応
再起動するとわかるが、テーマは何も変わっていません。。。
KDE neonがカスタマイズしているからです。

## 1.まずはtheme.txtの位置の確認
/usr/share/grub/themes/
/boot/grub/themes/

のどちらかにインストールしたテーマが入っています。
そして、インストールしたテーマの中に theme.txt があるはずなので、そのパスをコピーしておきます。
今回のテーマは/usr/share/grub/themes/sleek/theme.txtにありました。

## 2.テーマの適用
パスをコピーしたら、次のコマンドを実行します。

```bash
sudo nano /etc/default/grub.d/99_breeze-grub.cfg
```

すると、nanoが開くので、
GRUB_THEME=
の部分を先ほどコピーしたパスに置き換えます。
例）GRUB_THEME=/usr/share/grub/themes/sleek/theme.txt
そして "Ctrl + S", "Ctrl + X"でnanoを閉じ、

```bash
sudo update-grub
```

を実行してください。
これで再起動するとしっかりテーマが変更されているはずです。
なぜこのような仕様にしたのでしょうか...　不思議でたまりませんが、まぁおとなしく従うしかないです。
以上、ありがとうございました！！

# おまけ
ハードディスクにOSが１つしか入っていない場合でもGRUBを表示してテストしたい場合は、

```bash
sudo nano /etc/default/grub
```
でGRUBの設定ファイルを開き、

```bash
# GRUB_TIMEOUT_STYLE="0"から変更
GRUB_TIMEOUT_STYLE="menu"
# 20をお好みの秒数に変えてください
GRUB_TIMEOUT="20"
GRUB_RECORDFAIL_TIMEOUT="20"
```

↑のようにすると表示されるようになります！
最後まで見ていただき、ありがとうございました！！！！

引用元: https://www.youtube.com/watch?v=AIas8_X5qSg
AndroidManifest.xmlを上書きできずAPK生成に失敗する場合の解消方法

## 環境

* Android Studio: Arctic Fox 2021.3.1
* gradle 7.0.2

## 現象

プロジェクトのビルドや実行において、以下のようなエラーがでて失敗する。

```
Zip file '...\app\build\outputs\apk\debug\app-debug.apk' already contains entry 'AndroidManifest.xml', cannot overwrite
```

## 原因

- 依存ライブラリの中にAndroidManifest.xmlが含まれている場合、そのAndroidManifest.xmlが先にAPKにコピーされる
- その後、本プロジェクトのAndroidManifest.xmlをコピーしようとするが、既に存在するためエラーとなる
- [参考] Android Gradle プラグイン 7系で使用されているzipflingerというライブラリで上書きチェックが厳密にされるようになったため、問題が顕在化した模様 
 - https://android.googlesource.com/platform/tools/base/+/refs/heads/mirror-goog-studio-master-dev/zipflinger/src/com/android/zipflinger/ZipArchive.java#337

## 解消方法

- `build.gradle` の中から問題のある（AndroidManifest.xmlを含む）依存ライブラリを特定
- 依存の記載を削除（場合によって、代替ライブラリ等を検討）
【Sphinx】数式や図表のあるreSTドキュメントをPDFにする。

# １．はじめに

LaTeXについては「名前なら知っている」程度の無頼漢が、数式や図表（matplotlib）のあるreST文書をエラーなくPDFできるようになるまでのメモ。

#### 備考

エラーなくPDFにできるようになりましたが、こんな問題は残っています。

- 数式がフッター領域にはみ出する。
- 文章の後にあるはずの図表が文章の前にある。

これらはLaTeXに成熟するにつれて解決する問題だと思います。

# ２．環境

- Windows10/Cygwin64
- Python 3.8.10
- Sphinx 4.1.2
- TexLive 20210821

# ３．概要

1. Cicaフォントのインストール
1. matploglibのフォント設定
1. TexLiveインストール
1. LuaLaTeXの設定

# ４．手順
## ４．１．Cicaフォントのインストール

1. [ダウンロードサイト](https://github.com/miiton/Cica/releases/tag/v5.0.2) からダウンロード
1. cygwin環境に ```/usr/local/share/fonts/ttf/``` を作成
1. 解答したCicaのttfファイルをこのディレクトリに置く 

##  ４．２．matploglibのフォント設定
1. ```~/.matplotlib/matplotlibrc``` を作成する
1. この設定ファイルに ```font.family: Cica``` を追記


## ４．３．TexLiveインストール

1. インストラーのダウンロード
1. インストラーの実行
1. パッケージの選択
1. ダウンロード

### 選択したパッケージ
- ```Additinal fonts``` が容量を喰うが、数式を使う時は外れない。
- ```LaTeX additional package``` も外すと ```latexmk``` のエラーになる。
- 他はそれほど容量を取らないので、入れても入れなくても大差ない。

```
===============================================================================
   Select collections:

    a [X] Essential programs and files      w [ ] Italian
    b [X] BibTeX additional styles          x [X] Japanese
    c [X] TeX auxiliary programs            y [ ] Korean
    d [X] ConTeXt and packages              z [ ] Other languages
    e [X] Additional fonts                  A [ ] Polish
    f [X] Recommended fonts                 B [ ] Portuguese
    g [X] Graphics and font utilities       C [ ] Spanish
    h [X] Additional formats                D [X] LaTeX fundamental packages
    i [X] Games typesetting                 E [X] LaTeX additional packages
    j [X] Humanities packages               F [X] LaTeX recommended packages
    k [ ] Arabic                            G [X] LuaTeX packages
    l [ ] Chinese                           H [X] MetaPost and Metafont packages
    m [X] Chinese/Japanese/Korean (base)    I [ ] Music packages
    n [ ] Cyrillic                          J [X] Graphics, pictures, diagrams
    o [ ] Czech/Slovak                      K [X] Plain (La)TeX packages
    p [X] US and UK English                 L [X] PSTricks
    s [ ] Other European languages          M [X] Publisher styles, theses, etc.
    t [ ] French                            N [X] Windows-only support programs
    u [ ] German                            O [X] XeTeX and packages
    v [ ] Greek
    P [X] Mathematics, natural sciences, computer science packages
    S [ ] TeXworks editor; TL includes only the Windows binary

   Actions: (disk space required: 3192 MB)
    <-> deselect all
    <+> select all
    <R> return to main menu
    <Q> quit

   Enter letter(s) to (de)select collection(s):
```

## ４．４．LuaLaTeXの設定

```SHINX_PROJECT/source/conf.py``` に次の設定を追記する

```python
# lualatex
latex_engine = 'lualatex'
latex_docclass = {'manual': 'ltjsbook'}
latex_elements = {
    'preamble': r'\usepackage{cancel}',
}
```

# ５．```make latexpdf``` 中に発生したエラー

次の二つについて修正したらエラーがでなくりました。

- ```\begin{array}{l}``` の ```{l}``` の数を式に合わせて変更
- ```\bcancel{数式}``` を使えるようにパッケージの追加

LaTeXのことを何も知らないとエラーメッセージにビビりますが、メッセージ内容で検索したり、先ずはシンプルなreSTドキュメントで試すなどすれば解決すると思います。

# 以上
19歳学生でCCNA合格した話

#はじめに
僕は19歳専門1年生です。ネットワーク系に興味があって独学でccnaに合格しました。
実機は触ったことがないし、未経験ですが、合格できました。
同じ学生とかに未経験でもいける！ってのを伝えられたらいいなと思いこの記事を書きます。

#前提知識
僕は以下の知識や資格を持った状態で受験しました。
・基本情報技術者試験の知識
・2, 10, 16進数の変換がスムーズに出来る
・packet tracerである程度遊んで雰囲気が理解できる
・ネットワークへの興味!

#教材
参考書: [ccna参考書](https://www.google.com/aclk?sa=L&ai=DChcSEwiIvP7jg-byAhUl10wCHaSYARMYABAFGgJ0bQ&ae=2&sig=AOD64_21_rd6t2Qf2kB1FmFgmHY-k8u31g&ctype=5&q=&ved=2ahUKEwje-fXjg-byAhXHG6YKHXi9BEsQ9aACegQIARBg&adurl=)
ping-t
packet tracer

#期間
ccnaの参考書を1ヶ月 (1日平均20ページくらい進めた)
ping-tを半月
学校もあるので1日1時間くらいで毎日やりました。

合計約1.5ヶ月かかりました。

#勉強法
###最初は参考書でインプット。
コマンドではなく概念や構成を覚える。
lpicみたいにコマンドの問題はそんなに多くない。むしろどんな特徴でどんな動作をするのかの方が大事な気がする。

例) rip = ディスタンスベクタ型, ospf = リンクステート型 みたいに覚えるのではなく、
僕は頭にトポロジを思い浮かべてこのコマンドを叩くとこうなる~みたいにイメージ出来るように覚えました。( 語彙力なくて伝わるかわからないけど... )
まとめるとイコールではなく関連で覚えました。個人的に歴史と似てるかも？

途中でpacket tracerとかでospfを構築してみたり、ssh接続の設定を復習してみたり。
packet tracerでコマンドは結構慣れることができました。

###問題を解きまくる。
ping-tのコマ問でコマンドを覚えて、問題集をやりまくって定着させました。
自分の得意不得意を把握すると苦手分野のカバーをしやすいと思います。

ping-tの問題集は2周しました。1日100問。(本番102問)
最初はミスを放置し、全部解き切ってからミスした問題をやりました。

なぜ間違えたか理解できる程度までは解き直しました。

#合格して変わったこと
学生で実務はやらないので生活が変わったりすることがありません。
学校の授業がすごく楽に思う感はあります。
ただ、
ccnaは3年で失効するので卒業までにccnpに挑戦したい。

あとは他の資格のページ数が少なく見えることくらいしか変化はありませんでした。

#一番重要だと思ったこと
覚え方よりも毎日やることが定着に繋がると思います。
誕生日だろうが彼女ができただろうが関係なく毎日やり続けることだと思います。

ccnaはボリュームが多いので大変でしたが、「 継続は力なり 」を実感しました。
Laravelでuuidをidとするモデルを作りたいとき

LaravelのEloquentモデルのidは通常数値なわけですが、uuidを使いたい！といった場合があると思います。

そういった場合、

```php
$post = new Post();
$post->id = Str::uuid();
...
$post->save();
```

といった形を取るかもしれないのですが、もっと良い形で書く方法があって、それはイベントを利用する方法です。

```php
class Post extends Model
{
    protected static function booted()
    {
        static::creating(function(Post $model) {
            empty($model->id) && $model->id = Str::uuid();
        });
    }
}
```

このように書くことによってidをセットしてなくとも作成しようとするときに自動的にuuidが作成されて保存されます。

オブザーバークラスを作る方法もありますが、これくらいであればそのまま書いて良さそうです。

この辺に書いてあります
https://laravel.com/docs/8.x/eloquent#events-using-closures
std::accumulateをstd::reduceに書き換えるためにどうすればいいか

# はじめに

配列の要素を合計するような関数としてC++17より前は`std::accumulate`というのがありました。

https://cpprefjp.github.io/reference/numeric/accumulate.html

C++17では新たに`std::reduce`が追加されました。

https://cpprefjp.github.io/reference/numeric/reduce.html

`std::reduce`はC++17で追加されたparallel algoritmsと呼ばれる、並列化に対応しています。

`std::accumulate`は対象配列の先頭から合計するという性質を持っていたために、並列化できなかったのですが、`std::reduce`にはその制約がないため並列化ができるわけです。

当然並列化してくれたほうが助かるので書き換えたいわけですが、この制約の違いから、バグを作り込まないようにする必要があります。

# 単純な書き換えで済む場合

単なる合計などは特に悩むことはありません。

```cpp:accumulate
using value_type = std::int64_t;
value_type calc_sum(const std::deque<value_type>& logbuf) {
	return std::accumulate(logbuf.begin(), logbuf.end());
}
```

```cpp:reduce
using value_type = std::int64_t;
value_type calc_sum(const std::deque<value_type>& logbuf) {
	return std::reduce(std::execution::par, logbuf.begin(), logbuf.end());
}
```

# 交換法則が成り立っていなかった場合

標準偏差を求める例を見ていきます。標本標準偏差は各要素と平均値との差の2乗の総和を要素数-1で割ってルートをとったたものでした

```cpp:accumulate
using value_type = std::int64_t;
double calc_stdev(const std::deque<value_type>& logbuf, double average) {
	return std::sqrt(
		std::accumulate(logbuf.begin(), logbuf.end(), 0.0, [average](double sum, value_type val) {
			return sum + std::pow(static_cast<double>(val) - average, 2);
		}) / (logbuf.size() - 1)
	);
}
```

```cpp:reduce
using value_type = std::int64_t;
double calc_stdev_impl(double n, double) { return n; }
double calc_stdev_impl(value_type n, double average)
{
	const auto re = static_cast<double>(n) - average;
	return re * re;
}
double calc_stdev(const std::deque<value_type>& logbuf, double average) {
	return std::sqrt(
		std::reduce(std::execution::par, logbuf.begin(), logbuf.end(), 0.0, [average](auto l, auto r) {
			return calc_stdev_impl(l, average) + calc_stdev_impl(r, average);
		}) / (logbuf.size() - 1)
	);
}
```

std::reduceにわたす`binary_op`は以下の全ての演算結果の型が、型`T`に変換可能であることが必要です。

- `binary_op(init, *first)`
- `binary_op(*first, init)`
- `binary_op(init, init)`
- `binary_op(*first, *first)`

さて、今回の例だと`T`は`double`です。一方で要素の型は`std::int64_t`型です。つまり`binary_op`の2つの引数はこの2つの引数をそれぞれ受け取れる必要があります。これを解決するためにC++14で追加された[ジェネリックラムダ](https://cpprefjp.github.io/lang/cpp14/generic_lambdas.html)を用います。

また、`binary_op`の計算結果は`double`型にしたので、引数がdouble型のとき、その値はすでに平均差の2乗の部分和になっているわけですから加工は不要になります。今回は関数overloadで解決してみました。

`std::accumulate`では部分和は第一引数に来ましたが、`std::reduce`ではどちらに来るかわからないという点がポイントとなりそうです。
UIImageViewにボタン(タップアクション)をつける

やりたいことはこんな感じ。
 
![スクリーンショット 2021-09-05 3.14.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/a1e9e7f8-ea2f-c561-0156-e8a9b90cbec8.png)

ImageViewをタップしたらボタンのような動作をできるようにします。
　
そしてソースコードはこちら。

    class ViewController: UIViewController {
    
        //ImageView
        @IBOutlet weak var imageView: UIImageView!
        
        override func viewDidLoad() {
            super.viewDidLoad()

            //タップアクションの有効化
            imageView.isUserInteractionEnabled = true

            //imageViewにタップアクションを追加と呼び出すメソッドの追加
            imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageView)))
        }

        @objc
        func imageViewTapped() {
        
            //アラート通知
            let alert = UIAlertController(title: "", message: "画像をタップしました", preferredStyle: .alert)

            //アラートにOKボタンを追加
            let dismiss = UIAlertAction(title: "OK", style: .cancel, handler: nil)
            alert.addAction(dismiss)

            //アラートの呼び出し
            self.present(alert, animated: true, completion: nil)
        }

    }
　
imageViewのOutlet接続は下記を参考にしてください。

https://capibara1969.com/1253/
Java Silver 1章　Javaの基礎

#コンパイルと実行

```java
// ソースに複数のクラスがあれば複数のクラスファイルが作製される
class Foo {}

// JavaではPublicクラスはファイルと同名
public class Main{
  public static void main(String[] args){
    System.out.println("Hi!!");
  }
}

// ソースファイル→クラスファイル（コンパイル）→実行（JVM:Java Virtual Machine上で実行）
// この学習ではWindowsOSにあるJVM.ver11を VScode Editerで参照してターミナル（PowerShell)で実行している。
```
インタプリタ言語のPHP、JSと違いソースファイルをコンパイラして各クラスファイルを作製
実行環境の差をJVM（Java Virtual Machine）が埋めてくれる。

##1億回ループさせた時の実行時間の差
```java
public class Loop {
    public static void main(String[] args){
        int result = 0;
        long start = System.currentTimeMillis();
        for(int i = 0; i < 10000000; i++){
            result += 1;
        }
        long end = System.currentTimeMillis();
        System.out.println((end - start) + "ms");
    }
}
// 1億回足し算をするコードを実行する場合
// インタプリタ（1行づつ翻訳：PHP、JS、Rubyなど） ターミナルで -xオプション →821mm秒
// コンパイラ（機械語に一旦翻訳）  クラスファイルを作り実行    →31mm秒
```

###main()メソッド
mainメソッドはJavaでは特別なメソッドで記述は必ず
Public static void main(String[] arg){...}　　
（今のところ意味不明）
プログラムの実行開始位置となる。
###コンパイルエラーと実行時エラーのイメージ
コンパイルエラー：英語でいう単語や文法の間違い
実行時エラー　　：単語や文法はあってるが言ってる内容がおかしい


#PacageとImport

```java
package com.se;
// PHPにおけるNamespaceと同じような概念
// ファイルを置くディレクトリーも分け、物理的に区別する感じ
class Foo{
    void print(){
        System.out.println("package sample");
    }
}
class Main{
    public static void main(String[] args){
        Foo f = new Foo();
        f.print();
    }
}
```

PHPのNamespaceに似ている
Javaではフォルダとファイル構造でも区別する。おもしろい。

パッケージファイルをコンパイルする時は、パッケージ階層の一番上のディレクトリで実行
-d オプションで　com\se\Foo.class　と　com\se\Main.classが作製される。

##Import
Import宣言をする場合とパッケージ名まで含めた完全なクラス名を指定する場合がある
###Importする側
```java
package com.se;

// 他パッケージを参照するにはImportを使用
import com.se.ren.Foo;

public class Main {
    public static void main(String[] arg){
        Foo f = new Foo();
        f.print();
    }
}
```
###Importされる側
```java
package com.se.ren;

// 外部クラスからアクセスできるのはPublic修飾子が付いたクラスと
public class Foo {
    // Public修飾子が付いたメソッドのみ。
    public void print(){
        System.out.print("Foo#print()");
    }
}
```
ファイル名とPublicクラス名は同一
#クラスライブラリ
便利な機能を提供してれるクラスの集まり

PHPではWebサイト作製に特化したライブラリが多かった。
Composerで管理していたがJavaはどうか…

Pacage化されているので使用する時はImport文を宣言

#一章の感想
メソッド定義が必ずクラス内でなければいけない所がオブジェクト指向っぽい。

JSやPHPではメソッドも変数も好きに宣言できてたが、その分ごちゃごちゃになりやすかった。

必要なパーツはクラス名を付けて管理して使うときはクラスを明示して使う。

##参考文献：Javaプログラマ　Silver SE11．山本道子
SpringBootのWebアプリケーションをHTTPS化する

# はじめに

[IntelliJでJava SpringBootのWebページを作成](https://qiita.com/ykdevs/items/788ceeb0972c48bd1e74)で作成したWebアプリケーションをHTTPS化していきます。

# 手順

## 鍵ファイルの作成

以下のコマンドを実行して、local.keystoreという鍵ファイルを作成します。

```bash
$ keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore local.keystore -validity 3650
キーストアのパスワードを入力してください:  
新規パスワードを再入力してください: 
姓名は何ですか。
  [Unknown]:  localhost
組織単位名は何ですか。
  [Unknown]:  
組織名は何ですか。
  [Unknown]:  ykdevs
都市名または地域名は何ですか。
  [Unknown]:  Yokohama
都道府県名または州名は何ですか。
  [Unknown]:  Kanagawa
この単位に該当する2文字の国コードは何ですか。
  [Unknown]:  JP
CN=localhost, OU=Unknown, O=ykdevs, L=Yokohama, ST=Kanagawa, C=JPでよろしいですか。
  [いいえ]:  はい
```

## application.ymlに鍵ファイルの設定を登録

main/resourcesの配下にapplication.ymlを作成します。

![スクリーンショット 2021-09-05 1.38.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/f35f3a56-aaec-99df-d11f-cd3b3a4a5595.png)

![スクリーンショット 2021-09-05 1.39.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/611be05b-5dc4-3aec-f09f-6eeb6d4ef861.png)

先程作成した鍵ファイルの名前とパスワードを設定します。
パスワードは環境変数から読めるようにしておきます。

```yaml:application.yaml
server:
  port: 8443
  ssl:
    key-store: local.keystore
    key-store-password: "${KEY_STORE_PASSWORD}"
    keyStoreType: PKCS12
    keyAlias: tomcat
```

## IntelliJの環境変数設定

KEY_STORE_PASSWORDはIntelliJのProjectのProfile設定から環境変数として足しておきます。

![スクリーンショット 2021-09-05 1.42.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/fcc2f84e-d298-4a3d-855d-96a2e46b9d3d.png)


![スクリーンショット 2021-09-05 1.43.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/f6b4ab53-5630-a36f-6fb6-2f542b864cfa.png)

![スクリーンショット 2021-09-05 1.44.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/55ef2674-df90-d23d-4249-7e7d969c7cb5.png)

## アプリケーションを起動

セルフサイン証明書のためエラーとして警告されてしまう。

![スクリーンショット 2021-09-05 1.50.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/3e92fdfa-0b36-df0e-7cb9-35f0e6c832f8.png)

証明書をダウンロードする。

![スクリーンショット 2021-09-05 1.51.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/ee54bb25-38e5-b42e-ab8e-1b93dec93fbc.png)

ダウンロードした証明書をダブルクリックしてKeyChainへの追加を行う。

![スクリーンショット 2021-09-05 1.51.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/4b04d4cd-1c07-85bb-a448-12783f02e5b8.png)

登録した証明書を常に信頼する。

![スクリーンショット 2021-09-05 1.52.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/3766f77a-11b9-9eac-2b6c-8808555758f3.png)

ページが表示できるようになる。

![スクリーンショット 2021-09-05 1.56.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/809a0286-555f-49c8-63df-19c950195467.png)
viewで使う<% @posts.each do |post| %>とは

#<% @posts.each do |post| %>とは
![Qiita](https://camo.qiitausercontent.com/b2e1d1d527fd3ca16b92651fca04d51d7291dee5/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3238353131342f65326435623531342d343134372d623562352d343238352d3635353834363035663639332e706e67 "Qiita")
https://qiita.com/s_tatsuki/items/66ffee4519451812a448

controllerから送られてきた@postsの中のレコードを一つずつ取り出してpostという変数に入れる。
この変数はeachメソッドである。
https://teratail.com/questions/255789

#rails each文

変数postsに配列を代入

```
<% posts = [ "文章", "文章"] %>
```


```

<% posts.each do |post| %>
<%= post %>
<% end %>

```
・<% posts.each do |post| %>とはposts(配列).each do |post(変数名)|
・<%= post %>で配列から1つずつ取り出し、表示している
・each文は最後に「end」をつける

結果は下のようになる

```
文章
文章
```

https://terakura-aina.hatenablog.com/entry/2020/09/17/153321
とりあえずYOLOを使って好きな画像で物体検知をしてみたいという方へ

# はじめに

この記事ではできるだけ最短ルートでYOLOの物体検知ロジックを自前の画像に適用してみる方法を示したいと思います。

流れは以下のようになります。

1. Python環境構築
2. YOLOを導入する
3. YOLOを実際に使う

VS Code、pipenv、gitが導入済みの方であれば、作業フォルダ内でターミナルを開いて以下の4つのコマンドを打つと動かせます。

```terminal
git clone https://github.com/ultralytics/yolov5.git
```
```terminal
pipenv install -r requirements.txt
```
```terminal
pipenv shell
```
yoloのフォルダ/data/image/に好きな画像を入れて

```terminal
python detect.py --weights yolov5s.pt --source data/images/画像名
```
これで、yoloのフォルダ/runs/detect/exp内に結果が出力されます。

では順々に見ていきます。

# 1. Python 環境構築

自分の書いた記事で恐縮ですが[こちら](https://qiita.com/APRILSIXTEEN/items/9d8ba8b6e8eb3ee3fb43)をご覧ください。環境がある方は飛ばしてもらって結構です。ただし、以降の説明ではVS Code上でpipenvを使って動作環境の構築をします。


# 2. YOLOを導入する

まずVS Codeを開いて、適当な作業フォルダに移動しましょう。

![スクリーンショット 2021-09-05 002448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/8357d406-ae9d-f4b6-b097-8811206e67cb.png)

今回は[この](https://github.com/ultralytics/yolov5)yoloを動かしてみることにします。開くと下のような感じになっています。codeをクリックしてzipをダウンロードして解凍します。

![スクリーンショット 2021-09-05 003452.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/07f81013-61e7-6638-a31f-47d6917fd119.png)


もちろん、git cloneできる方はそちらでも大丈夫です。

```terminal
git clone https://github.com/ultralytics/yolov5.git
```

出てきたフォルダーの中身を作業フォルダ直下に置いて、本体があるディレクトリ内でterminalを開きましょう。

![スクリーンショット 2021-09-05 004116.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/2431afa8-6875-5c3a-089e-a92479244bb2.png)

yolo用の環境を構築します。以下のようにterminalに打ちましょう。

```terminal
pipenv install -r requirements.txt
```
これでYOLOの導入は終了です。

# 3. YOLOを実際に使う

まずは構築した仮想環境に入りましょう。

```terminal
pipenv shell
```

好きな画像をdata内のimagesというところに入れましょう。busという画像とziadaneという画像がデフォルトで入っているはずです。
私は飼っているワンちゃんの画像で検出を行うことにします。
（モデルのトレーニング抜きでは検出できる物体や生き物の種類に限りがあるので、ご注意ください。）

![スクリーンショット 2021-09-05 010152.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/4aa78caa-3849-cec3-6d20-07d88376958b.png)

以下のコマンドを打ちましょう。画像名を適宜使用されたものに変えてください。

```terminal
python detect.py --weights yolov5s.pt --source data/images/test.jpg
```

Done.が出たら、検出結果はruns/detect/exp内に保存されます。

無事検出されたようです。

![スクリーンショット 2021-09-05 011613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/d2b27d93-d2c7-b89d-1146-5d5e0fa59ab0.png)

# おわりに

まず、唐突に出てきた以下のコマンドについて、少し話しておきます。

```terminal
python detect.py --weights yolov5s.pt --source data/images/test.jpg
```

物体検知を行いたいときはdetect.pyを起動します。--weightsの引数は使うyoloのモデルの重みを指定します。今回使用したのはyolov5ですが一口にyolov5といっても多数のモデルがあります。そのうちのyolov5sというモデルを使用したということです。

このコマンドはtutorial.ipynb内に書いてありますので、参考にしてください。

また、gpuをお持ちでcudaをすでに導入されてる方はpytorchのサイトから対応するcuda用のpytorchライブラリをpipで入れなおすと、gpuを使ってモデルを回すことができます。
IntelliJでJava SpringBootのWebページを作成

# はじめに

[IntelliJでJava SpringBootのプロジェクトを作成](https://qiita.com/ykdevs/items/77e3903ec0bb2aec8845)で作成したアプリケーションにTymeleafを使ってWebページの作成を行います。

# 手順

## build.gradleの編集

spring-boot-starter-thymeleafを追加します。

```gradle:build.gradle
dependencies {
    // SpringBoot
    implementation "org.springframework.boot:spring-boot-starter-web"
    testImplementation "org.springframework.boot:spring-boot-starter-test"
    implementation "org.springframework.boot:spring-boot-starter-thymeleaf"
```

## Controllerを変更

Controllerを変更し、返却値をテンプレート名（index)に変更します。

```
package com.ykdevs.SpringBootTest.app;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class IndexController {

    @GetMapping("/")
    public String index() {
        return "index";
    }
}
```

## ページを作成

src/main/resources/templates にindex.htmlを作成します。

![スクリーンショット 2021-09-05 1.22.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/7a7535bb-116a-9489-12b8-67aefc008cb2.png)

![スクリーンショット 2021-09-05 1.23.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/2c011adb-d3d0-39a6-4682-1cf791235a39.png)

```html:index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>テストページ</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello World!!
</body>
</html>
```

## アプリケーションを起動

![スクリーンショット 2021-09-05 1.25.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/4b43909b-3426-a813-79a6-251156f57309.png)


## 変数を表示できるように変更

引数にModelクラスを指定して、addAttributeで値を指定します。

```
package com.ykdevs.SpringBootTest.app;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class IndexController {

    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("name", "山田　太郎");
        return "index";
    }
}
```

## テンプレートを編集

```html:index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>テストページ</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'こんにちは, ' + ${name} + 'さん!'" />
</body>
</html>
```

## アプリケーションを起動

![スクリーンショット 2021-09-05 1.30.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/b1bfc081-4873-a429-9898-f28f3e8e88ca.png)
[2021Sep] Linux で Bluetooth バージョンを確認する

# はじめに

Bluetooth LE デバイスを使おうかと思った時に、まずは手元の環境が対応しているか調べないとね、ということで、調べました。

調べられたのですけれど、世間の情報が錯綜している感じだったので、調査に使ったツールのソースコードを確認して、情報を確定させようと思った次第です。


# 結論

`hciconfig` で表示される LMP Version は Bluetooth コア仕様バージョンです。


# サンプル

`hciconfig` を使うと下記のような出力が得られます。

```
$ hciconfig -a
hci0:   Type: Primary  Bus: USB
(中略)
        HCI Version: 5.1 (0xa)  Revision: 0x100
        LMP Version: 5.1 (0xa)  Subversion: 0x100
        Manufacturer: Intel Corp. (2)
```

この `LMP Version: 5.1` の `5.1` は、Bluetooth 5.1 であることを示しています。そして `(0xa)` の方が LMP のバージョンが 10 であることを示しています。


# コード

※以下のリンクやコードは bluez 5.61 のものです。

0xa を 5.1 に変換している関数が [lmp_vertostr()](https://github.com/bluez/bluez/blob/5.61/lib/hci.c#L666) です。

```c:lib/hci.c
char *lmp_vertostr(unsigned int ver)
{
	return hci_uint2str(ver_map, ver);
}

static char *hci_uint2str(hci_map *m, unsigned int val)
{
	char *str = malloc(50);
	char *ptr = str;

	if (!str)
		return NULL;

	*ptr = 0;
	while (m->str) {
		if ((unsigned int) m->val == val) {
			ptr += sprintf(ptr, "%s", m->str);
			break;
		}
		m++;
	}
	return str;
}
```

この [ver_map](https://github.com/bluez/bluez/blob/5.61/lib/hci.c#L639) 変数に LMP バージョンと Bluetooth コア仕様バージョンの対応一覧が入っています。

```c:lib/hci.c
/* Version mapping */
static hci_map ver_map[] = {
	{ "1.0b",	0x00 },
	{ "1.1",	0x01 },
	{ "1.2",	0x02 },
	{ "2.0",	0x03 },
	{ "2.1",	0x04 },
	{ "3.0",	0x05 },
	{ "4.0",	0x06 },
	{ "4.1",	0x07 },
	{ "4.2",	0x08 },
	{ "5.0",	0x09 },
	{ "5.1",	0x0a },
	{ "5.2",	0x0b },
	{ NULL }
};
```


# おわりに

Bluetooth バージョン（やプロファイル）が不明瞭なまま販売されてる機器ってありますよね。書いてなかったり、矛盾することが書いてあったり。いろいろと複雑なので仕方ないかと思います。是正しようにも出来なさそう。

とりあえず母艦（ＰＣ本体やらドングルやら）のバージョンが大きければ何とかなる可能性が高いと思います。それを確認する方法が確立できて良かったです。