OmniAICreator/Qiita-1.07M huggingface dataset:
Fizz Buzz（paizaランク C 相当）：Python3解答例

## 問題
- 整数 N が入力として与えられます。
1からNまでの整数を1から順に表示してください。

- ただし、表示しようとしている数値が、

1. 3の倍数かつ5の倍数のときには、"Fizz Buzz"
2. 3の倍数のときには、"Fizz"
3. 5の倍数のときには、"Buzz"

を数値の代わりに表示してください。

```diff_python
N = int(input())

for i in range(1, N + 1):
    #3の倍数かつ5の倍数（15の倍数）のとき
    if i % 3 == i % 5 == 0:
        print("Fizz Buzz")

    #3の倍数のときには、"Fizz"    
    elif i % 3 == 0:
        print("Fizz")

    #5の倍数のときには、"Buzz"
    elif i % 5 == 0:
        print("Buzz")

    #3の倍数、5の倍数、１５の倍数以外のときには、数字を出力
    else:
        print(i)

```

- i % 3 == i % 5 == 0 は「i を 3 で割った余りと i を 5 で割った余りが共通して 0 である」という条件式です。
- 
15の倍数とすることも可能です。
- i % 3 == i % 5 == 0 の条件式は最初に置く必要があることに注意してください。
たとえば、この条件式が i % 3 == 0 の後の elif 節にある場合、
3 の倍数はすべて i % 3 == 0 で引っかかってしまいます。
そのため、i % 3 == i % 5 == 0 内の処理がおこなわれなくなってしまいます。

## リストを用いた解答例

```diff_python
N = int(input())

def is_FizzBuzz(num):
    return (num % 3 == 0, num % 5 == 0)

results = []
for i in range(1, N + 1):
    Fizz, Buzz = is_FizzBuzz(i)
    if Fizz and Buzz:
        results.append("Fizz Buzz")
    elif Fizz:
        results.append("Fizz")
    elif Buzz:
        results.append("Buzz")
    else:
        results.append(i)

for result in results:
    print(result)
```

results = []のリストへ
1. 3の倍数かつ5の倍数のときには、"Fizz Buzz"
2. 3の倍数のときには、"Fizz"
3. 5の倍数のときには、"Buzz"
4. 3の倍数、5の倍数以外は数値

を追加して、
for文を用いて出力していきます。
【Salesforce】Winter'25 3つだけピックアップ

![01ロゴ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/a098ef04-b08f-9e85-7e5d-a5212d728229.jpeg)

2024/8/8からWinter'25 プレリリース組織のサインアップ開始されました。この記事では、プレリリース組織で個人的に、SalesforceのWinter'25の気になった機能を3つだけピックアップして紹介しています。

## Winter'25のリリース
Salesforceは、毎年3回（春、夏、冬）新しい機能や改善をリリースして、機能の追加や使い勝手が向上しています。Winter'25のリリースでも、効率が高まったり、見た目に関するアップデートが含まれています。
先行して新機能を試すには、プレリリース組織を利用するのが推進されています。

https://admin.salesforce.com/blog/2024/admin-winter-25-release-dates-countdown

## プレリリース組織とは
Winter '25 の機能を先行して試すことができるプレリリース版Developer Edition環境です。Summer '24 のプレリリース組織をすでにお持ちの場合は、その組織に再度ログインできます。

