OmniAICreator/Qiita-1.07M huggingface dataset:
【数式】Salesforceの算術の計算

Salesforceの数式で個人的によく使うもののメモです。

# 算術のあれこれ

## 桁数の計算
数値$N$の桁数$n$は下記の数式で定義できます。
```math
n-1\le\log_{10}N<n
```
Salesforceでは、LOG関数とFLOOR関数を使うことで計算ができます。
```
FLOOR( LOG( 数値型 ) + 1 )
```
これは、大きな値を扱う場合に桁数を省略する場面で活躍します。例えば、金額を省略形で示す場合は下記のように表現できます。
```
TEXT( FLOOR( 数値型 / 10 ^ FLOOR( ( FLOOR( LOG( 数値型 ) ) ) / 4 ) ) )
+ CASE( FLOOR( ( FLOOR( LOG( 数値型 ) ) ) / 4 ) ,
  0 , "円" ,
  1 , "万円" ,
  2 , "億円" ,
  3 , "兆円" ,
  ...
)
```

## 対数関数の底の変換
Salesforceで準備されている対数関数は自然対数と常用対数のみのため、その他の底で対数計算を行う場合には変換を行う必要があります。このとき、底の変換公式
```math
\log_{x}b=\frac{\log_{a}b}{\log_{a}x}
```
を利用します。変換先の底が$x$とすると、$a$はSalesforceで準備されている対数関数を加味して自然対数または常用対数の底を選択すると良いです。よって、数値型の値に対して任意の底の対数関数を計算する場合は下記のように表現されます。
```
LOG( 数値型 ) / LOG( 任意の底 )
```

## 直線からの距離の計算
$xy$の平面上に
```math
ax+by+c=0
```
の直線の方程式が定義されている場合に、データ点$(x_{0},y_{0})$と直線の間の距離は
```math
\frac{|ax_{0}+by_{0}+c|}{\sqrt{a^{2}+b^{2}}}
```
で表現されます。これをSalesforceの数式を使って表現すると下記のようになります。
```
ABS( a * x0 + b + y0 + c ) / SQRT( a ^ 2 + b ^ 2 )
```
これは、散布図の点に対する評価の一種として使える場合があります。

## 緯度経度からの距離の計算
緯度経度から距離を計算するには、地球が楕円体であることを加味して計算を行う必要があります。
厳密な計算を行うためには複雑な計算式が必要ですが、大凡の数値であれば下記のような簡潔な数式で計算することができます。
```math
d = \sqrt{\left[\left(D_{y1}-D_{y2}\right)\cdot R_{x} \cdot \left(1-\left|\frac{R_{x}^{2}-R_{y}^{2}}{R_{x}^{2}}\right|\right) \cdot \left(1-\left|\frac{R_{x}^{2}-R_{y}^{2}}{R_{x}^{2}}\right| \cdot \sin^{2}\left(\frac{D_{y1}-D_{y2}}{2}\right)\right)^{-\frac{3}{2}}\right]^{2}+\left[\left(D_{x1}-D_{x2}\right)\cdot R_{x} \cdot \left(1-\left|\frac{R_{x}^{2}-R_{y}^{2}}{R_{x}^{2}}\right| \cdot \sin^{2}\left(\frac{D_{y1}-D_{y2}}{2}\right)\right)^{-\frac{1}{2}} \cdot \cos\left(\frac{D_{y1}-D_{y2}}{2}\right)\right]^{2}}
```
これは、2つの緯度経度$(D_{1},D_{2})$の間の距離の式で、それぞれ下記のようなラジアン単位の緯度経度の値を持ちます。
```math
\begin{eqnarray}
    D_{1} &=& (D_{x1} , D_{y1})\\
    D_{2} &=& (D_{x2} , D_{y2})
\end{eqnarray}
```
$R_{x}$と$R_{y}$は楕円体の長半径と短半径で、WGS84の測地系では下記の値となります。
```math
\begin{eqnarray}
    R_{x} &=& 6,378,137.000000\\
    R_{y} &=& 6,356,752.314245
\end{eqnarray}
```
これを踏まえて、Salesforceの数式で表現すると、下記のようになります。
```
SQRT(
  (
    ( 緯度1 - 緯度2 )
    * 6,378,137.000000
    * ( 1 - ABS( ( 6,378,137.000000 * 6,378,137.000000 - 6,356,752.314245 * 6,356,752.314245 ) / ( 6,378,137.000000 * 6,378,137.000000 ) ) )
    / SQRT(
      ( 1 - ABS( ( 6,378,137.000000 * 6,378,137.000000 - 6,356,752.314245 * 6,356,752.314245 ) / ( 6,378,137.000000 * 6,378,137.000000 ) ) * SIN( ( 緯度1 - 緯度2 ) / 2 ) ) ^ 3
    )
  ) ^ 2
  + (
    ( 経度1 - 経度2 )
    * 6,378,137.000000
    / SQRT(
      ( 1 - ABS( ( 6,378,137.000000 * 6,378,137.000000 - 6,356,752.314245 * 6,356,752.314245 ) / ( 6,378,137.000000 * 6,378,137.000000 ) ) * SIN( ( 緯度1 - 緯度2 ) / 2 ) )
    )
  ) ^ 2
)
```
この数式は緯度経度の間の距離をメートル単位で計算します。

上記の緯度経度の情報が度数法であればラジアンに変換する必要があり、簡単とはいえ長大な数式ではあります。度数法の緯度経度を持っている場合、Salesforceの地理位置情報特有の関数を使って、もっと短く下記のように書くこともできます。
```
DISTANCE( GEOLOCATION( 緯度1 , 経度1 ) , GEOLOCATION( 緯度2 , 経度2 ) , "km" )
```
この数式は緯度経度の間の距離をキロメートル単位で計算します。
Twitter Clone まとめ　part1-10

# 講座

https://www.udemy.com/course/react-js-tutorial/learn/lecture/32461766?start=60#overview


# 一覧

##  Part1　サイドバー作成

![twitterSidebar１１.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/76b37426-4b4a-e4b0-4b6c-0f803ba9af1b.gif)

https://qiita.com/RYA234/items/1c97f3e81f86e10d0adb


## Part2　ヘッダー作成

![twitterHeader111.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/b3ef1ee6-6898-5f6c-ecf7-23f87f742bbf.gif)

https://qiita.com/RYA234/items/be586055506439831ef5

##  Part3　ツイート欄のUIを実装　tailwindcss/formを使う

![tailwindform.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/1575b75e-c92b-24a1-4f32-7f2a1283fdff.gif)


https://qiita.com/RYA234/items/ed676f4b159ce095febc

## Part4 投稿情報を表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a1082347-8b4f-a0bf-f8e4-767a2218d55c.png)

https://qiita.com/RYA234/items/f5368fa0e35ce094ee11


## Part5　右側に検索欄のUIを実装

![SearchBar11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a12c1966-cef0-5ce3-c6c9-96c856c25417.gif)

https://qiita.com/RYA234/items/d37ecfba699a5b5eec50

## Part6　右側にニュース欄を加える

![newsaaaaaaaaaaa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/41070418-f4e2-ee21-8e8d-9edfcfcf8eff.gif)

https://qiita.com/RYA234/items/8b8d902ecd4066469f96

## Part7　ユーザーをランダムに表示

![RandomUser.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/525f9fd0-1470-f7d4-ef92-b7bc01e68e6f.gif)

https://qiita.com/RYA234/items/b27b08b1ea31be99ad2f

## Part8　next authとfirebaseを使ってログインページの実装

![loginPage.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f6641c28-39fe-36fd-13a7-244d54ccb629.gif)

https://qiita.com/RYA234/items/6376272fb2f469d577bd

## Part9　ログイン成功後のページを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c6e06cee-8f39-8100-e0f4-6a455b83d65c.png)

https://qiita.com/RYA234/items/2dee839985ac6c0b02da

## Part10 firebaseに投稿情報を加える

![PostData12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/47b93c02-ad89-a3f2-923d-6794b86ae906.gif)


https://qiita.com/RYA234/items/14484a9e8c1fe04c9096
nginx + gunicorn のリバースプロキシ設定で.sockを誤って消去してしまった

### 1. トラブルの内容
AWS EC2上にDjangoRestFrameworkアプリケーションを構築したのですが、その際に.sockファイルを誤って消去してしまいリバースプロキシがワークしなくなってしまいました。
gunicornを再起動すれば.sockファイルは自動生成されるはず・・・が、手間取ってしまったのでメモ。

### 2. 開発環境
[環境]
EC2 Amazon linux 2023
nginx 1.24.0
gunicorn 20.0.4

[ファイル構成]
/etc/nginx/nginx.conf
/etc/nginx/conf.d/[PROJECT_NAME].conf
/etc/systemd/system/gunicorn.service
/etc/systemd/system/gunicorn.socket
※下の2つのファイルは[任意の名前].serviceと[任意の名前].socketのファイルです。

### 3. 実際のトラブルシューティング
消してしまわないところに.sockファイルを置くように設定するのがまず第一と考え、homeフォルダ直下にgunicorn-sockディレクトリを作成し、その中に.sockを作成する設定にしました。

