OmniAICreator/Qiita-1.07M huggingface dataset:
パーセプトロンとは

# パーセプトロンとは
<!-- 発端や概要を記載 -->
・パーセプトロンの仕組み：複数の入力を重み付けして、０か１を出力するもの。	
	　　　　　　　　　　　　　（＝ある入力を与えたら、決まった値が出力される。）
・パーセプトロンでは、「重み」と「バイアス」をパラメータとして設定する。	
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/ca9fe18c-e023-bed6-2f4f-f83c054790e8.png"width=40%>


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [線形と非線形](#線形と非線形)
1. [多層パーセプトロン](#多層パーセプトロン)
1. [多層パーセプトロンのアルゴリズム](#多層パーセプトロンのアルゴリズム)
1. [パーセプトロンのコーディング](#パーセプトロンのコーディング)
1. [多層パーセプトロンの例](#多層パーセプトロンの例)
1. [参考文献](#参考文献)

<!-- 各チャプター -->
<a id="#線形と非線形"></a>
# 線形と非線形
・線形：AND / OR / NAND ゲート	
・非線形：XORゲート　（線形分離不可能）	
　　　　　→XORゲートは単層のパーセプトロンでは表現できない。（２層以上必要）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/4e3658b1-0ccf-fcbe-c832-c704cf0466aa.png"width=40%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/25e437c6-a99a-d514-d5d7-3f30b8b8d9fc.png"width=80%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/5c1b07f0-9764-db0d-2b81-c591d928afee.png"width=30%>


<a id="#多層パーセプトロン"></a>
# 多層パーセプトロン
（多層パーセプトロン＝ニューラルネットワーク）
多層パーセプトロン：少なくとも3つの層（入力層(m)・中間層(n)・出力層(o)）を持つ。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/f290c481-253a-bdc5-1bcb-d807d764419a.png"width=40%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/da617bc5-fe9e-2e47-ce7e-1b085202cd4e.png"width=60%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/ca262eeb-e21e-4aaf-e805-fb45e4104c25.png"width=80%>




<a id="#多層パーセプトロンのアルゴリズム"></a>
# 多層パーセプトロンのアルゴリズム

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/bc5a3896-3178-1696-5d25-759d67fe4989.png"width=80%>

<a id="#パーセプトロンのコーディング"></a>
# パーセプトロンのコーディング

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/29232829-e17a-c338-62cf-12dfcf25de0b.png"width=90%>

<a id="#多層パーセプトロンの例"></a>
# 多層パーセプトロンの例

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/a646c74a-40b2-d79a-fe2d-4ceef66daa88.png"width=50%>

・上記の図は、2入力・1出力の多層パーセプトロン
・入力層はm=2，中間層はn=4，出力層はo=1
・重みwは m×n=2×4=8 の要素で構成される行列
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/425d92e1-a987-2348-4874-d7fd68aa624c.png)

・中間層の中間出力yは下記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/96ae0f36-20e9-a0fb-1e1c-7cf591b3f27b.png)

・この中間出力yに活性化関数fを適用し、中間層の最終的な出力となる。

---
その他参考資料
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/ee3df0a9-66f1-b26d-d2cf-01887560384c.png)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/c8e342a2-6f45-aefc-bed4-68ecf7c2ae36.png"width=70%>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/7e6354e3-8fd4-f466-aeaa-fe99dfe36204.png)
引用：http://www.sakurai.comp.ae.keio.ac.jp/classes/infosem-class/2010/05MLP.pdf

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089224/26b397c4-8f7f-5e08-cee8-9ce7f65dd7fd.png)
引用：http://www.sakurai.comp.ae.keio.ac.jp/classes/infosem-class/2010/05MLP.pdf


<a id="#参考文献"></a>
# 参考文献
- [書籍、ウェブサイト](URL)
- [リンクテキスト](URL)
UNIX ファイルシステムへのアクセス検査

z/OS UNIXでは、一般のUNIX/Linuxと同じようにOwner,Group,OtherのPermissionとACLリストによる管理ができるのですが、それに加えてSecurity Server (RACF)による追加のアクセス権の検査が追加できるため、全く同じ挙動にならないことがあります。
こちらのマニュアルにアクセスの検査についての一連の流れが書かれているので非常に参考になります。

<B>z/OS UNIX ファイルおよびディレクトリーへのアクセス許可</B>
https://www.ibm.com/docs/ja/zos/2.3.0?topic=resources-authorizing-access-zos-unix-files-directories
scipy.stats: 1 標本 t 検定 ttest_1samp

# scipy.stats: 1 標本 t 検定 `ttest_1samp`

`scipy.stats.ttest_rel` の項で既に書いたが，これはこれで改めて書き起こす。

1 標本 $t$ 検定は，2 つの局面で使われる。

1. 本当に 1 つの標本の，母平均の検定として
1. 本当は 2 つの対応のある標本の母平均の差の検定として

後者の場合は `scipy.stats.ttest_rel` を使えばよいが，対応するデータの差をとって `scipy.stats.ttest_1samp` を使うこともできる。その際，差の母平均が 0 であるかの検定になる。


```python
from scipy.stats import ttest_1samp
```

`ttest_1samp(a, popmean, axis=0, nan_policy='propagate', alternative='two-sided')`

# 1.　母平均の検定

検定したい母平均を `popmean` で指定する。

例題:　ある工業製品の重さは規格により 10g とされている。20 個の製品の重さを測定したところ，以下のようになっていた。母平均は 10g といえるか?
<pre>
 9.99941 10.00150 10.00078  9.99899  9.99992
10.00215  9.99807 10.00007 10.00177  9.99963
 9.99982 10.00041 10.00199  9.99986 10.00006
10.00007 10.00271 10.00269 10.00150 10.00089
</pre>
帰無仮説 $H_0$:　母平均は 10g である。
対立仮説 $H_1$:　母平均は 10g ではない。


```python
x = [
      9.99941, 10.00150, 10.00078,  9.99899,  9.99992,
     10.00215,  9.99807, 10.00007, 10.00177,  9.99963,
      9.99982, 10.00041, 10.00199,  9.99986, 10.00006,
     10.00007, 10.00271, 10.00269, 10.00150, 10.00089
    ]

from scipy.stats import ttest_1samp
ttest_1samp(x, popmean=10)
```




    Ttest_1sampResult(statistic=2.1828817986464135, pvalue=0.04179698621109555)



結論: $p$ 値が 0.0418 なので，有意水準 5% で帰無仮説は棄却される。すなわち，母平均は 10g ではないという結論になる。

なお，標本平均，標本標準偏差は以下の通りである。


```python
np.mean(x), np.std(x, ddof=1)
```




    (10.0006145, 0.0012589447335390237)



# 2.　母平均=0 の検定

対応のある 2 標本の母平均の差の検定は，対応するデータの差をとって母平均=0 の 1 標本検定を行うのと同じである。

例題:　東京都の新型コロナの新規感染者数は以下のようであった。
<pre>2022/05/15（日）からの一週間  3348, 2377, 3633, 4355, 4712, 3573, 3467
2022/05/22（日）からの一週間  3317, 2025, 3271, 3929, 3391, 2530, 2549
</pre>
このデータは曜日で対応付けられた対応のある 2 標本データと見てよい。15日からの週と，22日からの週の母平均に差があるだろうか?


```python
import numpy as np
w15 = np.array([3348, 2377, 3633, 4355, 4712, 3573, 3467])
w22 = np.array([3317, 2025, 3271, 3929, 3391, 2530, 2549])
dif = w15 - w22
print(np.mean(w15), np.mean(w22), np.mean(dif))
```

    3637.8571428571427 3001.714285714286 636.1428571428571



```python
import matplotlib.pyplot as plt
plt.plot(range(7), w15)
plt.plot(range(7), w22)
plt.legend(['05/15〜', '05/22〜'])
plt.xticks(range(7), ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'])
plt.ylabel('人数');
```


    
![output_10_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/6eef25f1-3fc4-e26d-0a63-50950e57d83d.png)
    


```python
from scipy.stats import ttest_rel, ttest_1samp
ttest_rel(w15, w22)
```




    Ttest_relResult(statistic=3.643603278912914, pvalue=0.010788365449744446)




```python
import matplotlib.pyplot as plt
plt.plot(range(7), dif)
plt.legend(['差'])
plt.xticks(range(7), ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'])
plt.ylabel('人数');
```


    
![output_12_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/9fb5660a-af55-4c0f-6594-238d3bda0961.png)

    



```python
ttest_1samp(dif, popmean=0)
```




    Ttest_1sampResult(statistic=3.643603278912914, pvalue=0.010788365449744446)


`ttest_rel` の結果は `ttest_1samp` と同じになる。

結論: $p$ 値が 0.0108 なので，5% 有意水準のもとで帰無仮説は棄却される。すなわち，5/15 の週と 5/22 の週では，母平均に差があるといえる。
[Rails] コードに全角スペースが混ざるとCSSレイアウトに影響が出る事がある

初投稿です。
プログラミングを初めて3ヶ月。
備忘録としてつまづいたところを記載し、アウトプットツールとして活用していきます。

# なんかレイアウトがちょこちょこズレてる
BootstrapとCSSを使ってレイアウト調整を行っていたが
コンテンツの配列がどう調整しても合わない、、、
（ここでは一旦画像は添付しませんが、、、）

# 検証ツールを開いて確認
原因わからず、、、

# メンターに聞く
コード的には問題ない。
残るは全角スペースが悪さしているかもとのこと。
command + Fで全角スペースを検索すると、、、、

なんとか数カ所出てきた！！

# 半角に修正
直った！！！

プログラミングにおいて全角は敵すぎる、、、、
そんな事を痛感した瞬間でした。

スペースは気づかない事多いけど
ちょこちょこ確認していこうと思います！！
mp4の動画なのにTwitterに投稿できないときにすること

# Twitterに動画を投稿できない

- mp4でサイズは512MB以下
- 動画の時間も2分20秒以内
- なのに動画を投稿できない！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96970/d4ec6faf-73b0-462c-7f9f-485c7bbb2d58.png)

詳細はこちら

https://help.twitter.com/en/using-twitter/twitter-videos

> モバイルアプリではMP4とMOVの動画形式をサポートしています。
ブラウザではMP4（H264形式、AACオーディオ）をサポートしています。アップロードできる動画のサイズは最大512MBです。ただし長さは2分20秒間以下にしてください。

ほうほう、mp4の形式に問題がありそうだ。

どうすればいいのか、解決したい

# 結論

ffmpegのコマンド

```
ffmpeg -i input.mp4-vcodec libx264 -pix_fmt yuv420p -strict -2 -acodec aac output.mp4
```

を叩く。

この結果

- フォーマットをyuv420pにする
- コーデックをaacにする


ことにより投稿可能な形式になるようです。

参考記事はこちら

https://kivantium.hateblo.jp/entry/2017/07/16/160859


# 投稿成功したTweet

https://twitter.com/iwaken71/status/1531883790368645120?s=20&t=PuXiXlbhaRGgRI_EhgB45g
Python　yamlファイルからデータを抽出する方法


#### ソースコード

``` python
#!/usr/bin/python3

import yaml

with open('testdata.yaml') as file:
  yaml_file = yaml.safe_load(file)
  all_parameter = yaml_file['parameter_defaults']
  for data in all_parameter:
    if 'name' in data:
      print(yaml_file['parameter_defaults'][data])
```

#### yamlファイル

``` yaml
parameter_defaults:
  name: aaa
  age: 5
```

#### 実行結果

``` shell
$ ./test-yaml.py
aaa
```

テストのために簡単なyamlファイルだがネスト構造や複数データがあってもこれで可能なはず。
GCP Professional Data Engineerに1日で合格する方法

[Professional Data Engineer](https://cloud.google.com/certification/data-engineer?hl=ja)に合格しました。受験体験記を共有したいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/69be6800-9349-3c43-7821-118b8147b07d.png)

# Professional Data Engineerとは

2022年の最も高収入につながる IT 認定資格ランキングで1位の資格です。平均年収2200万円($171,749)

https://www.pcmag.com/news/highest-paying-it-certifications#1-google-cloud-professional-data-engineer

https://cloud.google.com/certification

# 合格するためにやったこと

模擬問題集で70%あれば合格できます。1セット1時間合計8時間で終わります。試験開始前に間違えた問題を再度確認しておきましょう。Udemyのセール時に購入するのがおすすめです

## 【最短攻略】Google Cloud 認定 Professional Data Engineer 模擬問題集

https://www.udemy.com/course/google-cloud-professional-data-engineer-s/

## Google Cloud Professional Data Engineer - GCP - Exams - 2022

https://www.udemy.com/course/google-cloud-professional-data-engineer-gcp-exams/

テストは英語ですが、右クリックで日本語にできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/4e7c8bcc-8a5d-e856-7309-b68a4014812e.png)


## Udemy自動化

[Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=ja)をインストールし、下記ユーザースクリプトをインストールすることで次へボタンを自動で押せます。2倍ほど速くテストを進められるので便利です。タッチパネルでやると更によいです。

```javascript
// ==UserScript==
// @name         AutoNextUdemy
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.udemy.com/course/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=udemy.com
// @grant        none
// ==/UserScript==

document.body.addEventListener('click', e => {
    if (e.target.type === 'radio') {
        requestIdleCallback(() => document.querySelector('[data-purpose="go-to-next-question"]').click())
    } else if (e.target.type === 'checkbox') {
        const m = document.querySelector('#question-prompt').textContent.match(/(?<=select )\d|\d(?=を選択)|\d(?=つ選択してください)|\d(?=つ選択)/)
        if (m && e.target.closest('form').querySelectorAll('input[type=checkbox]:checked').length === parseInt(m[0], 10)) {
            requestIdleCallback(() => document.querySelector('[data-purpose="go-to-next-question"]').click())
        }
    }
})
```

# まとめ
上記の問題集だけで十分合格できると思いました。参考になれば幸いです。

# 受験料無料キャンペーン開催中

Google Cloud Skills BoostをするとGoogle Cloud 認定資格試験バウチャー 1 回分をプレゼントキャンペーンやってるようです。もしよろしければご活用ください

https://cloudonair.withgoogle.com/events/try-together-0602
AWS SSL化設定後に、アクセスできない【見直したい点】

# AWS SSL化の設定したはずが、、、
おはこんばんにちは！
AWSを触り始めのエンジニアです。

今回、EC2上にアプリケーションを構築し、httpにてDNS名前解決までできており、
**https通信**したい！と思い立ち、以下記事を参考に設定を全て完了しました。

https://qiita.com/nakanishi03/items/3a514026acc7abe25977

*しかし、、、*
設定したはずの、ドメインにてアクセスするもタイムアウトになり、アクセス不可。

Apacheのエラーログを見てみたり、以下記事を参考に見直してみるも解消できず...

https://qiita.com/kn2728/items/c4c1504753a3aefff927

# 原因はセキュリティグループだった
EC2インスタンスのセキュリティグループが、作成したロードバランサーのセキュリティグループに追加されていませんでした。

![スクリーンショット 2022-06-01 14.15.37.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/31c00cb8-5199-deb6-7a95-b1eeb33324c7.jpeg)

作成したロードバランサーの...

![スクリーンショット 2022-06-01 14.18.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/ee918ca4-6da7-00f6-fcc6-55c2baf069ca.jpeg)

セキュリティグループ！

この中に対象のEC2インスタンスのセキュリティグループが追加されていませんでした。

追加して再度アクセス確認すると、表示され一件落着。

# 単純なことだけど...

参考にするサイトを, **理解せずに** 手順を進めていたため、直すために時間がかかった。

理解して手順を進めていればこんな単純な問題に悩まなかったはずです。

少しずつでも理解しながら進めていこう！
フロントでのリロード対策どうしようか

### はじめに
フロント側のみでリロード対策をしなければならないときがありました

できればユーザーにリロードをさせないようにしたいのですが、完全にリロードを禁止するというのは無理そうかつ、こういったユーザーの行動を制限するのもあまりよくないみたい

とりあえず今回は、

- 幸い保持しておきたいデータが漏れても大丈夫なレベル
- データ量も少ない


という理由から ~~localStorage~~ sessionStorageで情報を保持することで対策しようと思いました。


### sessionStorageでリロード対策
全体の流れとしては、

- ページ読み込み時にリロードしたのかの判定
- リロード判定が必要な処理内でリロードの場合とそうでない場合で処理わける
  - リロードじゃない場合：ローカルストレージにデータ保存
  - リロードの場合ローカルストレージからデータ取得



まずはリロードの判定について、

```javascript
let isReload = false

window.addEventListener('load', () => {
  const perfEntries = performance.getEntriesByType("navigation")
  isReload = perfEntries[0].type === 'reload'
})
```

`getEntriesByType`を使って`navigation`オブジェクトを取得し、読み込みタイプを取得します。

`navigate`、`reload`、`back_forward`、`prerender`のいずれかが返ってくるので、その値に応じて`isReload`を更新します。

そして、`addEventListener`の`load`イベントを用いて、ページ読み込み時のみリロード判定の処理を実行させます。


続いて、リロード判定が必要な関数内に処理をかきます。

```javascript
let key = null

async function sample() {
// 他の処理
// ~~~~
// ~~~~

  if(isReload){
    key = sessionStorage.getItem('key')
    sessionStorage.removeItem('key')
    isReload = false
  }

  // key返す処理
  // リロードあった場合は別の値が返ってくるが、前の値と紐づけておきたいのでリロード前の値が必要
  key = await getKey(key)

  if(!sessionStorage.getItem('key')) {
    sessionStorage.setItem('key', key)
  }


// 他の処理
// ~~~~
// ~~~~

}
```

リロードから読み込まれた場合は、ローカルストレージから保存しておいたデータを取得。

リロードじゃない場合かつ、ローカルストレージの任意のキーに値が保存されていない場合は値をセット。

### 最後に

リロード対策についていろいろと情報があると思うのですが、他にいい方法があればご教示いただけたら嬉しいです
【Flutterレイアウト】IntrinsicHeightとIntrinsicWidthでサイズをお揃える


# IntrinsicHeight、IntrinsicWidthとは
IntrinsicHeight、IntrinsicWidthを使う際、下記の４つのメソッドが呼び出されて、UIを描画している。IntrinsicHeightの応用の場面としては、子たちの高さやサイズを揃えたい時です。

```dart
@override
  double computeMinIntrinsicWidth(double height) {
    if (child != null)
      return child!.getMinIntrinsicWidth(height);
    return 0.0;
  }

  @override
  double computeMaxIntrinsicWidth(double height) {
    if (child != null)
      return child!.getMaxIntrinsicWidth(height);
    return 0.0;
  }

  @override
  double computeMinIntrinsicHeight(double width) {
    if (child != null)
      return child!.getMinIntrinsicHeight(width);
    return 0.0;
  }

  @override
  double computeMaxIntrinsicHeight(double width) {
    if (child != null)
      return child!.getMaxIntrinsicHeight(width);
    return 0.0;
  }
```
## constraints制約について
RenderIntrinsicWidthクラスに下記の記述があります。要するに、constraintsの制約が厳しめの場合、IntrinsicHeight、IntrinsicWidthが機能しません。うまくいかない時は焦らず、ソースコードをチェックしましょう。とはいえ、親からの制約あるということはサイズ決められていることです。**IntrinsicHeight** を使う意味がなくなっています、現実的は存在しないと思います。
※constraintsの制約突破について、前の[記事](https://qiita.com/ling350181/items/9e927826f1164c9205b1)をご参考ください。
```dart
      if (!constraints.hasTightWidth) {
        final double width = child!.getMaxIntrinsicWidth(constraints.maxHeight);
        assert(width.isFinite);
        constraints = constraints.tighten(width: _applyStep(width, _stepWidth));
      }
      if (_stepHeight != null) {
        final double height = child!.getMaxIntrinsicHeight(constraints.maxWidth);
        assert(height.isFinite);
        constraints = constraints.tighten(height: _applyStep(height, _stepHeight));
      }
      return layoutChild(child!, constraints);
```

# 使い方
```dart
return Scaffold(
      appBar: AppBar(
        title: const Text('Demo'),
      ),
      body: Align(
        alignment: Alignment.topRight,
        child: IntrinsicHeight(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                width: 40,
                height: 120,
                color: Colors.red,
              ),
              Container(
                width: 40,
                height: 80,
                color: Colors.blue,
              ),
              Container(
                width: 40,
                color: Colors.green,
              ),
            ],
          ),
        ),
      ),
    );
```
IntrinsicHeightありとなしの効果比較
|あり|なし|
| -- | -- |
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/6ce4350a-a76e-7bd6-ff6d-988c4efe7eec.png"width=180>|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/f3933a95-fa57-6421-e86c-31010a747a6b.png"width=180>

上記の例で、IntrinsicHeightは、高さ未定の子たちはお互いの高さを合わせて、描画していることはわかる。
datadogのログ管理機能で破産しそうになったので料金を1000分の1に抑えた


ログ・インデックスとは？
-
Datadogの`ログ・インデックス`は、アプリケーションから取り込んだログをインデックス化して様々な高度な検索、集計、パターン分析、監視等ができる機能です。

https://docs.datadoghq.com/ja/logs/indexes/

使いこなせればとても便利な機能です。



請求がきた
-

上記の`ログ・インデックス`なんですが、油断すると飛んでもない料金を請求されるので注意が必要です。
もともと別のエンジニアがちょっと前にDatadogを導入し、最近自分が責任者を引き継いだ矢先、Datadogから飛んでもない額の請求が来ていることが発覚。その額なんと約30万円、、、

上記の額はもう確定済みでしたので致し方なしです。
請求の内訳としては、インフラストラクチャーや、APM(アプリケーション・パフォーマンス・マネジメント)といったプランにも入っていましたがこちらは1万円くらいで収まっていて、約29万円が`ログ・インデックス`の請求でした。

もともとdatadogを導入したエンジニアは、月額1万くらいを想定していたようで会社としても月額30万円はかなりの痛手でした。
他人任せにせずBillingのページは常日頃から監視しておく、というのが今回の反省点ですね。。
導入したエンジニアはすでに退職していたので現責任者の自分がプランの見直しをする運びに。

解決策
-
Datadogのカスタマーサクセスに問い合わせたりして、以下の方針でいくことにしました。

- 除外フィルター
- ログのS3へのアーカイブ

ひとつひとつ簡単に解説していきます。

除外フィルター
-

アプリケーションから取り込まれたログは、datadog側で自動的に以下のステータスレベルで分類分けされます。
(もしかしたら、実際はもっとあるかもしれませんが、うちのサービスでは以下でした。)

- error
- warn
- notice
- info
- ok

うちのサービスで発生しているログの99.9%以上を`info`と`ok`で占めていました。
うちでは`info`や`ok`のログに関しては、そうそう分析することがなかったためインデックス化する(`ログ・インデックス`上で見れるようにする)必要ないという結論にいたりました。

そのような要件を叶える手段を調べた所、除外フィルターという機能を発見。
インデックス化する際に`info`などは除外することで`error`と`warn`に分類されるログだけ、インデックス化することができました。
これで料金がほぼ1000分の1に！！

https://docs.datadoghq.com/ja/logs/indexes/#%E9%99%A4%E5%A4%96%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%83%BC

ログのS3へのアーカイブ
-
ただ、そうなると今後`info`ログも含め`ログ・インデックス`で分析したいなーってなったときに、できないので良い方法はないかなと調べたところ、ログを圧縮してS3にアーカイブして、必要なときに必要な範囲のログをDatadogに取り込む(リハイドレート)という運用方法を発見。
さっそく導入しました。


### 手順

手順は公式通りやったら、割とあっさりできた。
大枠だけ記載する。

-  DatadogとAWSを統合

https://docs.datadoghq.com/ja/integrations/amazon_web_services/?tab=roledelegation#setup

- S3にアーカイブする設定 (上記のAWS統合を行っている前提となっています。)

https://docs.datadoghq.com/ja/logs/archives/?tab=awss3#set-up-an-integration

S3への`PutObject`、`GetObject`のポリシーを設定する場所で、
jsonのなかのリソースのパスを設定する箇所で、`/*`を忘れがちなので注意


<img width="400" alt="スクリーンショット 2022-05-13 10 56 34" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425910/c7a3b00e-3cef-1d69-508c-78169716d7b2.png">

うまくS3と連携ができると、1時間に１回くらいのペースでDatadogに圧縮されたログがアップロードされるようになります。

- リハイドレート

S3上の圧縮されたログデータをDatadog上に取り込みます。
どのようなログを取り込みたいか、時間範囲の指定、statusの指定と細かい条件設定ができます。

https://docs.datadoghq.com/ja/logs/archives/rehydrating/?tab=awss3


おわりに
-
`ログ・インデックスの`料金を1/1000にすることができました。
ただし、正確にはリハイドレートのさいにかかる料金や、ログの100%インデックス化している場合免除されているログ取り込み機能(`Ingested Log`)の料金などが発生します。
前者はどれくらいリハイドレートするか次第です、後者はそんな大きな額ではないです。
正確なコストはカスタマーサクセスに問い合わせることを推奨いたします。

また今回は、`info`ログは常に見れなくて問題ないという条件でしたが、常に可視化しておいて、いろいろ分析に使いたいようなケースでは使えないかもしれないです。
スタバのWi-Fiに自動ログイン【at_STARBUCKS_Wi2】

1時間おきにログインするのは大変なので自動でできるようにしてみました。

```bash
sudo tee /etc/NetworkManager/dispatcher.d/99-portal <<'EOT'
#!/bin/bash

[ "$CONNECTIVITY_STATE" = "PORTAL" ] || exit 0

wget --save-cookies cookies.txt -O- https://service.wi2.ne.jp/wi2auth/redirect >> portal.log
grep service.wi2.ne.jp cookies.txt && wget --load-cookies cookies.txt -O- https://service.wi2.ne.jp/wi2auth/xhr/login --post-data '{"login_method":"onetap","login_params":{"agree":"1"}}' >> portal.log
EOT
sudo chmod +x /etc/NetworkManager/dispatcher.d/99-portal
```

再起動すると有効になると思います


# 参考

https://michael.stapelberg.ch/posts/2017-05-25-network-manager-portal/
【はじめの一歩】OCIのMySQL Database Serviceをつかってみよう！（MDS＋Python 他⑥）：プレースホルダー使用のSELECT

# はじめに
講釈よりも、とにかく触りたい・使いたい初心者向け手順書テイスト
OCIのMDSをたてて、Python等で繋げて使ってみる。
今回はConnector/Pythonを利用しDBからのデータ取得の続きです。
更新系でもやったプレースホルダーを参照系でもやりましょう。
前提：OCIの有償アカウントであること（30日間無料トライアルの方もOKです）

本手順は、翔泳社の良書
[MySQL徹底入門 第4版 MySQL 8.0対応](https://www.shoeisha.co.jp/book/detail/9784798161488)を参考としています。
同書籍の[サンプルファイル](https://www.shoeisha.co.jp/book/download/9784798161488)を活用します。
※サンプルファイルのReadMeに以下のありがたいお言葉があるので活用して効率化します。
「本書のサンプルデータは自由に利用できることとします。改変のほか、自由に利用、複製、再配布することができます。」
ただ、サンプルファイルの日本語部分は文字化けしているファイルがあるので、
そのまま使うのが難しい場合があります。

本記事の・・・
OCI環境については[MDS＋Python 他①](https://qiita.com/hm-peasant/items/246b19095e347e568f44)
DB構成については[MDS＋Python 他②](https://qiita.com/hm-peasant/items/07660df8261e6ea16a43)
シンプルなデータ更新については[MDS＋Python 他③](https://qiita.com/hm-peasant/items/c861eb82da6a8ac5aa8a)
プレースホルダーを使用したデータ更新については[MDS＋Python 他④](https://qiita.com/hm-peasant/items/60ecf35271571f99115e)
シンプルなデータ参照については[MDS＋Python 他⑤](https://qiita.com/hm-peasant/items/2e4d5aa870126b4ed12b)
をご確認ください。

# 前準備
・MDSの起動
・コンピュートの起動
・Cloud Shellの起動とコンピュートへのSSH接続
```ruby:Cloud Shellからのssh接続
$ ssh -i 秘密キー パブリックIPアドレス -l opc
例：$ ssh -i ssh-key-2022-05-31.key 150.230.193.122-l opc
```
を行います。

# PYファイルの作成
```ruby:pyファイル作成
$ vi ファイル名.py
ファイルが開かれたら「i」キーを押下した後、処理内容を記入し、「ESCキー →　:(コロン)　→ wq!」で上書き保存
```
# 前処理
前段で接続処理を記入します。
mysql.connector.connectのカッコ内：user、password、host、databaseを自身の環境に合わせて編集

```ruby:
import mysql.connector
from mysql.connector import errorcode

try:
    conn = mysql.connector.connect(user='mdsuser', password='Mdsp@ss01',
                                   host='10.0.1.51',
                                   database='mdstest', use_pure=True)
```

# プレースホルダー使用のSELECTクエリ
更新系と説明は同様です。セキュリティ向上にも役立ちますので
その理由に興味があれば調べてみましょう
では早速やっていきます。

```ruby:プレースホルダー使用の参照処理
    cur = conn.cursor(buffered=True)
    sql_str = "SELECT * FROM commodity WHERE code > %s";
    cur.execute(sql_str, (1,))
    for row in cur:
        print(row)
```

# 後処理
後段で例外処理や切断処理を記入します。
```ruby:後処理
except mysql.connector.Error as err:
    print("VendorError:", err.errno)
    print("SQLState:", err.sqlstate)
    print("SQLException:", err.msg)
else:
    cur.close()
    conn.close()
```
# 実行結果
```ruby:
$ python P_SELECT.py 
(2, 'Py_リンゴ(10kg)', 4000, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(3, 'Py_ブドウ(3kg)', 5000, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(4, 'Py_ミカン(10kg)', 3000, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(5, 'Py_イワシ', 100, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(6, 'Py_アジ', 200, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(7, 'Py_サバ', 300, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(8, 'Py_サンマ', 400, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
(9, 'Py_マグロ', 900, None, datetime.datetime(2022, 6, 1, 2, 0, 14))
$ 

```

今回は以上です。お付き合い頂き、ありがとうございました。

【重要】ＭＤＳは安価ですが、使わないのであれば、停止する、もしくは削除するのを忘れずに
　　　　停止だけだと、ストレージは月単位で課金されます。
お片付け方法は、[初回：MDS＋Python 他① お片付け](https://qiita.com/hm-peasant/items/246b19095e347e568f44#%E3%81%8A%E7%89%87%E4%BB%98%E3%81%91)を参考にしてください。
Winmerge 二つExcelファイルを比較　文字化けの対策

WinMergeでエクセルのファイルを比較するための設定方法
参考リンク
https://beiyan-tool.info/?p=818

1.初期状態では「手動展開」となっているので、「自動展開に変更」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442974/0a22edfb-f487-520b-0460-5a4a3595a551.png)

2.ツールバーの「プラグイン」をクリックし、
「プラグインの設定」を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442974/ae031e74-5c87-0732-7eab-de22e8441c54.png)

3.「CompareMSExcelFiles.sct」を選択し、「プラグインの設定」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442974/14ec1317-2ac8-cd59-5b41-1bb3b1548f9e.png)

以下の２つの項目にチェックを入れます。
・ワークブックの情報を複数ファイルに展開する
・ワークシートを画像化して比較する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442974/40899482-b939-97d6-fe37-893dd9e9b2a6.png)
CSSの結合子(書いて理解する)

## 【結合子】
CSSは、`結合子`を使用してセレクタを組み合わせることができます。

| 名前 | 説明 |  
| - | - |
| 複数のセレクタ | 指定したすべてのセレクタ |  
| 子孫セレクタ | セレクタAの要素内すべてのセレクタ |  
| 子セレクタ | セレクタAに隣接する(同じ階層の直後にある)セレクタB |  
| 隣接セレクタ | セレクタAの直後からすべてのセレクタB |  
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>結合子</title>
    <style>

        /*
        ・基本構文
         セレクタA [結合子] セレクタB
        　
          ※ 複数のセレクタはセレクタA,Bともに適用される。
           　それ以外は、セレクタBにのみ適用される。
        */

        /* 複数のセレクタ - 指定したすべてのセレクタ */
        h1, h2 {
            font-size: medium;
        }

        /* 子孫セレクタ - セレクタAの１つ下の階層の以下すべてのセレクタB */
        .combinator span {
            color: darkred;
        }

        /* 子セレクタ - セレクタAの１つ下の階層のセレクタB */
        .combinator > p {
            color: cornflowerblue;
        }

        /* 隣接セレクタ - セレクタAに隣接する(同じ階層の直後にある)セレクタB */
        .combinator + p {
            background-color: darkred;
        }

        /* 間接セレクタ - セレクタAの直後にある以下すべてのセレクタB */
        li ~ li {
            background-color: red;
        }
    </style>
</head>
<body>

<h3>結合子</h3>

<h1>複数のセレクタA</h1>
<h2>複数のセレクタB</h2>

<!-- 子孫セレクタA・隣接セレクタA-->
<div class="combinator">
    <span>子孫セレクタB</span>
    <div>
        <span>子孫セレクタB</span>
    </div>
    <ul>
        <li>間接セレクタA</li>
        <li>間接セレクタB</li>
        <li>間接セレクタB</li>
    </ul>
</div>
<p>隣接セレクタB</p>
<p>隣接しない要素</p>
</body>
</html>
```

### [プレビュー]

![Screenshot from 2022-06-01 13-29-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1907077/824e9ba9-c3c9-c97a-2e5c-be8edc76ebb1.png)
【mt4/mql4】曜日によって稼働/停止を制御する


# はじめに
<!-- 発端や概要を記載 -->
システムトレードプログラマのmt4/mql4のメモノートです。
初心者向けの簡単なトピックから公開していきます。
.noteでEAそのものも公開していますので良ければそちらも見てください。


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [処理内容](#処理内容)
1. [mql4ソースコード](#mql4ソースコード)

<!-- 各チャプター -->
<a id="#処理内容"></a>
# 処理内容
任意に指定した一定期間の最低価格を算出するコードです。
使うシーンとしては
現在値と最低値の剥離額でエントリーするかどうかを判断するとか
期間別に最低値を算出して、トレンドを解析するとか
色々なシーンで使えるコードだと思います。

ちなみに期間は時間足種の本数で指定します。何本前から何本前までという感じです。
なので、算出した時間は足種によって異なりますので注意してください。

使いたいシーンに挿入して使ってください。


<a id="#mql4ソースコード"></a>
# mql4ソースコード

こちらがソースコードです。


変数・関数側
呼び出し側の前に記述されている必要があります。

```c++:test.mq4
//稼働対象曜日 true:可能、false-:不可
input bool Entry_Mon=true;
input bool Entry_Tue=true;
input bool Entry_Wed=true;
input bool Entry_Thu=true;
input bool Entry_Fri=true;
input bool Entry_Sat=false;
input bool Entry_Sun=false;

//稼働対象曜日判定
int EntryWeekdayRunCheck()
 {
  int ret=-1;
  int weekday = DayOfWeek();

  if(Entry_Mon==true && weekday == 1)
     ret = 1;
  if(Entry_Tue==true && weekday == 2)
     ret = 1;
  if(Entry_Wed==true && weekday == 3)
     ret = 1;
  if(Entry_Thu==true && weekday == 4)
     ret = 1;
  if(Entry_Fri==true && weekday == 5)
     ret = 1;
  if(Entry_Sat==true && weekday == 6)
     ret = 1;
  if(Entry_Sun==true && weekday == 0)
     ret = 1;
  return(ret);//-1は禁止、1は許可
 }
```

呼び出し側
呼び出したいタイミングに合わせてOnTick()、OnInit()とかOnTimer()の中で記述してみてください。
↓こちらは設定した曜日に対して稼働停止するコードサンプルです。
```c++:test.mq4
if(-1 == EntryWeekdayRunCheck())
{
void  ExpertRemove();
}
```

皆様の手助けになりますように。
間違いなどあればご指摘いただけると助かります。
以上です
M5stack Core2でBluetooth接続　PCのpythonプログラム3（PCで受信）

# BLE通信の送信ができ、受信もできる

https://qiita.com/ganmodoki_oishii/items/b2b576ff8562209af196

送信はできるようになった
PCが受信側となって実行できるようにするには？


# PC側の受信プログラム
前々回のUUIDで調べた（read）にはValueにすでに値が入っていたので、
notifyにあたるキャラクタリスティックを読み込んでみたところ成功しました

```python
import asyncio
import uuid
from bleak import BleakScanner
from bleak import BleakClient
from bleak import BleakError

device_name = "FIVE_STACK"
#[Characteristic] 6e400003-b5a3-f393-e0a9-e50e24dcca9e (Handle: 20): 
# (notify), Value: None
read_UUID = uuid.UUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e")

async def ble_scan():
    devices = await BleakScanner.discover()
    idx = list(filter(lambda x: x.name == device_name, devices))

    # 検出デバイスの表示
    #for d in devices:
    #    print(d)

    global ADDRESS
    ADDRESS = idx[0].address
    print("find device " + str(idx[0].name))

async def connect_read():
    global ADDRESS

    async with BleakClient(ADDRESS,use_cached=False) as client:
        def callback(sender, data):
            print(f"Received: {data}")

            data_str = data.decode()
            print("decode ->"+data_str)
        
        print("..receive message")
        while True:
            await client.start_notify(read_UUID, callback)          

if __name__ == "__main__":
    asyncio.run(ble_scan())
    asyncio.run(connect_read())
```
notifyはコールバック関数で～とリファレンスサイトにあったので、受信時にコールバック関数へ飛ばしました

# UIFLOWのBlockly
前回のものに、BLE writeブロックを追加、1秒おきにカウントアップしていく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2660324/9afedb2c-3cbf-51ff-db7b-1566f7a21629.png)


# 実行結果
1秒ごとに表示される
受信データをそのまま表示させると`bytearray(b'')`が返ってくる
受信データをデコードすることで文字列になった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2660324/e70b8204-3722-2dfa-26fe-d841fb513db9.png)


次はPCのプログラムをデスクトップアプリケーション化してみようと思います
GraphQLでページネーションを実装する際はGraphQL Cursor Connections Specificationを参考にしよう！

## はじめに

NestJS x GraphQLで実装したユーザー一覧を取得するAPIにページング機能をつけてNext.js x URQLで呼び出そうとしたらうまくいかなかったので躓いたところを記録として残しておきます。

この記事が同様の問題で悩んでいる人の助けになれば嬉しいです。

## TL;DR

- この解決方法はGraphQLのPaginationを`Cursor-based pagination`で実装した方に有効です
- Request, Responseパラメータは[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm)に従いましょう

## 環境

| ツール・ライブラリ | 用途 | バージョン |
| --- | --- | --- |
| Next.js | フロントエンドとして利用 | 12.1.0 |
| NestJS | サーバーサイドとして利用 | 8.0.0 |
| GraphQL Code Generator | コード自動生成ツール | 2.6.2 |
| URQL | GraphQL Clientのライブラリ | 2.2.0 |
| node.js | フロント、サーバーサイドの実行環境 | v16.14.0 |
| ページネーションの方式 | Cursor-based pagination |  |

## 課題

NestJSで作ったページネーションをgraphql code gen x URQLを使ってWeb側で表示するような実装をしようとしていました。

基本的な書き方は以下を参考にしたのですが、いざ自分の環境でも再現させようとすると追加のn件を取得することができませんでした。

https://codesandbox.io/s/qeuix


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/948547d9-172b-6b8a-3b74-d18e5b5bcf5a.gif" width=500 />

見ての通り、Fetch moreをクリックしても次のn件が表示されません。

その時に設定していたリクエストパラメータは以下になります
```graphql:Request
query Users($paginatedUsersInput: PaginatedUsersInput) {
  users(paginatedUsersInput: $paginatedUsersInput) {
    ...paginatedUsers
  }
}

fragment paginatedUsers on PaginatedUsersOutput {
  edges {
    node {
      ...userProfile
    }
  }
  pageInfo {
    endCursor
    hasNext
  }
}

fragment userProfile on UserOutput {
  nickname
  uid
}
```

```ts:Response
{
  edges: {
    node: User
  }
  pageInfo: {
    endCursor: string
    hasNext: boolean
  }
}
```

## 解決方法

InputとOutputをGraphQL Cursor Connections Specificationに合わせることで解決することができました。

https://relay.dev/graphql/connections.htm

実際に変えてみたコードがこちら↓

```graphql:Request
# paginatedUsersInputを除外してfirst, afterだけにする
query Users($first: Int, $after: String) {
  users(first: $first, after: $after) {
    ...paginatedUsers
  }
}

fragment userProfile on UserOutput {
  # ~~ 省略 ~~
```

```ts:Response
{
	edges: {
		// cursorを追加
		cursor: string
		node: User
	}
	pageInfo: {
		endCursor: string
		// hasNextからhasNextPageに変更
		hasNextPage: boolean
	}
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/5a730b24-a35f-e3ee-ef8b-209f5e23b08a.gif" width=500 />

無事正常にFetchMoreができました！


## 注意点

今回採用したページネーションの方式は`Cursor-based`であって、`Offset-based`や`Time-based`には適用できないので注意してください。

## 余談
ページングの実装をしたことがなかったので今回理解しながら書けるようになれて良かったです！

引き続き開発を続けていこうと思います！

ではまた！

## 参考記事

https://codesandbox.io/s/qeuix

https://relay.dev/graphql/connections.htm

https://formidable.com/open-source/urql/docs/graphcache/local-resolvers/#relay-pagination
【萎える話】エンジニアやクリエイターと一緒に仕事をする非専門職の人へ

これ本当に毎日のように小さなストレスの積み重ねなので
是非、周りの非専門職の人にシェアしてほしい

web制作でも店舗設計でもなんでもいいのだが
ここでは例としてバスケットボールのイベントの会場を作る
という架空事例にそって話をする。
```
発注者（非専門職）
とりあえず、イケてるバスケコートを作ってくれ！
```

発注が超曖昧なままスタートする

専門職サイドも
そんな曖昧な指示じゃ作れないと思いつつも
プロなのでなんとか制作模型などを作り始める

なんとか発注者の意図を汲み取りながら
とりあえず、色や看板配置などの詳細はさておき
コートの全体雰囲気を仕上げて見せる。
```
まだざっくりベースだけなんですが
こんな感じで行きますか？
```
と

発注者はそれを見るやいなや
```
うーん、看板の位置意識してる？
全体の色が見えてこないとなんとも言えないな、、
```
とまだ実装していないと言っている色や看板配置などの詳細
に対して、
あーだこーだ言い始める

### （いや、まだコートだけしかやってないのでそのへん周りのオプションはこれからなんだけど、、）

と不満を持ちつつも
持ち帰って、周りのオプションも作り始める。

そしてに発注者に見せる直前に
こう思いつく、

### どーせコート周りだけの状態だと観客席の雰囲気が分からんとかも言うだろうから前に作ったフットサルのコートのやつをちゃちゃっと加えて会場全体の雰囲気を演出した模型を付け足しておこうっと

発注者に
```
コート周りと、とりあえず、
観客席周りはラフですが見てもらえれば
```
と言って見せる。
```
うーん観客席全部埋まってるけど、報道席とか考えてる？
そのへん、全体見てみないと良し悪し分からないね
```

お分かりだろうか？

雑な依頼に対して120点の仕事をしている
専門職側としては方向性が合ってるかどうか、
今完成しているところに対して問題がないか
そういう確認をして欲しいのに

成果物をみるやいなや　その先の工程や論点外の話いきなりし始める。

そもそも発注者が最初に依頼してきたのは
コート周りだけだよね？

もちろん、契約だったり、社内外の立場だったり、スケジュールの問題も絡んで
いろんなケースがあるのでこの話の良し悪しは一概には決められないだろう。

ただ、一言だけ言えるのは
## 非専門職の人たちのその一言一言で専門職の人たちは日々萎えている。

あなたのご指摘はごもっともですが、
専門職はロボットではありません。
正しいコミュニケーションを心がけましょう

専門職の人たちはこう思ってますよ。
非専門職でコミュニケーションだけが取り柄のくせに
それさえもできてないじゃないか
と

おしまい

ちなみに発注者が自分で製作者も自分のwebサービス開発は天国です。

https://fx-labo.app/
グーグルしごと検索に掲載してもらうためにしたこと

https://nightjob.info/
<p>こちらのサイトの求人ページを、グーグル仕事検索に掲載してほしいとのことでした。</p>
<p>グーグルで求人について検索すると上に出てくるあれです。</p>
<p>実際にあそこから求人の応募があるかは微妙なのですが、試してみたいと思います。</p>
<p>以下をヘッダーに書き込みます。</p>

```
<?php get_template_part('google-for-jobs'); ?>
```

<p>それから、PHPファイルを下階層に増やして以下を書きます。</p>

```
<pre><code><?php $activation = get_post_meta($post->ID, 'activation', true); ?>
<?php if( !empty($activation) ):?>
<!-- Googleしごと検索はじめ -->
<script type="application/ld+json">
{
 "@context" : "http://schema.org",
 "@type" : "JobPosting",
 "title" : "<?php the_field("job_title");?>",
 "hiringOrganization": {
   "@type": "Organization",
   "name": "<?php the_field("company_name");?>",
   <?php $sameAs = get_post_meta($post->ID, 'sameAs', true); if( !empty($sameAs) ): ?>"sameAs": "<?php the_field("sameAs");?>",<?php endif; ?>
   <?php $logo = get_post_meta($post->ID, 'logo', true); if( !empty($logo) ): ?>"logo": "<?php the_field("logo");?>"<?php endif; ?>
 },
 "jobLocation": {
   "@type": "Place",
   "address": {
     "@type": "PostalAddress",
     "streetAddress": "<?php the_field("streetAddress");?>",
     "addressLocality": "<?php the_field("addressLocality");?>",
     "addressRegion": "<?php the_field("addressRegion");?>",
     "postalCode": "<?php the_field("postalCode");?>",
     "addressCountry": "JP"
   }
 },
 "baseSalary" : {
   "@type" : "MonetaryAmount",
   "currency" : "JPY",
   "value": {
     "@type": "QuantitativeValue",
	 <?php if(get_post_meta($post->ID,"set_value",true)=== "basic"): ?>
	 <?php $value = get_post_meta($post->ID, 'value', true); if( !empty($value) ): ?>"Value": <?php the_field("value");?>,<?php endif; ?>
	 <?php else: ?>
	 <?php $minValue = get_post_meta($post->ID, 'minValue', true); if( !empty($minValue) ): ?>"minValue": <?php the_field("minValue");?><?php endif; ?>
	 <?php $maxValue = get_post_meta($post->ID, 'maxValue', true); if( !empty($maxValue) ): ?>,"maxValue": <?php the_field("maxValue");?>,<?php endif; ?>
	 <?php endif; ?>
	 <?php $unitText = get_post_meta($post->ID, 'unitText', true); if( !empty($unitText) ): ?>"unitText": "<?php the_field("unitText");?>"<?php endif; ?>
   }
 },
	 "employmentType": "<?php the_field("employmentType"); ?>",
	 <?php $description = get_post_meta($post->ID, 'description', true); if( !empty($description) ): ?>"description": "<?php echo strip_tags(get_field("description"));?>",<?php endif;?>
"datePosted" : "<?php the_time('Y-m-d'); ?>"
	 <?php $validThrough = get_post_meta($post->ID, 'validThrough', true); if( !empty($validThrough) ): ?>,"validThrough": "<?php the_field("validThrough");?>"<?php endif; ?>
}
</script>
<!-- Googleしごと検索おわり -->
<?php endif;?></code></pre>
```
<p>あとはAdvanced Custom Fieldsで求人ページにカスタムフィールドを追加。</p>

https://nightjob.info/mens/

<p>こちらのページをリッチリザルトテストツールに掛けてみると、「リッチリザルトの対象です」と出たので、Indexing APIを利用してGoogleに送信しました。</p>

<p>こういった作業は慣れないもので、このやり方であっているかわかりません…。</p>

<p>もしご意見などあればお願いいたします。</p>
WordPressでアニクラDJ用のアーティストサイトつくってみた。その3【トップページの制作】

## トップページを作ろう！
とりあえず、顔となるトップページを作ってサイトっぽさを感じていきたい！！ということでアーティストサイトの重要なポイントであるトップページ。早速、作ってみました。

![screencapture-kaira-net-2022-06-01-08_48_51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115918/69f93f74-7279-07bf-edae-ede18dac6ef9.jpeg)

http://kaira-net.com/

### 見た目の印象・・・ダサい
ぱっと見、かっこよくとあれほど言っていたのにダサく感じます。
なぜだろう。

## ダサい原因と解決策
### 写真がそもそもイケてない。
とてもダサく見えます。写真などの画像データがカッコ悪いので、ダサいDJに見えますね。

#### 対策
- イベント中にたくさん写真を撮ること。選択肢が増えれば、それだけカッコ良く見える確率が上がります。もちろん、他の演者さんにも協力してもらうことを惜しまないこと。イベント後に素材を共有すれば、Win-Winになれると思う。
- Photoshopなどの画像加工ソフトで、手直しすること。後から直せるというのは、利点ではあるが、頼りすぎない。個人レベルでやる時には、技量によってかかる時間が違うので、写真をそのまま使えるのであれば、それがベストに感じます。

### ヘッダ、フッタと文字色があっていない気がする。
ポップさをイメージして、とりあえずの色味を決めていきましたが、なんか毒々しいような気がします。この辺りの感覚は、個性の部分もありそうです。

#### 対策
- カラーパターンを考えること。色見本になる技術書で、とにかく良さげな色を試していくことが大事だと思います。
- 映すディスプレイを変えてみること。Mac・WindowsなどのPC画面、iPhoneのスマホ画面で表示を確認することで気づくことがあると思います。同じ画像が、異なるディスプレイによって違って見えることも多いです。

### イメージが伝わってこない
DJのサイトというようなところは、ぱっと見で伝わるが、まだ弱く感じます。アニメやサブカルが好きというようなニュアンスを前面に出していきたいので、もう少しインパクトが欲しいと感じます。

#### 対策
- サイトコンセプトをアップデートすること。「DJサイトをとりあえず作る」というレベルから、「どういうDJサイトにしたい」という部分を深掘りすることが必要です。
- トップページ単体の目的をはっきりさせること。ページ単位の役割が明確になれば、自ずと伝えたい印象がシンプルになると思います。

## そのほか気になるところ
- ファビコンがない
- 使っているテーマがワンパターン
- Mix音声ファイルがない

## 感想
カッコ良いサイト作っていくんだと息巻いていましたが、いざ実装始めると自分がダサくなっているという印象が強いですね。
個人レベルで行っているから、仕方ないという風に言い訳をしたくはないのです。広いアンテナを張り巡らして、キャッチアップをしながら修正を続けていくことが大切かなと思います。

あとは、カッコ悪いのもいずれはよくなるんだという期待を持ちながら、Webサイト作成を楽しんでいくことが何より大切かなと思います。

## 次回の作業タスク
- Topページをカッコ良く改修
- aboutページのレイアウト構成
- blogページのレイアウト構成
- FAQページのレイアウト構成
- Contactページのレイアウト構成
🔰【初学者用】RSpecでテストコードを書こう！【概念・準備】

# はじめに
オリアプ作成も遂に終盤に差し掛かり、今日からテストコードを書くフェーズに突入します。
テストコードを書く前に今まで学んだテストコードの知識を今日から少しずつアウトプットしていきたいと思います！
※プログラミング初学者の私がアウトプットとこれから学習される皆様の参考になればと思い投稿しています。また、マークダウン記法も不慣れな初学者ですので、間違い等があれば指摘いただけると幸いです。


## この記事を見てできるようになること
Ruby on Railsのgemであるrspec-railsを使用して、テストコードを実装できるようになります！

## Rspecとは？
Ruby on Railsのアプリケーションのテストコードを便利に実装できるGemです。

## テストコードを書く意義
テストコードとはアプリケーション内に記述する、そのアプリケーションの挙動を確認するコードのことを言います。
なぜ、このコードを書かなければならないのでしょうか？メリット・デメリットに分けて考えてみましょう！
**テストコードを書くメリット**
①クオリティの担保
ブラウザでアプリケーションの挙動を確認することは、デメリットが多いから。
②使用の見極め
テストコードが書ける=そのアプリケーションの仕様を理解している。ということになるから。
**手動で挙動確認するデメリット**
①人為的なミスが生じる可能性がある。
②仕様が変わった時に、もう一度手動で確認する必要がある。
③どこをテストしたか記録が残らない。

## テストコードを書くべきパターン
アプリケーションの挙動を確認するときは「うまくいくとき」(正常系)と「うまくいかないとき」(異常系)に分けられます。
**正常系**
「ユーザーが情報を正しく入力してログインする。」のように開発者の意図する操作を行った時の挙動を確認するテストコード。
**異常系**
「ユーザーが情報を間違えて入力したためログインできない。」のようにユーザーが開発者の意図しない操作を行った時の挙動を確認するテストコード。

## テストコードの種類
テストコードの種類は大きく以下の２つに分けられます。
**単体テストコード**
モデルやコントローラーなど、機能ごとに問題がないか確かめる。
**結合テストコード**
ユーザーがブラウザで操作する一連の流れを再現して、問題がないか確かめる。

以上のようなメリット・デメリット、テストコードの書くべきパターンと種類を記述しましたが、初めて読んだという方は、ここで100%意味が分からなくても大丈夫です！実際に今、分からなくても書いた後に必要性が分かります。今言えることはとにかく書こう！書いたら分かる！ということです。

# テストコードのRSpecの導入と設定
　まずはRspecのインストール
```rails:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'　＃追記
end
```
忘れずに`bundle install`を実行。
```rails:ターミナル
% bundle install
```
続いて設定ファイルを作成します。以下コマンドを実行します。
```rails:ターミナル
% rails g rspec:install
```
すると、いくつかのディレクトリとファイルが生成されます。
このコマンドで生成されたファイルのうち.rspecファイルを開き、以下のように記述します。
テストコードの結果をターミナル上に可視化するための記述です。
```.rspec
--require spec_helper
--format documentation # 追記
```
これでRSpecの導入と設定は完了です！
# Userモデルの単体テストコード（準備）
ここからはUserモデルを例に挙げてテストコードを書く準備を行います。
以下のコマンドを実行してください。
```rails:ターミナル
rails g rspec:model user
```
このコマンドにより、以下のファイルが生成されます。
```rails:spec/modeks/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
end
```
このファイルにテストコードを記述していきます。
ちなみに！
１行目のrails_helperはRspecを用いてRailsの機能をテストするときに、共通の設定を書いておくファイルです。各テスト用ファイルでspec/rails_helper.rbを読み込むことで、共通の設定やメソッドを適用します。
rails gコマンドでテストファイルを生成すると、rails_helperを読み込む記述が、自動的追加されます。



# 終わりに
今日はここまで。
次回はテストコードを実装してきます！
↓続き

https://qiita.com/hondano_gentuki/items/0a91a595df9c0d76f1cc
Discordに送信されたPDFファイルを画像ファイルに変換して送信

身内用に作ったもののメモ書き

# 環境
CodeSpaces
- Python3.8

# 使用ライブラリ
- discord.py 1.7.3
- pdf2image  1.16.0
- pillow     9.1.1

# インストール
```bash
$ pip install -U pdf2image

$ sudo apt install poppler-utils poppler-data
```

# 処理の流れ
- 添付ファイルの形式を確認
- PDFだったらダウンロードして変換
- ページごとに画像を書き出して送信&削除
- ダウンロードしたPDFファイルを削除

ファイル名がかぶるのを避けるため、下記のコードでは`message.id`をファイル名に使用


# コード
```py
async def on_message(message):
    if message.author.bot:
        return
    for attachment in message.attachments:
        if attachment.content_type != "application/pdf":
            continue
        await attachment.save(f"{message.id}.pdf")
        images = pdf2image.convert_from_path(f"{message.id}.pdf")
        for index, image in enumerate(images):
            image.save(f"{message.id}-{str(index+1)}.jpg")
            await message.channel.send(file=discord.File(f"{message.id}-{str(index+1)}.jpg"))
            os.remove(f"{message.id}-{str(index+1)}.jpg")
        os.remove(f"{message.id}.pdf")
```
10枚ずつ出力すれば高速化できそうな気もするが、時間がなかったので割愛

# 参考文献
[pdf2image リポジトリ](https://github.com/Belval/pdf2image)
PHP8でPDO::inTransactionの挙動が変わった

# PHP8では、PDO::inTransactionでDBサーバの状態も見るようになった

PHP8で、PDO::inTransactionの挙動が変わりました。
[PHP: 下位互換性のない変更点 - Manual](https://www.php.net/manual/ja/migration80.incompatible.php#migration80.incompatible.pdo-mysql)
> PDO::inTransaction() は、 PDO が管理しているおおよその情報ではなく、 実際のトランザクションの状態を報告するようになりました。

だいぶざっくりした書き方だな・・・と思ったのでいろいろ調べてみると、下記でinTransactionの判定にMySQLサーバの状態を確認するコードが入ったようです。
（php-8.0.0RC2から適用。php7.4.27までのコードには入っていない。）
https://github.com/php/php-src/pull/4996

今まではbeginTransaction()を使ってトランザクションが開始されたかどうかのみを判定しており、それ以外の方法で開始されたトランザクションは検出できなかったとのこと。
[PHP: PDO::inTransaction - Manual](https://www.php.net/manual/ja/pdo.intransaction.php#125087)
> This will only detect whether a transaction has been started using beginTransaction(). It will not be able to detect transactions started by any other means, for example by executing "START TRANSACTION".

が、PHP8からは、DBサーバの状態も確認した結果を返却するようになリました。

inTransactionを使って色々してる部分はPHP8にバージョンアップする際に確認が必要そうですね。
EC2のデフォルトユーザーを変更する

EC2のデフォルトユーザーを `ec2-user` から任意のユーザーに変更する。 

## 手順
- ec2-userでEC2にssh
- 新規ユーザーを作成
- .sshディレクトリをコピー,所有者変更
- wheelグループへの登録
- sudo権限の付与
- 新規ユーザーでのssh確認,sudo確認
- ec2-userの削除

### ec2-userでssh


```
ssh -i プライベートキーファイル ec2-user@ipアドレス
```

ec2-userでログインしたらrootになっておく。

```
sudo su -
```

### 新規ユーザーを作成

ここでは新規ユーザー名をhogeとする。

```
adduser hoge
```

### .sshディレクトリをコピー,権限変更

ec2-userの.sshディレクトリをhogeにコピーし、所有者もhogeにしておく。

```
cp -r /home/ec2-user/.ssh /home/hoge/
chown -R hoge:hoge /home/hoge/.ssh
```

### wheelグループへの登録

hogeをwheelグループへ登録する。

```
usermod -aG wheel hoge
```

### sudo権限の付与

ec2-userのパスワードなしsudo権限をhogeに移し替える。

```
visudo -f /etc/sudoers.d/90-cloud-init-users
```

下記が開くので、ec2-userの記述をhogeに変更して保存する。

```
# User rules for ec2-user
ec2-user ALL=(ALL) NOPASSWD:ALL
```

↓

```
# User rules for hoge
hoge ALL=(ALL) NOPASSWD:ALL
```

### 新規ユーザーでのssh確認,sudo確認

ec2-userはログアウトして、改めてhogeでsshする。

```
ssh -i プライベートキーファイル hoge@ipアドレス
```

ログインできたらrootユーザーにパスワードなしでなれることを確認する。

```
sudo su -
```

### ec2-userの削除

ここまで確認できたらec2-userは削除して問題ない。

```
userdel -r ec2-user
```
OSSコントリビュートのしやすさ


## コントリビュートしやすいOSS

個人的な意見として、以下のような点があるプロジェクトはコントリビュートしやすそうだなと思う。

- コントリビュート方法が書かれた記事がある
- 他の人もコントリビュートしている
  - 他人のプルリクを見ることでなんとなく雰囲気がわかる
- 開発方法が書かれている
  - 「コントリビューターの人は`git clone`して`npm script ***`コマンドを打ってください」みたいなのがREADMEに書かれている
- 巨大すぎない
  - 注目されているリポジトリやプルリクは議論が紛糾しがち？
- 雰囲気
  - ギスギスした雰囲気のOSSよりオープンなOSSのほうが参加しやすい
- 日本人のコントリビューターが既に参加している
  - いざとなったら日本語で聞ける人がいる

以下の記事も参考になる。

> 個人的には、以下の条件が揃っているとコントリビュートしやすいと思います:
> - 技術的に興味のもてるプロジェクトである
> - コントリビュートしたい人向けのドキュメントが充実している（開発の始め方、テストの走らせ方、コードのアーキテクチャがドキュメントにまとまっている、など）
> - コードが複雑すぎず、がんばれば処理の流れを読み解くことができる
> - コミュニティが活発である（issueやPRへの対応が早く、スムーズに事が進みます）
> - good first issue が付いた issue で、まだ他の人が着手していないものが多くある
> - メンテナに日本人がいて、日本語でやりとりできる
> https://zenn.dev/magurotuna/articles/25436752b7c32c

## コントリビュートしづらいOSS

コントリビュートしづらそうだなと思った例をいくつか挙げる。

- プルリクを出してからマージするまでに3年間かかった人（途中誕生日ケーキで3周年をお祝いしている）

> I bought this PR a birthday cake for its third birthday.
https://github.com/microsoft/TypeScript/pull/29374

- プルリクを出したもののレビューされず放置され、「古くなったのでcloseします」と言われるパターン

> This experiment is pretty old, so I'm going to close it to reduce the number of open PRs.
https://github.com/microsoft/TypeScript/pull/42634#issuecomment-1136501587

- 機械翻訳の誤訳を報告したら炎上した人

> Microsoftの社員様からこんなチケット判るわけがないという言葉をいただいた

> マイクロソフトコミュニティはビジネス上のつながりが強すぎて、深い形でのコントリビュートがされて当然、そうでなければやらないほうが良いというのがあるんだろうなぁと思いました。

> 自称有識者が出てきて物知り顔でちんぷんかんぷんな解説が始まり、レポーターが疲弊する
> https://megascus.hatenablog.com/entry/20180726/1532557216

最初から完璧なプルリクを出せるコントリビューターはいないので、そういうプルリクでも割り切って対応する（変更すべきところは指摘する）くらいのドライさが受け入れ側にあると、こちらも安心してプルリクを出せる。
プルリクを受け入れる余裕がなさそうなプロジェクトは、コントリビュートしづらい。

## まとめ

コントリビュートする側はお客様ではないし、コントリビュートされる側もお客様ではないけど、コントリビュートしやすいOSSとしづらいOSSがあるのは確か。

未知のプロジェクトにコントリビュートするときは特に、コントリビュートしやすいOSSのほうがありがたい。
PostgreSQL 小技

# PostgreSQL

- 自分用メモ
- ググってもなかなか出てこなかったやつ

## 簡単にSQLを試したい時にテーブルを作らなくてもよいやつ
```SQL
WITH tmp(cd,point) AS (
    values
    ('1111111',1),('1111111',2),('1111111',3),
    ('2222222',5),('2222222',6),('2222222',7),
    ('3333333',10),('3333333',12),('3333333',15)
)
SELECT * FROM tmp
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274058/beb41938-1911-8a03-c843-61ee20d5171d.png)

## グルーピング内での順番を指定して取得
cdでグルーピングして、pointを降順ソートし、1番最初のレコードを取得
```SQL
WITH tmp(cd,point) AS (
    values
    ('1111111',1),('1111111',2),('1111111',3),
    ('2222222',5),('2222222',6),('2222222',7),
    ('3333333',10),('3333333',12),('3333333',15)
)
select * from
(
    select
        cd,point,
        row_number() OVER(PARTITION BY cd ORDER BY point desc) AS row_no
    from tmp
) as tmp2
where row_no = 1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274058/c94dce81-9197-6b2c-ca66-d0907a31688a.png)

## 複数行のカラムを１つの文字列にする
cdでグルーピングして、pointを降順にして文字列結合
```SQL
WITH tmp(cd,point) AS (
    values
    ('1111111','1'),('1111111','2'),('1111111','3'),
    ('2222222','5'),('2222222','6'),('2222222','7'),
    ('3333333','10'),('3333333','12'),('3333333','15')
)
select
    cd,
    string_agg(point, ':' order by point desc) as cat_point
from tmp
group by cd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274058/7a8f42b5-0118-634b-6d12-0ea58f3b9135.png)

## データを増幅（テストデータ作る際に便利）
- `GENERATE_SERIES`で1,2,3,4,5という集合を作成し、`I`で定義
- `100 + I AS ID` 100から始まる連番を作成
- `'TEST'|| LPAD(CAST(I AS CHARACTER VARYING), 5, '0') AS CD` "TEST" + 左5桁"0"埋文字の連番を作成
```SQL
WITH tmp AS (
  SELECT
  I,
  100 + I AS ID,
  'TEST'|| LPAD(CAST(I AS CHARACTER VARYING), 5, '0') AS CD
  FROM (SELECT GENERATE_SERIES(1, 5)AS I)  ZOUFUKU
)
SELECT * FROM tmp
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274058/580fef4f-d1ca-3ac7-be6a-82d06240494f.png)

## 現在日付から1年6か月を引く
```SQL
select '現在日',CURRENT_DATE as "日付" union all
select '1年6か月前', CURRENT_DATE - CAST('1 YEARS 6 MONTHS' AS INTERVAL) as "日付"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274058/9653e992-9306-2a97-bee0-609323c1edfc.png)
スパコン世界ランキング2022の真の勝者はAMDなのでは？と思う件

# スパコンは2位じゃダメなのか？
2年前のシステムで2位だからゴロは良い。今は投資資金の回収フェーズだと思うので
(wikiには1300億円かかっているみたい)今は元が取れれば個人的には良いと思う。
でも思ったより敗北しているように見えるので早く改修フェーズに移行できるともっと良いと思います。

# ランキングの勝者とは
https://pc.watch.impress.co.jp/docs/news/1413160.html
上記リンクの結果の表を見ると1位と3位は同じAMDのCPUを積んでいる。
同じCPUで3位とか・・・
と思われがちだが、消費電力を見ると別アプローチなのが分かる。
しばきあげで世界ランキング1位、省エネでも世界ランキング3位と考えるとAMDすごくない？と思ってしまう。
数値的には1/10の消費電力で1/4程度の性能、同程度の消費電力なら倍以上の性能だから超えるのも至難の業に思えてしまう。

第3世代EPYCに期待が集まるばかりである。
スティッキービットについて

## 環境
Ubuntu2.4

## 記事
ファイルやディレクトリの権限設定をする場合、chmodコマンドを使ってパーミッションを設定することになるのだが、「どのユーザーでも書き込みはできるようにしたいが、削除だけは所有者にしかできないようにしたい」といった、かゆい所に手を届かすような、微妙な権限設定がしたいといった場合、スティッキービットで実現できるようになります。

Ubuntuでデフォルトでスティッキービットが設定されている代表的になディレクトとして、**/tmp**があります。**/tmp**のパーミッションを確認してみると、最後が、**x**でも **-** でもなく、**t**になっています。これがスティッキービットです。

```
ls -ld /tmp
drwxrwxrwt
```

/tmpのパーミッションは777になっているため、/tmpディレクトリにあるファイルは、自分（所有者）が作成したファイルは勿論のこと、別のユーザーが作成したファイルも削除できると思いがちだが、スティッキービットが設定されているため削除することはできません。試しにrmをしてみると怒られます。

ファイルおよび、ディレクトリにスティッキービットを設定するには、パーミッションの設定で1000を加算すれば実現できます。
```
chmod 1777
```

スティッキービットを外す場合は、パーミッション設定で1000を減算すればOKです。
playwrightでテストする際、物理カメラがないのでwebcamに動画を流したい

# 問題

playwrightが操作するchromeとかはplaywrightが自前でインストールするもので、物理カメラがない（更に自分はdocker化している）

# 解決

https://playwright.dev/docs/test-configuration#global-configuration

playwright.config.ts にlaunchOptionsを追加する。この際に必要なのが`.y4m`拡張子か`.mjpeg`拡張子の動画

https://source.chromium.org/chromium/chromium/src/+/main:media/capture/video/file_video_capture_device.h;l=31

> The supported file formats are YUV4MPEG2 (a.k.a. Y4M) and MJPEG/JPEG

自分はiPhoneにあった動画をffmpegで`.mjepg`に変換した

```
$ ffmpeg -i iPhone.MOV sample.mjpeg
```

その上でlaunchOptionsのargsにこのように設定

```ts
import { PlaywrightTestConfig } from "@playwright/test"
const config: PlaywrightTestConfig = {
  use: {
    launchOptions: {
      args: [
        "--use-fake-ui-for-media-stream",
        "--use-fake-device-for-media-stream",
        "--use-file-for-fake-video-capture=/app/sample.mjpeg",
      ],
    },
  },
}
export default config
```


`--use-fake-ui-for-media-stream`は合わせて使うという事が書かれているページは見なかったが、自分の場合はこの3つを合わせないとだめだった
使っているパッケージの問題なのか、最近のchromeでの違いなのか...

- --use-fake-ui-for-media-stream
- --use-fake-device-for-media-stream
- --use-file-for-fake-video-capture=/app/sample.mjpeg

https://peter.sh/experiments/chromium-command-line-switches/#use-file-for-fake-video-capture

使っていたパッケージ

https://github.com/mozmorris/react-webcam


# 参考

https://stackoverflow.com/questions/52095416/how-can-i-correctly-provide-a-mock-webcam-video-to-chrome