[プレリリース版](https://www.salesforce.com/form/signup/prerelease-winter25/?_ga=2.191424233.238125248.1723203529-1504051416.1719646367&_gl=1*117sur8*_ga*MTUwNDA1MTQxNi4xNzE5NjQ2MzY3*_ga_EE9XB9ZV8F*MTcyMzI0MDI1Ny4xLjAuMTcyMzI0MDI1Ny4wLjAuMA..)を取得していきます。

早速、Winter'25で追加された新機能について確認してみましょう。

## Enhanced User List View
Salesforceでは、リードや取引先、ケースなど、他のオブジェクトに対してリストビューが存在します。今回のアップデートで、ユーザーのリストビューも他のオブジェクトと同じように確認・設定できるようになります。

有効にするには、設定>>ユーザー管理設定から「Enhanced User List View」を有効化するだけす。
![02ユーザー管理設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/de859a23-f4df-9064-8217-ea8d2c2adfe6.png)

実際のユーザーのリストビューです。
たとえば、リストビューでのデータの並べ替え、フィルタの適用、カスタムビューの作成といった操作が、ユーザーリストビューでも簡単にできるようになります。
デフォルトは「最近参照〜」でしたが、管理できる範囲であればピンは「すべてのユーザー」で良さそうでかと思いました。
![03ユーザーリストビュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/23959f40-68e5-4944-b695-5b878fc595b7.png)

## Object Access
これまでは、プロファイルや権限セットの画面からどのオブジェクトにアクセス権があるかを確認することしかできませんでした。

次からはオブジェクトマネージャーの各オブジェクトから、オブジェクトへのアクセス権の状態を確認できるようになり、権限セット、権限セットグループ、プロファイルによって付与されたアクセス権のレベルを、直接確認できるようになります。
![04オブジェクトアクセス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/2037897d-0952-3898-58e4-df13cda97fe7.png)

## 設定のＵＩ変更
地味に、「右上の歯車マーク」こと設定のUIも変更になるようです。

### before
![05設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/82c2956c-4838-5d8e-95f4-1769ed9e046c.png)

 ### after
![06SetUpMenu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/064eeb92-7a39-fd39-8d00-2fb8d0878a6f.png)

いかがでしたでしょうか？
Winter '25リリースでは、Salesforceの操作性と機能性がさらに向上し、特にユーザーリストビューの拡張モードやオブジェクトマネージャーでのアクセス権確認といった新しい機能が追加されています。

今回は、プレリリース組織を利用して、Winter '25から3つだけ紹介しました。
他にも、Winter '25のリリースは、Salesforceの機能やシステム管理者の使い勝手をさらに向上させるためのアップデートが含まれていそうでした。
今後も新しい機能を触って紹介していきます！
エスケープ文字と表示の仕方

Kotlinのエスケープ文字は例えば下記の種類がある。バックスラッシュを使用することによって記号や改行などを表現できる。

```kotlin
println("The quick \"brown fox\" jumps\n over the lazy dog")
// The quick "brown fox" jumps
//  over the lazy dog

println("このお魚は\\400\$です。")
// このお魚は\400$です。

val country = "東京"
println("私は${country}出身です。")
// 私は東京出身です。
```

絵文字（特殊文字）もUnicodeを使用すれば表現可能です。三重クォートはインデントもそのまま表示されるので、扱いにくい。
```kotlin
println("\uD83D\uDE42\u200D \uD83D\uDE3A");
// 🙂‍ 😺

println("\\uD83D\\uDE42\\u200D \\uD83D\\uDE3A");
// \uD83D\uDE42\u200D \uD83D\uDE3A

println("""Kotlinで
        三重クォートを
        使用した表示です。""")
// Kotlinで
//         三重クォートを
//         使用した表示です。
```
#### 参考
https://kk90info.com/%E3%80%90kotlin%E5%85%A5%E9%96%80%E3%80%91%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E3%83%BB%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E3%81%AB%E9%96%A2%E3%81%97%E3%81%A6%E3%80%9Cwindows/

https://qiita.com/irgaly/items/5decdbf5ed89f9cf2c27
RP2040 zeroの、debugprobe配線

AliExpressから、RP2040-Zero互換の小さいボードを入手した。
これを機会に、debugprobeで使ってみた。以下はその配線
![aaa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782224/cb550f4b-8c00-2488-41b7-1f01da87d7a8.jpeg)

この図に至るまでの詳細
RP2040-Zeroの pin layout
https://www.waveshare.com/w/upload/2/2b/RP2040-Zero-details-7.jpg
![RP2040-Zero-details-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782224/7beb5cb6-80e2-cd5b-a34b-c0615852b05c.jpeg)

debugprobeの配線：左側がdebugprobe(本家picoの場合)で、右がターゲット
https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf
「Debug with a second Pico or Pico 2」の章から引用
![debugprobe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782224/c9235100-5b9d-82db-ad69-777dbcaa0134.png)

上記の図と、picoのGP番号を照合すると GP2～5を接続すれば良いことが分かる。
![Pico-R3-Pinout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782224/8eefe411-4ab4-f038-703a-a2e4dbbc19ff.png)

書き込むファームウェア・ファイルは以下より入手
https://github.com/raspberrypi/debugprobe/releases
ファイル名　debugprobe_on_pico.uf2

参考　Raspberry Pi Picoのピンの電気的な仕様
https://zenn.dev/ythk/articles/ythk-raspico-pins

おまけ
「横一列のpinグリッドがあるので、ブレッドボードで使いにくいなあ～」と最初思ったが、不要なら使わなければ良いだけ、と気が付いた。という事で、縦2列の部分のpinを はんだ付けして使用する。
paizaラーニングレベルアップ問題集の「文字の一致」を色々な言語でやってみた

paiza×Qiita記事投稿キャンペーンということで、paizaラーニングレベルアップ問題集の[文字の一致](https://paiza.jp/works/mondai/d_rank_skillcheck_sample/diff_str)を色々な言語でやってみました。対象は[コードモンスター大図鑑](https://paiza.jp/code_monster)で対応している9言語です。

2024/08/24追記
Perl, Scala, Go, Swiftの4言語を追加いたしました。
- - -
###### 方針
- 文字列$a$を標準入力から受け取る
- 文字列$b$を標準入力から受け取る
- 文字列$a$と文字列$b$が一致していれば`OK`、異なっていれば`NG`と出力する
- - -
###### PHP
```php
<?php
	$a = trim(fgets(STDIN));
	$b = trim(fgets(STDIN));
	echo $a == $b ? "OK\n" : "NG\n";
?>
```
- - -
###### Ruby
```rb
a = gets.chomp
b = gets.chomp
puts a == b ? "OK" : "NG"
```
- - -
###### Java	
```java
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String a = sc.nextLine();
		String b = sc.nextLine();
		sc.close();
		System.out.println(a.equals(b) ? "OK" : "NG");
	}
}
```
- - -
###### Python
```py
a = input()
b = input()
print("OK" if a == b else "NG")
```
- - -
###### C言語
```c
#include <stdio.h>
#include <string.h>

int main(void){
	char a[101];
	scanf("%s", a);
	char b[101];
	scanf("%s", b);
	puts(strcmp(a, b) ? "NG" : "OK");
	return 0;
}
```
- - -
###### C#
```cs
using System;

class Program
{
	static void Main()
	{
		string a = Console.ReadLine();
		string b = Console.ReadLine();
		Console.WriteLine(a.Equals(b) ? "OK" : "NG");
	}
}
```
- - -
###### Javascript
```js
const lines = require("fs").readFileSync("/dev/stdin", "utf8").split("\n");
const a = lines[0];
const b = lines[1];
console.log(a === b ? "OK" : "NG");
```
- - -
###### C++
```cpp
#include <iostream>
using namespace std;

int main(void){
	string a;
	cin >> a;
	string b;
	cin >> b;
	cout << (a == b ? "OK" : "NG") << endl;
	return 0;
}
```
- - -
###### Kotlin
```kotlin
fun main() {
	val a = readLine()
	val b = readLine()
	println(if (a.equals(b)) "OK" else "NG")
}
```
- - -
###### Perl
```pl
chomp(my $a = <STDIN>);
chomp(my $b = <STDIN>);
print $a eq $b ? "OK" : "NG" , "\n";
```
- - -
###### Scala
```scala
import scala.io.StdIn._

object Main extends App{
    val a = readLine()
    val b = readLine()
	println(if (a.equals(b)) "OK" else "NG")
}
```
- - -
###### Go
```go
package main

import "fmt"

func main() {
	var a string
	fmt.Scan(&a)
	var b string
	fmt.Scan(&b)
	if a == b {
	    fmt.Println("OK")
	} else {
        fmt.Println("NG")
    }
}
```
- - -
###### Swift
```swift
import Foundation

let a = readLine()
let b = readLine()
print(a == b ? "OK" : "NG")
```
(UNIO)センサーの値0...1023を0...約5Vに変換してあそぶ(39.0625掛けて8で割る)


参考

https://qiita.com/caa45040/items/755a9b1b2f55c96400a2


https://qiita.com/caa45040/items/09848d08a81b0d157458


x 過去ログを見よ
x 軽量高速化、見やすくした。


小ねた

39.0625 = 2.5 x 2.5 x 2.5 x 2.5
39.0625 = 6.25 x 6.25

10000 = 39.0626 x 256


結果

![o_coq303.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/32ac3f92-1b32-4850-35b8-139cd40329ba.jpeg)



プログラム


```c++


//ADC_0__5_x39_UNO_1

//初期化
void setup() {

  //シリアルポート初期化とメッセージ
  Serial.begin(9600);
  Serial.println("START");

  int s; //センサーの値
  unsigned int vo; //電圧

  s = 1024; //センサーの値を1024

  //センサーの値から電圧に変換(x39.0625/8)
  vo = s;
  vo = ((vo * 39U) + (vo >> 4)) >> 3;

  //センサーの値と電圧を表示
  Serial.print(s);
  Serial.print(',');
  Serial.print((int)vo);
  Serial.println();

}//setup

//メインループ
void loop() {
}//loop


```
robloxでassistant その168

# 概要
robloxでassistantやってみた。
練習問題、やってみた。

# 練習問題
ViewportFrameを使え。

# サンプルコード

```
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local screenGui = Instance.new("ScreenGui")
screenGui.Parent = playerGui
local TweenService = game:GetService("TweenService")
local viewportFrame = Instance.new("ViewportFrame")
viewportFrame.Size = UDim2.new(0.3, 0, 0.4, 0)
viewportFrame.Position = UDim2.new(0, 15, 0, 15)
viewportFrame.BackgroundColor3 = Color3.new(0, 0, 0)
viewportFrame.BorderColor3 = Color3.new(0.6, 0.5, 0.4)
viewportFrame.BorderSizePixel = 2
viewportFrame.BackgroundTransparency = 0.25
viewportFrame.Parent = screenGui
local part = Instance.new("Part")
part.Material = Enum.Material.Concrete
part.Color = Color3.new(0.25, 0.75, 1)
part.Position = Vector3.new(0, 0, 0)
part.Parent = viewportFrame
local viewportCamera = Instance.new("Camera")
viewportFrame.CurrentCamera = viewportCamera
viewportCamera.Parent = viewportFrame
viewportCamera.CFrame = CFrame.new(Vector3.new(0, 2, 12), part.Position)
task.wait(2)
local cameraGoal = {
	CFrame = CFrame.new(Vector3.new(0, 6, 4), part.Position),
}
local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local tween = TweenService:Create(viewportCamera, tweenInfo, cameraGoal)
tween:Play()

```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/93da05b0-f20f-369d-db93-28a35636ad6c.png)


以上。
robloxでassistant その167

# 概要
robloxでassistantやってみた。
練習問題、やってみた。

# 練習問題
DepthOfFieldEffectを使え。

# サンプルコード

```
local depth = Instance.new("DepthOfFieldEffect")
depth.FarIntensity = 1
depth.FocusDistance = 1
depth.InFocusRadius = 30
depth.NearIntensity = 1
depth.Parent = workspace.CurrentCamera
depth.Enabled = true
```

以上。
EventRelation : 行動に招待された人

[Activity(活動)、Task (ToDo)、Event(行動)に戻る](https://qiita.com/Keiji_otsubo/items/6b3602414638bb2bf33d)

+ [行動の招集機能で個人ユーザー以外を指定する方法(公開グループ)](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Yvcpd)

:::note
公開グループの使用は残念ながらアイデアに上がってます

https://ideas.salesforce.com/s/idea/a0B8W00000Gdi6zUAB/group-events-add-invitees-from-public-group
:::



+ [主催者だけを表示させる行動レポートを作成したいです。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLGPS)

:::note
英語ですが回答があります。

There is an easier way to stop the double counting!  In your report, add a filter which has the following criteria:

Event Invitation  equals  False.

You'll notice that the report will only return the assigned person and not the invitees.
https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A7MxRSAV

実際にはこのオブジェクトのIsInvitee項目のことかな。
[EventRelation](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_eventattendee.htm)
:::

+ [「行動」に登録された複数の取引先責任者レコードの取得について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLKVu)

:::note
アクティビティ設定で [複数の取引先責任者を関連付ける] を有効にしてますよね？

この場合はおそらく、２人目からは別のオブジェクトを使って参照関係を作っていると思います。

[EventRelation](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_eventattendee.htm)

２人目からは上記オブジェクトでEventIdをキーに検索してみてください。
取引先責任者はRelationIdのうち 003で始まるIdが取引先責任者です。残念ながら処理を追加しないとできないと思います。
:::

+ [複数の登録がある項目をレポート作成で確認できるようにしたい](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007eqjdL)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/92d313e3-571b-aadb-77c7-0474ecd59fe9.png)

:::note
この項目ですが行動に招待された人( [EventRelation](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_eventattendee.htm) )というオブジェクトのレコードとして保存されています。

このオブジェクトはカスタムレポートタイプでも、レコードトリガーフロー、Apexトリガーでもオブジェクトのオプションとして出てこなんですよね。

ただし、SOQLのクエリーでは使うことができるので、
スケジュールされたApexバッチやスケジュールされたフローで 招待された人 を検索して行動オブジェクトのカスタム項目に名前をカンマ区切りなどで追加はできると思います。

カスタム項目にしてしまえば、レポートにも表示できると思います。
:::
Azure Portal / Graph Explorer

# 概要
(日記)Azure Portalの情報をGraphで参照
[総目次](https://qiita.com/shokkaa/private/7a1633dbf58ddc81f894)

# 前提
- 対象となるAzure EntraIDに、グローバル管理者権限を持つアカウント
AzurePortal > ユーザ > 割り当てられたロール で確認。

# 環境


# Graph Explorer
[Graph Explorer](https://developer.microsoft.com/en-us/graph/graph-explorer)
→ はじめに → 自分のプロファイル → Run Query : 自身の情報が表示される
※上記以外の要求はAuthorization_RequestDeniedが返ってくる

### 権限付与
[Azure Portal](https://portal.azure.com/) → アプリケーション → Graph Explorer 
 → 付与されたアクセス許可の表示 →  ~に管理者の同意を与えます
 → 再ログイン
 
Graph Explorer → 組織内のすべてのユーザー → Run query: ユーザ情報

Note: 応答の中にこんなメッセージが...

"@microsoft.graph.tips": "This request only returns a subset of the resource's properties. Your app will need to use $select to return non-default properties. To find out what other properties are available for this resource see https://learn.microsoft.com/graph/api/resources/user",

# クエリの例
### 情報を限定する・デフォルトで取れない情報を指定する
`https://graph.microsoft.com/v1.0/users?$select=displayName,mail,faxNumber`

# 参照

https://learn.microsoft.com/ja-jp/graph/


https://learn.microsoft.com/ja-jp/graph/permissions-reference
AtCoder [C++]勉強記録 その46

AtCoderで入茶を目指して勉強しています。
勉強を継続するために投稿を始めました。
もともとアカウントを作成していましたが、今年の4月から本格的に勉強を始めました。
一応自分用に解法を書いていますが雑です、自分で読み返して困ったら修正します。
[私のアカウント](https://atcoder.jp/users/nanami_brother)
[解いた問題](https://kenkoooo.com/atcoder/#/table/nanami_brother)
# 本日解いた問題
## C - ±1 Operation 1
[C - ±1 Operation 1](https://atcoder.jp/contests/abc255/tasks/abc255_c)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<int>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll x, a, d, n;
  cin >> x >> a >> d >> n;
  if(d<0){
    ll tmp = a + d * (n-1);
    a = tmp;
    d *= -1;
  }
  ll left = 0, right = n-1;
  while(left<=right){
    ll h = (left+right)/2;
    if(a+d*h<x) left = h + 1;
    else right = h - 1;
  }
  ll res = LLONG_MAX;
  for(ll i = max(0ll, left-5); i <= min(n-1, left+5); i++){
    res = min(abs(a+d*i-x), res);
  }
  cout << res << endl;
}
```
### 解答
`D<0`の場合、`A=A+D(N-1)`、`D=-D`と置き換えることができる。その後、Xに最も近い要素数を二分探索することで結果が求まる。
## C - Filling 3x3 array
[C - Filling 3x3 array](https://atcoder.jp/contests/abc256/tasks/abc256_c)
解答
```C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<int>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll h1, h2, h3, w1, w2, w3;
  cin >> h1 >> h2 >> h3 >> w1 >> w2 >> w3;
  ll res = 0;
  for(ll a = 1; a < h1; a++){
    for(ll b = 1; b < h1-a; b++){
      ll c = h1 - a - b;
      for(ll d  = 1; d < w1-a;d++){
        for(ll e = 1; e < h2-d; e++){
          ll f = h2 - d - e;
          ll g = w1 - a - d;
          ll h = w2 - b - e;
          ll i = w3 - c - f;
          if(min({c,f,g,h,i}) <= 0) continue;
          if(i == h3 - g - h) res++;
        }
      }
    }
  }
  cout << res << endl;
}
```
### 解法
すべての行列において2要素が決まると残りの1要素も確定する。そのため、左上の2×2の行列において、全探索を行うことで結果が求まる。
Azure AI 翻訳 の API で401001 エラーになる

以下ドキュメント通りに REST API の実行を試すとエラーになる

```bash:エラー内容
{"error":{"code":401001,"message":"The request is not authorized because credentials are missing or invalid."}}
```

https://learn.microsoft.com/en-us/azure/ai-services/translator/reference/v3-0-translate#translate-a-single-input

※英語版でもダメなのでドキュメントが仕様に追いついていないのだと思われる

```bash:ドキュメントの curl 例
curl -X POST "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=en&to=zh-Hans" \
-H "Ocp-Apim-Subscription-Key: <client-secret>"  \
-H "Content-Type: application/json; charset=UTF-8" \
-d "[{'Text':'Hello, what is your name?'}]"
```


```bash:修正版 curl(Japan East リージョンのリソースの場合)
curl -X POST "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=en&to=zh-Hans" \
-H "Ocp-Apim-Subscription-Key: <client-secret>"  \
-H "Ocp-Apim-Subscription-Region: japaneast"  \
-H "Content-Type: application/json; charset=UTF-8" \
-d "[{'Text':'Hello, what is your name?'}]"
```

// Cloud Shell での実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232184/7780e225-6e1e-2b03-5863-9147cbcf9a46.png)



後で気づいたけど、こっちのドキュメントにはちゃんと書いてあるのな

https://learn.microsoft.com/en-us/azure/ai-services/translator/reference/v3-0-reference#switzerland-service-endpoints

```bash:正しく動作するcurl例
// Pass secret key and region using headers to a custom endpoint
curl -X POST "https://my-swiss-n.cognitiveservices.azure.com/translator/text/v3.0/translate?to=fr" \
-H "Ocp-Apim-Subscription-Key: xxx" \
-H "Ocp-Apim-Subscription-Region: switzerlandnorth" \
-H "Content-Type: application/json" \
-d "[{'Text':'Hello'}]" -v
```bash:修正版curl
【Ubuntu Desktop 22.04】気合でマウスカーソルを変えてみた

# はじめに
Ubuntu Desktop を使用して作業をするとき、Windows と同じマウスカーソルを使用したかったため気合でマウスカーソルを変更した。

Windows では簡単に `.cur` ファイルを適用すれば変えられるが、Ubuntu ではテーマというものの中に含まれているようで、とても面倒くさかった。

結果的にマウスカーソルを変えることはできたが、文献も少なくかなり面倒だったため、手順を残しておく。


# 元になるデフォルトのカーソルとテーマファイルをコピーする
元となるファイルは、`/usr/share/icons/` ディレクトリに存在している。ここに存在するテーマは、Tweaks の Appearance 内で使用できるものとなっている。

ここにあるテーマディレクトリをユーザーのテーマ領域 `~/.icons/` にコピーし、カーソルを変更する下準備を完了させる。
コピーするものは以下の通り。

- テーマとして認識させるための `*.theme` ファイル
- マウスカーソルの画像が収められている `cursors` ディレクトリ

```bash
# YOUR_THEME ディレクトリを作成
mkdir ~/.icons/YOUR_THEME

# テーマファイルをコピー
cp -ai /usr/share/icons/Yaru/*.theme ~/.icons/YOUR_THEME

# カーソルフォルダをコピー
cp -ai /usr/share/icons/Yaru/cursors ~/.icons/YOUR_THEME/
```

## テーマファイルを書き換える
書き換えると言っても大したことではないが、自分好みな名前とコメントに書き換えておくと後々役立つかもしれない。

```properties
[Icon Theme]
Name=好きな名前
Comment=好きなコメント
```

# Ubuntu で使えるカーソルファイルを用意する
前セクションでコピーしたカーソルフォルダを見ると、「 X11 カーソル」というファイル形式が含まれている。Windows では `.cur` ファイルを直接使えたが、Ubuntu だと X11 カーソルファイルにしないといけない。そのため、変換するという一手間が必要となる。

もし、使用したいカーソルが `X11` なら話は速いが、私が使いたかったのは `.cur` ファイルだったので変換していく。

## X11 カーソルを用意する
1. Windows で使えるような `.cur` ファイルを用意する
2. `.cur` ファイルを `gimp` で ubuntu の X11 カーソルファイルに変換する

このような手順を追うと X11 ファイルに変換できる。

`GNU Image Manipulation Program (gimp)` という、フリーの画像編集ソフトを用いると X11 形式で書き出すことができる。

https://www.gimp.org/

`File > Export` を選択、`Select File Type` から `X11 Mouse Cursor` を選択して `Export` すると良い。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348896/389204be-65e2-04c4-fa5f-0cbf23139ae2.png)

これでカーソルファイルの用意が完了した。


# 気合でファイルを置き換えていく
ここが「気合で」と言っている本編である。ここからは根気のいる作業となっているため頑張ってください。

やることは至ってシンプルで、「コピーしたカーソルファイル」と「変換したカーソルファイル」の画像を見比べ、置き換えていくだけである。
ただ、とにかくファイル数が多い。すべてを見比べてやるのはとても根気がいる作業だった。がんばれ。

## やり方
1. 元ファイルの .cur と置き換えたいファイルの .cur を見比べる
1. 対応が取れていそうなファイルを見つける (どっちの画像もリンク用っぽいなみたいに)
1. 元ファイルの名前をコピーし削除 (ファイル名が重要なため)
1. 新しいファイルをコピーし 3 の名前をペースト
1. 以降繰り返し

# おわり
カーソルファイルの置き換えが終わった方、お疲れ様です！

Ubuntu のカーソルファイルは特殊で、よくわからん文字列で認識されていたり、普通に被ってるファイルもあり、ファイル数が膨大で大変だったと思う。
なんでこんなファイル形式なのかはよくわからないが、Windows のように楽に変えられたらなと思った。

多分そもそもカーソルを Ubuntu で変える人が少ないため、ソースがかなり少なく大変だったが、カーソルを変えるだけで自分だけ感でるし、モチベが上がるのでぜひやってみてください！

お疲れ様でした！
プリザンターでメールによる2段階認証を有効にする

# はじめに
[以前書いた記事](https://qiita.com/maki_s/items/ef3ced920cf6d9db2a47)でプリザンターのメール設定手順を調べていた時に、2段階認証ができるという事を知り試してみました。

https://pleasanter.org/ja/manual/secondary-authentication

## 環境
OS：Windows 11 Pro
DB：SQL Server 2019
プリザンター：1.4.6.4

プリザンターの格納場所は公式の通りです。
```
C:\web\pleasanter\
```



## 前提条件
プリザンターからメールを送信できるように設定する必要があります。
詳細は[以前書いた記事](https://qiita.com/maki_s/items/ef3ced920cf6d9db2a47)を参照ください。

## おおまかな手順
基本的にjsonファイルを編集するだけです。

### 設定内容
1. Mail.jsonの"SupportFrom"にメールアドレスを設定する
2. Security.jsonのModeをNoneからDefaultEnableに変更する

jsonファイルの格納先は以下の通りです。
```
C:\web\pleasanter\Implem.Pleasanter\App_Data\Parameters
```

# 1. Mail.jsonの変更
Mail.jsonの"SupportFrom"にメールアドレスを設定します。

```Mail.json
{
    "SmtpHost": "メールアドレス",
    "SmtpPort": 587,
    "SmtpUserName": "メールアドレス",
    "SmtpPassword": "パスワード",
    "SmtpEnableSsl": true,
    "ServerCertificateValidationCallback": false,
    "SecureSocketOptions": null,
    "FixedFrom": null,
    "AllowedFrom": null,
    "SupportFrom": "\"Pleasanter.org\" <メールアドレス>",
    "InternalDomains": "",
    "Encoding": null,
    "ContentEncoding": null
}
```

# Security.jsonの変更

Security.jsonのModeをNoneからDefaultEnableに変更します。

### 修正前

```Security.json  
"SecondaryAuthentication": {
    "Mode": "None",
    "NotificationType": "Mail",
    "CountTolerances": 1,
    "NotificationMailBcc": false,
    "AuthenticationCodeCharacterType": "Number",
    "AuthenticationCodeLength": 8,
    "AuthenticationCodeExpirationPeriod": 300
}
```

### 修正後

```Security.json  
"SecondaryAuthentication": {
    "Mode": "DefaultEnable",
    "NotificationType": "Mail",
    "CountTolerances": 1,
    "NotificationMailBcc": false,
    "AuthenticationCodeCharacterType": "Number",
    "AuthenticationCodeLength": 8,
    "AuthenticationCodeExpirationPeriod": 300
}
```
設定後はIISの再起動が必要となります。

# 実際に試してみる
再起動後、ログインすると、確認コードを求められます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/be1c49e9-4665-fd08-5a87-4da30434177d.png)

設定したメールアドレスに確認コードが届いているのが確認できます。

```mail.txt
Pleasanterの確認コードには、次のコードをお使いください。
確認コード: 99999999
Pleasanterのご利用ありがとうございます。
```

確認コードをコピペで貼り付けてログインできれば成功です。

# 感想
jsonの設定だけで2段階認証が利用できるので是非活用したい。
MacOSでP4コマンドを使えるようにする

# 前回までのあらすじ
サーバー構築編

https://qiita.com/toki_games/items/b712e9cb70f2fac32ca5

クライアント構築編

https://qiita.com/toki_games/items/a8127270d096dc86052f

# P4コマンドとは
クライアント用のPerforceコマンドです
Gitのgitコマンドのように、PerforceにはP4コマンドというものが存在します
P4コマンドを使用してsyncやsubmitを行うことができます
サーバー操作の場合はP4Dコマンドです

# Windowsでは？
通常Windows版では、GUIをインストールした際に同時にCLIがインストールされますが、MacではCLIは別途インストールする必要があり、またパスを自分で通す必要があります

# P4 CLIをインストールする
https://www.perforce.com/downloads/helix-command-line-client-p4

- FAMILY
MacOS
- PLATFORM
macOS 10.14+(ARM64)
- VERSION
選択不可

helix-core-server.tgzがインストールされるので解凍します
中にはコマンドを使用するためのexecファイルが入っています

# 書き込み権限を付与する
1. ターミナルから、解凍したhelix-core-serverディレクトリまでcdする
1. 以下を実行し、ディレクトリ内の全ファイルに書き込み権限を付与する
```
chmod +x *
```

# /usr/local/binに移動させる
execファイルをbinディレクトリに移動させます
「/usr/local/binとは何ぞや」という方は以下参照

https://qiita.com/valzer0/items/67a4c8bf2b1be0fc825a

ターミナルから以下を実行
 ```
 mv p4 /usr/local/bin
 ```

p4dも使いたい場合は以下も実行
```
mv p4d /usr/local/bin
```
 
# 初期設定
- P4PORTを設定する
```
export P4PORT=ssl:IPアドレス:1666
```
sslを使用している場合は、prefixにsslをつける必要があります
1666はポート番号。別のポートを指定している場合は書き換えます

- 初接続
```
p4
```
上記を実行すると、フィンガープリントの発行をされます
接続を許可するため、再度以下を実行します
```
p4 trust
```

# ユーザー登録
p4コマンドを実行する際に使用するユーザーを登録します
追加する際、clientコマンドを使用する必要があります
以下を実行します
```
p4 client -o Hoge | p4 client -i
```
Hogeは構築した際に作成したユーザー名に置き換えます

この状態で`p4 sync`を実行してみましょう
エラーが出ず、syncできたら成功です

## EX:環境変数を保存したい
ターミナルを再起動する度にP4PORTを毎回設定するのはめんどくさいので、プロファイルに保存させます
P4PORTを設定した後に、以下を実行します
```
source ~/.bash_profile
```
ファイルが存在していないと言われた場合は、下記を実行してファイルを作成し、再度上記のコマンドを実行します
```
touch ~/.bash_profile
```
AWS Well-Architected Frameworkの設計原則をただただ箇条書きで並べた


## モチベーション

公式のページは6つの柱と設計原則のページが分かれており、ざっと一気に見られないのが少しストレスだった。
クラウドプラクティショナーの試験では頻出なのにこのままでは覚えづらいので、ただただ自分のためにまとめた記事となります。
（記事と言っても抜き出しただけですが）

不安な方は試験直前の見直しにご利用ください！

公式のページはこちらです。

https://docs.aws.amazon.com/ja_jp/wellarchitected/latest/framework/the-pillars-of-the-framework.html

## 6つの柱と設計原則

### 運用上の優秀性

- ビジネス成果に基づいてチームを編成する
- オブザーバビリティを実装して実用的なインサイトを取得する
- 可能な限り安全に自動化する
- 小規模かつ可逆的な変更を頻繁に行う
- 運用手順を定期的に改善する
- 障害を想定する
- 運用上のあらゆるイベントやメトリクスから学ぶ
- マネージドサービスを使用する

### セキュリティ

- 強力なアイデンティティ基盤を実装する
- トレーサビリティの実現
- 全レイヤーでセキュリティを適用する
- セキュリティのベストプラクティスを自動化する
- 伝送中および保管中のデータを保護する
- データに人の手を入れない
- セキュリティイベントに備える

### 信頼性

- 障害から自動的に復旧する
- 復旧手順をテストする
- 水平方向にスケールしてワークロード全体の可用性を高める
- キャパシティーを推測することをやめる
- オートメーションで変更を管理する

### パフォーマンス効率

- 高度なテクノロジーを誰でも使えるようにする
- 数分でグローバルに展開する
- サーバーレスアーキテクチャを使用する
- 実験の頻度を高める
- メカニカルシンパシーを検討する

### コスト最適化

- クラウド財務管理を実装する
- 消費モデルを導入する
- 全体的な効率を測定する
- 差別化につながらない高負荷の作業に費用をかけるのをやめる
- 費用を分析し帰属関係を明らかにする

### サステナビリティ

- 影響を理解する
- 持続可能性の目標を設定する
- 使用率を最大化する
- より効率的なハードウェアやソフトウェアの新製品を予測して採用する
- マネージドサービスを使用する
- クラウドワークロードのダウンストリームの影響を軽減する
複数htmlファイルを対象に閉じタグミスを検出する方法

複数htmlファイルを対象に、HTMLHintを使用して閉じタグミス（「Tag must be paired」エラー）が発生しているファイル名を抽出する方法を説明します。この手法は、他のVSCodeのエラーメッセージにも汎用的に使用することができます。
## 手順
### 1. HTMLHintのインストール

まず、確認したいファイル群を含んだプロジェクトディレクトリにHTMLHintをインストールします。

```sh
npm install htmlhint --save-dev
```

### 2. HTMLHintの設定ファイルを作成

プロジェクトのルートディレクトリに .htmlhintrc ファイルを作成し、以下のように設定を記述します。

```sh
{
  "tagname-lowercase": true,
  "attr-lowercase": true,
  "attr-value-double-quotes": true,
  "doctype-first": true,
  "tag-pair": true,
  "spec-char-escape": true,
  "id-unique": true,
  "src-not-empty": true,
  "attr-no-duplication": true
}
```

### 3. HTMLHintの実行とJSON形式での保存

ターミナルで以下のコマンドを実行して、HTMLHintの出力をJSON形式で保存します。

```sh
npx htmlhint --format json "**/*.html" > htmlhint-log.json
```

### 4. 閉じタグミスを含むファイルを抽出するスクリプトの作成

以下のスクリプトを extract-errors.js という名前で保存します。このスクリプトは、閉じタグミス（「Tag must be paired」エラー）が含まれるファイル名を抽出します。そのほかのエラーに対して抽出したい場合はerrorMessageToFilterの値を変更してください。

```sh
const fs = require('fs');
const data = JSON.parse(fs.readFileSync('htmlhint-log.json', 'utf8'));

const errorFiles = new Set();
const errorMessageToFilter = 'Tag must be paired';

data.forEach(file => {
  if (file.messages) {
    file.messages.forEach(message => {
      if (message.message.includes(errorMessageToFilter)) {
        errorFiles.add(file.file);
      }
    });
  }
});

fs.writeFileSync('filtered-error-files.json', JSON.stringify([...errorFiles], null, 2));
```

### 5. スクリプトの実行

以下のコマンドを実行してスクリプトを実行します。

```sh
node extract-errors.js
```

### まとめ
上記の手順を実行することで、HTMLHintを使用して閉じタグミス（「Tag must be paired」エラー）が発生しているファイル名をJSON形式で抽出し、ログファイルに保存することができます。
VPC関連周りを学習

## VPC
AWSクラウド内に仮想ネットワークを作成できるサービスです。
仮想ネットワークを作成することでユーザーが自由に作業を行う土地を提供してくれます。

## IPアドレス
IPアドレスはネットワーク上の住所を表しており、コンピューターやスマホなどのネットワークに接続されているデバイスを識別します。

### IPv4
「Internet Protocol Version 4」の略称です。
一般的に広く使用されていますがアドレス数に限りがあり、枯渇問題を抱えています。
形式は192.168.1.1のような4つの数字のグループです。

### IPv6
IPv4の枯渇問題を解決するために、誕生したプロトコルで形式は
2001:0db8:85a3:0000:0000:8a2e:0370:7334 のような長い文字列になっています。

## CIDR
IPアドレスの範囲を決定するための表記方法で、VPC内で使用可能なIPアドレスの範囲を決定します。
例：　10.0.0.0/16を指定すると、10.0.0.0〜10.0.255.255までの範囲が使用可能になります。この時の使用可能アドレス数は256✖️256=65,536個のIPアドレスが使用可能です。

IPアドレスの範囲を決める理由としては、ネットワーク内のデバイスやサービスを整理するために存在しています。

## サブネット
ネットワークをさらに小さい単位で分割したものをサブネットと言います。
サブネットの役割は、ネットワークを分割して別々の役割を持たせることで管理しやすくしたり、サブネットごとにセキュリティポリシーを適用することでセキュリティを強化することができます。

### パプリックサブネット
インターネットと直接やりとりできるサブネットのことです。
用途はWebサーバやロードバランサーを置きます。

### プライペートサブネット
インターネットと直接やりとりできないサブネットのことです。
用途は、DBサーバや社内システムを置きます。

https://en-junior.com/vpc/#index_id0
FlutterのEnhanced enumとジェネリクスを使って良い感じにSharedPreferenceを実装する

## 目的
- FlutterのSharedPreferenceの呼び出しを簡略化したい
- 呼び出しもとがSharedPreferenceの型をあまり意識しない作りにしたい

## tl;dr
dartのenhanced enumならジェネリクスを使った表現ができる。
型指定をenum内でわかるようにすればSharedPreferenceに対応する値がどんな型なのか一目で理解できる


## 実装
### キー一覧のenum 
```dart
enum PrefKey<T> {
    userId<String>('USER_ID', ''),
    age<int>('AGE', 20),
    ;

    final String key;
    final T defaultValue;

    PrefKey(this.key, this.defaultValue);

    Future<T> get() async {
        return await _SharedPreferenceManager<T>().get(this);
    }
    
    Future<void> set(T newValue) async {
        await _SharedPreferenceManager<T>().set(this, newValue);
    }
}
```

### SharedPreferenceの管理クラス
SharedPreferenceの実際の取得や登録については他の記事を参考にしてください
```dart
/// PrefKeyと同じファイルにある想定で非公開クラスにしてあります
class _SharedPreferenceManager<T> {
  Future<T> get(PrefKey key) async {
    // SharedPreferenceから取得した値をTに変換して返却
    return key.defaultValue;
  }

  Future<void> set(PrefKey key, T newValue) async {
    // SharedPreferenceに値を登録する

  }

}
```

### 実際に使うとき
```dart
class UseCase {
  Future<void> useCase() async {
    await PrefKey.userId.set('newValue');
    final userId = await PrefKey.userId.get();
    print(userId);

    await PrefKey.age.set(2024);
    final age = await PrefKey.age.get();
  }
}

```
使うときに型を強制できるので数値やboolで欲しい場所では型チェックが不要になる。
また、エディタやコンパイル時のチェックが働くので間違いが起きにくい。
intの引数にStringを入れようとして怒られる。
![スクリーンショット 2024-08-10 0.11.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270504/6f86b813-9e04-4631-14b3-c477e85ab52a.png)

自画自賛ですがとてもエレガントにできたと思うので
SharedPreferenceを使うときにこの方式を検討してみてください。

## 参考記事
https://blog.logrocket.com/deep-dive-enhanced-enums-flutter-3-0/
dart2.7未満では使えないです。
生成AIパスポート試験に合格したので色々まとめてみた

6月上旬に受験した生成AIパスポート試験の結果が公開されました。結果はタイトルの通り、無事:cherry_blossom:合格:cherry_blossom:しました。よって、記憶が薄れないうちに以下の過去記事では触れなかった内容についてdumpしておこうと思います。

https://qiita.com/y-vectorfield/items/b946bf10214c6487d304

試験結果が記載されていたメールには受験者数、合格者数、合格率が記載されていました。これを見る限り、合格率は極めて高い試験と言えるでしょう。

> 総受験者数 : 2,985名
> 合格者数 : 2,351名
> 合格率 : 78.76％

https://guga.or.jp/2024-7-19/

参考までに筆者の得点率です。合格点や採点基準、各問題の配点、解答、解説などは一切公開されていないため、各分野何問中何問正解といった詳細な情報は分かりません。~~各得点率を平均すると、84.6%となるため、60問中50問正解(10問不正解)だったのかなと推察します。~~

**2024/8/13訂正**
以下の得点率は受験者全体での平均値だった様です。各得点率を平均すると、84.6%となるため、60問中50問正解(10問不正解)ということは合格者平均だともっと高い点数になりそうです。

> 【シラバス分野別得点率（小数点以下切り捨て）】
> １．AI（人工知能）：90%
> ２．生成AI（ジェネレーティブAI）：80%
> ３．現在の生成AI（ジェネレーティブAI）の動向：85%
> ４．情報リテラシー・基本理念とAI社会原則：86%
> ５．テキスト生成AIのプロンプト制作と実例：82%

# 試験対策
筆者は以下の書籍をKindle版で購入し、書籍を読む前に予備知識で付属の模擬問題にどれぐらい正解出来るか解いてみました。その時点で8割を超えていたため、書籍を一通り読了すると同時に模擬問題を複数回解き直しました。また、書籍内で気になるテーマについてはチェックを付けて後から見直せる様にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/49c45770-f3af-ebba-7ba7-6df4a94e81f9.png)

# まとめ
生成AIパスポート試験について前回の記事で扱わなかった内容について取り上げました。今後も生成AI、特にLLMについて自分なりにキャッチアップを継続出来ればと思っています。その一環としてこの資格の受験が有ったと思います。今後以下の資格にも挑戦してみようと思います。

https://exp-p.com/aitest
【Rails】Bulletの導入方法

## Gemをインストール

`Gemfile` に以下のように記述し、 `bundle install` します。

```ruby:Gemfile

group :development do
  gem "bullet", "~> 7.2"
end

```

## 設定する

ターミナルで以下のコマンドを実行し、設定を自動生成します。

```terminal
$ bundle exec rails g bullet:install
Enabled bullet in config/environments/development.rb
Would you like to enable bullet in test environment? (y/n) y
Enabled bullet in config/environments/test.rb
```

`config/environments/development.rb` と `config/environments/test.rb`　に次のような設定が生成されます。

```ruby:config/environments/development.rb
Rails.application.configure do
  config.after_initialize do
    Bullet.enable        = true
    Bullet.alert         = true
    Bullet.bullet_logger = true
    Bullet.console       = true
    Bullet.rails_logger  = true
    Bullet.add_footer    = true
  end

end
```

```ruby:config/environments/test.rb
Rails.application.configure do
  config.after_initialize do
    Bullet.enable        = true
    Bullet.bullet_logger = true
    Bullet.raise         = true # raise an error if n+1 query occurs
  end

end
```

カスタム構成については以下をご参照ください。

https://github.com/flyerhzm/bullet#configuration
投稿フルマラソン2024無事完走！！来年に向けた振り返り

6月11日〜7月17日の38日間にかけて開催されたQiita Engineer Festa 2024の記事投稿フルマラソンを無事完走しました。Qiitaで記事の投稿を開始して6年目となりますが、今回初めて参加しました。無事完走出来ましたが、課題も見えてきました。来年の投稿フルマラソンに参加する時のために、本当は完走直後に投稿したかった振り返り記事ですが、時間が取れず、このタイミングになってしまいましたが、振り返り記事を投稿したいと思います。

# 投稿状況
無事38投稿(厳密には39投稿)を達成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/6f5f5a17-3843-49a9-52c0-255a4188288b.png)

イベント期間の投稿数の推移を下図に示します。(最大投稿数達成日は赤色で表示)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/e9e05c7e-ceb7-8bfe-7c95-f35206f2d5b7.png)

投稿数の詳細を以下の表に示します。

|合計|平均|6月合計|6月平均|7月合計|7月平均|
|:---:|:---:|:---:|:---:|:---:|:---:|
|39|1.02|14|0.67|25|1.47|

# 振り返り
今回投稿マラソンに参加した振り返りを良かった点、反省点の2軸でまとめたいと思います。

## 良かった点
今回の投稿イベントへの参加を振り返って良かった点は以下の3点です。

1. 38投稿を無事達成出来た点
2. 投稿テーマを探す過程で新しいツールを導入し、研究出来た点
3. 所属のコミュニティのContribution数に貢献出来た点

2019年8月からQiitaへの記事投稿を開始して6年目となりますが、初めて投稿マラソンに参加しました。初めての参加となるため、まずはハーフマラソン完走を目標とすることも検討しましたが、折角まとまった期間で開催されるため、フルマラソンの完走を目指すこととしました。また、記事投稿ネタを探す過程で、Distill Web MonitorやParallels拡張機能、DeepL翻訳、pypdfなどの新しいツールの導入に向けた研究が出来たので、今回得られた知見をもとに積極的にこれらのツールを活用していこうと思います。そして、今回39投稿を達成したことで、参加しているOrganization(コミュニティ)のContribution数にも貢献出来たので良かったと思います。

## 反省点
反省点として以下の3点が挙げられると思います。

1. 投稿数0の日が続いてしまった期間が有った点
2. スポンサー企業の投稿イベントへの参加のための準備不足が否めなかった点
3. 時間が取れず、準備に時間を要するテーマでの投稿があまり出来なかった点

6月の中旬に、旅行に出掛けた日も有ったため、投稿出来ない日は発生するだろうとは思っていましたが、そのままズルズル投稿出来ない日が続いたり、原稿のストックが無いために、毎日0から書かなければならず、結果として準備に時間を要するテーマの記事執筆に時間が取れず、投稿出来ないという日も有りました。今後も投稿を継続的に続けていくためにも、ネタのストック、原稿のストックを貯めておくことも意識したいなと思いました。また、スポンサー企業の投稿イベントへの参加は当初予定していた全てのイベントへの記事投稿は出来ませんでした。スポンサー企業の記事投稿イベントは事前にお題などが公開されるため、次回の参加時は十分に準備時間を取って投稿出来れば参加を断念せずに済むと思いました。

# (おまけ) Organizationの投稿状況
イベント期間に所属しているコミュニティの合計投稿数は80だったため、約半数を筆者の投稿が占めていることが分かります。 @joule さんが投稿数38だったため、2人で大半の記事を投稿したことになります。参加者が3人だった割には健闘？しているのではと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/d0ff1ff0-d96c-a929-19ee-188e1a69bb59.png)
passenger-statusを実行するとERROR: Phusion Passenger doesn't seem to be running.が発生するときの解決方法

# 導入

Phusion Passenger上で動作しているRuby on Railsアプリケーションでメモリリークが発生していると思われる事象が起きていた。
メモリリークの調査のために公式リファレンスに従って`passenger-status`を実行しようとたところ以下のコードブロック内に記載したエラーが発生した。

https://www.phusionpassenger.com/library/admin/apache/memory_leaks.html

```shell
$ passenger-status
ERROR: Phusion Passenger doesn't seem to be running. If you are sure that it is running, then the causes of this problem could be:

1. You customized the instance registry directory using Apache's PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir option, or Phusion Passenger Standalone's --instance-registry-dir command line argument. If so, please set the environment variable PASSENGER_INSTANCE_REGISTRY_DIR to that directory and run passenger-status again.
2. The instance directory has been removed by an operating system background service. Please set a different instance registry directory using Apache's PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir option, or Phusion Passenger Standalone's --instance-registry-dir command line argument.
```

メモリリークの調査以前にこちらのエラーの解消に時間がかかったので本記事で解消方法を整理する。

# 環境

```shell
Amazon Linux 2

$ passenger-config --version
Phusion Passenger 6.0.6

$ httpd -v
Server version: Apache/2.4.59 ()
```
公式には記載がないが以下の記事によればAmazon Linux 2はRHEL7/CentOS7をベースにしているらしい。

https://www.acrovision.jp/service/aws/?p=653

# 状況

まずは諸々の操作を行う前の状況について整理する。

`/tmp`の中には以下のように`systemd-private-`から始まるフォルダが存在する。

```shell
$ ls /tmp
systemd-private-xxxxxx-chronyd.service-xxxxxx
systemd-private-xxxxxx-httpd.service-xxxxxx
```

以下の記事によるとこれらのフォルダはCentOS系においてサービスの設定で`PrivateTmp=true`にされていると作成される。`PrivateTmp=true`にするとプロセスが使用する一時フォルダを隠蔽でき、セキュリティ的に安全になるらしい。

https://tex2e.github.io/blog/linux/tmp-systemd-private

また今回の環境ではApacheの設定ファイルは`/etc/httpd/conf/httpd.conf`である。


# 解決方法

基本的には以下の回答に記載の方法で解決した。以下の回答では`Ubuntu 18.04 with Apache and Passenger v5+`とされているためか今回の環境では微妙に変える必要があった。

https://serverfault.com/questions/1010641/ubuntu-18-04-passenger-error-phusion-passenger-doesnt-seem-to-be-running/1055703#1055703

具体的には以下の手順を行った。

```shell
$ sudo systemctl edit httpd.service
```
を実行するとエディターが開く。
エディターに
```
[Service]
PrivateTmp=false
```
を入力し`/etc/systemd/system/httpd.service.d/override.conf`として保存する。

変更を反映するために
```shell
$ sudo systemctl daemon-reload
```
を実行する。

`systemctl daemon-reload`については以下の記事を参考にした。

https://qiita.com/taro-hida/items/ec187c0fae893177e575

https://qiita.com/k1LoW/items/50017db5e66f87051afd

ちなみに`sudo`をつけなかったら下記のエラーが発生した。
```shell
$ systemctl daemon-reload
Warning: httpd.service changed on disk. Run 'systemctl daemon-reload' to reload units.
```

念のため`httpd`をリスタートする。
```shell
$ sudo systemctl restart httpd
```
これで完了。`passenger-status`が正常に動作した。


# うまくいかなかった方法

`httpd.conf`に`PassengerInstanceRegistryDir /tmp`を追記したり`PASSENGER_TMPDIR=/tmp passenger-status`を実行したりしたがこれらでは解消されなかった。これらの方法は以下の記事に記載されているものである。

※今回の状況ではうまくいかなかっただけであり、記事を批判する意図はないことを注意する。以下の記事に記載の方法でもうまくいくケースはあると思われる。

https://zenn.dev/megeton/articles/a7ef246d1694fd

https://spirits.appirits.com/doruby/9841/
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（84/100）

【84日目】
トピック 9：SAPS/4HANAでの簡易製造（1/9）

≪問題84≫
SAPS/4HANAでは、かんばんプロセスの供給元をどのようにして設定できますか。
（３つ選択）
□内部調達と外部調達の見積を使用する。
□内製で実行計画数量を使用する。
□自動化された供給元優先順位付けで購買費用を使用する。
□外部調達で購買発注を使用する。
□在庫転送で自動転送入出庫予定を使用する。

≪解答≫
□内部調達と外部調達の見積を使用する。
■内製で実行計画数量を使用する。
□自動化された供給元優先順位付けで購買費用を使用する。
■外部調達で購買発注を使用する。
■在庫転送で自動転送入出庫予定を使用する。

≪解説≫
◆かんばん生産管理において、プロセスの供給元と需要元の関係は、管理周期によって制御されます。
◆かんばん生産管理での供給元は、管理周期に定義された以下の補充方針によって決定されます。
（1）外部調達の場合、購買発注を使用して補充します。
（2）内製の場合、実行計画数量を使用して補充します。
（3）在庫転送の場合、在庫転送入出庫予定を使用して補充します。
importの並びのところだけLintやPrettierが効かない？

# はじめに
開発用のパソコンを最近変えたのですが、1つ問題が発生して、拡張機能などは問題なくインストールできていたのですがimportのorderのところだけlintやprittierが効かないという現象に会いました。初歩的なところだったのですがあまり記事が見つからなかったので短くまとめていきます。
効いていなかったのは
https://github.com/import-js/eslint-plugin-import
ですね

# 開発環境
- OS -> macOS Sonoma 14.5
- IDE -> VSCode

# 結局何が問題だったのか
VSCodeのアプリケーションがダウンロードフォルダに入っており、それをアプリケーションフォルダに移行することによって解決
![bFv3w5PMJxq52sg1723204458_1723204496.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3739285/0773ba19-5d9b-3236-a029-9f37213ad1b6.png)

# 問題の原因
ダウンロードフォルダとアプリケーションフォルダではアクセス権が違う
ダウンロードフォルダではリソース（ファイル）へのアクセスがされ、eslint-plugin-importが効いていなかったみたいでした

# まとめ
default formatterなどの設定を見ても問題ないのになんで！と言う方がいたら自分のIDEアプリケーションの場所を確認してみるのも１つの解決の手段になるかもしれません
雑記事で申し訳ないです🙏
Google CloudのCloud Shellがとても便利なのでおすすめしたい

## はじめに

Google CloudのCloud Shellってご存知でしょうか？
私は仕事ではAWSを使うことが多いので、周りでGoogleのCloud Shellを使っている人はあまり見たことがありません。
しかしながら使ってみればみるほど素晴らしいサービスなのでGoogle Cloudを使ってない人にもぜひ知っておいて欲しいです。

## Cloud Shellとは

正確な説明は公式のドキュメントに譲るとして、ざっくり言ってしまうと、`ブラウザからアクセスできるLinux開発環境`です。
開発者がよく使うコマンドラインツールやプログラミング言語がプリインストールされており、アクセスしてすぐに使い始めることが可能です（Python、Node.js、Goなどの言語や、Docker、Minikube、Git、Terraformといったツール）。Minikubeまでデフォルトで使える状態になってるの凄いですね。Kubernetesの勉強も環境構築要らずで始めることができちゃいます。
また、当然ですがgcloud cliもプリインストールされているのでGoogle Cloudとの連携も容易です。

https://cloud.google.com/shell?hl=ja

## 何が嬉しいのか？

便利な点は色々あるのですが、Google Cloud Shellならではの特長を紹介します。

### googleアカウントがあればすぐに使い始めることができる

Cloud ShellはGoogle Cloudのサービスの1つなのですが、gmailのアカウントさえ持っていれば、ブラウザから[Cloud Shellを開く](https://shell.cloud.google.com/?hl=ja)ことができます。もちろん、gmailでなくともgoogleアカウントとして利用可能なものでも可です。
しかも、**Google Cloudのプロジェクト作成や支払い情報の登録などをしていなくても**使うことができます（すごい）。

### 組み込みのCloud Shell Editorが使える

シェル環境だからといってコマンドラインの操作だけしかできないわけではありません。VSCodeベースのCloud Shell Editorが組み込まれているため、不自由なくファイルの表示や編集が可能です。VSCode向けの拡張機能も利用可能です。
Cloud9のようなオンラインの統合開発環境としても使えそうですね。

![PWAモードでCloudShellEditorを開いた図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360735/94d69754-7326-b097-dd24-86ba32f02107.png)

### ウェブでプレビューの機能

`ウェブでプレビュー`の機能を使えばCloud Shell上でローカル実行されたウェブアプリケーションをシームレスにプレビューすることができます。

例えば、Viteのアプリ（Viteじゃなくてもなんでもいいです）をCloud Shell上でローカル起動して、
![Cloud Shell上でViteアプリをローカル起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360735/19bb4ab1-3ec5-bdd3-ed54-d25e127eb348.png)

コンソール出力される`http://localhost:5173`をクリックするだけで、勝手に以下のようにアクセス用のURL経由で遷移してくれます。
![ウェブプレビューを開いた画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360735/706b3aa5-14f4-c648-d7e6-b6ded351610d.png)

ちなみに、このプレビュー用のURLを別のgoogleアカウントでログインした状態のブラウザで開いたところ、しっかり400エラーになりました。

### 永続ストレージが5GB

最初に述べた通り、クレカの登録も無しに無料で使えるにも関わらず、永続ストレージが5GBも用意されています（個人の感想ですが、googleのストレージ系サービスって太っ腹な気がします）。
用途にもよりますが、私は5GBもあれば十分かなと思いますが、拡張する機能は提供されていないことには注意が必要です。

## 最後に

いかがだったでしょうか？
使い始めるまでのハードルの低さを考えると、普段、Google Cloudを使ってない方でもCloud Shellを使う価値は十分にありそうではないでしょうか。
ローカルを汚さずにちょっとした技術検証を行なったり、ハンズオンなどの受講者側環境を揃えるのにもとても役立ちそうですね。

私は普段はAWSを使うことが多いので、Cloud ShellからAWSへ安全にアクセスする方法などもまたの機会に記事にしてみたいと思います。

以上です。
【学習記録　2024-08-09】　JavaScript

## 教材を使用する
Udemy「超JavaScript完全ガイド 2024」

## 学習内容
### 学習時間：10分程度
- prototypeプロパティの復習
 
## 所感
　今日は予定があったので、通退勤の復習時間のみになってしまいました😅
　明日から三連休なので今日の分もガッツリ学習したいと思います！！
rustでpytorchしてみた

pytorchなるものがこの世の中にはあるらしいのだが、rustからでも使えるらしいのでちょっと使ってみた。
サンプルがMNISTとかばっかりだったので、もっとシンプルな実装の例の参考になると良いな。

# 環境
Lubuntu 24.04 on VMWare

# 導入
rustをインストール。
`cargo init PROJECT_NAME`する。
`tch-rs`crateの追加。v0.16.0。お気楽にやるために`features=["download-libtorch"]`。libtorchはv2.3.0。2024年07月末時点。

# サンプル
中間層1層、判別関数はsigmoid、最適化はAdam、ミニバッチあり。

```rust:main.rs
use tch::{nn, nn::{Module, OptimizerConfig, VarStore}};
use tch::{Device, data::Iter2, Kind, Tensor};

const INPUTSIZE : i64 = 10;  // 入力
const HIDDENSIZE : i64 = 64;  // 中間層
const OUTPUTSIZE : i64 = 4;  // 出力
const ETA : f64 = 0.01;  // 学習率
const MINIBATCH : i64 = 16;  // ミニバッチ数

// ネットワーク構成
// 重みは乱数で初期化される。
fn net(vs : &nn::Path) -> impl Module {
    nn::seq()
        .add(nn::linear(vs / "layer1",
            INPUTSIZE,  // 入力数
            HIDDENSIZE,  // 中間層
            Default::default()))
        .add_fn(|xs| xs.sigmoid())  // シグモイド
        .add(nn::linear(vs / "layer2",
            HIDDENSIZE,  // 中間層
            OUTPUTSIZE,  // 出力数
            Default::default()))
}

// 教師データセット数x入力数の教師データを
// 1次元として読み込み
fn loadinputdata() -> Vec<f32> {
    let ret = Vec::new();
    // 入力(特徴)データを読み込む。
    ret
}

// 教師データセット数x出力数の正解の推論結果の教師データを
// 1次元として読み込み
fn loadtargetdata() -> Vec<f32> {
    let ret = Vec::new();
    // 出力(正解)データを読み込む。
    ret
}

fn main() -> Result<(), tch::TchError> {
    let inputdata : Vec<f32> = loadinputdata();
    let targetdata : Vec<f32> = loadtargetdata();

    // 1次元のデータをデータセット数x入力数としてTensorに変換
    let input = tch::Tensor::from_slice(&inputdata)
            .view(inputdata.len() / INPUTSIZE, INPUTSIZE));
    println!("input : {} {:?}", input.dim(), input.size());

    // 1次元のデータをデータセット数x出力数としてTensorに変換
    let target = tch::Tensor::from_slice(&targetdata)
            .view(targetdata.len() / OUTPUTSIZE, OUTPUTSIZE));
    println!("target: {} {:?}", target.dim(), target.size());

    let mut vs = VarStore::new(Device::Cpu);  // CPUで計算
    let nnet = net(&vs.root());

    if ファイルの値を読み込みたい {
        vs.load(ファイル名).unwrap();
    }

    let mut optm = nn::Adam::default().build(&vs, ETA)?;  // Adam
    for (key, t) in vs.variables().iter_mut() {  // 例:各WEIGHTのサイズの確認
        println!("{key}:{:?}", t.size());
    }
    for ep in 0..100 {  // 100世代
        let mut dataset = Iter2::new(&input, &target, MINIBATCH);
        let dataset = dataset.shuffle();  // シャッフル
        for (xs, ys) in dataset {
            let loss = nnet.forward(&xs).mse_loss(&ys, tch::Reduction::Mean);
            optm.backward_step(&loss);
        }
        print!("epoch:{ep} ");
        std::io::stdout().flush().unwrap();
    }
    println!("");

    // ファイルに保存
    vs.save("weight.safetensors");

    Ok(())
}
```

# 感想
100行程度のコードで簡単なNNの学習が出来てしまってびっくりというかあっけないというか、Adamとか関数呼ぶだけで出来ちゃうもんセコすぎ、そりゃみんなpytorch使いますわ。

# 参考
https://github.com/LaurentMazare/tch-rs

https://docs.rs/tch/latest/tch/

https://pytorch.org/docs/2.3/

[tch-rsでググる](https://google.com/search?q=tch-rs)
windows pipenv環境にpytorch+cudaをインストールする。

## pyenv、pipenv環境はなんとかできた！
pyinstallerでexeを作りたい！
pipenvで仮想環境を作って、最小限のライブラリでEXE化するんだよ、ということで、まず仮想環境だったのですが、まずこれがよくわかんない！
pyenvとpipenvと、最初はどちらかが誤記なのかと思ってました。
以下の記事がwindowsでの仮想環境のセットアップを丁寧に書いてあり、とても参考になりました。

https://zenn.dev/tikita/articles/f7a5bc16c36101

## pytorch+cudaをpipenvで導入したい！
pipenv install 〇〇で、順調にライブラリをインストールしていったのですが、困ったのがpytorchです。
pytorchの公式では、下のように
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679605/81938014-61b3-7897-6831-bb03c1537425.png)
`pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121`
と記載すれば、pipでインストールできると書いてありますが、pipenvでは下記のように書いてもうまくいきません。
~~`pipenv install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121`~~

じゃあ、どうしたらええのんー？
下の記述が参考になりました。

https://github.com/pypa/pipenv/issues/5996

```
pipenv install torch --index https://download.pytorch.org/whl/cu121
pipenv install torchvision --indexl https://download.pytorch.org/whl/cu121
pipenv install torchaudio --index https://download.pytorch.org/whl/cu121
```

これでOKでした。
よかったよかった！
「type object 'datetime.datetime' has no attribute 'timedelta'」が出た方へ

そこの **「type object 'datetime.datetime' has no attribute 'timedelta'」** が出たあなた！

私も出ました…


```Python:成功例
import datetime

dt = datetime.datetime.now()

dt_JP = dt + datetime.timedelta(hours=9)

print(dt_JP)
```
これだと上手く行くのですが

<br>

```Python:エラーの再現
from datetime import datetime

dt = datetime.now()

dt_JP = dt + datetime.timedelta(hours=9)

print(dt_JP)
```
```
AttributeError: type object 'datetime.datetime' has no attribute 'timedelta'
```

"from datetime import datetime"を使うとこうなります。

回避方法は最初のに戻すかこちら。

<br>

```Python:timedeltaインポート
from datetime import datetime, timedelta

dt = datetime.now()

dt_JP = dt + timedelta(hours=9)

print(dt_JP)
```

<br>

時間の計算をするといったら**datetime.timedelta(～)** としてコードを書き進めてるうちになんかのコピペしてきて普段使わない **"from datetime import datetime"** を利用するとこうなってしまします。

"from datetime import datetime"を使う場合はdatetimeからtimedeltaをインポートしてあげましょう。

にしてもこの **"import datetime"** と **"from datetime import datetime"** は紛らわしい…

ここら辺はいつかちゃん勉強してみたい…と3年くらい前から思っています。
OpenWrtと組み合わせるならコレ！SelfhostedなVPNツール

# はじめに
なんか適当にいろいろ試していい感じだったやつをピックアップしました。
(基本的にOSS/セルフホストできるものを選定しています)

# おすすめ一覧
## ZeroTier(ZTNET)
:::note info
### 良いところ
- 設定が簡単
    - Docker Composeですぐに利用開始できる
- OpenWrtと相性が良い
    - ルーティングが即座かつ動的に反映され、スタティックで切る必要がない
- 画面が使いやすい
    - ZTNETの画面は日本語対応が無いものの分かりやすい画面で使いやすい
- ピアに振るIPアドレスやレンジが自由に指定できる
    - 後述のNetBirdでは出来ないメリット
:::

:::note alert
### 悪いところ
- 通信スタックは独自実装であまり速度が出ない
    - P2P接続状態の実測で80Mbps程度、拠点間通信には使いづらい
- DNS設定はドメイン指定が必須
    - AdGuardHomeやpihole等、広告ブロックVPNとして使う場合は出口NATで傍受して処理する必要がある
- フルトンネル運用は微妙
    - 再接続に少々時間がかかるなど多少の難あり
- 認証は接続要求後、管理画面で管理者が許可する必要あり
    - 一度許可すれば次回以降求められることはない
- アプリの見た目がダサ…じゃなくてレガシーな雰囲気
    - ちょっとかっこ悪い
:::


## NetBird
:::note info
### 良いところ
- WireGuard(カーネルベース)で高速通信
    - 実測150Mbps~200Mpbsくらい出るのでそれなりに使える
        - 調子が良ければもっと出る
- OpenWrtと相性が良い
    - 稀に調子悪い時があるが基本的にルーティングも即時反映される
- 認証基盤が色々使える
    - SSOしつつ管理画面で接続を許可するまで接続させないことも可能
    - クライアントに応じて定期認証を要求したり不要にしたり出来る
- 無料枠が潤沢なのでセルフホストしなくてもいいかも
    - 5ユーザー/100デバイスまで無料、ありがてぇ…！
- ルーティングやエグレスのHA(冗長化)が出来る
    - 複数のマシンにNetbirdクライアントを入れて設定してあげることで簡単にHAすることが出来る
    - 複数のエグレスノードを設定してHAも出来る
- フルトンネル運用が簡単
    - エグレスノードを設定→エグレスノードを使えるピアグループを指定→終わり
- DNS設定がアホほど簡単
    - ドメイン指定なしで独自のDNSサーバを指定できるのでアドブロックVPNとしての運用も簡単
    - もちろんドメイン指定でDNSサーバの選択も可
- クライアントをグループで分けて管理・ルーティング配布ができる
    - ネットワーク機器に振るルートと各クライアントに振るルートを分けたり出来る
- ポスチャチェックや通信ポリシー設定が出来る
    - 出来て損はないのでﾖｼ！
- 管理画面の見た目が良い
    - なお日本語は無い
:::

:::note alert
### 悪いところ
- IPレンジは`100.64.0.0/10`で固定、クライアントIPはランダムに設定され変更はできない
    - 使いたくないIPレンジと被ってしまったときが一番困るよね…
- DockerベースでセルフホストできるがDocker Compose単体ですぐに立ち上げは出来ない
    - Portainerで全部管理しているのでこれが割と個人的には困る…
:::

## WireGuard
:::note info
### 良いところ
- Simple is Best
- 一番速い
:::
:::note alert
### 悪いところ
- 管理が面倒(公開鍵を交換したりルート切ったり…)
:::

## その他
Tailscale(Headscale)やNetmaker、Nebula、Tinc等もありますが、Tailscale/Netmaker使うならNetbird使う方が良いかなと思いました。~~本音を言うと面倒なので触ってません~~機会があれば触ろうと思います。

# 最後に
- IPアドレスレンジや割り振るIPアドレスを気にするなら`ZeroTier(ZTNET)`
- あんまり気にしないかフルトンネルやアカウント管理、DNS周りを重視するのであれば`Netbird`
- 速度至上主義は`WireGuard`

がオススメかなと思いました。ちゃんちゃん。
mysql_native_passwordに変更したのにERROR 1045 (28000): Access denied が発生する

# 何が起きた
MySQL8.0のイメージを起動したDockerコンテナに外部(docker-composeの別のコンテナ)からアクセスすると、`ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded` とエラーが発生するので、`mysql_native_password` に認証方法を変更しました。すると、GRANTしているにもかかわらず、`ERROR 1045 (28000): Access denied `が発生します。

# 対処方法
`mysql_native_password` に変更した後に**改めてパスワードを修正**する。
```sql
ALTER USER 'develop'@'%' IDENTIFIED WITH mysql_native_password BY 'password'
ALTER USER 'develop'@'%' identified by 'develop';
```

# 詳しい経緯
1. docker-composeで以下のように設定しました
```yml
  db:
    image: mysql:8.0
    container_name: develop_db
    command: mysqld --character-set-server=utf8mb4 --sql-mode=""
    volumes:
      - mysql-volume:/var/lib/mysql:delegated
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_HOST: '%'
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: calcium
      MYSQL_USER: develop
      MYSQL_PASSWORD: develop
    tty: true
```
1. 別のコンテナからmysql cliでアクセスすると`ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded` が発生
1. 以下のSQLで「mysql_native_password」に変更
```sql
ALTER USER 'develop'@'%' IDENTIFIED WITH mysql_native_password BY 
'password'
```
1. 別のコンテナからmysql cliでアクセスすると`ERROR 1045 (28000): Access denied` が発生する
1. GRANT分で権限を付与
```sql
GRANT ALL PRIVILEGES ON `calcium_test`.* TO 'develop'@'%';
FLUSH PRIVILEGES;
```
1. ここまでやってもAccess deniedが消えなかった。けど、パスワードを再設定したらいけました。

たったこれだけで4時間溶かしました。