```shell:gunicorn.socket
[Unit]
・・・

[Socket]
# sockファイルを作る場所を絶対パスで指定
ListenStream=/home/ec2-user/gunicorn-sock/[PROJECT_NAME].sock #変更
・・・

[Install]
・・・
```

```shell:[PROJECT_NAME].conf
server {
    listen  80;
    server_name     [サーバのIPアドレス];

    location / {
        proxy_pass http://unix:/home/ec2-user/gunicorn-sock/[PROJECT_NAME].sock; #変更
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}
```
これで再起動すれば、、、

``` 
$ sudo systemctl restart gunicorn.service
```

結果
![スクリーンショット 2023-08-15 17.13.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590859/d67102bf-cd93-89fa-d62f-5d18ed779059.png)
なぜか繋がらない。。。

### 4. 解決法
gunicornの再起動前にgunicorn.socketを再起動する必要がありました。

```shell
$ sudo systemctl start gunicorn.socket
$ sudo systemctl start gunicorn
```

![スクリーンショット 2023-08-15 18.32.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590859/ec131246-5238-acaf-42a8-9f535c026cf4.png)


### 5. まとめ
nginxとgunicornのリバースプロキシ設定の際に、.socketファイルを再起動するのを忘れないようにというpitfallでした。
‘e’ implicitly has an ‘any’ type

# 問題

以下のコードで ‘e’ implicitly has an ‘any’ type というエラーが出ていた。

```jsx
<DropdownMenu>
  {props.options.map((item, idx) => (
    <DropdownOption
      key={idx}
      onMouseDown={(e) => handleSelectValue(e, item)}
      onClick={(e) => handleSelectValue(e, item)}
    >
      <DropdownItem item={item} />
    </DropdownOption>
  ))}
</DropdownMenu>
```

# 動機

DropdownOption を div タグに変えるとエラーが消えるが、DropdownOption は

```jsx
const DropdownOption = styled.div`
  padding: 8px 12px 8px 12px;
  &:hover {
    background-color: #f9f9f9;
  }
`;
```

という要素であり、div に少し装飾を加えた程度であるため、エラーの原因になるとは考えづらい。そこでライブラリのバグではないかと考えた。

# 行動

参考文献を見ると、同じエラーになっている人がおり、styled-components のアップデートで解決していた。そこで、styled-components をアップデートした。

```jsx
teppe@LAPTOP-N72NG92A MINGW64 ~/Documents/private/programming/js/react/shop/src/components/molecules/Dropdown (main)    
$ npm styled-components --version
9.6.6
(base) 
teppe@LAPTOP-N72NG92A MINGW64 ~/Documents/private/programming/js/react/shop/src/components/molecules/Dropdown (main)    
$ npm update styled-components

added 1 package, changed 1 package, and audited 1593 packages in 3s

296 packages are looking for funding
  run `npm fund` for details

2 moderate severity vulnerabilities

To address all issues, run:
  npm audit fix

Run `npm audit` for details.
(base) 
teppe@LAPTOP-N72NG92A MINGW64 ~/Documents/private/programming/js/react/shop/src/components/molecules/Dropdown (main)    
$ npm styled-components --version
9.6.6
```

バージョンは変わっていないが中身が少し変わった。

変更点は以下のようになっていた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532009/7edb22cb-8781-0315-1b2e-131fbe4d3832.png)

# 結果

event の型に関するエラーは styled-components のバグによるものだと考えられ、 styled-components をアップデートすることで解消した。

# 参考文献

> https://github.com/styled-components/styled-components/issues/4052
>
Herokuでの簡単デプロイ: Flask製ChatGPTテキスト要約ツールを公開しよう！

前回、FlaskとHTMLを使用して、ChatGPTを用いたテキスト要約ツールを作成しました。今回はそのツールをHerokuにデプロイする方法を解説します。

# 1. 必要なファイルの準備
```
・app.py: メインのFlaskアプリケーションコード
・Procfile: Herokuがアプリケーションを実行する方法を知るためのファイル。このファイルには web: python app.py と記述する。
・requirements.txt: アプリケーションが依存しているPythonのライブラリのリスト。例: flask, openai など。
・templates/index.html
```
# 2. Herokuのセットアップ
・Herokuアカウントを作成。
・Heroku CLIをインストールしてログイン。

# 3. アプリケーションのデプロイ
以下の手順でデプロイを行います：

```
$ heroku create [アプリ名]  # アプリ名はオプション
$ git init
$ heroku git:remote -a [アプリ名]
$ git add .
$ git commit -m "Initial commit"
$ git push heroku master
```

# 4. 環境変数の設定
OpenAIのAPIキーをHerokuの環境変数として設定：
```
$ heroku config:set OPENAI_API_KEY=YOUR_OPENAI_API_KEY
```

# 5. アプリケーションの確認
ブラウザで https://[アプリ名].herokuapp.com/ にアクセスして動作を確認。

以上が、FlaskとHTMLで作成したChatGPTテキスト要約ツールをHerokuでデプロイする方法です。このガイドを参考に、簡単にWebベースのアプリケーションを公開してみてください。
EC2タグのName属性をホスト名にhosts登録するPowershellスクリプト

# TL;DR

- AWS-Cli経由で稼働中インスタンスIPとName属性を取得し、hosts登録するWindows用のPowershellスクリプトです。
- 環境によってはうまく動作しない可能性もあり、自己責任でご利用ください。
- 修正点あればご教示いただけると嬉しいです。

```powershell: スクリプト
# AWS-cliから稼働中EC2インスタンスのIPを取得。TagのName属性をホスト名としてWindows上のhostsに登録するPowershellスクリプト。
# AWS-cliにアクセスキー設定されており、AWSリソースの設定が可能であることが前提。
# hostsファイルの各行内でホスト名の文字列に重複がないことが前提。(ex. myec21,myec22というName属性を持つ2インスタンスが存在する場合、文字列としてmyec2が重複しておりNG)




# エラー発生時は処理中断。
$ErrorActionPreference = "Stop"

# 初期値
$HostsFileFullPath = "C:\Windows\System32\drivers\etc\hosts"
$PreparetionHostsFileFullPath = "C:\Users\$Env:USERNAME\Desktop\hosts-changed-result.txt"
$SignOfEOL = "`r"

# 管理者権限がなければ、自らを管理者権限で呼び出して実行。
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) {
    Start-Process powershell.exe "-File $PSCommandPath" -Verb RunAs
    Exit
}

$HostsContents = (Get-Content $HostsFileFullPath)
#VSCode上でソース整形時(Shift+Alt+F)、Values=runningの前に空白挿入されエラーとなることから文字列としてコマンドを定義し実行。
$InstanceInfo = (Invoke-Expression "((aws ec2 describe-instances --filters Name=instance-state-name,Values=running | convertfrom-json).Reservations.Instances)")

# hostsファイルの内容を稼働中インスタンス数を評価。（稼働中インスタンスが存在しなければ予め読込済のhosts内容をそのまま出力）
foreach ($Instance in $InstanceInfo) {

    $updatedFlag = $false
    $outputHostsLines = $null
    $InstanceName = ($Instance.Tags | Where-Object { $_.Key -eq "Name" }).Value

    # Name属性が存在しなければ次インスタンスに処理を移す
    if ([string]::IsNullOrEmpty($InstanceName)) {
        continue
    }

    # hostsファイルを１行づつチェック
    foreach ($inputhostsLine in $HostsContents) {

        # コメント行以外で既に同一ホスト名が存在する場合は上書き。
        if (($inputHostsLine.contains($InstanceName)) -and (!($inputHostsLine.substring(0, 1).contains("#")))) { 
            $outputHostsLines += ($Instance.PublicIpAddress + ' ' + $InstanceName + $SignOfEOL)
            $updatedFlag = $true
            Write-Host "Updated:${InstanceName}"
        }
        else {
            # 存在しなかったら元の内容とする。
            $outputHostsLines += ($inputHostsLine) + $SignOfEOL
        }
    }

    # 全行チェックして同一ホスト名が存在しない場合は新規追加。
    if (!$updatedFlag) {
        Write-Host "Added:${InstanceName}"
        $outputHostsLines += ($Instance.PublicIpAddress + ' ' + $InstanceName + $SignOfEOL)
    }

    # 次のインスタンス情報の処理に備え、hosts内容を上書。
    # splitしていないと1行づつ分割して取り出せないので注意。
    $HostsContents = $outputHostsLines.split($SignOfEOL)
    # 最後配列に空行が入るので除外（最終配列添字となる$HostsContents.Length-1を含めない）
    $HostsContents = $HostsContents[0..($HostsContents.Length - 2)]
}


#過去分をバックアップ（削除は行わないため適宜手動メンテナンス要）
Copy-Item -Path $HostsFileFullPath -Destination ($HostsFileFullPath + "." + (Get-Date).ToString('yyyyMMddHHmmss') + ".txt") | Out-Null

#上書用ファイルをデスクトップ出力(確認も兼ねる)
Set-Content -Path $PreparetionHostsFileFullPath -Value $HostsContents -Force

