OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】 Pandas データフレームの操作

# インポート
~~~python
import pandas as pd
~~~
# CSVの読み込み
~~~python
data = pd.read_csv("ファイルのパス")
~~~
例えば、データフレームが以下だとして進めていく。
~~~
	name	height	weight	age
0	シンジ	160	49	14.0
1	レイ	159	38	14.0
2	カヲル	162	47	NaN
3	マリ	172	58	NaN
4	アスカ	160	42	14.0
~~~
# 特定の列を取得
~~~python
# locを使用した列の抽出
data_target = data.loc[:,"name"]

# 以下のコードでも同じ実行結果が得られる
# data_target = data.name

data_target
~~~
~~~
<実行結果>
0    シンジ
1     レイ
2    カヲル
3     マリ
4    アスカ
Name: name, dtype: object
~~~
~~~python
# ilocを使用してDataFrameのまま列を抽出

data_target = data.iloc[:,0:1]

data_target
~~~
~~~
<実行結果>
	name
0	シンジ
1	レイ
2	カヲル
3	マリ
4	アスカ
~~~
~~~python
# locを使用した複数列の抽出
data_train = data.loc[:,"height":"age"]

data_train
~~~
~~~
<実行結果>
	height	weight	age
0	160	49	14.0
1	159	38	14.0
2	162	47	NaN
3	172	58	NaN
4	160	42	14.0
~~~

# 特定の行を取得
~~~python
data[0:3]
~~~
~~~
<実行結果>
name	height	weight	age
0	シンジ	160	49	14.0
1	レイ	159	38	14.0
2	カヲル	162	47	NaN
~~~

# 行の削除
~~~python
# 1行目を削除
df = df.drop(0)
~~~

# DataFrameの単純結合
axis = 0がデフォルトで縦結合、axis = 1で横結合
~~~python
import pandas as pd

data = pd.read_csv("sample.csv")

# dataの分割
data1 = data.iloc[:2,:4]
data2 = data.iloc[2:5,:4]

# dataの結合
data3 = pd.concat([data1, data2])

print(data,"\n")
print(data1,"\n")
print(data2,"\n")
print(data3)
~~~
~~~
<実行結果>
 name  height  weight   age
0  シンジ     160      49  14.0
1   レイ     159      38  14.0
2  カヲル     162      47   NaN
3   マリ     172      58   NaN
4  アスカ     160      42  14.0 

 name  height  weight   age
0  シンジ     160      49  14.0
1   レイ     159      38  14.0 

 name  height  weight   age
2  カヲル     162      47   NaN
3   マリ     172      58   NaN
4  アスカ     160      42  14.0 

 name  height  weight   age
0  シンジ     160      49  14.0
1   レイ     159      38  14.0
2  カヲル     162      47   NaN
3   マリ     172      58   NaN
4  アスカ     160      42  14.0
~~~

# インデックスの振り直し
drop = Trueにすることで元のインデックスを削除できる
falseにする（デフォルト）と元のインデックスは新しい列として追加される
~~~python
df_r = df.reset_index(drop=True)
~~~
React Nativeで文字列を扱う時に使ったテクニック

株式会社FUNEEでCONCRUを開発中のどんちゃんです。

ReactNative(Expo)を1から学習して1年数ヶ月。

プロダクトの開発が落ち着いてきたので、スキマ時間を使って、CONCRU開発で学んだノウハウや、テクニックを小出しにしていこうと思います。

今回は、最初の記事ということで、初歩的な、**文字列を扱う時のテクニック**　を紹介します。

## 文字を任意の箇所で折り返す
ReactNativeでは`Text`コンポーネントが提供されています。
https://reactnative.dev/docs/text

上記ドキュメントに書いてあることではありますが、可読性を担保するのであれば、コンポーネントごとにレンダリングするのが良いです。
各Textコンポーネントは、Viewコンテナーの子にするのがミソです。
	
```Typescript
import React, { Text, View } from 'react-native'

export const ExampleComponent = () => {
  return (
    <View>
      <Text>一行目</Text>
      <Text>二行目</Text>
      <Text>三行目</Text>
    </View>
  )
}

```

### 他の実現方法
「ReactNative Text 改行」なんかでググると、テンプレートリテラルや、 改行コード(¥n)を使う方法を解説してる記事が多いですが、僕的には読みづらいと思ってます。

### 応用
![](https://storage.googleapis.com/zenn-user-upload/c480c658049b-20220426.png)
例えば、この「リストを作る」ボタンはこういう風に作ってます(コードは説明用に加工してます)

`map`でレンダリングしてもOKです。

```TypeScript
export const FAB = ({ onPress, name, label }: Props) => {
  return (
    <TouchableOpacity style={[styles.float_button]} onPress={onPress}>
      <View style={{ alignItems: 'center' }}>
        <FontAwesome5 name={name} size={18} color={colors.white} />
        <Spacer size={4} axis="vertical" />
        {label.map((m, i) => {
          return (
            <Text key={i} style={[styles.label]}>
              {m}
            </Text>
          )
        })}
      </View>
    </TouchableOpacity>
  )
}

```

## 条件付きレンダーの罠
Reactでは、こういう風に　if文が如く、　返すコンポーネントを条件付きレンダリングできます。

```Typescript
render() {
  const count = 0;
  return (
    <div>
      {count && <h1>Messages: {count}</h1>}
    </div>
  );
}
```

https://ja.reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator

これを参考にReact Native向けに書き換えてみたコードです。

```typescript
import React, { Text, View } from 'react-native'

type Props = {
  description?: string
}
export const ExampleComponent = ({ description = '' }: Props) => {
  return <View>{description && <Text>{description}</Text>}</View>
}

```

今回のミソは、 `description`　の規定値が空文字(文字列型)であることです。上記では、このようなエラーが出ます。

```
Error: Text strings must be rendered within a <Text> component.
```

### 原因と対応
原因は、descriptionが`falsy`な値のために、 `View`の子が `JSX.Element`ではなく、空文字になってしまいます。

Reactでは問題ないのがハマりポイントでした。

対応方法ですが、空文字(文字列型)であることが原因なのでこうしてあげます。

そもそも規定値が空文字であること自体が考えものですが、今回は仕方ない…。

```typescript
import React, { Text, View } from 'react-native'

type Props = {
  description?: string
}
export const ExampleComponent = ({ description = '' }: Props) => {
  return <View>{!!description && <Text>{description}</Text>}</View>
}

```
【Python】 リストの差分を求める

# 重複データを保持せずに差分を求める
~~~python
l1 = ['a', 'b', 'c', 'd','a','b']
l2 = ['a', 'c']
result = list(set(l1) - set(l2))
print(result)
~~~
＜実行結果＞
['b', 'd']
# 重複データを保持して差分を求める
~~~python
l1 = ['a', 'b', 'c', 'd','a','b']
l2 = ['a', 'c']
result = list(filter(lambda x: x not in l2, l1))
print(result)
~~~
＜実行結果＞
['b', 'd', 'b']
【Python】たまに苦戦するnumpy配列の結合

# 使用する配列
~~~python:
import numpy as np

# サンプル配列の用意
# ２行５列
a = np.arange(10).reshape(2,5)
# 3行５列
b = np.arange(15).reshape(3,5)
# 2行４列
c = np.arange(8).reshape(2,4)
# １行５列
d = list(range(5))

# 作成した配列をprintして中身を確認
print(a)
print("\n")
print(b)
print("\n")
print(c)
print("\n")
print(d)
~~~
＜実行結果＞
[[0 1 2 3 4]
[5 6 7 8 9]]

[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]

[[0 1 2 3]
[4 5 6 7]]

[0, 1, 2, 3, 4]

# 縦方向に結合
列数が同じ場合に使用できる
~~~python
# 5行５列へ
e = np.vstack((a,b))
# 3行５列へ
f = np.vstack((a,d))
# ６行５列へ（3つ以上の配列の結合）
g = np.vstack((a,b,d))

print("e = np.vstack((a,b))")
print(e)
print("\nf = np.vstack((a,d))")
print(f)
print("\ng = np.vstack((a,b,d))")
print(g)
~~~

＜実行結果＞
e = np.vstack((a,b))
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]

f = np.vstack((a,d))
[[0 1 2 3 4]
[5 6 7 8 9]
[0 1 2 3 4]]

g = np.vstack((a,b,d))
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[ 0 1 2 3 4]]

