OmniAICreator/Qiita-1.07M huggingface dataset:
yolov5をWindows10のAnacondaで簡単に試す(coco128.yamlのReaderError対応有り）

yolov5をWindows10のAnacondaで簡単に試したのでメモ。

# 仮想環境の構築

```bash
$ conda create -n py39_yolov5 python=3.9
```

# 仮想環境にログイン
```bash
$ conda activate py39_yolov5
```

# 作業用ディレクトリを作成
これは必要に応じて
```bash
mkdir yolov5_src
cd yolov5_src
```


# yolov5のソースをclone

```bash
$ git clone https://github.com/ultralytics/yolov5

# ディレクトリを移動しておく
$ cd yolov5
```

# 必要なモジュールのインストール

```bash
$ pip install -r requirements.txt
```

# サンプルの認識

```bash
$ python detect.py --source data/images/bus.jpg --conf 0.5 --weights yolov5s.pt
```

## 結果

```bash
detect: weights=['yolov5s.pt'], source=data/images/bus.jpg, data=data\coco128.yaml, imgsz=[640, 640], conf_thres=0.5, iou_thres=0.45, max_det=1000, device=, view_img=False, save_txt=False, save_conf=False, save_crop=False, nosave=False, classes=None, agnostic_nms=False, augment=False, visualize=False, update=False, project=runs\detect, name=exp, exist_ok=False, line_thickness=3, hide_labels=False, hide_conf=False, half=False, dnn=False
YOLOv5  v6.1-105-gd257c75 torch 1.11.0+cpu CPU

Fusing layers...
YOLOv5s summary: 213 layers, 7225885 parameters, 0 gradients
image 1/1 D:\xxx\yolov5\data\images\bus.jpg: 640x480 4 persons, 1 bus, Done. (0.130s)
Speed: 0.0ms pre-process, 130.0ms inference, 1.0ms NMS per image at shape (1, 3, 640, 640)
Results saved to runs\detect\exp5
```
runs\detect\exp5に画像があるとのこと

こんな感じ
![bus.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222012/16007b50-bc07-5974-f31c-a42cb44bb51a.jpeg)


非常に簡単に試せますね
ちなみに、detectの際、sourceを0でカメラからの画像を認識できます

```
python detect.py --source 0
```

\runs\detect\expに、mp4が保存されています

![WS000506.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222012/86aee54a-8412-4ff8-097e-d0c17daf94f8.jpeg)



# coco128.yamlでReaderErrorが発生する場合

```bash
～
\yaml\reader.py", line 143, in check_printable
    raise ReaderError(self.name, position, ord(character),
yaml.reader.ReaderError: unacceptable character #x0080: special characters are not allowed
  in "data\coco128.yaml", position 227
```

- coco128.yamlをutf8からsjisで保存しなおします
    - yolov5\data\coco128.yaml
        - YOLOv5の文字の後にロケットのような文字があればそれを削除して保存
![WS000505.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222012/e8dab90c-0e0c-6a7d-fc45-d28d5b590ec0.jpeg)
Rubyの基本的な構文をまとめてみる

# 初めに
こんにちは！都内でWEB制作を中心に活動しているりょうといいます！
今回はShopifyをきっかけに興味を持ったRubyの簡単な構文について、備忘録的にまとめていきます！

shopifyはRubyをもとにして作られたliquidという言語があるそうで、バックエンド全くの未経験の僕がいきなり始めるにはあまりにも敷居が高い。。。
それならRubyから始めてみよう！！

そんな経緯があってこの記事を書いた次第です！

## この記事の目的
Rubyの基本構文を忘れないうちにアウトプットする！

ではいきましょう。

### テキストの出力
~~~ruby
# コメントアウトは”＃”でできる！
puts "Hello Ruby!"
puts 8
# 出力結果：Hello Ruby! 8
~~~
Rubyのテキスト出力は『puts』
言語ごとに出力方法は違うようですが、個人的にはputs、とても好きですね。
なんかかわいい

また、Rubyにおいては『文字列』と『数値』の連結はできないようです。
これは注意が必要ですね。
~~~ruby
puts "string" + 10
#出力結果: エラー！
~~~

### 変数の宣言
~~~ruby
name "Ryo"
puts name
# 出力結果：Ryo
~~~
let とか　constとかしなくていいんですね。
他の言語を触っているとついつい今がらがってしまいそうです。

### 変数の展開
~~~ruby
name "Ryo"
age 20
puts "Hello! My name is #{name}. I am #{age} years old."
# 出力結果：Hello! My name is Ryo. I am 20 years old.
~~~

### 関数の宣言
~~~ruby
def hello(language)
  return "Hello" + language
end
puts hello("Ruby")
# 出力結果：Hello Ruby
~~~

### 条件分岐
~~~ruby
age = 20
# ageが２０以上の時
if age >= 20
  puts "adult"
# ageが２０より下の時
elsif age < 20
  puts "young"
# age　の中身が空っぽ(=nil)の場合
else
  puts "HI MI TSU"
end
~~~

大事なのは最後の『end』！
波括弧などで挟まない関係で、プログラムにどこからどこまでと教えてあげないといけないんですね。

何度もコンソールにendがないよ〜と指摘されてしまいました、、、
たまには『君のプログラムはすごいね！格好いいね！』とかいってほしいですよね。

はい。
### 配列
~~~ruby
languages = ["Japanese", "English", "Chinese", "Korean"]
puts languages
# 出力結果：Japanese English Chinese Korean (改行されて一つずつ出る)
~~~

### ハッシュ
~~~ruby
#　書き方１ キーを使う
user_01 = {"name" => "Bob", "country" => "America", age => 30}
puts user_01["name"]
#出力結果： Bob

# 書き方２　シンボルを使う
user_02 = {:name => "John", :country => "Canada", :age => 20}
puts user_02[:name]
# 出力結果：　John

# 書き方３　シンボルを省略する
user_03 = {name: "Kim", country: "China", age: 18}
puts user_03[:name]
# 出力結果：Kim
~~~
オブジェクトみたいな形だけどこれはRubyでは『ハッシュ』と言うんですね。
面白いなと思ったところはシンボルを使った書き方、特に<strong>省略しても呼び出す時は『シンボルを用いる』</strong>

というのが新鮮でした。

このシンボルはclassの『インスタンス変数』として似たような形で出てきますし、ハッシュを使う時は基本的に『シンボル』を使うのがいいようです。
何より簡単ですしね。簡単なのはいいことです。

### each文
~~~ruby
users = [
  {name: "Bob", country: "America", age: 30},
  {name: "John", country: "Canada", age: 20},
  {name: "Kim", country: "China", age: 18}
]

users.each do |user|
  puts user[:country]
end
# 出力結果　America Canada China
~~~
ここでも忘れずに『end』！！

## 終わりに

お疲れ様でした！
簡単なアウトプットを行ったのですが、HTMLなどと違い、
The プログラミングという感覚がいいですね！（HTMLももちろん大好きです）

Qiita初投稿ということもあり至らぬ点があったり、見づらいものになってしまっていないか心配ではありますが、
3日坊主にならないように頑張ろうと思います！
VBA Dir関数 ディレクトリの中のファイル名を取得したい



```
filename = Dir(srcPath, vbNormal)
```
```
filename = Dir(取得したいファイル名,オプション的な)
```

Dir関数は第一引数、第二引数どちらも省略可能
第一引数はパスではなく取得したいファイルなので注意
→ パス に "*.*"や"*.txt" などを文字結合してワイルドカードで取得する必要がある

一致するファイル名がないときDir関数は長さ0の文字列""を返す


## 指定したディレクトリの中のファイル名をすべて取得したい場合
```
変数 = Dir("C:\*.*")
Do While 変数 <> ""
    Cells(i,1).Value = 変数
    i = i+1
    変数 = Dir()
Loop
```
上記のようにすれば、指定したディレクトリの中のファイル名を順番に出力できるようになる
クラス、オブジェクトとかそのあたりの話


# はじめに

Qiitaに記事を書くきっかけは就職活動での技術質問にうまく回答できなかったので、学習内容を記録するためのモノです

**【目標】**
・バックエンドエンジニアになる
・基本情報技術者試験に合格する


## オブジェクト指向
オブジェクト指向とは、データとそれに関わるメソッドをまとめてプログラミングをする方法。
細かく説明すると色んな定義があるのですが、それぞれのコードを役割として分けるものと認識しています

メリットとしては
・仕様を変更する時に簡単に変更できる
→ボタンを変更する際などはオブジェクト指向を使うと「もの」だけを変更すれば済む
・不具合が起きた時に把握しやすい
→エラーが出た時にどこでエラーが出たのかを把握しやすくなります


## クラス
データと処理をひとつにまとめる機能。モノ（オブジェクト）の設計書のようなもの

例えば、車の機能を書くとすると
| 特徴 | メソッド |
|:-:|:-:|
| 車種  | 車の名前  |
|  色 |  車の色 |
|  燃費 |  1lで車が走る距離 |
|  最高速度 |  車ごとの最高速度 |

どの車も車種は存在するし、色もバラバラ
だからCarクラスで車種などを設定して、インスタンス化して、それぞれの特徴を具体的に明記する

## インスタンス化
クラスで設計しただけでは実際には動きません、それを具体的にしなければいけません

クラスでの設計図を基にそれを具体化するものです

```java
public class Main {

    public static void main(String[] args) {
        Car Porsche = new Car();   // PorscheというCarクラスのインスタンスを生成

        Porsche.setName("Porsche");//車の名前

        Porsche.setColor("black");//車の色

        Porsche.setFuel(100);//車の燃費

        Porsche.run(120);//車の最高速度
    }

}
```


## ポリモーフィズム
日本語で言うと多様性という意味
オブジェクト指向の一つの概念です。同じ名前のメソッドを用意して複数のクラスで使用できるようにしたものです

それによって同じ名前の操作が呼び出されたときに、生成されたクラスが異なれば、別の操作ができます

この辺りはJavaがしっかりかければ完璧なんだけど、しばらく書いてないもんで。。。


# 最後に

この記事は申し訳ないけど、自分用なのでわかりにくい部分も多いかもしれない
オブジェクト指向は継承やオーバーライドなどたくさんの覚えることがある
明確にわけながら記事にしていきたいと思う
JavaSilver

# Java Silver 攻略記事　その１

みなさんこんにちは、java Silver 攻略記事を書いているゆーたろと申します。今回は、Java Silver攻略するための避けては通れない　String に関する、内容になります。

## String メソッドを使いこなす極意

みなさん、今回、Stringのみ取り上げたのは、何かあるのかなと思ったと思います。
そうなんです、String 型　では他の　int型や　floot型　と異なり、プリミティブ型ではなくオブジェクト型なのです。でも　String ＝”XXX＂; ように表記しますよね、これにはカラクリがあるのです。つまりこのように書くと自動的に String クラスのインスタンスが生成されるようになっているのです。つまり

### String a = new Object ("AAA");
こんなふうに宣言することも可能なのです。

また、java Silver攻略のためには、internメソッド、copyメソッドについても必ず押さえなくてはなりません。

java ではString メソッドを呼び出すとき必ず新しいObjectを生成します。つまり、

### String a= "AAA";
### a.concat("B");
このようなコードがあるとすると、上のコードと下のコードで全く違うobjectが生成されるということなのです。
次にinternメソッドについても解説していきます。
internメソッドでは、元あるオブジェクトと同じString型のObject があった場合それを参照することができます。
String s1 = "AA";
String s2 = si.intern();
s1==s2 
trueとかえるのです。
複数のConfigと実行ファイルに分割したTeratermマクロの作成

## 作成するマクロの要件
ttlファイルを実行後すると接続先の選択画面が出力され、指定したホストに接続する。
接続後は自動的にログファイルを作成する。
また、接続方式は以下のように作成しています。
・Auth：passwd
・Protocol：ssh


## 作成するファイル
・Host-Addr.conf　※接続先情報を記載したConfigファイル
・User-Pass.conf　※接続ユーザ情報を記載したConfigファイル
・Login.ttl　※宛先を選択して接続する実行ファイル


## Teratermマクロの作成
テキストエディタで以下を作成する。
```bash:Host-Addr.conf
strdim HOSTNAME 2
HOSTNAME[0] = '<ホスト名1>'
HOSTNAME[1] = '<ホスト名2>'

strdim HOSTADDR 2
HOSTADDR[0] = '<ホストアドレス1>'
HOSTADDR[1] = '<ホストアドレス2>'
```

```bash:User-Pass.conf
USER = '<ユーザー名>'
PASS = '<パスワード>'
AUTH = '/auth=passwd'
PROTOCOL = '/ssh'

getenv 'USERPROFILE' LOGFOLDER
strconcat LOGFOLDER '\Desctop\'
getdate DATE '%Y%m%d'
strconcat LOGFOLDER DATE
```

```bash:Login.ttl
include 'Host-Addr.conf'
include 'User-Pass.conf'

listbox '接続先を選択してください' '接続先' HOSTNAME
HOSTNUMBER = result

sprintf2 LOGIN '%s %s %s /user=%s /passwd=%s' AUTH PROTOCOL HOSTADDR USER PASS
connect LOGIN

foldersearch LOGFOLDER
if result=0 then
  foldercreate LOGFOLDER
endif
changedir LOGFOLDER

LOGFILE = HOSTADDR[HOSTNUMBER]
strconcat LOGFOLDER '%Y%m%d.log'
logopen LOGFOLDER 0 0
```

## 動作確認
作成したファイルを同じフォルダに格納し、ttlファイルを実行する。
golangでgcpのサービスアカウントjsonを用いた認証

地味にいろいろ大変だったのでメモ

こんな感じで動いた

```golang
package hoge

import (
    "context"
    "os"
    "io/ioutil"

    "golang.org/x/oauth2/google"
    cloudbuild "google.golang.org/api/cloudbuild/v1"
    "google.golang.org/api/option"
)

func initCloudbuildClient() {
    file, err := os.Open("./credentials/your-own-service-account-keyfile.json")
    if err != nil {
        panic(err)
    }
    credentialBytes, err := ioutil.ReadAll(file)
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    credential, err := google.CredentialsFromJSON(ctx, credentialBytes, "https://www.googleapis.com/auth/cloud-platform")
    if err != nil {
        panic(err)
    }

    // 読み込んだサービスアカウントのcredentialで試しにcloudbuildのクライアントを初期化
    if _, err := cloudbuild.NewService(ctx, option.WithCredentials(credential)); err != nil {
        panic(err)
    }
}
```

**追記:** このやり方は認証情報が書かれているjsonファイルを直接保持する手法なので、セキュリティ的にはあまりよろしくない。可能な限りサービスアカウントによる認証か、あるいはWorkload Identity連携を使ったほうがいい。

https://cloud.google.com/blog/ja/products/identity-security/enable-keyless-access-to-gcp-with-workload-identity-federation
Java Silver　攻略その２

java Silver 試験対策　その2

java.lang 以外のパッケージを利用するとき
import文が必要

変数宣言でvarが使えるとき
ローカル変数の初期化、拡張for文、通常for文

a|b
aかbがtrueならtrueを返す　
a^b 
aとbが異なるときtrueを返す
PHP トレイト

# 概要
コードを再利用するための仕組み。

# 例
## 定義
```php
trait Move {
  function fowerd() {
    // 処理
  }

  function backwerd() {
    // 処理
  }
}
```

## 使用
```php
class Human extends Animal  {
  use Move;

  public function walk() {
    $this->fowerd();
  }
}
```

# 詳細
トレイトは単一継承の制約を減らすために作られたもの。
メソッド群を異なるクラス階層にある独立したクラスで再利用できるようにする。
**多重継承**や**mixin**にありがちな問題の回避ができる。

クラスに似ているが、トレイトは単に機能をまとめるだけもの。
**インスタンスを作成することはできない**。

トレイトを活用すれば、継承しなくてもクラスのメンバーに汎用メソッドを追加できるようになる。

# 参考
[PHP: トレイト](https://www.php.net/manual/ja/language.oop5.traits.php)
Salesforce Tableau CRM

# Salesforce Tableau CRM知識
## Tableau CRMの探索開始
### Tableau CRMとは
会社のデータが存在する場所は、Salesforce、ERP、データウェアハウス、ログファイルなどさまざまです。
これらのデータを併せて見ることで、隠れていた重要なインサイトが得られ、ビジネスの見方が変わったり、顧客の全体的なエクスペリエンスが向上したりする可能性があります。
Tableau CRM は、ビジネスユーザの重要な質問に答えるために、これらのすべての情報を組み合わせるという課題を解決します。
デスクトップブラウザでもモバイルデバイスでも、ビジネスを行うために必要な答えをデータから得ることができます。

Tableau CRMは、複数ソースからのデータの接続、そのデータの対話ビューの作成、アプリケーションでのそれらのビューの共有を行うためのクラウドベースのプラットフォームです。Tableau CRM は、ビジネスユーザへのインサイトの配布をより容易にし、ユーザが変化する情報を理解してアクションを実行できるようにします。

補足：Tableau CRMは、AIを搭載したSalesforceの分析プラットフォームです。Salesforceと直接連携し、現状や過去の経緯をもとにした分析だけでなく、将来の結果を予測し、ビジネスにおいて次の行動を考える手助けをします。

### Tableau CRM でできること
データ元：Salesforceデータ、外部データ両方

### Developer Edition組織でTableau CRMを試すとCharrage
１．以下のリンクからTableau CRMが有効なDeveloper Edition組織にサインアップ
　　　https://developer.salesforce.com/promotions/orgs/analytics-de
２．新しい組織をTrailheadに接続します
　　　Playground名をクリックし、[組織を接続]をクリック
　　　ユーザ名とパスワードを入力
　　　アクセスを許可する

## Tableau CRM ホームを知る
### Tableau CRM を開く
アプリケーションランチャー (アプリケーションランチャーアイコン) で、[Analytics Studio] を見つけて選択します。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/2112560c-e759-c8ad-0d6f-0e1128be7422.png)

### 最初の Tableau CRM アプリケーションの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/afc13d6d-8b18-3fe8-598b-dda06dc1dabc.png)
空白のアプリケーションを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/1da6eece-409e-b25a-4537-c98394dd17d3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/78847fbd-17d4-970d-7948-05d01607ff4e.png)
名前：My Exploration
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/4fea869f-19d1-60d3-6bbd-e442c67e06fc.png)
作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/38958ece-2176-24bc-29fd-2c12f6de28f1.png)