#hostsファイルの書き換え（直接Set-Contentで書いてしまうとタイミングイシューで空ファイルになるときがある）
Copy-Item $PreparetionHostsFileFullPath -Destination $HostsFileFullPath -Force | Out-Null

Read-Host "Finished. Please Enter Key..." | Out-Null

```
Chakra UIで親要素をhoverしたときに子要素のbackgroundも変更する

## はじめに
Chakra UIで、親要素のhoverで子要素のボタンも同時にstyleを変更するというUIをどのように実現すればよいかを調べてみました。

## groupHoverを使う
親要素のhoverを子要素に伝えるにはgroupHoverが使えます。
親要素のBoxに対して`role="group"`を指定して、子要素のIconButtonには`_groupHover={}`を指定します。
```react
export function App() {
  return (
    <Box
      w="200px"
      role="group"
      bg="blue.100"
      transitionProperty="common"
      transitionDuration="normal"
      _hover={{ bg: "blue.200" }}
    >
      <IconButton
        icon={<HamburgerIcon />}
        aria-label="sub-menu"
        bg="blue.100"
        _groupHover={{ bg: "blue.200" }}
      />
    </Box>
  );
}
```

これで、Boxにhoverしたときに、IconButtomも同時にbackgroundの色を変えることができるようになりました。
![groupHover.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551121/589434e7-ecbc-f88c-2a09-3d8c9b523ee2.gif)


## 子要素自体にhoverしたときに別のstyleを適用したい
この方法だと、子要素にhoverしても元々のstyleが適用されません。
子要素はIconButtonなので、そこにhoverするとIconButtonのstyleが適用されてほしいです。
![groupHover2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551121/7f2fffa8-018c-7f17-7aef-34a09b177fdb.gif)

元々のButtonの設定よりgroupHoverの設定が優先されてしまうようなので、以下のように、子要素に_hoverを設定して、`!important`にし、子要素の_hoverを優先するように設定することで子要素に対して別のstyleを適用することができました。
ただ、もう少しスマートに解決する方法があるかもです。

```react
export function App() {
  return (
    <Box
      w="200px"
      role="group"
      bg="blue.100"
      transitionProperty="common"
      transitionDuration="normal"
      _hover={{ bg: "blue.200" }}
    >
      <IconButton
        icon={<HamburgerIcon />}
        aria-label="sub-menu"
        bg="blue.100"
        _groupHover={{ bg: "blue.200" }}
        _hover={{ bg: "gray.200 !important" }}
      />
    </Box>
  );
}
```
![groupHover3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551121/823d5316-0e80-5b7d-98d3-919dc4bf60d0.gif)


## 参考資料
https://scrapbox.io/elecdeer-pub/ChakraUI%E3%81%A7%E8%A6%AA%E8%A6%81%E7%B4%A0%E3%81%B8%E3%81%AE%E3%83%9B%E3%83%90%E3%83%BC%E3%81%A7%E5%AD%90%E8%A6%81%E7%B4%A0%E3%81%AE%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%81%84
メロンブックスの入荷待ち商品をサクッと確認する

# はじめに
夏の陣で頒布された同人誌をメロンブックスの委託販売で予約しました。

送料の節約や受け取りの手間を最小限にしたいという理由から、予約商品をまとめて発送してもらえるおまとめ発送というサービスを使っているのですが、当たり前ですがこれは予約したすべての商品が入荷されないと商品が発送されません……。

# 解決したいこと
メロンブックスの注文履歴ページでは商品のステータスとして、「商品入荷済み」「商品未入荷」「商品入荷待ち」などが表示されていますが、一見してどれが入荷済みでどれが未入荷なのかが分かりにくいです。[^1]

[^1]: 未入荷のステータスは「商品未入荷」「商品入荷待ち」だったりします。どういう使い分けかはわかりませんが……。

私の場合、いつ頃発送されるのかなとソワソワしてしまい毎日確認するタチなのですが、都度確認するのに一つ一つのステータスを見るのが面倒なので、注文履歴ページ送信時に自動で表示されるようにしようと思います。

# 実現方法
開発者ツールで確認してみると、商品の入荷状況は`<td>`タグで表示されています。また、入荷状況に応じてクラスを付与してある・・・という訳ではありませんでした。

そこで今回は、ブラウザ拡張機能である「**ScriptAutoRunner**」と「**Stylebot**」を使用して、

> 1. 入荷状況が「商品未入荷」の場合は`<td>`要素に`backorder`クラスを付与する。
> 2. CSS で`backorder`にスタイルを設定する。
> 3. ページ訪問時に「未入荷商品：N点」といった　メッセージを表示する。

という処理を自動で実行できるようにします。

**[ScriptAutoRunner](https://chrome.google.com/webstore/detail/scriptautorunner/gpgjofmpmjjopcogjgdldidobhmjmdbm?hl=ja)**
指定したページを訪問した際に、`JavaScript`のコードを自動で実行できる拡張機能です。

**[Stylebot](https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha?hl=ja)**
独自の`CSS`を設定・反映できる拡張機能です。

# 設定方法
### ScriptAutoRunner

以下の記事を参考に、`JavaScript`のコードと対象ドメインの設定を行います。

https://qiita.com/itaya/items/36ed8b890c87ac47d9d3

次の`JavaScript`コードを記載します。関数である必要はありません。
**※「ここの書き方変だよ」「ここはこう書けるよ」みたいなのがあればぜひ教えてください！**

```js
// 現在のページが「購入履歴」の時のみ実行
// ScriptAutoRunnerがドメイン単位でしか指定できないため
if (document.location.href === `https://www.melonbooks.co.jp/mypage/history.php`) {
    // 「商品未入荷」「商品入荷待ち」の td 要素を取得
    const backOrders = [...document.querySelectorAll('td')].filter(e => e.innerText === '商品未入荷' || e.innerText === '商品入荷待ち')

    // 「商品未入荷」「商品入荷待ち」の td 要素に 'backorder' クラスを付加
    backOrders.map(e => e.classList.add('backorder'))

    // 「商品未入荷」「商品入荷待ち」の件数を表示
    alert(`未入荷商品：${backOrders.length}点`)
}
```

ホストにメロンブックスの URL(`www.melonbooks.co.jp`) を指定します。

最後に、プラグ部分をクリックするとスクリプトが有効化されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612381/dab2839c-6d35-fd93-2ec8-74e42f3c1000.png)

### Stylebot
メロンブックスのページで `[Stylebotを開く]` → `[<> コード]` を選択し、好みのスタイルを設定してください。

```css
.backorder {
  color: red;
  background-color: yellow;
}
```

対象サイトがメロンブックスの URL(`www.melonbooks.co.jp`) になっていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612381/032c130e-9a7d-0205-bf79-cf41ebe8246a.png)

# 結果
アクセスした段階で未入荷商品数が表示され、スタイルも適用されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612381/81c2ea5e-ea71-644a-0c75-6c02ae5923e7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612381/3297bf69-6684-5b86-073e-b91dd2af4e57.png)


ダイアログの内容や要否、スタイルの好みは適当に調整してください。
取り消しのGitコマンドの種類を覚えておく

基本的なGitコマンドについて復習しています。

復習すると、意外と使っていないコマンドもあったので、このタイミングで改めて覚えておきたいと思います。

## addしたファイルを取り消す

```
$ git add .
```

```
aaa.txt
trash.txt
```

- 誤ってtrashファイルを`add`してしまった。
- `$ git reset ファイル名`で`add`してしまったファイルを取り消すことができる。
- ステージングエリアから外れるという言い方もできる。
- 例】 `$ git reset trash.txt` （trash.txtはファイル名）


## commitを取り消す

ファイル
```
aaa.txt
trash.txt
```
```
$ git add .
$ git commit -m "only aaa.txt"
```

- aaa.txtのみをコミットしたいのだが、現状はtrash.txtもコミットされてしまっている状況


そんな時は下記コマンドを打つ。

```
$ git reset HEAD^
```

- これで`HEAD`（つまり一番直近、先頭のコミット状態）のひとつ前のコミット状況に戻すことができる。
- これで改めて `$ git add aaa.txt（ファイル名）`とすれば、`trash.txt`をコミットせずに済む。
- ちなみに、２個前に戻したい場合は、`HEAD^^`とする。


### git reset --soft と git reset --hardの違いについて

- これらはGitのコマンドで、指定したコミットまで履歴を巻き戻すコマンド。
- `--soft`は、ファイルの変更はそのままに、`インデックス`と`HEAD`だけを指定したコミットまで戻す。
- 一方、`--hard`は、ファイルの変更も含めて`すべて`を指定したコミットの状態まで戻す。
- （※ `$ git reset --soft`　はローカルのコミットをすべてリセットするので注意!!）
- （※ `$ git reset —-hard`　はリモートリポジトリを含めてすべてのコミットを取り消してしまうので要注意‼️）


## pushの取り消し

もう間違ってgit pushまでしちゃったよ。。。という場合。
自分だけで使ってるブランチなのかみんなで共有しているブランチなのかによって異なるが、、、、

ファイルが２つあるとする。
```
aaa.txt
trash.txt
```

それに対して以下を実行したとする。
```
$ git add .
$ git commit -m "only aaa.txt"
$ git push
```

ここまでやったところで、、、
`push`を取り消したい！と思った場合、、、以下を実行する。

```
$ git revert コミットID
```

- 例】 `$ git revert 28daab****6deb37******b3c6ff79f84******`みたいなコマンドになる。
- すると、`revertするけどいい？`みたいにターミナルで聞かれるので、、、writeの`「w」`を打つと実行される。
- これをすると、`push`した対象のファイルは取消される。
- さらにコミットは取り消すひとつ前のコミットに戻る。
- （※ひとつ前のコミットでそのファイル２個を作っていない状態だった場合は、ファイルは削除されるので注意）
- `$ git log`には取り消したコミットの履歴も残される。
Debian 12(bookwarm)でOpenLDAPサーバを構築するぞ

まずはOpenLDAPサーバのslapdをインストール

```
# apt install slapd
```

ブラグインを使うので、これもインストール
```
# apt install slapd-contrib
```
なんかheimdal的なものがたくさん入るので、Kerberos認証のプラグインが多いのか。

使いたいドメインがインストールしたサーバと異なる場合は再設定
```
# dpkg-reconfigure slapd
```

ドメインやらAdministratorのパスワードを聞かれるので答えていく。
設定が終わったら起動

```
# systemctl start slapd
```

`/etc/ldap`配下にslapdの設定ファイルがあると思ったが、ldifファイルでの設定に変更されている？
この辺はOpenLDAPが以前と管理方法を変えたのかもしれない。
記録として現在のバージョンを記載しておく

```
# slapd -V
@(#) $OpenLDAP: slapd 2.5.13+dfsg-5 (Feb  8 2023 01:56:12) $
        Debian OpenLDAP Maintainers <pkg-openldap-devel@lists.alioth.debian.org>
```

どうも設定自体もLDAPサーバに入れていくように見える。
調査してみるとldifを直接編集してパスワードを設定するらしい。まずはハッシュ化したパスワードを作成する。

```
# slappasswd
New password:
Re-enter new password:
{SSHA}XXXXXXXXXXXXXXXXXXXXXXXXXXX
```

この結果`{SSHA}XXXXXXXXXXXXXXXXXXXXXXX`を設定に反映
まずは設定を反映するためのldifを作成

```passwd.ldif
dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}XXXXXXXXXXXXXXXXXXXXXXXXXXX
```

これを反映させる
```
# ldapmodify -Y EXTERNAL -H ldapi:/// -f passwd.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={0}config,cn=config"
```

ここで`-Y EXTERNAL`はユーザ認証を迂回するためのオプション、
`-H ldapi:///`はUNIX Domain Socketを用いるためのオプション
特に必要ない気もするが、念のため再起動

