OmniAICreator/Qiita-1.07M huggingface dataset:
segmentation faultと動的割り当て(mallocとfree)

<details><summary>更新履歴</summary>

- sample.cの中身を書き換えた。参考にしたのはNUMERICAL RECIPES in C。

</details>

憎きsegmentation faultへの対応を記録する。
なんとなくメモリの使いすぎな気はしている。
結局はメモリの動的割り当て(mallocとfree)で解決した。

# デバッグ

まずはgdbのインストール。

~~~
% brew install gdb
gdb: The x86_64 architecture is required for this software.
Error: gdb: An unsatisfied requirement failed this build.
~~~

どうやらM1 Macでgdbが使えなくなっているらしい。
その代わりに[こちら](http://www.den.t.u-tokyo.ac.jp/ad_prog/debug/)を参考にlldbを使う。

~~~
% gcc -g -O0 -o hogehoge hogehoge.c -lm
% lldb hogehoge
(lldb) run
...
... stop reason = EXC_BAD_ACCESS
...
~~~

なんだかよくわからない。
直感を信じてメモリの使いすぎ(10,000×10,000の配列を使ってるだけなのに)だと思い、
メモリの動的割り当て(mallocとfree)をすることにする。

# mallocとfree

mallocとfreeに関しては、NUMERICAL RECIPES in Cという本を使うことをおすすめする。
特に、付録のユーティリティルーチンはとても使いやすい。
例えば、私は以下のように使っている。

~~~ sample.c
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define NR_END 1
#define FREE_ARG char*

void nrerror(char error_text[]);
long int *ivector(long nl, long nh);
void free_ivector(long int *v, long nl, long nh);
long int **imatrix(long nrl, long nrh, long ncl, long nch);
void free_imatrix(long int **m, long nrl, long nrh, long ncl, long nch);
double *dvector(long nl, long nh);
void free_dvector(double *v, long nl, long nh);

int main(void)
{
  long int *intonearray, **inttwoarray;
  intonearray = ivector(0,10);
  inttwoarray = imatrix(0,10,0,10);
  double *doubleonearray;
  doubleonearray = dvector(0,10);

  // ここにコードを書く

  free_ivector(intonearray,0,10);
  free_imatrix(inttwoarray,0,10,0,10);
  free_dvector(doubleonearray,0,10);

  return 0;
}

void nrerror(char error_text[])
/* Numerical Recipes standard error handler */
{
  // ここに本の通りのコードを書く
}

long int *ivector(long nl, long nh)
/* allocate an int vector with subscript range v[nl..nh] */
{
  // ここに本の通りのコードを書く
}

void free_ivector(long int *v, long nl, long nh)
/* free an int vector allocated with ivector() */
{
  // ここに本の通りのコードを書く
}

long int **imatrix(long nrl, long nrh, long ncl, long nch)
/* allocate an int matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  // ここに本の通りのコードを書く
}

void free_imatrix(long int **m, long nrl, long nrh, long ncl, long nch)
/* free an int matrix allocated by imatrix() */
{
  // ここに本の通りのコードを書く
}

double *dvector(long nl, long nh)
/* allocate a double vector with subscript range v[nl..nh] */
{
  // ここに本の通りのコードを書く
}

void free_dvector(double *v, long nl, long nh)
/* free a double vector allocated with ivector() */
{
  // ここに本の通りのコードを書く
}

~~~
【初学者向け】AWS VPCの基本のキ

## VPCとは
Amazon VPC(Virtual Private Cloud)は、AWS上に独立したプライベートネットワーク空間を作成できるサービスのことです。
通常AWS上のハードウェアやネットワークインフラストラクチャはユーザー全体で共有されていますが、「VPC」と呼ばれる仮想ネットワークを作成することで、論理的に分割された、特定のユーザーだけが利用できるプライベートネットワークを構築することができます。これにより、ネットワークのセキュリティを確保することができます。

## ネットワーク設計
サービスを構築する上で本番環境のほかに開発やステージング環境を作りますが、環境の分け方は次のいずれかになることが多いと思います。

- 1つのVPCに全ての環境を入れる
- 環境ごとにVPCを分ける
- 環境ごとにAWSアカウントを分ける

2のパターンで設計する場合、VPCをdevelopment、staging、productionという名称で3つ作成します。その際に以下のように２クオテット目が連番になるように設定すると分かりやすくなります。

|  環境    |   IP  |
| ----    | ---- |
|  production   |  10.0.0.0/16  |
|  staging  |  10.1.0.0/16  |
|  deveolopment    |  10.２.0.0/16  |

### IPレンジ設計
以下の理由から、VPCのIPアドレス範囲は、既存ネットワークのIPアドレス範囲を重複しないように構築します。

- VPCのCIDR(IPアドレス)は後から変更不可
- 変更にはVPC上に構築されたものを削除し再構築が必要
- 接続要件が無くても、数年後の要件変更に備える


## サブネット
サブネットとは、VPC内に構成するネットワークセグメントのことです。セグメント分割することで、部署ごとに独自のネットワーク設定を決めてセキュリティを向上したり、また、あるサブネットに障害が起きた時に違うサブネットを利用できるなどリスク分散することができます。
ユーザーはサブネットを作成する際、どのアベイラビリティーゾーンでサブネットを構成するかを指定する必要があります。
サブネットは1つのVPC内に複数作成することができますが、VPCのIPアドレスの範囲内でCIDRを設定する必要があります。

>※アベイラビリティーゾーン（AZ）：リージョン内にある複数のデータセンターの集合体であり、７７箇所存在する（2020年12月時点）

### パブリックサブネット
パブリックサブネットは、インターネットとの通信が可能なサブネットのことです。
もう少し具体的にいうと、ルートテーブル内のデフォルトゲートウェイ（0.0.0.0/0）へのルーティングにインターネットゲートウェイを指定したサブネットです。
 
>※インターネットゲートウェイ（IGW）：VPC内のリソースからインターネットへアクセスするためのゲートウェイのことです。インターネットゲートウェイをVPCにアタッチすることで、VPC内のリソースからインターネットへアクセスすることができます。

### プライベートサブネット
プライベートサブネットはインターネットと通信ができないサブネットのことです。


サブネットをインターネット接続の可否によって分けることにより、ネットワークのセキュリティを向上させることができます。

## 補足：IPアドレスの基礎知識
### IPアドレスとは
PCやサーバなど、TCP/IPで通信する機器を識別するためのアドレスのことです。現実世界で郵便物を配達する際に住所が必要なのと同じように、ネットワークの世界でもデータを特定の機器に届けるためにIPアドレスが必要になります。

### IPアドレスの主な種類
IPアドレスはグローバル（パブリック）IPアドレスと、プライベートIPアドレスの２種類があります。

**グローバル（パブリック）IPアドレス**はインターネットに接続するために用いるIPアドレスで、他と重複しないように割り当てられます。そのため、お名前.com等で同じドメインを取得することはできないのです。

一方**プライベートアドレス**は組織や家庭内で用いられるIPアドレスです。こちらは全世界に公開されているわけではないので、ある組織と別の組織で重複していても問題ありません。要は組織や家庭内などの1つのネットワーク内で重複せず、コンピューターが識別できればいいのです。


### ネットワーク部とホスト部
IPアドレスは通常表記の他に、３２ビットの整数値で表すことができます。この３２ビットで表したIPアドレスは左側のネットワーク部と呼ばれる部分と、右側のホスト部と呼ばれる部分に分けることができます。

```
// 通常のIPアドレスの表記
203.0.113.43

// ビット列での表記
11001011000000000111000100101011
```
ネットワーク部は、どのネットワークなのか。ホスト部はそのネットワークの中のどのコンピューターなのか。ということを表しています。


### IPアドレスのクラス
IPアドレスは、使用するネットワークの規模によってクラスA、クラスB、クラスCと3つのクラスに分かれています。それぞれ32ビット中の何ビットをネットワーク部に割り当てるかが規定されているので、それによって持つことのできるホスト数が違ってきます。
これらくのクラスは、以下のテーブルで示しているように、IPアドレスの最初の数字でクラスが分けられます。

|  IPアドレスの最初の文字    |   クラス  |   用途（ネットワークを構成するパソコンの台数）  |
| ----    | ---- | ---- |
|  0～127   |  クラスA  |  大規模ネットワーク用（最大16,777,214台）  |
|  128～191  |  クラスB  |  中規模ネットワーク用（最大65,534台）  |
|  192～223    |  クラスC  |  小規模ネットワーク用（最大254台）  |

## まとめ
AWS VPCの基礎の基礎をまとめてみました。何かご指摘等あればコメントいただけると嬉しいです。
テンプレートエンジン

データとテンプレートをもとに文字列を作成する方法。

https://www.codegrid.net/articles/template-engine-1/#:~:text=%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3%E3%81%A8%E3%81%AF%E3%83%87%E3%83%BC%E3%82%BF,%E3%81%A8%E8%80%83%E3%81%88%E3%81%A6%E5%95%8F%E9%A1%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82
【備忘録 AtCoder】アルゴリズムによって計算時間が大きく異なる二つのコード

# 問題
[ABC281](https://atcoder.jp/contests/abc281/tasks/abc281_c "問題を開く")

# 実行が間に合わなかったコード
```java:Main.java
import java.util.Scanner;

public class Main{

    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long t = sc.nextLong();
        int[] time = new int[n];
        for(int i=0; i<n; i++){
            time[i] = sc.nextInt();
        }

        long sum = 0;
        int i = 0;
        //ここのループがボトルネック
        while(sum < t){
            i ++;
            sum += time[i%n];
        }
        
        int ans_num;
        if(i%n==0){
            ans_num = n;
        }else{
            ans_num = i%n;
        }


        System.out.println(ans_num + " " + (time[i%n]-(sum-t)));

    }

}
```

コードないのwhile文のループ数がとても多くなり，TLE（実行時間超過）が頻発してしまいました．


# 改善ver

```java:Main.java
import java.util.Scanner;

public class Main{

    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long t = sc.nextLong();
        int[] time = new int[n];
        for(int i=0; i<n; i++){
            time[i] = sc.nextInt();
        }

        long time_oneround = 0;
        for(int i=0; i<n; i++){
            time_oneround += time[i];
        }

        long time_rem = t % time_oneround;

        long sum = 0;
        int i = -1;
        while(sum < time_rem){
            i++;
            sum += time[i];
        }

        System.out.println((i+1) + " " + (time[i]-(sum-time_rem)));

    }

}
```

「プレイリスト全体を何周するかを最初に計算しておいて、残りを1曲ずつ進めればO(N)である」と考えてアルゴリズムを組めば，計算量を大きく減らすことができる．無事にAC．

[参考ツイート](https://twitter.com/kyopro_friends/status/1601577372393742338?s=20&t=FwbMxf5QyBaY5q1FiWzaVg "ツイートを開く")


# 終わりに
アルゴリズムって大事だなぁと思いまいた（小並感）
maya mel bake abc

```
// baked rock 
$sf= `playbackOptions -q -minTime`-2;
$ef= `playbackOptions -q -maxTime`+2;
$ctrlabc = ls("*:*rock*AlembicNode");
print $ctrlabc;
$frange2 = $sf+":"+$ef;
if( size($ctrlabc) >0 ){ 
 bakeResults -t $frange2 -at time -at speed -simulation true "*:*rock*AlembicNode"; 
}
else{ print "no abc expression to bake";}

// baked concreate 
$sf= `playbackOptions -q -minTime`-2;
$ef= `playbackOptions -q -maxTime`+2;
$ctrlabc = ls("*:*concreate*AlembicNode");
print $ctrlabc;
$frange2 = $sf+":"+$ef;
if( size($ctrlabc) >0 ){ 
 bakeResults -t $frange2 -at time -at speed -simulation true "*:*concreate*AlembicNode"; 
}
else{ print "no abc expression to bake";}
```
FastAPIのミドルウェアを使ってサーバー全体でエラー処理を行う

## TL;DR

- FastAPIのミドルウェアを使えばInternal Server Errorの時にエラー処理を行うことができる
- ミドルウェアを使うことで、エラー処理を一ヶ所に共通化することができる

## 背景

FastAPIはルーティング=関数なので、処理のエラー時にはそれぞれの関数でエラー処理を行う必要がある。

```python
@app.get("/route_1")
def routing():
    try:
        # 何かの処理
    except Exception as e:
        # エラー処理

@app.get("/route_2")
def routing():
    try:
        # 何かの処理
    except Exception as e:
        # エラー処理
```

これは非常に手間だし可読性も悪い。

## ミドルウェアを使ってグローバルなエラー処理を行う

まず、ミドルウェアを作成する

```python
@app.middleware("http")
async def exception_handling_middleware(request: Request, call_next):
    try:
        return await call_next(request)
    except Exception as e:
        # エラー処理を行う、例えばSlackに通知する
        slack_notify(e)
        return Response("Internal server error", status_code=500)
```

これで、全てのルーティングでエラーが発生した時にSlackに通知することができる。
`slack_notify`の部分でエラー処理を行っている。
ここを変えれば、例えばDBにエラーを保存したり特殊なレスポンスを返したりすることができる。

## まとめ

ミドルウェアを活用しよう。

### 参考

https://stackoverflow.com/questions/61596911/catch-exception-globally-in-fastapi
bundle exec cap production deployでのエラー解決方法

## はじめに
プログラミング初心者による備忘録です。

railsアプリのEC2への`Capistrano`を使用しての自動デプロイ設定中に発生したエラーの解決方法を残します。


## 問題とエラーメッセージ

以下のコマンドを実行
```
 % bundle exec cap production deploy
```
すると以下のエラーが発生

```
    略

01:00 deploy:assets:precompile
      01 $HOME/.rbenv/bin/rbenv exec bundle exec rake assets:precompile
      01 bundler: failed to load command: rake (/var/www/myapp/shared/bundle/ruby/2.6.0/bin/rake)
      01 Bundler::GemNotFound: Could not find date-3.3.3 in any of the sources
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/spec_set.rb:86:in `block in materialize'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/spec_set.rb:80:in `map!'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/spec_set.rb:80:in `materialize'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/definition.rb:170:in `specs'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/definition.rb:237:in `specs_for'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/definition.rb:226:in `requested_specs'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:101:in `block in definition_method'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:20:in `setup'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler.rb:149:in `setup'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/setup.rb:20:in `block in <top (required)>'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/ui/shell.rb:136:in `with_level'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/ui/shell.rb:88:in `silence'
      01   /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/setup.rb:20:in `<top (required)>'
#<Thread:0x00007fd71da7a2a0@/Users/admin/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/sshkit-1.21.3/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
 	
    後略
```
## 原因
本番環境にインストールされているRubyGemsのバージョンが古かったようです。

バージョンの確認方法
```
$ gem -v
```
## 解決方法
参照サイト様です。
https://autovice.jp/articles/147

EC2内で以下のコマンドでRubyGemsを最新バージョンにアップデートします。
```
$ gem update --system
```
以下でバージョンを調べて
```
$ gem -v
```
`3.13`以上ならアップデートできています。

---
Activedirectory ドメインのコンピューターにソフトをインストールするバッチの作成

ActiveDirectory内のコンピューターにソフトを自動でインストールしようとして試行錯誤していたらうまくいったので共有します。
ある特定のソフトのインストールに成功しただけなのでうまくいかないこともあると思います。

# 状況
* msiインストーラがないのでソフトウェア配布機能は使えない
* ユーザーは管理者権限を持っていないのでユーザーのログインスクリプトでインストーラを実行させることはできない

# 検討事項
* コンピュータのスタートアップスクリプトでインストーラを実行させる
* インストール済みかどうか判別して未インストールの時のみ実行したい
* 各コンピュータのインストール状況を確認したい

# やったこと
* ADサーバに共有フォルダを作成してそこにインストーラとバッチファイルを保存
* そのフォルダにコンピュータのインストール状況を保存できるように Domain Computers に書き込み権限を付与
* 以下、バッチファイルを作成して共有フォルダに保存。
* グループポリシーオブジェクトを作成(SoftwareInstall)して「コンピューターの構成→ポリシー→Windowsの設定→スクリプト→スタートアップ」に上のバッチファイルを追加。ドメインコンピュータが実行できるようにUNC表記で追加(￥￥サーバー名￥フォルダ￥install.bat)
* Active Directory ユーザーとコンピューターで対象のコンピュータを入れるOU(ソフトインストール用)を作成
* 上記OU(ソフトインストール用)に作成したグループポリシーオブジェクト(SoftwareInstall)をリンク
* インストールしたいコンピュータを上記OU(ソフトインストール用)に移動

これで対象のコンピュータを再起動すればインストールされました！
共有フォルダ内に[コンピュータ名].txtが作成されて、そのコンピュータのインストール状況が記録されます。

# 参考にしたサイト
* http://rukifiel.net/ms-dos-001/ 
インストール済みソフトを調べる方法
* https://jj-blues.com/cms/wantto-changevalueinfor/ 
バッチのFOR文中で変数を更新して利用する方法

# 作成したバッチファイル
```batchfile:install.bat
@ECHO OFF

SETLOCAL ENABLEDELAYEDEXPANSION

SET filepath=%~dp0\%COMPUTERNAME%.txt
SET softname=[インストールソフト名(事前に調べておく)]
SET installed=False
SET installcommand=[インストーラ実行コマンド文字列(UNC表記)]

FOR /F "delims=" %%S IN ('reg query "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall" /s') DO (
    SET TMP=%%S
    IF NOT "!TMP:DisplayName=!" == "!TMP!" (
        IF NOT "!TMP:%softname%=!" == "!TMP!" (
            SET installed=True
        )
    )
)

FOR /F "delims=" %%S IN ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" /s') DO (
    SET TMP=%%S
    IF NOT "!TMP:DisplayName=!" == "!TMP!" (
        IF NOT "!TMP:%softname%=!" == "!TMP!" (
            SET installed=True
        )
    )
)

IF "%installed%" == "True" (
    @ECHO %DATE% %TIME% なにもしません。。。 [%username%] >> %filepath%
) ELSE (
    START /WAIT %installcommand%
    @ECHO %DATE% %TIME% インストール完了！ [%username%] >> %filepath%
)
```
《VBA｜Access》次へボタン：最後になったら最初のレコードに戻る

## 概要
Accessの「分割フォーム」で、フィルタリングしたレコードを順番に確認するような場合があります。
マクロ等で「次へ」ボタンは簡単に設置できますが、最終レコードに到達したあとでもボタンを押すとエラーになってしまいます。
VBAを使ってエラーを回避し、さらに最終レコード到達時には最初のレコードに戻るようにすると使用感がアップします。

## 前提
前提としてこのような分割フォームを想定しています。
![次へボタン01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/0ba62f3c-d96e-3d28-bcc5-c0140b01d17e.png)

左にフォームビュー、右にデータシートビューがあります。
フォームのヘッダー部分に検索窓があり、フィルタリングしたレコードが右にリスト表示されます。

## 「次のレコード」をフォームに表示するVBA
Accessのフォーム内でレコード移動するときに「次へ」ボタンを配置してVBAで動かす場合は、このように書くだけです。
```
DoCmd.GoToRecord , , acNext
```
![次へボタン02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/b4a32255-6fc7-59d1-6017-4dec962837ce.png)

## VBAのエラー
![次へボタン03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/2c0261bd-dc3b-a1ff-e8f4-96de01b5dad9.png)
しかし、これで作ったボタンを押し続けて最後のレコードに達すると「エラー」になってしまいます。

## エラー処理＆最初に戻る
「次へ」ボタンを押し続けて最後のレコードになったら、自動的に最初のレコードに戻ってくれると良いですよね。

上のコードにエラー処理を組みこんで、そのような処理を実現します。
```
Private Sub cmd次へ_Click()

    '最後のレコード（エラー）になったらエラーラベルに飛ぶ
    On Error GoTo ErrHandler

        '通常の処理：次のレコードに移動
        DoCmd.GoToRecord , , acNext
        Exit Sub

'エラーラベル（この指標の後にエラー処理を記述）
ErrHandler:
    '最初のレコードに行く
    DoCmd.GoToRecord , , acFirst
 
End Sub
```
## 実行
《次のレコード》ボタンを押していくだけでグルグルとレコードを移動し続ける事ができるようになります。
フィルターをかけていればフィルター内だけを移動します。

ちなみに都道府県のデータはこちらのサイトからいただきました。

https://www.start-point.net/maps/tool/
Goでbuild constraintsを使ってビルドを分ける

Goではbuild constraints（build tagsとも呼ばれる）を利用することで、異なるビルドを作り分けることができます。
この機能を利用することで、デバッグ用とリリース用や無償版と有償版といった複数のバリエーションのビルドを作ることができます。

## 本記事でのGoのバージョンについて

本記事ではGo 1.17以降を対象とします。

build constraintsの書き方はGo 1.17から変更になったのですが、1.16は既にサポートされていないバージョンなので、本記事でも扱わないこととします。

詳細については https://go.dev/design/draft-gobuild を見るようにとリリースノートにもあるので、以前の記法と「なぜ変更になったのか」が気になる方はそちらを御覧ください。

## build constraintsの付け方

build constraintsは以下のようにファイルの先頭に`//go:build 条件`という形式のコメントを書きます。

条件の部分は単純にタグ名を指定する以外にも、if文のような`(A || !B)`のような条件も指定できます。

ここでは簡単な例として`release`というタグを使ってみます。

```go:myapp.go
//go:build !release

package main

const API_SERVER_URL = "http://localhost:8080/
```

```go:myapp_release.go
//go:build release

package main

const API_SERVER_URL = "https://api.example.com/
```

`myapp.go`の方は`!release`（`!` = 否定）という指定で、`release`**以外**のときに対象となるようにしています。  
`myapp_release.go`のほうは単純に`release`という指定です。

:::note info
このconstraintsには上記のようにユーザーが独自でつけるもの以外にも、`linux`, `386`といったOSやアーキテクチャに対応するものもあります。

既定では`GOOS`, `GOARCH`と`cgo`に関するものがあるので、独自に付ける場合はこれらとかぶらないように気をつけたほうがよいでしょう。

他にも細かいルールなどがあるのですが、ここには書ききれないので、公式ドキュメントの[Build constraints](https://pkg.go.dev/cmd/go#hdr-Build_constraints)に目を通すことをお勧めします。
:::

## 対象を指定してビルドする

上記のようにbuild constraintsを指定した上で、対象を指定してビルドする場合は、以下のように`go build`時に`-tags`オプションを指定します。

```sh
go build -tags release
```

このようにすると`release`が指定された`myapp_release.go`ファイルがビルド対象となり、逆に`!release`が指定されている`myapp.go`はビルド対象外となります。

:::note warn
今回の例のようにconstraints毎に異なる値を設定する、異なる関数の実装にするといった場合は、いずれか1ファイルのみがビルド対象になるように設定しないとエラーになってしまいます。

なぜなら、両方がビルド対象に含まれてしまうと、今回の例でいえば`API_SERVER_URL`が二重に定義されていることになってしまうからです。
:::

### 上記の例で`-tags`を指定しなかった場合

```sh
go build
```

というように、`-tags release`を指定しなかった場合はどうなるでしょうか。

この場合は`!release`の条件に合致する`myapp.go`がビルド対象になり、`myapp_release.go`はビルド対象外になります。
## どのような時に使うのか

Go自身はこの機能をOSやアーキテクチャ別の実装のために使っていますが、今回のようにデバッグとリリースで分けるといった使い方も考えられます。

他にもFree版、Pro版、Enterprise版のように複数のエディションに分けるといった使い方もできそうです。

今回の例のような設定値であれば、設定ファイルから読み込むといったことも多いかと思いますが、場合によっては安易にユーザーに変更されては困るとか、エディションによって使える機能が変わってくる、といったような場合には、build constraintsで別々のビルドにするというのは良い考えではないでしょうか。
S3に設置したCSVをAppFlowでSalesforceにupsert反映させる

# 概要

- S3に設置したCSVファイルの内容をAmazon AppFlowを使ってSalesforceにupsert反映させる方法をまとめる

# AppFlowのupsert反映とは

- 指定したキーでSFを探索し「ヒットしたらレコード更新、ヒットしなかったレコード作成」をする同期方法のことである

# 前提

- AWS側でSalesforceの登録が完了していること

# 情報

- 諸事情により画面キャプチャをお見せすることができないため、文字ベースの説明となる。
- 今回はSalesforceの商品オブジェクトに対してS3のCSVの内容を反映していこうと思う。

# 方法

## S3

- 任意のバケット名でバケットを作成し、当該バケット内に下記の２つのフォルダを作成する。
    - test_data
    - error_data

## CSV

- 下記の内容のtest_data.csvを作成する。

    ```test_data.csv
    sync_id,name
    1,テスト商品_01
    ```

- 作成が完了したらS3の「test_data」フォルダにtest_data.csvをアップロードする。

## Salesforce

- ログインし、設定からオブジェクトマネージャーを開く。
- 表示ラベルが「商品」でAPI参照名が「Product2」のものをクリックする。
- 遷移先ページのサイドバーの「項目とリレーション」をクリックする。
- 「新規」をクリックする。
- データ型は「テキスト」を選択し「次へ」をクリックする。
- 遷移先のページで下記のように設定する

    | 項目 | 内容 | 備考 |
    | --- | --- | --- |
    | 項目の表示ラベル | syncId |  |
    | 文字数 | 255 |  |
    | 項目名 | syncId |  |
    | 説明 | 任意 |  |
    | ヘルプテキスト | 任意 |  |
    | 必須項目 | チェックしない |  |
    | ユニーク | チェックする |  |
    | 「ABC」と「abc」を別の値として扱う（大文字と小文字を区別する） | 選択する |  |
    | 外部ID | チェックする |  |
    | カスタムレポートタイプに自動追加 | チェックする |  |
    | デフォルト値 | 設定しない |  |

- 上記の設定をして「次へ」をクリックする。
- 項目レベルセキュリティの設定は特にいじらず「次へ」をクリックする。
- ページレイアウトの設定も特にいじらず「保存 & 新規」をクリックする。

## AppFlow

- 下記のように設定する。

    | 項目 | 内容 | 備考 |
    | --- | --- | --- |
    | フロー名 | 任意の内容を入力 |  |
    | 暗号化設定をカスタマイズする (高度) | チェックしない |  |
    | タグ | 特に設定しない |  |
    | 送信元名 | S3 |  |
    | バケット名 | 先に作成した任意のバケットを選択 |  |
    | バケットプレフィックス | test_data | 送信元csvファイルの入っているフォルダ名 |
    | データ形式の設定 | CSV 形式 |  |
    | 送信先名 | Salesforce |  |
    | Salesforce 接続を選択 | AWSに接続を登録済みのSalesforceを選択 |  |
    | Salesforceオブジェクトを選択 | Product2 |  |
    | Amazon AppFlowが送信先にレコードをを書き込めないと場合 | 現在のフロー実行を停止する |  |
    | 転送できなかったデータを書き込む - バケット名 | 先に作成した任意のバケットを選択 |  |
    | 転送できなかったデータを書き込む - バケットプレフィックス | error_data | エラーログを出力するフォルダ名 |
    | フロートリガー | オンデマンドで実行 |  |
    | マッピング方法 | 手動でフィールドをマッピングする |  |
    | 送信先レコードの設定 | upsert レコード |  |
    | 送信元フィールド名 | sync_id |  |
    | 送信先フィールド名 | syncId__c | プルダウンで選択後「選択したフィールドをマッピングする」をクリックする |
    | 送信元から送信先フィールドへのマッピング 送信元フィールド名 | name |  |
    | 送信元から送信先フィールドへのマッピング 送信先フィールド名 | Name（商品名） |  |

- 上記以外は特に設定せずにAppFlowの設定を完了にする。

# 実行

- 後はAppFlowのフローを手動実行すればSFの商品オブジェクトに「テスト商品_01」のレコードが追加される。
- 次に下記の様にCSVの内容を変更し、S3のtest_dataフォルダに上書きアップロードしてフローを手動実行してみる。

    ```test_data.csv
    sync_id,name
    1,テスト商品_a
    ```

- するとsync_idを使ってProduct2オブジェクトのsyncId__c項目を探索し「1」のレコードがヒットするため「テスト商品_01」が「テスト商品_a」に更新される。
ドットネットフレームワークでヘッダーやサイドメニューをインクルードする方法

<h1>.NETフレームワークでのインクルード方法</h1>
<p>こんにちは！見習いIOTエンジニアのめぐみです。</p>
<p>多くの画面で共通するヘッダーフッターやサイドメニューなどは使いまわしたい！<br>
１か所に記載した共通部分を読み込みする「インクルード」ですが、ドットネットフレームワークでは簡単にできる♪と思いきや、苦戦させられました(T_T)</p>
<p>今回の記事ではドットネットフレームワークでのインクルードの方法を書いていきます。<br>
※自分の勉強・備忘録と同じ沼にはまった方の助けになりますように。</p>

<h2>まずは「Site.Master」を作ろう！</h2>
<p>これが使いまわせる共通部分になります。<br>プロジェクトを右クリックして「追加」⇒「新しい項目」⇒「WEBFormsのマスターページ」というカッコいい名前をクリックします。<br>
![dotnetStart.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984282/255bf0d6-51af-943a-a0be-e57371bd1c2e.jpeg)

そこにヘッダーやフッターなどを記載したら、メインコンテンツ（ページごとに異なる部分）を表示させたい箇所に以下を記載してください。</p>
<br>
<code>&lt;asp:ContentPlaceHolder ID="MainContent" runat="server"&gt;
&lt;/asp:ContentPlaceHolder&gt;
</code>
<br><br>
<p>この<code>asp:ContentPlaceHolder</code>はいくつも作れます。<br>
メインコンテンツ以外にも、例えばお気に入りのサムネイル画面や、ユーザーや時期によってヘッダーの表示内容を変えたい時にも使えそうですね！<br>
重要なのはIDで、メインコンテンツを記載するページでこのIDを指定することになります。
</p>
<h2>メインコンテンツを作って連携</h2>
<p>では次は、ページごとに異なる内容を表示したいメインコンテンツ！<br>
「追加」⇒「新しい項目」⇒「WEBフォーム」で作った拡張子が「aspx」
のファイルですが、まず1番上の<code>&lt;%@ Page Langage="" %&gt;</code>の中でマスターページ（共通部分のページ）を登録するために、この１文を追記します。</p><br>
<code>MasterPageFile="~/Site.Master"</code><br><br>

<p>他はまっさらな状態で以下を記載してください。</p>
<br>
<code>&lt;asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"&gt;<br>
&lt;/asp:Content&gt;
</code>
<br><br>
<p>この<code>asp:Content</code>タグを開いて、そのの中にメインコンテンツの内容を記載していきましょう！<br>
これでインクルードは無事完了です(^^)</p>
<h3>そもそもWEBアプリケーション「空」を選択してしまったのがすべての始まり・・・かもしれない</h3>
<p>デザインしかしていなかった私はWEBアプリケーションを作成したときに自動で生成されるヘッダーやメニューを「消すのが面倒」としか考えていませんでした。<br>
そこで選択していたのが「空」のWEBアプリケーションです。</p>
![uploading...0]()

<br>
<p>ですが今回インクルード方法に困った挙句「空じゃない方のアプリケーションを参考にしてみよう！」と試したところ、あっさり、というかもう既に<code>Site.Master</code>や<code>asp:Content</code>タグも用意されていたのです。<br>
初心者のうちは、面倒くさいなんて考えていたらダメなんですね！
</p>
<h4>まとめ</h4>
<p>この<code>Site.Master</code>と<code>asp:ContentPlaceHolder</code>を使えば、WEBページのコンテンツをパーツ化して使いまわすのがとても簡単にできます。<br>
覚えるまでは長い道のりかもしれませんが、覚えてしまえばフレームワークはやはりとても便利なツールになってくれそうです。<br>
今後も勉強を続けて、脱！見習いを目指していきます♪<br>
最後まで読んでくださり、ありがとうございました。</p>
《VBA｜Access》メインフォームのテキストをサブフォームにコピーする

## 概要
メインフォームに入力したテキストをサブフォームにコピーするVBAです。
例えば「会社」のメインフォームの中に「社員」のサブフォームがある場合に、会社の住所・TEL番号と同じものをボタンクリックで社員のレコードに入れます。
わりと需要があると思うのですが、ネットで探してもはっきりと指南するページが見つからなかったので書いておきます。
VBAとしてはかなり簡単なものですが、備忘録としてなるべく初歩的な部分から説明したいと思います。


## 目的
こんな感じでメインフォームとサブフォームがある場合に、メインに入れた情報をサブフォームにコピーしたい。
![Access_01_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/7c123d23-f48e-db7c-04e9-914a68b2402b.png)

## リレーションの設定
フォームを作る前にリレーションを設定しておきます。例として、会社のテーブルと社員のテーブルを作成し、リレーションでIDを一対多でつなげます。IDは会社側をオートナンバーにしたら社員側は数値型にして、フィールドサイズを「長整数型」、インデックスを「はい (重複あり)」にしてください。
![Access_01_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/2be1bf5c-aebf-cde4-f2f2-98a972dcf6cd.png)

## フォームの作成
会社のテーブルからフォームを作成します。フォームデザインでサブフォームを選択して配置。データのソースオブジェクトを「社員」にします。プロパティシートの「すべて」タブを選択し、サブフォームオブジェクトの名前を設定します。
![Access_01_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/ba4e81fc-89a4-12c5-0f31-334a8ffaf5c3.png)

## ボタンの配置
フォームデザインからボタンを配置。プロパティシートの「すべて」タブを選択し、ボタンの名前を設定します。ボタンを選択状態のまま、次に「イベント」タブのいちばん上「クリック時」の右側の︙マークをクリックし、「コードビルダー」OKしてVBAのコード編集画面を開きます。
![Access_01_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885228/40976077-d0df-c183-db20-a1e94d9c1ea2.png)

## VBAの記述
VBAの内容としてはこれだけです。最初の行と最後の行の間にある部分が実行する内容となります。
```
Private Sub コピーボタン_Click()

   'ボタンクリックでサブフォームにメインフォームの内容をコピーする
   Forms!会社フォーム.社員フォーム!住所 = Me.住所
   Forms!会社フォーム.社員フォーム!電話 = Me.電話

End Sub
```

イコールの左側が内容を貼りつけたいサブフォームの項目、右側がコピー元になるメインフォームの項目。頭の「Forms!」は固定。メインフォーム名とサブフォーム名をドットでつなげて「！」を付けます。最後がコントロール（テキストボックスなど）の名前です。ここで指定するコントロール名はあくまでフォーム上の「名前」ですが、基本的にテーブルから作成したフォームではフィールド名がそのままフォームのコントロールの「名前」になっています。右側の「Me.」はメインフォームに紐付いたコードに書いているのでこの表現となります。全体として左側に右側を代入するという命令文になります。

## 実行
ボタンをクリックするとサブフォームの選択している行（レコード）にメインフォームの内容をコピーします。サブフォームにレコードが無い場合はコピーされた状態で新規作成されます。

Access VBAでももっとも基本的な構文のひとつになるかと思いますが、基本すぎて案外ネットで説明されていることが少ないような気がします。ちょっとしたことですがVBAで作っておくと入力作業が便利になります！
Oracle Analytics Cloud Classic： Answersで分析を編集するときに対象データが多いため、編集までに時間がかかるときの対処

はじめに
---
Oracle Analytics Cloud Classic： Answersで分析を編集するときに対象データが多いと、編集までに時間がかかるときがあります。
そんな場合に、
・編集画面のデフォルト表示を基準タブに変更する
・データを絞りこむためのフィルタをセットしておく
という対処で、ストレスを軽減します。
編集画面のデフォルト表示を基準タブに変更する方法を紹介します。

Answersの分析を編集モードで開こうとすると、データ量が多いと時間が・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/768e1b84-6015-9e36-e1d5-5e553514eae3.png)

編集画面のデフォルト表示を基準タブに変更する
---
Answersの編集画面で、初期表示は"結果タブ"にセットされています
変更するには、右上部のアカウントアイコンをクリックし、"マイ・アカウント"をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/0cad1e38-6603-5442-ddea-7d2922b8c1d4.png)

分析エディタが、"デフォルト-分析の編集時に「結果」タブで開始"にセットされています。
![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/6818c389-f7ed-597b-b2ba-9724d4e2a291.png)

分析エディタのリストで、"分析の編集時に「基準タブ」で開始"に変更します。OKをクリックします。
![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/2da7981e-0312-a7cb-ab4e-3c1ae19da42b.png)

カタログから、Answersで作成した分析を編集で開くと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/ae6b600f-eeeb-bad4-700f-74d275049c9f.png)