説明編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/402a052d-c029-7c65-a12d-a180f744b295.png)
アイコン変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/5dd33e43-3a2b-0e06-eca7-65f98f3aad95.png)
###Tableau CRMホームページをカスタマイズする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/e64c4249-bc52-ee5c-438e-d305460d4d5b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/b80f4224-b6b0-5971-4561-8dc6863553fc.png)
設定可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/5e3d438c-f8af-7432-b06d-f8887b499bc4.png)

### Tableau CRMアプリケーションからのプレゼンテーションの実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/d16e4c60-8589-694d-6e5f-71ffa0178b42.png)
アプリケーションを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/12dd9977-35f3-0dc8-dca1-cbfc4041480b.png)
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/b343f40d-0180-a058-fc65-86b872a78964.png)
※最初にアプリケーションが読み込まれなかった場合は、タブを閉じ、もう一度ログインします
Vueデータバインディングにおける逆ブラックリストcheckboxコンポーネント


# はじめに

　この記事は、配列要素の表示/非表示を指定するブラックリストを、Vueのv-modelデータバインディングされたcheckboxで実現した内容を記す。

# 動機: ホワイトリストに見えるブラックリストcheckbox

　ある共有された現場リストがある。担当ごとに異なるため、人によって無関係な現場が必ず存在する。サーバが現場リストを返却したとして、フロントでは自分に関係のある現場データだけ個別に表示/非表示を指定したい。