```
# systemctl restart slapd
```

これで通常のLDAPクライアントを用いて設定にアクセスできるようになった。
アカウントは`cn=admin,cn=config`が一般的だが、うまく入れない場合は`/etc/ldap/slapd.d/cn=config/olcDatabase={0}config.ldif`の`olcRootDN`が管理者アカウント名なので確認すると良い。
SQLで暗黙的なソートを避ける

# 暗黙的なソートが発生する演算
- GROUP BY
- 集約関数(SUM, CONNT, AVG, MAX, MIN)
- DISTINCT
- 集合演算子(UNION, INTERSECT, EXCEPT)
- ウィンドウ関数

ソート処理がメモリでは足りずにストレージを用いて行われる場合は、パフォーマンスが大きく低下する。
そのため無駄なソートはなるべく避ける。

## どう避ける?
### GROUP BY
避けることは不可能

### 集約関数(SUM, CONNT, AVG, MAX, MIN)
極値関数であるMAX, MIXに関しては、引数列にインデックスを貼ることで、実テーブルへの検索を回避できる。
ソートを無くしている訳ではないが、検索を高速化できる。

### DISTINCT
２つのテーブルを結合した結果を一意にするためにDISTINCTを用いている場合は、EXISTSで代用することでソートをお回避する。
以下のような会社一覧と、注文一覧があったとして、これまでに注文があった企業を出したい場合を考える。

**company**
| company_id | company_name |
| ---- | ---- |
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |

**orderhistory**
| company_id | price |
| ---- | ---- |
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
| 3 | 400 |
| 1 | 500 |
| 3 | 600 |
| 3 | 700 |

```sql
SELECT
    C.company_name
FROM
    company C
INNER JOIN
    orderhistory O
ON
    C.company_id = O.company.ID
;

company_name
-------------
A
A
B
C
C
C
C
```

1対多の結合なので重複が出ます(INNER JOINは重複削除はしない)。
そのため一意にしようとしてDISTINCを使うのではなく、EXSITSを使うことでソートを避ける。

```sql
SELECT
    C.company_name
FROM
    company C
WHERE
    (
    SELECT
        *
    FROM
        orderhistory O
    WHERE
        C.company_id = O.company.ID
    )
;

company_name
-------------
A
B
C
```

### 集合演算子(UNION, INTERSECT, EXCEPT)
集合のため基本的に重複は許さない。そのため重複削除のためのソートが働く。
ただしALLオプションを付与することで、重複削除をしないため、ソートが発生しない。

### ウィンドウ関数
避けることは不可能
SQLの評価順序

# SQLの高速化
SQLのパフォーマンスに問題があって、チューニング必要という場面はよくあります。
エンジニアの皆さんに役立つtipsではなく、基礎理論をまとめていこうと思います。

# SQLの評価順序
1. FROM
1. ON
1. JOIN
1. WHERE
1. GROUP BY
1. SUM, AVGなどの関数
1. HAVING
1. SELECT, UNION
1. DISTINCT
1. ORDER BY
1. LIMIT

SQLを書くときもこの順序で書くと、より効果的な成果を上げられるかもしれません。
またHAVING句で絞るよりもWHERE句で絞った方が効果的であることもわかります。
【C#】Span<byte>を用いて少しずつハッシュ値計算（IncrementalHash）

# はじめに
数年前に作ったハッシュ値を計算しながらファイル（`Stream`）を暗号化する汎用的なメソッドを、最近のC#コードへ持っていくにあたって、
- `byte[]`を使ったレガシーなストリームの読み取り処理になっていた部分を`Span<byte>`を使ったものに更新
- `Obsolete`属性が付いた`AesCryptoServiceProvider`クラスを使っていた部分は`Aes.Create()`に変更
- `Obsolete`属性が付いた`MD5CryptoServiceProvider`クラスを使っていた部分は`MD5.Create()`に変更

・・・と思ったら、`MD5`クラス（`ICryptoTransform`インターフェース）の`TransformBlock`メソッドと`TransformFinalBlock`メソッドは`byte[]`にしか対応しておらず`Span<byte>`が使えない・・・
クラス一覧を眺めていて代替クラスを見つけたもののクラス名でググっても、まさかの日本語サイトはMicrosoftのドキュメントだけ。英語の情報もかなり少なめ・・・
**「これは有りそうで無い情報を見つけたのでは！？」** と思ったので数年振りにメモ。

ストリームのハッシュ値計算だけなら`HashAlgorithm`クラスの`ComputeHash`メソッドに突っ込むだけで計算できるから意外と需要が無いのかな？

# IncrementalHashクラス
https://learn.microsoft.com/ja-jp/dotnet/api/system.security.cryptography.incrementalhash?view=net-7.0

このクラスを使えば超簡単にできた。
```csharp
/// <summary>
/// ストリームのデータを読み取ってハッシュ値を計算します。
/// </summary>
/// <param name="stream">ハッシュ値を計算するストリーム</param>
/// <param name="hashAlgorithm">計算に使用する使用するアルゴリズム</param>
/// <returns>ハッシュ値</returns>
public static ReadOnlySpan<byte> ComuputeHash(Stream stream, HashAlgorithmName hashAlgorithm)
{
	// 指定されたアルゴリズムでIncrementalHashを生成
	using var incHash = IncrementalHash.CreateHash(hashAlgorithm);

	Span<byte> buff = stackalloc byte[1024];
	for (; ; )
	{
		// ストリームから読み込み
		int readLen = stream.Read(buff);
		if (readLen == 0)
			break;

		// ハッシュ計算
		incHash.AppendData(buff[..readLen]);
	}

	// 計算したハッシュを取得
	return incHash.GetHashAndReset().AsSpan();
}

/// <summary>
/// ストリームのデータを読み取ってハッシュ値を計算します。
/// </summary>
/// <param name="stream">ハッシュ値を計算するストリーム</param>
/// <returns>ハッシュ値</returns>
public static ReadOnlySpan<byte> ComuputeHash(Stream stream)
	=> ComuputeHash(stream, HashAlgorithmName.SHA256);
```
（実際には読み取ったデータをそのまま `CryptoStream` クラスで書き込んだりしてるけど、省略して単純なハッシュ計算処理のみ掲載）

FinalBlockかどうかとかも気にする必要がなく、ただデータを突っ込んでいって `GetHashAndReset()` メソッドで計算結果を取得するだけのお手軽さ。
あと、引数で簡単にアルゴリズムが変えられたので、非推奨な`MD5`から`SHA256`に変えた。