「基準」タブが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/c0674b71-a4a1-4778-fa06-45547355309d.png)


※システム全体で変更するには、システム設定 - Answers Editor Start Tabを変更します。
"answerCriteria"にセットします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/4dbc7d32-a381-77be-0b59-79082a4a927e.png)

以上
[Windows10]複数の宛先へpingを1回送信するスクリプト[PowerShell]

# はじめに
遠方の拠点から「インターネットやシステムへの接続が遅い」という問い合わせがよくあるが、通常時の速度を定点測定していないため遅さが体感速度でしか計れず、速度を計る指標がないという問題を抱えている。
まずはお金をかけずに複数拠点-本社間の通常状態での通信速度を収集したいと考え、
Powershellにてスクリプトを作成した。

# 環境
Windows10 22H2 64bit Pro
Powershell 5.1.19041.2364

# 処理内容
~~~powershell:ping_v1.ps1
#ログファイル名へ付加するタイムスタンプのフォーマット
$date = Get-Date -Format _yyyy_MMdd_HHmmss

#pingの送信先を記載したtarget.txtを$fileへ格納
$file = Get-Content ".\target.txt"

#ログファイルの出力先として、ユーザープロファイル(%userprofile%)のパスを$outputへ格納
$output = $env:USERPROFILE

foreach ($target in $file) {
　#$fileに記載された宛先へ一度pingを送信
  $p=ping $target -n 1
 
  #pingの結果から統計情報等を除いた部分をユーザープロファイル直下へ出力
  $p[1]+$p[2] >> $output\pinglog_$date.txt
  }