　「初期状態が表示」で、かつ「チェックが外された状態を管理」しなければならない。

　ブラックリストは選択したものを除外するためのリストで、ホワイトリストは選択したものを残すためのリストである。「初期状態が表示」なのはホワイトリストのように見えるが、実際にやっていることは除外リストを作っていることになるのが普通の状況と異なる点である。

# Vueデータバインディング
## checkboxのtrue-valueとfalse-value

 現場リストはプロパティprojectsに格納されているとする

```HTML
<ul v-for="p in projects">
  <li>
　　　　　　　　<label><input type="checkbox" true-value="" :false-value="p.id" v-model="excludeList">{{ p.name }}</label>
　　　　</li>
</ul>
```

結果は、excludeListが [] or <font color="red">[null]</font> どゆこと?

## 配列にデータバインディングされる場合に使われる値はvalue属性

 実は、true-value, false-valueが有効なのは、excludeListプロパティが配列**以外の場合なのだった**。
valueが指定されてないのでnullになっていたと。なるほど。これを解決するには次の通り。

```HTML
<ul v-for="(p, i) in projects">
  <li><label><input type="checkbox" true-value="" :false-value="p.id" v-model="excludeList[i]">{{ p.name }}</label></li>
</ul>
```

　ここで、Vueデータバインディングで初期状態をチェック済みにするには真の場合の値が入っていないといけない。具体的には、除外リストexcludeListに初期値として["", "", "", ...]である必要がある。現場リストは可変長で、新しく現場が追加された場合は、excludeListには新しい現場に対応する値が未定義となる。未定義値と空文字列「""」は比較するとfalseだからチェック済みにならない。つまり、新しい現場の初期表示は、チェック未済になってしまう。したがって、最終的にはtrue-valueを未定義値であるundefinedにすれば良い。

```HTML
<ul v-for="(p, i) in projects">
  <li><label><input type="checkbox" :true-value="undefined" :false-value="p.id" v-model="excludeList[i]">{{ p.name }}</label></li>
</ul>
```
技術メモ：ノーコード承認ボタン作成

画面フロー作成（オブジェクトのアクション追加するため）
<font color='red'>※アクションに画面フローしか利用できない</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/6ef46f77-78bd-5cb9-c4cd-0ad73b2397fa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/996c05f6-b614-ecb7-75b7-18500ae22a90.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/48b7922c-3f6c-07b8-8586-66eb92e689f6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/f3f4c33e-cda0-2e59-ab7f-4ffc694bf641.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/3c30d58a-cf0f-88f1-e0a3-dbc218086c5c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/3ac94b2c-7aeb-961f-f702-b5531b720dfc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/e6569222-aad0-0993-2606-ab732916f5be.png)
100日でSQLの達人になる@LeetCode! Day61 <UNION ALLしたテーブルからの集計>

## 602. Friend Requests II: Who Has the Most Friends （問題レベル: Medium）要課金
今日の問題はこれ。
友達申請をした人のIDと友達申請をされた人のIDが一行になったテーブルから最も友達が多い人のIDとその友達の数をリストする問題。