（余談）
無限ループは、`while(true)`よりリテラルを一切書かない`for(;;)`派。
一応、言語（コンパイラ？）によっては、`while(true)`だとループのたびに条件を評価しちゃうとかなんとかを聞いたことがあるような・・・
てか、このコードだと`for`文の中に組み込んでしまう手も・・・
```csharp
for (int readLen = stream.Read(buff);
	 readLen != 0;
	 readLen = stream.Read(buff))
{
	// ハッシュ計算
	incHash.AppendData(buff[..readLen]);
}
```
見やすいかどうかはさておき()

# おまけ（高速ハッシュ値比較）
以前は２つのハッシュ値を格納した `byte[]` を比較するのに、`for`で１バイトずつ比較したり、LINQの`Enumerable.SequenceEqual`を使ったり、強引に`memcmp`したり、どれもイマイチしっくりこなかったけど、今は`Span<byte>`同士を拡張メソッドの`MemoryExtensions.SequenceEqual`で高速比較できて超便利・・・
```csharp
if (!hash1.SequenceEqual(hash2))
{
	// 不一致
	throw new InvalidDataException("ハッシュ値が一致しません。");
}
```
参考：`MemoryExtensions.SequenceEqual`(`SpanHelpers.SequenceEqual`)の高速性について

https://qiita.com/Kujiro/items/e687b089a0348d989f1b#string%E3%81%AE%E3%81%AE%E5%AE%9F%E8%A3%85

# さいごに
長年C#の`byte[]`を使うたびに「もう少し何とかならんのか・・・」と思いつつ「低レベルな実装だから仕方ないのかなぁ」と思っていたところ、`Span<T>`や`Memory<T>`の登場で大幅に改善されたのが感動的すぎて（特に`Slice`が泣けた）、過去・現在・未来の全てのソースから`byte[]`を消し去りたい今日この頃・・・
Databricks secretsをSQLで使おうとしたらハマった話

タイトル通りですが、Databricks secretsに登録した認証情報をSQL言語のセルで利用しようとしたら少しハマったので書き残し。
普通にPythonのセルで使う方が楽だと思います。

## やったこと

https://docs.databricks.com/ja/security/secrets/secrets.html

こちらを参考にクラスター設定内の下部「高度なオプション」のSparkタブに以下を設定。

```:ini
spark.user {{secrets/conection/user}}
spark.password {{secrets/conection/password}}
```

その上で下記のようなクエリをNotebookから実行

```:SQL
CREATE OR REPLACE TEMP VIEW xxx
USING xxx.jdbc
OPTIONS (
    url "xxx",
    dbtable "xxx",
    user "${spark.user}",
    password "${spark.password}",
    driver "xxx"
)
```

すると下記のようなエラーが発生しました。

```
Error in SQL statement: SparkSecurityException: Cannot read sensitive key 'spark.fernet' from secure provider
```


## 解決策

https://community.databricks.com/t5/data-engineering/quot-sparksecurityexception-cannot-read-sensitive-key-quot-error/td-p/27497

これの通りに下記をクラスター設定内の下部「高度なオプション」のSparkタブに以下を追記。

```:ini
spark.databricks.secureVariableSubstitute.enabled false
```

ちなみに私はValiableってタイポして30分ぐらい潰しました。
不正な設定値になってても気付きづらいのはなかなかつらいですね。
[TS] Next.js + postgresの環境構築

# はじめに
無料でDBを使いたいと思い探した結果、Vercelで無料のpostgresができるとのことだったので、試してみた。



# 環境構築
## Next.js の準備
```terminal
npx create-next-app@latest
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/f5fb4e16-a20d-e67f-f938-e83f8c838035.png)


`No / Yes` の選択肢が出たらすべてOKで大丈夫
もしくはVercelのホームページからテンプレートから作成しても良い
    自分はTSのみ選択肢を変えてYesにした(スクショは異なるが)。


```terminal
npm run dev
```
`http://localhost:3000/`で確認することができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/2576cf4f-f3a2-0011-4fc1-625e17d6d29c.png)

## Github と Vercel を連携する

VercelとGihubが繋がっている状態なら、簡単に取り込むことができる。
もしくはVercelからテンプレートを作成することが、簡単にGithubに取り込むことも可能。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/7b1cddb1-39e7-66bd-80f5-e802e4b5f4d8.png)

連携された状態のプロジェクト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/7cb46998-a861-ce2d-0ada-b4d13330f4fd.png)

Githubのデータに基づいて、Vercelでhostingされる。



## postresを導入

`プロジェクト → Storage → Connect Store ボタンをクリック`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/85ab0804-15f8-e10e-854b-3db6387a3024.png)

４つほどの選択肢があるが、今回はPostgresを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/ae4ff85b-c544-99ac-a75c-a04f38b08536.png)

`プロジェクト → Settings → Environment Variables`

postgresへの接続はとても簡単で、.envの情報が自動で入力された状態にある。
local環境で同じくDBとつなぐためには、envデータをコピーし、ローカルで`env.local`を作成し、移すのみ


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/58da84c0-5d0b-21d2-bd3b-2f2068aa7ebd.png)


```:env.local
POSTGRES_URL=
POSTGRES_URL_NON_POOLING=
POSTGRES_USER=
POSTGRES_HOST=
POSTGRES_PASSWORD=
POSTGRES_DATABASE=
```



## 接続の確認

```terminal
npm i @vercel/postgres
npm run dev
```


```typescript:app/page.tsx


import { sql } from "@vercel/postgres";

export default async function Home() {

  const drop = await sql`
  drop table if exists  test;`

  const create = await sql`
  create table test(
    id serial primary key,
    name text
    );`

  const insert = await sql`
  insert into test(name) values('test good');
  `
  
  const { rows } = await sql`select * from test;`
  console.log(rows)

  return (
    <div>
      {rows.map((row) => (
        <div key={row.id}>
          {row.id} - {row.name}
        </div>
      ))}
    </div>
  );
}
```
```terminal:terminal
[ { id: 1, name: 'test good' } ]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/637801e9-c3ff-735a-d899-9cb86770f4dd.png)


# 終わりに
サーバーレスでDBと連携しながら動かしていることがとにかくすごい。
hostingも簡単にできてしまうので、手軽に公開するためのweb siteとしてはとても使い勝手がよろしいと思われる。


# 参考

https://vercel.com/docs/storage/vercel-postgres/quickstart
各言語でカレンダー作成

# きっかけ
- Flutterを利用してクロスプラットフォームなアプリ開発。カレンダーを描画したい。
- カレンダー画面の作成は一苦労。
    - 当該月の始まりと終わりの日にち
    - 週の始まりは日曜なのか月曜なのか
    - 週の中に先月の日付や来月の日付が含まれる場合はどうするか。
- ライブラリやパッケージを駆使するのも良いが、デザインの縛りがあったりでカスタマイズがしずらい。
- 後々、様々な言語でカレンダー画面を作成する可能性がある為、それぞれの言語へ翻訳しておきたい。

# コーディング開始
## Flutterバージョン
### 1. データ生成だけを行うクラスを作成
月を指定して上記の一苦労ポイントを抑えて日にちのリストを生成する。
> [github](https://github.com/asa-leon/calendar_generator_dart/blob/main/lib/calendar_generator.dart)にて全てのコードを確認できます。
```dart:calendar_generator.dart
//...前略
// 週の始まりが日曜日と月曜日のどちらかは、利用する親Widgetで指定する
late bool startFromMonday;

// 指定する日付を引数に、その日付の属する1ヶ月分の日付をリストで返す
List<List<int?>> build(DateTime date){
    // some codes
}
//...後略
```

> 2023年8月の場合↓
>```console:CONSOLE
>[[30, 31, 1, 2, 3, 4, 5],
>  [6, 7, 8, 9, 10, 11, 12],
>  [13, 14, 15, 16, 17, 18, 19],
>  [20, 21, 22, 23, 24, 25, 26],
>  [27, 28, 29, 30, 31, 1, 2]]
>```

### 2. 生成されたデータを描画するWidgetを作成
#### 完成イメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471571/21e08c4f-0be4-95ec-03ad-160662ea37e8.png" alt="calendar view" width="50%" />

#### 描画のアプローチ

- 数値のリスト（2次元配列）の構成： `List<List<int?>>`
    - 1週間分の7つの数値
        - 前月の日を含む週
        - 含まない週
        - 翌月の日を含む週

- 配列内の一つの配列を横に並べて、翌月の日を含む週の配列まで縦に並べて行く。
- 後は`Stack`、`Column`や`Table`ウィジェットを使ってレイアウトする。

#### 大まかなWidget Tree
```plaintext
`MainApp`
v MainApp
  v Scaffold
    v Column
      v Container
        v CalendarWidget // ここから`calendar_widget`
          v Container
            v Stack
              - Text
            v Column
              v Table
                - Text
                ...
              v Table
                v Padding
                  - Text
                ...