~~~

## target.txt記載例
~~~target.txt
8.8.8.8
www.yahoo.co.jp
~~~

# 使い方
1. [target.txt]を作成し、pingを送付したいホスト名 or IPアドレスを記載。
アドレス1つごとに改行する。
1. [target.txt]、[ping_v1.ps1]を同一ディレクトリに配置する。
1. [ping.ps1]を実行
1. 実行ユーザーのユーザープロファイル直下に[pinglog_"yyyy_MMdd_HHmmss".txt]が出力される

# ログの例
~~~
8.8.8.8 に ping を送信しています 32 バイトのデータ:8.8.8.8 からの応答: バイト数 =32 時間 =14ms TTL=115
edge12.g.yimg.jp [182.22.25.124]に ping を送信しています 32 バイトのデータ:182.22.25.124 からの応答: バイト数 =32 時間 =15ms TTL=56
~~~

# 余談
本当はping結果をそのままテキストに出力ではなく、宛先と応答時間(ms)をテーブル形式で表示させたかったが
powershellの習熟度が足りず断念。。。と思っていたらうまくいった。

~~~powershell:ping_v2.ps1
#ログファイル名へ付加するタイムスタンプのフォーマット
$date = Get-Date -Format _yyyy_MMdd_HHmmss

#pingの送信先を記載したtarget.txtのパスを$fileへ格納
$file = Get-Content ".\target.txt"