[LeetCode](https://leetcode.com/)の問題に取り組むのが久しぶりだったのでリハビリに選んだ問題。

最終的に提出した回答はこちら。
```:SQL Server
SELECT TOP 1 tbl.id, COUNT(tbl.id) AS num
    FROM (
	    SELECT requester_id AS id FROM requestaccepted
		    UNION ALL
		SELECT accepter_id AS id FROM requestaccepted) tbl
    GROUP BY tbl.id
    ORDER BY COUNT(tbl.id) DESC
```

ポイントは`UNION ALL`したテーブルを集計する方法としました。

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
LaravelのEloquent ORMとは？【個人的なお勉強アウトプット】

## ORMとは？
DBクラスのクエリビルダはメソッドの呼び出しだけでデータベースのアクセスが行えて便利。
しかし、取り出したレコードは連想配列としてまとめたものが更に配列やコレクションとしてまとめられている。これはあまりPHPらしいという感じではない。
テーブルをPHPのクラスのように定義して、レコードをクラスのインスタンスのように扱えたなら、ずいぶんPHPらしくなる。データベースを使うときもPHPとは異なる構造のデータということを意識することもない。データベースとPHPオブジェクト間の橋渡しをしてくれる仕組み、それがORM。

ORMとはObject-Relational-Mapping。
互換性のないデータを自動的に変換して、相互にデータベースをやり取りできるようにする。

Eloquentはテーブルの内容を定義したクラス。
そのテーブル内にあるフィールドをプロパティとして持たせていて、テーブルとフィールドをモデルクラスとインスタンスを扱う感覚で操作できる。

>フィールドはデータベースに存在しているデータの最小単位のことです。 このフィールドの集合体がカラムやレコードであり、テーブルに該当します。 Excelで例えると「セル」を意味する言葉です。
https://it-trend.jp/database/article/89-0061#:~:text=%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AF%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AB%E5%AD%98%E5%9C%A8,%E3%82%92%E6%84%8F%E5%91%B3%E3%81%99%E3%82%8B%E8%A8%80%E8%91%89%E3%81%A7%E3%81%99%E3%80%82
100日でSQLの達人になる@LeetCode! Day60 <CREATE FUNCTION ユーザー定義関数>

## 177. Nth Highest Salary （問題レベル: Medium）課金不要
今日の問題はこれ。
N番目に高いSalaryを表示するユーザー定義関数を作成するという問題。
久しぶりに[LeetCode](https://leetcode.com/)に戻ってきました。

### CREATE FUNCTION
まずは、`CREATE FUNCTION`について学びます。
```:SQL
CREATE FUNCTION ユーザー定義関数名 (引数名)
 RETURNS INT AS
 BEGIN
   -- 実際のプログラムの中身
   RETURN (関数の結果をここで返す)
 END
```
引数は`,`で区切って複数の引数も可能。二行目の`RETURNS`　の後には関数が返す結果のデータタイプを記載する。

最終的に提出した回答はこちら。
```:SQL
CREATE FUNCTION getNthHighestSalary(@N INT) RETURNS INT AS
BEGIN
    RETURN (
        SELECT DISTINCT salary FROM employee
         ORDER BY salary DESC OFFSET @N-1 ROWS FETCH NEXT 1 ROWS ONLY
    );
END
```

ポイントは`CREATE FUNCTION`でユーザー定義関数を使うとした。

`CREATE FUNCTION`はテーブルを結果に出力することも可能だが、今回は値を返す関数のみを学習しました。

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
MLflow tracking 備忘録

# MLflow tracking 概要
機械学習を行う際のハイパーパラメータや評価指標のログをとり、管理を楽にするツール

# 基本となる使い方
以下ではpython APIについての説明をする。
### インストール
```
pip install mlflow
```

### code
```
import mlflow 

# 処理を記述
lr = ~
model = ~
loss = ~

# MLflowでのログ 
with mlflow.sart_run():
   mlflow.log_param('lr', lr)
   mlflow.log_metrics('loss', loss)
   mlflow.pytorch.log_model(model, 'model')
```

### code解説
* with mlflow.start_run():
    * このコードブロック内でログの記述をする
* mlflow.log_param('lr', lr)
    * パラメータの保存(学習率等のハイパラ)
* mlflow.log_metrics('loss', loss)
    * メトリクスの保存(損失関数,精度等)
* mlflow.pytorch.log_model(model, 'loss')
    * モデルの保存

プログラム実行後、ディレクトリ直下のmlruns/以下にログが保存される。
mlruns/のあるディレクトリで

```
mlflow ui
```
とするとローカルサーバーが立ち上がるりurlが表示されるのでアクセス
(デフォルトはhttp://127.0.0.1:5000)
ログとして保存したものをグラフで確認できる。

# MLflow with pytorch lightning
pytorch lightningと組み合わせて使うとさらに簡単にログをとることができる。
(最初にMLflowを使ったのがこちらだったため簡単すぎて逆に仕組みが分かりにくかった)


### Lightning Moduleの定義

```
class Model(pl.LightningModule):
    def __init__():
        ~
    def training_step(self, batch, batch_idx):
        loss=~
        return loss
    def training_epoch_end(self, losses):
        self.log('train_loss', np.mean(losses))
    def ~

```

### code
```
import mlflow
import pytorch_lightning as pl
with mlflow.start_run():
    mlflow.pytorch.autolog()
    model=Model()
    dataloader=~
    trainer=pl.trainer()
    trainer.fit(model,data_loader)
```
* mlflow.pytorch.autolog()
    * Lightning Moduleのログ(この場合train_loss),trainerのパラメータ,モデルの保存が自動で行われる。


# その他便利なメソッド(追記予定)
* mlflow.set_experiment(mlflow_exp_name)
    * 実験に名前を付けられる。(あとで見るとき分かりやすい)
ローカルPC環境にMinicondaとPHi-C仮想環境を構築

Hi-Cデータから動的ゲノム状態を理解するための「[PHi-C](https://github.com/soyashinkai/PHi-C2)」を実行するための計算環境構築を説明します。
すでにPython環境を利用している人は[PHi-C仮想環境を構築](https://qiita.com/soyashinkai/items/49cefc917eb2b1a7c44c#phi-c%E4%BB%AE%E6%83%B3%E7%92%B0%E5%A2%83%E3%82%92%E6%A7%8B%E7%AF%89)から始めてください。
AnacondaによるPython環境の導入は規約上有償の場合もあるので、ここではMinicondaでの構築を説明します。


# MinicondaでPython環境を導入

### Minicondaのダウンロード
以下のMiniconda公式サイトから、使用OSに対応したインストーラーをクリックして、ローカルPCの適当なフォルダに保存する。
https://docs.conda.io/en/latest/miniconda.html

### Minicondaのインストール
ダウンロードしたフォルダ上で端末を開いてインストーラーを実行する。
```
(Linuxの場合) bash Miniconda3-latest-Linux-x86_64.sh
```

```
In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
```
と表示されるのENTERキーを押しましょう。さらに規約を読み進めるためENTERキーを押し続けましょう。
```
Do you accept the license terms? [yes|no]
```
と問われるので
```
yes
```
と入力する。
```
Miniconda3 will now be installed into this location:
/home/USER/miniconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below
```
とインストール先を問われるので、特に気にしなければENTERキーを押す。
```
Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
```
と問われるので
```
yes
```
と入力することで、`~/.bashrc`にPATHが設定される。
改めて端末を開いて
```
python
```
と入力して
```
Python 3.9.7 (default, Sep 16 2021, 13:09:58) 
[GCC 7.5.0] :: Anaconda, Inc. on linux
```
が表示されていればインストール成功です。
一旦、端末を閉じましょう。

Anacondaの有償ライセンス規約に触れないよう、無償のconda-forgeチャンネルを利用するように設定する。
```
conda config --add channels conda-forge
conda config --remove channels defaults
conda config --set channel_priority strict
conda config --show channels
```

# PHi-C仮想環境を構築
PHi-Cのアルゴリズムは主に`numpy`による行列演算で動作しています。その高速化のため、[Intel® Distribution for Python*](https://www.intel.com/content/www/us/en/developer/tools/oneapi/distribution-for-python.html)に基づいた仮想環境を構築しましょう。
MacのM1チップの場合はIntel Math Kernel Libraryが非対応とのことなので、通常の仮想環境を作成してください。
まずは端末を開き、`conda`の更新のため
```
conda update conda
```
を実行します。
```
Proceed ([y]/n)?
```
と問われたら
```
y
```
を入力して更新しましょう。
`phic`仮想環境を構築します：
```
conda create -n phic python=3.12
```
と入力して
```
Proceed ([y]/n)?
```
と問われたら
```
y
```
を入力する。
```
conda info -e
```
で`phic`という仮想環境ができているか確認できます。
次に
```
conda activate phic
```
を入力して`phic`仮想環境に入る。
その後
```
pip install phic
```
と入力し、Hi-Cデータ解析のための[PHi-C2](https://github.com/soyashinkai/PHi-C2)をインストールする。
以上で計算環境構築は終了です。

※[Straw for Python](https://github.com/aidenlab/straw/tree/master/pybind11_python)を`pip install hic-straw`で追加インストールする際にgcc関連のエラーが出る場合があります。エラーの原因はcurl.hなので、Ubuntuの場合は`sudo apt install libcurl4-openssl-dev`でライブラリを事前にインストールしておくとうまくいくはずです。

# PHi-C仮想環境のメンテナンス
```
conda activate phic
```
で仮想環境に入る。
```
pip install -U phic
```
でアップデートする。
【Python】Pythonの型名が覚えられなかったのでメモ

Java, Rubyの実務経験があり、Pythonも覚えてみたいと考えた今日このごろ。
型の種類と名前が全く一致しなかった戒め。

下記のフォーマットで自分用にメモ
###### 大枠のジャンル
```
・Pythonでの呼び方
　・Java, Ruby(他覚えやすかったキーワードなど)での呼び方

※あれば感想など
```

###### 数値
```
・int
　・整数

・float
　・小数点

※散々やってきたので大丈夫。小数点の計算 ^ Javaのときは「BigDicimal」を使わないとダメだぞ！と怒られた記憶がある
```

###### 論理
```
・bool(Yes / No)
　・boolean
```

###### 文字列
```
・str
　・String

※大した違いじゃないからまぁいいんだけど、こういう微妙な違いがあると困るよね。
```

###### シーケンス
```
・list
　・ArrayList(Java)(後から追加できるからArrayListで覚える)

・tuple
　・list(配列)(後から変更できないからlistで覚える)

・range
　・範囲(Rubyならtimeみたいなのがあった気がする。あくまでこれまでの自分の担当領域では使わなかった)

・dict
　・HashMap(Java), Hash(Ruby)

※大幅に異なるので、ここまで違うと清々しい気持ちで潔く覚える気になる
```

###### ついでに変数初期化方法もメモっとく
・list
・tuple
・dict
ここらが特にややこしいので、上記に絞る

``` list.
x = [10, 20, 30, 'テキスト']
Javaの配列と同じ
```
``` tuple.
x = (10, 20, 30, 'テキスト')
()にすればいいだけ。不変の型は好きなので覚える。
```
``` dict.
x = {'a':10, 'b':20, 'c':30, 'd':'テキスト'}
Hashと同じ。名前が違うだけで方法と役割も同じ
```
M1 Mac 初期設定メモ

## zsh から bash に切り替え

bashに切り替える場合
```
% chsh -s /bin/bash
```

zshへ切り替える場合
```
$ chsh -s /bin/zsh
```

※切り替えた際は、ターミナルを再起動

## llコマンドを使えるようにする
↓こちらの記事のとおり設定
<a href="https://qiita.com/miriwo/items/a1bf6917dc630fb6d24f">mac ターミナル で llコマンドを 実行 できるようにする</a>

## Homebrewインストール

brewインストール前にXcodeをインストールし、Xcodeを1回起動してAgreeをする必要がある。
↓それをしてないとbrewインストール時に怒られる
```
You have not agreed to the Xcode license.
Before running the installer again please agree to the license by opening
Xcode.app or running:
  sudo xcodebuild -license
```

<a href="https://brew.sh/">brew</a> のサイトにインストールコマンドがあるのでコピーして、ターミナルで実行する。
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
M1 Macだと、実行結果の最後の方に「Next steps」なるものが表示されるので、ここをコピペして実行する。
```
==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
    echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/ユーザー名/.bash_profile
    eval "$(/opt/homebrew/bin/brew shellenv)"
```
下記を実行し、ターミナル再起動するとbrewが使えるようになっている。
```
$echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/ユーザー名/.bash_profile
```
バージョン確認してbrewが使えること確認
```
$ brew -v
Homebrew 3.4.5
Homebrew/homebrew-core (git revision 81874c83da6; last commit 2022-04-06)
```

## .NET SDKをインストール
```
$brew install --cask dotnet-sdk
```

## Mono をインストール
<a href="https://www.mono-project.com/download/stable/">こちら</a>から最新をダウンロードしてインストール。
（この時は「Download Mono 6.12.0(Visual Studio channel*)」）

## VSCodeの設定を変更

メニュー > Code > 基本設定 > 設定 で下記を設定する
| 設定項目 | 設定値 |
|:-----------|:-----------|
|omnisharp.useGlobalMono| always |
|omnisharp.monoPath|/Library/Frameworks/Mono.framework/Versions/Current|

ここまで設定してVSCodeでエラーが出ずに使用できるようになった。
Macアクティベーションロックが解除できない

## 事象
Macの切り替え時にアクティベーションロックが解除できない

## 対応
切り替え後のMacの
システム環境設定 > Apple ID（右上）を選択。左下に表示される端末から前のMacを削除する。
（おそらく自分のMacの方は削除できないです。）

![スクリーンショット 2022-04-06 15.32.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566476/d44c1683-ad4a-d99e-cb1c-74cc0848493a.png)
Konva.jsでcanvasにカメラ映像を表示する(iPhone実機 Safari対応版)

# デモ

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="qBpxyQr" data-user="qwe001" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/qwe001/pen/qBpxyQr">
  Web Camera Streaming for iPhone by Konva.js</a> by qwe001 (<a href="https://codepen.io/qwe001">@qwe001</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# キモ

[公式デモ](https://konvajs.org/docs/sandbox/Video_On_Canvas.html)では、`document.createElement('video');` を使って、
JavaScriptでvideoタグを生成していましたが、
iPhone実機は、Javascriptで生成したvideoタグでは読み込んでくれないっぽいです。生成タイミングの問題かしら。
Android実機やエミュレータでは表示されたから、iPhone実機で表示されない理由が分からなくてかなり沼りました。
誰かしら同じ問題に直面していると思ったんですが…

```html
<video id="bg_video" autoplay muted playsinline></video>
<div id="app"></div>
```

```javascript
  //var video = document.createElement('video');
  // [IMPORTANT] iPhone実機 Safariはmuted=trueでDOMに設定したvideo要素しか表示できない模様
  var video = document.getElementById('bg_video');
```

# JSでvideoタグを生成した場合、どうなるのか

以下のように、動画の自動再生を許可しないエラーが出ます。
iPhoneの機種次第で、一瞬だけ出たり、まったくでなかったりします。
ユーザーがダイアログで動画を許可するように押しても出ます。
SafariじゃなくてもChromeブラウザでも同様にエラーが出ます。

```
NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
```

上のデモのコメントアウトしてるほうを使って、iPhone実機でWEBインスペクターを使って確認すればわかります。

# 2022.04.10 追記

iOS 12.1 以下だと、カメラ映像が表示されません。
`Invalid constraint`という謎のエラーが出ます。
原因は、デバイス側で対応していない解像度を指定したためです。

解決策は、16:9サイズの縦横の値を明確に指定するか、
いっそのこと解像度を指定しないことです。

```javascript
app.syncCamera = function(video, layer)
{
  var anim = new Konva.Animation(function() {
    // do nothing, animation just need to update the layer
  }, layer);

  var options = {
    audio: false,
    video: {
      //width: app.width,
      height: app.height,
      facingMode: "user" // use front camera
      //facingMode: { exact: "environment" } // use rear camera
    }
  };
};

↓

app.syncCamera = function(video, layer)
{
  var anim = new Konva.Animation(function() {
    // do nothing, animation just need to update the layer
  }, layer);

  var options = {
    audio: false,
    video: {
      facingMode: "user" // use front camera
      //facingMode: { exact: "environment" } // use rear camera
    }
  };
};

・case1
video: {width:960, height: 540}　→ NG

・case2
video: {width: 1280, height: 720}  → OK

・case3
video: true → OK

・case4
video: {width: {min:1280}, height: {min:720}}  → OK
```

1280x720を指定しても、デバイスがその解像度に対応していなければ映像は表示されません。
一番いいのでは、デバイスの使用可能な解像度一覧を取得して、最大サイズを代入する方法でしょうが、いかんせん締め切りまで時間が全くないので上記のやり方で。
誰かもっと良い方法教えて

iOSが嫌いになるのに十分なほど苦しめられました。。
Windows環境だとデバッグめんどうだし。やっぱAndroidが一番よ

# 参考サイト

* https://konvajs.org/docs/sandbox/Video_On_Canvas.html
Laravelで独自のBasic認証を実装する

Basic認証を実装した備忘録として残します。

***

### Basic認証について簡単に。。

・Basic認証にはBase64といエンコード方式が使用されている。
[Base64: wiki](https://ja.wikipedia.org/wiki/Base64)

・Basic認証はセキュアな認証とは 「 **言えない** 」ため、簡易的なアクセス制限以外では使用しないこと。
[Basic認証がなぜ安全とは言えないのか？](https://jp.quora.com/BASIC%E8%AA%8D%E8%A8%BC%E3%81%AF%E3%81%A9%E3%81%AE%E3%81%8F%E3%82%89%E3%81%84%E5%AE%89%E5%85%A8%E3%81%A7%E3%81%99%E3%81%8B)

認証情報に特定のユーザー名とパスワードを設定しておき、入力された値が一致した場合に認証とします。

## 実装

Laravelの基本的なBasic認証の実装方法については、[HTTP基本認証](https://readouble.com/laravel/8.x/ja/authentication.html)に記載されています。

今回はLaravelにデフォルトで用意されている`auth.basic`ミドルウェアを使用せずに
独自のBasic認証用ミドルウェアを作成したいと思います。

まずはartisanコマンドで`BasicAuthenticate`という名前のミドルウェアを作成します。

```
php artisan make:middleware BasicAuthenticate
```

`app/Http/Middleware`に作成された`BasicAuthenticate.php`のコードです

```php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class BasicAuthenticate
{
    // ➀
    public const AUTH_USER_NAME = 'hoge';
    public const AUTH_PASSWORD = 'P@ssword';
    
    public function handle(Request $request, Closure $next)
    {
        // ➁
        if ($request->getUser() !== self::AUTH_USER_NAME || $request->getPassword() !== self::AUTH_PASSWORD) {
            // ➂
            abort(401, headers: [
                header('WWW-Authenticate: Basic realm="Enter username and password."'),
                header('Content-Type: text/plain; charset=utf-8')
            ]);
        }
        // ➃ 
        return $next($request);
    }
}

```
簡潔にするためコメントは省略しています。

コードの説明としましては

➀ まずクラス定数で認証情報の設定を行っています。

➁ メソッドインジェクションをしたRequestクラスの親クラス
　`Symfony\Component\HttpFoundation\Request`クラスが持つ`getUser()`と`getPassword()`を使用し、グローバル変数`$_SERVER`から
　`PHP_AUTH_USER`と`PHP_AUTH_PASSWORD`というキーでそれぞれ入力された値を取得しています。

➂ 取得したユーザー名が設定したユーザー名もしくはパスワードと一致しない場合
　`abort()`メソッドで401(認証エラー)を返し、レスポンスheaderには入力フォームのポップアップを表示するための
　`WWW-Authenticate: Basic realm="message"` を入力しています。

➃ 最初は必ずif文に引っかかりポップアップが表示されます。
　認証に成功した場合は、次のミドルウェアを実行します。
　このreturn文をhandleメソッドに記述していない場合、もしくはif文の中で 記述している場合は
　`Attempt to read property "headers" on null` というエラーが発生してしまうので注意。

認証に成功した場合はリクエストヘッダーのAuthorizationに
認証したユーザー名とパスワードの組み合わせをbase64エンコードした文字列が挿入されます。（[MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Authorization)）
`Authorization: Basic Zm9vOlBAc3N3b3Jk`

あとは作成したミドルウェアをカーネルに登録し、ルーティングに適用するだけです。


```php:app/Http/Kernel.php
protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        // 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'auth.basic' => \App\Http\Middleware\BasicAuthenticate::class, // 追加
        // 以下省略
    ];
```

```php:routes/web.php
Route::middleware('auth.basic')->group(function(){
    Route::get('/', function () {
        return view('welcome');
    });
});
```
Go言語 マップ

## マップ
連想配列に類するデータ構造。
任意のキーと、任意の値を保持することが出来る。

## Code
```Go
func main() {
	// マップの生成
	abcMap := make(map[int]string)
	fmt.Println(abcMap)

	// 値の代入
	abcMap[1] = "A"
	abcMap[2] = "B"
	abcMap[3] = "C"
	fmt.Println(abcMap)

	// リテラルを用いた生成
	abcdeMap := map[int]string{1:"A", 2:"B", 3:"C", 4:"D", 5:"E"}
	fmt.Println(abcdeMap)

	// 要素の参照
	fmt.Println(abcdeMap[1])
	fmt.Println(abcdeMap[5])

	// 要素数
	fmt.Println(len(abcMap))

	// 要素の削除
	delete(abcMap, 2)
	fmt.Println(abcMap)

	// forによる出力
	for i, m := range abcdeMap {
		fmt.Println(strconv.Itoa(i) + " : " + m)
	}
}
```

## Output Sample
~ $ go build map.go 
~ $ ./map
map[]
map[1:A 2:B 3:C]
map[1:A 2:B 3:C 4:D 5:E]
A
E
3
map[1:A 3:C]
1 : A
2 : B
3 : C
4 : D
5 : E

## GitHub
https://github.com/GL-Kageyama/Go_Map
SPIRE v1.2.1, v1.2.2, v.1.2.3変更点調査

_この記事は [Z Lab](https://qiita.com/organizations/zlab) の業務の一環として作成したものです。_

# はじめに

SPIRE v1.2.1, ｖ1.2.2, v1.2.3 の変更内容を紹介します。 
- https://github.com/spiffe/spire/releases/tag/v1.2.1
- https://github.com/spiffe/spire/releases/tag/v1.2.2
- https://github.com/spiffe/spire/releases/tag/v1.2.3

:pencil: がついた文章は、CHANGELOG の公式内容ではなく筆者の補足です。
前バージョン v1.2.0 の変更内容は[こちら](https://qiita.com/Ladicle/items/66f04a773bd6cc5b14dd)を参照してください。

# v1.2.1
## Added 機能追加

- SPIRE Agentの`fetch jwt`コマンドがJSON outputに対応しました [#2650](https://github.com/spiffe/spire/pull/2650)

## Changed 変更点

- OIDC Discovery ProviderがJWKsに`alg`パラメータを含むようになりました。[#2771](https://github.com/spiffe/spire/pull/2771)
- SPIRE Serverはプラグインをグレースフルシャットダウンするようになりました。接続しているRPCが完了するのを待つということです。[#2722](https://github.com/spiffe/spire/pull/2722)
- SPIRE ServerのログにRPCリクエストの認証に関する情報について変更がありました[#2776](https://github.com/spiffe/spire/pull/2776)
  - SPIRE Agentからアクセスを示すログのauthorized_as, authorized_viaの値が期待と違っていたものを修正しました。(Z Labの @hiyosi が 修正しました😎 )
- ドキュメントに小さな改善を実施しました[#2746](https://github.com/spiffe/spire/pull/2746), [#2792](https://github.com/spiffe/spire/pull/2792)

## Fixed バグ修正

- SPIRE Serverはローカルファイルの公開鍵/証明書 が何らかの理由でデータベースに格納できなかった場合、それを検知しローテーションできるようにしました[#2770](https://github.com/spiffe/spire/pull/2770)
- AWS IID node attestorがプロファイルにパスのような構造を含むインスタンスに対しても正しく動作するようになりました。[#2825](https://github.com/spiffe/spire/pull/2825)
- SPIRE Agentがキャッシュの競合によりクラッシュする問題を修正しました。[#2699](https://github.com/spiffe/spire/pull/2699)

# v1.2.2

## Added 機能追加

- `SIGUSR2`シグナルで SPIRE Server, Agentのログファイルをローテーションできるようになりました[#2703](https://github.com/spiffe/spire/pull/2703)
- K8s Workload Registrar CRDが "downstream" ワークロードの登録をサポートしました[#2885](https://github.com/spiffe/spire/pull/2885)
  - これは[Nested SPIREを構成する際](https://qiita.com/hiyosi/items/1bf4d7003bc9b6dcd598#nested-spire%E3%81%A8%E3%81%AF)に利用するものです
- Apple Silicon CPU搭載の macOS向けにSPIREをコンパイルできるようになりました[#2876](https://github.com/spiffe/spire/pull/2876)
- 些細なドキュメントの修正をしました[#2851](https://github.com/spiffe/spire/pull/2851)

## Changed 変更点

- SPIRE ServerのCA証明書の`DigitalSignature` KeyUsage ビットをセットしないようにしました[#2896](https://github.com/spiffe/spire/pull/2896)

## Fixed バグ修正

- SPIRE Serverの`k8sbundle` Notifier pluginが過剰にCPUサイクルを消費する問題を修正しました[#2857](https://github.com/spiffe/spire/pull/2857)

# v1.2.3

- CVE-2022-24675, CVE-2022-28327, CVE-2022-27536 に対応した Go 1.17.9 に更新しました。
Go言語 スライス

## スライス
可変長配列を表す型。
配列と違い、スライスは要素の追加が出来る。

## Code
```Go
func main() {
	// スライスの生成
	tenSlice := make([]int, 10)
	fmt.Println(tenSlice)

	// 要素への代入
	tenSlice[0] = 123
	tenSlice[3] = 456
	tenSlice[6] = 789
	fmt.Println(tenSlice)

	// 値の参照
	fmt.Println(tenSlice[0])
	fmt.Println(tenSlice[1])

	// スライスの要素数
	fmt.Println(len(tenSlice))

	// スライスの容量
	fmt.Println(cap(tenSlice))

	// 簡易スライス式
	fiveSlice := tenSlice[2:7]
	fmt.Println(fiveSlice)

	// 要素の拡張
	elevenSlice := append(tenSlice, 101112)
	fmt.Println(elevenSlice)

	// 完全スライス式
	fullSlice := tenSlice[1:7:8]
	fmt.Println(fullSlice)

	// forによる出力
	for i, s := range tenSlice {
		fmt.Println(strconv.Itoa(i)+" : "+strconv.Itoa(s))
	}
}
```

## Output Sample
~ $ go build slice.go  
~ $ ./slice  
[0 0 0 0 0 0 0 0 0 0]  
[123 0 0 456 0 0 789 0 0 0]  
123  
0  
10  
10  
[0 456 0 0 789]  
[123 0 0 456 0 0 789 0 0 0 101112]  
[0 0 456 0 0 789]  
0 : 123  
1 : 0  
2 : 0  
3 : 456  
4 : 0  
5 : 0  
6 : 789  
7 : 0  
8 : 0  
9 : 0  

## GitHub
https://github.com/GL-Kageyama/Go_Slice
Spring Boot 2.5から出るようになったプレーンアーカイブの抑止

## 現象

Spring Bootを2.4.9から2.5.10へアップデートしてから、
CircleCIのARTIFACTSを見ると、`-plain.jar`や`-plain.war`が出力されるようになった。
特に利用しないので、出力されないようにしたい。

## 解決策

Gradleファイルの、Jar及びWarタスクそれぞれに、下記記述を追加する。

### プレーンアーカイブを出力するタスクを抑止する書き方

#### JAR

```build.gradle
jar {
    enabled = false
}
```

#### WAR

```build.gradle
war {
    enabled = false
}
```

### 実行可能アーカイブに対してプレーンアーカイブを上書きする書き方

#### JAR

```build.gradle
jar {
    enabled = true
    archiveClassifier = ''
}
```

#### WAR

```build.gradle
war {
    enabled = true
    archiveClassifier = ''
}
```

## 参考

https://spring.pleiades.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/

https://zenn.dev/donchan922/articles/ea76614f72b15e
PHPで連続して出現してくる文字列を成敗する方法

# 正規表現??とか意味わからん
やりたいこととして、連続して出現してしまう文字列を一つに統一したかった。
↓みたいなやつを....
```
$fuck = 'test1,,,test2,,,,,test3,,test4,test5,,test6';
```
こうしたい
```
$fuck = 'test1,test2,test3,test4,test5,test6';
```
preg_replaceってやつを使ったらいけた。
[preg_replace](https://www.php.net/manual/ja/function.preg-replace.php)
読んでみたけどなんか難しいことばっかり書いてあるで
なんとか喰らいついて書いてみた

```
$fuck = preg_replace('|,+|', ',', 'test1,,,test2,,,,,test3,,test4,test5,,test6');
```

こんな感じでやればカンマ区切りで配列にできたのでうれしい。

```
$fuck = explode(',', preg_replace('|,+|', ',', 'test1,,,test2,,,,,test3,,test4,test5,,test6'));
```
Mapbox Maps SDK for Android v10 実装メモ ①

## 現在地アイコンを変更する方法
```kotlin
    private fun initLocationComponent() {
        val locationComponentPlugin = binding.mapView.location
        locationComponentPlugin.updateSettings {
            this.enabled = true
            this.locationPuck = LocationPuck2D(
                bearingImage = AppCompatResources.getDrawable(this@MainActivity,
                    R.drawable.ic_baseline_navigation_24
                ),
                shadowImage = AppCompatResources.getDrawable(this@MainActivity,
                    R.drawable.mapbox_user_icon_shadow
                ),
                scaleExpression = interpolate {
                    linear()
                    zoom()
                    stop {
                        literal(0.0)
                        literal(0.6)
                    }
                    stop {
                        literal(20.0)
                        literal(1.0)
                    }
                }.toJson()
            )
        }
    }
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141937/03c67c97-7407-c058-177c-c6eee3de3dec.png" width="400">


## 軌跡を動的に描画する方法

まず、 `loadStyle()` 時に軌跡描画用の `lineLayer` および `geoJsonSource` を追加しておく

```kotlin
        binding.mapView.getMapboxMap().loadStyle(
            styleExtension = style("...") {

                ...

                +geoJsonSource(id = SOURCE_ID_MY_ROUTE)

                +lineLayer(layerId = LAYER_ID_MY_ROUTE, sourceId = SOURCE_ID_MY_ROUTE) {
                    lineCap(LineCap.ROUND)
                    lineJoin(LineJoin.ROUND)
                    lineWidth(6.0)
                    lineColor("#2E98EA")
                }
            }
        )
```

その後、軌跡データを取得したら、先ほど追加した `geoJsonSource` を取り出し、軌跡データを詰め込んだ `Feature` を作成しセットする
 
```kotlin
fun drawRoute() {
    val style = binding.mapView.getMapboxMap().getStyle() ?: return
    val source = style.getSourceAs(SOURCE_ID_MY_ROUTE) as GeoJsonSource? ?: return
    source.feature(Feature.fromGeometry(LineString.fromLngLats(points)))
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141937/5899c31b-8328-90a8-8755-952abc62dc56.png" width="400">

## 参考
https://docs.mapbox.com/android/maps/examples/
【初心者】AWS Wavelengthを使ってみる #6 (SSHリモートポートフォワードを用いたサーバ⇒デバイス方向のアクセス実現)

# 1. 目的
- AWS Wavelengthを利用する際、クライアントとなるデバイス(PC、ラズパイなど)は、スマホやモバイルルータでテザリングし、Wavelength上のサーバと通信する。その際はNAPT経由でのアクセスとなるため、デバイス⇒サーバ方向のセッションは問題なく可能だが、基本的にはサーバ⇒デバイス方向のセッションは不可。
- 「サーバ側からデバイスにアクセスして、デバイス内に蓄積したデータを取得したい」といったニーズ対応へのため、SSHを用いて疑似的にサーバ⇒デバイス方向のセッションを開始できるような設定を確認する。

# 2. やったこと
- Wavelength上にインスタンス(Amazon Linux 2)を作成する。
- PC(Windows11)に、WEBサーバを立てておく。
- PCをスマホでテザリングし、Wavelength上のインスタンスにSSH接続する。
- SSHのリモートポートフォワード機能を用いて、Wavelength上のインスタンスからPCのWEBサーバにhttpアクセスする。

# 3. 構成

![sshポートフォワード構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/758eb3b4-a472-941a-a706-e03fb083aa60.png)

# 4. 手順

## WEBサーバの準備
- Windows上に簡単にWEBサーバが作れるフリーソフト「簡単WEBサーバ」を起動する。利用手順については[「【簡単】Windowsで簡易Webサーバを立ち上げる方法](https://blackbird-blog.com/windows-kantan-webserver)」を参照。
- アプリを起動後、「localhost:80」にhttpアクセスして、WEBサーバのトップ画面が表示可能なことを確認しておく。

## SSH接続
- PCをスマホでテザリングする。
- リモートポートフォワードのオプションを付けて、PCからWavelength上のインスタンスにSSH接続する。
- Windows11標準のSSHコマンドを使用する場合は以下となる。

```
> ssh x.x.x.x -l ec2-user -i [秘密鍵ファイル] -R "localhost:10080:y.y.y.y:80"
```
- 「-R」がリモートポートフォワードの有効化。SSHでの接続先(Wavelength上のインスタンス)のlocalhost:10080にアクセスすると、その通信がPCの80番ポート(tcp)に転送されるようになる。
- 「x.x.x.x」はWavelength上のインスタンスのキャリアIP。「y.y.y.y」はPCのプライベートIP。

## インスタンスからPCのWEBサーバへhttpアクセス
- 上記のSSH接続が存在している状態で、Wavelength上のインスタンスにて、localhost:10080にhttpアクセスすると、その通信がSSHのリモートポートフォワード機能により転送されて、PCのWEBサーバにアクセスすることができる。

```
[ec2-user@ip-10-0-10-201 ~]$ curl http://localhost:10080
<html>
<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">
<head>
<title>KANTAN HTTP Server</title>
</head>
<body bgcolor="deepskyblue" LINK="#FFFFFF" VLINK ="yellow">
<div style=" margin: 5px 5px 5px 5px; font-weight: bold; color: #ffffff; font-size: 20px; width: 300px; filter:Shadow(color=blue)";>
TTFA HTTP Server
</div>
<div class = "folder">
<a href="./KantanWebServer/">KantanWebServer</a>
</div>
</body>
</html>
```

## (参考) TeraTermの場合の設定
- SSHコマンドの代わりに、TeraTermを使用する場合は「SSHポート転送」の項目にて同様の設定が可能。

![sshポートフォワード1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/f74d5a10-c301-aee5-4bcf-c1adcd536f3a.png)

# 5. 所感
- 実際に使うには例えばSSHのセッションの維持（切れたら再接続）などの考慮も必要かもしれないが、まずはベースとなる動作確認はできた。

# 6. 参考サイト
- SSHのポートフォワード設定（「ローカルポートフォワード」と、今回使用した「リモートポートフォワード」の2種類あり）の理解にあたり、参考になったサイトは以下。
    - [SSH Port Forwardingを使ってNAT間で通信するPort Proxy Server in Docker](https://blog.aoirint.com/entry/2021/ssh_proxy_server_docker/)
    - [SSH逆ポートフォワードを利用してFW/NAPT環境ホストに外部からRDP接続する](http://www.prosper2.org/devwiki/index.php?SSH%E9%80%86%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6FW%2FNAPT%E7%92%B0%E5%A2%83%E3%83%9B%E3%82%B9%E3%83%88%E3%81%AB%E5%A4%96%E9%83%A8%E3%81%8B%E3%82%89RDP%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B)
    - [SSHポートフォワード：OpenSSH の -L と -R オプションの動作を図解](https://hrkworks.com/it/windows-tips/openssh/)
Parallels 関連

毎回わからなくなるのでメモ。

# Ubuntu

## Parallels Tools

### インストール

https://download.parallels.com/desktop/v13/docs/ja_JP/Parallels%20Desktop%20User%27s%20Guide/33306.htm

の手順に従う。

```bash
# mount -o exec /dev/cdrom /media/cdrom
mount: /media/cdrom: mount point does not exist.
```

となるので、 `/media/cdrom` を作る。

```bash
# mkdir /media/cdrom
# mount -o exec /dev/cdrom /media/cdrom
mount: /media/cdrom: no medium found on /dev/sr0.
```

`/dev/cdrom` は `/dev/sr0` にリンクされているが、 Paralles Tools のディスクは `sr1` にマップされている様なので、下記のコマンドでマウント。

```bash
# mount -o exec /dev/sr1 /media/cdrom/
mount: /media/cdrom: WARNING: device write-protected, mounted read-only.
```

インストール。

```bash
# cd /media/cdrom/
# ./install
```

### アップデートする

Parallels のウィンドウ上の警告をクリックするだけではアップデートされないので、下記の手順でアップデートする。

https://download.parallels.com/desktop/v13/docs/ja_JP/Parallels%20Desktop%20User%27s%20Guide/33306.htm

```bash
# mount | grep iso9660
/tmp/PrlToolsPackages/prl_tools.iso on /tmp/PrlToolsPackages type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048,iocharset=utf8)
# cd /tmp/PrlToolsPackages/
# ./install
```

で画面上の指示に従ってアップデートで OK。



## 共有されたフォルダの場所

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/d05d3d6e-a158-a70a-fe92-8022e2dae6b8.png)

こんな感じで、カスタムフォルダを共有した場合には、`/media/psf` に現れる。

```bash
$ ls /media/psf
Share
```
PHP 任意の文字、文字数でランダムな文字列を生成する

## コード

```php:random.php
<?php declare(strict_types=1);

class Str
{
    private const CHARS = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_/*+.,!#$%&()~|';

    /**
     * @param int $length
     * @return string
     */
    public static function random(int $length): string
    {
        return substr(str_shuffle(str_repeat(self::CHARS, $length)), 0, $length);
    }
}

echo Str::random(8), PHP_EOL;
echo Str::random(16), PHP_EOL;
echo Str::random(32), PHP_EOL;
```

## 補足1

`CHARS` に指定した文字でランダムな文字列を生成します。
使いたくない文字は取り除いてください。

`str_repeat` を使ってるのは、指定しないと `CHARS` で定義された文字数までの文字列しか作れないことと、同じ文字が2回以上表示されないためです。
https://www.php.net/manual/ja/function.str-repeat.php

`str_shuffle` は暗号学的には安全ではないので、暗号の値としては使えません。
https://www.php.net/manual/ja/function.str-shuffle.php

## 補足2

小文字の英字と数字のみで良い場合はrandom-bytesを使った方が良さそう。

https://qiita.com/ucan-lab/items/06e2ae043fbba4d72843#random-bytes
ブログ編集画面での画像表示

# 目次
[1.元の記事にサムネイルがあるかどうかで分岐する](#1-元の記事にサムネイルがあるかどうかで分岐する)
[2.条件付きレンダリング](#2-条件付きレンダリング)
[3.削除後の動き](#3-削除後の動き)

Laravel + Vue.js を使ったブログ開発で、
**ブログ編集画面に編集前記事のサムネイルを表示させる機能**を作ったのでアウトプットとして記事を書いてみました。

編集画面で、やっぱりサムネイルを別の画像に変更したい！という時ってありますよね！
**編集画面に画像を表示させ、削除して別の画像に変更する**という機能を付けてみました。

# 1. 元の記事にサムネイルがあるかどうかで分岐する

まずは元の記事にサムネイルがあるかどうかで条件分岐します。
**サムネイルがないのに、サムネイル変更ボタンがあったら不自然ですよね**

というわけで、
**サムネイルが無い場合 -> サムネイル選択ボタン**
**サムネイルがある場合 -> サムネイル表示 & サムネイル変更ボタン**
という仕組みにしていきます！

# 2. 条件付きレンダリング

Vue を使用した開発なので、
`v-if` `v-else` を使って書いていきます。

**サムネイルが無い場合**

```javascript:EditComponent.vue
<div
    v-show="reShow"
    v-if="images.length === 0"
    class="form-group"
>
    <label for="exampleFormControlFile1">サムネイル</label>
    <input
        type="file"
        ref="file"
        class="form-control-file"
        id="exampleFormControlFile1"
        name="imageData"
        accept="image/*"
        v-on:change="onFileChange"
    />
</div>
```

**サムネイルがある場合**

```javascript:EditComponent.vue
<div v-else v-show="show" class="form-group">
    <label for="exampleFormControlFile1">サムネイル</label>
    <div v-for="(image, index) of images" :key="index">
        <img
            v-for="(image, index) of images"
            :key="index"
            :src="'/storage/image/' + image.image"
            style="width: 200px"
        />
        <button
            v-show="show"
            @click="resetThumbnail()"
            class="btn btn-outline-danger"
        >
            削除
        </button>
    </div>
</div>
```

`<div v-for="(image, index) of images" :key="index">`

これを使うために、blade 側で 下記を定義します。

```php:edit.blade.php
<edit-component 
    v-bind:post="{{ json_encode($post) }}"
    v-bind:images="{{ ($post->images) }}"
>
</edit-component>
```

これによって、
**サムネイルが無い場合**
![スクリーンショット 2022-04-05 15.40.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2267102/2c3574c3-29a2-0e1e-8567-337bd4389612.png)

**サムネイルがある場合**
![スクリーンショット 2022-04-05 15.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2267102/42ab1f2f-acd9-20f1-fa12-bcac5ad7229b.png)


こんな感じになります！

# 3. 削除後の動き

**ただ、削除後も削除ボタンが残っていては不自然ですよね。**
そのため、
```php5
<button
    v-show="show"
    @click="resetThumbnail()"
    class="btn btn-outline-danger"
>
    削除
</button>
```

**このように `v-show="show"`を使い、
`@click="resetThumbnail()"`が作動したら
画像削除と同時に、`this.show = !this.show;` が走るようにしてあります。**

```javascript:EditComponent.vue
methods: {
    resetThumbnail(images) {
        this.show = !this.show;
        const id = this.images.map((item) => item.id);
    
        axios.delete("/images/" + id).then((res) => {
            console.log(res);
        });
    },
```

こんな感じです！

細かい部分は省略しましたが、大まかな流れを書いてみました！
どこか修正部分ありましたらコメントください...!
mh-z19/CO2センサ/ambient　２

#環境
ラズパイ3B+
センサ：mh-z19C : 非分散型赤外線吸収法方式(NDIR)

# mh-z19
https://pypi.org/project/mh-z19/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/eeab1b91-e17b-352a-898a-50beb74a95ba.png)
 
#参考
https://qiita.com/kanamekun/items/db27968080a1fcf3ad93
https://dev.classmethod.jp/articles/raspberry-pi-4-b-mh-z19b-co2/

#H/W接続

#ライブラリのインストール
sudo pip install mh-z19

確認、versionが表示される。
python -m pip list | grep mh-z19　

# 動作確認
pi@raspberrypi:~ $ sudo python -m mh_z19
{"co2": 949}

# スクリプトで確認
MH-Z19センサーはシリアル通信を利用して読み込むため、デフォルトの設定ではroot権限が必要になるようです。

```
import mh_z19

out = mh_z19.read()
print(out)
```

# グラフ化する ambient

```
sudo pip install git+https://github.com/TakehikoShimojima/ambient-python-lib.git　
```

mh-z19はsudoで実行する必要がある。ambientをsudoで実行するためにはインストール時にsudo pip する必要がある。

# crontab 

sudo crontab -e 
```
* * * * * sudo python /home/pi/mh-z19/testgraph.py
```

#ambientから最新データを取得してGmailでメール送信
https://qiita.com/nonbiri3/items/225319f50e6752aac301

上には書いていないけど、gmailはメールアカウント設定で「セキュリティの低いアプリ～～」を有効にしないと拒絶される。


# データーをmatplotlibでグラフ化する
https://qiita.com/AmbientData/items/0d071503a21706dd9b3e