OmniAICreator/Qiita-1.07M huggingface dataset:
配列でのセグメンテーションフォルト

# 何があったか
競技プログラミングの勉強でdpのコードを書いていたときに`Segmentation fault: 11`というエラーが出ました。
原因がわからず結構悩んだので記事にしておきたいと思います。
#実行環境
OS: macOS
言語: C++
コンパイラ: g++
#問題が起きたコード
コンパイル時にはエラーにならず、実行時にエラー文が出力されました。

```c++:問題のコード
#include<bits/stdc++.h>
using namespace std;

int main(){
  int n, W;
  int dp[1010][10000];
  int value[1010], weight[1010];
  cin >> n >> W;

  //dp初期値設定
  for(int w = 0; w <= W; i++){
    dp[0][i] = 0;
  }
  //value, weight入力
  for(int i = 0; i < n; i++){
    cin >> weight[i] >> value[i];
  }
  //wまでの最大値
  for(int i = 0; i < n; i++){
    for(int w = 0; w <= W; w++){
      if(w >= weight[i]){
        dp[i+1][w] = max(dp[i][w-weight[i]] + value[i], dp[i][w]);
      }
      else{
        dp[i+1][w] = dp[i][w];
      }
    }
  }
  cout << dp[n][W] << endl;
  return 0;
}

```
今回は、上記のコードを実行したところエラーが出ました。
ちなみにこのコードは[@drken](https://qiita.com/drken)さんの[典型的な DP (動的計画法) のパターンを整理 Part 1 ～ ナップサック DP 編 ～](https://qiita.com/drken/items/a5e6fe22863b7992efdb)を参考にさせていただきました。とても参考になるのでおすすめです。

#セグメンテーションフォルトとは
セグメンテーションフォルトについて少し説明しておきます。
ウィキペディアの[セグメンテーション違反](https://ja.wikipedia.org/wiki/%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%81%95%E5%8F%8D#:~:text=%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%81%95%E5%8F%8D%EF%BC%88%E8%8B%B1%E8%AA%9E%3A%20segmentation%20fault,%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AB)には、
>
セグメンテーション違反（英語: segmentation fault）とは、ソフトウェアの実行時のフォールト状態（あるいはフォールト条件）の一種であり、ソフトウェアがアクセス禁止とされているメモリ上のエリアにアクセスしようとしたり、メモリ上の位置ごとに設定されているルールに違反してメモリにアクセスしようとするときに起こるものである。略してセグフォールト（英: segfault）とも。

とあります。
要するに、アクセスできないメモリの領域に対してアクセスしようとすると、セグメンテーションフォルトが起こります。

#今回のコードでは
C++では、配列を関数内（ローカル変数）で宣言するとスタック領域にデータが入れられ、関数外（グローバル変数）で宣言すると<del>ヒープ領域</del>静的領域にデータが入れられるらしいです。
このため、関数内では大きな配列を宣言してはならないようです（スタック領域はOSに決められたサイズしか確保されないため。）。
先ほど載せたコードでは、関数内で宣言された配列のサイズがスタック領域のサイズより大きかったため、セグメンテーションフォルトが起こったようです。
配列の宣言を関数外で行ったところセグメンテーションフォルトは起きませんでした。
一応、変更後のコードを載せておきます。

```c++:変更後のコード
#include<bits/stdc++.h>
using namespace std;

int n, W;
int dp[1010][10000];
int value[1010], weight[1010];

int main(){
  cin >> n >> W;

  //dp初期値設定
  for(int w = 0; w <= W; i++){
    dp[0][i] = 0;
  }
  //value, weight入力
  for(int i = 0; i < n; i++){
    cin >> weight[i] >> value[i];
  }
  //wまでの最大値
  for(int i = 0; i < n; i++){
    for(int w = 0; w <= W; w++){
      if(w >= weight[i]){
        dp[i+1][w] = max(dp[i][w-weight[i]] + value[i], dp[i][w]);
      }
      else{
        dp[i+1][w] = dp[i][w];
      }
    }
  }
  cout << dp[n][W] << endl;
  return 0;
}

```
関数内でのstatic変数も、グローバル変数と同じように静的領域に入れられるので、以下のように関数内でstatic変数を定義することでも、解決できるようです。
`static int dp[1010][10000];`
#まとめ
今まで何度かセグメンテーションフォルトに悩まされていて、その度に調べていた気がするのでいい機会になったかと思います。
今回の原因を調べる中で、自分のメモリ領域に関する知識不足を感じたので、今後そちらの方についても勉強していきたいと思っています。
Python3で多次元リストを作成するときにハマったこと

#はじめに
今回は、Pythonでプログラムを書いていた際にハマったことについて備忘録的にメモしておきます。
同じようなポイントにハマった方も少なからずいらっしゃるとおもうので、ご参考ください。

#今回やりたかったこと
動的計画法を用いたアルゴリズムを実装する際に、多次元リストを作成する必要がありました。

以下のような感じです。

```
[[[], [], [],[]], 
[[],[],[],[]],
[[],[],[],[]],
[[],[],[],[]],]
```

要は、リストの要素をリストにしたい。

#ハマったポイント
初めに、いつも使うような内包表記で記述しました。

```python
w, h = 3, 4
list_l = [[[]] * w for i in range(h)]
print(list_l) #check

>>>[[[], [], []], [[], [], []], [[], [], []], [[], [], []]]
```

ここからが問題です。

```python
w, h = 3, 4
list_l = [[[]] * w for i in range(h)]
#print(list_l)

for i in range(w):
    list_l[0][i].append(i)
print(list_l)

>>> [[[0, 1, 2], [0, 1, 2], [0, 1, 2]], [[], [], []], [[], [], []], [[], [], []]]
```

for文で１つ目のリストに対して、１つずつ.appendを実行すると、すべてのリストが一括で更新されてしまいます。

###問題点
問題は以下の部分です。

```python
[[]] * w
```
これは、複数のリストを宣言するのではなく、複製していることになっています。なので、そのどれかに要素を追加しようとすると、ほかのリストも同様の操作をされてしまいます。

#解決策
```python
w, h = 3, 4
list_l =[[[] for i in range(w)] for j in range(h)]
#print(list_l)

for i in range(w):
    list_l[0][i].append(i)
print(list_l)

>>>[[[0], [1], [2]], [[], [], []], [[], [], []], [[], [], []]]
```
ECCUBE4 PHP Fatal error:  "Cannot declare class [クラス名], because the name is already in use in ****.php on line 0


## 発生状況
プラグインで管理画面の商品検索Formをカスタマイズしようと
インストールコマンドを叩いたところ、以下のエラーに遭遇しました。

``` php 
#インストールコマンド実行
bin/console eccube:plugin:install --code=AdminProductSearchCustomize

Compile Error: Cannot declare class 
 AdminProductSearchCustomize\Form\Extension\AdminSearchProductTypeExtension, 
because the name is already in use  
      
#キャッシュ削除実行するも変わらず。
bin/console cache:clear --no-warmup

PHP Fatal error:  Cannot declare class AdminProductSearchCustomize\Form\Extension\AdminSearchProductTypeExtension, 
because the name is already in use  in/var/www/*****/app/Plugin/AdminProductSearchCustomize/Form/Extension/AdminSearchProductTypeExtension.php on line 0

```


## namespace の記述が問題でした。
プラグインとして今回は作成するので、namespaceは
正： `Plugin\AdminProductSearchCustomize\Form\Extension;`
誤： `AdminProductSearchCustomize\Form\Extension;`

初歩的なことですが、他のプラグインからコピペしてしまうとあるあるですね💦

ECCUBE4は、Plugin内でController,Entity,Form,Repository,イベントと色々カスタマイズできますが、気をつけて開発したいと思います。


## 参考文献
- [Laravel "Cannot declare class (クラス名), because the name is already in use" のエラーに翻弄されました](https://qiita.com/jonsumisu/items/358384f8021c573ea4fc)
- [ECCUBE4 Compile Error: Cannot declare class … , because the name is already in use](https://umebius.com/eccube/compile-error-cannot-declare-class-name-already-use/)
Lightning Experience のオムニチャネル ⇒ スキルベースのルーティングについて

１．オムニチャネルのスキルベースのルーティングでは、どのようなスキルを持つエージェントに作業項目が割り当てられますか?
２．企業がスキルベースのルーティングの使用を検討する必要があるのはどのような場合ですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/0236a729-46c1-bda9-8c53-94c1f001e9f6.png)
Laminas (旧Zend fremework) MezzioのQuick Start

# レンダラーがTwigのとき, Quick Startが動かない

Quick StartのスケルトンコードがレンララーにTwigを選択したときには動かなかったので色々やってみました。Windows上でPHP7.4がコマンドラインで使えて、かつcomposerが使える環境でやっています。

https://docs.mezzio.dev/mezzio/v3/getting-started/quick-start/

## 設定
適当なフォルダを作って、そこで上記ページにあるcomposerのコマンドを実行します。

```console:command
> composer create-project mezzio/mezzio-skeleton mezzio
```

色々聞かれますが、リターンしていくと、こんな感じになります。


```console:command
  What type of installation would you like?
  [1] Minimal (no default middleware, templates, or assets; configuration only)
  [2] Flat (flat source code structure; default selection)　<<<これ1
  [3] Modular (modular source code structure; recommended)
  Make your selection (2):

  Which container do you want to use for dependency injection?
  [1] Aura.Di (supported by laminas)
  [2] Pimple (supported by laminas)
  [3] laminas-servicemanager (supported by laminas)　<<<これ2
  [4] Auryn
  [5] Symfony DI Container
  [6] PHP-DI
  [7] chubbyphp-container
  Make your selection or type a composer package name and version (laminas-servicemanager (supported by laminas)):

  Which router do you want to use?
  [1] Aura.Router (supported by laminas)
  [2] FastRoute (supported by laminas)　<<<これ3
  [3] laminas-router (supported by laminas)
  Make your selection or type a composer package name and version (FastRoute (supported by laminas)):

  Which template engine do you want to use?
  [1] Plates (supported by laminas)
  [2] Twig (supported by laminas)
  [3] laminas-view installs laminas-servicemanager (supported by laminas)
  [n] None of the above　　<<<これ4
  Make your selection or type a composer package name and version (n):

  Which error handler do you want to use during development?
  [1] Whoops (supported by laminas)　　<<<これ5
  [n] None of the above
  Make your selection or type a composer package name and version (Whoops (supported by laminas)):

  Please select which config file you wish to inject 'Laminas\Validator\ConfigProvider' into:
  [0] Do not inject
  [1] config/config.php　　<<<これ6
  Make your selection (default is 1):

  Remember this option for other packages of the same type? (Y/n)
```

その後mezzioディレクトリに入って

```console:command
> composer run --timeout=86400 serve
```

を実行してプラウザでlocalhost:8080にアクセスすると・・・

![レンダリングできないYo!](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/317b0b84-3aad-d349-460f-ac51057a5647.png)


あれま。。。

## 修正
デフォルトではレンダラーがないのでTwigを追加してみます。

```console:command
> composer require mezzio/mezzio-twigrenderer
```

すると今度は様子が変わる。

![ディレクトリがないYo!](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/e8113397-e12a-db5e-991c-dad09bee02ce.png)


テンプレートディレクトリがないとのことなので、プロジェクトディレクトリの直下に
templates/app
templates/layout
templates/error
を作成し、appの下に
home-page.html.twig
というファイルをおきます。中身は"It Works!"とかでいいです。

## オプションについて
「これ4」のところで[3]のlaminas-viewを選んでやると、きちんと出力されました。

![見た目よし](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/e54a938a-42a3-c84b-dd34-545e1245b4e0.png)
npm runでコマンドを実行する場合と直接コマンドを実行する場合の違い【初心者向け】

#typescriptをインストールして比べてみる

##ターミナルで実行する場合（グローバルインストール）
適当にnpmプロジェクトを作成します。

```shell:
mkdir npm_project
cd npm_project
npm init
```

ここで、typescriptをグローバルインストールします。

```shell:
npm install -g typescript
which tsc
/mnt/c/Program Files (x86)/Nodist/bin/tsc
```
とコマンドを打つと、パスが通っていればグローバルインストールしたtscへのパスが表示されます。(WSL環境のパスです）

##npm run で実行する場合（ローカルインストール）
```shell:~/npm_project
npm install typescript
```

package.jsonのscriptを編集します。

```json:package.json
"scripts": {
    "tsc": "which tsc"
  }
```
npm runでコマンドを実行します

```shell:~/npm_project
npm run tsc
/mnt/c/Users/mano-syou/Desktop/npm_project/node_modules/.bin/tsc
```
プロジェクト配下のnode_modules内にローカルインストールしたtscへのパスが表示されます。
Google Slidesでベクター画像を使いたい

## TL;DR

- emf形式でベクター図をGoogleDriveに保存
- Google図形描画で開く
- GoogleSlidesにコピペ

## やっぱり色も変えたいし、図はきれいな方がいい

論文書く時はInkscapeでポンチ絵などを作ってpdf出力しているのですが、それをスライドに使おうとするとGoogleSlidesはpngかjpegのみ対応でした。
色々な方の話を聞くと、Powerpointのデフォルトアイコンだけで頑張っている方、イラレでスライド全部作ってしまう方、png化して埋め込む方等色々でした。

ただ、個人的な好みの問題で日常的に使うツールはできる限りOSSかフリーのツールを使っていきたいと考えてて、良い方法がないか探してました。しばらくこの方法でスライド作成はやっていこうと思ってます。他に良い方法模索中。

## 注意点
自分のInkspace等への理解不足が原因だと思うのですが、点線が普通の直線になってGoogle図形描画に読み込まれました。
対策などご存知の方がいたらコメントで教えていただけるとありがたいです。
カスタムボタンで外部URLを呼ぶ時にIF関数を使う

簡単だと思った質問です。

通常だと URLのところにハードコーディングすれば問題ない。
どうも https://が先頭にあれば、①そのまま外部URLに飛びます。

問題はここにある。https://がないと②今のURLの後ろにここで設定したURLを連結する仕様みたい。
（いろいろ試した結果でそう判断しています。）

以上のことを前提に考えてみます。
まず質問者さんは以下のように設定したそうです。
そうすると、②が発動。外部のサイトに飛びません

```
If(CONTAINS($Api.Enterprise_Server_URL_490, "--dev"), "devlogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--qa"), "qalogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--training"), "traininglogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--uat"), "uatlogin.company.com/users/"+FederationIdentifier__c,
"login.company.com/users/"+FederationIdentifier__c))))
```

そこで私は以下を提案。でもこれだとカスタムボタンの数式チェックはOKなのですが
Error: Function URLFOR may not be used in this type of formula
となって、保存できない。

```
If(CONTAINS($Api.Enterprise_Server_URL_490, "--dev"), "https://devlogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--qa"), "https://qalogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--training"), "https://traininglogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--uat"), "https://uatlogin.company.com/users/"+FederationIdentifier__c,
"https://login.company.com/users/"+FederationIdentifier__c))))
```

そこで、私はてっきりカスタムボタンの式のころにこれを書いていたと思っていたのですが、初めのうちは数式フィールドにこれを書いて
その数式フィールドのAPI名を指定していたようです。数式フィールド経由でなく直接書いたら、こんなエラーになりました。


そこでError: Function URLFOR may not be used in this type of formulaを回避するために
数式フィールド経由させますが、そのまま経由しても②の状態になるので、もしかしたらと思い
URLFORを使ってみると、なんとうまく行きました。


#結果
まず、数式フィールドを作ります。
external_url__c

```
If(CONTAINS($Api.Enterprise_Server_URL_490, "--dev"), "https://devlogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--qa"), "https://qalogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--training"), "https://traininglogin.company.com/users/"+FederationIdentifier__c,
If(CONTAINS($Api.Enterprise_Server_URL_490, "--uat"), "https://uatlogin.company.com/users/"+FederationIdentifier__c,
"https://login.company.com/users/"+FederationIdentifier__c))))
```

上記の数式フィールドをカスタムボタンで呼び出します。


```
{!URLFOR(your_object_api_name.external_url__c)}
```

２時間ほど悩みました... 何故かベストアンサーはもらえませんでしたがね。まぁ、１つ賢くなったな。

https://trailblazers.salesforce.com/answers?id=9064S000000kIG7
【C#】ErrorLog 出力時に Exception の内容が消失していた話

# はじめに
とある秘密プロジェクト X で作成したバッチを実行してエラーログを出力した際、例外の内容が消失した事件が発生しました。例外の内容はどこにいったのか … その謎を解き明かしていきます。
# 対象のコード
```
catch (Exception ex)
{
  _logger.LogError("ここにメッセージが入っていたよ", ex);
}
```
# 結論
_logger.LogError の使い方が間違っていました。解き明かすプロセスを楽しみにしていた人はごめんなさい。単純だったので解き明かすプロセスの話が思い浮かばなかったのです。許してください。さて、正しい使い方はこうです。

```
catch (Exception ex)
{
  _logger.LogError("ここにメッセージが入っていたよ {ex}", ex);
}
```
引数に指定した ex を string 引数の方で指定してあげなくては出力されなかったのです。ex からしてみると休日上司に呼び出しをくらって会社に出社したときに「呼び出した理由？ん～、何だっけ、忘れちゃった。」と言われたようなものです。私だったら顔には出しませんが、内心発狂しています。ちなみに例外を先に持ってきて以下のように書いても例外は出力されます。

```
catch (Exception ex)
{
  _logger.LogError(ex ,"ここにメッセージが入っていたよ" );
}
```
というわけでログの出力時に渡す引数の順番や引数の内容に気をつけましょうという話でした。
# 参考
https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.extensions.logging.loggerextensions.logerror?view=dotnet-plat-ext-5.0#Microsoft_Extensions_Logging_LoggerExtensions_LogError_Microsoft_Extensions_Logging_ILogger_System_String_System_Object___
【Lambda＋RDS Proxy】RDS Proxy利用時に'?'などのパラメータを用いているSQLである「プリペアドステートメント」を使った場合、ピン留めが発生して悪影響が出た


公式ページに出てる中で、躓いたところです。「公式をよく読め」という話ですが、失敗例の一つとして掲載します。

# 読もう！　RDS Proxyでのピン留め！

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html

```
場合によっては、RDS Proxy は、現在のセッションの外でデータベース接続を再利用しても安全であると判断できません。このような場合、セッションが終了するまで、セッションは同じ接続で維持されます。このフォールバック動作は、ピン留めと呼ばれます。
```

```
ステートメントのテキストサイズが 16 KB を超える場合、プロキシはセッションをピン留めします。

プリペアドステートメントの場合、プロキシはセッションをピン留めします。このルールは、プリペアドステートメントで SQL テキストを使用するか、バイナリプロトコルを使用するかに関係なく、適用されます。

明示的な MySQL ステートメントである LOCK TABLE、LOCK TABLES、または FLUSH TABLES WITH READ LOCK が原因でプロキシによるセッションのピン留めが発生します。

ユーザー変数またはシステム変数 (例外あり) を設定した場合、プロキシはセッションをピン留めします。この状況によって接続の再利用が制限されすぎる場合は、SET オペレーションでピン留めを発生させないように選択できます。SessionPinningFilters プロパティを設定する方法については、「RDS Proxy の作成」を参照してください。

一時テーブルを作成した場合、プロキシはセッションをピン留めします。これにより、トランザクションの境界に関係なく、一時テーブルの内容がセッション全体で保持されます。

MySQL 関数 ROW_COUNT、FOUND_ROWS、および LAST_INSERT_ID を呼び出すと、ピン留めが発生する場合があります。

これらの関数によりピン留めが発生する正確な状況は、MySQL 5.6 および MySQL 5.7 と互換性のある Aurora MySQL バージョン間で異なる場合があります。
```


# 実際に起きた障害

Lambda＋RDS Proxyを試してみて、実際に上手く行ったのでそのまま少人数で利用してみた。
ただある期間からたまーにDB接続失敗が出現することがあった。

報告を受けてRDSを確認してみるとdbconnectionが一定数のまま、CPU使用率が跳ね上がったまま維持されている。
ログを見ると

```
The client session was pinned to the database connection 
for the remainder of the session. The proxy can't reuse this connection until the session ends. 
Reason: A protocol-level prepared statement was detected.
```

といった警告とともにセッションがピン留め？され、connectionがずっと続いていることが分かった。

# 原因

RDS Proxyによるピン留めが発生し、connectionの肥大化によってDBの許容量オーバーを起こしていた。

```
プリペアドステートメントの場合、プロキシはセッションをピン留めします。このルールは、プリペアドステートメントで SQL テキストを使用するか、バイナリプロトコルを使用するかに関係なく、適用されます。
```

プリペアドステートメントを使用していたのが原因。

https://docs.oracle.com/javase/jp/8/docs/api/java/sql/PreparedStatement.html

```
パラメータ設定の例を次に示します。conはアクティブな接続を表します。

   PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                                     SET SALARY = ? WHERE ID = ?");
   pstmt.setBigDecimal(1, 153833.00)
   pstmt.setInt(2, 110592)
```

プリペアドステートメントの分かりやすい例だと上記のようなSQLと考えられる。 `?`の箇所にパラメータを設定して実行できるような、プリコンパイルSQLという認識。
Sequelizeを利用しており、Raw Queriesによるprepare SQLを利用していたので、ソレが原因と考えられる。

https://sequelize.org/master/manual/raw-queries.html



# 解決法

RDS Proxyを利用せず、単純にRDSへの直接接続にした。少人数運用であるため、RDS Proxyの恩恵が単純に感じられなかったのもある。


# 終わりに

PrismaというORMの場合、以下のように明記されている。

https://www.prisma.io/docs/guides/deployment/deployment-guides/caveats-when-deploying-to-aws-platforms

```
PrismaはAWSRDSプロキシと互換性があります。ただし、RDSプロキシが接続を固定する方法が原因で、Prismaとの接続プーリングに使用するメリットはありません。

Prismaはすべてのクエリにプリペアドステートメントを使用するため、PrismaでRDSプロキシを使用してもメリットはありません。
```

RDS Proxyの可用性は各所で検証されている。だが「公式ドキュメントに書かれているようなことを良く読まなかったことによるアンチパターン」と思しきこともある。

* AWS公式ドキュメントをよく読む
* 今回のような「プリペアドステートメントを利用することがピン留め発生の原因となり、悪影響となる」といった場合、
  それらをもととして環境構築および利用ライブラリ、実装手法などを見直す必要が出てくると考えられる。
【tweepy】ツイート結果(TweepError)の取得

## はじめに
　tweepyのupdate_status()やupdate_with_media()でツイートしたときに，エラーならエラーと表示されるが成功したときに何も出ないので，成功したら成功したと表示させたい。

## 実装
　エラーのステータスはtweepy.TweepError.reasonに入ってるらしい。

```python
try:
    api.update_status(tweet)
except tweepy.TweepError as e:
    print(e.reason)
```
って感じにすると

```python
[{'code': 187, 'message': 'Status is a duplicate.'}]
```
って返ってくるからキーを指定すればcodeだけ取り出せそうだけどどうやらこれ丸ごとstringらしいので，エラー文をそのまま条件に使用して下のような感じで実装(するのが手っ取り早そう)。
　エラーになる要因はたいていAPIのリクエスト制限に引っかかるか重複したツイートしてるか(テスト投稿でやっちゃいがち)だと思うのでその二つは表示できるようにしてそれ以外のエラーはそのままって感じで。

```python
try:
    api.update_status(self.tweet)
except tweepy.TweepError as e:
    if e.reason == "[{'code': 88, 'message': 'Rate limit exceeded'}]":
        print("エラー；リクエスト上限に達しました。15分間待ってください")
    if e.reason == "[{'code': 187, 'message': 'Status is a duplicate.'}]":
        print("エラー：ツイートが重複しています")
    else:
        print(e)
else:
    print("ツイート成功")
```

tkinterでGUIにする場合は`print`部分をtk.Labelの`textveriable=`に使用してる`tk.StringVar()`に`.set`するよう置き換えればOK
postGisでのよく使うQueryのメモ

## やりたいこと
- 緯度経度情報(POINT)から、そのポイントの情報を取得
- 範囲を指定すると、その範囲内にあるポイントを取得

## 環境・条件
### 環境
- macOS Big Sur 11.2.3
- psql (PostgreSQL) 13.3
- postGis 3.1.2


## 1.緯度経度情報(POINT)から、そのポイントの情報を取得
### 使用例
緯度経度情報から、そのポイントの県や市区町村名を取得する場合

### 条件
- POLYGONのGeography型データを持つテーブルが登録済み(データの取得は扱わない)


```sql
SELECT * FROM table_name
WHERE ST_Covers(
    geog, 
    ST_GeogFromText('POINT(lon lat)')
)
ORDER BY column_name desc;
```
## 2．範囲を指定すると、その範囲内にあるポイントを取得
### 使用例
表示中の地図範囲に存在する建物(病院とか学校とか)の一覧を取得する場合

### 条件
- POINTのGeography型データを持つテーブルが登録済み(データの取得は扱わない)

```sql
SELECT * FROM table_name
WHERE ST_Covers(
    ST_GeogFromText('
        POLYGON(
            (lon0 lat0, lon1 lat1, lon1 lat1, lon1 lat1, lon0 lat0)
        )
    '),
    geog
);
```
Adobe Portfolioで独自ドメインのサブドメインが使いたい

この記事は、自分の写真blogからの加筆転載です。

https://web-kosaku.com/photo/2021/05/23/adobe-portfolio%e3%82%b5%e3%83%96%e3%83%89%e3%83%a1%e3%82%a4%e3%83%b3%e3%81%ae%e8%a8%ad%e5%ae%9a/

#Adobe Portfolioは、adobeCC系を使っていると、基本無料で使えるサービス。（のはず）
ドメインを個人的に持っていない場合は、個人で決めたサブドメイン＋Adobeが決めたドメイン（例：nfactory.myportfolio.com）が利用可能。

###じゃ、独自ドメインで運用できないの？
勿論可能です。方法としては、Aレコードに設定を追加。前提として、Aレコードが操作できるドメイン契約であること。詳しくは、Adobeの公式ドキュメントを確認してみてください。
<font color=silver> ※ブルジョアジーな方は、Adobeのドメイン案内から購入すると、簡単に設定できます。</font>

###サブドメイン運用の記述がない
ここで疑問が。公式ドキュメントを確認しても、サブドメイン運用の記載が無い。どういうことかというと、example.comとwww.example.comを全て、Adobe Portfolioに転送するということが前提になっているようです。

もちろん、それで問題無い人は、全く問題無いのですが、<font color=Red>サブドメインでも運用したい人は多いはず。</font>（そう思いたい）
そこで、インターネットを検索するとサブドメイン運用の設定方法も懇切丁寧に書いてあるのですが、1点だけ陥りやすいのが、Adobeのカスタムドメイン指定画面では、~~example.com~~では無く、利用したいサブドメインを、例えば、pfにしたい場合は、<font color=Green>**pf.example.com**</font>を指定することです。Aレコードの指定は、pfとwww.pfに対して設定します。

    ☆設定の一例
    カスタムドメイン：pf.example.com
    Aレコードの@：pf
    Aレコードのwww：www.pf

意外とうかっとしてると、ついつい、example.comを指定しがちです。僕も、カスタムドメインの指定を勘違いしていた一人です。

#ここからはある意味愚痴？#
WordPressも写真については、いろいろ出来るのですが、同じ写真を何回もアップロードするのも、それなりに手間なので、一カ所にまとめようというのが、今回の事の起こり。以前のブログでも、同じ形を取っていたので、元に戻ったのかな。あと、単純に、Portfolioのデザインがかなり写真向けに洗練されていることです（時々表示が遅いときがあるのが残念と言えば残念ですが）。WPのテーマを1から作るには、面倒ですし、似たようなテーマも見つからず、じゃ、Aレコードで行こうぜって話です。

#ご注意#
最後に、大事なことですが今回の設定は、ブログエントリー時点での結果です。加えて、Adobe社の公式の見解でも方法でもありません。参考にして設定された場合、当方では一切の責任を担保することは出来ませんので、よろしくお願いします。
oracleのjdbcドライバを含むmetabase docker imageの作成

version v0.39.3

まず、以下のようなディレクトリにDockerfileとoracleのjdbcドライバを配置した、とする。

```
Dockerfile
plugins
+-ojdbc8.jar
```

Dockerfileで、jdbcドライバをmetabaseのプラグインディレクトリ```/plugins```にコピーする。なお、このプラグインディレクトリはversionによって異なる（ぐぐってると異なる記述がある）なので注意が必要。

また、777にする。これはmetabase起動時に書き込み処理があるため。

```Dockerfile
FROM metabase/metabase:latest

COPY plugins/ojdbc8 /plugins/ojdbc8
RUN chmod -R 777 /plugins
```

以下は動作確認用のビルドと起動コマンド。

```
docker build -t metabase-oracle .  
```

```
docker run -d -p 3000:3000 --name metaoracle metabase-oracle
```

参考 https://cirovladimir.wordpress.com/2019/05/10/running-metabase-on-docker-and-connecting-it-to-oracle-database/
Kintone JavaScript APIの使い方をさっくり把握

仕事でKintoneを扱うことになったので、勉強中です。

とりあえずサクッと概要を把握するために書きました。

## Kintone JavaScript APIとは
Kintone内で任意のJavaScriptコードを実行できるらしい。

Kintoneのイベントをトリガーに処理実行することも可能。

私はレコードが追加されたらSlack通知する処理を作ってみようとか思ってます。

## コーディングガイドライン
[Kintone JavaScript　コーディングガイドライン](https://developer.cybozu.io/hc/ja/articles/201793484)

## 作ったJSファイルをKintoneにインポート

1. Kintoneのシステム管理画面を開く（多分権限必要）
2. [JavaScript / CSSでカスタマイズ]を選択
3. 適用範囲を選択
JSの適用範囲を指定する。  
とりあえず最初はテストのため「kintoneのシステム管理者だけに適用」にしましょうとのこと。  
※何を選択してもゲストユーザには適用されないらしい
4. アップロード欄からアップロードする
5. 保存押下  
↓↓↓↓↓保存ボタンは左上にありました↓↓↓↓↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430401/7aa777a3-2b3c-912c-1c07-a3e15b76d0b2.png)

これでアップロード完了。
イベントじゃない系のスクリプトだと画面操作したときに実行されてました。
MySQL select句の表示条件に括弧を付ける

# 目的

- select句を用いてレコードの情報を出力する際の条件に括弧を付ける方法をメモ的にまとめる

# 困り事

- 下記のようなSQLを記載して実行したが思うような結果が得られなかった。

    ```sql
    select * from users 
    where admin_flag = 1
    and test_user_flag = 1
    or master_user_flag = 1;
    ```

- 上記のSQLを記載したときは下記の条件のレコード情報を取得したかった。
    - usersテーブルのadmin_flagカラムの値が1、かつ test_user_flagカラムの値が1か、master_user_flagが1のレコード情報

# 方法

- 下記のように記載することで欲しい情報が取得できた。

    ```sql
    select * from users 
    where admin_flag = 1
    and (test_user_flag = 1 or master_user_flag = 1);
    ```

- test_user_flagが1かmaster_user_flagが1のレコードがほしいので当該条件部分を括弧でくくった。
TextPad Editor　に関するメモ

#TextPad Editor ８　に関するメモ

Windows環境で好んで使用しているエディタではあるが
どうにも　製品の日本語ヘルプの内容が古いまま更新されていない箇所があるので
ここにメモを残しておく

・環境設定内容の記録／復元方法

　環境設定でカスタマイズした内容は、Ver8　では下記フォルダに記録されている
　C:¥Users¥[ user ]￥AppData￥Roaming￥Helios￥TextPad￥8￥

　[ user ]　・・・　ログインユーザー名

　※　新しいPCで設定を復元するのはかなり大変なので（表示色、フォント、
　　　キーボード設定等）、このフォルダのファイルをコピーするだけで
　　　復元できるのは本当にありがたい。
Unityのゲームをリリースする

**※自分用メモ**

# iOSリリース手順
- https://learn.unity.com/tutorial/publishing-for-ios
- Xcodeのアップロードが完了してからApp Store Connectに反映するまで、12時間くらいかかった経験がある
- ゲームの内容がつまらなすぎて、リジェクトされたことがある

# Application's Icon
- App icon Generator
    - https://appicon.co/
    - 1024x1024 の画像を用意する

# Privacy Policy
- Game Privacy Policy Generator
    - https://letsmakeagame.net/game-privacy-policy-generator/
- FirebaseHosting
    - https://firebase.google.com/docs/hosting/quickstart
GitLab に SSH 鍵を登録して git 操作を楽にする全手順

#概要
HTTP接続でのgit操作は毎回パスワード聞かれたりして煩わしいため、ssh鍵をGitLabに登録して操作を楽にしたい。
そのための備忘録。

PCで、SSH鍵を生成（公開鍵/秘密鍵）→ 公開鍵をGitLabに登録
という手順で行う。

#前提

- GitLab にアカウント作成済み
- PC に Git を導入済み
- GitLab（クラウド版）
- OS: MacOSX 10.14.6
- ターミナルツールが使用可能
  - cat コマンド使用可能
  - ssh-keygen コマンドが使用可能

※今回の手順はWindowsOSでも多分、ほぼ同様に作業可能

#手順

### SSH鍵の生成
ターミナルツールを開き、SSH鍵を生成する前に隠しフォルダへ移動

```bash
cd ~/.ssh
```

公開鍵と秘密鍵を生成

```bash
# t: 鍵タイプ, f: 任意のファイル名
$ ssh-keygen -t rsa -f gitlab_rsa

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):   // パスワード不要ならそのまま Enter キー押下
Enter same passphrase again:
Your identification has been saved in gitlab_rsa.
Your public key has been saved in gitlab_rsa.pub.
The key fingerprint is:
SHA256:XZhiuvhCcZYuHYK7loKtNUGZY0+KfY3VHuXWiuAF6tE
The key's randomart image is:
+---[RSA 2048]----+
|..  .  o.        |
// 省略
|     ..          |
+----[SHA256]-----+
```

すると、.ssh ディレクトリ内に以下のファイルが生成される

- gitlab_rsa （秘密鍵）
- gitlab_rsa.pub （公開鍵）

### 公開鍵を GitLab に登録

作成した公開鍵の中身を見る

```bash
# cat コマンドで確認
$ cat gitlab_rsa.pub

# 実行結果
ssh-rsa ABCDB3NzaC1yc2EABCD...（中略）...RGv0PPQeKfefkqFST7gpr user@users-mac.local
```

実行結果の中身をコピーし、GitLab の以下の画面でペーストする
（GitLabログイン後、右上のユーザーアイコン →「Edit profile」で画面遷移し、左メニューから「SSH 鍵」を選択）

![GitLab SSH登録.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557654/23a9c501-0453-7ca5-c83a-04016a8fa7a8.png)

以上で完了。

これで、git クローン時に、HTTP指定ではなく `git clone git@gitlab:/test.git` などという指定ができるようになる。

※この設定は、マシンごとに必要です。
【Google Cloud Day '21】「オンライン業務効率化に向けた Google Meet の新しい可能性」を視聴して

otterは英語書き起こしサービス。話者を自動認識し、その後ラベル付けしてくれる
運営会社の社長は元々Googleの人だった
みらい翻訳は、ドキュメントの翻訳をしてくれる。otterで英語を自動書き起こししてデータをダウンロードして、みらい翻訳で日本語に翻訳できる。
年間33000円。日本円。ビジネスプランのみ

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/28f9cf25-24d3-0bc7-98fc-5fc802c59b7c.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/08f80e34-d1c0-32ad-6b90-f09f0b2a5777.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/3bde0cb3-861e-6b9a-d584-76c7bdf9597c.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/fc8f85c8-62bd-d134-3c70-df0991da4d8c.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/5a00b498-d33d-ef19-89aa-39c0444e40ac.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/60357fe7-b5df-0fe8-49a9-0f63c1d049f5.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/b5bf2805-0ca6-a5de-dfaf-3ccef4890eae.png)
MLflowにてautologを無効にする方法

## 概要
MLflowにてautologを一度有効にすると他のRUNでも有効となってしまうため、disableという引数で停止する方法を共有します。

本記事ではscikit-learnでの実施方法を紹介しますが、他のライブラリも同様の引数のようです。詳細は、ドキュメントにてご確認ください。

[Python API — MLflow 1.17.0 documentation](https://www.mlflow.org/docs/latest/python_api/index.html)

## 手順
### 1. Autologを有効にしてMLモデルを作成
```python
import numpy as np
from sklearn.linear_model import LogisticRegression

import mlflow
import mlflow.sklearn


# Autologの有効化
mlflow.sklearn.autolog()

# データ準備
X = np.array([-2, -1, 0, 1, 2, 1]).reshape(-1, 1)
y = np.array([0, 0, 1, 1, 1, 0])


# MLflowにおけるRUNの実行
with mlflow.start_run(run_name="autolog ON") as run:
  lr = LogisticRegression()
  lr.fit(X, y)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/53fc86b4-665f-a546-9759-f04112a5ccd6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/8b487f86-566d-1a9b-7ee8-730cf3fbcf42.png)

### 2. Autologを無効化
```python
# Autologの無効化
mlflow.sklearn.autolog(disable=True)
```

### 3. 再度MLモデルを作成してログが残ってないことを確認
```python
import numpy as np
from sklearn.linear_model import LogisticRegression

import mlflow
import mlflow.sklearn


# データ準備
X = np.array([-2, -1, 0, 1, 2, 1]).reshape(-1, 1)
y = np.array([0, 0, 1, 1, 1, 0])

# MLflowにおけるRUNの実行
with mlflow.start_run(run_name="autolog OFF") as run:
  lr = LogisticRegression()
  lr.fit(X, y)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0e911edd-1052-80d6-c242-10fb65b48127.png)
やったこと

<h2>利用ツール</h2>
JUnit5,pgAdmin4,Selenium,Selenide,Git,Github,Redmine,Maven,Eclipse(STS),Jmeter,PICT

<h2>ミドルウェア</h2>
PostgreSQL11,Tomcat8

<h2>開発言語/フレームワーク</h2>
Java8(SpringBoot),HTML,CSS,SQL,JavaScript,コマンドスクリプト,Thymeleaf,Ajax,jQuery
Gitコマンド　メモ

#コミット直後に戻る
###addもcommitもしていない場合

```
git checkout .
``` 

これで、コミットした後に試行錯誤で試しながらコードを書いていたけど、やっぱなんもなかったことにしたい時に
使える

###commitしたけど、前回のコミットに戻りたい

```
git reset --hard HEAD^
```

これは、コミットした後に別の処理を書いて、それもコミットした。だけどやっぱりこのコミットしたの必要なかったわってなった時に使える
M1 Mac でmysqlインストールのエラー ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries

M1 Macでdocker-composeをするときにmysqlのインストールに失敗するとき。

```
Status: Downloaded newer image for nginx:latest
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries
```

このようなエラーが出る。
ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries
デフォルトでlinux/arm64/v8のmysqlを探しに行って見つからずにエラーを吐いているようだ。


###対処法
docker-compose.ymlにplatformを指定して再度docker-composeをする。

```
  db:
    image: mysql:5.7
    platform: linux/x86_64
```
platform: linux/x86_64または
platform: linux/amd64
をDBの箇所に指定してあげればエラー無くインストールが完了する。
strapiの自作プラグインのアイコンを変更する方法

# はじめに

strapiのプラグインのメニューアイコンを変更する方法です。

# 動作環境

Mac: MacBookPro macOS Big Sur 11.3.1
node: v12.18.3
yarn: 1.22.10
Strapi v3.6.2

# 自作プラグインの追加

現象を再現するために新規にプロジェクトを作成します。

``` terminal
$ yarn create strapi-app my-project --quickstart
```


適当にadminユーザーを作成してログインします。

以下のコマンドからプラグインを追加します。

``` terminal
cd my-project/
yarn strapi generate:plugin qiitaPlugin
```

adminモードでもう一度起動します。(デフォルトで８０００ポートで起動します。)

```
yarn develop --watch-admin
```

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/06924254-3c91-56c0-47dc-2fb076b7bea7.png)


# アイコンの変更

アイコンを変更したい場合は、プラグインのディレクトリの`package.json`のiconの部分を変更します。
`プロジェクト/plugin/プラグイン名/package.json`


``` package.json
{
  "name": "strapi-plugin-{プラグイン名}",
  "version": "0.0.0",
  "description": "This is the description of the plugin.",
  "strapi": {
    "name": "{プラグイン名}",
    "icon": "plug", <- ここを変更
    "description": "Description of *** plugin."
  },
  "dependencies": {
    "@buffetjs/core": "^3.3.6",
    "@material-ui/core": "^4.11.4",
    "@material-ui/icons": "^4.11.2",
    "styled-components": "^5.3.0"
  },
  "author": {
    "name": "A Strapi developer",
    "email": "",
    "url": ""
  },
  "maintainers": [
    {
      "name": "A Strapi developer",
      "email": "",
      "url": ""
    }
  ],
  "engines": {
    "node": ">=10.16.0 <=14.x.x",
    "npm": ">=6.0.0"
  },
  "license": "MIT"
}
```

デフォルトでは`plug`となっており、選択肢は、[github](https://github.com/strapi/strapi/blob/86e0cf0f55d58e714a67cf4daee2e59e39974dd9/packages/strapi-plugin-content-type-builder/admin/src/containers/App/utils/icons.json)上で確認することができます。

おそらくですが、`FontAwesome`から流用していると思われますが、[公式サイト](https://fontawesome.com/v5.15/icons?d=gallery&p=10)から利用したいアイコンを探すと良いと思います.

例えば、歯車アイコンの`cogs`に変更すると以下のようになります。

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/bddc3a58-a2aa-d4bb-6bf0-82f6880c6352.png)
AtCoder Beginner Contest 204 備忘録

https://atcoder.jp/contests/abc204

当日未参加
A：AC
B：AC
C：回答見ながら
D：
E：
F：

A - Rock-paper-scissors
https://atcoder.jp/contests/abc204/tasks/abc204_a
じゃんけんであいこになる手を出力させるやつ。
当然ながら全部同じの時と全部違うときの2通り。
全部違うときは全部足したら3になるようにすればよい。

```php
#include <stdio.h>
#include <bits/stdc++.h>
#include <math.h>
#include <iostream>
using namespace std;

int main(void){
    int x,y,z;
    cin>>x>>y;
    if(x==y){
        z=x;
    }
    else{
        z=3-x-y;
    }
    cout<<z<<endl;
}
```
B - Nuts
https://atcoder.jp/contests/abc204/tasks/abc204_b
10以上の時は10個残して木の実をとる、というのをそのまま実装するだけ。

```php
#include <stdio.h>
#include <bits/stdc++.h>
#include <math.h>
#include <iostream>
using namespace std;

int main(void){
    int N;
    int A[1100];
    cin>>N;
    long long ans=0;
    for(int i=0;i<N;i++){
        cin>>A[i];
        if(A[i]>10){
            ans=ans+A[i]-10;
        }
    }
    cout<<ans<<endl;
}
```

C - Tour
https://atcoder.jp/contests/abc204/tasks/abc204_c
動的計画法の幅優先探索を用いる問題。

[グラフ入力]
・動的配列 ```vector<vector<int>>```で、各点から訪問できるところを入力する。

[探索]
・探索待ち配列（q:queue配列）と訪問済み配列(vis：set配列)を用意する。
・ある点をスタート地点として選ぶ
・スタート地点を探索待ち、訪問済み配列に入力する。
・探索待ち配列から探索待ちの値を取り出す。
・探索待ち配列から取り出した値を消す。
　　※最初に入力した値を取出し、消去するのがが幅優先探索、
      最後に入力した値を取り出すのが深さ優先探索
・探索待ちから取り出した値から、訪問できるところを先の動的配列から取り出す。
・取り出した訪問できるところが、訪問済みかどうかを判定
・未訪問の場合は、探索待ちに追加、訪問済みに追加する
・探索待ちに追加されたものがある場合は、```While```で探索待ちがなくなるまで繰り返す
※訪問できるところがなくなったら探索待ちに追加されなくなるので終了する。
・いくつ訪問できたかを出力し、ansに加算する。
・次の地点をスタート地点にして、再度上記探索を繰り返す。

この流れがいわゆる幅優先探索。
これは知識として知らないとまず実装できない類。
とにかく数こなして慣れていくしかないタイプのやつ。

```php
#include <bits/stdc++.h>
#include <math.h>
using namespace std;

int main(){
	int N,M;
	cin >> N >> M;
    vector<vector<int>>G(3000);//グラフ用

	for(int i=0;i<M;i++){//グラフ入力
		int a,b;
		cin >> a >> b;  
		G[a].push_back(b);
	}
    int ans=0;
    for(int i=1;i<=N;i++){//スタート地点を全探索
        queue<int>q;//探索待ち用
        set<int>vis;//訪問した記録用
        q.push(i);//まずスタート地点をキューに入れる
        vis.insert(i);//スタート地点を訪問済みに入れる

    while(q.empty()==0){//探索待ちになんかある限りループ
        int A =q.front();//探索待ちの先頭を取り出す
        q.pop();//キューの先頭を消す
        for(auto j:G[A]){//Aからいけるところを全出力する
            if(vis.count(j)==0){//未訪問の場合だけ。
                q.push(j);//探索待ちに追加
                vis.insert(j);//訪問済みに追加
            }
            //未訪問あったらqが加算されるので、whileﾙｰﾌﾟ継続
            //訪問済みの場合はqが加算されないので、qが空になってループ解除
        }
    }
        ans=ans+vis.size();//i地点からいける数をansに足す
    }
	cout << ans<<endl;;
}
```
【Docker】Docker-compose のコマンドのまとめ　no.12

![パンプキン カフェ (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/f58d6108-df7c-7540-98ce-71029004d947.png)


こんにちは。まゆみです。

Dockerについての記事をシリーズで書いています

[前回の記事](https://qiita.com/Mayumi_Pythonista/items/b866fad31eb3b17c30d0)に、『docker-compose』で2つ以上の独立したContainerをお互いにコミュニケーションを取らせ、情報をやり取りさせるにはどのようにしたらいいのかを書きました。

![見出しを追加 - 2021-06-11T082653.478.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/d4667877-33ab-88fa-8f57-d30f64c71eb6.png)

今回の記事では、docker-compose で使う主要なコマンドをまとめていきたいと思います

[前回の記事](https://qiita.com/Mayumi_Pythonista/items/b866fad31eb3b17c30d0)に、docker-composeを使う時の手順や、YAMLファイルの書き方などは記載していますので、今回の記事では、docker-composeのコマンドのみに焦点をあてて書いていきます

#docker-composeのコマンド自体を見るコマンド
docker-composeはどんなコマンドが使えるのかな？と

docker-composeで使えるdockerのコマンドを見たい時のコマンドは

```
docker-compose
```
になります。


![2021-06-11_8-56-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/e5cbeebf-cd2d-0232-c76f-db4b6fcc45c2.png)


#イメージをbuildする

docker-compose でイメージをbuildする時は

```
docker-compose build
```
になります

Docker CLIを使って、docker イメージをbuildする時には、

```
docker build <build context>
```

と、build context名が必要でしたが、docker-compose でイメージをbuildする時には、＜build context＞を書く必要はありません。

 <font color="Red">なぜなら、YAMLファイルに書いてあるから</font>です。

#docker-compose up

DockerCLIを使ってdockerを一つづつ実行するときは

```
docker run <Image ID>
```
でした。

Docker-composeを使って2つ以上のContainerを起動するには

```
docker-compose up
```
を用います。

docker-compose up についても、＜image ID ＞を指定しなくても大丈夫です。

理由は、先ほどの  docker-compose build と同じく、YAMLファイルに書いてあるからです。

##Dockerfileを更新した後にdocker-compose upするには？

Dockerfileの内容を書き換えたあと、そのあとまた『docker-compose up』で実行すると、 <font color="Red">古い方のDockerfileが使われ</font>て実行されてしまいます。

新しいDockerfileの内容を反映させたい時は

```
docker-compose up --build
```
で実行します

#dockerをストップさせるには？
docker-compose up で起動したcontainer は

```
docker-compose down
```
でストップさせることができます

Docker CLIでは、docker stop でストップさせても、

Container自体を消すことはできませんでしたが、

docker-compose down だと、 <font color="Red">Containerを止めてさらに消す</font>ことまでやってくれます。

#まとめ
Docker CLIを使うのに慣れていたら、docker-composeのコマンドにも比較的すぐ慣れることができると思います。

今回の記事は短いですが、ここで締めくくらせていただきますね。
QAエンジニアが異世界転生(WF開発→スクラム開発)しても一向にかまわんッッ！と思った話

#**はじめに**
はじめまして、QAエンジニアの川満です！

2年前までWFモデルの開発工程でテスト担当（QA）を行っていましたが
別プロジェクトに参画する事となり、スクラム開発の現場に配属される事になりました！

昨年1年間の間に経験した異世界転生(ウォーターフォール（WF）モデル開発→スクラム開発)した実体験をここに記したいと思います！

##**スクラム開発って？QAはどのように動く？？**
これまで案件開始の要件定義段階から参画しドメインスキル（仕様把握力）や検証観点を持って機能のあるべき姿を提案しつつ、テスト計画を立てスケジュールを設計～実行・不具合管理を下流工程のテストフェーズに実施する。という流れをWFモデルで実践してきました。

ある程度期間を頂きながらテストという工程の役割を果たす。という所に重きを置き、
業務に励んでいました。・・・ところがスクラム開発に入ると考え方・動き方が全然違いました。

まず、テストという工程の役割を果たす。という考えを改めさせられました。
**対象のプロダクトがユーザーに価値を届ける為にはどうすればよいのか？**という議論を
プロダクトオーナー、開発者、デザイナー、QAが真剣に突き詰めていく必要があり、
**”テスト”という工程の考えだけでは十分ではないと感じさせられました。**

さらに進捗状況の確認や振り返りを行うスクラムイベントに参加することになりましたが、
横文字がいっぱい。。。不安がいっぱいでしたが・・・・・？？？！
#スクラムイベント
初めはわからないことだらけでしたが、
進んで実践したり声を上げることで**「楽しい！面白い！」**が増えていきました！
実践して気づいた部分を記します！
##リファイメント
プロダクトバックログ（製品が保有している課題）に対して
課題解決する為のタスクの明確化、見積もり、優先度付けを行う場。
※ここでQAとしてはユーザーが利用するケースを想定し、要件やタスクに不足があれば声をあげる。

##スプリントプランニング
リファイメントで決めたタスクを次回のスプリント（実装～設計～テスト）で
どこまでやるか決め、スプリント成功基準（ゴール）を決める。
例：今回は機能Aと機能Bを実装し、QAしよう！なので
　　ゴールはユーザーに〇〇をさせるサービスのQAまでを行うにする！
※工数的に達成可能か不可能かを判断しながら、QA側のスケジュールも考慮してもらう。

##デイリースクラム
プランニングで決めたタスクの進捗状況を確認し、現在のタスク消化推移をチェック。
※毎日参加し、タスクを進めるうえでの課題が出たらこの場で報告・相談する。

##スプリントレビュー
スプリント内で作成した機能のお披露目会を ステークホルダー（上長や営業さん等）向けに行う。
※自分たちのチームだとPOがファシリテートして成果物を動かしながら会を進めていました。

##レトロスペクティブ
振り返り会です。
今スプリントで何をやって、何を想ったかを共有し合い、
チームが目指すゴールに近づけているか？をみんなで振り返ります。
※会のファシリテートは持ち回りで行いました。

#イベントを通して
結果から言うとここまでか！と思うほど
コミュニケーションを取る必要があり、**臆さず発言する勇気**が必要です。
ただ、いろんなメンバーと検討しながら良いモノを作ろうとする取り組みは凄く勉強になります。
相手への理解が深まり、**自身の存在価値を証明出来る素敵な場**だと感じました。

#**工夫した点**
Wikiに改修内容等を纏めて頂く事もありますが、基本的に仕様書などはない場合が多いです。
なのでスクラムイベント内で出たタスクをみて求められる要件（実装される機能）を把握し、
項目書の設計を行いQA実施するという業務の流れになりました。

ただ、、
**1.緊急を要する案件だと1スプリントで設計～実施を完了させる必要がある。**
**2.要件から項目書作成を行うも認識合わせがうまく出来てないと手戻りが発生する。**

また要件をみても具体的に何が求められているか
わからない（QA側の観点から深堀が足りない）なんてことも・・・・・
※例として自動販売機のプロダクトバックログ・リファイメント内容のイメージ
![困った困った.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/a3c7bbc3-de7d-ec0f-1ae4-b921d2379064.jpeg)

そこでデシジョンテーブル等のマトリクス表を用いて、
項目書の設計をする前にマインドマップを利用してチーム全員でQAをするなら
どんな機能が必要か？どんなパターンをQAしないといけないのか？を話していきました！

すると**ツリー構造上に広がる観点が見やすい！**ということで
沢山の観点を頂きながらパターンがあれよあれよと出来ていきました。
![mindmap.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/55b9395e-eb79-5cdf-c47b-a4834af8e645.jpeg)

チーム全員でQA観点をつくっていくことで、
**「次のスプリントではこうしないといけないね。」**なんてお話も出て、
チームの結束力も強まったと感じることもできました。

このマインドマップを基にマトリクス表にQA観点を落とし込み、
項目書の実装を行った後にQAを実施するというサイクルが出来たことで自信ついていきました。
その結果、**難しい納期や依頼に立ち向かう事が出来る様になりました。**
#**最後に**
とっつきにくいイメージがあったスクラムですが、
いざやってみると、**貪欲に学んでいきたくなるほど素敵な開発手法**でした。

またこのご時世、リモートワークの中でも活かせるチームビルディングの方法等もあるので、
**強固なチーム作りが出来るという点**も魅力の一つだと思います。

あなたもスクラムを怖がらずに、挑戦する機会があればぜひ挑戦してみてください！
**異世界転生(WF開発→スクラム開発)しても一向にかまわんッッ！**と思えるでしょう。

以上、最後まで読んでくれてありがとう御座いました！
Microsoft Edgeにて現在開いている複数のタブを再度一括で開く方法

## 概要
Microsoft Edgeにて現在開いている複数のタブを再度開く方法として、現在のタブをお気に入りにすべて登録することで、再度すべてのタブを開けることがわかりましたので、共有します。

紹介する手順を実施することで、履歴から複数のタブを開くことと同等のことが実施できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5cf07d27-b7ad-a43d-1be0-d0b186d95641.png)

## 手順
### 1. Edgeのタブのすべてを選択（Shift+Click）後、右クリック--> "すべてのタブをお気に入りに追加"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/bd35ce93-0828-5405-295a-6898898f235b.png)

### 2. 適切な名前を設定した上で、"保存"を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/34cdd0a8-766a-a34c-f1b2-dd664dacffee.png)

### 3. ブラウザを再起動、作成したフォルダーを右クリック --> "すべてを開く"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/b1d922a2-b5c1-44c3-8d9f-d1861f879391.png)

### 4. 先ほど保存したサイトが表示されることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/782bf339-5319-31c1-7e19-dbcb44c83573.png)
Dockerfileで完結 CentOS8でlinuxbrewを使う方法

## 概要
linuxbrew使っていますか？
Macユーザーはお馴染みの`brew`コマンドがlinuxでも使えます。

[公式　Homebrew on Linux](https://docs.brew.sh/Homebrew-on-Linux)

他の記事では、せっかくdockerを使っているのに、brewのインストールは手動で行う、、、というものをよく見かけます。

そんなdockerはいやだ！！(笑)ということで、今回は、Dockerfile内の記述でbrewコマンドが使えるようにしてみましょう。


## 環境
- maxOS BigSur 11.2.3
- Docker version 20.10.6  
- docker-compose version 1.29.1

## 構成
```
.
├── docker
│   └── app
│       └── Dockerfile
└── docker-compose.yml
```

## 手順
### 1. docker-compose.yml
今回の構成ではいらないと言えばいらないけれども、dockerfile単体で使うことはあまりないので(私はw)、いつも通りdocker-compose.ymlにまとめる方向です。

```docker-compose.yml
version: "3.9"
services:
  app:
    build:
      context: ./docker/app
    tty: true
```

ちなみに、`tty: true`は、設定していないと起動後に終了してしまうためです。

### 2. Dockerfileを作成
さあ、お待ちかねのDockerfileです。

```dockerfile
FROM centos:centos8

SHELL ["/bin/bash", "-c"]

RUN dnf -y update && \
    dnf install -y procps-ng curl file git \
      && dnf clean all
RUN dnf -y groupinstall 'Development Tools'

# linuxbrew
RUN git clone https://github.com/Homebrew/brew ~/.linuxbrew/Homebrew && \
    mkdir ~/.linuxbrew/bin && \
    ln -s ~/.linuxbrew/Homebrew/bin/brew ~/.linuxbrew/bin
ENV PATH $PATH:~/.linuxbrew/bin
```

#### 解説
##### イメージ
```dockerfile
FROM centos:centos8
```
イメージは、CentOS8を利用します。  


##### シェルはBash
`SHELL ["/bin/bash", "-c"]`で、bashを利用するように指定しています。

##### インストールのためのパッケージ準備
```dockerfile
RUN dnf -y update && \
    dnf install -y procps-ng curl file git \
      && dnf clean all
      && dnf clean all
RUN dnf -y groupinstall 'Development Tools'
```

[Fedora, CentOS, or Red Hat](https://docs.brew.sh/Homebrew-on-Linux#fedora-centos-or-red-hat)にある通りlinuxbrewをインストールするために必要な`procps-ng curl file git`と`Development Tools`をインストールします。

##### linuxbrewのインストール

```dockerfile
RUN git clone https://github.com/Homebrew/brew ~/.linuxbrew/Homebrew && \
    mkdir ~/.linuxbrew/bin && \
    ln -s ~/.linuxbrew/Homebrew/bin/brew ~/.linuxbrew/bin
ENV PATH $PATH:~/.linuxbrew/bin
```

通常のインストールだと、対話式でコマンド実行をしなければならずDockerfile内の記述ではうまくいかないため、
[Alternative Installation](https://docs.brew.sh/Homebrew-on-Linux#alternative-installation)を参考にしています。
**ただし、パスを通す方法が公式とは異なります。**
公式の方法では、`eval $(~/.linuxbrew/bin/brew shellenv)`となっていますが、Dockerfile内でパスを通すには`ENV`を利用する必要があるため、`ENV PATH $PATH:~/.linuxbrew/bin`としています。

## 3. 確認

### 起動
```sh
docker-compose up -d
```

### コンテナにインスペクション
```sh
docker-compose exec app bash
```

### brewコマンド実行
```sh
brew -v
```

以下のようにバージョン情報が出力されたらOKです。

```
Homebrew 3.1.11-45-g33e71c9
Homebrew/homebrew-core N/A
```

### 停止
```sh
docker-compose down
```

## 最後に
Dockerを使うなら、Dockerで完結したいですよね！
とはいえ、今回linuxbrewをDockerfileで完結させるために１日かかってしまったのは辛いところです(汗)
今回だけで見れば、手動でインストールしてもよかった感は否めません。
今後、docker×linuxbrewを使う場面が多々あることを祈ります(笑)

## 参考
- [DockerfileでPATHを通す時はRUNではなくENVを使おう](https://qiita.com/TakashiOshikawa/items/2b8974c242a7054e0be5)
- [Dockerfileでビルド時にbashを使う](https://qiita.com/anagura0000/items/bef08bf129f1bd8529ce)
[awk]HTTPヘッダーのGMTのDateの整形

- HTTPでのリクエストやレスポンスを確認する手段としてのヘッダーは、厳格に表示仕様が決まっている。
- その中で**If-Modified-Since(リクエスト)やLast-Modified(レスポンス)**といったようなDate、いわゆる日時は以下のような形式で表される。
    - 形式 : `<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT`
    - 例 : `Mon, 01 Feb 2021 11:15:07 GMT`
- 今回はこのようなGMT(グリニッジ標準時)での形式をawkで見やすい時刻へ整形する方法を記録する。

## 環境
- Mac OS X 10.15.6

## 結果
- 結果の記述は以下の通り。

```awk:main.awk
BEGIN{ print time_from_gmt(ARGV[1]) }

# 変換関数
function time_from_gmt(g){
	if(g==""){
		error("対象時刻を指定してください。")
	}
    # 月の対応表の作成
	count=split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",m," ")
	for(i=1;i<=count;i++){
		ma[m[i]]=i
	}
    # 対象時刻の正規化
	gsub(/:|,/,"",g)
	split(g,ga," ")
	time=sprintf("%04d%02d%02d%06d",ga[4],ma[ga[3]],ga[2],ga[5])
	return time
}

# error message
function error(m){
	print(m) > "/dev/stderr"
	exit(1)
}
```

- 表示結果は以下。

```bash
$ awk -f main.awk "Mon, 01 Feb 2021 11:15:07 GMT"

# 年(4桁)月(2桁)日(2桁)時(2桁)分(2桁)秒(2桁)
20210201111507
```

## 内容

### 月の対応表の作成
- HTTPヘッダーのDateでの月の表示は数字ではなくEnglish（先頭3語）となっているため、月名と数値の対応表を作る必要がある。
- 月名をkeyにした連想配列にするため、splitで一度数値をkeyにした中間配列を作成した後に反転した新規の配列を作成する必要がある。
    - **※awkでの配列は全て連想配列である。**

### 対象時刻の正規化
- 引数として渡ってくるDateから不要なものを不要な文字や記号(コロンやカンマ)を取り除く。
- またここでもsplitで連想配列化しておくことで、個々として扱うことが容易になる。
- 表示形式を以下にしておくことで、**各JSTやUTCへの変換**や**分析の際のソート処理**をする際にも便利。

## まとめ
- 一度awkやshellに定義しておくことで、以下のような用途の際に便利であると感じた。
    - curlでの最終更新時刻の取得及びこれを利用した判断ロジック
    - RSSにて提供される`<pubDate>`型の時刻の整形及びこれを利用したソート処理
- また上記のことから最低限の機能を利用した処理の重要性を再認識した。


## 参考
- [Date - HTTP|MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Date)
- [RSS 2.0](https://cyber.harvard.edu/rss/rss.html)
XamarinバインドプロジェクトでJARなどをバインドする際、Javaのファイナライザが含まれる場合の対処法。

Javaでは、finalizeという名前の関数は「ファイナライザ」という特別な関数です。ファイナライザはクラスの後始末を行うために存在するが、いつ呼び出されるかわからない、また、呼び出されないこともあるらしく、「何かを積極的におこなう場所」ではありません。基本的に使用は推奨されてない、らしいです。

C#では同じような目的で「デストラクタ」があります。C#でデストラクタはクラス名に「~」をつけて宣言しますが、内部的には「Finalize」という関数名に変換されます。そのため、「Finalize」という関数名を使用すると、以下のような警告やエラーが出ます。

* 「void Finalize()」という関数を作成すると「デストラクタを宣言しようとしましたか？」警告が出ます。
* 「override void Finalize()」という関数を作成すると「Finalizeをオーバーライドしないでください。代わりにデストラクタを提供してください。」エラーが出ます。

# 何が問題か
XamarinバインドプロジェクトでJARをバインドする際、JARの中にファイナライザが含まれていると、Javaの「finalize」がC#の「Finalize」という関数名となってエラーが出てしまう、という問題が発生します。

本来あるべき姿としては、「Javaのfinalizeという関数名をC#のデストラクタに変換してほしい」のですが、そうはなりません。

Xamarinバインドプロジェクトでは、ビルド時エラーが発生した場合、「Metadata.xml」を編集することで、変換の方法を細かく指示することにより、エラーを回避することができます。それでは、今回、「Metadata.xml」でどのように指定すればよいか？ネットで検索したところ、いい方法はないらしい。

## 案１．消してしまえばいい説
ファイナライザは使用すべきでないのだから、消してしまっても問題ない、という考えのようです。

https://stackoverflow.com/questions/40407755/xamarin-android-binding-generations-for-finalizer

```xml
<remove-node path="/api/package[@name='your.package.name']/class[@name='Proper.ClassName']/method[@name='finalize' and count(parameter)=0]" />
```

## 案２．強引におきかえる派
https://forums.xamarin.com/discussion/80680/binding-a-finalizer

Javaの

```java
protected final void finalize()
```
という関数名は、通常なら

```C#
protected override sealed unsafe void Finalize()
```

に変換されてエラーになるが、無理やり

```C#
unsafe /**/ ~FooIterator()
```

というデストラクタにしています。なかなかすごい手です。

```xml
<attr path="/api/package[@name='com.company.api']/class[@name='FooIterator']/method[@name='finalize']" name="managedName">~FooIterator</attr>
<attr path="/api/package[@name='com.company.api']/class[@name='FooIterator']/method[@name='finalize']" name="visibility"></attr>
<attr path="/api/package[@name='com.company.api']/class[@name='FooIterator']/method[@name='finalize']" name="managedReturn">/**/</attr>
```

## 案３．自分で見つけた方法。
まずはビルドします。当然エラーになります。以下のようにエラー一覧が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/84f80416-95d4-c7b8-e616-9de66a9b5efa.png)

「エラー一覧」ウインドウからエラーが発生したダブルクリックしてエラー箇所を表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/2620bb1f-6d23-356b-9641-341512bdd35a.png)

Finalizeが関数名です。赤波線で「ここがエラーだよ」と教えてくれています。このソースコードを直接変更します。この例だと、たとえば今回はEventクラスのデストラクタですので、関数名をFinalizeから「~Event」に変更します。「protected override sealed」「void」は不要なので削除します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/d0d8bfd0-0c32-ae77-9e0d-4d6d9efd354f.png)

このように変更後、「ビルド」を選択すれば、問題なくビルドできました。ただし「リビルド」や「クリーン」を選択してはいけません。「リビルト」を選択すると、デストラクタがもとのファイナライザに戻ってしまします。

# どれがベストか？
* 実際は案１で問題になる事はないと思われます。
* しかし、本来あるべき姿としては、案２か案３です。案３はリビルドしたらエラーになるため、現実的には案２が最適ではないか思います。
機械学習勉強記録 相関関係 相関係数

入力変数同士の相関関係が強いと多重共線性という問題が発生します。

# 1 相関関係
入力変数同士の相関が高いかどうかを調べる時には、`.corr()`を使用します。

```python
# 相関係数の算出
df_corr = df.corr()
```
すると、相関係数が表示されます。
相関係数は1が最大で、その2つの変数が完全に正の相関があることを示しています。
変数aと変数bの相関係数が1の場合は、aが1増えるとbも1増えるような関係です。
また、相関係数が-1の時は、その逆で、aが1増えるとbが1減るような、負の相関を示します。

## 1.1 相関関係の可視化
seabornを用いて、ヒートマップで相関関係を可視化をすることができます。

```python
plt.figure(figsize=(12, 8)) # figsizeは一つ一つのマス（プロット）の大きさを調整できる
sns.heatmap(df_corr.iloc[:20, :20], annot=True); 
# .iloc[:20,:20]とすると、最初の20行、20列だけが表示される
# annot=Trueでヒートマップ中に数値を表示することができる
```

（復習）
`df_corr[df_corr['A'] > 0.5]`のように書くことでA列の値が0.5を超える行だけを表示することができます。
Gatlingで複数のランダム値を使う方法

## 概要

Gatlingで負荷試験をする際、URLに複数のクエリパラメータをつけ、値をランダムで回したかった。
feederを複数作ればいいだけだったのでメモ。
(2時間くらいググったけどなかなかなかった)

## やりたいこと

`https://example.com/?key_A=value_A&key_B=value_B`

のような複数のクエリストリングの値(`value_A`や`value_B`)を指定されたものからランダムの組み合わせでリクエストしたかった。中にはnullもあり。
要するに

```
https://example.com/?key_A=value_A001&key_B=value_B001
https://example.com/?key_A=value_A001&key_B=value_B002
https://example.com/?key_A=value_A111&key_B=value_B999
https://example.com/?key_A=&key_B=value_B150
https://example.com/?key_A=value_A999&key_B=

```
みたいな感じ。

## どうやったか

- feederを複数個置いた
- Arrayで定義した
    - CSVだとnullが表現できない

## 例

- まずArrayでfeederを定義する

```
  val feeder_key_A = Array(
    Map("key_A" -> "value_A001"),
    Map("key_A" -> "value_A002"),
    Map("key_A" -> "value_A003"),
    Map("key_A" -> ""),
      :
      :
  )

  val feeder_key_B = Array(
    Map("key_B" -> "value_B001"),
    Map("key_B" -> "value_B002"),
    Map("key_B" -> "value_B003"),
    Map("key_B" -> ""),
      :
      :
  )
```

- feederを使う

```
  val scn = scenario("シナリオ")
    .feed(feeder_key_A.random)
    .feed(feeder_key_B.random)

    .exec(
      http("アクセス")
      .get("/")
      .queryParam("key_A","${key_A}")
      .queryParam("key_B","${key_B}")
      .check(status.in(200 ))
    )
```
[React] useCallbackで作られる関数に対してgenericを使いたい

# 問題

```tsx
import React from "react"
interface Props {}

interface CallbackProps {
  a: number
  b: string
}

interface CallbackReturn {
  c: boolean
}

const Test: React.FC<Props> = (props) => {
  const callback = React.useCallback<(props: CallbackProps) => CallbackReturn>(
    (props) => {
      const {a, b} = props
      
      return {
        c: true,
      }
    },
    []
  )

  const x = callback({ a: 1, b: "弐" })
  console.log('x.c:', x.c)

  return <></>
}
export default Test
```

![Screen Shot 2021-06-11 at 10.16.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/ce8e3abc-bb4a-3a3d-fdd1-ec9e4e252c3c.png)

![Screen Shot 2021-06-11 at 10.24.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/71ac7f3c-1d37-ed19-95b7-ed977b0bcd93.png)


useCallback自体にはgenericで型付けが出来るんだけど、ここで言う`callback`変数となった関数にはgenericは渡せない。

```tsx
callback<Generic>(...)  // こうしたい場合
```



# 解決

関数を返すuseMemoに切り替える。こうすることでdependencyも使え無駄に関数を生成することはないし、genericを渡せる関数にもなる。

```tsx
import React from "react"
interface Props {}

interface CallbackProps<T> {
  a: T
  b: string
}

interface CallbackReturn {
  c: boolean
}



const Test: React.FC<Props> = (props) => {
  const callback = React.useMemo(() => function<T>(
    props: CallbackProps<T>
  ): CallbackReturn {
    const { a, b } = props

    return {
      c: true,
    }
  },
  [])

  const x = callback<boolean>({ a: false, b: "弐" })
  console.log('x.c:', x.c)

  return <></>
}
export default Test
```