#ログファイルの出力先として、ユーザープロファイル(%userprofile%)のパスを$outputへ格納
$output = $env:USERPROFILE

#ハッシュテーブル$arrayを作成
$array = @{}
foreach ($target in $file) {
    #$fileに記載された宛先へ一度pingを送信し$pへ結果を格納
    $p=ping $target -n 1

    #応答速度が =xxmsという形式になっている為、=を削除し$p1へ格納
    $p1 = $p[1]+$p[2] -replace "=", ""

    #半角スペースを区切り文字とし配列化、$p2へ格納
    $p2 = $p1.split(" ")

    #$arrayへ宛先、応答速度を追加
    $array.add($p2[0],$p2[10])
    }
#$arrayをテキスト形式でユーザープロファイル直下へ出力
$array >> $output\pinglog_$date.txt
~~~

~~~
Name                           Value                          
----                           -----                          
edge12.g.yimg.jp               26ms
8.8.8.8                        17ms
~~~

# 参考にさせていただいたページ

https://www.tekizai.net/entry/powershell_ping_3

https://qiita.com/TAKA-SHU/items/d4467583c62d9b556fa4

https://learn.microsoft.com/ja-jp/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.3

https://soma-engineering.com/coding/powershell/what-is-hashtable/2018/06/06/
AtCoder 競プロ典型 90問 001 - Yokan Party（★4） Python解答例(二分探索 / 貪欲法)

