OmniAICreator/Qiita-1.07M huggingface dataset:
統計検定2級(CBT方式)に1週間でとりあえず合格する。

 ### この記事が対象とする人
- とりあえず「統計検定2級に合格した！」と言いたい人
- できる限りお金・時間をかけずに合格したい人


### 前提
2022年9月5日に過去問を購入して勉強を始め、2022年9月12日に統計検定2級(CBT方式)に合格しました。
※67/100点で、合格点は60点ですので、かなりギリギリです。
新卒でデータサイエンティスト就職を目指すにあたって、統計検定2級を持っていて損はないと感じたのが受験のきっかけです。元々大学一年時(4年前)に基礎統計を履修しましたが、ほぼ全て忘れていました。（そして成績も良くなかったはず…）

### 使用教材
- [統計web](https://bellcurve.jp/statistics/course/)
    - 統計検定2級に合格するためにはマストの教材だと思います。
    - 過去問を解いていて分からないことが出てきたらサイト内でまずは検索していました。
- 統計検定2級過去問(2018年~2021年)
    - 1周しました。最後の1つ以外調べながら解きました。
    - 他の方も言うように、問題傾向はCBTとは違う気が…。
    - 中古でほとんど売ってないので学生の自分には出費が痛かったです。
- まとめノート
    - あとで見返せるように簡単に間違えたところ・単語・式を自己流でまとめました。

![統計検定2級](https://images-na.ssl-images-amazon.com/images/I/51PRkPbugTL._SX351_BO1,204,203,200_.jpg)


### 対策
- 過去問を解く
- 分からないことをググりまくる(特に統計web)
- ノートにまとめる・メモする
※webで調べても不十分だと感じたところは図書館で参考書を借りて該当部分を読みました。

### 試験1週間前から当日までの主なスケジュール
- 7日前：過去問購入・情報収集(詳細は後述）
- 6日前：2021年6月・2021年6月やり直し
- 5日前：分かっていない部分の統計web練習問題を解く
- 4日前：2019年11月・2019年11月やり直し
- 3日前：2019年6月・2019年6月やり直し
- 2日前：2018年11月・2018年11月やり直し
- 1日前：2018年6月・2018年6月やり直し
- 当日：ノート見直し、受験
1日約3時間、合計約21時間勉強しました。


### 試験を終えて
推定・検定・統計モデルの正解率が55%という何とも残念な結果に終わりました。
今後準一級に向けて勉強する中で理解を深めていこうと思います…。
また、いくつかのサイトで古い過去問を解いた方がいいという意見が散見されましたが、合格するだけなら過去問は1冊でいいと思います。ただあくまで個人の意見ですので参考程度にお願いします。


### 参考記事
最短で合格したかったので、とにかくググって合格体験記を読み漁りました。
特に参考になったのをいくつかピックアップさせていただきます。

- [統計検定2級を１週間の勉強期間で合格するためにしたことまとめ
](https://qiita.com/tachiken0210/items/a5a2363b481896f04fa7)
- [統計検定２級に楽に合格する方法](https://qiita.com/okoppe8/items/6caca7ab6509edf0c497)
- [統計検定2級合格までの勉強方法](https://qiita.com/FukuharaYohei/items/3c4114e0ed8fa48a408e)
153.JSON

## JSONの存在意義
JSONというのは見た目オブジェクトのような書き方をした

主にHTTP通信や、サーバーへのデータ送信する時に、
このJSON型に変換するというルール（またはXML）形式
になります。
簡単にいうと、取り決めで、データを通信するときの書き方は
JSON型に変換するというルール（またはXML）に統一しよーぜと決まってます。
そんなルールにしたのも、どんな言語でもわかりやすい書き方になっているからだと言われています。
### オブジェクト→JSONに変換する方法
1.オブジェクト→JSONに変換する方法　JSON.stfringfy
2.JSON→オブジェクトに変換する方法　JSON.parse

#### 1.JSON→オブジェクトに変換する方法　JSON.stfringfy
```js
// 1.オブジェクトを作成してみる
const obj = {a:0,b:1,c:2};

// 3.replacer(){}
 function replacer(prop,value){
	if(value < 1){
  	return;
  }
   return value;
}
// 2.stringify(obj,replacer) にて変換 
const json = JSON.stringify(obj,replacer);
```
#### 2.JSON→オブジェクトに変換する方法　JSON.parse
```js
// 1.1のjsonをparseにてオブジェクトに変換
const backobj = JSON.parse(json);
```
アンテナ技術(SISO,MIMO,MU-MIMO)

アンテナとは、無線信号を受け取ったり、渡したりすることができる機器です。これは無線ネットワーク機器に搭載されております。

# SISO

送信する側も受信する側も１つのアンテナを持っている。このため、１つずつデータストリームを送ることになる。

信号は、部屋の物に反射して、部屋の中に複数の信号が飛び交うことになる、こうなると干渉が起こって、低いスループットになってしまう。そのため、一番良く受信できた信号のみを受け取って他の信号は捨てる。

# MIMOとMulti User-MIMO

送信する側も受信する側も複数のアンテナを持っている。このため、送受信できるデータ量が増える。

複数の人がいる場合、信号の飛ばす方向を変えて、同時に複数の人のデータを送受信することができる。
100均のアイテムで外部接点入力のLEDライトを作ってみた

100均で入手できる材料で接点操作ができるLEDライトを作成しました。
接点操作は何でも良いですが、今回は[別ブログで紹介している定期的な画像送信](https://qiita.com/umasa/private/23942c2892fdb00d1fba)で送られた写真が暗かったので撮影時にLEDライトを点灯させるという目的で [KC4-C-100A](https://www.kyocera.co.jp/prdct/telecom/office/iot/products/kc4-c-100a.html?qiita) を利用しています。
![電気室メーター監視_素材.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/393cd318-38fa-af88-5a69-b6b150f10f84.gif)


# 準備するもの

| 品名 | 数量 | 価格 | 詳細 |
|:-:|:-:|:-:|:-:|
|LEDライト| 1 | 100 | [ダイソーネットストア](https://jp.daisonet.com/products/4972822310680?_pos=31&_sid=2dc01fcd1&_ss=r) |
|USB延長ケーブル| 1 | 100 | USB Type-A オス/メス<br>[ダイソーネットストア](https://jp.daisonet.com/products/4549131456547?_pos=17&_sid=191fad553&_ss=r) |
|USB充電用ACアダプタ| 1 | 300 | [ダイソーネットストア](https://jp.daisonet.com/products/4549131931884?_pos=3&_sid=b13b9c5b4&_ss=r) |
|抵抗|1|－|220 Ω|
|ユニバーサル基板|1|－|40mm×40mm程度の大きさ|


# 回路図

KC4-C-100A の[ホワイトペーパー](https://www.kyocera.co.jp/prdct/telecom/office/iot/guide/kc4-c-100a_kc4-c-101a/guide03.html?qiita#sec6-5)を参考に各パーツをつなぎ合わせます。
![ホワイトペーパーLED接続図.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/52cff4f2-552e-e486-2ec7-109bb3364832.png)

- 本ブログでは抵抗 Rpu は 220Ω を採用。
- GPIOx は pin10(茶)、GND は pin12(灰)。※詳しくは[コチラ](https://www.kyocera.co.jp/prdct/telecom/office/iot/guide/kc4-c-100a_kc4-c-101a/guide03.html?qiita#sec1-1)を参照

実際に作成したものがこちら
![LED回路_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/d1a75e19-43bd-cc7b-e9ba-405144a0fcb6.jpeg)
![LED回路_2説明あり.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/27aaedd3-76ee-da62-c988-0586f6df78fd.jpeg)

::: note info
設置の操作性を考慮し KC4-C-100A への接続はコネクタを採用しています。
コネクタの先をスイッチなどに変えれば接点操作が可能です。その際は抵抗は不要です。
また、USBケーブルは4芯ですが不要な2芯は短く切断しています。
:::

# レシピ
定期的な写真撮影のレシピに接点入出力のコマンドを追加したものがこちら
※元になっている画像撮影のレシピは[こちらのブログ](https://qiita.com/umasa/private/23942c2892fdb00d1fba)を参照ください。
![レシピ_LED点灯.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/acee6727-e9a6-bfc8-dce3-1764d521c936.png)


# 設置の様子
実際の現場に設置した様子はこちら
![LED設置の様子.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/b7bd46d3-1db5-e5e9-e056-1df2935437b6.jpeg)

# 結果
外部入力によるLEDの点灯を確認します。
※KC4-C-100A のボタン操作をトリガに外部出力接点を操作している例となります。
![LED点灯.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/ccedd68e-3bd7-ab54-b721-42f85b383d32.gif)


別ブログで作った[KC4-C-100A を使った遠隔監視システム](https://qiita.com/umasa/private/23942c2892fdb00d1fba)にて、LEDライトがない状態とLEDライトがある状態の撮影画像の比較です。
![LEDなし.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/7bdb5927-8b47-2914-c8cf-6115c76606d6.jpeg)
![LEDあり.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1188107/f83bd448-8283-7696-7b2a-590a7c5c73b3.jpeg)

**見やすくなりました！！**

# 注記
- 商標
※その他本文中に記載されている会社名および商品名は、各社の商標または登録商標です。
151.WeakMap　152

## 覚えておくべき前提条件
1.まず配列を作成したら、メモリに情報が格納されている
2.メモリは有限なので使わない配列はガベージコレクションという清掃員さんにて、
定期的に解放している（消している）
## WeakMapの存在意義
弱い参照でオブジェクトを保持するコレクションのこと
上記のことから、バリューが使われなければ、自分で捨てればいいんじゃないの？
というのがWeakMapです。

注意点:キーは必ずオブジェクト

#### 例

```js
const wm = new WeakMap();
const o = {};
wm.set(o,'value1');
console.log(wm.get(o))
console.log(wm.has(o))
```
https://teratail.com/questions/121941
Twitterでエゴサするときに便利な検索コマンド

# 前提
私のアカウント名は@iwaken71 です。
エゴサーチとして「イワケン」を検索したいとします。

https://twitter.com/explore
こちらのキーワード検索に入力していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96970/747080fd-df0f-fe85-2afc-3a3e668155b3.png)


# 検索コマンド

## 通常
```
イワケン
```

## 自分のツイート以外を検索

- 「-」
    - 入れることでその条件を除外することができます。
- from:{アカウント名}
    - 誰からのツイートなのか指定できます

```
-from:iwaken71 イワケン
```


## 期間を限定
- since:{日付}
    - ここから
- until:{日付}
    - ここまで
```
イワケン until:2022-09-30 since:2022-07-01
```

## いいね数の最小を設定

- min_faves:{数字}
    - いいねの最低ラインを指定
```
イワケン min_faves:50 
```

## RT数の最小を設定

- min_retweets:{数字}
    - RTの最低ラインを指定
```
イワケン min_retweets:50
```

# 備考

https://twitter.com/search-advanced?f=top
をクリックして、三点ボタンから「高度な検索」を選択すると、GUIで条件付きの検索ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96970/1ee56f2d-a4ef-1ee0-4c62-7cd1cb1b82e9.png)
OpenCV使用時にQt platform plugin "xcb"エラーで動画が出ない場合


## 行いたかった作業：OpenCVをつかうプログラムを動かしたい(YOLOX)

:::note info
2024年10月
同一エラー、Opencv絡みで類似症状がでたので改善策を追記
:::

# 1. エラー表示

* エラー表示はこの表示で始まっています。
**qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.**

* その下に〇〇といったplatform pluginsは使えるけど云々、最終的に再インストールを促すような表示になっています。
    * 多くの方が検索して以下のような記事を見つけて解決されている方も多いかと思います。
    
# 2. 参考にした記事等

* 私の場合は残念ながらすべて解決しませんでした・・・

* 変数の変更や不足、設定変更（OpenCV）
    
https://qiita.com/seigot/items/f379854eb595b932b9e4

https://qiita.com/fukasawah/items/99219e1ff7d08915952f

* 最終目的はOpenCVでの描画だったのですが、今回は残念ながら解決に至りませんでした。

***

* aptで不足パッケージの追加や再インストール

https://forum.qt.io/topic/127696/qt-qpa-plugin-could-not-load-the-qt-platform-plugin-xcb-in-even-though-it-was-found

https://medicalfields.jp/blog/python/ubuntu%E3%81%A7python3%E3%81%A7pyqt5%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%9F%E3%81%84%E3%81%AE%E3%81%AB%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E3%81%A7%E3%82%8B/

***

* condaでパッケージを再インストール

https://stackoverflow.com/questions/33051790/could-not-find-or-load-the-qt-platform-plugin-xcb


***

# 2. 私の場合の解決策
* 動作させていたのはYOLOX でエラーはQtがらみでもあり、OpenCV絡みでもある。
    * Qtはいろんな方法で再インストールやパス変更をしたけど、解決せず。
    *  **こうなれば OpenCVか？？**
    
* インストール済みOpencv-pythonのバージョンが 4.5.5.62
    * アンインストールして、徐々にバージョンを下げてみる。
  
```Ubuntu:opencv-python入れ直し


# 4.5.5.64(元のバージョン)
# 改善せず
# 4.5.5.62
pip uninstall opencv-python


# 動作したバージョン
pip install==4.5.4.60

```

* 画像はコンプライアンスにかかってしまうので、動作している画面だけ載せます(一部塗りつぶし)
![Screenshot from 2022-09-12 16-05-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/a4f71a84-41c9-dad2-cd93-2507a26f471a.png)


# 3. 今回もOpencvのアプリ作成
- ただし動画は再生しません
- でもOpencvを使用するアプリでかつPyQt5使用

## 

```Ubuntu:ターミナル画面

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/xxxxx/anaconda3/envs/anoma/lib/python3.8/site-packages/cv2/qt/plugins" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: xcb, linuxfb, minimal, offscreen, vnc, webgl

```
### エラーにxcbの処理にOpencvがまたしても・・・
 
:::note info
resolution
In this case, failure cause is opencv-python-headless.
After uninstalled it, my application is working well.
:::

```
pip list |grep open
opencv-python                        4.7.0.72
opencv-python-headless               4.7.0.72 <---kore
```
- 度々邪魔をしてくれていたheadlessを見つけたのでアンインストール
- **無事にアプリが起動してくれました**

## 上記方法でもインストールしない場合
- This application failed to start because no Qt platform plugin could be initialized. Reinstalling
- このエラーがで続けている
- Plugin is whatな場合

```Ubuntu:ターミナル画面

pip install PyQt5-tool

```
:::note info
まとめ
エラーの表示も大事ですが、何をしているかも考える必要性を感じました。
:::
Sample App of Flutter3 x MySQL8 with mysql_client 3

# Appの現状を動画にしました。

　[元の記事はこちら](https://qiita.com/dongri727/items/412b97eed4943006a0a0)


- insert・update・deleteは、データベースで確認しないとできてるのかどうかわからないのが問題ですね。スナックバーなどを出せるようにしたいです。
- selectはまだ一件しか表示できていません。ListView化に鋭意邁進中です。
- bottom navigation barもつけたいですね。

<iframe width="560" height="315" src="https://www.youtube.com/embed/PwdqohRbk88" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Azure pipelines にてエラー終了する方法

## 概要

Azure pipelines にてエラー終了する方法を共有します。

エラーメッセージを表示する方法として`Logging commands`の`task.LogIssue`を、エラーとして終了する方法として`Logging commands`の`task.complete`を利用します。

[Logging commands - Azure Pipelines | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash)

## 実行方法詳細

```yaml
jobs:
- job: raise_error
  steps:
  - task: CmdLine@2
    name: cmd
    inputs:
      script: |
        echo "##vso[task.LogIssue type=error;]Test error message."
        echo "##vso[task.complete result=Failed;]"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/61b6074c-aa8f-ac18-7921-6449fdbfb1c9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1c2d162e-46c0-081d-0059-29bb56246e4f.png)
Umbrella S3 ログを aws cli から直接参照する

### はじめに
以前 Umbrella の S3 ログをデスクトップクライアント（Cyberduck)を使ってアクセスする方法を紹介した。
https://qiita.com/urikura/items/1fccd893f2f483f1f7ec
いちいちローカルにファイルを保存して操作するのが面倒な場合に備えて CLI 操作する方法も調べてみた。
### 準備
#### awscli インストール
=> https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

#### aws configure
=> https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html

Umbrella で生成したクレデンシャルを設定
```
$ aws configure
AWS Access Key ID [****************FQBK]: 
AWS Secret Access Key [****************aZOu]: 
Default region name [us-west-2]: 
Default output format [None]: 
```
確認
```
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************FQBK shared-credentials-file    
secret_key     ****************aZOu shared-credentials-file    
    region                us-west-2      config-file    ~/.aws/config
```


### S3 アクセスの確認
＊バケツ名や IP などはマスクしてます。

ルートと各機能ごとの階層
```
$ aws s3 ls s3://umbrella-managed-yyy-xxx/
                           PRE auditlogs/
                           PRE dnslogs/
                           PRE proxylogs/
```
各機能ごとの日付ディレクトリ

```
$ aws s3 ls s3://umbrella-managed-yyy-xxx/dnslogs/
                           PRE 2022-08-11/
                           PRE 2022-08-12/
                           PRE 2022-08-13/
                           PRE 2022-08-14/
                           PRE 2022-08-15/
                           PRE 2022-08-16/
                           PRE 2022-08-17/
                           PRE 2022-08-18/
                           PRE 2022-08-19/
                           PRE 2022-08-20/
```
ファイル一覧
```
$ aws s3 ls s3://umbrella-managed-yyy-xxx/dnslogs --recursive
2022-08-12 00:04:36        380 dnslogs/2022-08-11/2022-08-11-23-50-44ea.csv.gz
2022-08-12 00:01:57        367 dnslogs/2022-08-11/2022-08-11-23-50-91dd.csv.gz
2022-08-12 00:04:00        471 dnslogs/2022-08-11/2022-08-11-23-50-a6fd.csv.gz
```
### ファイルの中身を見る
` aws s3 cp s3://{bucket}/{path}/{filename} - | zcat ` を使う。
さらにパイプで grep なども可能。
宛先に` - ` を指定することで標準出力することが可能。zcat に渡すことで可読となる。

```
$ aws s3 cp s3://umbrella-managed-yyy-xxx/dnslogs/2022-09-12/2022-09-12-05-30-cb6f.csv.gz - | zcat
"2022-09-12 05:34:08","Site-PPPoE","Site-PPPoE","xx.xx.xx.xx","xx.xx.xx.xx","Allowed","1 (A)","NOERROR","gae2-spclient.spotify.com.","Radio,Music,Podcasts,Application,Streaming Audio"
"2022-09-12 05:37:03","Site-IPv6","Site-IPv6","xx:xx:xx:xx:xx:xx:xx:xx","xx:xx:xx:xx:xx:xx:xx:xx","Allowed","1 (A)","NOERROR","app.slack.com.","Chat,Instant Messaging,Application,Chat and Instant Messaging"
```


### 展望
複数ファイルを横断した検索はローカル作業が必要。これも CLI だけで完結できるとより実用性がありそう。

### 参考
https://qiita.com/mimimi-no-sesese/items/0e7955172ab53ccbbde1
https://qiita.com/nakazax/items/b62309884a19d71f9a34
https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html
[0,1,1,1,0,0,0,1,1,0,0,1,0,1,0]を作る旅

プログラミングをやっていると、適当な順に並んだ整数をループで作り出したくなる瞬間が度々あると思います。

そんな時にはまず [The On-Line Encyclopedia of Integer Sequences® (OEIS®)](http://oeis.org/) あたりを調査するのが定石だと思いますが、つい先日、面白い仕掛けを使っている tweet を発見しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">これぐらいしか遊びが思いつかなかった <a href="https://t.co/M0OO1ySUsf">https://t.co/M0OO1ySUsf</a> <a href="https://t.co/bwrZOWaaUk">pic.twitter.com/bwrZOWaaUk</a></p>&mdash; ぶーやー (@tyabu12) <a href="https://twitter.com/tyabu12/status/1567904347299917824?ref_src=twsrc%5Etfw">September 8, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

なんと rand() を使用して、適当な整数配列を再現しようという試み！

そこで、seed の **152965** を簡単に探し出したいと思いコードを書いてみました。
```php
<?php
$arr = [0,1,1,1,0,0,0,1,1,0,0,1,0,1,0];
$max= max($arr);
$min= min($arr);
$i = 0;
$count = count($arr);
$result = [];
while($result !== $arr){
    srand($i);
    for($j = 0; $j < $count; $j++){
        $rand = rand($min, $max);
        if($rand === $arr[$j]){
            $result[$j] = $rand;
        } else {
            $i += 1;
            break;
        }
    }
}
echo $i . PHP_EOL;
```

[0,1] 以外の組み合わせも対応できるように max, min を使用しましたが、paiza.io では time out になってしまったので、[0,1] 以外は現実的ではないかもしれません。

# 感想
参考にした tweet とかみると、知ってたはずの仕組みをまだまだ有効に使えてないなぁと感じます。
あと、某プロジェクトの締め切り間近なのにこんな記事書いてるなんて時間も有効に使えてないなぁともｗ
書いてる30分間は楽しかったのになぁ。。。
どうしよ。間に合わないｗｗｗ
Azure Pipelines から Databricks の API を実行する方法

## 概要

Azure Pipelines の標準タスクを用いて Databricks の API を実行する３つの方法を紹介します。

1. `CmdLine`タスクにより Databricks REST API を実行する方法
1. `InvokeRESTAPI`タスクにより Databricks REST API を実行する方法
1. `CmdLine`タスクにより Databricks CLI を実行する方法


## 事前準備
### 1. Databricks にて、Databricks Workflows のジョブを作成

```python
import time

# sleep 前のエポック秒(UNIX時間)を取得
startSec = time.time()

# 1.5 秒 止める
time.sleep(90)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/32830717-2f3e-25d7-d155-1d8e79b52aca.png)

### 2. Azure Pipeines にて パイプラインを作成後、３つの変数を定義

| #    | 変数値 | 概要                           |
| ---- | ------ | ------------------------------ |
| 1    | DATABRICKS_WORKSPACE_URL       | Databricks Workspace の URL    |
| 2    | DATABRICKS_TOKEN       | Databricks のシークレット      |
| 3    | DATABRICKS_JOB_ID       | Databricks Workflows の Job ID |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/53c5f9d0-3c93-ddd0-68a7-fca29490666b.png)


## 1. `CmdLine`タスクにより Databricks REST API を実行する方法

```yaml
jobs:
  - job: Databrics_REST_API_by_CmdLine
    steps:
    - task: CmdLine@2
      displayName: Execute Databricks Workflow
      inputs:
        script: |
          results=$(curl -X POST $(DATABRICKS_WORKSPACE_URL)/api/2.1/jobs/run-now \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer $(DATABRICKS_TOKEN)' \
          -d '{"job_id": "$(DATABRICKS_JOB_ID)"}' \
          )
          echo $results
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3ecaa87c-e3c9-bdcf-7752-6a69dc909002.png)


## 2. `InvokeRESTAPI`タスクにより Databricks REST API を実行する方法

```yaml
jobs:
  - job: Databrics_REST_API_by_InvokeRESTAPI
    pool: server
    steps:
    - task: InvokeRESTAPI@1
      inputs:
        connectionType: 'connectedServiceName'
        serviceConnection: 'databricks_jobs'
        method: 'POST'
        headers: |
          {
          "Content-Type": "application/json",
          "Authorization": "Bearer $(DATABRICKS_TOKEN)"
          }
        body: |
          {
            "job_id": "$(DATABRICKS_JOB_ID)"
          }
        urlSuffix: 'api/2.1/jobs/run-now'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ac33f034-ba2e-4442-a46f-da1d2fcfe31a.png)

## 3. `CmdLine`タスクにより Databricks CLI を実行する方法

```yaml
jobs:
  - job: Databrics_CLI
    steps:
    - task: UsePythonVersion@0
      displayName: 'Use Python 3.8'
    - task: CmdLine@2
      inputs:
        script: |
          pip install databricks-cli -q
          databricks jobs run-now --job-id $(DATABRICKS_JOB_ID)
      env:
        DATABRICKS_HOST: $(DATABRICKS_WORKSPACE_URL)
        DATABRICKS_TOKEN: $(DATABRICKS_TOKEN)

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6a31f083-e200-f067-eda3-194ca844bdf5.png)
良い物件の探し方

#### 初めに
　IT全然関係ありません（汗。ですが、色々と勉強になったので備忘録として残しておきます。一応、引っ越しの際などの物件探しの参考になれば。

#### 結論
　やっぱり、業者の方は詳しい（当たり前）。条件を伝えると、最適な物件を紹介してくれる。ですが、一応、自分でも幾つか候補の物件を用意しておいた方が、やりとりもスムーズになると思います。

#### 準備
　最近は[SUUMO](https://suumo.jp/)や[HOME's](https://www.homes.co.jp/)などで物件を検索できるので、物件の**検索条件**や**お気に入り物件**を幾つか準備しておくと、色々と相談に乗って貰えると思います。とは言え、一般的な検索条件だと数百件くらい表示される場合のあるので、その辺りは気合と根性で調べる。

### 来店
　いざ来店して業者の方に物件の希望条件を伝えると、よさげな物件を紹介して貰える。そして、自分で調べたお気に入り物件も伝えると、それについても色々と自分では気づかない様なアドバイスを貰えるので、とても参考になる。例えば、下記の様なもの。

**静かな物件に関するアドバイス**
- 大通りに面しているので交通量が多い
- 線路が隣にある
- 大学が近いので学生が多い
- 繁華街が近いので、夜騒がしい
- 空港が近いので飛行機が飛んでいる

**駐車場に関するアドバイス**
- 駐車場が空いていない
- 近くに月極駐車場も少ない
- 駐車場代が高い
- 駐車場が狭く、大型車は停めれない

**費用に関するアドバイス**
- 家賃に対する部屋の広さなどのコスパ
- 敷金・礼金などの有無
- 家賃以外にかかる費用
- 初期費用
- 退去時の費用

**その他のアドバイス**
- 坂道の多い地域の物件で移動が大変
- 周りの雰囲気（住宅街など）
- スーパーやバス停の有無
- ネット環境

#### 地道に調べる
　上記の様なアドバイスを頂いて、「それだったら家賃同じだし、こちらの物件の方が良いですね。」と言う感じで、物件を絞っていく。土地勘がないと、坂道の多い地域などはまず分からないですね（汗。周りの雰囲気なども教えて貰えると、とても参考になる。勿論、繁華街から遠いほど、家賃や駐車場代は安くなる。でも、リモートワークなら、敢えて繁華街から離れた所に住むのも、それはそれでありな気もする。
　色々と細かく見ていくと、探している物件数はそれほど多くないことが分かる。そして、候補が幾つか絞れたところで、実際に物件を見に行く。当然ながら、家賃が上がれば部屋のグレードも上がる。

#### 考察
　物件を検索する時に、上記の様な条件も選択できると物件数もかなり絞れるのではないかなと思いました。線路が隣にあるとか、大学が近いとかは、いちいち地図を確認しないと分からないよね。因みに、月極駐車場の検索サイトは、まだ充実していない感じ。google mapで地道に調べるしかなさそう。

#### 最後に
　**「お客様に最適な物件を見つけるのが我々の仕事ですから。」** という言葉に痺れた。
Mapbox GL JS クリックイベントが多重に起動するのを防ぐ

線路上に駅があり、駅をクリックすると駅のイベントと線路のイベントが両方起動してしまうような場合、
[こちら](https://github.com/mapbox/mapbox-gl-js/issues/5783)にあるように

```
    map.on('click', 'station', function (e) {
        e.originalEvent.cancelBubble = true;
        new mapboxgl.Popup()
          .setLngLat(e.lngLat)
          .setHTML('layer 1')
          .addTo(map);
    });

    map.on('click', 'route', function (e) {
        if (e.originalEvent.cancelBubble) {
            return;
        }
        new mapboxgl.Popup()
          .setLngLat(e.lngLat)
          .setHTML('layer 2')
          .addTo(map);
    });
```
のようにすればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/8d3594ec-5527-53fc-6642-248f5ed1cb33.png)
Sequelize 30分以内の範囲でレコードデータを取得

```ts
const { Op } = require('sequelize')
```
まずは、こちらの`Op`を`sequelize`より取得します。
```
[Op.eq]     =
[Op.ne]     !=
[Op.lt]     <
[Op.lte]    <=
[Op.gt]     >
[Op.gte]    >=
[Op.like]   like
[Op.ilike]  ilike
```
現在の時間から過去３０分間を取得する場合、`>=`を使用して
```
new Date(Date.now() - (1000 * 60 * 30))
```
`new Date()`はでオブジェクトを生成して`Date.now()`で基準日から経過時間を返します。
他にも`Date.now()`を日時で指定する場合、
```
1秒＝1000ミリ秒　（１０００）
1分＝1000ミリ秒×60秒　（1000 * 60）
1時間＝1000ミリ秒×60秒×60分　(1000 * 60 * 60)
1日＝1000ミリ秒×60秒×60分×24時間 (1000 * 60 * 60 * 24)
1年＝1000ミリ秒×60秒×60分×24時間×365日 (1000 * 60 * 60 * 24 * 365)
```
こちらを参考にして下さい。
`sequelize`で`id`と`createdAt`を検索条件にかけた例は
```ts
export const getId = async (req: Request, res: Response) => {
  const { Op } = require('sequelize')
  res.json(
    await TableData.findAll({
      where: {
        id: req.params.id,
        createdAt: {
          [Op.gte]: new Date(Date.now() - (1000 * 60 * 30)),
        },
      },
      order: [['created_at', 'DESC']],
    })
  )
}
```
このような形になります。
VisualStudio2022でキーボードショートカット変更（Ctrl + Wでタブウィンドウ閉じるように、など）

# やり方

ツール⇒オプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/06ff398f-5876-acd9-75e3-12875717add9.png)

環境⇒キーボード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/73766185-608c-d806-359e-751be1446f25.png)

今回は ```Ctrl + W``` を『タブウィンドウを閉じる』に割り当ててみます。

まず、 ```Ctrl + W``` に **既に割り当てられている設定を削除** する必要があります。
キーボードショートカットへの割り当ては複数設定できます。
なのでこの『使用しない割り当ての削除』をしておかないと、思ったとおりの動作にならない場合があります。

ショートカットキーのところで ```Ctrl + W``` 。
これで割り当てられている設定が確認できます。
下記の場合は『編集.キータイピング登録』に既に割り当てられている状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c08096bb-76fc-92c4-6b96-b3118c81591d.png)

『以下の文字列を含むコマンドを表示』のことろで ```編集.キー``` 。
『編集.キータイピング登録』を選択したら、削除。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1ba9af0b-7f01-ca75-4213-f669f5323e52.png)

割り当ての削除が全て済んだら、次は自分が割り当てたい設定に移ります。
削除の時と同じようにコマンドの検索。
目当てのコマンドを選択した『割り当て』ボタン⇒OK。
VisualStudioの再起動は不要。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e053324b-b64e-9fc7-d2b3-fa61ac8a2bbd.png)

この設定をすると、例えば下記のような状態で ```Ctrl + W``` 押すと、Form1.csのタブを閉じられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5eaf7900-25f6-ffe7-2ca8-5a96c4d97b36.png)

# 参考サイトさん

https://docs.microsoft.com/ja-jp/visualstudio/ide/identifying-and-customizing-keyboard-shortcuts-in-visual-studio?view=vs-2022

# バージョン

Windows 10 Pro 21H2 OSビルド 19044.1889
Microsoft Visual Studio Community 2022 (64 ビット) - Current Version 17.3.0
Pumaの再起動に時間がかかる

本番のElastic Beanstalk環境にてRailsアプリをデプロイしたところ、Pumaの再起動に時間がかかりダウンタイムが発生しました。
なぜこの事象が発生したのかがわからず、調査を行ったので記録として残しておきます。

解決していないのでhelp wantedです。

## 前提
#### 環境
- ElasticBeanstalk環境 (Ruby 2.7 running on 64bit Amazon Linux 2/3.4.7)
- EC2インスタンス数:1台 (t3.medium)
- Puma 5.6.4

#### その他
デプロイ時にWeb、DBサーバーのCPU使用率、メモリ使用率に問題がないことから、インフラ側ではなくアプリ側の問題と推測しています。


## 発生した事象
デプロイ終了間際のアプリ再起動時に、Pumaが立ち上がるまでに時間がかかり(6分40秒)、その間にダウンタイム`502 Bad Gateway`が発生しました。

`/var/log/puma/puma.log`より
Pumaを落としたログ(17:56:22)
[![Image from Gyazo](https://i.gyazo.com/f430ab98948c10f2846ae2d6111398ce.png)](https://gyazo.com/f430ab98948c10f2846ae2d6111398ce)

Pumaが再度立ち上がったログ(18:03:02)
[![Image from Gyazo](https://i.gyazo.com/a88a6390bd38921ee536894d15701c3f.png)](https://gyazo.com/a88a6390bd38921ee536894d15701c3f)

デプロイログ(`/var/log/eb-engine.log`)を見ても、該当時間にてデプロイ処理が進んでいないことが確認できる。
```terminal:eb-engine.log
2022/09/09 17:56:22.324227 [INFO] Running command /bin/sh -c systemctl daemon-reload
2022/09/09 17:56:22.458577 [INFO] Running command /bin/sh -c systemctl reset-failed
2022/09/09 17:56:22.462352 [INFO] Removing /var/app/current/ if it exists
2022/09/09 18:03:00.882353 [INFO] Renaming /var/app/staging/ to /var/app/current/ # ここで6分38秒くらい処理が止まっている！！！
2022/09/09 18:03:00.882379 [INFO] Register application processes...
2022/09/09 18:03:00.882383 [INFO] Registering the proc: web
```

## 調査内容

### 1. 手動でPumaを再起動してみる
再現しないかEB環境にSSHして直接Pumaを何度か再起動してみる。

```terminal
$ sudo su
$ export $(sudo cat /opt/elasticbeanstalk/deployment/env) # 環境変数の読み込み
$ ps aux | grep puma # pumaのpid調査
$ pumactl -p 14271 restart # 上記で取得したpidを元にpumaの再起動
```

[![Image from Gyazo](https://i.gyazo.com/af3dbdddc060313b9f2ad9ea4cf74139.jpg)](https://gyazo.com/af3dbdddc060313b9f2ad9ea4cf74139)

事象再現せず。


### 2. ログローテーションの処理とPumaの再起動をぶつけてみる

現象再現時にElastic Beanstalkによりpuma.logのログローテーション処理が走っていたので、
手動でログローテションを行なって、その処理とPumaの再起動を同時に行なってみました。

```terminal
$ /usr/sbin/logrotate -f /etc/logrotate.elasticbeanstalk.hourly/logrotate.elasticbeanstalk.puma.conf #ログローテションの実行
$ pumactl -p 14271 restart
```

事象再現せず。


### 3. Elastic Beanstalkのログローテーションの処理とPumaの再起動をぶつけてみる

1時間に1度、Elastic Beanstalkによりシステム全体のログローテーション処理が走っているので、
そのタイミング周りで、手動でPumaの再起動を何度か行なってみました。

```terminal
$ pumactl -p 14271 restart
```

事象再現せず。


## 対応策
サービスグロースも伴ってインスタンスを増やそうとしていたので、
現在1台で動いているEC2インスタンス数を2台に増やし、ローリングでデプロイさせる方式で進めようと思います。

原因を特定できずに力技の対応になってしまいますが。。。
今後原因特定ができれば追記しようと思います。



ん〜悔しい。

## 追記
Puma Workerが全て落とされてから、再度起動するのはEBデプロイ時のデフォルト動作っぽい。
監視コマンドは下記
```terminal
$ watch -n 1 'ps -ef | grep puma'
```
※動画(右側がデプロイによりリスタートが走った時のPumaプロセス監視、6秒あたりでworker数が0になってる)
https://gyazo.com/49908a78db5e7ab7fac5804fc4f2378c

これはデフォルトのリスタート、下記コマンドと同等の動き。
```terminal
$ pumactl -p <pid> restart
```

下記のコマンドと同等の動き(片方のPumaWorkerのリスタートが完了した後に、もう1台のPumaWorkerをリスタートさせる)
をEBデプロイ時に実現できればなぁ、。
```terminal
$ pumactl -p <pid> phased-restart
```
Render.comでRailsアプリをデプロイする方法

Herokuの無料プランが廃止され、代替サービスのRender.comを使ってみました。

https://qiita.com/koki_73/items/60b327a586129d157f38

非常に参考になる記事がありましたので、まずは上の記事を読んでいただくことをおすすめします。
この記事では注意点を補足したいと思います。

# render.yamlの設定

Blueprintsを使用するために、render.yamlを設定します。
その時、`plan: free`が書かれていることを確認してください。
これを設定しないと、Render.comでBlueprint Instanceを作成する時、クレジットカードを要求されます。
```yaml:render.yaml
databases:
  - name: rails7_sample_staging
    databaseName: rails7_sample_staging
    user: rails7_sample
    region: singapore

services:
  - type: web
    name: rails7-sample-staging
    env: ruby
    region: singapore
    plan: free #確認
    buildCommand: "./bin/render-build.sh"
    startCommand: "bundle exec puma -C config/puma.rb"
    envVars:
      - key: DATABASE_URL
        fromDatabase:
          name: rails7_sample_staging
          property: connectionString
      - key: RAILS_MASTER_KEY
        sync: false
```

# データベースのエラー
以下のようなエラーが出てる場合、`bundle exec rake db:migrate`が出来ていない可能性が高いです。
```
# PostgreSQL
ActiveRecord::ConnectionNotEstablished (connection to server on socket /var/run/postgresql/.s.PGSQL.5432 failed: No such file or directory
```

その場合、Blueprintsが正しく設定できているか、`render-build.sh`を正しく設定できているか、`render.yaml`で`buildCommand: "./bin/render-build.sh"`と設定できているかを確認してください。

もしBlueprintsがどうしても設定できない場合、手動で設定することもできます。

1.Render.comのSettingsから`Build Command`・`Start Command`を下記のように設定してください。

```
# Build Command
./bin/render-build.sh
```

```
# Start Command
bundle exec puma -C config/puma.rb
```

2.Render.comのEnvironmentから`Environment Variables`を下記のように設定してください。


|Key|Value|
|---|---|
|RAILS_MASTER_KEY|`config/master.key`ファイルの内容を貼り付ける|

これでエラーが解決できると思います。

参考

https://render.com/docs/deploy-rails#deploy-manually
148.Proxyについて

#### Proxyオブジェクトの使いどころ
1.あるオブジェクトがありました
2.そのオブジェクトに対して『独自の処理』をしたい場合に使用する。
つまり、既存のオブジェクトのメソッドの機能を拡張したい時に使う
#### できること
1.メンバーに登録されていないプロパティを読んだ時に返される値を設定
2.ログを出力したり
3.プロパティに新しい値を書き込むなど、正しい値かチェックする、、など
『いつも通り、プロパティやメソッドを呼び出した時に追加で何かしてほしい時に使う』
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Meta_programming#Handlers_and_traps

イメージできるかわかりませんが
遊戯王で、『トラップカード発動！』ってありますが
攻撃すると呼び出されるという認識で、『トラップ』する。と呼びます。


## 実装方法
1.通常通りオブジェクトを生成
2.オブジェクトとは別にハンドラーを作成
3.トラップ名:関数(指定の引数)を加える
4.インスタンスを生成する
5.インスタンスにアクセスすることにより実行される
```javascript
//1.通常通りオブジェクトを生成
const targetObj = { a: 0 };
//2.オブジェクトとは別にハンドラーを作成
const handler = {
//3.トラップ名:関数(指定の引数)を加える
  set: function(target, prop, value, receiver) {
    console.log(`[set]: ${prop}`);
    // target[prop] = value;
    throw new Error('cannot add prop.');
  },
  get: function(target, prop, receiver) {
    console.log(`[get]: ${prop}`);
    if(target.hasOwnProperty(prop)) {
      return target[prop];
    } else {
      return -1;
    }
  },
  deleteProperty: function(target, prop) {
    console.log(`[delete]: ${prop}`);
    delete target[prop];
  },
}
//4.インスタンスを生成する
const pxy = new Proxy(targetObj, handler);
//5.インスタンスにアクセスすることにより実行される
// pxy.a = 1;
console.log(pxy.b);
delete pxy.a;
```
[AppSheet] スプレッドシートのフォルダ名を変更する

# データフォルダの名前変更について

データソースとして利用している Google スプレッドシートの保存フォルダ名を変更しました。
その時の手順を記しておきます。

## Google ドライブ側の変更

Google ドライブを開き、マイドライブ > appsheet > data フォルダへ移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/4e438fd0-f6ad-c529-7707-84891c5e9234.png)

対象のフォルダを右クリックして、[名前を変更]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/e7f55e40-aaf5-9464-9645-8026229ca573.png)

新しいフォルダ名を入力して変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/4d7e6b18-d9fa-0b58-57af-ed014db4955d.png)


## AppSheet 側の変更

特に何もする必要はありません。

Google ドライブのフォルダは一意な ID を持っており、名前変更してもその ID が変わらないため、AppSheet との紐づけも影響を受けないのだと思います。

もしスプレッドシートを新たに作成、もしくはコピーした場合は、以下の手順で再設定が可能です。

左メニューの [Data] -> [Tables] タブ -> 対象のテーブルをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/7b91f9c8-836a-bbc8-0c3c-b10de3036b13.png)

[Table name] が対象テーブルであることを確認し
[Storage] -> [Source Path] -> [- browse for more data -] をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/ef6c7515-35cd-898a-685c-959769f11702.png)

[Google Sheets] をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/5decdfe0-8b8b-ee01-9554-9b7ca289e88e.png)

[My Drive] > appsheet > data から対象のシートを選択し、最後に [Select] で決定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/acbcc08a-6466-e9d6-4c65-ea960bd02874.png)

右上の [SAVE] で保存します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/8cf37da2-bc38-fc98-ac86-d13e4da9a763.png)


## 動作確認
以上で完了です。
あとはアプリが正常に動作することを確認します。

# 画像フォルダへの影響
本環境ではスプレッドシートの他に画像ファイルのアップロードを同フォルダ内のサブフォルダに保存・参照していました。

設定上は [Table] の [Column] の [TYPE] を [Image] としていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/e60c71a3-71e3-6899-c297-f4d8842ce9e8.png)

この場合は、スプレッドシートに記録されるパスは [スプレッドシート名] が付いた相対パスとなります。

フルパスではなく相対パスだったので、親フォルダ名が変更されて影響はありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/4da484ce-cb56-6ea1-38a6-ffba978ff808.png)


# スプレッドシートの名前変更

こちらも Google ドライブ側で名前変更するだけで反映されました。
【PHP8.1】あなたはどっち？ array_merge VS unpacking（スプレッド演算子）

PHP8.1がリリースされてそろそろ1年。PHP8.1のRelease Announcementを今更じっくりと眺めていたところ、見逃していた変更点を発見。

**Array unpacking support for string-keyed arrays**
[https://www.php.net/releases/8.1/en.php](https://www.php.net/releases/8.1/en.php#array_unpacking_support_for_string_keyed_arrays)

配列アンパックが連想配列をサポートするようになった、とのこと。
配列アンパックとは、一般的にいう『スプレッド演算子』『スプレッド構文』のことです。

```php:アンパック例
$x = ['a' => 1, 'b' => 2];
$y = ['c' => 3, 'd' => 4];
$result = [...$x, ...$y];
// ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]
```

これによって、array_mergeを完全にアンパックに置き換える事が可能になった、ということになりそう。
もうarray_mergeを使うこともなくなるかな、と思いつつ、念のためパフォーマンスを比較してみることに。

## 検証

```php:比較用コード（PHP8.1.9）
// 1000個ほどの要素をもつ連想配列を２つ用意する
$str = join([...range(0, 9), ...range('a', 'z'), ...range('A', 'Z')]);
$arr1 = $arr2 = [];
for ($i = 0; $i < 1000; ++$i) {
	$arr1[str_shuffle($str)] = $i;
	$arr2[str_shuffle($str)] = $i;
}

// array_mergeを1万回実行するのに要した時間
$start = microtime(true);
for ($i = 0; $i < 10000; ++$i) {
	$tmp = array_merge($arr1, $arr2);
}
echo 'array_merge:' . (microtime(true) - $start) . "\n";

// アンパックを1万回実行するのに要した時間
$start = microtime(true);
for ($i = 0; $i < 10000; ++$i) {
	$tmp = [...$arr1, ...$arr2];
}
echo 'unpacking:' . (microtime(true) - $start) . "\n";
```

|            | array_merge | unpacking    |
|:-----------|------------:|:------------:|
| 1st        | 0.606       | 1.031        |
| 2nd        | 0.626       | 1.044        |
| 3rd        | 0.620       | 1.076        |
| 4th        | 0.613       | 1.046        |
| 5th        | 0.621       | 1.039        |

一般的には関数より構文のほうが処理速度が速いといわれていますが、意外な結果になりました。

どうしても納得できず・・・
2つの配列の要素数を100に減らしてみましたが、array_mergeの圧勝。
2つの配列を添字配列にしてみましたが、array_mergeの圧勝。
結合する配列数を増やしてみましたが、array_mergeの圧勝。

せめてメモリ使用量はアンパックに軍配が上がって欲しい・・・と
memory_get_peak_usageを仕込んでみましたが、array_mergeのほうがやや優れていました。

## 結局どっちを使えばいいの？

他にもいくつかのパターンを比較してみましたが、
すべてではないにしろ、パフォーマンスの面ではarray_mergeのほうが優れているという結果になりました。

特にパフォーマンスが重要な場面ではarray_mergeを使う選択肢はありそうですが、
この程度のパフォーマンス差であれば、どちらかにこだわる必要もないかなと。

個人的にはアンパックを積極的に使っていこうと思います。

ご指摘・ご意見などありましたら、ぜひコメントお願いします。
Adminロールを持つユーザーが削除できない

概要
-
Adminロールを削除しようとすると「構成された2人のアクティブなアプリケーション管理者よりも少ないため、役割を削除できません」というエラーメッセージが表示され実施できない。

エラー詳細
-
System Administratorアカウントを使い、ユーザーからadminロールを削除しようとすると次のエラーメッセージが表示され、実施できませんでした。
__「このロールは、構成された2アクティブアプリケーション管理者よりも少ないため削除できません。」__

[KB0857988](https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0857988)を参考に設定をしたが、同様のエラーのメッセージが表示され解決せず。

原因
-
adminロールには、「sn_templated_snip.template_snippet_admin」と「sn_hr_sp.esc_admin」ロールが含まれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840666/2672d0e2-6f4e-d294-0124-f596dc206a6e.png)
この２つのロールにはそれぞれシステムプロパティ「sn_templated_snip.min_admin_count」と
「sn_hr_sp.min_admin_count」があり、「sn_templated_snip.template_snippet_admin」と「sn_hr_sp.esc_admin」のロールを持つユーザーがインスタンスに何人存在しているかをチェックしています。
デフォルトのプロパティの値は 2 のため、このロールを持つユーザー数が 2 未満になるとシステムはそれを許可せず、エラーメッセージが表示される仕様となっています。

解決方法①
-
__＜システムプロパティの値を変更したくない場合＞__
1．System Administratorでログイン。
2.ユーザーテーブルのリスト画面から任意の2ユーザーに対して
「sn_templated_snip.template_snippet_admin」と「sn_hr_sp.esc_admin」ロールを付与し保存。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840666/30dcb1b3-9d1b-0d55-48b5-6e7470205534.png)
3．ユーザーテーブルのリスト画面からadmin権限を持つアカウントを選択。
4．ロールタブの編集を選択。
5．adminロールを選択、削除し保存を選択。
6.エラーメッセージ「このロールは、構成された2アクティブアプリケーション管理者よりも少ないため削除できません。」が表示されないことを確認。

解決方法②
-
__＜System Administrator以外にadmin権限を付与したくない場合＞__
1.システムプロパティ「sn_templated_snip.min_admin_count」と
「sn_hr_sp.min_admin_count」の値を1に変更し更新を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840666/8f9d6dc2-5f82-81d3-ed7c-8044927f10c0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840666/d1f6ba8b-5c47-3bbb-412a-b55183454a22.png)
2．ユーザーテーブルのリスト画面からadmin権限を持つアカウントを選択。
3．ロールタブの編集を選択。
4．adminロールを選択、削除し保存を選択。
5.エラーメッセージ「このロールは、構成された2アクティブアプリケーション管理者よりも少ないため削除できません。」が表示されないことを確認。


以上
Googleグループ（メンバーや設定）の一覧を出力してみた

##概要
タイトルどおりです。[こちら](https://zenn.dev/a03/articles/a5ea329ccdaa92)をベースに書いてみました。

##今回詰まった点：
配列同士ってくっつけたりできるの？って悩んでました
[これ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/push)で出来た。

###コード：
[GitHub](https://github.com/sakichi33/gas-getgroupinfo)に移しました。
Qiita投稿のメリット

# はじめに
Qiitaで投稿し始めて2年経過&投稿数は70を超えたので、その過程で感じたメリットを記述。

# メリット
#### アウトプット力が身につく
* 伝えたいことだけに絞って簡潔にアウトプットできるようになる。
* どういう言い回しだと伝わるか考えるようになる。
* アウトプットすることにより投稿内容への理解が深まる。
* 公の場に投稿するので、丁寧な投稿を心がけるようになる。

#### 自分で見返せる
* 一度躓いた箇所で躓かないようになる。車輪の再発明が無くなる。
* 異なるPCでの作業でもネットに繋がっていれば閲覧可能になる。
* 投稿後改めて自分で見返すと、分かりにくい表現が見つかるようになる。その場合は編集して再投稿する。

#### 第三者に見てもらえる
* 他の人への手助けになる。
* 第三者視点のフィードバックが貰える。
* いいねが貰えると嬉しい。

# おわりに
Qiita投稿により、アウトプットの重要性が実感できた。今後はQiita以外の媒体で技術面以外のアウトプットもやってみたい。
[Rails]selectフォームにenumのリストを表示する2つの方法

すんごい基礎的な内容なのですが、２通りのやり方に出会ったので整理したかったのと、地味なとこでハマったので備忘録。

## やりたいこと
Postモデルにstatusというenumがあるとする。

```ruby
class Post < ApplicationRecord
  enum status: { active: 10, inactive: 20 }, _prefix: true
end
```

これをこういう感じ↓で表示したい。
![スクリーンショット 2022-09-12 12.09.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645077/b0e3c242-c7da-f570-f417-f87c24cf5242.png)

htmlはこう。ブラウザで見える文字列とvalue属性を渡してあげたい。

```html
<select class="form-control" name="post[status]" id="post_status">
  <option selected="selected" value="active">有効</option>
  <option value="inactive">非有効</option>
</select>
```

selectの出力にはRailsのselectメソッドを使う。
https://railsdoc.com/page/select

```
# f.object
f.select(メソッド名, 要素(配列 or ハッシュ)=nil, オプション={}, HTML属性={} or イベント属性={}, ブロック引数)
```

第二引数には以下のようなハッシュ、もしくは配列を渡してあげれば良い。

```
# { "ブラウザで見える文字列"=>"value属性" }
=> {"有効"=>"active", "非有効"=>"inactive"}
```

## 1. gemを使わず自分でメソッドを作るやり方

こちらを参照しました。gemを無闇に使いたくないならこれ。

https://qiita.com/daichirata/items/9495e2548417a4507fec


```yaml:config/locales
ja:
  activerecord:
    attributes:
      post/status:
        active: 有効
        inactive: 無効
```

```erb:view
<%= f.select(:status, Post.status_options, {}, class: 'form-control') %>
```

```ruby:app/models/post.rb
  def self.status_options
    statuses.map { |k, _| [human_attribute_enum_value(:status, k), k] }.to_h
  end

  def self.human_attribute_enum_value(attr_name, value)
    human_attribute_name("#{attr_name}.#{value}")
  end

  def human_attribute_enum(attr_name)
    self.class.human_attribute_enum_value(attr_name, self[attr_name])
  end
```

## 2. gem使う。 "exnum"でやる。

exnumはこちら。
https://github.com/Kta-M/exnum#array-for-select-box-extention

https://qiita.com/Kta-M/items/04ec2f52af4d64930429

```ruby:Gemfile
gem 'exnum'
```

↓ここが地味にハマった。`enum`を`exnum`にしないといけない。

```ruby:app.models/post.rb
  exnum status: { active: 10, inactive: 20 }, _prefix: true
```

```yaml:config/locales/
ja:
  activerecord:
    enum:
      post:
        status:
          active: 有効
          inactive: 非有効
```

ここまですると以下のようなメソッドが使える。

```ruby
[1] pry(main)> Post.statuses_i18n
=> {"active"=>"有効", "inactive"=>"非有効"}

[2] pry(main)> Post.statuses_i18n.invert
=> {"有効"=>"active", "非有効"=>"inactive"}

[3] pry(main)> Post.statuses_for_select
=> [["有効", "active"], ["非有効", "inactive"]]
```

これ↑の1だとブラウザで見える文字列とvalue属性が逆になっちゃうので、2か3をselectの引数に渡してあげればOK。

```erb:view
<%= f.select(:status, Post.statuses_i18n.invert, {}, class: 'form-control') %>
```

## どっちにするんだい！？

modelに色々メソッドとか書きたくないので、gem使う方に一票。
Dockerで構築したNext.jsの開発環境に、Storybookを導入する

最近Dockerで構築したNext.jsの開発環境にStorybookを導入して遊び始めたので、その手順を忘れないうちに残しておこうと思います(少し詰まったところもあったので…)。  
ついでなので、簡単にですがNext.jsプロジェクトを作成するところから書いていきます。

## 使用環境

* Windows10 Pro
* Docker version 20.10.17-rd  

## (前準備)Next.jsのプロジェクトを作成

まずはNext.jsのプロジェクトを作成するため、Dockerfileとdocker-compose.ymlを作成します。  
初期状態のディレクトリ構成はこんな感じ(srcディレクトリは空です)↓

```
.
├ docker
|    ├ Dockerfile
|    └ docker-compose.yml
└ src
```

* Dockerfile

```Dockerfile:Dockerfile
FROM node:18.9.0-alpine3.16

WORKDIR /usr/src

RUN npm install -g npm@latest && npm install create-next-app
```

* docker-compose.yml

```yml:docker-compose.yml
version: '3'
services:
  app:
    build: ./
    container_name: next
    tty: true
    volumes:
      - ../src:/usr/src
    ports:
      - "3000:3000"
      - "6006:6006"
    command: sh -c "npm run dev"
```

上記の準備を終えたら、次のコマンドを実行します。  

```shell:PowerShell
docker-compose build
# TypeScriptを使用するので「--ts」を付けてます
docker-compose run --rm app npx create-next-app ../src --ts
```

これでアプリのひな型がsrcディレクトリ内に作成されました。

## Storybookの導入

ここから本題です。  

```shell
docker-compose up -d
docker exec -it next sh
```

まずはコンテナを起動して中に入り、

```shell
npx sb@latest init
npm run storybook
```

上記コマンドでStorybookを導入、そして起動するだけ。　
<localhost:6006>にアクセスすると、Storybookが表示されていることを確認できるかと思います。  

![スクリーンショット _storybook_start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780581/bc8a5dea-8486-40b7-e36b-1aa466e8b988.png)

## 試しにコンポーネントを実装してみる

実際にコンポーネントを実装してみて、Storybookで表示されるかを見てみましょう。  

srcディレクトリ内に`components/SampleButton/index.tsx`というファイルを、src/storiesディレクトリ(create-next-app時に作成されているはずです)内に`SampleButton.stories.tsx`ファイルをそれぞれ作成し、以下のように実装します。  

```tsx:components/SampleButton/index.tsx
type SampleButtonProps = {
  backgroundColor: string;
  color: string;
  border: string;
}

export const SampleButton = (props: SampleButtonProps) => {
  const {backgroundColor, color, border} = props

  return (
    <button style={{backgroundColor: backgroundColor, color: color, border: border}}>
      SampleButton
    </button>
  )
}
```

```tsx:stories/SampleButton.stories.tsx
import { ComponentMeta } from "@storybook/react";
import { SampleButton } from "../components/SampleButton";

// ファイル内のStoryの設定
export default {
  // グループ名
  title: 'SampleButton',
  // 使用するコンポーネント
  component: SampleButton,
} as ComponentMeta<typeof SampleButton>

export const RedSample = () => {
  return (
    <SampleButton {...{backgroundColor: "#ff0000", height: "36px", width: "100px"}}>
      Red
    </SampleButton>
  )
}
```

再度Storybookを起動して、<localhost:6006>を見に行くと…

![スクリーンショット_storybook_samplebutton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780581/4622072b-8f6c-46d2-e9fe-b57c7ed4f852.png)


新しく作成したコンポーネントを、Storybookで表示することができていました！  

## おわり

以上、DockerでNext.jsの開発をする際にStorybookも導入してみる手順でした。  
ちなみにどこに一番時間がかかったというと、docker-compose.ymlに`- "6006:6006"`の記述が抜けていて、「なんでつながらないの？？ローカルだとできるのにぃ…」と半日くらい頭を抱えていたところです(ローカルでやりなさいよ…)。

## 参考資料

[TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発](https://gihyo.jp/book/2022/978-4-297-12916-3)
Azure Pipelines にて異なるジョブ間で変数を利用する場合には dependsOn が必要

## 概要

Azure Pipelines にて異なるジョブ間で変数を利用する場合には dependsOn が必要となるようです。

下記のようなジョブをもつパイプラインを実行する場合に、変数を定義している①のジョブに直接依存関係がある③にて①で定義した変数を利用でき、依存関係がない④では①で定義した変数を利用できませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/85d1b2a8-6cea-a828-11cc-dbb462d146d8.png)

下記のように、明示的に変数を定義している（`set_var`）に対して`dependsOn`の指定をする必要があります。

```yaml
- job: can_get_variable
  dependsOn:
    - server_task
    - set_var
  variables:
    SET_VAR: $[ dependencies.set_var.outputs['set_var.MyVar'] ]
  steps:
  - checkout: none
  - task: CmdLine@2
    displayName: Execute Databricks Workflow of test
    inputs:
      script: |
        echo $(SET_VAR)
```

## 詳細

### 実行 YAML

```yaml
jobs:
- job: set_var
  steps:
  - checkout: none
  - task: CmdLine@2
    displayName: Execute Databricks Workflow of test
    name: set_var
    inputs:
      script: |
        echo "##vso[task.setvariable variable=MyVar;isOutput=true;]abc"
- job: server_task
  dependsOn: set_var
  pool: Server
  steps:
  - task: Delay@1
    displayName: 'Delay'
    inputs:
      delayForMinutes: 0
- job: can_get_variable
  dependsOn:
    - server_task
    - set_var
  variables:
    SET_VAR: $[ dependencies.set_var.outputs['set_var.MyVar'] ]
  steps:
  - checkout: none
  - task: CmdLine@2
    displayName: Execute Databricks Workflow of test
    inputs:
      script: |
        echo $(SET_VAR)
- job: can_not_get_variable
  dependsOn:
    - server_task
    # - set_var
  variables:
    SET_VAR: $[ dependencies.set_var.outputs['set_var.MyVar'] ]
  steps:
  - checkout: none
  - task: CmdLine@2
    displayName: Execute Databricks Workflow of test
    inputs:
      script: |
        echo $(SET_VAR)

```

### ①`set_var`の実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7d821437-69e0-7f52-1e20-83da322e59af.png)

### ②`server_task`の実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3ffad131-8b1c-cb69-2b8d-44af35363737.png)

### ③`can_get_variable`の実行結果

`echo` で呼び出すことができている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/662bf5ed-6e5a-1d25-d4d0-0329534bd8c4.png)

### ④`can_not_get_variable`の実行結果

`echo` で呼び出すことができていない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/556b64a2-cee3-5460-d7c7-b75f4604a164.png)
【Python】min/max関数は文字列にも使える

昨日のプロコン解説を見て初めて知ったので、メモ

## 文字列に`min/max`関数を使うと**辞書順最小/最大**の文字列を返す

#### サンプル
```python
print(min("a","b"))
print(max("a","b"))
```

#### 実行結果
```
a
b
```

## **リスト**についても同様に**辞書順最小/最大**の文字列を返す
#### サンプル
```python
print(min(["a","b","c"]))
print(max(["a","b","c"]))
```

#### 実行結果
```
a
c
```

## 文字列と数値を引数にするとエラーが発生する
#### サンプル
```python
print(min("2",1))
```

#### エラー文
```
TypeError: '<' not supported between instances of 'int' and 'str'
```
__swift_FORCE_LOAD_$_swiftCompatibilityConcurrencyでハマった

FlutterでFirestoreビルド短縮のため `firestore-ios-sdk-frameworks` を導入したらドハマリしました。

# 解決策
XCodeを最新にしましょう。
今回は
`13.0.0 → 13.4.1`
で解決しました。
__swift_FORCE_LOAD_系のエラーはXCode更新で解決することがある模様。
あとはSwiftサポートが有効になってなくてもなることがあるらしいです。

解決の糸口になった記事
https://developers.facebook.com/docs/audience-network/setting-up/platform-setup/ios/add-sdk?locale=ja_JP

# 備考
時間返せ
Excel出力するcaxlsx_railsの使い方について

## 環境
Rails 5.2
Ruby 2.6
Ubuntu 20.4


## はじめに
RailsでExcel出力をする方法についての記事です。Excel出力をするgemに**caxlsx_rails**を利用します。RailsでExcel出力する方法についてググると、**axlsx_rails**というgemに関する情報が多く検索されます。caxlsx_railsの公式サイトを見ると、以前は、axlsx_railsという名前のgemで提供されていたが、caxlsx_railsという名前に変更されているようです。

caxlsx_railsの公式サイト
https://github.com/caxlsx/caxlsx_rails

## Excel出力の仕方
Gemfileに下記のgemを追加して、**bundle install**を実行します。
```Gemfile
gem 'caxlsx_rails'
```

Excel出力をするメソッド名をこの記事ではexportとします。routesにtasksコントローラーのexportメソッドへのルート情報を記述します。
```routes.rb
resources :tasks
    get :export,  on: :collection
end
```

コントローラーにexportメソッドを記述します。tasksテーブルの内容を全件取得して、Excelファイルに出力します。ExcelファイルはTask一覧.xlsxというファイル名にしています。ファイル選択のサブ画面を表示して、任意のファイル名を初期表示することができます。サブ画面では初期表示されたファイル名を変更することができます。
```tasks.rb
def export
    @tasks = Task.All
    respond_to do |format|
        format.xlsx do
            response.headers['Content-Disposition'] = 'attachment; filename="Task一覧.xlsx"'
        end
    end
end
```

ビューで処理を実行するボタンを記述します。form_tagではなく**link_to**にしなくてはいけないところがポイントです。
```index.html.slim
= link_to "Excel出力", tasks_path(@tasks, format: :xlsx)
```

viewフォルダの配下に、excel.xlsx.axlsxファイルを作成します。公式サイトにテンプレートがあるため、それを参考にするといいでしょう。**wb.add_worksheet**でExcelのタブ名を指定できます。下記では、tasksテーブルの、idとTask名を出力しています。また、Excelの１行目にタイトルを出力しています。
```excel.xlsx.axlsx
wb = xlsx_package.workbook
wb.add_worksheet(name: "Task一覧") do |sheet|

    sheet.add_row %w(id Task名)

    @tasks.each do |task|
        sheet.add_row do |row|
	        row.add_cell(task.id)
	        row.add_cell(task.tasknm)
	    end
    end
end
```
Unreal EngineでTriplanar Mapping

Unreal EngineのマテリアルでTriplanar Mappingを作成してみます。検証に使用したUnreal Engineのバージョンは5.0.3です。

---

マテリアルのネットワーク全体は次のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/e3eab242-bc3e-2ffe-bc67-ea1bcc8a3c16.png" width="50%">

上部でXYZの各方向に対する重みを計算し、下部で各方向ごとにテクスチャをサンプリングします。最後にそれぞれで求めた値を用いて重み付き和を計算します。

このマテリアルを適用すると次のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/b7d3422e-c14d-e318-313c-b03b8f0115ba.png" width="50%">


以下ではネットワークの各箇所を詳しくみていきます。

---

重みの計算部分です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/c1d42f87-ebd2-29c2-6a79-ebefe02ffcf4.png" width="50%">


法線の絶対値に対してブレンド部分の鋭さを調整するために累乗を計算し、重みの和が1になるようにします。プレビュー表示は次のようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/3a5e709d-0f2c-1da7-2773-f3b6b08d5a72.png" width="50%">

---

テクスチャのサンプリング部分です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/c6d7755f-1be0-9bdd-0d22-f0f4d3c0482f.png" width="50%">

ワールド座標を利用してX方向(YZ平面)、Y方向(ZX平面)、Z方向(XY平面)ごとにサンプリングします。プレビュー表示は次のようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/bd1ca168-7dd0-d59d-6570-4219504b9e75.png" width="50%">

各方向のUV値を求める箇所が少し複雑ですが、こうすることで以下のようにテクスチャが反転したりせず適用することができます。
![TestPattern.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/18dce2fa-4dcd-9804-3888-f301036cf010.gif)

例えば以下のように、もっとシンプルに各方向のUV値を求めることもできますが、気をつけないと2つ目の画像のようにテクスチャのブレンド部分付近で同じUV値となることで対称な構造(わかりづらいですが中心付近から右上へ延びる部分)ができてしまうことがあるので注意が必要です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/18caf7ce-9401-433a-8ddb-678809b2279a.png" width="50%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/b9b202a3-395a-0021-e64e-98857f6f6533.png" width="50%">

--- 


テクスチャのサンプリング値と重みの積を合計している箇所です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/a8259b1b-0a0b-02ba-5386-8b9dcca772f5.png" width="50%">

プレビュー表示は次のようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/2f32a971-6647-4631-7697-82e124224035.png" width="50%">