```

## TypeScriptバージョン
> 翻訳作業中

***
**更新履歴**
| No. | 日付 | 内容 |
|:-:|:-:|:-:|
| 2 | 2023/8/24 | Flutterコーディングの各項目に詳しい思考過程を追記 |
| 1 | 2023/8/15 | 初稿 |
bash sleepコマンドスリープ（待機）

Bashスクリプトにおいて、特定の時間だけ処理を停止させる必要がある場合がよくあります。このような状況で便利なのがsleepコマンドです。sleepコマンドは、指定した時間だけスクリプトの実行を一時停止します。

### X秒の単位スリープ

```sh
sleep 5  # 5秒間の一時停止
sleep 0.5  # 0.5秒間の一時停止
```

### X分の単位スリープ

```sh
sleep 5m  # 5分間の一時停止
```

### X時間の単位スリープ

```sh
sleep 5h  # 5時間間の一時停止
```

### X天の単位スリープ

```sh
sleep 5d  # 5天間の一時停止
```

### 複合的な時間指定
sleepコマンドは、複数の時間単位を組み合わせて使用することもできます。例えば、1時間2分3秒スリープさせたい場合、次のように指定できます。

```bash
sleep 1h 2m 3s
```
### スクリプト内での応用例
このスクリプトは、5秒おきに「コマンドを実行しました」と表示し続けます。
```bash
while true; do
  # 実行したいコマンド
  echo "コマンドを実行しました"
  sleep 5
done
```

Bashスクリプト内で一時的に処理を停止させる簡単かつ効果的な方法を提供します。そのシンプルさと柔軟性により、さまざまなシナリオでの使用が可能です。コマンドの詳細については、ターミナル内で man sleep コマンドを実行するか、Bash ドキュメントを参照してください。

```
Usage: sleep NUMBER[SUFFIX]...
  or:  sleep OPTION
Pause for NUMBER seconds.  SUFFIX may be 's' for seconds (the default),
'm' for minutes, 'h' for hours or 'd' for days.  Unlike most implementations
that require NUMBER be an integer, here NUMBER may be an arbitrary floating
point number.  Given two or more arguments, pause for the amount of time
specified by the sum of their values.

      --help     display this help and exit
      --version  output version information and exit

GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
For complete documentation, run: info coreutils 'sleep invocation'
```

https://www.geeksforgeeks.org/sleep-command-in-linux-with-examples/
Googleダークウェブレポートで個人情報漏洩を確認をしてみた

## Google One ダークウェブレポートとは？
オンライン上のプライバシーを守るための一つの手段として、Googleが提供している機能

Google One
https://one.google.com/

<font color="Red">ユーザーの個人情報がダークウェブ上で漏洩していないかをチェックする機能</font>で、具体的には、ユーザーがGoogleに登録したメールアドレスや関連情報がダークウェブ上に出回っていないかを定期的にスキャンする。もし情報が漏洩している場合、ユーザーに警告を送り、どのような情報が漏れているのかを知らせる

無料でスキャンできる対象は、**メールアドレス**と**パスワード**のみ。
有料のGoogle Oneに登録することで、以下の情報をスキャン対象にできる
```
名前
社会保障番号（米国のみ）
生年月日
住所
メールアドレス（最大 10 個）
電話番号（最大 10 件）
```

## そもそもダークウェブとは

普通のGoogle検索等ではヒットしない、ちょっと隠れたインターネットの世界。
特定のソフトウェアや認証を通じてのみアクセスができる。

##### なぜ通常の検索エンジンでダークウェブがヒットしないのか？
通常の検索エンジン（例：GoogleやBing）でダークウェブのサイトが表示されない主な理由

##### 1. インデックス化の拒否
ダークウェブのサイトは、検索エンジンのクローラーがアクセスできないように設定されているため、サイトの内容が検索エンジンのデータベースにインデックス化されない。インデックス化の拒否とは、ウェブサイトの所有者が検索エンジンのクローラーから特定のページやサイト全体を隠すための方法

**例1:robotsファイル**
ウェブサイトのルートディレクトリに配置されるテキストファイル。
クローラーにどのページを巡回すべきか、または巡回すべきでないかの指示を与えることができる。

以下は、全てのクローラーに対してサイト全体の巡回を禁止する例
```
User-agent: *
Disallow: /
```

**例2:metaタグの使用**
HTMLの&lt;head&gt;セクション内に配置される&lt;meta&gt;タグを使用して、特定のページが検索エンジンにインデックス化されないようにする。

以下はその例
```
<meta name="robots" content="noindex">
```

##### 2. アクセス制限（特殊なドメインやソフトウェアが必要）
ダークウェブのサイトは特殊なドメインを使用しており、このドメインは特定のソフトウェア等を用いてのみアクセスができる。

**ドメイン例**
1. "**.onion**"はTorネットワーク専用の匿名ドメインで、Torブラウザを通じてのみアクセス可能
2. "**.i2p**"は「eepsite」と呼ばれ、独自のドメインを使用し、I2Pソフトウェアを用いてアクセス可能
3. "**.bit**"はNamecoinという分散型のドメイン名システム（DNS）を使用し、Namecoinクライアントを用いてアクセス可能

:::note warn
警告
ダークウェブには合法的なサイトや情報も存在しますが、違法な活動や商品の取引、危険な情報が流通している場所も多いため、アクセスや利用には十分な注意が必要
:::

## Googleダークウェブレポートで自分の情報があるか確認してみる
まずは、[Google One](https://one.google.com/)にアクセスする

TOPページの中央に、ダークウェブレポートへのリンクがあるので、**今すぐ試す**をクリックする
![貼り付けた画像_2023_08_15_17_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/f05c8b45-7c5b-1863-394a-4f0f01dd124b.png)

ダークウェブレポートの説明が記載されているページにいくので、内容を確認する
![貼り付けた画像_2023_08_15_17_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/c6952db0-6b24-cdd7-42f3-01d901b5c4e2.png)

問題なければ、一番したにある**スキャンの実行**をクリック
![貼り付けた画像_2023_08_15_17_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/92361a0f-b21c-2d4a-3da4-793660f956cd.png)

### 特に何も見つからない場合
**一致する結果はありません**とのことで、情報漏洩が確認できなかった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/0686f758-831f-7c88-c1a3-f3debd91ead9.png)

### 情報漏洩が確認された場合
漏洩が確認された場合、もう少し詳細が確認できる
![貼り付けた画像_2023_08_15_17_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/2f02bf0d-67fc-4d32-2e85-9c7012fb8c78.png)

実際に漏洩した情報の詳細の確認
複数のCollectionで、漏洩日、メールアドレスとパスワードの流出を確認
さらに、右端にある&gt;をクリックし、詳細を確認可能

![貼り付けた画像_2023_08_15_17_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/dde5b78e-34f4-ffc0-7778-184196a45273.png)

発見されたパスワードは昔使っていたやつ・・・。
うん、しっかり漏洩しているということがわかったぞ！！
![貼り付けた画像_2023_08_15_17_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/2a7f395d-6f1c-16d7-7931-7cb27b804396.png)
Flutter UI構築でExpandedはかなり使える話

# はじめに
初心者にとってはExpandedの使い所がイマイチわからなかったりするものかと。。。

https://api.flutter.dev/flutter/widgets/Expanded-class.html

>A widget that expands a child of a Row, Column, or Flex so that the child fills the available space.
行、列、またはフレックスの子を展開して、使用可能なスペースを埋めるウィジェット。

**要は「目一杯要素を広げてくれるウィジェット」です。**
このExpandedを使いこなせれば、少し悩むUIの構成もシンプルに実装できたりします。

Expandedの使える使用例をいくつか紹介！！

# ２つの要素を画面幅の半分ずつ表示
![Screenshot 2023-08-15 at 16.34.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/d481b29e-b6fc-06de-6cd9-9689b0676978.png)
端末の大きさに関係なく、常に画面の半分ずつ何かを表示したいとき

```dart
    return Row(
      children: [
        Expanded(
            child: Container( ),
        const SizedBox(
            child: VerticalDivider(
              thickness: 1.0,
            )),
        Expanded(
            child:Container( ),
      ],
    );
```

# Column内の要素を一部だけ真ん中にする
![Screenshot 2023-08-15 at 16.57.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/d58a1acb-2c3a-a721-990a-68826ebaede6.png)

```dart
    return Center(
        child: Column(
      children: [
        const Container(), // 上に表示
        const Expanded(child: SizedBox()),
        Container(
          
        ),
        const Expanded(child: SizedBox()),
      ],
    ));
```

# Row内の要素を一部だけ右端にする
![Screenshot 2023-08-15 at 17.27.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/e54d4387-01ee-f3ea-1e50-dd5b56f94cc2.png)

```dart
 final deviceWidth = MediaQuery.of(context).size.width;

    return Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
             Expanded(
                  child: Padding(
                    padding: EdgeInsets.only(left: deviceWidth * 0.1), // 画面幅に対して10%の余白
                    child: const Text(
                      'Text',
                      textAlign: TextAlign.center,
                    ),
                  ),
                ),
              // 右端のばつボタン
              Container(
                  padding: const EdgeInsets.only(right: 15),
                  child: GestureDetector(
                    onTap: () {
                      Navigator.pop(context);
                    },
                    child: Image.asset(
                      'images/icon/Close.png',
                      width: 24,
                      height: 24,
                    ),
                  ),
                ),
      ],
    );