[Supership](https://supership.jp/)の名畑です。先日、知り合いの一世代上の女性が「[スラムダンクの映画](https://slamdunk-movie.jp/)が流行ってるんですよね。原作読んだことないけど行ってみようかな」という話をしていて、本当に人気なんだなと実感しました。

## はじめに

競プロ典型 90問の過去問解答例シリーズです。
今回は1問目のYokan Partyです。難易度は★4なので緑diffの難易度でしょうか。

:::note info
**競プロ典型 90問**についての説明や解答例の目次は[こちらの記事](https://qiita.com/nabata/items/2872fc1485f24ee2865a)をご覧ください
:::

## 001 - Yokan Party（★4）

### 公式リンク

- [問題](https://atcoder.jp/contests/typical90/tasks/typical90_a)
- [解説](https://github.com/E869120/kyopro_educational_90/blob/main/editorial/001.jpg)
- [C++コード](https://github.com/E869120/kyopro_educational_90/blob/main/sol/001.cpp)

### 言語

- Python (3.8.2) / PyPy3 (7.3.0)

PyPy3 (7.3.0)だと100msec程度ですが、Python (3.8.2)でも500msecは切ります。

### 解答例

```
# 条件を満たすした分割が可能か判定する貪欲法の関数
def can_cut(req_length, req_cut, length_list):
    # req_length:求められる長さ
    # req_cut：求められる分割数
    # length_list：切れ目毎の長さ
    cut = 0  # 分割数
    length = 0  # 最後に分割してからの長さ
    for ix in range(0, len(length_list) - 1):
        if length + length_list[ix] >= req_length and cut < req_cut:  # 分割可能か判定
            cut += 1
            length = 0
        else:  # 今の切れ目では分割できない
            length += length_list[ix]
    length += length_list[-1]  # 最後の切れ目以降の長さを加える
    return cut == req_cut and length >= req_length


# 入力
N, L = map(int, input().split())
K = int(input())
A = list(map(int, input().split()))

# 処理しやすいようにAを切れ目毎の長さに変換しておく
A.append(L)
for i in range(len(A) - 1, 0, -1):
    A[i] -= A[i - 1]

# 二分探索によって最大となるスコアを求める
score = 0
low = 1
high = L - 1
while True:
    score = (low + high) // 2
    if can_cut(score, K, A):  # 分割できるためscore以上が最大値と確定する
        if low == score:
            break
        low = score
    else:  # 分割できないためscore未満が最大値と確定する
        if high == score:
            break
        high = score
```

Kの値もNの値も100000とそこまで大きくないですが、総当たりすると間に合わないため、[二分探索](https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2)を用いています。たとえば羊羹の長さが100であれば、解のとりうる最小値を1、解のとりうる最大値は99とした二分探索で処理できます。

**そのスコアの取得が可能かどうか** は[貪欲法](https://ja.wikipedia.org/wiki/%E8%B2%AA%E6%AC%B2%E6%B3%95)で求めています。長さのリストを先頭から順番に操作して分割可能かどうかを判定しています。解答例の関数 **can_cut** です。

## 宣伝

[SupershipのQiita Organization](https://qiita.com/organizations/supership-inc)を合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。

Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方は[Supership株式会社 採用サイト](https://supership.jp/recruit/)よりご確認ください。
docker × Laravel × MysqlでDB接続したーい！

# はじめに
LaravelでDBに接続をするのに苦戦したので、備忘録として詰まったところと注意点を記載する。
dockerを使って構築したローカル環境において、LaravelでDB接続をする時に詰まった方の一助になれば幸いです。

# 環境
docker
Laravel6.2系
Mysql
# 接続できなかった原因
1.envファイルのDB_HOSTの値にポート番号を指定していた。
　dockerで構築した環境の場合、ポート番号ではなくdocker-compose.ymlで定義したサービス名を指定しなくてはならない。

2.envファイルのDB_PASSWORDが空欄だった。
　docker-compose.ymlで定義したパスワードを指定しなくてはならない。

3.キャッシュのクリアを行っていなかった。
　envファイルの更新を行った時はキャッシュのクリアが必須。
　php artisan config:cache

# まとめ
これでも接続できない時は、envファイルやdatabase.phpを改めてチェックしよう。
【Android】RoomのInstrumentTestでInstrumentation run failed due to 'Process crashed.'

AndroidのRoomでInstrumentTestを行っていたところ、以下のエラーが出ました。
その時の解決のメモです。

```
Instrumentation run failed due to 'Process crashed.'
```

悲しいことにエラー文がこれだけでした。

エラー文で検索したところ、以下のstackoverflowの質問を見つけました。

https://stackoverflow.com/questions/52605267/instrumentation-run-failed-due-to-process-crashed

いくつか回答があるので、一通り全部読みます。すると以下の回答を発見。
(ちなみにこの時点で、○○の依存を追加しよう！みたいな回答もありますが、エラー内容が分かっていないのに行うのは危険です。)

>In my case, the android test console only showed the error above without any details.
>But in the logcat, the full error was shown.

実機テストではテストコンソールにエラーの詳細は表示されない。ただしlogcatには詳細が表示されるみたい。なんとなくそりゃそうかって感じです。

logcatを確認したところ、以下のエラー文を発見。

```
Didn't find class "androidx.test.runner.AndroidJUnitRunner"
```

`build.gradle`でテストランナーを以下のように設定していますが、このクラスが発見できないことが予想されます。

```
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
```

https://stackoverflow.com/questions/52717048/didnt-find-class-android-support-test-runner-androidjunitrunner

https://developer.android.com/training/testing/junit-runner?hl=ja

これでした

```gradle
androidTestImplementation "androidx.test.ext:junit:1.1.5"
androidTestImplementation "androidx.test:runner:1.5.2" //追加
```
Salesforce オブジェクトIDについて

# 概要

- SalesforceのオブジェクトID（カスタムオブジェクトID）について情報をまとめる。

# 前提

- SFはDBを構成するものの名前が独特である。
    - テーブルのことを、オブジェクトと呼ぶ。
    - 行のことを、レコードと呼ぶ。
    - 列のことを、フィールドと呼ぶ。
    - カラムのことを、項目と呼ぶ。
- オブジェクトは3種類存在する。
    - 標準オブジェクト：Salesforceが予め用意しているオブジェクト
    - カスタムオブジェクト：Salesforceユーザーが同時に作成するオブジェクト
    - 外部オブジェクト：カスタムオブジェクトの親戚で、Salesforce以外になるデータをマッピングするためのオブジェクト

# オブジェクトIDと形式

- DBにも主キーの値があるように、SFのオブジェクトにもレコードを一意に特定するための項目が存在し、オブジェクトID（カスタムオブジェクトID）と呼ぶ。
- さらにSFでレコードが新規登録された時に自動でオブジェクトIDは発行される。
- このオブジェクトIDは「15文字の大文字と小文字が区別される形式」と「18文字の大文字と小文字が区別されない形式」の2種類の形式が存在する。
- 2.5以降のバージョンでは18文字の方のみ使う事ができる。
- 18文字の方の構成は「15文字形式」＋「3文字のエンコード用文字列」で構成されている。
- 18文字形式から15文字形式に変更したい場合、下記のツールを使うか、単純に末尾の3桁を削除すれば良い。
    - [https://www.adminbooster.com/tool/15to18](https://www.adminbooster.com/tool/15to18)

# オブジェクトIDの確認方法

- オブジェクトIDは下記の様にして確認する事ができる。例として「取引先」の一つのレコードのオブジェクトIDを確認してみる。（同様の方法でカスタムオブジェクトIDも確認する事ができる）
    1. Salesforceにログインする
    1. 「サービス」アプリケーションを開く
    1. タブの「取引先」をクリックする
    1. いくつか登録されている任意の「取引先名」をクリックする
    1. 開いたページのURLを確認する
    1. `ドメイン/Foo/Var/Account/000000000000000XXX/view`みたいなURLになっているはずである
    1. `000000000000000XXX`の部分が18文字のオブジェクトIDで、末尾3文字を切り取った`000000000000000`が15文字のオブジェクトIDとなる

# 参考文献

https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/field_types.htm

↑「ID データ型」部分

https://help.salesforce.com/s/articleView?id=000383751&type=1

https://www.adminbooster.com/tool/15to18

https://help.salesforce.com/s/articleView?id=000384487&type=1

https://help.salesforce.com/s/articleView?id=000385008&type=1
HERE Maps × Google Spreadsheetsで簡単にマッピングしてみた

### できたらローコードで実現したい、私。
ということで、今日はGoogle Spreadsheetsをデータベース代わりにして、誰でも位置情報を追記できる仕組みを作ってみた。
今日は以下の茨城県神栖市のオープンデータを使って作ってみた。

https://www.city.kamisu.ibaraki.jp/opendata/1003195/1003198.html

Googleのスプレットシートはここに置いてあります。
https://docs.google.com/spreadsheets/d/1D1h0ct4NclQo28B2tmI1coqh6bhlFWaDvK22ngLNbHU/edit#gid=0

## 実装
この記事を参考にさせてもらいました。

https://qiita.com/champierre/items/e7758b69b39476148492


## 参考記事と違う箇所

#### HERE独自のマーカーの設定が必要なので、、、
以下を参考に、addmakerの設定の変更が必要。

https://developer.here.com/documentation/examples/maps-js/markers/markers-on-the-map

```
       function addMarker(lat,lng) {
       var parisMarker = new H.map.Marker({lat:lat, lng:lng});
       map.addObject(parisMarker);
       }
```

## 実装完了

https://unrivaled-kitsune-ca1460.netlify.app/

![スクリーンショット 2023-01-13 13.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858388/9e5b9b74-a3cb-3ac0-0158-49436d33338d.png)
UnaryOperator interface

given argument, return が同じtype
default void replaceAll​(UnaryOperator<E> operator)と組み合わせて使用
するサンプルも載せる
```java
        UnaryOperator<String> u = (x) -> x + ",";
        System.out.println(u.apply("3"));
        
        ArrayList<String> l = new ArrayList<>();
        l.add("1");
        l.add("2");
        l.replaceAll(u);
        for(String str:l){
            System.out.println(str);
        }
```
```
3,
1,
2,
```
何故、率直な発言が出来ないのか？【心理的安全性シリーズ 1/3】

「率直な発言が出来ない」という事は、多くの人にある。
---
懸念を抱いても、上司に話すのは　無理だと感じた経験が少なくとも一度はある。
ある市場調査結果では、__85%__ の人々がそう回答している。

「ミーティングでは、他の人が気づかない問題点が、私にはとてもはっきり見えることがよくあった。」
「だが、間違っている事を恐れて、何も言わず、傍観する事を覚えた。」
「他の人を敵にまわさないためだ。」
「私は、発言して愚かに見えてしまうかもしれないリスクを冒すより、
安全地帯に留まる事によって、仕事を維持したいと思った。」


元アップルの幹部の言葉である。

「率直な発言」は、どのような影響を与えているのだろうか?
---
エイミーエドモンドソンは、「率直な発言」の重要性に気づいた経緯を次のように説明している。

高い成果を上げるチームは、ミスが少ないという仮説を検証した所、
有能なチーム程、ミスを多くしているという事がわかった。


有能なチーム程、ミスが多いのは、何故か分析した所、
__実は、有能なチームは、ミスが多いのではなく、ミスの報告数が多かった。__
__率直に発言が出来るようなチームだから、高い成果を出せるという事を発見した。__
(逆を言うと、「率直な発言が出来ない」と言う事が業務にマイナスの影響を与えていると言う事である。)

ハーバードビジネススクール教授、エイミー・C・エドモンドソンは、
__「心理的安全性」の定義を「対人関係のリスクをとっても安全だと信じられる職場環境」としている。__


皆さんは、「率直な発言」を受け入れてもらえないと感じた事は、ありますか？
「率直な発言」をしても、たぶん、聞いてもらえないだろうな。と感じて、発言しなかった事は、あるかと思います。
その時、「対人関係のリスク」を取ってまで、発言する程の事ではないと考えたのではないでしょうか。

ただ、トロイの木馬の裏話を聞いても、そう考えるでしょうか？
---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920213/a70042ba-1f19-72bf-b41f-4c8579966174.png)
木馬の中に兵士を忍び込ませ、敵国に攻め込んだ話です。

裏話として、悲劇の王女カッサンドラの話があります。
---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920213/6b506fa6-1d0c-7177-ab2b-3d4eb3841746.png)

彼女は、予言の力を授かったが、その予言を信じてもらえないという呪いもあわせてかけられた。
トロイの木馬をイリオス市民が市内に運び込もうとした時、破滅につながることを予言して抗議したが、誰も信じなかった。
「率直な発言」が受け入れてもらえなかった。

王女カッサンドラの「率直な発言」を聞いていれば、国は滅びなかった。
<font color="red">「対人関係のリスク」を取ってでも、発言すべき事は、あるという事です。
<font color="red">そして、「率直な発言」をばかにせず、「素直に耳を傾ける」必要があるという事です。

対人関係のリスクとは
---
「率直な発言」をする事によって、
__「無知だと思われたり」「無能だと思われたり」「邪魔をしていると思われたり」「否定的だと思われたり」__
する可能性がある事を指します。

__Ⅰ　無知だと思われる不安__
__Ⅱ　無能だと思われる不安__
__Ⅲ　邪魔をしていると思われる不安__
__Ⅳ　ネガティブだと思われる不安__

__Ⅰ　無知だと思われる不安__

業務で知らないことやわからないことを聞く際、「こんなことも知らないのか」と思われないか不安になり、上司や同僚に必要な質問ができなくなってしまう。相談することが不安になり、従業員同士のコミュニケーションがなくなっていく。
「分からない」と言えない。
知らない事や不明点を聞く事が出来ない。

__Ⅱ　無能だと思われる不安__

業務で失敗した際、「こんなこともできないのか」と思われないか不安になり、
ミスを報告しなかったり、自分の失敗を認めなかったりするようになる。
失敗やミスを隠したくなる。
過ちを認めると責められると感じる。

__Ⅲ　邪魔をしていると思われる不安__

ミーティングの時に、自分の発言で議論が長引いたり本題から外れたりした際、上司や同僚から「いつも議論の邪魔をしてくる」と思われないか不安に駆られてしまう。自分から提案や発言をしなくなっていくため、新たなアイデアやイノベーションも生まれにくくなる。
自分の考えが言えない。
新しいアイディアを出しても、否定されると感じる。

__Ⅳ　ネガティブだと思われる不安__

現状の改善について提案しようと思った際、「いつも他人の意見を否定する」と思われないか不安になってしまう。上司や同僚に否定的に捉えられる可能性があると、発言をためらったり、本当に重要な指摘をしなくなったりする。やがて常に自分を隠して仕事をするようになる。
間違いを指摘しにくい。
問題を指摘しにくい。

誰もが率直な発言が出来るように取り組む事は、
時間がかかりすぎて、非効率ではないか？
---
著者は、心理的安全性は効率性に役立つ可能性があり、時間の浪費ではなく節約になるとしています。
__時間を節約できるかどうかは、あなた次第です。__


ハーバード大学で組織行動学を研究している
エイミー・エドモンドソン教授（Amy C. Edmondson）の

・TEDトーク
・恐れのない組織 「心理的安全性」が学習・イノベーション・成長をもたらす
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920213/8ac3a678-a3fa-2f96-96f1-b6f8271c94e4.png)

を参考にしました。

次に続く
組織の力学【心理的安全性シリーズ 2/3】
https://qiita.com/kimuni-i/items/8d4268442ba2d21d8af4

ダイバーシティーインクルージョンとは？【心理的安全性シリーズ 3/3】
https://qiita.com/kimuni-i/items/c84777691aaf06e20461
Value Stream Mappingをやってみた

こんちは〜。
おせちだと伊達巻が一番好きなとよしーです。

あけましておめでとうございます。2023年ですね。
今年の抱負は、「最近どう？元気？」と気軽に声をかけられる人間になることです。
「久々の人から連絡が来たと思ったらマルチ商法だった」のパターンと間違えられないように気をつけます。


さて、この記事では年始にチーム内でValue Stream Mappingをやってみたことを紹介したいと思います。

## Value Stream Mappingってなんや？
製品やサービス、機能を顧客に届けるために必要なプロセスを可視化するためのツールです

引用：https://dev.classmethod.jp/articles/value-stream-mapping/

## なぜやるのか？
- 言語化できていない課題が見つかると思ったから
- 単純にいまのチームメンバーで実験的にやってみたかったから

## 前提条件
- 構成
    - 開発者 3名
    - マネージャー 1名
    - ファシリテーター とよしー
- ツール：Miro
- かかった時間：2時間

## やったこと
本当は開発プロセス全体でやると効果的なのかもしれないですが、スモールスタートということでCustomerSuccessチームから来る依頼のプロセスでValue Stream Mappingをしました。


まずスタートとゴールを決める
↓
スタートはユーザーから依頼が来ることに決定
↓
ゴールはユーザーが満足することに決定
↓
各プロセスを書く
↓
チーム名と必要な人数を書く （例：Dev1 = Devが1名）
↓
リードタイムを書く
※ 前のプロセスの完了から該当プロセスの完了までにかかる時間
↓
プロセスタイムを書く
※ 該当プロセス自体にかかる時間
↓
同一チームが連続して行うプロセスの場合は実線、チームが変わる場合は破線でつなぐ
↓
各プロセスのおおよその手戻り率を書く
↓
無駄にマークをつける
※ [こちらの記事](https://dev.classmethod.jp/articles/value-stream-mapping/)を参考にさせていただきました
↓
無駄が多い部分の改善案をチームで相談する
↓
ふりかえり



## 結果/わかったこと
- 待ちの無駄（W）が発生しているプロセスは他チームとのやりとりが関わっている部分に多いことがわかった
    - 開発者のレビューの待ち問題に関しては、レビューしやすくするように粒度を小さくするように改善していく案が出た
    - CustomerSuccessとのやりとりでの待ち問題に関しては、空中戦ではなく適宜直接話す改善案が出た
- 手戻り率が30%を超えている箇所が、全体のプロセスで35%以上あった
- 今回作られたValue Stream Mappingが、オンボーディングで役に立つのではという意見がメンバーから出た
    - これは自分もはっとさせられた


## まとめ
以上、Value Stream Mappingをやってみたの記事でした。

最近、なんとなくですが、
「あ〜なんか課題っぽいな〜」
と
「これは課題だ！」
との間には結構差があるのではないかと思っています。
そんなぼやけている課題をクリアな課題にしていくのに必要なのは、
課題の周辺にある数値だったり定性的なデータになると私は考えています。
上記のようなプロセスをふむと、課題に対する納得感も醸成されるので、当事者意識も持ちやすくなるのではないでしょうか。

Value Stream Mappingはその一助にもなるワークだと思うので個人的におすすめです。
開催にあたってまとまった時間は必要になるかもしれませんが、ぜひやってみてください。
Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure ADグループアカウント」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Azure ADグループアカウント」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure での ID とガバナンスの管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-identities-governance/)
◇対応するモジュール
[グループ アカウントを作成する](https://learn.microsoft.com/ja-jp/training/modules/configure-user-group-accounts/5-create)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure ADユーザアカウントの一括操作」](https://qiita.com/fsd-jume/items/c80821f5dc17449cee14)

## Azure ADグループアカウント
### Azure ADのグループ
**2種類のグループアカウントと3種類のメンバーシップを定義可能**

### グループアカウント
**◆セキュリティグループ**
・共有リソースに対するユーザとコンピュータのアクセスを管理するために使用
・特定のセキュリティポリシーを適用させたセキュリティグループを作成
⇒グループ内の全メンバーに同じアクセス許可を適用可能
・Azure AD管理者のみが実装可能
・グループのメンバーに含めることができるもの
⇒ユーザ/デバイス/他のグループ/サービスプリンシパル
・グループ所有者に含めることができるもの
⇒ユーザ/サービスプリンシパル

**◆Microsoft365グループ**
・共同作業の機会を提供
・共有メールボックス、カレンダー、ファイル、SharePointサイトなどへアクセス可能
・Azure AD組織外のゲストユーザにグループへのアクセス権付与も可能
・通常のユーザとAzure AD管理者のどちらも使用可能
・グループのメンバーに含めることができるもの
⇒ユーザ
・グループ所有者に含めることができるもの
⇒ユーザ/サービスプリンシパル

### メンバーシップ
・グループへのメンバー追加方法を選択可能

**◆割り当て済み**
・特定のユーザを追加し、固有のアクセス許可を付与可能

**◆動的ユーザ**
・動的メンバーシップルールを使用してグループメンバーを自動的に追加/削除可能
・メンバーの属性が変わると、ルール要件を満たしているか判定を実施
　-満たしている場合：グループに追加
　-満たさなくなった場合：削除

**◆動的デバイス**
・セキュリティグループのみ選択可能
・動的メンバーシップルールを使用して自動的にデバイスを追加/削除可能
・デバイスの属性が変わると、ルール要件を満たしているか判定を実施
　-満たしている場合：グループに追加
　-満たさなくなった場合：削除

## 次の学習内容
**◆Azure AD管理単位**

https://qiita.com/fsd-jume/items/10d2e9a9c689aeeb6662

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
Pythonで文字列から、日本語だけを消す方法

# 課題
Pythonでの出力結果で、英語だけの情報を欲しいのに日本語の情報も混ざってしまうという課題がありました。
そこで出力結果の日本語と、日本語に関連する「。」と「、」を削除しようと考えました。
しかし文字列から日本語、「。」、「、」だけを消す方法が探しにくかったので、ここで共有させていただきます。

# 結論
re.sub()を使って、該当する文字列を空文字に置換する。

# コード
```python
import re

text = " 今日は本当に素晴らしい一日でした。朝起きたときから、心が躍っていました。今日は自分のやりたいことに挑戦する日です。Today was truly a wonderful day. From the moment I woke up this morning, my heart was racing. Today is the day I challenge myself to do what I want to do."

# 日本語と「。」「、」だけを削除
result = re.sub(r'[\u3040-\u309f\u30a0-\u30ff\u4e00-\u9faf|、|。]', "", text)
print(result)

# output>>> Today was truly a wonderful day. From the moment I woke up this morning, my heart was racing. Today is the day I challenge myself to do what I want to do.

```
:::note info
注意点：
reという正規表現を扱うためのライブラリを忘れずにインポートしておく。
:::
解説：
`` `[\u3040-\u309f\u30a0-\u30ff\u4e00-\u9faf]` ``は、日本語の文字を表すUnicodeのコード範囲を表します。
`|、|。`で、置換する対象として「、」「。」を追加しています。

↓Unicodeのコード範囲について、参考になったサイト

https://tamasoft.co.jp/DocChecker/hlp/glossary.html

https://qiita.com/nwsoyogi/items/ab87b82ed41932095a21

# まとめ

今回はPythonで文字列から、日本語と、日本語と関連する「、」と「。」だけを消す方法を紹介しました！
日本語以外でも、「re.sub()を使って、該当する文字列を空文字に置換する。」という考え方は役に立つと思うので、ぜひ使ってみてください！

少しでもお役に立てれば、幸いです！
最後までお読みいただき、ありがとうございました！
GlueジョブからCloudWatchLogsへ出力されるログ転送量の削減

## Glueジョブに関係するCloudWatchLogsの料金
GlueジョブからCloudWatchLogsへログが転送されるときに、二つの料金が発生します。
[AWS公式ドキュメント](https://aws.amazon.com/jp/cloudwatch/pricing/?nc1=h_ls)

- ログの保管量：1Gbあたり、0.033$
- ログの転送量：1Gbあたり、0.76$

ここで、ログの保管量は、それほど高くはないが、ログの転送量は高額のため、
できる限りログの転送量を減らしたほうがいい

## ログの転送量を減らすための設定
以下のオプションを追加するのみ。
「WARN」の設定は、主に「WARNログ」「ERROEログ」が出力される実装となり、「INFOログ」は出力されなくなるため、ログの転送量を大幅に減らすことができる。
Glueジョブを運用していく中で、INFOログは不要であることが多いため、基本的には問題なしの場面が多い。（検証時に多少閲覧するくらいです）
- sc.setLogLevel("WARN")
```python
import os
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.dynamicframe import DynamicFrame

args = common.get_args(sys.argv)
sc = SparkContext()
sc.setLogLevel("WARN") # ← 設定はこちらのみ
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args["JOB_NAME"], args)
```
Flutter/Riverpod StateNotifierProviderでListを管理するときのUtils備忘録

# はじめに
　StateNotifierProvider便利ですよね〜。やっぱり大体の解説記事でコレ使ってますからね。
まず使って驚いたのですが、stateを更新するときは新しいListを作成しないといけないんですよね。（Riverpod完全理解民からしたら当たり前）
stateにinsert()したら画面が更新されなくてアレ??なんてことも見かけます。そんなときにいちいち値の追加や削除を書くのは時間がかかります（プログラマーたるもの怠惰であれ）。そこで、この記事ではstate用の```insert()```,```add()```,```remove()```を作りたいと思います。もちろん画面も更新されますよ。

# ベースとなるコード
```dart
@immutable
class Todo {
  const Todo({required this.id, required this.description, required this.completed});

  final String id;
  final String description;
  final bool completed;

  Todo copyWith({String? id, String? description, bool? completed}) {
    return Todo(
      id: id ?? this.id,
      description: description ?? this.description,
      completed: completed ?? this.completed,
    );
  }
}

class TodosNotifier extends StateNotifier<List<Todo>> {
  TodosNotifier(): super([]);

  void addTodo(Todo todo) {
    state = [...state, todo];
  }

  void removeTodo(String todoId) {
    state = [
      for (final todo in state)
        if (todo.id != todoId) todo,
    ];
  }

  void toggle(String todoId) {
    state = [
      for (final todo in state)
        if (todo.id == todoId)
          todo.copyWith(completed: !todo.completed)
        else
          todo,
    ];
  }
}

final todosProvider = StateNotifierProvider<TodosNotifier, List<Todo>>((ref) {
  return TodosNotifier();
});
```
:::note
参考：https://docs-v2.riverpod.dev/docs/providers/state_notifier_provider
閲覧日：2023/1/13
:::

このコードの中でもadd()でremove()は実装されていますね。
ですが、備忘録なので一応実装方法を書いておきます。

# insert()
```dart
void _insert(Todo todo, int index) {
    state = [
        ...state.sublist(0, index),
        todo,
        ...state.sublist(index),
    ];
}
```

# add()
```dart
void _add(Todo todo) {
    state = [...state, todo];
}
```

# remove()
```dart
void _remove(int index) {
    state = [
        ...state.sublist(0, index),
        ...state.sublist(index + 1),
    ];
}
```

# 以上です。
　この記事に書いてあるコード自体は細心の注意を払って書いておりますが、動作の確認はしておりませんので、エラーが出たら直して使ってください。それでは！！

# 追記
https://docs-v2.riverpod.dev/docs/providers/notifier_provider
なんか、公式のサイトに知らんやつがいた。
その名も、「NotifierProvider」！！
誰か使ってないかな？
MySQLが起動しないのを解決したメモ【mac/brew】

brewでインストールしたmysqlが起動しなくなってしまいました。
調べて上位に出てくる方法では解決できなかったのでメモしておきます。

### TL;DR
アップグレードに失敗していたので、下記で解消
```sh
mysqld --upgrade=MINIMAL
```

### 前提
```sh
$ mysql -V
mysql  Ver 8.0.31 for macos13.0 on arm64 (Homebrew)
```

### 状況
`mysql -u root`すると、
```
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
```

`sudo mysql.server start`すると、
```
ERROR! The server quit without updating PID file
```
と言われた。
`ps aux | grep mysql`すると、そもそも起動していない様子

### 思い当たること
`brew upgrade`した

### 試したけどダメだったこと
`/tmp/mysql.sock`を作る
```sh
sudo touch /tmp/mysql.sock
```

PIDファイルを作る
```sh
touch /opt/homebrew/var/mysql/***.local.pid
```

PIDファイルの所有権を変える
```sh
sudo chown -R _mysql:_mysql /opt/homebrew/var/mysql/
```

エラー内容で検索すると出てくるのはこの辺りかな、と思います

### 解決策
ちゃんとエラーを見てみます
```sh
less /opt/homebrew/var/mysql/***.local.err
```

```
2023-01-12T13:10:56.863867Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /opt/homebrew/var/mysql/ is case insensitive
2023-01-12T13:10:57.087353Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2023-01-12T13:11:44.613924Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2023-01-12T13:11:48.080019Z 4 [System] [MY-013381] [Server] Server upgrade from '80030' to '80031' started.
2023-01-12T13:12:13.662641Z 4 [ERROR] [MY-013178] [Server] Execution of server-side SQL statement 'INSERT IGNORE INTO mysql.db VALUES ('localhost', 'performance_schema', 'mysql.session','Y','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N'); ' failed with error code = 1136, error message = 'Column count doesn't match value count at row 1'.
2023-01-12T13:12:13.664626Z 0 [ERROR] [MY-013380] [Server] Failed to upgrade server.
2023-01-12T13:12:13.664640Z 0 [ERROR] [MY-010119] [Server] Aborting
```
アップグレードしようとして、何やら失敗しているようです

一旦アップグレードせずに起動する方法を探したところ、下記で不要なパフォーマンススキーマのアップグレードを回避できそうです
参考：https://dev.mysql.com/doc/refman/8.0/ja/upgrading-what-is-upgraded.html
```sh
mysqld --upgrade=MINIMAL
```

一度上記コマンドで実行したところ、その後は普通に`mysql -u root`でアクセスできるようになりました。