OmniAICreator/Qiita-1.07M huggingface dataset:
Cloud Strageに保存したmp4ファイルからHandPoseを取得する

## やりたいこと
iOS14以降のCoreMLでは、体や指の特徴点座標データを取得できます。この特徴点座標を機械学習用の入力データとし、Python環境にて推論モデルの構築を目指しています。iOSデバイスで取得するリアルタイム動画のSampleBufferに対しては、HandPoseRequestやBodyPoseRequestすることで特徴点座標を取得できるようにはなりました。しかし、今後（ネット動画なども活用できるようにして）機械学習用に大量の訓練データが欲しいとなると、汎用的な動画ファイルを元データに使えるようにしておく必要があります。動画ファイルをクラウドストレージに保存し、必要なファイルを読み出して特徴点座標のリストを返す仕組みの構築を試みました。

特徴点座標取得に関しての以前の投稿はこちら
[keypointsMultiArrayから機械学習用データを取得する](https://qiita.com/katsuhiro-eqol/items/8cf48a604ee296f2f14d)

## Firebase Cloud Storageに保存した動画の取得方法
Firebase Cloud Storageに保存したmp4ファイルを再生するだけなら、こちらの公式サイトにあるように３つのダウンロード方法があります。
[Apple プラットフォームで Cloud Storage を使用してファイルをダウンロードする](https://firebase.google.com/docs/storage/ios/download-files?hl=ja)

> 1. メモリ内の NSData にダウンロードする
> 2. デバイス上のファイルを表す NSURL にダウンロードする
> 3. オンラインのファイルを表す NSURL を生成する

SampleBufferはlocalURLに対してならば動画ファイルからでも取得できるものの、remoteURLのファイル（オンラインのファイル）に対して取得しようとするとエラーが起きるようです。ネット上に出回る動画に対して簡単に画像情報を取得させないようにする配慮でしょうか。それとも技術的な問題でしょうか。いずれにせよ、ここが今回一番躓いた点です。今回は2の方法を採用しました。

## ローカルファイルの保存場所
mp4ファイルを一時的に保存するローカルURLを以下のように設定します。
~~~swift
let path = "file://" + NSHomeDirectory() + "/tmp/video.mp4"
let localURL = URL(string: path)!
~~~

## ローカルmp4ファイルのSampleBuffer取得
以下のサイトが大変参考になりました。
[iOSで動画ファイルからフレームデータを抽出する実装方法の調査メモ](https://note.com/shu223/n/n4016c10b679c)
これによると
> ・AVAssetReaderを使う
> ・AVAssetImageGeneratorを使う
> ・VTDecompressionSessionを使う

の３つの方法があるとのことですが、情報が多いのは最初の方法でサンプルコードの記載もあります。これに従って、ほとんどコピペでmp4ファイルのサンプルバッファーが取得できるようになります。
~~~swift
import AVFoundation

func setupReader(url: URL){ //ローカルファイルURLを指定
    let avAsset = AVAsset(url: url)
    let avAssetReader = try! AVAssetReader(asset: avAsset)
    guard let videoTrack = avAsset.tracks(withMediaType: AVMediaType.video).last else {return}
        
    let readerOutputSettings: [String: Any] = [kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)]
    let readerOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: readerOutputSettings)
    avAssetReader.add(readerOutput)
    avAssetReader.startReading()
    /*
    以下のwhile節でSampleBufferが1フレームずつ取得される。このSampleBufferに対して必要な
    処理（今回の目的ではHandPoseRequest)を行えばよい。
    */
    while let sampleBuffer = readerOutput.copyNextSampleBuffer() {
        //ここでお望みの処理。今回の目的では特徴点座標を取得するメソッドを適用
    }
}
~~~
これでCloud Storageに保存したmp4ファイルに対して、iOSデバイスでリアルタイムに撮影した動画と同様に手や体の特徴点情報が取得できるようになりました。

## 補足
外部ストレージに保存したmp4ファイルに対して、特徴点情報の取得ができるようになりましたが、鏡像の情報となっていることがわかりました。mp4ファイルにbackカメラかfrontカメラかの情報が欠落して（あるいは取得できていなくて）、frontカメラで撮影したにも関わらずbackカメラ（普通の撮影）として処理したことが原因と思われます。機械学習用訓練データにする際には、この辺りも注意が必要です。handlerのorientationを変更してmirror画像に対しても特徴点情報取得するという方法もありますが、簡便にはx座標だけ(1-x)としたデータセットを用意しても良さそうです。
Laravel コントローラへジャンプ「Laravel Goto」

## TL;DR
「[Laravel Goto](https://marketplace.visualstudio.com/items?itemName=absszero.vscode-laravel-goto)」 でViewとかControllerとかいろんなファイルにジャンプできる。

「Laravel goto Contoroller」では反応せず、動作しなかったたため、こちらを採用。
【UiPath】データテーブルの操作（8）重複行の削除

# はじめに

この投稿は、RPAツール「UiPath」で Datatable から「重複行の削除」をする方法について、個人的にまとめたものです。

UiPathブログ発信チャレンジ の 23日目の記事です。

https://note.com/shumpei_w/n/n19383ce5abb1

「UiPath Friends もくもく会 2022年07月開催 2022-07-23（土）9:00 - 12:00」で書きました。

https://uipath-friends.doorkeeper.jp/events/138756

# データテーブルの操作 シリーズ
DataTable の操作方法について記載した記事が、他にもあります。参考まで。

https://qiita.com/miya_gis/items/6c0dd40378db702bd4b2

https://qiita.com/miya_gis/items/edc3557f3dc7cf6b3cfd

https://qiita.com/miya_gis/items/171b3d12775c95f722c4

https://qiita.com/miya_gis/items/cde6c1eb3c33378d9718

https://qiita.com/miya_gis/items/78dd08bc7f0b5497b83d

https://qiita.com/miya_gis/items/966113ce9732cb112c49

https://qiita.com/miya_gis/items/f45b67fbc2575f0d6d77

# 重複の削除方法

DataTable 内で、以下のように「内容が重複している行」があることがあります。

- パターンA）行単位で重複している（全ての列で内容が同じ）
- パターンB）列の一部で重複している（一部の列で内容が同じ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/1864489c-c9c1-dfb2-fb87-6cf087c4cac9.png)
上記のような重複している行を「削除」する方法は、以下があります。

- 1）「重複行を削除」アクティビティで、重複を削除
- 2）.NET の「DataView」で重複を削除
- 3）Linqの「Distinct」で、重複を削除
- 4）Linqの「GroupBy」で、重複を削除

以下で順に説明します。


# 1）「重複行を削除」アクティビティで、重複を削除

標準アクティビティにある「重複行を削除」アクティビティを使えば、行単位で重複している行を自動で削除できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/f3ae63bc-b68a-6619-7f2c-c14fc6efad70.png)

一部の列だけを対象にしたい場合は、使用できません。
が、多くのケースでは、このアクティビティの使用でOKでしょう。

https://docs.uipath.com/activities/lang-ja/docs/remove-duplicate-rows


# 2）.NET の「DataView」で重複を削除

.NETの機能の「DataView」という便利な「検索・編集・並び替え」機能を使用すると「指定列」で重複を取り除いた形に編集できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/f5c57f84-b93c-dfb6-66ed-083046b8b772.png)
指定しない列は消えてしまいます。
指定しない列を「残したい」場合は、以下に紹介する方法で実施する必要があります。


# 3）Linqの「Distinct」で、重複を削除

「行単位」でユニークに（重複を削除）したいなら、Linqの「Distinct」を使うと簡単です。
引数に「DataRowComparer.Default」を使用すると、データテーブルで重複する行を削除できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/3d1c8ab8-fba4-941f-b5fb-b6167a306895.png)

https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.distinct?view=net-6.0


# 4）Linqの「GroupBy」で、重複を削除

「指定列」でユニークに（重複を削除）したいなら、LinqのGroupByで集計した結果の１つ目を取得すれば出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/12ea7cdd-de54-7560-b225-529b3bdb3086.png)

# 終わりに

以上、DataTableの重複行の削除方法について、でした。なにかの役に立てば幸いです。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
JavaScript　returnとは　処理流れがいまいち分からない人向け

return・・・戻り値、返り値と言われます。

<h1>結果：returnは仲介人</h1>

<h1>returnの処理流れ</h1>

```
       ① var array = [1,2,3,4,5,6,7,8,9,10];

       ④ function abc(arrayOrg) {
            // var _array = arrayOrg.concat();
        ⑤    for (var i =0; i < arrayOrg.length; i++) {
                arrayOrg[i] *= arrayOrg[i];
            }
         ⑥   return arrayOrg;
        }
       ② console.log(array);
       ③ console.log(abc(array));
       ⑦ console.log(array);

出力結果：
(3) [1, 2, 3]
(3) [1, 4, 9]
(3) [1, 4, 9]

```