# 横方向に結合
行数が同じ場合に使用できる
~~~python
# ２行９列へ
h = np.hstack((a,c))

print("h = np.hstack((a,c))")
print(h)
~~~
＜実行結果＞
h = np.hstack((a,c))
[[0 1 2 3 4 0 1 2 3]
[5 6 7 8 9 4 5 6 7]]
nginxでバックエンドがFQDNの場合に問い合わせごとにIPアドレスをキャッシュさせずに名前解決させる設定

## 仕組み
- NginxではProxy_passやUpstreamで指定しているFQDNのIPアドレスをキャッシュしてしまう
- バックエンドがDNSラウンドロビンなどで返ってくるIPアドレスが動的である場合、Failとしてカウントされ、そのバックエンドが死亡扱いになってしまう
- NginxPlusであれば、serverセクションにresolveを指定することで、IPアドレスをキャッシュせずに問い合わせごとに名前解決してくれる
- OSS版のNginxではresolveは使えないため、setを使ってFQDNを変数化する必要がある

## 設定例

```nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;
    resolver 8.8.8.8 valid=5s; #追加

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
```

```default.conf
server {
    listen       80;
    server_name  _;
    proxy_next_upstream error timeout http_502 http_503 http_504;

    location /google {
        proxy_pass  http://google_backend;
    }

    location /vamdemic {
        proxy_pass  http://vamdemic_backend;
    }
}

server {
    listen       unix:/var/run/nginx_backend1.sock;
    server_name  _;

    set $lb_backend1 "google.com";

    location / {
        proxy_pass  http://$lb_backend1:80;
    }
}

server {
    listen       unix:/var/run/nginx_backend2.sock;
    server_name  _;

    set $lb_backend2 "vamdemicsystem.black";

    location / {
        proxy_pass  http://$lb_backend2:80;
    }
}

upstream google_backend {
    server unix:/var/run/nginx_backend1.sock;
}

upstream vamdemic_backend {
    server unix:/var/run/nginx_backend2.sock;
}
```
autoComplete='off' がGoogleChromeで効かない

## オートコンプリートを無効にする方法

通常、こう書きますが
```tsx
  <input
    autoComplete='off' // reactで書いてるのでキャメルケースです
  />
```
なぜかchromeだとこれでもオートコンプリートが出てきます。
そして色々ググった結果、、、

```tsx
  <input
    autoComplete='new-off' // 色々試したけどnew-offとかnew-xxxならOKだった
  />
```
や、


```tsx
  <input
    autoComplete='none'
  />
```
と書くとchromeでのオートコンプリートが無効にできることを知りました。
このnewとかnoneがgoogleChrome内でどう認識され処理されているかは不明。。。


参考：https://stackoverflow.com/questions/37503656/react-doesnt-render-autocomplete-off
【Python】 単変量統計による特徴量選択

# はじめに
単変量統計とは、個々の特徴量とターゲットとの間に統計的に顕著な関係があるかどうかを計算し、最も高い確信度で関連している特徴量を選択しようとする手法です。

この手法は単変量であるため、他の特徴量と組み合わさって意味を持つような特徴量は捨てられてしまいます。
利点としてはモデルを構築する必要がなく、計算が高速な点です。
欠点としてはモデルベース特徴量選択や反復特徴量選択に比べ精度が劣る点です。

# プログラム（カイ二乗統計を用いた場合）
~~~python:chi2.py
# 単変量統計
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest

# それぞれの特徴量と目的変数間のカイ二乗統計量を計算
from sklearn.feature_selection import chi2

columns = ['sepal length','sepal width','petal length','petal width']
iris = load_iris()
X, y = iris.data, iris.target

# 特徴量を2つに絞る
selector = SelectKBest(chi2, k=2)
X_new = selector.fit_transform(X, y)

print('original features count: {}, selected features count: {}'.format(X.shape[1], X_new.shape[1]))
print('feature importance: ', selector.scores_)
print('pvalues: ', selector.pvalues_)
~~~


**実行結果**

original features count: 4, selected features count: 2
feature importance:  [ 10.81782088   3.7107283  116.31261309  67.0483602 ]
pvalues:  [4.47651499e-03 1.56395980e-01 5.53397228e-26 2.75824965e-15]


# カイ二乗スコアをグラフ表示
~~~python:chi2_plot.py
import matplotlib.pyplot as plt

# 特徴量とカイ二乗スコアを結合
feature_scores = list(zip(selector.scores_,columns))
# 降順にソート
sorted_feature_scores = sorted(feature_scores,reverse=True)

# 特徴量とカイ二乗スコアを分割
num_list = []
col_list = []
for i in range(4):
   num_list.append((sorted_feature_scores[i])[0])
   col_list.append((sorted_feature_scores [i])[1])


plt.bar(col_list,num_list)
plt.xticks(rotation=90)
plt.savefig('feture_score.png')
~~~
**実行結果**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781151/37b95608-2304-528c-2988-64a3219cd526.png)

# p値をグラフ表示
~~~python:chi2_p_value_plot.py
plt.bar(columns,selector.pvalues_)
plt.xticks(rotation=45)
plt.savefig('feture_pvalues.png')
~~~
**実行結果**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781151/d1982739-f81c-df10-b204-388d82145511.png)

# 考察
カイ二乗スコアは「petal length」、「petal width」が4つの特徴量の内で比較的高い値を示している。しかし、p値は「sepal length」、「petal length」、「petal width」の3つが00.5以下なのでこの3つがカイ二乗スコアとして高い値を示していると言えます

よって、2つ選ぶとすれば「petal length」、「petal width」となるが、「sepal length」、「petal length」、「petal width」の3つを選ぶのが妥当と言えます。
Watson StudioでNotebookのバージョン管理

Watson StudioのJupyter Notebookで過去のバージョンを保存しておくことができます。

■テスト環境
Watson Studio on Cloud(2022/4/26テスト）


# 1.バージョン保存
ノートブックを編集状態にして、時計のようなアイコンのバージョンのサイドメニューを開き、バージョンの保存ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4146ecef-fe13-2383-58e8-c3ace18d6673.png)

新しいバージョンが保存されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f735be82-fe47-caa0-46bc-b117db5d3f52.png)


コードを追加し、さらにバージョンを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/47246e97-cc14-3ca8-91e4-67e8ae8d6a47.png)

二つのバージョンが保存されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ec13d489-91b4-a3af-44d8-de0db82956fa.png)

スナップショットを保存しておくイメージになります。

# 2.バージョンの確認
各バージョンの中身を確認するには、バージョンを保存した日時をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e2f667bc-ad6e-d4ba-f74b-b73a913c51bc.png)

あらたなタブが開いて、古いバージョンを参照することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/c5e5ff62-2e7f-5b36-b0b0-01deaf1ebaf5.png)

# 3.バージョンの復元
編集対象のNotebookを古いバージョンに戻す場合には、バージョンのメニューから「戻す」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/223fa792-097a-bde0-08e6-71af1a17dcb8.png)

警告がでますので、「戻す」で進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/33aa9449-62bd-5360-aee6-49df5dee52fc.png)

最初のバージョンに戻りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ec57fb46-6474-db65-1bad-e1cd90562384.png)

新しい方のバージョンも消えてはいないので、新しいバージョンで戻すこともできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5227a364-2f3b-63b9-f7fe-39b290e5e17d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/3ce63d39-bc78-32f3-7851-b3577ef1ee97.png)
本気(マジ)で覚えろ！【Windowsショートカット基本編】

# はじめに
ショートカット覚えたら効率爆上がり(当社比)という声が私からありましてので共有します
※Windows10を基本にしています