```

テキストを画面幅に対して中央に表示するには少し工夫が必要でした。。
普通に中央寄せすると`Expanded`の領域内で中央になり、画面幅に対しての中央とは少しズレた位置になります。
なので`Padding`で無理やりleftに余白を与え、テキストを画面幅に対して中央に表示


Expandedは使い方が色々あって難しいですが、いい感じに使えればとても便利なウィジェットです！
【Laravel】L5-Swaggerでファイルを含むリクエストボディを定義する

# 目的
L5-Swaggerは、LaravelのOpenAPI（Swagger）の仕様書を記述するためのライブラリです。
リクエストボディにファイルを含む場合のSwagger-PHPの記述方法を備忘録として残します。

# 実行環境
- Laravel 10
- OpenAPI 3.1.0

# 記述方法

下記の例のように`@OA\MediaType`を指定する必要があります。
参考: [File Upload (Swagger)](https://swagger.io/docs/specification/describing-request-body/file-upload/)
ファイルの場合、プロパティのtypeは`string`、formatは`binary`です。

```php
    /**
     * @OA\Post(
     *     path="/api/image",
     *     summary="画像をアップロードする",
     *     @OA\RequestBody(
     *         @OA\MediaType(
     *             mediaType="multipart/form-data",
     *             @OA\Property(
     *                 property="image",
     *                 type="string",
     *                 format="binary"
     *             )
     *         )
     *     )
     * )
     */
```

これは、次のyamlの定義に相当します。
```yaml
paths:
  /api/image:
    post:
      summary: 画像をアップロードする
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                image:
                  type: string
                  format: binary