上記のサンプルコードを用意しました。
Q：returnはどこに処理結果を戻しているでしょうか？
A：console.log(abc(array));　です。

処理順を①〜⑦をコード上に記載しました。

③console.log(abc(array));
→abc関数(配列の数字を倍にする処理)処理結果をコンソール出力しようとしています。
このタイミングで初めて、abc関数が呼ばれます。
④⑤処理で配列の数字を倍にした結果出ました。
その結果を、③ console.log(abc(array));にreturn(返す)します。

つまり、console.logで呼ばれた関数の処理結果を、
console.logに渡す仲介人がreturnということです。

<h2>補足①：例えば、returnをコメントアウトに </h2>


```
       ① var array = [1,2,3,4,5,6,7,8,9,10];

       ④ function abc(arrayOrg) {
            // var _array = arrayOrg.concat();
        ⑤    for (var i =0; i < arrayOrg.length; i++) {
                arrayOrg[i] *= arrayOrg[i];
            }
         ⑥ //  return arrayOrg;
        }
       ② console.log(array);
       ③ console.log(abc(array));
       ⑦ console.log(array);


//出力結果：
(3) [1, 2, 3]
undefined
(3) [1, 4, 9]

```

retrunをコメントアウトにしてみると、③ではabc関数処理が実行されますが、
コンソール出力結果は、undefinedが返ってきます。


<h2>補足②：⑦の出力結果は、意図しない。</h2>
②⑦は、同じ元の配列(①)を呼び出していますが、
⑦は、③と同じ出力結果になっています。

関数型プログラミングでは、元の配列を書き換える行為は良くないです。

concat()を使って、配列のコピーを作成した上で、そのコピー配列の値で処理を実行して
処理結果を③に返しているだけです。そのため、元の配列は書き換えられずに済みました。

```
       ① var array = [1,2,3,4,5,6,7,8,9,10];

       ④ function abc(arrayOrg) {
            var _array = arrayOrg.concat();
        ⑤    for (var i =0; i < _array.length; i++) {
                _array[i] *= _array[i];
            }
         ⑥ //  return _array;
        }
       ② console.log(array);
       ③ console.log(abc(array));
       ⑦ console.log(array);


//出力結果：
(3) [1, 2, 3]
undefined
(3) [1, 4, 9]

```
多階層フォルダ構成の AWS MediaStore のファイルを全部消す方法