今回参考にしたのはMicrosoft公式のサイト
[こちら](https://support.microsoft.com/ja-jp/windows/windows-%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89-%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88-dcc61a57-8ff0-cffe-9796-cb9706c75eec#WindowsVersion=Windows_10 "Windows10ショートカット")から全て確認できます。

# 基本編
|ショートカット|動作|
|:-:|:-:|
|Ctrl + X|選択した項目を切り取る|
|Ctrl + C (or Ctrl + Insert)   |選択した項目をコピーする|
|Ctrl + V (or Shift + Insert)|選択した項目を貼り付ける|
|Ctrl + Z|操作を元に戻す|
|Alt + Tab|開いているアプリ間で切り替える|
|Alt + F4|アクティブな項目を閉じる、またはアクティブなアプリを終了する|
|Windows + L|PC をロックする|
|Windows + D|デスクトップを表示または非表示にする|
|F2|選択された項目の名前を変更する|
|F3|エクスプローラーでファイルまたはフォルダーを検索する|
|F4|エクスプローラーのアドレス バー リストを表示する|
|F5|作業中のウィンドウを最新の情報に更新する|
|F6|ウィンドウ内またはデスクトップ上の画面要素を順番に切り替える|
|F10|アクティブなアプリのメニュー バーをアクティブにする|
|Alt + F8|サインイン画面でパスワードを表示する|
|Alt + Esc|項目を開かれた順序で順番に切り替える|
|Alt + 下線付き文字|その文字に対応するコマンドを実行する|
|Alt + Enter|選択した項目のプロパティを表示する|
|Alt + Space|作業中のウィンドウのショートカット メニューを開く|
|Alt + ←|前に戻る|
|Alt + →|次に進む|
|Alt + PageUp|1画面上へ移動する|
|Alt + PageDown|1画面下へ移動する|
|Ctrl + F4|作業中のドキュメントを閉じる (複数のドキュメントを同時に開くことができる全画面表示のアプリで)|
|Ctrl + A|ドキュメント内またはウィンドウ内のすべての項目を選択する|
|Ctrl + D (または Del)|選択した項目を削除し、ごみ箱に移動する|
|Ctrl + R (または F5)|作業中のウィンドウを最新の情報に更新する|
|Ctrl + Y|操作をやり直す|
|Ctrl + →|次の単語の先頭にカーソルを移動する|
|Ctrl + ←|前の単語の先頭にカーソルを移動する|
|Ctrl + ↓|次の段落の先頭にカーソルを移動する|
|Ctrl + ↑|前の段落の先頭にカーソルを移動する|
|Ctrl + Alt + Tab|方向キーを使って、開いているすべてのアプリ間で切り替える|
|Alt + Shift + 方向キー|スタート メニュー内でフォーカスされているグループまたはタイルを指定した方向に移動する|
|Ctrl + Shift + 方向キー|スタート メニューのタイルにフォーカスがあるときに、別のタイルに移動してフォルダーを作成する|
|Ctrl + 方向キー|スタート メニューが開いているときにサイズを変更する|
|Ctrl + 方向キー (項目に移動する) + Space キー|ウィンドウ内またはデスクトップ上の複数の項目を個別に選択する|
|Ctrl + Shift + 方向キー|テキストのブロックを選択する|
|Ctrl + Esc|スタート メニューを開く|
|Ctrl + Shift + Esc|タスク マネージャーを開く|
|Ctrl + Shift|キーボード レイアウトを切り替える (複数のキーボード レイアウトが使用可能になっている場合)|
|Ctrl + Space|中国語の入力方式エディター (IME) をオンまたはオフにする。|
|Shift + F10|選択した項目のショートカット メニューを表示する|
|Shift + 任意の方向キー|ウィンドウ内またはデスクトップ上の複数の項目を選択する、またはドキュメント内のテキストを選択する|
|Shift + Del|選択した項目をごみ箱に移動せずに削除する|
|→|右側にある次のメニューを開く、またはサブメニューを開く|
|←|左側にある次のメニューを開く、またはサブメニューを閉じる|
|Esc|現在の作業を停止または終了する|
|PrintScreen|画面全体のスクリーンショットを撮影し、クリップボードにコピーする|

# おわりに
~~想像以上に多かった~~
JISキーボード使ってる方とかは``Ctrl``+``Space``とか使用しない人が大半だと思います(USキーボードだとよく使う)
個人的使用頻度が高いものもピックアップしたのも別途あげるかもしれません
今回は基本的なショートカットだけで、まだまだWiondowsキーとか、エクスプローラ向けのショートカットなど多数あります
こちらも使用事例含めて改めて紹介できればと思います

Twitterもやってます。よろしければフォローお願いします→[@mzsn53](https://twitter.com/mzsn53 "Twitter@mzsn53")
【Python】 matplotlib x軸ラベルを縦に書く（90度回転）

# プログラム
```python
import matplotlib.pyplot as plt

columns = ['Tom','Mike','Emi']
values = [178,182,165]

plt.bar(columns,values)

# x軸ラベルを縦に書く（90度回転）
plt.xticks(rotation=90)

# plt.show()
# 保存
plt.savefig('Fig1.png')
```
# 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781151/776b4a7b-d278-6462-54ba-5eac4dce547f.png)
WSL2のUbuntuを22.04にアップグレードしたらdockerが起動できなくなった

## 前提：構成
* Windows10
* WSL2 カーネルバージョン 5.10.102.1
* Ubuntu 22.04 LTS　※アップグレード前は「Ubuntu 20.04.4 LTS」
* docker-ce 20.10.14　※docker desktopは未使用

## 前提：アップグレードでやったこと
```
sudo apt update && sudo apt upgrade
sudo apt dist-upgrade && sudo apt install update-manager-core
sudo do-release-upgrade -d
```

## dockerが起動しない
```
$ sudo /etc/init.d/docker start
 * Starting Docker: docker                        [ OK ]
$ docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See 'docker run --help'.
$
```

## docker起動時のエラーメッセージ

>failed to start daemon: Error initializing network controller: error obtaining controller instance: unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain:  (iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: iptables v1.8.7 (nf_tables):  RULE_APPEND failed (No such file or directory): rule in chain DOCKER-ISOLATION-STAGE-1  (exit status 4))


## エラー内容にiptablesとあったのでlegacyにしてみる
```
$ sudo update-alternatives --config iptables
alternative iptables (/usr/sbin/iptables を提供) には 2 個の選択肢があります。
選択肢 パス 優先度 状態
------------------------------------------------------------
* 0 /usr/sbin/iptables-nft 20 自動モード
1 /usr/sbin/iptables-legacy 10 手動モード
2 /usr/sbin/iptables-nft 20 手動モード
現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 1
update-alternatives: /usr/sbin/iptables (iptables) を提供するためにマニュアルモードで /usr/sbin/iptables-legacy を使います
$
```

## 無事起動できました
```
$ sudo /etc/init.d/docker start
 * Starting Docker: docker                        [ OK ]
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:10d7d58d5ebd2a652f4d93fdd86da8f265f5318c6a73cc5b6a9798ff6d2b2e67
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```
Windows10 + WSL2(Ubuntu-20.04) + phpStorm でGitがコケた

phpStorm いつのまにか、GitHubへの操作ができない

```
git@github.com: Permission denied (publickey). Could not read from remote repository.
```
と、怒られた。

![スクリーンショット 2022-04-26 112959.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378284/33aab080-f1c9-09e2-49f9-e432a2aadbe0.jpeg)

ぐぬぬ。

phpStorm以外のGit系のツールやWindowsのコマンドでは動く
なんか設定おかしい？
と思って確認すると

あれ？
![スクリーンショット 2022-04-26 112800.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378284/cb749a9a-6893-ad8c-ac71-ba3374f71b0a.jpeg)
開発したブツはUbuntuでGitは基本的にせずWindows側でしているのだが、
いつのまにか設定かわっておる
別件でUbuntu上でGitからみの作業した記憶はある。が勝手にかわるものなのか？


ということで、以下のように設定して事なきを得た。
![スクリーンショット 2022-04-26 112908.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378284/ea096831-d5e3-6ff4-8025-8ed32f3fdc20.jpeg)
Trying to populate non string value into a string for variable ${sls:stage}

メモ: Serverlessframework で

```
Trying to populate non string value into a string for variable ${sls:stage}. Please make sure the value of the property is a string.
```

のようなエラーが出る時は、一見 --stage hoge オプションを付け忘れたのかなと思ってしまうが、実際は serverless.yml の中に

```
${self:custom.myproject.${sls:stage}.GRAPHQL_API_KEY}
```

のような stage で場合分けしたいカスタムエントリえの参照があるのに

```
custom:
  myproject:
    hoge:
      GRAPHQL_ENDPOINT: 'https://hoge/graphql'
```

のようなエントリを作成するのを忘れた時。
PythonでSlackにメッセージを送る

今開発しているプログラムでエラーが出た時に、Slackの特定のチャンネルにエラー通知を送る必要が出たので、メモとして記録してみる。Pythonのrequestsのモジュールを使えば特に難しいことはなかったが、Slackのドキュメント？が英語だったため、個人的にはそこに苦労した。

# 前提
Slackのアカウントを持っていることと、SlackのWorkspaceを持っていること。でないと次へは進めない。

# Slack側の準備
まずは[slack api](https://api.slack.com/)のページから"Create an app"に入る。目的は、Webhookを利用すること。
多分、こんな画面が出てくる。

![スクリーンショット 2022-04-26 10.25.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/4673f7bf-3420-762e-2803-15d2dc777bcb.png)

ここでは"From scratch"を選択する。すると、次の画面が登場。

![スクリーンショット 2022-04-26 10.27.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/f7dd336b-8b6b-f7bb-c393-1a4f35941ffb.png)

"App Name"は適当に。このNameでメッセージが書き込まれるので、そのつもりで。次に"Pick a workspace develop your app in:"でメッセージを送りたいワークスペースを選択する。この２つを実行することで、"Create App"に進める。次はこんな画面になる。

![スクリーンショット 2022-04-26 10.33.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/810e4c66-4feb-ca86-069f-ec6dcf548870.png)

英語です、、。一気に面倒臭さが増す。でもあとちょっとでSlack側の設定は終わるから頑張ろう。で、下のほうに進んでいくと、こんな画面がある。

![スクリーンショット 2022-04-26 10.35.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/81781cbc-b8aa-0549-a7b1-80ebfb29e3e7.png)

ここを選択する。で、この画面になる。

![スクリーンショット 2022-04-26 10.36.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/49958b6b-6acc-6b94-e17a-8fa18fc1e8cf.png)

"Activate Incoming Webhooks"をOnにしよう。すると下にこんなのが出てくる。

![スクリーンショット 2022-04-26 10.38.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/06b40c59-664e-76d9-eadb-dbc993c3bd63.png)

"Add New Webhook to Workspace"のボタンを押す。するとこんな画面。

![スクリーンショット 2022-04-26 10.39.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/f3a936c9-7903-5c54-7e27-283726a3e01e.png)

来たぜ！日本語！で、メッセージを送りたいチャンネルを選択して、"許可する"のボタンを押す。すると、下の画面にようにURLが発行される。

![スクリーンショット 2022-04-26 10.55.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617838/3e49628f-6d4b-423d-f2e5-fdaeea10fbed.png)


このURLは使うので、コピーするなり画面をそのままにしておくなりしておいて欲しい。ここでコピーしたURLを"Webhool_URL"をする。これでSlack側の設定は終了。

# 実際のコーディング
実際のコーディングをやってみる。シンプルに書いてみた。

```Python:send_msg_slack.py
import requests
import json

def send_msg():
    slack_url = "Webhool_URL"
    content = {'content-type': 'application/json', 'text': "これはTESTです。"}
    requests.post(slack_url, data=json.dumps(content))

```

これだけでメッセージが送れるようになります。上でも説明した通り、"Webhool_URL"はSlackで設定したときに取得できたURLの事。私が実際に書いたコードはプログラムの途中にあるので、一部改変してます。

# まとめ
以外に簡単に出来た感じがする。Python初めて学習する人には難しく感じるかもしれないが、requestsのモジュールの使い方が分かれば、他の似たようなサービスでも同じような手順でできるかもと思っている。
ちなみに@seratch(Slack)さんの記事[Python で Slack API や Webhook を扱うなら公式 SDK（slack-sdk/slack-bolt）を使おう](https://qiita.com/seratch/items/8f93fd0bf815b0b1d557)でSDKの使い方について紹介されている。Slack で公式 SDK の開発に従事している方との事なので、この記事に勝るものはないはず。私も後日勉強させて頂こう。
Node.jsからLINE Notifyを使うメモ (Fetch API利用）


Node.js v18のアップデートでFetch APIがフラグなしで使えるようになったよという話題があるのでLINE NotifyのAPIで試してみました。

> [「Node.js 18」がリリース ～fetch API、Web Streams APIがグローバルスコープで利用可能に](https://forest.watch.impress.co.jp/docs/news/1404310.html)

## 先に実装したコピペ用コード

v18以降ならこのまま実行して動くと思います。

```js
'use strcit';

const BASE_URL = 'https://notify-api.line.me';
const PATH =  '/api/notify';
const LINE_TOKEN = `トークン`;

const params = new URLSearchParams({
    message: 'こんばんわ。Node.js v18 Fetch APIでLINE Notify API を使ってみました。',
});

const config = {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': `Bearer ${LINE_TOKEN}`
    },
    body: params.toString()
};


const main = async () => {
    const res = await fetch(BASE_URL + PATH, config);
    console.log(res.status);
}

main();
```

> ![スクリーンショット 2022-04-26 11.02.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/3d192e73-f87b-375d-0e1f-6ab5584f3053.png "スクリーンショット 2022-04-26 11.02.50.png")

問題なく動きました。

## 書き換えた部分

ちなみに前に書いたaxiosのコードを参考に書き換えてます。

https://qiita.com/n0bisuke/items/b96ee96314104447a63f

パラメータの指定が少し書きかわってるのはありますが、大体似たような感じです。

axiosだとdataにリクエストデータを詰め込みますが、`body`になっています。

また、これはFetch API話とは違いますが、querystringの箇所も怒られたのでURLSearchParamsを利用するように書き換えました。

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/178cc77b-d947-1bca-41e6-65720b99656b.png" width="300px" />
 
### Fetch APIのリクエストオプション

MDNのサイトに書いてるものを参考に。

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch

## 所感

試してないですが、ブラウザ側と同じコードで動きそうですね。

`npm i axios`などを実行しないでできるのは新鮮。
PostgreSQLのバックアップとリストアの、些末な事例

# 前提

　パッケージとは名ばかりの、顧客ごとにカスタマイズが都度発生して微妙に仕様が変わってしまうようなwebシステムを、DBにPostgreSQLを構えて納めているお仕事。サーバーはオンプレミス、UPSに繋いで基本的に停止させることがない業務用組織内システム。
　保守対応を遠隔操作にて行う上で作業時間を短縮するために、現地のサーバー行き当たりばったりでいじることをせず、社内でも同じ環境を立ち上げるようにしている。

# 保守のために、現地サーバーのデータを社内検証サーバーに反映する

　現地では時々刻々新しいデータが追加されていく。
　スキーマやテーブルなど構造の変更はなく、単にレコード追加がされていき、ユーザーはweb画面越しに表示される情報を見ているだけ。
　そのため、**必要なテーブルのデータのみをバックアップを取って反映する**やり方を採用している。

# バックアップは pg_dump コマンドを活用

　出張の際にも持ち歩く紙ノートに、pg_dump コマンドをメモしてある。

```bash
pg_dump -U foo -d foo_db -n foo -a > fooYYYYMMDD.dump
```

　まぁ、それもシェルスクリプトを使って日付時刻をファイル名に展開すればいいんだろうけど、そこまで自動化させてない。ダンプファイル名に年月日は必ずつけて、作業前ならbefore、作業後ならafterをファイル名に補ったりする。
　コマンドオプションの、-U はユーザ(ロール)の指定、-d は対象データベース名、-n は対象スキーマ名、-a はデータのみ出力して CREATE TABLE文などを含まない。
　出力されるダンプファイルはSQLファイルそのもので、テキストエディタで読ませて加工することもできる。データのみ出力なので、ほぼほぼCOPY文になっている。

# リストアで一工夫

　スキーマほかデータ構造は変わっていないため、関係するテーブルのレコードを全て削除してから、ダンプファイルを psql コマンドにて「\i fooYYYYMMDD.dump」などとすればOK。

　TRUNCATE TABLE文を固定で用意しておくのもいいけど、いつテーブルが追加になる変更が加わるかわからないので、今のところ直前に対象テーブルをクエリーで拾い上げてTRUNCATE TABLE文を自動生成させている。
　[PostgreSQLにてテーブルをTRUNCATEするクエリを出力するクエリ \- いろいろ備忘録日記](https://devlights.hatenablog.com/entry/2021/01/15/110921)の記事で紹介されているのを応用して、こういうふうにした。

```SQL
SELECT
    'TRUNCATE TABLE ' || ARRAY_TO_STRING(ARRAY_AGG(relname), ',') || ';' AS query
FROM
    pg_stat_user_tables
WHERE
    schemaname = 'foo';
```

　バックアップするときにスキーマ名を指定しているのだから、TRUNCATE TABLE文を実行する対象もスキーマ名を指定するべき、という考え方。

# 余談：サーバー構築にHyper-VとDisk2VHD

　web＆dbサーバーとしてUbuntu 20.04ベースでやっており、以前はPC2台用意して一つはLinuxが入っているものを調達していたものの、PC2台設置は場所も取るしコストもかかるため、今はHyper-V上にUbuntuを立てている。（当然、Windows 10 Proが必要になる。）

　社内の開発サーバー上でHyper-V上にUbuntuサーバーを構築。
　出荷時には、出荷用PC（もちろんWindows 10 Pro）のHyper-V マネージャーにてVMをインポートする。[インポートの種類](https://docs.microsoft.com/ja-jp/windows-server/virtualization/hyper-v/deploy/export-and-import-virtual-machines#import-types)は「仮想マシンをコピーする」を選択している。

　Windows 10 Pro上でもいくつか弊社製作プログラムが動いているので、初期構築時に[Disk2vhd](https://docs.microsoft.com/ja-jp/sysinternals/downloads/disk2vhd)を使ってCドライブをイメージファイル化してバックアップとする。が、ちっぽけなUSBメモリには収まりきらないのでUSB接続SSDを借りてくることも。
Field Service Dispatcher Console for Dispatchers -> Customize Your View

[Trailhead関係　個別の課題別 に戻る](https://qiita.com/Keiji_otsubo/items/56eb7a90bb72138ece1f)


# We can't find the Short Jobs palette

+ [Customize Your View - We can't find the Short Jobs palette](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000GhxRHSAZ)

+ [I cannot complete the challenge (Field Service)](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000J68ioSAB)
Thank you! I was able to figure out the problem. You can't use the current date you have to go to Sept 22, 2021

+ [Field Service: Customize your view](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JeLc3)

:::note
Turns out my issue was not getting set up on the right version of the developer org -  I ended up finding success by deleting the 'Short Jobs' palette that existed, and starting from scratch, rather than simply updating the existing palette that came with the org.   I believe I selected a value other than 'Duration in Minutes' to begin, then went back and updated - though the challenge wouldn't recognize the update.
:::

# short Jobs paletteがない　FLS : 2021年11月の質問の中から整理します

+ [フィールドサービスディスパッチャモジュールの問題](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000BsYFUSA3)
+ [We can't find the Short Jobs palette:FLSの特別バージョン環境でなかったようです](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000GgvpeSAB)

# ディスパッチャ用のフィールドサービスディスパッチャコンソール We can’t find the Short Jobs palette. : 2022年03月の質問の中から整理します

+ [チャレンジを完了できません](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000FXw9m)

+ [In 'Customize your view' module under 'Field service dispatcher console for Dispatchers' we are asked to create a Short jobs palette. I created the same, but the challenge is not getting completed. Not sure on the issue. unable to add screenshot here.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PZEuu)

+ [We can't find the Short Jobs palette. Make sure the palette was created according to the requirements, including the minimum and maximum values and colors.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000BsYFU)

:::note
 Deleting the palette and rebuilding it fixed the issue.
:::
フローのDatatable: Unable to configure columnsエラー

[Datatable: Unable to configure columns](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G5ewoSAB)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d0bf9514-1a5c-0e1e-6bc4-1ab38d10a1ea.png)


列を構成しようとしたときにこのエラーが表示された場合は、
[設定]>[セキュリティ]>[セッション設定]に移動し、 
[ヘッダーが無効になっているカスタマーVisualforceページのクリックジャック保護を有効にする]のチェックを外してみてください。
また、[設定]> [ユーザー設定]で、デバッグモードと開発モードの両方がオフになっていることを確認します。
cscの作法 その154

# 概要
cscの作法、調べてみた。
winmm.dll使ってみた。

# 参考にしたページ

http://otktake.blogspot.com/2016/02/c.html


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/2fbcd77e-488b-5c1d-8b5d-24e386b7f691.png)


以上。
cscの作法 その153

# 概要
cscの作法、調べてみた。
opencvやってみた。
DescriptorMatcher使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/aec65420-aed5-78bd-96d1-7c8d42030d51.png)


# サンプルコード


```
using System;
using System.Windows.Forms;
using System.Drawing;
using OpenCvSharp;

namespace cv
{
	public class Form1 : Form {
		public Button button1;
		public Form1() {
			Text = "akaze";
			button1 = new Button();
			button1.Location = new System.Drawing.Point(50, 50);
			button1.Size = new System.Drawing.Size(100, 30);
			button1.Text = "show";
			Controls.Add(button1);
			button1.Click += new EventHandler(button1_Click);
		}
		private void button1_Click(object sender, EventArgs e) {
			Mat mat = new Mat("j0.png", ImreadModes.Color);
			Mat temp = new Mat("j1.png", ImreadModes.Color);
			Mat output1 = new Mat();
			Mat output2 = new Mat();
			Mat output3 = new Mat();
			AKAZE akaze = AKAZE.Create(AKAZEDescriptorType.MLDB, 0, 3, 0.001f, 4, 4, KAZEDiffusivityType.DiffPmG2);
			KeyPoint[] key_point1;
			KeyPoint[] key_point2;
			Mat descriptor1 = new Mat();
			Mat descriptor2 = new Mat();
			DescriptorMatcher matcher;
			DMatch[] matches;
			akaze.DetectAndCompute(mat, null, out key_point1, descriptor1, false);
			akaze.DetectAndCompute(temp, null, out key_point2, descriptor2, false);
			Cv2.DrawKeypoints(mat, key_point1, output1, 0,  DrawMatchesFlags.Default);
			Cv2.ImShow("output1", output1);
			Cv2.DrawKeypoints(temp, key_point2, output2, 0,  DrawMatchesFlags.Default);
			Cv2.ImShow("output2", output2);
			matcher = DescriptorMatcher.Create("BruteForce");
			matches = matcher.Match(descriptor1, descriptor2, null);
			Cv2.DrawMatches(mat, key_point1, temp, key_point2, matches, output3, null, null, null, DrawMatchesFlags.Default);
			Cv2.ImShow("output3", output3);
		}
		[STAThread]
		static void Main() {
			Application.Run(new Form1());
		}
	}
}



```

以上。
APIコール時のエラーでデバッグログを作成する


[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


セットアップに移動し、「デバッグログ」を検索します。「新規」ボタンをクリックして、必須フィールドに入力します。開始日時と終了日時を設定する必要があります。ここでの説明。次に、エラーが発生しているアクションを実行すると、ログで何が起こっているかをより詳細に確認できます。ログを正しく設定して必要なものをキャプチャするには少し手間がかかりますが、必要に応じて日付を変更するだけで、ログを再利用できます。一度に取得できるログは24時間のみです。

[Set Up Debug Logging](https://help.salesforce.com/s/articleView?id=sf.code_add_users_debug_log.htm&type=5)

元の質問

[Asanaにリクエストしようとしたときに「リクエストに一致するルートがありません」](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G6LUH)

# 関連するエラー

+ [PythonでのSalesforceAPI連携の開発中に遭遇したエラーについて](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Jdy6qSAB)

```
TypeError: __init__() got an unexpected keyword argument 'sandbox'
```

ライブラリーのバージョンアップを実施すると解消されたようです。
cscの作法 その152

# 概要
cscの作法、調べてみた。
opencvやってみた。
WarpPerspective使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/88fbbc82-93e8-3871-0f51-cdf9afe301cb.png)

# サンプルコード

```
using System;
using System.Windows.Forms;
using System.Drawing;
using OpenCvSharp;

namespace cv
{
	public class Form1 : Form {
		public Button button1;
		public Form1() {
			Text = "WarpPerspective";
			button1 = new Button();
			button1.Location = new System.Drawing.Point(50, 50);
			button1.Size = new System.Drawing.Size(100, 30);
			button1.Text = "show";
			Controls.Add(button1);
			button1.Click += new EventHandler(button1_Click);
		}
		private void button1_Click(object sender, EventArgs e) {
			Mat src = new Mat("cv.png", ImreadModes.Color);
			Mat dst = new Mat();
			Point2f[] srcPoints = new Point2f[] {
				new Point2f(69, 110),
				new Point2f(81, 457),
				new Point2f(500, 300),
				new Point2f(500, 50),
			};
			Point2f[] dstPoints = new Point2f[] {
				new Point2f(0, 0),
				new Point2f(0, 512),
				new Point2f(512, 512),
				new Point2f(512, 0),
			};
			Mat matrix = Cv2.GetPerspectiveTransform(srcPoints, dstPoints);
			Cv2.WarpPerspective(src, dst, matrix, dst.Size(), 0, 0, 0);
			Cv2.ImShow("src", src);
			Cv2.ImShow("dst", dst);
		}
		[STAThread]
		static void Main() {
			Application.Run(new Form1());
		}
	}
}





```

以上。
競技プログラミングで頻繁に使用されるrepマクロの問題点と解決案

# そもそもrepマクロとは

競技プログラミングで入力文字数を減らすためにしばしば使われる、以下のようなマクロである。

```c
#define REP(i, n)    for (int i = 0; i < (n); i++)
```

# repマクロのなにが問題か

## そもそもC++ではマクロの使用自体が推奨されていない

現行のC++においてマクロは**本当に必要でない限り利用すべきでない機能**とされており、他の記法を使用できる限りそちらを使用するべきである。

## C/C++のマクロの変換処理は構文を考慮しない

C/C++のマクロは、単に引数をテキスト置換した上で実コードに変換される。

重要な点として、**マクロの変換処理はスコープを一切考慮しない**ため、例えば`namespace`などのステートメントで適用範囲を束縛することが出来ない。

本来C/C++のfor文は宣言からループ処理の記述を含めて一つのステートメントとされているが、構文規則を無視することで宣言部分のみを無理やり分割して変換しているため、注意しないと構文の整合性を損なう恐れがある。
引数`n`をカッコで括っているのはこれを防ぐためである。

意地悪な例としては以下のようなものがある。

```c++
void solve() {
 	int a = 8;
 
   	REP(i = a, 3)
   		std::cout << i << std::endl;
 
    std::cout << "Out: " << a << std::endl;
}
```

この関数の実行結果は以下のようになる。

```
1
1
1
Out: 3
```

この関数のループカウンタは正しく動作せず、変数`a`は代入されているはずの8ではなく、3を返す。
マクロが以下のように変換されるからである。

```c
for (int i = a = 0; i = a < (3); i = a++)   // aの値が変更されている！
```

このfor文はループカウンタ変数`i`の代わりに変数`a`をインクリメントし、条件式を含む全ての式を実行するごとに、ループカウンタに値を代入してしまう。[^1]

[^1]: `i`にカッコをつければ抑制できるが、~~GCCの場合、カッコが必要ないケースでwarningが出る。~~`int{i}`と書けばwarningを抑制できます。

# 代わりになりそうな方法

## boost::irangeを使う

[Boost Library](https://www.boost.org/)の中に`irange`というループを処理するためのクラスがある。

```c++
for (int i : boost::irange(0, n)) {
    // 0からn-1までのループ
}
```

第一引数に`0`以外を指定すれば`0`以外で始まるループも指定可能。

## C++のラムダ式を使う

```c++
template<typename F> constexpr void rep(int n, F function) {
    for (int i = 0; i < n; i++)
        function(i);
}
```

以下のように書けるようになる。

```c++
rep(n, [&](int i) {
    // do something
});
```

`std::for_each`とほとんど同じように使えるので、タイプ数を減らすなら多分この方法が一番実用的。

### クローリング中に見つけたのですが…

- [AtCorder の rep マクロを関数にしたい](https://qiita.com/terukazu/items/2126d1e6b5b71678377f)

良記事です。ループの途中抜けに対応していたりと色々すごい。

## 番外編：while (n--)

古い環境でミリ秒単位の高速化をするために、C時代から使われていたループ。
元の変数そのものをループカウンタとして使用するため、値が変わってしまうのがネック。
当然ながら、値がマイナスだった場合は（実質的に）無限ループしてしまう。

```c
while (n--) {
    // do something
}
```

確かにタイプ量は少ないが…

<!-- この節いる？
# 結局repマクロは使ってはいけないのか？

微妙なところです。

意外に思うかもしれませんが、ストラウストラップ本を見ると以下のマクロの例は問題がないと書かれています。

```c
#define FOREVER for (;;)
```

結局のところ使わざるを得ないのであれば、バグさえ出さなければ（推奨こそしないものの）使うこと自体は問題ないようで、for文をぶった切る用途に使うこと自体が絶対にいけない、という訳ではなさそうです。

ただCはともかく、C++の場合ループを表現する手法自体はいくらでもあるので、マクロにこだわるのはあんまりいい傾向ではないかなあと思います。
競プロの様な短時間でコードを書き捨てる状況ではある程度しょうがない様な気もしますが、自分なら個人・集団を問わず**C++の実開発では絶対に使わないでください**[^1]と言うと思います。

[^1]: 言い換えれば、素のC言語では使わざるを得ないケースがあり得ると言うことでもある。
-->

# 最後に

多分そろそろRustに乗り換えたほうがいいです。

# 参考文献

- プログラミング言語C++ 第4版 - Bjarne Stroustrup, 柴田望洋, SBクリエイティブ
cscの作法 その151

# 概要
cscの作法、調べてみた。
opencvやってみた。
akazeやってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6a229c45-eb9b-7e5a-697f-04f53da70ee1.png)


# サンプルコード


```
using System;
using System.Windows.Forms;
using System.Drawing;
using OpenCvSharp;

namespace cv
{
	public class Form1 : Form {
		public Button button1;
		public Form1() {
			Text = "akaze";
			button1 = new Button();
			button1.Location = new System.Drawing.Point(50, 50);
			button1.Size = new System.Drawing.Size(100, 30);
			button1.Text = "show";
			Controls.Add(button1);
			button1.Click += new EventHandler(button1_Click);
		}
		private void button1_Click(object sender, EventArgs e) {
			Mat src = new Mat("cv.png", ImreadModes.Color);
			Mat dst = new Mat();
			Mat kpt = new Mat();
			KeyPoint[] keyPoints;
			AKAZE akaze = AKAZE.Create(AKAZEDescriptorType.MLDB, 0, 3, 0.001f, 4, 4, KAZEDiffusivityType.DiffPmG2);
			akaze.DetectAndCompute(src, null, out keyPoints, dst, false);
			Cv2.DrawKeypoints(src, keyPoints, kpt, 0,  DrawMatchesFlags.Default);
			Cv2.ImShow("src", src);
			Cv2.ImShow("out", kpt);
		}
		[STAThread]
		static void Main() {
			Application.Run(new Form1());
		}
	}
}




```

以上。
AWS CDKで "but no credentials have been configured" のエラーが出る

## 発生した問題

AWS CDKに入門してbootstrapしようとしたら、"but no credentials have been configured" みたいなエラーが出てきて詰まったので、解決策をメモしておく。

## TL;DR

`~/.aws/config` の該当箇所を全てを以下のように直せば解決する。

### Before

```
[<PROFILE_NAME_1>]
...
[<PROFILE_NAME_2>]
...
```

### After

```
[profile <PROFILE_NAME_1>]
...
[profile <PROFILE_NAME_2>]
...

```

## 解決への道のり

エラー文の通り、AWSの認証情報がCDK側で受け取れていないのが原因そうだった。しかし、`~/.aws/config` と `~/.aws/credentials` にはちゃんと `cdk bootstrap aws://xxx/yyy --profile <PROFILE_NAME>` で指定したプロファイルに対する設定が書かれていた。

なぜちゃんと書かれているプロファイル設定がCDK側で認識できないのかと悩み、色々ググったら[GitHubのissue](https://github.com/aws/aws-cdk/issues/6947)が見つかった。このissueの問題には直接関係なかったが、issue中の[あるコメント](https://github.com/aws/aws-cdk/issues/6947#issuecomment-840473976)を見ると、`~/.aws/config` 内のプロファイル名の指定はprefixとして `profile` 付くらしいというのがわかった。自分のを見ると付いておらず、

```
[<PROFILE_NAME>]
...
```

のようになっていた。

特段自分でいじった覚えがなく、なぜprefixがつかないで記述されていたのかは分からなかった。AWS CLIやTerraformで使う分にはprefixがついてない設定ファイルでも問題なく動作していたので、今まで気づかなかった。

そこで、`~/.aws/config` のプロファイルの指定を

```
[profile <PROFILE_NAME>]
...
```

のように直すと、無事AWS CDKの方でプロファイルの設定を認識してくれるようになった。めでたしめでたし。
GithubでPull Requestのマージを打ち消す方法と、やっぱり打ち消しをなかったことにしたいとき（RevertのRevert）

参考記事
https://saikeblog.com/2020/03/09/github%E3%81%A7pull-request%E3%81%AE%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%92%E6%89%93%E3%81%A1%E6%B6%88%E3%81%99%E6%96%B9%E6%B3%95/#:~:text=Github%E3%81%A7Pull%20Request%E3%81%AE%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%92%E6%89%93%E3%81%A1%E6%B6%88%E3%81%99%E3%81%AB%E3%81%AF,%E6%89%93%E3%81%A1%E6%B6%88%E3%81%99%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82
Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize

#### 概要
下記の様なコードでメモリエラーが出ました。


```sample.py
import matplotlib
import matplotlib.pyplot as plt

#グラフループ
for i in range(1000):
    #グラフオブジェクト
    fig, ax = plt.subplots()
    #描画
    ax.plot(x,y)
    #出力
    fig.savefig(path_file)
    #図形クリア
    plt.clf()
    #window閉じる
    plt.close()

```

#### エラー内容
**Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize**

#### 原因
**fig.savefig**が原因の様です。

#### 解決方法

**matplotlib.use('Agg')** を追記して、解決しました。

```sample.py
import matplotlib
import matplotlib.pyplot as plt

#
matplotlib.use('Agg')  #追記

#グラフループ
for i in range(1000):
    #グラフオブジェクト
    fig, ax = plt.subplots()
    #描画
    ax.plot(x,y)
    #出力
    fig.savefig(path_file)
    #図形クリア
    plt.clf()
    #window閉じる
    plt.close()

```
  
参照
[plt.close() だけではメモリが解放されない場合がある](https://qiita.com/Masahiro_T/items/bdd0482a8efd84cdd270)
キャラクター液晶ACM1602K-NLW-BBWと74HC164のまとめ(リンク集)



74HC164を使うのは、総配線距離と配線数を減らす為、74HC164は、秋月等で100円で売っている。
電子工作には、74HC164を使ってひと手間かけるのも重要。
特に8ピンしかないSTM32G031J6M6では、74HC164を使うのは、絶対条件。


![o_con363.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5d57ffa0-db25-8868-079c-7b60bba45ca1.jpeg)


![o_con364.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1bed353a-05e5-5cc0-08b1-e6acdd50a133.jpeg)


I2C化の参考例

![o_con317.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/15a61664-059f-9b47-fcf0-86e0ffb02dfb.jpeg)




●ライブラリー化

Arduino + 74HC164


https://qiita.com/caa45040/items/07df54303d1ded7048a0


STM32G031 + 74HC164


https://qiita.com/caa45040/items/7ff6fae040cbb862d3c9


STM32L010 + 74HC164


https://qiita.com/caa45040/items/8400069a385cb2fbff8e


●I2C化


つくり方のページ


https://qiita.com/caa45040/items/090e7eed845ddec0543b


STM32G031のライブラリー


https://qiita.com/caa45040/items/24d135efbfab0760ec31


Arduinoの場合


https://qiita.com/caa45040/items/25a203514d4ffa1d886d


STM32L010のライブラリー


https://qiita.com/caa45040/items/34688d1bdf4115aca627
[Laravel-adminを導入しよう！その4] [CentOS Stream8 & Nginx] 無料のSSL証明書「Let's Encrypt」でSSL化する

1. [[Laravel-adminを導入しよう！その1] ConoHa VPSにCentOS Stream8をインストールしVSCodeでSSH接続できるようにする - Qiita](https://qiita.com/yuki-masaki/items/8d8e2f595f26a20cdf80)
2. [[Laravel-adminを導入しよう！その2] CentOS Stream8にNginx、PHPをインストールする - Qiita](https://qiita.com/yuki-masaki/items/4d9c2fb4769512049f03)
3. [[Laravel-adminを導入しよう！その3] CentOS Stream8にLaravel9（PHP8、Nginx、MariaDB）をインストールする - Qiita](https://qiita.com/yuki-masaki/items/fe412f961b5164536c64)
4. [[Laravel-adminを導入しよう！その4] [CentOS Stream8 & Nginx] 無料のSSL証明書「Let's Encrypt」でSSL化する - Qiita](https://qiita.com/yuki-masaki/items/fc1e0d73c49d9afdda7e) ←本記事
5. [[Laravel-adminを導入しよう！その5] Laravel-adminをインストールしSSL化する - Qiita](https://qiita.com/yuki-masaki/items/172bd66f26f9932906e0)

# サーバー構成
OS: CentOS Stream8
Nginx: 1.20.2
PHP: 8.1.5
MariaDB: 10.3.28
Laravel: 9.9.0

# 概要
本シリーズは、VPS上に構築したCentOSに、IT資産管理ツールを構築することを最終目的としています。
IT資産管理ツールのUIは、Laravelの管理画面ライブラリである「Laravel-admin」を使用します。
[前回の記事](https://qiita.com/yuki-masaki/items/fe412f961b5164536c64)では、MariaDBとLaravelのインストールまでしました。
今回は、無料SSL証明書「Let's Encrypt」を使ったHTTPS化の手順説明をします。

# Certbotをインストールする
SSL化をするにあたって下記サイトがとても参考になりました。

https://e-i-te.dev/blog/2021-09-28_centosstream8%E3%81%AEweb%E3%82%B5%E3%83%BC%E3%83%90%E3%81%ABssl%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B/

SSL化するまでの流れ
1. snapdをインストール
2. Certbotをインストール
3. 証明書を発行しNginxに適用

### snapdをインストール

```bash
# root権限でログイン
sudo su

# EPELを一時的に有効にしてsnapdをインストール
dnf --enablerepo=epel install snapd

# サービスの有効化
systemctl enable --now snapd.socket

# 古いsnapとの互換性を保つためシンボリックリンクを設定
ln -s /var/lib/snapd/snap /snap

# インストールできたか確認
snap --version

# ↓こんな結果が表示されればOK
snap    2.55.3-1.el8
snapd   2.55.3-1.el8
series  16
centos  8
kernel  4.18.0-373.el8.x86_64

```

### Cerbotをインストール

```bash
# snap coreのインストールとリフレッシュ
snap install core
snap refresh core

# Cerbotのインストール
snap install --classic certbot

# コマンドのPathを通す
ln -s /snap/bin/certbot /usr/bin/certbot

# インストールできたか確認
certbot --version
```

### Let’s Encryptの発行と適用

事前に、証明書を適用するサーバーのドメインの疎通確認をしておきます。

```bash
# 1. 「dig {申請したいドメイン名}」の形式でコマンドを入力します
dig example.jp

;; ANSWER SECTION:
example.jp.            3600    IN      A       xxx.xxx.xxx.xxx

# 2. ログイン中サーバーのグローバルIPを表示
curl ifconfig.me

xxx.xxx.xxx.xxx # digコマンド結果と同じグローバルIPが表示されていればOK

# 3. 申請したいドメイン名のサイトでHTTP接続ができるか確認
curl -I http://example.com

HTTP/1.1 200 OK # ステータスコードが200番台＝HTTP接続できているのでOK
```

ここまできたら、いよいよ発行と適用をします。
今回はNginxのconfigを自動変更するので、事前にconfigをバックアップしておきます。

```bash
# Nginxのconfigをバックアップ
cp -p /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak

# 証明書の発行と適用を開始（対話型の設定確認が始まります）
certbot --nginx

# 証明書有効期限の通知先メールアドレスを求められるので入力します
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): hogehoge@example.jp
```

利用規約の同意　→　yと入力しEnter
キャンペーン情報を受け取るか　→　nと入力しEnter
申請したいドメイン名の入力　→　ドメイン名の先頭の数字を入力しEnter

以上で、HTTPS化の作業が完了しました。
ブラウザでサイトにアクセスし、HTTPS接続できているか確認しましょう😉

# 参考サイト
[CentOSサーバにCertbotを使ってLet's Encrypt SSL証明書を適用する](https://e-i-te.dev/blog/2021-09-28_centosstream8%E3%81%AEweb%E3%82%B5%E3%83%BC%E3%83%90%E3%81%ABssl%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B/)
畳み込み層について(2022.4.26)

# 背景
畳み込み層は理解しているけど、プログラミングでの動きしか理解しておらず、細かい所までちゃんと見れてないなあと思い、改めて理論も含めておさらいしようと思いました。単純に畳み込み層の部分しか触れません。
畳み込みニューラルネットワーク全体について簡単に知りたい人は[「畳み込みニューラルネットワークについて(2022.6.29)」](https://qiita.com/tan0ry0shiny/items/661989f59f3948eba2a2)をご覧下さい。

# 畳み込み層とは
畳み込み層の機能を考える時、簡単には「入力データ」「カーネル（フィルター）」「出力データ」を考えます。それぞれを見ていきます。
## 入力データ
文字通り入力するデータの事です。今回は$4\times4$のデータを想定します。具体的には以下の様になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/01516b97-cbc6-fe8a-3497-83e6a6e03fa0.png)

## カーネル
入力データに対してフィルター的な役割をします。カーネルを通して出力したデータを可視化したものは特徴マップと言われ、データの一部の特徴を表現しています。どのような特徴かはカーネルに設定されるパラメータ（数字）によって変わります。今回は$3\times3$のカーネルを想定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/0efbb357-c733-4933-6794-d98d7ea2a077.png)

## 出力データ
カーネルを通した後の入力データです。これを可視化したものは特徴マップと言われます。計算は次のように行われます。
1. まず、入力データ(input data)の赤枠部とカーネル(filter)の同じマスを掛けたものを足します。下の図で言うと、赤枠部の同じ色の丸同士を掛け合わせます。具体的には$(1\times2)+(2\times0)+(3\times1)+(0\times0)+(1\times1)+(2\times2)+(3\times1)+(0\times0)+(1\times2)=15$となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/2d25a6f0-7622-9d84-b0da-fa2e563d4ee7.png)


1. 次にカーネルと一つ右にずらします。具体的には以下の赤枠部です。再度、入力データの赤枠部とカーネルの同じマスを掛けたものを足します。$(2\times2)+(3\times0)+(0\times1)+(1\times0)+(2\times1)+(3\times2)+(0\times1)+(1\times0)+(2\times2)=16$となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/27a116c2-1a20-68b2-4666-956791821faa.png)


1. 以下、同じように左下9マス、右下9マスの計算を行います。

# まとめ
基本的にやっている事はこれだけです。画像のデータなどを使うと$256\times256\times3$サイズだったり、畳み込み層が何層もある上に、プーリング層やら活性化関数やら考える必要があり、初学者には大変分かり辛いと思います。今回は思い切ってデータも簡単に、畳み込みの計算だけをやってみました。

# 感想
いろんな本を見ても明確な定義が無く、どう書こうか迷う事が多くあります。その場合は、多くの人が同じようなイメージを持つように自分で定義しています。表現力が乏しく間違った表現になっているかもしれません。また、簡単にし過ぎて違和感がある方も多くいらっしゃると思いますので、ご意見等ありがたく頂戴いたします。遠慮なく編集リクエストなりコメントなりして頂ければ幸いです。

# 参考
[岐阜工業高等専門学校電気情報工学科(2022.4)、畳み込み層の定義](https://www.gifu-nct.ac.jp/elec/deguchi/sotsuron/tgoto/node22.html)

# 関連
モデルサービングとMLOpsを加速するためにCortex LabsがDatabricksにジョイン

[Cortex Labs is Joining Databricks to Accelerate Model Serving and MLOps \- The Databricks Blog](https://databricks.com/blog/2022/04/25/cortex-labs-databricks-model-serving-mlops.html)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

企業のデータプラットフォームへの投資が増加するにつれて、彼らは内部の分析にデータを使うこと以上のことをしたいと考えるようになり、自身の製品やサービスの競合優位性を高めるために、機械学習モデル(ML)による予測とのインテグレーションを開始しています。例えば、[金融サービスはリアルタイムで不正なトランザクションを検知](https://databricks.com/solutions/accelerators/fraud-detection)するためにMLモデルをデプロイしており、[小売業者は顧客ごとのの製品レコメンデーションをパーソナライズ](https://databricks.com/blog/2022/03/03/hyper-personalization-accelerator-for-banks-and-fintechs-using-credit-card-transactions.html)するためにMLモデルを使用しています。

これらミッションクリティカルなアプリケーションでは、低レーテンシーによる秒毎数百万の予測を処理できるようにスケールし、高可用性を提供しつつもプロダクション環境でモデルがどのように動作しているのかをモニタリングできるMLOpsプラットフォームが必要となります。これは、自然言語処理やコンピュータービジョンアプリケーションを支援する計算処理主体のディープラーニングモデルにおいてはさらに大きな課題となります。

DatabricksにおけるモデルサービングとMLOpsを加速するために、ベイエリアをベースとしたMLOpsスタートアップであるCortex LabsがDatabricksにジョインしたことを発表できることを嬉しく思います。Cortex Labsは、プロダクション環境におけるMLモデルのデプロイ、管理、スケーリングを行うための人気のあるオープンソースプラットフォームであるCortexのメーカーです。Cortex Labsは、著名なインフラストラクチャソフトウェア投資家であるPitango Venture Capital、Engineering Capital、Uncorrelated Ventures、at.inc/、Abstraction Capital、エンジェルであるJeremey SchneiderとLior Gavishの支援を受けています。

Cortexを用いることで、エンジニアやデータサイエンティストはDevOpsやクラウドインフラストラクチャを心配することなしに、MLモデルをプロダクション環境にデプロイすることができます。MLワークロードを高信頼、セキュアかつコスト効率高くスケールするために、サイバーセキュリティ、バイオテクノロジー、リテールなど様々な業界でCortexを使用しています。

すでにDatabricksはモデルのデプロイメントに[高度な機能](https://databricks.com/jp/product/machine-learning)を提供しており、今後は、プロダクションにおけるMLワークロードをスケールし、モニタリングするための機能を用いて、このプラットフォームを拡張するためにCortexのチームと取り組むことになります。共同創始者のOmer SpillingerとDavid EliahuをDatabricksチームに迎えられることを嬉しく思います。お客様に機械学習アプリケーションをデリバリーするために企業を支援するエンドツーエンド、マルチクラウドプラットフォームのビジョンの共有を実現するために共に取り組んでいきます。更なるアップデートをご期待ください！

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Lombok の @EqualsAndHashCode の callSuper について

`@EqualsAndHashCode` の `callSuper` には `true` か `false` を指定できます。


# `false` にした場合

デフォルトの挙動で、`java.lang.Object` を直接継承したクラスでは適切です。

他のクラスを継承したクラスで `true` を指定していないと警告が出ます。警告されるのは、`false` が適切なのはスーパークラスに `equals` の判定に使うフィールドが存在しない場合くらいしかないためです。`true` に設定して `callSuper` の機能に頼るか、`super.equals(Object)` を呼び出さなくても良いような実装を頑張って書く必要があります。

`false` が適切な場合がないわけではありません。『Effective Java』(第3版、p. 47) に以下の記述があるのですが、この `Circle` や `Rectangle` でも警告が出ます。このような場合は `false` にしてください。

> 何も値要素を持たない抽象クラス Shape、radius フィールドを追加した Circle サブクラス、length と width フィールドを追加した Rectangle サブクラスを持てます。


# `true` にした場合

`super.equals(Object)` が `false` のときは `false` を返すようにすることで、スーパークラスのフィールドを `equals` の判定で使うようにします。`Object.equals(Object)` を使って構わないなら Lombok に `equals` を生成させるはずがありませんので、正しく処理するためにはスーパークラスで `equals` がオーバーライドされている必要があります。

ちなみに、`java.lang.Object` を直接継承したクラスで指定すると、意味のある処理にならないのでコンパイル エラーになります。


# 参考

https://projectlombok.org/features/EqualsAndHashCode

https://qiita.com/OSKD/items/0890a608a7bff5476b9d
【学習メモ】【小技】ファイルの変更がブラウザに反映されない時に試すこと

開発中、CSSや各種設定ファイルを変更したのに画面に結果が反映されない時がありますよね。
ローカルサーバーの再起動やブラウザの再読み込みをしても変更内容が画面に反映されない時は、ブラウザのキャッシュが悪さをしている可能性があります。

Google Chromeの場合、「**command + shift + r**」でキャッシュを無視したリロードで解決できる時がある（スーパーリロードというらしい。。）

# 環境
| OS | macOS Monterey 12.3.1 |
|:-:|:-:|
|ブラウザ   |Google Chrome   |

# まとめ
開発中、変更内容が画面に内容が反映されないときは
・ローカルサーバーの再起動
・ブラウザの再読み込み
・ブラウザの強制再読み込み（スーパーリロード）
を試してみましょう。

# 参照
https://blog.skeg.jp/archives/2017/10/safari-super-reload.html