```

Swagger UIでも、ファイルのアップロードを検証することができます。

![スクリーンショット 2023-08-15 17.33.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1995792/f2014421-e7fa-c1c6-52e0-2633028d6183.png)
国産クラウドは何が今あるのか

## はじめに
デジタル庁の記事以来ずっとデジタル庁の動きを見ています。2023/08/15に「政府クラウドの『国産』後押し」という記事が出ました。

https://www.yomiuri.co.jp/economy/20230814-OYT1T50278/

確かに今、Saasを除くクラウドサービスといえば、Amazon,Google,Microsoftが多く使われています。実際、現在のガバメントクラウドもAWSやAzureが使われています。
政府が国産を後押ししたい理由としては、為替の問題や外交などの政治的な問題、経済的な問題等多数あるからだと思われます。
しかし今あまり日本のクラウドサービスに関する技術記事はほとんど見かけません。実際に今どんな国産クラウドがあるのかをすごくざっくりと調べてみました。ただしSaasは除きます。

ちなみに、Qiitaでそれぞれのサービスを検索するとヒットする件数は、「AWS」が64356件、「GCP」が10618件、「Azure」が16018件です。（2023/08/15現在）

## さくらのクラウド (さくらインターネット)
https://cloud.sakura.ad.jp/

国産クラウドと聞いてまず思い浮かべる方も多いのではないのでしょうか。日本の老舗IT企業、さくらインターネットが提供するクラウドサービスです。
コンピューティング、ストレージ、データベース、VPCなどWebサービスを公開する上で必要なサービスが一通り揃っています。オートスケーリングやセキュリティーサービスなども手軽に行えるみたいです。データセンターは石狩（北海道）、東京、大阪の3拠点です。国内だけにむけたサービスであれば使ってみるのもありかもしれません。
デメリットとしては、ハンズオンがあまり豊富でない、使ってみた記事があまりない、AWSのような無料枠がないため手軽に試してみたいということができないところです。
「さくらのモノプラットフォーム」というIoT向けサービスも展開しているみたいですね。
Qiitaで「さくらのクラウド」と調べるとヒットした記事数は821件でした。

## ALTUS (GMOクラウド)
https://altus.gmocloud.com/

お名前.comで有名なGMOのグループ会社「GMOクラウド」が提供するクラウドサービスです。GMOクラウドってすべてクラウドサービスなのかと思ったらどうやらこのALTUSがIaasにあたるようです。
BasicとIsolateのプランがあるみたいです。IsolateはVLAN環境を搭載しているそうで、セキュアなプライベート環境を構築するのに向いているそうです。
こちらもコンピューティングやストレージ、データベースなどWebサービスを公開する上で問題ないサービスを提供しています。こちらは14日間の無料サービス期間があるようです。
Qiitaで「GMO Altus」と調べるとヒットした記事数は18件でした。

## SDPF (NTTコミュニケーションズ)
https://www.ntt.com/business/sdpf.html

NTTコミュニケーションズが提供するクラウドサービスです。Smart Data Platformの略です。法人向けみたいです。こちらのサービスはWebサービス向けのサービスももちろんありますが、データ分析やデータ活用、IoT向けのサービスを提供しているのが特徴的だなと思いました。データ加工や分析などのサービスもあります。
Qiitaで「sdpf」と調べると2件ヒットしましたが、こちらのサービスに触れてる記事ではありませんでした。

## FJcloud （富士通）
https://jp.fujitsu.com/solutions/cloud/fjcloud/

ガバメントクラウド系のサーバーも提供しているみたいです。音声認識サービスや、IoT、コンテンツ配信サービスなんかもあるみたいです。

Qiitaで「Fjcloud」と調べると、4件ヒットしました。
## ニフクラ(富士通クラウドテクノロジーズ）

https://pfs.nifcloud.com/

同じ富士通でややこしいですが、富士通がサービスをニフクラのサービスを提供する際は「Fjcloud-V」となるみたいです。コンテナ向けサービスなんかも提供しているみたいです。国産クラウドの多くが法人向けっぽい感じなのに対し、ニフクラは個人向けにも力を入れているっぽいです。2ヶ月の無料枠もあるみたいです。技術ブログも配信しているみたいです。

Qiitaで「ニフクラ」と調べると、349件ヒットしました。割と多いですね。

## NEC Cloud Solutions (NEC)
https://jpn.nec.com/cloud/index.html

NECが提供するクラウドサービスです。こちらも法人向けみたいです。

## IIJ GIO P2 Gen.2 (IIJ)
https://www.iij.ad.jp/biz/p2/

IIJのオリジナルIaaSのようです。法人向けっぽい感じですかね。

## 調べてみて思ったこと
ここからは完全に自分の感想です。
国産クラウドもそこそこあるんだなって思いました。多くの人が使いやすいのは「さくらのクラウド」、「ALTUS」、「ニフクラ」ぐらいでしょうか。

しかしどれも敷居が高そうに思えます。少なくとも自分は今すぐこれらを使おうとはなりにくいです。思うに、あまりハンズオンの記事がないのが非常に問題だと思います。

AWS、GCP、Azureの強みは1年間の無料枠、そして技術的に枯れているおかげで多くのハンズオン記事が載っていることが挙げられると思います。これだけの無料枠があると、気軽に立ち上げられるし、気軽にハンズオンを行えます。すると多くの人がサービスに触れられるおかげで、技術記事が多くつくられ、結果的にサービスの利用者が増え使ってみようというスパイラルが生まれるのではないでしょうか？

扱えるエンジニアが増えないことにはサービスは尻すぼみになると思います。例えば今自分がサービスを立ち上げたとして、「AWSエンジニア募集します」と「さくらのクラウドエンジニア募集します」と求人を出したら圧倒的にAWSエンジニアの方が募集が集まりやすいです。それは扱えるエンジニアが多いからです。

国産のSaasでも[microCMS](https://microcms.io/)は無料枠もあり、使い方などもわかりやすく載せていたりしているおかげで結構microCMSを使ってみたなどの記事もあり、国内で成長しているサービスとしてはとてもいい例だと思います。

https://microcms.io/

タダで使わせろと主張したいわけではなく、利用者を増やす取り組みをしてほしいと主張しています。AmazonやGoogle,Microsoftなんかは巨額の資本をもっているからコストの面ではなかなか苦戦するとは思います。しかしせっかくQiitaやZennといった技術ブログプラットフォームが発展していて、かつ日本人のほぼ全員が日本語を読めるこの環境だからこそ、もっと国産クラウドも顧客を獲得するためにあらゆる発信手段を使って盛り上げてもらいたいなと思っています。せっかくこの政府の後押しもあるこの機会こそ。

## 参考
https://www.gadgeblo.com/cloud-service-brand/
略称まとめ

# これってなんの略?って時に見る記事
自分のような初心者だと略されると何がなんだかわからんので備忘録的な感じでまとめます
## 略語
実際の単語 日本語の意味 コマンドの意味
## linux系
### bin
binary 置き場
### ls
list segments リスト区切りカレントディレクトリ内を出力
x86_64のUbuntuでarm64のdockerイメージを実行する

arm64のCPUアーキテクチャを使用しているLambda関数用のレイヤをWindowsで作成したかったのですが、`exec /bin/sh: exec format error`がどうしても解消できず、インターネットの海を彷徨っていたところ、数ヶ月越しに解決策が見つかりました。  
[Docker exec /bin/sh: exec format error on Arm64](https://stackoverflow.com/questions/73253352/docker-exec-bin-sh-exec-format-error-on-arm64)

## 前提条件
別で書いた「[WSL2でDocker環境構築(Docker Desktop有料化対策)](https://qiita.com/haveAbook/items/0d0ae20a19214f65e7cd)」の通りに環境構築していること。

## 手順
QEMUをインストールする
* dockerドライバがサポートしているプラットフォームを確認する。
  ```terminal
  docker buildx ls
  ```
  おそらくamd64(x86-64)しかサポートされていない。
  ```terminal
  NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT             PLATFORMS
  default * docker                                                                                                          
  default   default         running v0.11.6+0a15675913b7 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386
  ```

* QEMUをインストールする。
  ```terminal
  sudo apt-get install -y qemu qemu-user-static
  ```

* 再度確認したら、arm64のサポートが追加されているはず。
  ```terminal
  docker buildx ls

  NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT             PLATFORMS                                                        
  default * docker                                                                                                          
  default   default         running v0.11.6+0a15675913b7 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386, linux/arm64, linux/riscv64, linux/ppc64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
  ```
【プラクティス紹介】1分でさらっと分かる「レトロスペクティブ」

![scrum_e_retro.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526800/ad47a654-b2ea-2795-7ca3-5e2de76decb3.jpeg)


## プラクティス名（別名）
レトロスペクティブ （ふりかえり、レトロ、スプリントレトロ～、リリースレトロ～、プロジェクトレトロ～）

:::note info
　スプリントレトロスペクティブ　：スプリントの最終日に行うふりかえり
　リリースレトロスペクティブ　　：リリースを行うたびに行うふりかえり
　プロジェクトレトロスペクティブ：プロジェクト完了後に行うふりかえり
:::

## プラクティスの目的・狙い
* 気づき、学びの共有
* チームの成長
* 関係の修復

## どんな時に使うか
* スクラムでは必須（最低限スプリントレトロは実施する）
* チームの問題を解消したい時
* チームを改善し、方向性を軌道修正したい時

## 実施手順
※以下はスプリントレトロの場合
1. スクラムチーム全員でふりかえり、良かった点や改善したい点について話し合う
1. 主な観点は５つ「個人」「相互作用」「プロセス」「ツール」「完成の定義」
1. プロダクトの課題より、チームの課題（活動やコミュニケーション）に着目する
1. 次スプリントで行う改善アクションを最低1つは決める（多すぎてもよくない）

とくにスプリントゴールが未達に終わった回はPOとDEVの間に溝ができがちなため、原因と対策について掘り下げ、同じ失敗を繰り返さないように最大限努力する。納得感のある改善策を提示することでPOとの関係を修復することができ、前向きな気持ちで次のスプリントに臨むことができる。これはDEV間の関係についても同様。

## アレンジ例
* YWTやKPTといったフレームワークを使って事前に各自で意見を書き出しておく
* 2週間スプリントだが、レトロスペクティブは毎週実施する

## アンチパターン
* 発言が特定のメンバーに偏っている、そもそもいつも参加しない人がいる
* 悪かった点ばかりに注目してしまい憂鬱なイベントになる
* 特に困ってることは無いので改善する点も無い、という姿勢

## 参考情報
[公式スクラムガイド(2020年日本語版)](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)

## こぼれ話（私的コメント）
ウォーターフォール出身者は「ふりかえり」と聞くと"できればやっといた方がいいもの"ぐらいの温度感で認識されている方が多いのですが、スクラムにおいては"絶対にやらないとダメなヤツ"です。レトロをやらずにどうやってスクラムを回すのか、ぐらいの勢いです。
レトロで悩むのが誰がファシリテーターを務めるべきか、という点。定番はSMだと思いますが、DEVが主体性を持ち始めたら任せてもいいと思いますし、チームをリードしてくれるタイプのPOだったらその人が適任かもしれません。逆に避けた方がいいかもと思うパターンは持ち回り制ですね。レトロをきちんと回すってそんなに簡単じゃないので、ある程度は個人に集約した方が無難な気がします。でもその場合は「ファシ役はいつも自分の意見が言えない」問題があるので悩ましい。
余談ですがアジャイル界隈では「振り返り」ではなく「ふりかえり」とひらがなで表記することが多いです。(りゆうはマニアックなので省きます。悪しからず。)

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
【プラクティス紹介】1分でさらっと分かる「スプリントレビュー」

![scrum_e_review.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526800/41fc9140-bad4-ccd5-df54-c0b533630981.jpeg)


## プラクティス名（別名）
スプリントレビュー　（デモ、ショーケース）

## プラクティスの目的・狙い
* スプリントの成果物確認（デモ）
* ユーザからのフィードバック収集

## どんな時に使うか
* スクラムでは必須（スプリント期間の最終日付近に実施）
* プロダクトのユーザ満足度を確認したい時
* プロダクトに対する新たな要望を引き出したい時

## 実施手順
1. PO主催で関係者（任意のステークホルダー）を集めてレビューを開催する
1. DEVより今回のスプリントの成果物（＝インクリメント）をデモする
1. PO（とステークホルダー）は要求にマッチしていることを確認する
1. プロダクトの所感や改善要望をDEVにフィードバックする（必要に応じてPBIを追加）
1. 今後の予定や見通しを共有する（リリース時期や完了日など）

なおスプリント内で作り切れなかった機能があった場合でも、プロダクトとしては使える形（＝その気になればリリースできる状態）にして提供すること。レビューの合否と実際のリリースタイミングは切り分けて考えてよい。POに不合格と判断された場合でもスプリント期間は延長せず、未完了のPBIは一旦プロダクトバックログに差し戻す。

## アレンジ例
* PBI（ユーザストーリー形式）のシナリオに沿ってデモを行う
* DEVからデモするのではなく、PO（やステークホルダー）に直接触ってもらい、その様子を観察する

## アンチパターン
* レビュー時間を終始デモで使ってしまい、次に向けたフィードバックを聞けていない
* PO不在のレビュー開催

## 参考情報
[公式スクラムガイド(2020年日本語版)](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)



## こぼれ話（私的コメント）
スプリントレビューは誰から誰に対して行うものか、については２つのケースがあります。

1. 「DEV」から「PO＆ステークホルダー」へ
1. 「DEV＆PO」から「ステークホルダー」へ

どちらのケースになるかはPOの立場やPO自身がエンドユーザの一人かどうかによっても変わってきます。
いずれのケースでもPOがレビューの場で初めてインクリメントを目にするという状況はあまり望ましくないと思います。スプリント途中でも仕様確認の意味も含め、先行して触ってもらった方が無難です。レビューは受け入れ検証とは別物で、あくまでも最終確認の場だと思った方が良いでしょう。

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
【プラクティス紹介】1分でさらっと分かる「デイリースクラム」

![scrum_e_daily.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526800/a1b14548-698f-6b8b-705d-e650869d2d0a.jpeg)


## プラクティス名（別名）
デイリースクラム　（朝会、昼会、夕会、スタンドアップ・ミーティング、３つの質問）

## プラクティスの目的・狙い
* ゴール達成に向けた状況の共有（＝透明性）
* 問題の早期発見/対処（＝検査/適応）

## どんな時に使うか
* スクラムでは必須（毎日決まった時間と場所で開催）
* 今、誰が何を進めているのか共有されておらず手戻りが増える
* 問題発生によりタスクが遅れていることが数日後に発覚することが多い

## 実施手順
1. 参加者はDEV（必須）とSM,PO（任意）
1. チームで集まり、進捗・予定・課題などを簡潔に共有する
1. 人数に関わらず15分以内に終わらせる
1. 課題検討などが必要であれば別会議を設定しデイリーの中では概要に留める

DEVのためのイベントであり、SMやPOへの進捗報告会**ではない**。
立ったまま行われることも多いため、デイリースタンドアップとも呼ばれる。


## アレンジ例
* タスクボード（カンバン）の前に集まって、タスクカードを移動させながら話す
* バーンダウンチャートを表示し、現状認識を揃える

## アンチパターン
* デイリーの中で詳細に話しすぎてしまい、いつも15分で終わらない

## 参考情報
[公式スクラムガイド(2020年日本語版)](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)

デイリースクラムの悩みやコツについてはRyuzeeさんが全て言い尽くしてくれている感があります。
[『デイリースクラムが15分で終わらないのですが、どうしたらいいですか？』](https://www.ryuzee.com/faq/0027)
[『デイリースクラムのTIPS』](https://www.ryuzee.com/contents/blog/7083)


## こぼれ話（私的コメント）
以前は「３つの質問」ということで「昨日やったこと、今日やること、障害はないか？」について話すと良いとスクラムガイドにも記載されていましたが、2020年版の改訂で「指示的すぎる」という理由で削除されています。
SMやPOはデイリーに出なくていいのか？という点に関しては、スクラムガイド2020にはSMやPOにDEVとしての顔があるならDEVとして参加しよう、と書いてあります。デイリースクラムはチームの縮図。それを見ればチームの練度が分かるのでSMとしては時間の許す限り毎回参加したいところです。POが参加すべきかどうかはDEVとの関係性（距離感）にもよると思いますが、時々は顔出してもよいのではと思います。というか顔出してくれるようなPOが欲しいです。
逆にDEV側にPOには内情を知られたくないという温度感があるとしたら「透明性」の原則について考え直した方がよいかもしれません。

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)