# はじめに
アカウント削除の前にMediastoreのファイルを全削除する必要があり
[AWS MediaStore のファイルを全部消す方法](https://qiita.com/tomopyonsama/items/938d702b1052747e6d14) を見つけてためしたところ、 A/B/C/media みたいな階層をもった構造だと削除できませんでした。ということでスクリプト書いたので共有します。

# スクリプト

msdelete.py
```
#!/usr/bin/env python3

import boto3

ms = boto3.client('mediastore')
msd = boto3.client('mediastore-data')

def in_folder(path):
    print(path)
    items = msd.list_items(Path=path)
    for item in items['Items']:
        if item['Type'] == 'FOLDER' :
            in_folder(path+'/'+item['Name'] )
        elif item['Type'] == 'OBJECT' :
            print("delete object ", path+'/'+item['Name'])
            msd.delete_object(Path=path+'/'+item['Name'])
        else :
            print("Unknown", item) 


containers = ms.list_containers()

for container in containers['Containers']:
    msd = boto3.client('mediastore-data',endpoint_url=container['Endpoint'])
    in_folder('')

```

# 使いかた

以下環境変数を設定してください。

```
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION
```

またboto3をpip3でインストールしておいてください。

実行は
```
python3 msdelete.py
```


# 要改善点

- 全部のコンテナ消します。特定のコンテナ消す場合はコード変更してもらえれば。
- ページネーションに対応していないので、大量のファイルの場合は削除できないかもしれません。
- 再帰つかってますがあまりにフォルダ構成が深いと死ぬかもしれません。

# 知見

- 今回フォルダ消してないのですが、オブジェクトを消すとフォルダもきえました。S3とおなじような構成なのでしょうか。
- boto3.clientの引数としてendpoint_urlを指定するってところに気づくまでに2時間無駄にしました。少し賢くなった。
MacでPython｜Jupyter notebookを使う (Mac OS 11/12)

# 目的
MacにPythonの開発環境を構築し，フロントエンドとしてJupter notebookを使う。
データサイエンスや科学技術計算向けに便利なAnacondaを使って管理。

# 環境
Mac OS 11.2.2でテスト済み。 Mac OS 12.x.x でも多分同じ。

# 手順
#### Command Line Tools のインストール　
Xcode+Command Line ToolsはMacでプログラム開発するうえで基本のパッケージ。
まずXcodeをいれていない場合はApp storeからインストールする。
https://apps.apple.com/jp/app/xcode/

ターミナルで以下のコマンドを実行。
```
xcode-select --install
```

#### Homebrewのインストール
Macで動作するパッケージ管理ツール。これも必須。
ターミナルで以下を実行するだけ。 。

```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
参考：https://brew.sh/index_ja

#### Pyenvのインストール
Pythonのバージョン管理を行うためにHomebrewを使ってpyenvを入れます。以下のコマンドを実行。
```
brew install pyenv
```
数分で終わる。以下のコマンドを打ってpyenv 2.3.2のようにバージョンが返ってくれば無事にインストールされている。
```
pyenv -v
```

以下のコマンドを順に入力して，パスを通す。
```
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```

#### Anacondaのインストール
Jupyter notebookに加えて，numpy, scipy, matplotlib, pandas, jupyter notebook .... など，データサイエンスや科学技術計算向けのツールがまとめて入る。
```
pyenv install -l | grep anaconda3
```
でインストール可能なパッケージの一覧を調べて，
```
pyenv install anaconda3-2022.05
pyenv global anaconda3-2022.05
```
を順に実行。2022.05の部分は一覧の中から最新のものを入れればよい。

# Jupyter notebookの起動
ターミナルで
```
jupyter notebook
```
を実行すると立ち上がる。作業ディレクトリに移動してNew > Python3を選ぶ。


以上。
【rails】【rspec】RspecでRails のActionMailer の本文をテストする

## はじめに
未経験からエンジニアに転職して、４ヶ月ほど経つエンジニアです。
RspecでRails のActionMailer のメール本文に期待通りの文章が表示されているかどうか
をテストする方法についてです。


![アイコンバー.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/61a0d3ee-6ff7-f4ca-bb00-622c3c99cfa5.jpeg)

## 結論
~~~ruby
expect(ActionMailer::Base.deliveries.last.html_part.body.to_s).to match("メール本文の内容を書きます")
~~~
上記のように↓を使うとテストできます。
~~~ruby
expext(XXXX.html_part.body.to_s).to match("")
~~~

## 具体例
~~~ruby
# models/send_mail.rb
def send_mail
  # メールを送信する処理
  mail.deliver_now
end

# spec/models/send_mail.rb
 it 'メール本文が適切であること' do
   expect { Model.send_mail }.to change(ActionMailer::Base.deliveries, :count).by(5)
   expect(ActionMailer::Base.deliveries[0].html_part.body.to_s).to match("期待通りのメール本文が表示される")
 end
~~~

## 補足
~~~ruby
expext(XXXX.text_part.body.to_s).to match("")
~~~
↑だとテキスト形式でメールが描画され、その形式でテストすることも可能です。

また、以下のようにすることでメールの送信元、送信先なども検証できます。

~~~ruby
expect(mail.from.first).to eq('fuga.mail@test.com')
expect(mail.to.first).to eq('hoge.mail@test.com')
~~~
【Rails】【Ruby】decoratorでHTMLのタグを作る【初心者】

## はじめに
未経験からエンジニアに転職して、４ヶ月ほど経つエンジニアです。
![アイコンバー.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/61a0d3ee-6ff7-f4ca-bb00-622c3c99cfa5.jpeg)

今回は decorator で HTMのタグを作る方法を手短に紹介します。
rails の gem 'draper' を使用しています。

~~~ruby
def user_status_tag
  h.tag.span class: "[text-weight-bold"] do
      # 描画したい文字や変数、メソッドなど
  end
end
~~~

↓に使いたいHTMLのタグを続ければOKです。↑ではspanを使っています。
~~~ruby
h.tag.HTMLのタグ名
~~~

↓のようにスタイルを当てることもできます。
~~~ruby
class: "[text-weight-bold"]
~~~

## 最後に
今回は decorator で HTML のタグを作る方法を手短に紹介しました。
似たような条件で書き方が分からない方の助けになれば嬉しいです。

decorator には他にも使い所がたくさんあります。
rails の view のみで参照するロジックは decorator を使用すると良いでしょう。
【Git】グローバルな.gitignoreを設定する方法

## `~/.config/git/ignore`を作成する
`~/.config/git/ignore`を作成して`.gitignore`と同様に記述します。
```:~/.config/git/ignore
.DS_Store

```

## ファイルを指定して設定する
任意のファイルを作成して内容を記述します。
```:ターミナル
$ echo .DS_Store > ~/.gitignore_global
```

以下のコマンドを実行するか`~/.gitconfig`に設定を記述します。
```:ターミナル
$ git config --global core.excludesFile ~/.gitignore_global
```

```~/.gitconfig
[core]
  excludesfile = /User/ユーザー名/.gitignore_global
```
承認プロセスで　Insufficient Privileges　が表示される

[Delegate Approver on Approval Process](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000HEQNY)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4984e224-bb61-e6f8-2a57-c925f719eba7.png)


Setup>User Interface>Enable Improved Setup User Interface That should do it.

意味が分からん。
2022/7/23主にITとかセキュリティの記事

脆弱性DB「JVN iPedia」への登録、2Qは2325件 - 前四半期から1455件減
https://www.security-next.com/138308

職員が上長アカウントに不正アクセス、投書から複数発覚 - 登米市
https://www.security-next.com/138338

申込フォームで設定ミス、入力内容が閲覧可能に - シェアリングエコノミー協会
https://www.security-next.com/138297

サイバー脅威の進化と増大--防衛の要はリスクの把握と基本対策の徹底(7/21)
https://japan.zdnet.com/article/35190666/

リケン、ランサムウエアによるサイバー攻撃　サーバーへの不正アクセス確認　復旧には一定時間要する(7/21)
https://www.netdenjd.com/articles/-/270728

自動車セキュリティの技術力を特許データから分析 パナソニックが日米欧でNo.1に(7/21)
https://news.panasonic.com/jp/topics/204758.html

ハーモニック　カード情報2.8万人分流出か、カタログギフト販売サイトで不正アクセス受け(7/21)
https://www.tsuhanshimbun.com/products/article_detail.php?product_id=6336

南房総市にランサムウエア攻撃　小中学校が被害(7/21)
https://www.nikkei.com/article/DGXZQOUC2119H0R20C22A7000000/

ラピッドセブン、調査レポート「ランサムウェアのデータ公開のトレンド」を発表(7/21)
https://securityinsight.jp/news/13-inbrief/5109-220721-1

政府　“国産クラウド”開発へ　経済安保上のリスク回避へ(7/20)
https://news.tv-asahi.co.jp/news_economy/articles/000262251.html

フィッシング詐欺に使われるブランド2位はMicrosoft、不動の1位は？(7/21)
https://news.mynavi.jp/techplus/article/20220721-2403804/

Web3.0時代の個人情報管理の新常識！「SSI」「DID」を知っていますか？(7/21)
https://liginc.co.jp/599123

WordPressプラグイン「Modern WPBakery」を削除せよ、侵入は時間の問題(7/20)
https://news.mynavi.jp/techplus/article/20220720-2403330/

PayPalユーザーを標的としたフィッシングキャンペーンに注意(7/21)
https://news.mynavi.jp/techplus/article/20220721-2403618/

生体情報を活用したMFAにより、安全で便利なパスワードレス認証を実現(7/21)
https://cloud.watch.impress.co.jp/docs/topic/special/1423970.html

Google Playストア、検出機能回避しマルウェアアプリが混入(7/21)
https://news.mynavi.jp/techplus/article/20220721-2403575/

「Microsoft Teams」で障害 ～OfficeやSharePointなどの関連サービスにも影響拡大【17時10分追記】(7/21)
https://news.yahoo.co.jp/articles/ed2663c0b8a6886833addb32b6aa06a9a31c12fc

マイクロソフト「Teams」などで障害発生--一部で回復も(7/21)
https://japan.cnet.com/article/35190758/

Teamsの障害が「ほとんど回復」、原因はストレージの接続不良(7/21)
https://xtech.nikkei.com/atcl/nxt/news/18/13351/

Microsoft「Teamsのサービス、大部分が回復」と公表(7/21)
https://www.nikkei.com/article/DGXZQOUC2129G0R20C22A7000000/

金融活動作業部会（FATF）による「金融犯罪との闘いにおける提携：データ保護、テクノロジー、民間セクターの情報共有に関する報告書」の公表について(7/21)
https://www.fsa.go.jp/inter/etc/20220721/20220721.html

ソフトウェア等の脆弱性関連情報に関する届出状況[2022年第2四半期（4月～6月）](7/21)
https://www.ipa.go.jp/security/vuln/report/vuln2022q2.html

『コミュニティ拡大のカギは』イーサリアム財団 宮口あや氏とデジガレ伊藤穰一氏が対談(7/21)
https://coinpost.jp/?p=369063

マイクロソフトのサービス「ビング」　１９省庁と自治体検索で偽サイト表示　群馬・前橋、高崎両市も(7/21)
https://www.jomo-news.co.jp/articles/-/148219

日本のメタバースが抱える課題とは？　弁護士と官僚、それぞれの視点からみた「メタバースにおける法整備の重要性」(7/21)
https://realsound.jp/tech/2022/07/post-1079128.html

GoogleとOracleのCloudサーバー、英国の記録的な暑さで冷却障害に(7/21)
https://www.zaikei.co.jp/article/20220721/681990.html

NTTコムのホスティングサービスで障害、約20時間後に完全復旧(7/21)
https://xtech.nikkei.com/atcl/nxt/news/18/13350/

イーサリアムL2「zkSync2.0」、100日以内にメインネット予定(7/21)
https://www.neweconomy.jp/posts/246195

すぐに始められる！GitHubコミュニケーションでチームの情報共有コストを下げよう(7/21)
https://moneyforward.com/engineers_blog/2022/07/21/start-with-github-discussion/

尼崎市のUSB紛失事件を機に「ニセ名刺」問題を考えた、本当に悪い奴は誰だ(7/21)
https://business.nikkei.com/atcl/gen/19/00322/070600052/

NRIセキュア、セキュリティ業務の漏れ・偏り・無駄を評価するサービス提供(7/21)
https://gunosy.com/articles/eQvll

児童見守りの行政データ活用に国際ルール抵触の恐れ、「OECD原則」を巡り議論噴出(7/22)
https://xtech.nikkei.com/atcl/nxt/column/18/00989/071900090/
画像の枚数に応じてレイアウトを自動で変形するJavaScript処理

# この記事について
先日、インターンでの課題としてライブラリを作成しました。記事に残しておくと身になるという話をよく聞くので、作成した過程を書き残したいと思います。
筆者は駆け出しでありJavaScriptは勉強したてなので、アドバイスなどがあればお願いします！

# ライブラリの概要
* htmlのul要素に.js-photo-galleryというクラス名を付けるとli要素の画像がhttps://master.dxgxkh02xtdew.amplifyapp.com のようなレイアウトに自動で整形される
* 同じ枚数でも、画像のアスペクト比に応じて異なるレイアウトになる
* レイアウトはcssのGrid Layoutを使用する

# レイアウトの作り方

## css適用
下のサイトを参考にレイアウトを作成しました。
まず、好きな割合で区切りを決めると境目に番号が割り振られます（縦の線は左、横の線は上から1）。大きさをどの境からどの境までかで指定することで好きな形にできるという使い方でした。

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout

レイアウトの枠組み
```styles.css
ul.js-photo-gallery {
    margin-left: 0;
    padding-left: 0;
    width: 500px;
    height: 500px;
    grid-gap: var(--gridgap-size);
    list-style: none;
}

/*横長の2枚の場合*/
.layout-2-horizontal {
    display: grid;
    grid-template-rows: 50% 50%;
}
```
クラス名は`layout-枚数-形`としました。
分割の指定方法として%とfrがありますが、形が崩れてしまうときがあったので変に使い分けています。

## javascriptの処理
おおまかな処理の流れは
`js-photo-gallery`クラスのエレメントを取得→画像の形、枚数を取得→合うクラス名を付与

```index.js
function run () {
  const elements = document.getElementsByClassName("js-photo-gallery");
  const elementsArray = Array.from(elements);
  elementsArray.forEach((elem) => {
    const shape = getImageShape(elem);
    var numberOfImages = elem.childElementCount;

    if (numberOfImages >= 6) {
      const li = elem.getElementsByTagName("li");
      setOverlayPosition(li);
      displayOverflowNumbers(elem, li);
      setHideClass(li);
      numberOfImages = "more";
    }

    elem.classList.add(`layout-${numberOfImages}-${shape}`);
    gridGapSize("5px");
  });
}
```

画像の形はただwidthとheightを比べるだけです。
```index.js
function getImageShape(elem) {
    const imgs = elem.getElementsByTagName("img");
    if (imgs[0].width > imgs[0].height) {
      return shape = "horizontal";
    } else if (imgs[0].width < imgs[0].height) {
      return shape = "vertical";
    } else {
      return shape = "square";
    }
}
```

6枚以上の場合は下図のようにしたかったため、オーバーレイの処理を行っています。
<img width="350" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606536/54ab289a-46b8-d515-76e2-47788c8ec225.png">
```index.js
/*5番目の画像に重ねるようにする*/
function setOverlayPosition(li) {
    li[4].classList.add("position");
    const newElement = document.createElement("div");
    newElement.classList.add("overlay");
    const parentLi = li[4];
    parentLi.insertBefore(newElement, parentLi.firstChild);
}
/*何枚の画像があるか見やすくする*/
function displayOverflowNumbers(elem, li) {
    const numberTextElement = document.createElement("p");
    const numberContent = document.createTextNode("+" + (li.length - 4));
    numberTextElement.appendChild(numberContent);
    numberTextElement.classList.add("more");

    const parentDiv = elem.getElementsByClassName("overlay");
    parentDiv[0].appendChild(numberTextElement);
}
/*6番目以降の画像は見えないようにする*/
function setHideClass(li) {
    liArray = Array.from(li);
    liArray.forEach((v, i) => {
        if (i >= 5) {
            v.classList.add("hide");
        }
    });
}
```

# 反省
DOMに依存しすぎている、アスペクト比の異なる複数の画像の場合に対応できないなど、完成度はまだまだ実用的ではないですが、一通り機能が完成してよかったです。
分からなくなったときに、検索能力の乏しさや自分の質問の曖昧さを感じたので、そういった基礎的な能力を身に付けたいと思いました。
[Django] request オブジェクトの中身が見たい

## requestの中身を見たい
Djangoで開発中に `request` の中身を見たいと思ったことはありませんか？ 僕はあります。
`django-debug-toolbar` 使えと言われたらそれまでなんですが、コードベースで見れるならその方がいいですよね。

## 方法

```python:views.py
def index(request)
    print(request.__dict__)
    # または
    print(vars(request))
```

## 出力
```bash:bash
{
    '_request': <ASGIRequest: PATCH'/api/notifications/6/'>,
    'parsers': [<rest_framework.parsers.JSONParser object at 0x10ef9e620>,
    <rest_framework.parsers.FormParser object at 0x10ef9e320>,
    <rest_framework.parsers.MultiPartParser object at 0x10ef9de70>],
    'authenticators': [<rest_framework.authentication.TokenAuthentication object at 0x10ef9ea10>,
    <rest_framework.authentication.SessionAuthentication object at 0x10ef9ca90>],
    'negotiator': <rest_framework.negotiation.DefaultContentNegotiation object at 0x10ef9c400>,
    'parser_context': {'view': <admin_api.views.NotificationViewSet object at 0x10ef9d8d0>,
    'args': (),
    'kwargs': {'pk': '6'},
    'request': <rest_framework.request.Request: PATCH '/api/notifications/6/'>,
    'encoding': 'utf-8'},
    '_data': {'send_time': '2022-07-26T17:22:00.000Z',
    'contents': '2123123',
    'country': [2]},
    '_files': <MultiValueDict: {}>,
    '_full_data': {'send_time': '2022-07-26T17:22:00.000Z',
    'contents': '2123123',
    'country': [2]},
    '_content_type': <class 'rest_framework.request.Empty'>,
    '_stream': <ASGIRequest: PATCH '/api/notifications/6/'>,
    'accepted_renderer': <game_api.renderers.UTF8JSONRenderer object at 0x10ef9d840>,
    'accepted_media_type': 'application/json',
    'version': None,
    'versioning_scheme': None,
    '_authenticator': <rest_framework.authentication.TokenAuthentication object at 0x10ef9ea10>,
    '_user': <User: foo@example.com>,
    '_auth': <Token: 4943996d8d43c13b6ccb12ac6da0e148a5>
}

```

それぞれの意味は [公式ドキュメント Request and response objects](https://docs.djangoproject.com/en/4.0/ref/request-response/) を参考にしてください。
HTMLの基礎知識（YoutubeのURL 投稿と反映）

みなさん今日もプログラミングの学習お疲れ様です！！

今回はYoutudeの動画を投稿し、それを詳細ページに反映する機能を実装していきます！！:sunny:

<dt>Step1:モデルを作成</dt>

```ruby:ターミナル
rails generate migration AddYoutubeUrlToTweets youtube_url:string
```

```ruby:ターミナル
rails db:migrate
```

<dt>Step2:コントローラーの追加</dt>

```ruby:tweets_controller.rb
 private
    def tweet_params
        params.require(:tweet).permit(:youtube_url)
    end
```

<dt>Step3:newにyoutude_urlのデータを追加</dt>


```ruby:tweets_new.html.erb
<%= form_for @モデル名 do |f| %>
省略
  <%= f.label :youtube_url %>
    <%= f.text_field :youtube_url, :size => 140 %>
省略
<% end %>
```

<dt>Step4: helperにメソッドの定義</dt>

```ruby:tweets_helper.erb
module TweetsHelper
  def find_youtube_url(youtube_url)
    if youtube_url[0..16] == "https://youtu.be/"
      return youtube_url[17..27]
      # "https://youtu.be/WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする
    else
      return youtube_url[32..42]
      # "https://www.youtube.com/watch?v=WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする
    end
  end
end
```

<dt>Step5:Viewにyoutude_urlを反映(show)</dt>

```ruby:tweets_show.html.erb
<iframe width="560" height="315" src="https://www.youtube.com/embed/<%= find_youtube_url(@tweet.youtube_url) %>" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
```

<dt>Step6:Viewにyoutude_urlを反映(index)</dt>

```ruby:tweets_show.html.erb
<% @モデル名.each do |t| %>
    <div class="tweet">
      省略
      <iframe width="560" height="315" src="https://www.youtube.com/embed/<%= find_youtube_url(t.youtube_url) %>" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
      省略
    </div>
  <% end %>

```

<dt>Step7:確認！！</dt>

![スクリーンショット (63).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/679bc098-865c-3495-7b50-c63814fc826f.png)

以上です！！！
ABC228 A Dif:55 『AtCoder ABC226～250 ARC129～139 灰・茶・緑問題 超詳細解説』サンプル

この記事は **『AtCoder ABC226～250 ARC129～139 灰・茶・緑問題 超詳細解説』** のサンプルです。

値段：**300円(Kindle Unlimited対象)**
**【kindle】**
https://www.amazon.co.jp/dp/B0B7G13QMS

**【booth(pdf)】**
https://sano192.booth.pm/items/4025713

**ARC129～139の部分のみ抜粋した廉価版** もあります。
値段：**200円(Kindle Unlimited対象)**
**【kindle】**
https://www.amazon.co.jp/dp/B0B7G337YF

**【booth(pdf)】**
https://sano192.booth.pm/items/4025737

**【サンプル一覧】**
ABC228 A：https://qiita.com/sano192/private/f8f09ea769f2414a5733
ABC249 B：https://qiita.com/sano192/private/daf74d7c31bc698d33ce
ABC226 C：https://qiita.com/sano192/private/3aa26373ca6cfcb3ef0f
ABC246 D：https://qiita.com/sano192/private/a22aadde99945bfb01a8

「ものすごく丁寧でわかりやすいABC解説」シリーズをベースに【キーワード】【どう考える？】【別解】を追加し、【解説】と【実装のコツ】を分けることでよりわかりやすく、具体例や図もより豊富に全ての問題の解説を書き直しました！
さらにQiitaでは公開していないARC129～139の灰・茶・緑問題も解説しています！
緑を目指す灰・茶コーダーの方へおすすめ！

https://qiita.com/sano192/items/54accd04df62242b70f0

https://atcoder.jp/contests/abc228/tasks/abc228_a

**【キーワード】**
なし

**【どう考える？】**
S,Tにてきとうな数字をいれて考えるとS<Tの場合とT<Sの場合を分けるべきだということに気づくだろう。
それぞれの場合についてどのパターンが「Yes」となるか考え、ifで条件分岐するだけ。

**【解説】**
S<Tの場合とT<Sの場合でそれぞれ考える。

(1)S<T
S≤X<T→「Yes」
上記以外→「No」

～例～
S：4
T：20
4≤X<20ならば「Yes」

(2)T<S
S≤XまたはX<T→「Yes」
上記以外→「No」

～例～
S：20
T：4
20≤XまたはX<4ならば「Yes」

**【実装のコツ】**
入力の受け取り、出力がわからない人はまず巻末にある「入力と出力」を読んでほしい。

**\<ifの書き方>**
if 条件:
　　処理内容
else:
　　処理内容

ifは「条件を満たせば」→「処理内容を行う」という意味。コードの上から順に処理を行っていく。
elseは「そうでなければ」すなわち「ifの条件が満たされなければ」→「処理内容を行う」という意味。

**\<条件　または>**
条件が「または」で繋がる場合はorを使う。
S≤XまたはX<T
if X<T or S<=X:

**\<文字列の出力>**
文字を出力する際は
print(”文字”)
というようにダブルクォーテーションをつける。
pythonにこれは変数ではなく、文字であると伝えるため。
・正　print(“Yes”)
・誤　print(Yes)

**【提出】**

```python:　
# 入力の受け取り
S,T,X=map(int,input().split())

# S<Tならば
if S<T:
    # S<=X<Tなら
    if S<=X<T:
        # 「Yes」を出力
        print("Yes")
    # そうでなければ
    else:
        # 「No」を出力
        print("No")

# そうでなければ(T<Sならば)
else:
    # X<TまたはS<=Xならば
    if X<T or S<=X:
        # 「Yes」を出力
        print("Yes")
    # そうでなければ
    else:
        # 「No」を出力
        print("No")
```
APIとは

## APIとは？

いきなりだが、最近「ユニコーンに乗って」というドラマが面白くて毎週観ている。

毎週火曜日、時間になったらソファーに座ってテレビをつけ、リモコンでテレビをドラマのチャンネルにする。こうしてことで好きなドラマを観ることができる。
この過程を絵で表現してみると以下のよう。
![tv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/cacae2c4-e678-e853-f392-82433715530c.png)

ここでリモコンやテレビは人間と放送局をつないでくれる。
**API**はまさにリモコンやテレビのような役をする。

---

本題に戻り、話しましょう。

Webサービスには、会員登録、ログイン、イメージやつぶやきの投稿、商品購入、写真や動画の視聴などいろいろな機能があります。
このような人のいろんな要求を受けて処理してくれるのがサーバーであるが、人間の言語とコンピュータの言語は異なるため、APIが中間で対話のルールを定め、相互間の要求応答（Request and Response）を制御してくれる。
つまり、API（Application Programming Interface）は、アプリケーションをプログラミングするために使用される約束だと定義できる。

<br><br><br>

#### REST(Representational State Transfer) API

このようにAPIはプログラミングで不可欠な役割を果たしたが、共通する規則がなかったため、ユーザーがそれぞれ作成した規則に頼るしかなかった。そこで共通規則の必要により登場したのがRESTである。
REST APIの最大の特徴は、「Represent」が「表現する」という意味であるかのように要求する内容を見るだけで、クライアントが何を要求しているのか直感的に理解できる。下のURIのように。
https://www.nikkansports.com/baseball/news/

そして、そういうREST規約をよく守って作られたAPIをRESTful APIという。

<br>

###### REST APIを設計する時重要な2つの項目
- URIを介してアクセスしたいリソースがどこにあるかを表さないといけない
- リソースへの要求はHTTPメソッドでする　

###### RESTの構成要素

- リソース（資源）
クライアントがサーバーに要求するもので、Webサーバーが管理する全てのことを表す。固有のアドレスを指定し、識別できる。
- メソッド（行為）
リソースにアクセスするためHTTPメソッドを使用する。もっといろいろあるが、よく使われるメソッドは、以下の通り。
<dd>

| メソッド名 | CRUDで言うと |実例|
|:-:|:-:|:-:|
| POST | Create  |掲示板に投稿|
|  GET | Read  |投稿を読む|
|  PUT | Update  |投稿の編集|
| DELETE  | Delete  |投稿を削除|
</dd>
<dd>※POSTは複数のリソースに対しても実行できる反面、PUTは1つのリソースに対してのみ実行できる。</dd>

- Representation（表現） 
クライアントがメソッドでリソースを要求すると、サーバーはそれを処理し、応答する過程。
AWSCDKVERSION2の対応

今回AWS CDKVERSION2をつかうにあたりはまったところがあったのでそれを記事にしてみました。
今回はecsでALBを使いブラウザ上に表示させることをやってみようと思います。
aws configureは設定済みと考えます。

nodeのインストール

```
curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash -
sudo yum install -y nodejs
```

cdkのインストール 

```
 mkdir hello-cdk
 cd hello-cdk
 sudo npm install -g aws-cdk
 cdk init app --language typescript
``` 
Verison2で大事なのはCDK.jsonとpackage.jsonの編集です。

CDK.json
```
{
  "app": "npx ts-node --prefer-ts-exts bin/hello-cdk.ts",
    "versionReporting": false,
  "context": {
    "systemName": "hello-cdk",
    "envType": "stg",
    "keyName": ""
  }
}
```

package.json
```
{
  "name": "hello-cdk",
  "version": "0.1.0",
  "bin": {
    "hello-cdk": "bin/hello-cdk.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "devDependencies": {
    "@types/jest": "^26.0.23",
    "@types/node": "10.17.27",
    "aws-cdk-lib": "^2.0.0",
    "constructs": "^10.0.0",
    "jest": "^26.6.3",
    "ts-jest": "^26.2.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "aws-cdk-lib": "^2.0.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.16"
  },
  "jest": {
    "moduleFileExtensions": [
      "js"
    ]
  }
}
```

上記のように直した後

```
cdk bootstrap aws://<アカウント番号>/<リージョン名>
npm install
```

プログラムの部分。

```
import { Stack, StackProps } from 'aws-cdk-lib';
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';


export class HelloCdkStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
 
    new ecsp.ApplicationLoadBalancedFargateService(this, 'MyWebServer', {
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
      },
      publicLoadBalancer: true
    });
  }
}
```

```
プログラミングで大切な部分は
import * as ecs from '@aws-cdk-lib/aws-ecs';---→import * as ecs from 'aws-cdk-lib/aws-ecs';
に変更すること@を除くことです。
後古いバージョンだと@aws-cdkがついていると思いますが、それをすべてaws-cdk-libに書き換えてください。
```

これでVERSION2のほとんどは動くと思います。
下記にgithub載せます。
[github](https://github.com/gichioka/cdkecs) 

参考資料

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/tutorial-ecs-web-server-cdk.html

https://dev.classmethod.jp/articles/cdk-practice-26-version-2/
Linuxについて３（自分用メモ

ファイル名は大文字と小文字が区別される
アルファベット・数字・一部記号が使用可
ドットで始まる名前のファイルは表示されない
ファイルには通常ファイル、ディレクトリ、リンクファイル、特殊ファイルがある


・絶対パス
ルートディレクトリを基点として表す方法
・相対パス
カレントディレクトリを基点とする方法

カレントディレクトリはpwdコマンドで確認できる

パスの記述で使用可能な記号
.. １つ上のディレクトリ
~ ホームディレクトリ

cat ［ファイル名］
ファイルの内容を表示

less ［ファイル名］
テキストファイルの内容を１ページずつ表示。catコマンドでは１画面に収まりきらない大きなファイルを表示すると、ファイル先頭がスクロールされてしまい見ることができない。

cd　［-］　［移動先ディレクトリ］
カレントディレクトリの移動
オプションなしで実行するとcdコマンドを実行したユーザーのホームディレクトリに移動。
「cd -」で１つ前の作業ディレクトリに戻る。

ディレクトリの指定に、パス記述で使用する「..」や「~」も使用できる。


ファイルはiノードで管理されていて、ファイルの属性情報が格納されている。
iノード番号とファイル名の対応付をリンクという。
Linuxでは１つのiノードに複数のファイル名をリンクさせることができる。これをハードリンクという。ハードリンクを使うと１つのファイルに複数のファイル名でアクセスできる。

ハードリンク作成
ln 元のファイル　作成するリンクファイル

ファイルに別名をつける仕組みをシンボリックファイルという。lnコマンドに-sをつける。
ln -s 元のファイル　作成するリンクファイル

※元のファイルを削除した場合、ハードリンクファイルは今まで通り表示されるが、シンボリックファイルはエラーになってしまう。シンボリックファイルはあくまでもファイルへのポインタ（ファイルの参照先）にすぎない。
Firebase cloud functions(storageトリガ)をデプロイ

Firebase cloud functionsで
・storageにファイル格納されたことをトリガにして動く
・そのファイルを読み込んで中身をdatastoreに格納
したときのメモ

※補足
GCPのcloud functionsではありません。GCPのcloud functionsは、コンソールは共通なのに微妙に実装方法やデプロイ方法が違います。混乱のもとだ。。

## 前提
Firebaseのプロジェクト作成

## 環境作成
ツールのインストール
```
npm install -g firebase-tools
```
cloud functions初期化
```
mkdir myproject
cd myproject
firebase login
firebase init functions
```
・既存プロジェクトを選択
・今回はtypescriptを選択
functionsフォルダが生成される
```
cd functions
```

## ソースを書く
・ソースは1つのfunctionの中に書く
・世の中のソースを参考にするときは、firebase cloud functionsのソースを参考にする。GCPのほうと間違えないように。。
・package.jsonを直接編集してパッケージ追加するのは避けたほうが良さそう。デプロイのときにはまります。。

インポート
```javascript
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
```
トリガとなるバケット名を指定。トリガの仕方も指定(今回はonFinalize)
リージョンも指定(省略した場合はデフォルトでアメリカのどこだったかになります)
※GCPの場合はソースの書き方が違うし、バケット名やトリガの仕方はデプロイ時に指定
```javascript
exports.myfunction = functions.region("asia-northeast1").storage
    .bucket("mybucket").object()
    .onFinalize(async (object) => {
       ：
```
firebaseコンソールに入り、設定情報を持ってきてソースにコピペ。初期化処理する
```javascript
const firebaseConfig = {
  apiKey: "xxxxxxxxxxxxxxxxxx",
  authDomain: "xxxxxxxx",
  projectId: "xxxxxxxxxxxxx",
  storageBucket: "xxxxxxxxxxx",
  messagingSenderId: "xxxxxxxxxx",
  appId: "xxxxxxxxxxxx",
  measurementId: "xxxxxxx",
};
if (getApps().length == null || getApps().length == 0) {
  admin.initializeApp(firebaseConfig);
}
```
バケット配下のファイルを検索
```javascript
const fileBucket = object.bucket;
const filePath = object.name;

(await admin.storage().bucket(fileBucket).getFiles({prefix: filePath})
    .then((files) => {
      files[0].forEach((file) => {
      ：
```
ファイルを見つけたら中身を読み込む
```javascript
          file.createReadStream().on("data", function(chunk) {
            const read_data = Buffer.from(chunk).toString();
                  ：
```
ファイルの中身を解析してデータを取りだしたらdatastoreに格納
```javascript
        ：
            const db = admin.firestore();
            db.collection("mycollection")
                .doc().set(input_data).then(() => {
        ：
```
ビルド
```
npm run build
```

## デプロイ
```
firebase deploy --only functions
```
debugオプションでログを出せる
```
firebase deploy --debug --only functions
```
自分の場合はcould not find image for functionというエラーが出てはまりました。どうもpackage.jsonを手で編集したのが原因だったようです。再度環境作成からやり直してpackage.jsonは自動生成に任せるやり方にすると、デプロイが上手く行きました。基本的にはfirebase init functions実行時に自動生成されたファイルたちを変に編集しないほうが良さそう。デプロイが失敗してはまります。。
Pythonのimportとハマるファイル名の話

# はじめに
以前「[Pythonのimport方法まとめ](https://qiita.com/elfincafe/items/a393594ba61799a7bac1 "Pythonのimport方法まとめ")」という記事も書きましたが、PHPを使ってきたエンジニアには Python の import はなかなか難しい。今回はそんな import にハマったお話し。

# エラーが発生
ディレクトリ構成は以下のとおり。
~~~
test/
  ┣━ __init__.py
  ┗━ redis.py
~~~

redis.py の内容は以下のとおり。
~~~python:redis.py
import redis

if __name__ == "__main__":
  r = redis.Redis(host="localhost", port=6379, db=0)
  r.set("key1", "value1")
  print(r.get("key1").decode())
~~~
redis.py を実行すると、redis には Redis というアトリビュートはないよ、と怒られる。いや、あるんですよ。Redis というクラスが。redisパッケージのソースを読みましたが、確実にあります。
~~~
$ python3 redis.py 
Traceback (most recent call last):
  File "/path/to/test/redis.py", line 4, in <module>
    r = redis.Redis(host="localhost", port=6379, db=0)
AttributeError: module 'redis' has no attribute 'Redis'. Did you mean: 'redis'?
~~~

# 原因がわかった
あれやこれやと半日くらい悩んだ結果、redis.py というファイル名とimportしようとしたパッケージ名がかち合っていることにに気が付きました。1行目の import はredisパッケージではなく自分自身(redis.py)を呼び出していたのです。ファイル名を redis_test.py に変えたら期待通りに動きました。
ファイル名がモジュール名として認識される Python の仕様は、扱うのに慣れが必要だと思います。
SHAPでplotした画像を保存すると真っ白になってしまったときの対処法

# 画像が真っ白になる理由
SHAPのsummary_plotで描画したグラフを保存したいとき、下のように書くと真っ白な画像が保存されてしまう。

```python:
shap.summary_plot(
  shap_values=shap_values,
  features=X,
  feature_names=X.columns,
)

plt.savefig("image.png") # 画像を保存
```

この理由は以下の通り。
1. 実はsummary_plotの内部で`plt.show()`が実行されている。
2. `plt.show()`でグラフを描画すると、そのグラフのデータは消されてしまうため、その後に`plt.savefig()`を実行しても保存する画像のデータがなくなってしまっている。
3. だから、仕方なく真っ白な画像が保存されてしまうという訳である。

したがって、summary_plotの内部では`plt.show()`は実行しないで、`plt.savefig()`した後に`plt.show()`を実行すればよい。

# 解決法

summary_plotの**show**というパラメータを`False`にすれば、内部の`plt.show()`が実行されないので、下のように書けば解決できる。デフォルトでは**show**は`True`になっている。

```python:
shap.summary_plot(
  shap_values=shap_values,
  features=X,
  feature_names=X.columns,
  show=False, # ←これを追加
)

plt.savefig("image.png") # 画像を保存
plt.show() # グラフを描画
```

`dependence_plot`や`force_plot`、`waterfall_plot`にもshowというパラメータがあるので、これらに関しても同様にして解決できる。

参考までにsummary_plotの公式リファレンスを貼っておくので、パラメータについて詳しく知りたい方はどうぞ。

[shap.summary_plot](https://shap-lrjball.readthedocs.io/en/latest/generated/shap.summary_plot.html)
PHPの基礎１


## はじめに


こんにちは。
私は現在未経験の駆け出しエンジニアとして様々な学習をしています。
先日PHPの基礎文法について学んだので、自分のアウトプットように記事を残します。
初めての投稿になりますので至らない点がありましたら申し訳ございません。


## 基本記述

```PHP:lesson.php
<?php

 echo 'hallo world'.PHP_EOL;
 echo 'good morning!'.PHP_EOL;

?>
```

```:出力結果
hallo world
good morning!
```
PHP_EOLはPHPの定義済み定数であり、OSに応じて自動的に改行文字を設定してくれる。

## nowdoc(ナウドキュメント)とheredoc(ヒアドキュメント)

```PHP:lesson.php
<?php

$a = 'こんにちわ'; //$変数を宣言

$text = <<<"EOT"
hello!
  this is looooong
text!
$a

EOT;

echo $text;
```

```:出力結果
hello!
  this is looooong
text!
こんにちわ
```

$変数 = <<<"EOT"　
　処理内容
EOT;

とすることでここに書いたテキストや字下げを保持したまま変数に代入してくれる。
EOT部分を終端記号と呼ぶ。
またこの処理内に変数を展開することをheredoc（ヒアドキュメント）、変数展開しない書き方をnowdoc(ナウドキュメント)と呼ぶ。

## if文

```
 if(条件){
	処理
 }
```

自分が初めて知った事として、このような記述があるとします。

```PHP:lesson.php
$x = 4;
 
if(x){
   echo '結果はtrueです';
} else {
   echo '結果はfalseです';
}
```
これの結果は、、、

```:結果
結果はtrueです
```

真偽値の判定において、
false. ±0, ±0.0, '0', '', null, [],
上記がfalseとして扱われる。

## 論理演算子
```PHP:lesson.php
$score = 60;
$name = 'tanaka';

if ($score >= 50 && $name === 'tanaka'){
  echo 'Good job!'.PHP_EOL;
}
// && and なおかつ
// || or もしくわ
// ! ~ではない
```
```:結果
Good job!
```
スコアが50以上で名前がtanakaさんの場合に処理を実行する。

## switch文

```
switch($変数){
  case ‘判定したい値’: //コロン
    echo 処理;
    break;　//ここで処理を止める
 }
```
```PHP:lesson.php
$signal = 'blue';

switch($signal){
  case 'red':
    echo 'Stop!' . PHP_EOL;
    break;
  case 'yellow':
    echo 'Caution!' . PHP_EOL;
    break;
  case 'blue':
    echo 'Go!' . PHP_EOL;
    break;
}
```
```:結果
Go!
```
breakを書き忘れると全て実行されてしまうので注意。
また、default:を使うと、どれにも当てはまらないが何らかの処理をしなさいと命令できる。
```PHP:lesson.php
$signal = 'pink';

switch ($signal) {
  case 'red':
    echo 'Stop!' . PHP_EOL;
    break;
  case 'yellow':
    echo 'Caution!' . PHP_EOL;
    break;
  case 'blue':
  case 'green':
    echo 'Go!' . PHP_EOL;
    break;
    default:
      echo 'Wrongsignal'. PHP_EOL;
      break;
}
```
```:結果
Wrongsignal
```

## 関数

```PHP
function 関数名(){
	//ここに処理内容
}
関数名(); //これで呼び出しができる。
```
```PHP:lesson.php
function showAd($message = 'Ad') //仮引数
{
  echo '----------' . PHP_EOL;
  echo '---'.$message. '---' . PHP_EOL;
  echo '----------' . PHP_EOL;
}

showAd('Header Ad');//実引数
echo 'Tom is great!' . PHP_EOL;
echo 'Bob is great!' . PHP_EOL;
showAd();
echo 'Steve is great!' . PHP_EOL;
echo 'Bob is great!' . PHP_EOL;
showAd('footer Ad');
```
```:結果
----------
---Header Ad---
----------
Tom is great!
Bob is great!
----------
---Ad---
----------
Steve is great!
Bob is great!
----------
---footer Ad---
----------
```
関数を使う場合は外から変数を持って来れない。
外から持ってきたい場合は　global $変数;　の記述が必要。
負の二項分布と負の二項定理

# はじめに
負の二項分布を勉強したときに、負の二項定理を知ったので、
2つの関係性を考えていたらなんか見つけました。

# 負の二項分布
これは何かを簡単に説明します。
まず 1 回の試行で当たりが出る確率を $\theta$ とします。
この時 $n$ 回当たりが出るまでに $k$ 回ハズレが出る確率の分布になっています。
式にするとこんな感じ。
$$
p(k \ ; n) = \binom{k + n - 1}{n - 1} \theta^{n}(1 - \theta)^{k}
$$
最後の1回は当たり確定なので、残った $ n - 1 + k $ 回の中で当たりを引く場所が $n - 1$ 箇所ある場合の数が二項係数の部分に相当するというのが直感的な説明です。

# 負の二項定理
とりあえず式を載せます。
$$
(1 - x)^{-n} = \sum_{k=0}^{\infty}\binom{k + n - 1}{n - 1} x^k
$$

ご覧の通り、さっき見たやつとすごい似ています。

# 関係
負の二項分布は離散確率分布なので$k$について和を取ると $1$ です。
$$
1 = \sum_{k = 0}^{\infty} \binom{k + n - 1}{n - 1} \theta^{n}(1 - \theta)^{k}
$$
両辺を$\theta^n$で割ります。
$$
\theta^{-n} = \sum_{k=0}^{\infty} \binom{k + n - 1}{n - 1} (1 - \theta)^{k}
$$
$x = 1 - \theta$ と置換してやると $ \theta = 1 - x $ で
$$
(1 - x)^{-n} = \sum_{k=0}^{\infty}\binom{k + n - 1}{n - 1} x^k
$$
これは負の二項定理です。

# 結論
個人的には負の二項分布の方が、意味があって覚えやすい。。。
負の二項定理を忘れても、すぐ導けますね。
Google スプレッドシートのセルから HTML Tag を生成したい

# Google スプレッドシートのセルから HTML Tag を生成したい

## 背景
クライアントから依頼を受けた案件を GAS/HTMLService + スプレッドシートで開発中に、クライアントがスプレッドシートに入力した文字列を書式付きで HTML に出す必要がでてきました。
流石に HTML やマークアップを知らない人に、「タグ書いてね」とは言えず、なにか手がないかと考えた結果、Google のセル内のリッチテキストを変換する方法を思いついたので、メモとして残します。

## やったこと

Google スプレッドシートシートは、セル内でリンクを貼ったり、一部の文字に色を付けたりでき、セル内でそれなりにリッチな表現ができます。GAS から セル内のリッチな書式を解析できるので、RichText -> HTML Tag コンバータを作成してみました。
今回は手抜きで、リンクと文字色しかサポートしていません。

1. セルアドレスを指定して セルのレンジオブジェクトを取得
2. セルの RichTextValue() を取得
3. 書式の異なる文字列ごとに配列分解
4. color , link , text 情報を取得し、HTML Tag を連結していく。

あまりスピードが速くないので多用はできないですがメッセージ変換程度には使えるかと。


## スクリーンショット
![スクリーンショット 2022-07-22 23.32.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533932/4a498fdb-9817-6ff7-0be7-a3fc9cca46c8.png)

## コード

```
function genHTMLfromCell(celladdress) {
// celladdress から Range オブジェクトを取得
  var r=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(celladdress)
// cell の リッチテキスト情報を取得
  var rt=r.getRichTextValue()

  var tag=""　　　// 生成した html 用の 変数

// リッチテキストを配列分割し繰り返す。
  var rn =rt.getRuns().forEach(
  run => {
// ##LINKSTART##, ##LINLEND##, ##COLORSTART##, ##COLOREND##, ##TEXT## をトークンとして初期値を tag に連結し、配列の要素ごとに LINK, COLOR, TEXT を設定する。 
      tag=tag+"##LINKSTART####COLORSTART####TEXT####COLOREND####LINKEND##"
      const url=run.getLinkUrl()
      const text = run.getText() ;
      const style = run.getTextStyle();
      if (style==null || style.getForegroundColor()=="#000000"){
        tag=tag.replace('##COLORSTART##','')
        tag=tag.replace('##COLOREND##','')        
      } else {
        tag=tag.replace('##COLORSTART##','<span style="color:'+style.getForegroundColor()+'">')
        tag=tag.replace('##COLOREND##','</span>')        

      }
      if (url==null ){
        tag=tag.replace('##LINKSTART##','')
        tag=tag.replace('##LINKEND##','')        
      } else {
        tag=tag.replace('##LINKSTART##','<a href="'+url+'" target="_new">')
        tag=tag.replace('##LINKEND##','</a>')        
      }
// ##TEXT## に関してだけ、entity 変換     
tag=tag.replace('##TEXT##',text.replace(/[&]/g,'&amp;').replace(/[>]/g,'&lt;').replace(/[<]/g,'&gt;'))

      Logger.log(text )
      Logger.log(style.getForegroundColor())
      Logger.log(url)
    });
    return tag  
}

```
Schematronではposition()関数に使いでがない

XPath に position() 関数というのがあります。XSLT だと for-each select か何かでノードセットを作ってループするときに、順番が簡単に取れる便利な関数です。

ところがこれがschematronでは使い出がないという話。たとえばなんかこんな感じのXMLがあるとするじゃないですか。

```xml
（なんか深い構造　略）
<TimeDefines>
<TimeDefine timeId="1">
<DateTime>2020-01-30T01:00:00Z</DateTime>
</TimeDefine>
<TimeDefine timeId="2">
<DateTime>2020-01-30T02:00:00Z</DateTime>
</TimeDefine>
<TimeDefine timeId="3">
<DateTime>2020-01-30T03:00:00Z</DateTime>
</TimeDefine>
```

一見すると timeId 属性は1から始まる連番のような気がします。しかし本当にそれをあてにしていいでしょうか。この TimeDefines 構造は無数にあるとなれば自動的検査がしたいですね。

XSLT であれば `<xsl:for-each select="//TimeDefines">` の中に `<xsl:for-each select="TimeDefine">` みたいなループの中で position() を使えば連番を取り出せます。それと属性値 `@timeId` を比べて相違があったときだけ苦情をいうようなスタイルシートが書けますね。ここで for-each をネストするのがミソで、そうしないと内側ループの TimeDefine の探索が全ドキュメント内の通番になってしまって、複数回 TimeDefines 構造が現れた時に思ったのと違う値になってくるわけです。

ところが Schematron だとこういうループのスコープ切替ができません。少なくとも Schematron 1.5 の少なくとも xmllint の実装では rule タグがネストできないのです。

仕方がないのでどうするかというと、次のように preceding-sibling::* 要素を数えると同じことができます。じゃあ最初っから position() なんか要らなかったじゃないかってまあそれは厳密には意味がちがうので。

```xml
<s:rule context="//nwp:TimeDefine">
<s:assert test="number(@timeId) = count(preceding-sibling::*)+1"
>時系列定義の timeId 属性は1から始まる連番である</s:assert>
</s:rule>
```
DataExplorerの無料クラスタが出ました

DataExplorerの無料クラスタが出ました。
いつものAzureポータルからではなく、専用の[https://aka.ms/kustofree](https://aka.ms/kustofree)から遷移して利用します。

https://docs.microsoft.com/ja-jp/azure/data-explorer/start-for-free-web-ui

以下の制限があります。その他の主な違いは[こちら](https://github.com/MicrosoftDocs/dataexplorer-docs/blob/main/data-explorer/start-for-free.md#feature-comparison)を参照してください。

* Storage (uncompressed)	~100 GB
* Databases	Up to 10
* Tables per database	Up to 100
* Columns per table	Up to 200
* Materialized views per database	Up to 5

# ちょっと遊んでみた

国土交通省が公開しているデータから東京都の公共施設のデータを取ってきました。

https://nlftp.mlit.go.jp/index.html

ここでアップロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/4641b2cb-eb9c-ec50-e555-cfb08f21be72.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/f07dfd97-a67c-e08c-8607-7af7f57950c8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/00121536-74fe-e32c-c869-d2590a1e8e83.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/22f2cb03-6b95-3699-0e3f-649e9a7d99fa.png)

取り込んだデータには本物のDataExplorerと同じKustoを使ってクエリをなげることができました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/19fd84da-fc29-521a-bd79-e33720068ec1.png)

# 国土交通省の不動産取引価格情報

こんどはこのデータを使ってみます

https://www.land.mlit.go.jp/webland/servlet/MainServlet

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/851992b1-71da-9f6e-5270-24010837a2ed.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/db30f415-8157-2d79-1580-7a1aba6ff7d2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/1b78e5d7-5700-513a-0306-a5fa69cccc50.png)

```kusto
real_estate
| extend year = toint(replace_regex(dt, "年(.+?)$", ""))
| extend m2p = total_price / m2
| summarize avg(m2p) by addr, year
| render linechart 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/598dfe34-d461-6ccf-8bd6-6e6807a72d14.png)
【Xcode】シュミレーターAppleWatchとシュミレーターiPhoneの紐付け

# はじめに
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/SwiftUI%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E4%B8%80%E6%9C%AC%E5%8B%9D%E8%B2%A0?src=hash&amp;ref_src=twsrc%5Etfw">#SwiftUIレイアウト一本勝負</a> 002<br><br>- ナビゲーション階層による画面遷移を前提としてください（NavigationLink を用いてください）<br>- macOS App は考慮しなくてよいこととします<br>- エンティティ・サンプルデータ の提供があります（リプライを参照、利用は必須ではありません） <a href="https://t.co/VdmBbux8fr">pic.twitter.com/VdmBbux8fr</a></p>&mdash; treastrain / Tanaka.R (@treastrain) <a href="https://twitter.com/treastrain/status/1549595274653609984?ref_src=twsrc%5Etfw">July 20, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こちらのお題を解いている時に初めてApple Watchをシュミレーターで起動しました。
そこで気づきました。
Apple Watchの言語が英語から変更できない。。。
ここでかなり時間溶けました笑

根本の原因はAppleWatchとiPhoneの関係性がわかっていなかったからだと思います。
今回はシュミレーターのApple WatchをシュミレーターのiPhoneに紐付けする方法を紹介します。

明日はシュミレーターのApple Watchの言語を変更する方法を投稿します。

# 方法
「Window」から「Devices and Simulators」を選択します。
![スクリーンショット 2022-07-22 22.48.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/54285ae8-bcbb-fcab-4663-f98bc136f603.png)
今回はiPhone13を使用します。
iPhoneを選択したら「＋」を押します。
![スクリーンショット 2022-07-22 22.51.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3958ef61-e3b2-f135-27dc-630a2082b812.png)
紐付けしたいapple watchの種類を選択したら「Pair」を押します。
![スクリーンショット 2022-07-22 22.55.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/67b3fbde-365a-3378-a0eb-da9da218198d.png)
こうなってればOKです。
![スクリーンショット 2022-07-22 22.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/586469ad-9cb1-bab2-db99-83615fdba17c.png)
紐付けした端末を両方ビルドします。
今回の例では「iPhone13」と「Apple Watch Series7 - 45mm」です。
両方ビルドできたら「Watch」を開いてみましょう。同期が始まります。
![スクリーンショット 2022-07-22 23.05.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ae30f9b3-d67a-3961-20e4-b1ce12d3a866.png)
以下の画像のように表示されていれば、同期は完了です。
![スクリーンショット 2022-07-22 23.12.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4ce6e96d-b968-7e50-95ff-fe0ac201501e.png)

# 完成
![スクリーンショット 2022-07-22 23.13.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1bfd953d-86d3-9dd9-f4f9-628f3c496fb1.png)

# おわり
watchOSの情報は少ないので沼にハマると一瞬で時間が溶けます笑
赤外線リモコンを自作する - その1データ解析編

## 目次
1. [赤外線リモコンを自作する - その1データ解析編](https://qiita.com/ayakix/items/3ad454f135fb63a92026)
1. [赤外線リモコンを自作する - その2データ送信編](https://qiita.com/ayakix/items/75adbe742c32689a3cae)
1. [赤外線リモコンを自作する - その3温度/湿度センサー編](https://qiita.com/ayakix/items/69cf14e57dec86f4415a)
1. [赤外線リモコンを自作する - その4サーバサイド編](https://qiita.com/ayakix/items/5161a70ffca3b84e51f3)
1. [赤外線リモコンを自作する - その5クライアント編](https://qiita.com/ayakix/items/ca69c61deff3fb3fdb20)

## 赤外線リモコンを自作する - その1データ解析編

何番煎じかわからないが、赤外線リモコンを自作し、API経由で操作できるようにしたい。
今回はその1データ解析編として、家電の赤外線リモコンからどのような信号が送られているかを解析する。
この信号を端末から送ることで、家電を操作できるようにする。

## 用意するもの

|  機器  |  型番  |  参考価格  |
| :--- | :--- | ---: |
|  Arduino互換機  |  [ESP32-DevKitC-32D](https://akizukidenshi.com/catalog/g/gM-13628/)  |  1,480円  |
|  赤外線受信モジュール  |  [PL-IRM0101](https://akizukidenshi.com/catalog/g/gI-00622/)  |  110円  |

## 手順
1. Arduino IDE > ツール >ライブラリを管理より`IRremoteESP8266`を検索し、インストールする
1. ファイル > スケッチ例 > IRremoteESP8266 > IRrecvDumpV3を選択する

赤外線受信モジュールは、左からVout、GND、Vccとなっているので、ESP32の14pin、GND、5Vに接続する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706/02dbdc07-c9ee-69b0-f212-4a84236d9c38.jpeg" width="440px">

Runしたあと、赤外線リモコンのボタンを押すと、シリアルモニタの11520bpsに下記のような値が表示される。

シーリングライト
```
Protocol  : UNKNOWN
Code      : 0xCA21A230 (42 Bits)
uint16_t rawData[83] = {3486, 1722,  446, 418,  446...}
```

Panasonicエアコン
```
Protocol  : PANASONIC_AC
Code      : 0x0220E004000000060220E004003132803F00000660400080000654 (216 Bits)
Mesg Desc.: Model: 4 (JKE), Power: On, Mode: 3 (Cool), Temp: 25C, Fan: 0 (Quiet), Swing(V): 15 (Auto), Quiet: Off, Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off
uint16_t rawData[439] = {3496, 1724,  452, 418,  452...}
```

このrawDataを赤外線LEDより送信することで、家電を操作できるのでメモしておく。

## 補足と注意点
* IRremoteESP8266と似たようなライブラリとして、IRremoteというのがあるが、こちらのReceiveDemoは、エアコンのように長い信号の場合、正しく値を取得できない問題があるみたいです。
* IRrecvDumpV3は、パナソニック、三菱、東芝、ダイキン、富士通などの国内メーカーのエアコンデータを解析できます。詳しくは[リポジトリ](https://github.com/crankyoldgit/IRremoteESP8266)を参照してください。
* 上記メーカーのエアコンなのに、ProtocolがUNKNOWNとなる場合、kTimeoutの値を長くしてください。`#define DECODE_AC true`をファイルの上の方に書くことで、プログラムで用意されている値を使用することができます。
* IRremoteESP8266のスケッチ例として他にもTurnOnPanasonicACなどがあり、これを使うことで、rawDataを扱うことなく、信号を送信できます。