OmniAICreator/Qiita-1.07M huggingface dataset:
2024/07/02備忘録

## IDMC
クラウドやオンプレミス(自社に設置している)上のデータをワンプラットフォームで処理する。
ユーザなどが必要とするデータに関する機能を提供している。
その中の一つがIICSというもの。


## そもそもIICSって？
クラウド上のデータ結合や管理の為のプラットフォーム。
	企業がデータの結合や品質管理、セキュリティなどをクラウド上で効率的行うためのツール。
	データ結合やデータ管理をクラウド上で効率的に行うための協力的なプラットフォームのこと。

#### 【以下のようなコンポーネント構成】
* データ結合(DI)：異なるデータソース間で結合する機能
* アプリケーション結合(API)：異なるアプリケーション間でデータを結合しリアルタイム同期する機能
* データ品質管理(DQ)：データのクレンジング、標準化、検証を行い、データ品質を保つ機能
* マスターデータ管理(MDM)企業全体の重要なデータを一元管理し、一貫性のあるデータを提供する機能
	
#### 【IICSのアーキテクチャ】
・Informatica Cloud:IICSの中核となるクラウドベースのプラットフォーム
・Secure Agent:クラウドとオンプレミスのデータソース間で安全にデータを転送するためのエージェント
・Connector:異なるデータソース(データベースやファイルやAPなど)との接続を可能にする
	
#### 【使用例】
* ETLプロセスにおけるデータの抽出、変換、ロードを自動化しデータウェアハウスに結合する
* リアルタイムデータ同期：異なるアプリケーション間でリアルタイムにデータを同期し、ビジネスプロセスの効率を向上させる
* データクレンジング：データの不正確さや重複を排除し、データの品質を向上させる
	
※データウェアハウス：ここでは目的別に編成されたデータを保管する場所として理解する
	
## IICSのCDI(Informatica Cloud Data Integration)とは？
クラウドや自社サーバーに存在する大量のデータをシームレスに結合してくれるもの。
infomaticaに用意されているドライバを使うことで色んなデータソースから様々なデータを結合することができる。

* Filter（フィルタ）とRouter（ルーター）
    * Filter：入力されてきたデータを条件によって絞り込むもの(SQLのWHERE句みたいなもん)
	* Rounter：入力されたデータを条件に応じて複数のグループに分けて出力してくれるもの

* Sorter（ソーター）
	* データをソートしてくれるもの
	* 後々に使うアグリゲーターという集約関数の機能を提供してくれているインターフェイスの前にやる必要がある
			
* Aggregator （集約関数）
	* 集約関数の機能を提供しているインターフェイス
    * AVGやSUMなどがある


## 【ETLとはなんぞや？】

#### そもそもETLって？
ETLとは「データの抽出」、「データの変換」、「データの書き出し」の略語からなる言葉。
データベースやシステムからデータを抽出しフォーマットに変換して、データウェアハウスなどに書き出す一連のプロセス。一般的にはデータを保存する前に行われる。
主な活用ケースとしてはBIなどで分析をする際に使われる。
		
* 抽出(Extract)
    基幹システムやデータベースからデータを抽出する。
	どのような目的でデータを抽出するのか明確化してから作業に臨むと、どんなデータを抽出すれば良いか分かるので効率が良くなる
		
		
* 変換・加工(Transform)
		データを保存しやすいように一定の規則に従いデータを変換、加工する
		注意点として保存場所(データウェアハウス)に適したデータ形式を把握せず、別の形式でデータを抽出してしまうと変換や加工に大幅な時間がかかってしまう
		そのため、各過程で担当者が異なる場合には情報を共有する必要がある
		
* 書き出し(Road)
		変換、加工済みの過程で作成したデータを保存する場所に書き出す工程
		データウェアハウスが保有する「インポート命令」というものを利用すると効率的で、SQLのINSERT文よりも一度に大量のデータを高速に取り込める
		

### 【データウェアハウスとは】
簡単に言うとデータを保管しておくデータベースのこと。
DWHは、意志決定のため、目的別に編成され、統合された時系列で、削除や更新しないデータの集合体」と定義されている。
	会計管理や在庫管理など様々なシステムなどから集められる。
	
### 【データウェアハウスとデータベースの違いは？】
データウェアハウスはデータ分析に特化したデータベースのこと。
	超並列処理のアーキテクチャを採用しており、１つのクエリ処理を同時に処理する事ができるため、
	通常のデータベース処理における検索、分析機能を飛躍的に高く発揮できる。
	また、データの格納もデータ毎(顧客や商品、店舗など)に分解・整理されているので
	データ分析に適している。
	さらに、データが時系列に沿って消去・更新されることなく常に蓄積されていく。
	
	
### 【データレイクとは】
主な違いとしては格納されるデータが違う。
	データレイクは、構造化データに加えて、データベース化できない非構造化データも対象にしている。
	非構造化は例えば電子メールや画像や動画などを指す。
	データレイクでは、これらのデータが、加工を施されることなくそのままの形で一元的に格納される。
	
もっと詳しい情報に関しては以下のリンクを参照する。

### 【BIとは】
BI(ビジネスインテリジェンス)とは、企業のシステム集められているデータを分析し、経営上の意思決定に役立てられるツール。
	BIはデータを有効活用し、ビジネスのパフォーマンスを向上させる。

#### 【参考サイト】
[ETLとは？](https://it-trend.jp/etl/article/function "ETLとは？")
[DWH（データウェアハウス）とは？](https://www.dal.co.jp/column/b-dwh/ "DWHとは？")
[【パートナーブログ：クラスメソッド】IICS CDI Mapping Designer入門](https://www.informatica.com/jp/blogs/classmethod_partnerblog22.html "informaticaのCDI")
Scriptから別Scriptを実行／別フォルダを参照したい

# はじめに

Script内にScriptから見たフォルダやScriptの相対パスを定義したのに、正しく実行されない。。。
Scriptを呼び出す際、Scriptを呼び出す場所に関わらず内部で子Scriptを呼び出したい場合はどうすればいい？
という疑問を解消する為の処理について、紹介します。

対象ユースケース：
- Scriptを呼び出すカレントディレクトリに関わらない結果を担保する
- 親Scriptに子Scriptの相対パスを定義し、実行する
- Script内に相対パスを定義したフォルダに対して操作する

# 環境
Windows／Linuxの端末

# Script内の記述

## Windows の場合

Windows では　[Get-Location](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/get-location?view=powershell-7.4) というモジュールがあります。
これは、現在のディレクトリを表すオブジェクトを取得します。
結果をアーカイブしておき、[Set-Location](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/set-location?view=powershell-7.4) というモジュールでScriptが配置されているディレクトリへ移動します。
```
# 現在のディレクトリの位置を記録
$LOCATION_ORG = Get-Location
# スクリプトの位置に移動
$SCRIPT_DIR = $PSScriptRoot
Set-Location $SCRIPT_DIR
```

このままScriptを終えると、Set-Location で移動した位置が最終的な作業ディレクトリとなってしまいます。
そこで、Get-Location で取得しておいた実行前の位置に戻る処理を実行します。
```
# PowerShell Script実行前の位置にディレクトリ移動
Set-Location $LOCATION_ORG
```


## Linux の場合

Linuxの場合は簡素で、Script内で実行するパスに移動してもScript実行後はカレントディレクトリに変わりはありせん。
```
cd `dirname $0`
```

# 終わりに

スクリプトを呼ぶスクリプトを書くときにハマるところかな、と思います。
ご参考になれば幸いです。
KQLを使ってLog Queryを長期間アーカイブしたい

# はじめに

とある事情でKubernetes Clusterのログ出力を取得するKQL結果をアーカイブすることになったので、備忘録を残します。

対象ユースケース：
- KQLの実行結果をLog Analyticsワークスペース以外で確認したい
- 環境毎にLog Analyticsワークスペースが分かれているので、環境毎にLog Queryをアーカイブしたい
- Log Analyticsワークスペースの保管期間を超えてLog Queryを外部に保管したい

# 実行環境
Azure CLIが導入済み
az Login済み
PowerShellを実行可能な端末

# フォルダ構成

スクリプトに関するフォルダ構成はこのような形になっています。
KQLは非常に長くなることがあるので、別にファイルとして記述しております。
```
Root Path
├── archive/
│   ├── 202401010000.csv
│   ...
├── log_query/
│   ├── log_query_fuga.txt
│   ...
└── <当該Script>.ps1

```

# 引数・環境変数の定義

環境変数をここで定義ています。
変数は、環境とCluster名を使用しています。
```
param(
  [string]$ENV,
  [string]$CONTAINER_NAME
)
```

開発・本番などのLog AnalyticsワークスペースIDを定義しています。
ここではハードコーディングしていますが、必要に応じてグローバル変数に置き換えてください。
日付はログローテーションの為定義しています。
```
# 開発環境Log Analytics Workspace ID
$WORKSPACEID_DEV = "<Workspace ID for DEV>"
# 本番環境Log Analytics Workspace ID
$WORKSPACEID_PRD = "<Workspace ID for PRD>"
# アーカイブ先のディレクトリ
$ARCHIVE_DIR = "archive"
# 日付
$DATE = Get-Date -Format "yyyyMMddHHmm"
```

Script内で、KQLファイルが記述されているファイルとScriptとの相対的な位置を使用するので、その為の記述です。

```
# 現在のディレクトリの位置を記録
$LOCATION_ORG = Get-Location
# スクリプトの位置に移動
$SCRIPT_DIR = $PSScriptRoot
Set-Location $SCRIPT_DIR
```
詳しくは[こちらの記事](https://qiita.com/gKhdrt_chan/items/e129e64ed5e7a1ba65ff)をご参照ください。

## 

引数の環境変数文字列に応じて、KQLを実行するLog Analyticsワークスペースを切り替えます。

```
# 引数ENVを大文字に変換
$ENV = $ENV.ToUpper()

# 引数ENVから環境の切り替え
if($ENV -eq "DEV"){
  # DEV環境
  $WORKSPACEID = $WORKSPACEID_DEV
}
if($ENV -eq "PRD"){
  # PRD環境 
  $WORKSPACEID = $WORKSPACEID_PRD
}
```


# KQLに関する処理

## KQLの取得
ファイルとして記載されたKQLを読み込み、実行します。
任意のコンテナー、任意のPod／Jobなど分ける場合、引数となる環境変数が多くなる場合あり。
```
# 引数CONTAINER_NAMEからLog Queryの取得
$QUERY_PATH = "./log_query/log_query_$CONTAINER_NAME.txt"
```

## KQLの実行
アーカイブ対象となるKubernetes Clusterのログが出力されるLog AnalyticsワークスペースからLog Queryを取得し、結果を格納します。

```
Write-Host $QUERY
$QUERY = @"
  $(Get-Content -Path $QUERY_PATH)
"@
# Log Analyticsから分析結果を取得
$QUERY_RESULT = Invoke-AzOperationalInsightsQuery -WorkspaceId $WORKSPACEID -Query $QUERY
```

## エラーハンドリング
Query応答に応じて、エラーハンドリングをします。
必要に応じて、内容は変えてください。
正常にQueryが返ってきていた場合、対象フォルダにファイル名が日付のCSVファイルがアーカイブされます。

```
if($QUERY_RESULT.Error){
  Write-Host "クエリーにエラーが生じました。: $($QUERY_RESULT.Error)"
  exit 1
}

if($QUERY_RESULT.Results){
  Write-Host "クエリーの結果をアーカイブします。"
  if(-not (Test-Path ./$ARCHIVE_DIR/<任意のアーカイブ先のフォルダ名>)) {
  New-Item -ItemType Directory -Path ./$ARCHIVE_DIR/<任意のアーカイブ先のフォルダ名>
  }
  $QUERY_RESULT.Results | Export-CSV -Path ./$ARCHIVE_DIR/$CONTAINER_NAME/$DATE.csv -Encoding Default
  Write-Host "アーカイブ先のパス: ./$ARCHIVE_DIR/<任意のアーカイブ先のフォルダ名>/$DATE.csv"
}
```

## Scriptに書く魔法の言葉
最後の後処理として、Scriptを実行する前のディレクトリに移動します。

```
# PowerShell Script実行前の位置にディレクトリ移動
Set-Location $LOCATION_ORG
```
# 最後に

KQLを実行し、任意のLog AnalyticsワークスペースからLog Queryを取得する処理の流れをご紹介しました。Kubernetes Clusterに限らず、Log Analyticsワークスペースに収集される処理は対応しております。
ご参考になれば幸いです。
FTP環境構築について

FTP環境を構築したときのメモ

※最低限のFTP環境構築のためセキュリティは考慮されていません。必要であれば適宜設定してください。

## インストール

```console:インストール
$ sudo yum install vsftpd
```

## 設定

```console:元々の設定ファイルをバックアップ
$ sudo cp -p /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.org
```

```console:vsftpd.confの編集
$ sudo vim /etc/vsftpd/vsftpd.conf
・・・
chroot_list_enable=YES ←コメント解除
・・・
chroot_list_file=/etc/vsftpd/chroot_list ←コメント解除
・・・
pasv_address=FTPサーバ（自身）のIP ←IPを記載

----
※IP確認の際は以下を実行してください
$ curl http://xxx.xxx.xxx.xxx/latest/meta-data/public-ipv4
```

## FTPの起動および自動起動

```console
sudo service vsftpd start
sudo chkconfig vsftpd on
```

## FTPユーザの作成

```console
sudo su
useradd {ユーザ名}
passwd {パスワード}
```


## 参考

https://qiita.com/dogyear/items/289b314db9af42e15cfa

https://qiita.com/Yuki_BB3/items/deeb84c360c6f3c37f51

https://www.mussyu1204.com/wordpress/it/?p=61

https://protocol.nekono.tokyo/2019/02/20/vsftp%E3%81%ABsftp%E9%80%9A%E4%BF%A1%E7%94%A8%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E4%BD%9C%E6%88%90%E3%81%A8%E6%8E%A5%E7%B6%9A%E7%A2%BA%E8%AA%8D/
サイバースペースのメジャーデビューから40年 - 1984/07/01 ニューロマンサー発売 -

番外編のポエムです

1984年07月01日、ウィリアム・ギブソンの「ニューロマンサー」がカナダで発売されました(もちろん原書の話です)。40周年です。


ちょうど10年後、1994年にラスベガスで開催されたインタロップではcyberstationなるFMラジオがあったそうです。

もう、みんなサブカルチャーが大好きだから:-)?

サイバーを代表する色は、もちろんクロームです。Google Chromeがデビューしたとき「あ〜ギブソン？」って思いましたよね？Kubernetesの元ネタと言われるGoogle Borgって、きっとスタートレックでしょ？(TNGというセカンドシステム症候群なシリーズでガッカリしたけど、Googleの中の人は世代が違うんだな〜と思いましたね)

いずれにせよ、こんな"こっぱずかしい"単語が現代用語の基礎知識状態ってスゴいと思うのですけど、ものごころついた時、すでに商用インターネットだった世代は疑問に思わない ... ですかね？



### 邦訳を紹介

- 1985 ニューロマンサー
    - 黒丸尚訳なのがいいところ
    - 原書で読むより、黒丸尚訳のほうがカッコいい気がする ... (?)
- 1987 クローム襲撃
    - 短編集
    - 表題は有名な「Burning Chrome」
    - やっぱり「記憶屋ジョニー」と「クローム襲撃」かな？
    - 訳者が複数なので訳し方の違いを楽しめる


![](https://technotes.fml.org/tech/history/worlds-in-mono/aux/202407_neuromancer/images/Hayakawa-SF_Gibson_Neuromancer.jpg)みんなが読んだのは、このバージョンだ！この表紙がそれっぽい。ハヤカワ文庫がリニューアルすると、どれも表紙がリニューアルされて寂しい。


## 参考文献

https://www.hayakawa-online.co.jp/shopdetail/000000000738/author_KAgyo_GI_1083/page1/order/

https://www.hayakawa-online.co.jp/shopdetail/000000000783/author_KAgyo_GI_1083/page1/order/

https://qiita.com/fmlorg/items/5696ad17a01c3c8ccfe2

## 初出情報

- 2024/07/01 [1984/07 ニューロマンサー発売, サイバースペースのデビューから40年 - 色づかないWorld Wide Webの昨日から - 番外編](https://technotes.fml.org/tech/history/worlds-in-mono/aux/202407_neuromancer/)
    - 元の前半だけ抜粋

original site: https://technotes.fml.org/tech/history/worlds-in-mono/

(qiita版も致命的な間違いやTYPOは修正しますがupdatesはoriginalのほうだけです)

Copyright (C) 2024 Ken’ichi Fukamachi, CC BY-NC-SA 4.0
EC2でディスクが削除しても減らない場合

df コマンドでディスク容量が 100% として表示される事象があったときの対応メモ

## 概要

対処として不要ファイル削除や access_log削除を実施するも、ディスク容量に大きく影響することもなかった。
また、ルート「/」で du コマンド （$ du -ch） を実行するも 5.8GB/30GB の使用量となる。

その後の調査で、過去に削除したデータが kernel 上に残ることがわかり、該当プロセスを再起動することで正常なディスク容量となった。

## 実行手順

```
■ 確認方法

以下の例は rsyslogd 実行中に、/var/log/messages を削除した場合となります。

1. 下記のコマンドを実行します。lsof [1] は、オープン状態のファイルを表示します。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# lsof / | sort -k7 -nr | grep deleted
rsyslogd  2294           root   23w   REG  259,1     747870 12586215 /var/log/messages (deleted)
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

[1] lsof 
https://man7.org/linux/man-pages/man8/lsof.8.html 

2. 上記のように (deleted) ファイルが存在していた場合、
　該当するプロセスを再起動しファイルが完全に削除されたか du コマンドと df コマンドにて確認します。

以上で改善されない場合はもう一度 「1」 を実行して (deleted) が残っているか確認してください。

その後、ps コマンド （$ ps -ef | grep {プロセスを特定するための文字列}） にてプロセスを確認

ゾンビプロセスとして残っていた場合は 強制的に停止 kill コマンド（$ kill {プロセス番号}） するなどをしてください。

※ただし kill コマンド する場合はシステムに影響がないことをよく確認してください

```
【WSL2・Ubuntu環境 / Python】tkinterのsimpledialog.askstringでdialogにフォーカスが当たらない際の解決方法

# 1.はじめに
Pythonでtkinterパッケージを使用して簡易的なGUIアプリを自作していました。その際、simpledialogモジュールのaskstringメソッド使用時に表示したdialogに対してマウスポインターがフォーカス出来なかったため、その際の解決策について投稿します。

**開発環境**
・WSL2/Ubuntu環境
・Python: 3.10.12

# 2.simpledialog.askstringでdialogにマウスポインターがフォーカスしなかった失敗例
dialogに対してフォーカスが失敗した際のサンプルコードを以下に記載します。

:::note warn
**※サンプルコードを実行する際の注意**
以下サンプルコードを実行するとdialogにマウスポインターがフォーカスせず、文字入力GUIアプリ自体を閉じても、dialogは画面上に残ります。dialogを画面上から取り除きたい場合は、WSL2を終了することが必要です。
:::

```notfocus_dialog.py:
import tkinter as tk
from tkinter import Text, messagebox, simpledialog

# A function that does not focus on the dialog
def NotFocus_Sample_Input_WordFunc(event=None):
    search_word = simpledialog.askstring("Input-Word", "Please input word")
    messagebox.askokcancel("Input-Word", f"{search_word} ")


# make main window and configure title
root = tk.Tk()
root.title("simpledialog_sample")
root.geometry("800x600")

# make text
text = Text(root, wrap="word", undo=True)
text.pack(fill="both", expand=True)

# make bind
root.bind("<Control-f>", NotFocus_Sample_Input_WordFunc)
root.bind("<Control-F>", NotFocus_Sample_Input_WordFunc)

# display window
root.mainloop()

```
### プログラムの動作

キーボード操作で「Control-f」を押すと、NotFocus_Sample_Input_WordFunc関数が呼ばれ、
NotFocus_Sample_Input_WordFuncでは文字列を入力できるdialogを表示し、文字列を入力するとmessageboxでその文字列を表示するプログラムを想定しています。ただ実行すると上の注意書きにも記載した通り、dialogにマウスポインターがフォーカスしない状態になります。


# 3.simpledialog.askstringdialogにマウスポインターがフォーカスした成功例
dialogに対してフォーカスが成功した際のサンプルコードを以下に記載します。
コードの変更点としては、simpledialog.askstringの引数として「parent=root」を追加した点です。明示的に「parent」を記載することで解決しました。

```focus_dialog.py:
import tkinter as tk
from tkinter import Text, messagebox, simpledialog


# A function that does focus on the dialog
def Focus_Sample_Input_WordFunc(event=None):
    search_word = simpledialog.askstring("Input-Word", "Please input word", parent=root)
    messagebox.askokcancel("Input-Word", f"{search_word} ")


# make main window and configure title
root = tk.Tk()
root.title("simpledialog_sample")
root.geometry("800x600")

# make text
text = Text(root, wrap="word", undo=True)
text.pack(fill="both", expand=True)

# make bind
root.bind("<Control-f>", Focus_Sample_Input_WordFunc)
root.bind("<Control-F>", Focus_Sample_Input_WordFunc)

# display window
root.mainloop()


```

# 4.終わりに
本記事では、simpledialogモジュールのaskstringメソッド使用時に表示したdialogに対して、マウスポインターがフォーカス出来ない場合の解決策を紹介しました。
同じ事象に遭遇した場合、参考にしていただけると幸いです。


# 参考文献
本記事は以下情報を参考にして執筆しました。

https://docs.python.org/ja/3.11/library/dialog.html
matplotlib on jupyterlab

# JupterLabの弱点
JupyterLabはJupyter Notebookの後継であり、多くの機能改善がされているゆえ、通常はJupyter Notebookをあえて使う必要はありません。
しかしながら、私の知る範囲において唯一の弱点は、マジックコマンド`%matplotlib`でどのバックグラウンドを指定しても、matplotlibで作成したグラフをブラウザ上のGUIで操作出来ないということでした。

# ipympl
この弱点を解決するものが`ipympl`です。これについての日本語の解説記事が少なく、また後述の余分なタイトルが付加される件に関してはChatGPTに聞いてもなかなか正解にたどり着かなったので、ここにそれらを整理します。

# インストール
[Github matplotlib/ipympl](https://github.com/matplotlib/ipympl)に古いjupyterlabと使う場合などが書かれていますが、最新版かそれに近いJupyterLabを使っているならば、pipやcondaで単純にインストールするのみです。JupyterLabの必要な拡張機能も標準的にインストール済みと思われます。

## 例：pipを用いたインストール
```bash
pip install ipympl
```

## 実行中のJupyterLab
`ipympl`のインストール前に、JupyterLab上で他のバックグラウンドを指定してmatplotlibのグラフを表示していた場合、ipythonのカーネルのリスタートか、JupyterLab自体の再起動をしないと、バックグラウンドを`ipympl`にうまく切り替えれないようです。その場合には、カーネルのりスタートかJupyterLab自体の再起動をして下さい。

# 使い方
単純にJupyterLabのノートブック上で下記のマジックコマンドを実行するのみで、matplotlibのグラフのバックグラウンドに`ipympl`が使われます。
```
%matplotlib ipympl
```

# 追加のタイトルなど
バックグラウンドを`ipympl`にして、matplotlibのグラフを書かせると、その上部に`Figure 1`などと追加のタイトルが表示され、グラフの追加や再作成をさせるたびにそのタイトル中の番号は大きくなります。

その消し方についてChatGPTに聞いても、ググっても正解を見つけるのに苦労しました。
やっと見つけた方法が以下です。
```python
    fig, ax = plt.subplots()
    
    fig.canvas.header_visible = False
    fig.canvas.footer_visible = True
    fig.canvas.toolbar_visible = True
```

グラフ作成時に`fig.canvas`の以下の属性をFalseにすることで、非表示に出来ます。それぞれの属性は次の通りです。

+ `fig.canvas.header_visible` : グラフ上部のタイトルの表示/非表示
+ `fig.canvas.footer_visible` : グラフ下部のフッターの表示/非表示
+ `fig.canvas.toolbar_visible` ： グラフのGUIでの操作用のツールバーの表示/非表示

フッターを表示させておくと、グラフ上にマウスカーソルを移動することで、その点における値がフッターに表示されるので便利です。

## 参考ページ
+ [ipympl](https://matplotlib.org/ipympl/index.html)

# まとめ
私はJupyter NotebookよりJupyterLabの方が断然好きなのですが、上述の問題がちょっとネックだな、と思っておりました。グラフ作成時だけJupyter Notebookを使うしかないかな、って思っていたのですが、`ipympl`が使える状態になりました。

`ipympl`についてはどうも日本語の情報が断片的にしか見つからなかったので、ここに最低限をまとめてみました。
id_rsa⇒pem⇔ppk 相互変換

pem,ppk を相互変換したときのメモ

## 用途
### pem

OpenSSH形式の秘密鍵
AWSで初めてインスタンスを立てた際に、KeyPairが作成されます。
この時作成されたKeyPairはpemファイルです。
TeraTermなどのターミナルで利用可能です。

### ppk
PuTTY形式の秘密鍵
WinSCPを使用する際はこの形式の秘密鍵が必要です。
Tera Termなどのターミナルでも利用可能です。

## 変換方法

### id_rsa ⇒ ppk
1. puttygen.exeを起動
1. [Load] をクリックしてid_rsa をロード
1. ロードできたら、[Save private key] をクリックしてppkファイルを保存

### ppk ⇒ pem
1. puttygen.exeを起動
1. [Load]からppkファイルを選択
1. メニューの[Conversions]>[Export OpenSSH key]でエクスポート

### pem ⇒ ppk
1. puttygen.exeを起動
1. メニューの[Conversions]>[Import Key]を選択
1. pemファイルを選択し、任意でパスワードを設定
1. [Save private key]ボタンでppkファイルを生成

## 変換方法（コマンド）

※ puttygenコマンドを使用します。
　macの方は事前にputtyをインストールしてください。

```console
$ brew install putty
 ```

### ppk ⇒ pem

```console
$ puttygen ファイル名.ppk -O private-openssh -o ファイル名.pem
```

### pem ⇒ ppk

```console
$ puttygen ファイル名.pem -o ファイル名.ppk -O private
```
【c++】ABC360 A-D問題解説【ACコード付き】（毎日ABC day24）

# AtCoder Beginner Contest 360
A,B,C,Dの4完。

B問題に出題ミスがあったらしく、まだレートの更新は行われていない。

そこそこD問題まで早く解けた回だったので、きちんとrate反映されることだけを祈る。全員レート更新になることだけはやめてほしい。笑

https://atcoder.jp/contests/abc360

## A - A Healthy Breakfast

アルファベット大文字`S`,`M`,`R`の3文字が並び順が変わって入力される。

'R'よりも'M'が右にあるかどうかを判定せよ、という問題。

左の文字から見ていって、先にどちらの文字が来るかで判定すればOK。

```cpp
string S;

int main()
{
	cin >> S;
	for (int i = 0; i < S.size() ; i++)
	{
		if (S[i] == 'R')
		{
			cout << "Yes" << endl;
			return 0;
		}
		if (S[i] == 'M')
		{
			cout << "No" << endl;
			return 0;
		}
	}
    return 0;
}
```

## B - Vertical Reading
文字列$S$と$T$が与えられる。

$1≤c≤w<∣S∣$ という条件の時に、以下の整数の組が存在するか判定せよ。

$S$ を先頭から順に 
$w$ 文字毎に区切ったとき、長さが 
$c$ 以上の文字列の 
$c$ 文字目を順番に連結した文字列が 
$T$ と一致する

区切る文字$w$を1から$S$の文字列の長さまで動かしつつ、抽出する$c$文字目は1から区切る文字数$w$まで動かしながら、Tに一致する文字列になるかひたすら試していく。

```cpp
int N;
string S, T;

int main()
{
	cin >> S >> T;
	for (int i = 1; i < S.size() ; i++)
	{
		for (int j = 1; j <= i ; j++)
		{
			string tmp;
			int sep = j - 1;
			while (sep < S.size())
			{
				tmp += S[sep];
				sep += i;
			}
			if (tmp == T)
			{
				cout << "Yes" << endl;
				return 0;
			}
		}
	}
	cout << "No" << endl;
    return 0;
}
```

## C - Move 

$N$ 個の箱があり、$i$番目の荷物は箱$A_i$に入っており、その重さ$W_i$が与えられる。

1回の移動に重さ$W_i$と同等のコストがかかる時、全ての箱の中に荷物が1つだけ入っている状態にするまでにかかる最小のコストはいくらか、という問題。

最小コストで移動させたい場合は同じ荷物が1回以上移動することはなく、どの箱に移動させるかはコストに関係ないので、同じ箱に2つ以上荷物が入っている場合は、一番移動コストの高い、重い荷物をその箱に残し、そのほかの荷物は任意の空の箱へ移動させていく。

つまり全ての荷物の重さから、それぞれの箱に入っている一番重い荷物の重さを引いた数がかかる最小のコストになる。

```cpp
int N;
int A[100009];
int W[100009];
vector<int> boxex[100009];

int main()
{
	cin >> N;
	for (int i = 1; i <= N ; i++) cin >> A[i];
	for (int i = 1; i <= N ; i++) cin >> W[i];
	for (int i = 1; i <= N ; i++)
	{
		boxex[A[i]].push_back(W[i]);
	}
	ll ans = 0;
	for (int i = 1; i <= N ; i++)
	{
		if (boxex[i].size() > 0)
		{
			sort(boxex[i].begin(), boxex[i].end());
			for (int j = 0; j < boxex[i].size()-1; j++)
			{
				ans += boxex[i][j];
			}
		}
	}
	cout << ans << endl;
    return 0;
}
```

## D - Ghost Ants
数直線上に$N$匹のありがいる。それぞれの蟻は重複しない$X_i$座標におり、正負のどちらに向いているかの情報が与えられる。

それぞれの蟻が向いている方向へ毎秒1ずつ進む時、今から$T+0.1$秒までの時間ですれ違う蟻の数はいくらか、という問題。

左向きの蟻を固定し、右向きの蟻が$2 × T+0.1$進むと考えて、右向きの蟻がすれ違う左向きの蟻の数の合計が答え、と考えても同じ状況のため、以下のプログラムではその考え方を用いている。

特定の右向きの蟻1匹に注目した時、最初の位置の一番近い右側にいる左向きの蟻から、移動終了後の一番近い右側にいる左向きの蟻 -1 まですれ違うことになる。

その数を二分探索を用いて求め、全ての右向きの蟻に対して足し合わせたものが答えである。

```cpp
ll N, T;
string S;
ll X[200009];
vector<ll> left_ants, right_ants;

int main()
{
    // 入力
    cin >> N >> T >> S;
    for (int i = 0; i < N ; i++)
    {
        cin >> X[i];
        if (S[i] == '0') left_ants.push_back(X[i]);
        else right_ants.push_back(X[i]);
    }
    
    // ソート
    sort(left_ants.begin(), left_ants.end());
    sort(right_ants.begin(), right_ants.end());

    // 答えを求める
    ll ans = 0;
    for (ll x : right_ants)
    {
        // 左向きの蟻とのすれ違いをカウント
        ans += lower_bound(left_ants.begin(), left_ants.end(), x + 2 * T + 0.1) - lower_bound(left_ants.begin(), left_ants.end(), x);
    }

    cout << ans << endl;
    return 0;
}
```
【laravel】sail+playwright環境構築

laravel sailで構築したプロジェクトにplaywrightを入れた時のメモ

## 環境

- windows 11
- wsl2
- ubuntu 22.04
- laravel 11
- laravel sail

## とりあえずインストール

sail起動

```bash:WSL
sail up -d
```

:::note info
エイリアスを登録していない場合は`sail`を`./vendor/bin/sail`に適宜読み替えて実行してください
:::

プロジェクトが起動しているコンテナの中にはいる

```bash:WSL
sail root-shell
```
playwrightをインストール

```bash:dockerコンテナ
npm init playwright@latest
```

いろいろきかれる

```bash:dockerコンテナ
Need to install the following packages:
create-playwright@1.17.133
Ok to proceed? (y)


> npx
> create-playwright

Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Where to put your end-to-end tests? · e2e
✔ Add a GitHub Actions workflow? (y/N) · false
✔ Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) · true
✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo npx playwright install-deps')? (y/N) · true
```

インストールがはじまって、この表示がでたらOK

```bash:dockerコンテナ
✔ Success! Created a Playwright Test project at /var/www/html

Inside that directory, you can run several commands:

  npx playwright test
    Runs the end-to-end tests.

  npx playwright test --ui
    Starts the interactive UI mode.

  npx playwright test --project=chromium
    Runs the tests only on Desktop Chrome.

  npx playwright test example
    Runs the tests in a specific file.

  npx playwright test --debug
    Runs the tests in debug mode.

  npx playwright codegen
    Auto generate tests with Codegen.

We suggest that you begin by typing:

    npx playwright test

And check out the following files:
  - ./e2e/example.spec.ts - Example end-to-end test
  - ./tests-examples/demo-todo-app.spec.ts - Demo Todo App end-to-end tests
  - ./playwright.config.ts - Playwright Test configuration

Visit https://playwright.dev/docs/intro for more information. ✨

Happy hacking! 🎭
```

sailがplaywrightを実行できるように権限を変更する

```bash:dockerコンテナ
chown -R sail:sail /var/www/html
```

コンテナから抜ける

```bash:dockerコンテナ
exit
```

## とりあえず動かしてみる

デフォルトではいっているやつをうごかしてみる

```bash:WSL
npx playwright test
```

とりあえずとおった

```bash:WSL
Running 6 tests using 6 workers
  6 passed (18.7s)

To open last HTML report run:

  npx playwright show-report
```

## 実行結果を表示してみる

```bash:WSL
npx playwright show-report
```
```bash:WSL
 Serving HTML report at http://localhost:9323. Press Ctrl+C to quit.
```

URLをコピペしなくても勝手に表示されました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3580241/5f168df7-8021-9350-f2b4-7ff3cb01e65b.png)

## テストコードを生成してみる

ポート番号はご自身の環境に合わせて変えてください(私の場合は8080)

```bash:WSL
npx playwright codegen localhost:8080
```

あとはお好きに～
毎日ABC day25【c++】ABC324 A-C問題解説【ACコード付き】

# AtCoder Beginner Contest 324

https://atcoder.jp/contests/abc324

## A - Same
与えられる $N$ 個の整数が同じ数か判定する。

```cpp
int main()
{
	int N;
	cin >> N;
	vector<int> A(N);
	for (int i = 0; i < N; i++) cin >> A[i];
	for (int i = 0; i < N - 1; i++)
	{
		if (A[i] != A[i+1])
		{
			cout << "No" << endl;
			return 0;
		}
	}
	cout << "Yes" << endl;
	return 0;
}
```

## B - 3-smooth Numbers
与えられる整数 $N$ が $N =  2^x3^y$ という式で表されるかを判定せよ、という問題。

2で割れるときは2で割って、3で割れるときは3で割るのを繰り返し、$N=1$ になれば$N =  2^x3^y$ で表される。

```cpp
int main()
{
	ll N;
	cin >> N;
	while (N % 2 == 0) N /= 2;
	while (N % 3 == 0) N /= 3;
	if (N == 1) cout << "Yes" << endl;
	else cout << "No" << endl;
	return 0;
}
```

## C - Error Correction
```cpp
```
EC2ユーザ追加

EC2でユーザ作成や鍵ファイル、ルート設定などしたときのメモ

## 準備
- 上位権限のアカウント（root）または sudo の実行できるユーザ環境で作業を行う

##  ユーザ作成

```console
$ sudo useradd {ユーザ名}
```

## 鍵の作成
### .sshフォルダ作成

```console
$ sudo su - {ユーザ名}
$ mkdir -m 700 .ssh
$ cd .ssh
```

### 鍵の作成

```console
$ ssh-keygen -t rsa -b 4096 -C "メールアドレス"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/{ユーザ名}/.ssh/id_rsa): /home/{ユーザ名}/.ssh/id_rsa
Enter passphrase (empty for no passphrase): {パスフレーズ}
Enter same passphrase again: {パスフレーズ}

* -C で コメントを入れるのが主流らしい
```

```console:結果
$ ls -l
-rw------- 1 {ユーザ名}   {ユーザ名}   3326 Jun 25 18:44 id_rsa
-rw-r--r-- 1 {ユーザ名}   {ユーザ名}   3326 Jun 25 18:44 id_rsa.pub

* id_rsa 秘密鍵
* id_rsa.pub 公開鍵
```

## 各種鍵の設定
### 公開鍵のファイル名および権限の変更
※公開鍵はサーバ側で管理する鍵となります。適切なファイル名・権限に変更する。

```console
$ mv id_rsa.pub authorized_keys
$ chmod 600 authorized_keys
```

```console:結果
$ ls -l
-rw------- 1 {ユーザ名}   {ユーザ名}   3326 Jun 25 18:44authorized_keys
-rw------- 1 {ユーザ名}   {ユーザ名}   3326 Jun 25 18:44 id_rsa
```

### 秘密鍵
※秘密鍵は使用者が管理する鍵となります。ファイルをダウンロードして使用するか、ファイルの内容をコピーしてローカルで保存してください。
※ローカルで管理後はサーバ側のid_rsaは削除しても構いません
※ id_rsaのファイル名は変更しても構いません```

## sudo設定
※rootになるにパスワードが要らない設定
※ec2-userで下記実行

```
$ sudo visudo
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
dduser     ALL=(ALL)       NOPASSWD:ALL # 追加
```

## 接続の確認
### ssh接続
※SSHできる、かつrootになれることを確認

```console
$ ssh -i "{秘密鍵のパス}/id_rsa" {ユーザ名}@{サーバIP}
```

## EC2のタイムゾーン変更手順
EC2の初期タイムゾーンはUTCで、ログファイルの日時がUTCでしたので、Asia/Tokyoへ変更。

```
１．現在タイムゾーン確認
$ date

Thu Apr 18 06:41:39 UTC 2019
```

```
２．設定変更
$ sudo vi /etc/sysconfig/clock

#ZONE="UTC" ※変更前
ZONE="Asia/Tokyo"　※変更後
UTC=true
```

```
３．シンボリックリンク作成　※これが作成しなかったらUTCのままな気が。。。
$ sudo ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

４．Asia/Tokyoに変更されたことを確認
$ date

Thu Apr 18 15:43:03 JST 2019
```
Pyenvからasdfへの移行方法

## 概要
pythonのバージョン管理にPyenvを使っていたが、asdfが便利そうなのでそちらに移行した。

## asdfとは

簡単に言うと複数の言語やツールをまとめてバージョン管理できるコマンドラインツールです。
使い方などは下記が詳しいです。

https://qiita.com/naotwu/items/76f34a3eb4d7ade2e55b


## 環境
- M2 Macbook
- MacOS Sonoma 14.4

## 1. pyenvの削除

消さなくても動くと思いますが、きれいにしたかったのでまずpyenvを消しました。
```console
$ pyenv versions
$ pyenv uninstall 3.12.2
$ brew uninstall pyenv-virtualenv
$ brew uninstall pyenv
$ rm -rf ~/.pyenv
```

## 2. asdfのインストール
公式ドキュメントを見ながらインストールしていきます。

https://asdf-vm.com/guide/getting-started.html

```shell
#依存関係のインストール
$　brew install coreutils curl git

# asdfのダウンロード
$　git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
# 下記でもインストール可能ですが、公式としてはgit cloneを推奨しているようです
$ brew install asdf  

# パスを通す
$ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc

# インストールできているか確認
$　asdf --version    
```

## 3. pythonのインストール

```shell
# pythonインストールの前にプラグインを入れます。
$ asdf plugin-add python

# インストールできるpythonの一覧を表示
$ asdf list-all python

# 必要な依存関係のインストール
$ brew install openssl readline sqlite3 xz zlib tcl-tk

# pythonをインストール
$ asdf install python {バージョン}

# インストールされたバージョンを確認
asdf list python
```

## 4.バージョンの切り替え

```shell
# グローバルで設定
$ asdf global python {バージョン}
# ローカルで設定
$ asdf local python {バージョン}
# 現在のバージョンを確認
$ asdf current python
```

## プラグインの更新
```shell
$ asdf plugin-update --all
$ asdf plugin-update <plugin_name>

# インストールしたプラグインの確認
$ asdf plugin list

# それぞれのバージョン確認
$ asdf current 
```

## asdf自体の更新
```
$ asdf update
```

## 参考

https://zenn.dev/hayato94087/articles/a2bde47e14840a

https://note.com/noa813/n/n4d54ee8b3378
配列に対する処理　for, forEach, find, filter

新人エンジニアの三上です。
今回は、配列に対する操作の中で、私が実際に使用したことのあるものをまとめてみようと思う。

## for
配列の要素をループごとに変数に代入し、そのループ内で変数を使用する。
以下にサンプルコードを示す。

```Kotlin:for
    val sampleList = [0,1,2,3,4,5]
    
    for (sample in sampleList) {
    	if (sample == 2) {
        	println(sample)
    	}
    }
```

配列 sampleList の要素を 変数 sample に設定し、sample に対し、条件判定を行うことで、任意の要素を出力する。


## forEach
for と処理は同様だが、記載の方法が異なる。
以下にサンプルコードを示す。

```Kotlin:forEach
    val sampleList = [0,1,2,3,4,5]
    
    sampleList.forEach {sample =>
    	if (sample == 2) {
        	println(sample)
    	}
    }
```

for と同様であるため、省略。
ここで、sample を定義せずとも、forEach 内では it として各要素を指定することが出来る。
明示的に変数を定義する方が、各変数の意味が分かりやすいため、変数定義することが望ましい。


## find
配列内の要素に対して、条件判定を行い、その条件を満たす要素を取得する。
以下にサンプルコードを示す。

```Kotlin:find
    val sampleList = [0,1,2,3,4,5]
    
    val findSample = sampleList.find (sample =>
    	sample == 2
    }
```

ここで、戻り値は条件判定を満たす配列内の1つ目の要素となる。型としてはInt型である。


## filter
配列内の要素に対して、条件判定を行い、その条件を満たす要素で構成された配列を取得する。
以下にサンプルコードを示す。

```Kotlin:filter
    val sampleList = [0,1,2,3,4,5]

    val filterdList = sampleList.filter (sample =>
    	sample == 2
    )
```
ここで、戻り値の型は sampleList と同じ Int 型の配列である。

## まとめ
同様の操作でも上記の操作を使い分けることで、コード量を抑えることが出来る。
また、処理の内容を簡潔で分かりやすく記載することが出来る。

以上、三上でした。
【応用情報技術者試験】末尾に「エンジニアリング」とつくワードまとめ

# 概要
応用情報技術者試験にでてくる〇〇エンジニアリングという名前のワードを纏めました。
エンジニアリングは「工学」という意味です。

# 目次
- [インダストリアルエンジニアリング](#インダストリアルエンジニアリング)
- [コンカレントエンジニアリング](#コンカレントエンジニアリング)
- [ソーシャルエンジニアリング](#ソーシャルエンジニアリング)
- [バリューエンジニアリング](#バリューエンジニアリング)
- [フォワードエンジニアリング](#フォワードエンジニアリング)
- [リエンジニアリング](#リエンジニアリング)
- [リバースエンジニアリング](#リバースエンジニアリング)
- [リバース・ソーシャル・エンジニアリング](#リバースソーシャルエンジニアリング)

# インダストリアルエンジニアリング
インダストリアル (industrial) は「産業の」という意味。
業務改善を行う技術のひとつで、工程管理技術のひとつ。
工程や作業内容を分析し、より良い生産管理方法を追求する手法。

# コンカレントエンジニアリング
コンカレント (concurrent) は、「同時」という意味。
造業の製品開発工程で、複数の業務を同時進行させ、開発を効率化したり、開発期間を短縮を図る手法。

# ソーシャルエンジニアリング
ソーシャル (social) は「社会の」という意味。
人間の心理的な隙や行動ミスにつけ込み、幸神情報をを入手する犯罪のこと。

手口の例としては以下がある。
- ショルダーハッキング (のぞき見)
- トラッシング (ゴミ箱漁り)
トラッシュ (trash) は「ゴミ」のこと
- スピアフィッシング攻撃 (特定の相手に狙いを定めて攻撃する)

# バリューエンジニアリング
製品やサービスを「コスト」と「機能」の観点から見直し改善することによって価値を高めていく手法。
日本語で「価値工学」と言われる。

# フォワードエンジニアリング
システムの開発手法のひとつ。
リバースエンジニアリングによって解析された仕様をもとに、新しいシステムの開発を行うこと。

# リエンジニアリング
「ビジネスプロセス・リエンジニアリング」ともいわれる。
コスト削減やパフォーマンスの向上等を目標に、企業のビジネスルールを見直し、新たなルールを再構築すること。

# リバースエンジニアリング
製品を分解したり、動作を観察、解析するなどして、製品の構造を分析して、その製品の製造方法や仕様、ソースコードなどを調査すること。
「逆アセンブル」や「逆コンパイル」もリバースエンジニアリングに入る。

# リバース・ソーシャル・エンジニアリング
ターゲットから攻撃者に行動を促し、攻撃者とコンタクトをとった際にターゲットから情報を盗む手法。
例えば、メールでパスワードの更新通知をアナウンスし、ターゲットが主体的に連絡を行うよう仕向けるようなことが当てはまる。

***
**[記載した応用情報技術者試験の記事まとめ](https://qiita.com/MetroOsamu/items/550001240d76e24f505f)**
【初心者向け】Pythonのプレースホルダー使い方まとめ

Pythonのプレースホルダーがよくわからなくて、chatgptに教えてもらったらわかりやすかったのでメモ。

## プレースホルダーとは
変数やデータ構造において、一時的なデータや仮の値を設定するために使用されます。
文字列の中にある`{}`を見たことはないでしょうか?
これを置くことで文字列の中に変数を埋め込むことができます。

## 文字列フォーマット

Pythonの`str.format()`メソッドやf-strings（フォーマット済み文字列リテラル）で、`{}`はプレースホルダーとして使用されます。

### `str.format()`メソッド
`str.format()`メソッドを使用すると、文字列内の`{}`を特定の値に置き換えることができます。
例：

```python
name = "Alice"
age = 30
formatted_string = "My name is {} and I am {} years old.".format(name, age)
print(formatted_string)
```

出力：
```
My name is Alice and I am 30 years old.
```

### f-strings（Python 3.6以降）
f-stringsを使用すると、変数や式を`{}`の中に直接埋め込むことができます。
こちらはstr.format()メソッドより簡素でわかりやすいですね。
f-stringsは、文字列リテラルの前に`f`または`F`を付け、` {} `の中に変数や式を書きます。Pythonは波括弧内の内容を評価し、その結果を文字列に埋め込みます。

例：

```python
name = "Alice"
age = 30
formatted_string = f"My name is {name} and I am {age} years old."
print(formatted_string)
```

出力：
```
My name is Alice and I am 30 years old.
```

## `str.format()`メソッドでの詳細なフォーマット

`str.format()`メソッドでは、`{}`内に番号や名前を指定して、置き換える値を指定することができます。

### 位置引数によるフォーマット
位置引数を使用して、フォーマットする順序を指定できます。

```python
formatted_string = "My name is {0} and I am {1} years old.".format(name, age)
```

### 名前付き引数によるフォーマット
名前付き引数を使用して、より読みやすいフォーマットができます。

```python
formatted_string = "My name is {name} and I am {age} years old.".format(name="Alice", age=30)
```

## f-stringsでの詳細なフォーマット

f-stringsでは、`{}`内に式やフォーマット指定子を含めることができます。

### 1. 式の埋め込み
```python
a = 5
b = 10
print(f"The sum of {a} and {b} is {a + b}.")
```

出力：
```
The sum of 5 and 10 is 15.
```

### 2. フォーマット指定子
例えば、小数点以下の桁数を指定することができます。

```python
value = 3.14159
print(f"Value: {value:.2f}")
```

出力：
```
Value: 3.14
```


### 3. 辞書の使用
辞書のキーを使って値を埋め込むこともできます。

```python
person = {"name": "Alice", "age": 30}

greeting = f"Name: {person['name']}, Age: {person['age']}"
print(greeting)  # Name: Alice, Age: 30
```

### 4. 関数呼び出し
f-strings内で関数を呼び出すことも可能です。

```python
def greet(name):
    return f"Hello, {name}!"

message = f"{greet('Alice')}"
print(message)  # Hello, Alice!
```

### 5. 日付のフォーマット
日付をフォーマットするためにもf-stringsを使用できます。

```python
from datetime import datetime

now = datetime.now()

formatted_date = f"Current date and time: {now:%Y-%m-%d %H:%M:%S}"
print(formatted_date)  # Current date and time: 2024-07-02 10:30:45
```

### 6. エスケープシーケンス
 `{}` 自体を文字列に含めたい場合は、エスケープする必要があります。

```python
escaped_braces = f"{{This is a literal brace}}"
print(escaped_braces)  # {This is a literal brace}
```

### パフォーマンス
f-stringsは他の文字列フォーマット方法に比べて高速です。これは、f-stringsがPythonのコンパイル時に直接評価されるためです。
Gitでpushすると400エラーが出た

# はじめに
ディレクトリに写真を追加し，pushした時に以下のようなエラーが出た．
それを解決した手順を書いていく．

```
Enumerating objects: 31, done.
Counting objects: 100% (31/31), done.
Delta compression using up to 8 threads
Compressing objects: 100% (28/28), done.
error: RPC failed; HTTP 400 curl 22 The requested URL returned error: 400
send-pack: unexpected disconnect while reading sideband packet
Writing objects: 100% (28/28), 9.97 MiB | 12.45 MiB/s, done.
Total 28 (delta 16), reused 0 (delta 0), pack-reused 0
fatal: the remote end hung up unexpectedly
Everything up-to-date
```


***この『物語』はぼくがエラーから立ち上がって歩き出す物語だ!***

# どんなエラー
今回は400エラーがでたのだが，クライアントからサーバーへのリクエストに問題がある場合に発生するとのことだった．
400エラーの種類
つまり，***直接的なエラーがなんなのかわからないのだ!!***
なので，AIツールでエラーを投げてもわからない．
今回は写真のpushのみでエラーが起きたので，http.postBufferの容量が上限を上回っているのだと予想した．
すると解決した
通常gitのデフォルトのhttp.postBufferの容量は`gitconfig`2MiBらしい．

400エラーのStackOverFlow

https://stackoverflow.com/questions/35827033/git-push-error-the-requested-url-returned-error-400

http.postBufferエラーのStackOverFlow

https://stackoverflow.com/questions/6842687/the-remote-end-hung-up-unexpectedly-while-git-cloning


# 解決方法
pushエラーが起きたもののルートでこのコードをすればいい．
```
git config http.postBuffer 524288000
```

>```
>git config http.postBuffer 500M
>```
>も可

これはHTTP経由でデータを送信する際に使用するhttp.postBufferの容量を500MiBに設定する．

# 最後に
今回は写真を追加した経緯から，bufferサイズが不足を推測することができたため，たまたま解決できた．しかし，400エラーは多くの場合、具体的な原因を特定することが難しい．本記事で紹介した解決方法は一例に過ぎないが、同様の問題に直面している人にとって、エラー解決の手がかりになることを願っている．
それでは，みなさんよいエンジニア生活を~👋
【AtCoder】RatedでABC360のD問題をPythonで解きました

## はじめに

この記事では、PythonでABC360のD問題の解き方を紹介します。

問題は下のリンクを見てください。

https://atcoder.jp/contests/abc360/tasks/abc360_d

## ACコード

```python
import bisect

n,t=map(int,input().split())
s=list(input())
*x,=map(int,input().split())
s0=[]
s1=[]
for i in range(n):
    if s[i]=='0':
        s0.append(x[i])
    else:
        s1.append(x[i])
ans=0
s0.sort()
s1.sort()
for i in range(len(s0)):
    xxx=bisect.bisect_left(s1,s0[i]-(t*2))
    yyy=bisect.bisect_right(s1,s0[i]-1)
    ans+=yyy-xxx
print(ans)
```

## ACコードのざっくりとした説明

蟻を負の値に向かうものと正の値に向かうもので場合分けをします。

その後、それぞれのlistをソートして、二分探索をして、答えを出力するという流れです。

## 今回のサンプルケースの凶悪さ

今回の問題は**ソートをしなくても、サンプルケースがACで通ってしまう**という凶悪さがあります。しかし、**その罠にはまってしまうと、テストケースではWA**となってしまいます。

## 具体的にACコードの解説を

まず、蟻の向かう方向が正か負で分けます。そして、ソートします。

その後、二分探索で`s1`のlistの中で、`s0[i]-t*2`から`s0[i]-1`の範囲を二分探索して探します。

なんで、`s0[i]-t*2`が左端になるのかというと、蟻はT秒でT移動します。そのため、2匹の蟻は向かい合って1秒ごとに1移動します。すると、1秒あたり距離は2縮まります。そのため、`s0[i]-t*2`までの距離は交わることができるでしょう。

また、座標の初期値はそれぞれの蟻ですべて異なると言われているため、右端は`s0[i]-1`か`s0[i]`ということがわかります。しかし、`s0[i]+1`になった場合、どんどん蟻の距離は離れていくため、交わることはできません。

そして、左端と右端の間にある蟻の匹数をカウントすればOKです。

## 終わりに

今回のABCはB問題のこともあり、レートは更新されていませんが、自分なりにはD問題を解けたので、満足しています。これからも精進を頑張ります。

---

記事を読んでくれてありがとうございます。

ぜひ、「いいね」と「フォロー」をお願いします。
LINE WORKS の Webhook をすぐに使える Power Automate 用カスタム コネクタ作った

# LINE WORKS の Incoming Webhook アプリで簡単に Bot からメッセージを送れます

Microsoft Power Automate で、すぐに LINE WORKS の Bot からメッセージを送ることができるカスタム コネクタを作りました



# カスタム コネクタをインポートする
## Power Automate の設定

1. [Power Automate](https://flow.microsoft.com) にアクセスし、Microsoftアカウントでログインします。

2. 左側のナビゲーションメニューから「データ」を選択し、「カスタムコネクタ」をクリックします。
3. 右上の「+ カスタムコネクタの新規作成」をクリックし、「URL から OpenAPI をインポートします」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/94459f12-a750-540c-eaa3-e663a35f9623.png)

4.「Open API の URL に貼り付ける」 に以下の URL を入力して、[インポート] をクリック。
```
https://raw.githubusercontent.com/iwaohig/line-works-webhook-power-automate/main/LINE-WORKS-Incoming-Webhook.swagger.json
```
![l_1517737_3717_6f2f1c5471031f65d1f74bd7014c24dd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/e0f3dcd3-bad7-5c27-5b99-c0a992d99a37.png)

5. 「続行」 をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/1f2bd209-9b4f-2dc5-fea5-28dffb115260.png)

6. 必要に応じてアイコン ファイルや背景色を指定します。
6. 「コネクタの作成」をクリック。
![l_1517737_3718_fcb1be19226ca68e0202415cab3731f4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/62d52bbc-e8b9-88e0-533c-f7e9391c252d.png)

8. カスタム コネクタが作成されました。
![l_1517737_3719_e5c104643ae54bef229cb1d03e8c020f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/d42c30ac-f604-c925-052c-5991802c0928.png)

# LINE WORKS の Incoming Webhook アプリの準備
https://qiita.com/mmclsntr/items/b2960c2f630b02e4af99
こちらの記事の、1. から 3. の手順を実行してください。

追加した Webhook URL の末尾の部分をコネクタの設定で使います。
![l_1517737_3720_b3f75b2a495f7ad7c5a8df353b964e62.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/a5b2a3a5-8bcd-6a2a-5541-e7abd9aabb8d.png)

# Power Automate でカスタム コネクタを使う
フローのアクションでカスタム コネクタのリストから作成したコネクタを選択します。
![l_1517737_3721_a50291dbb8eeac21d9cb5083468da412.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/401808cd-a231-72f7-86bb-7d9def174936.png)

コネクタの最初に利用時には接続の作成が必要です。
![l_1517737_3722_170dc84cac325f75f3a99c367623ab95.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/d9750f75-d04a-0dd1-f35c-c8288fb1d27b.png)

パラメーターの設定画面で、詳細パラメーターの「すべてを表示」をクリック。
![l_1517737_3726_b0e3740a8b669f5dba877d0641696a56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/46107cab-c6e5-3623-cebb-9d9129adb9e0.png)

各パラメーターを設定します。
ボタンのラベルとボタンのラベルは不要な場合は空欄で大丈夫です。
![l_1517737_3727_4d6d6aeb9a08562d02c7f824d965d12b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/76b29846-4613-9a04-0fb0-5d85ff8e5570.png)

例
![l_1517737_3728_c457c25418a3f67ec21423d6758437ca.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/06f99006-365a-4fad-701e-af499d16b06c.png)

実行されると以下のようにメッセージが送信されます。
![l_1517737_3729_986005141ca9c5278d4d4333d97a1c40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/b31c8df7-b3e7-84c4-a535-022a4839e419.png)

以上のように、GitHub上のOpenAPI定義ファイルのURLを直接使用してPower Automateにカスタムコネクタをインポートし、LINE WORKS Incoming Webhookを使用してメッセージを送信するフローを簡単に作成することができます。

ぜひお試しください！
Mac OS SonomaでForticlient VPN 7.4がクラッシュする問題

# 概要
発生日時：2024/07/02
Forticlient VPNを使用したく、インストールし起動したところクラッシュし、起動できませんでした。

# 原因
詳しいことは分かりませんが、[バージョン7.4](https://docs.fortinet.com/product/forticlient/7.4)に原因があるようでした。[コミュニティサポートフォーラム](https://community.fortinet.com/t5/Support-Forum/Can-t-open-console-Forticlient-VPN-7-4-In-Sonoma/td-p/321785)でも同じエラーに遭遇している人の投稿がありました。

以下のような投稿もありました

https://twitter.com/scr_malu/status/1800451428659683499

# 対処
この問題が修正されるまではバージョン7.4は使わず、前のバージョンを使用するしかないと思います。私は以前にダウンロードしていたバージョン7.2のインストーラがダウンロードフォルダに残っていたので、それを用いてインストールしました。


特定のバージョンのインストール手順は以下を参考にしてみてください。

:::note warn
追記：以下の手順ではライセンス購入をしていないとダウンロードできないようです。
:::

[Technical Tip: How to download different or old versions of FortiClient and FortiClientEMS from the Fortinet Support Site](https://community.fortinet.com/t5/FortiGate/Technical-Tip-How-to-download-different-or-old-versions-of/ta-p/285874)

# 最後に
同じような内容で詰まっている方の助けになれば幸いです。
もし、他の対策方法を知っている方がいればコメントで教えて頂けると助かります。

# 追記
下記で修正した話が上がってます。検証できていないので本当にこれで動作するかは不明です
[How to connect Forticlient on Mac OS Sonoma. FIX with Screenshots](https://www.reddit.com/r/fortinet/comments/1c6414r/how_to_connect_forticlient_on_mac_os_sonoma_fix/)
Polyfill.io事件まとめ

## 概要
Polyfill.ioという広く利用されているJavaScriptライブラリにマルウェアを混入される事件が発生しました。このPolyfill.ioは、ウェブサイトが異なるブラウザで正しく動作するための互換性を提供するコードを提供しています。

## 事件の概要
### 買収とマルウェアの注入:
2024年2月、Polyfill.ioのドメインとGitHubアカウントが中国の企業Funnullに買収されました。その後、このライブラリにマルウェアが注入されました​。

### 影響:
マルウェアは、cdn.polyfill.ioから提供されるスクリプトに含まれ、これを利用している約100,000のウェブサイトに影響を及ぼしました。ユーザーがこれらのウェブサイトを訪れると、マルウェアが実行され、データ盗難や不正なリダイレクトなどの被害が発生する可能性がありました​。

### 検出と対応:
セキュリティ企業のSansecやその他の研究者がこの問題を特定し、警告を発しました。また、Googleはこのスクリプトを利用しているウェブサイトへの広告をブロックし、影響を受けたサイト運営者に対して警告を出しました​​。

## 対策と推奨
### 利用停止と代替:
開発者は、直ちにcdn.polyfill.ioドメインの使用を停止し、信頼できる代替手段や自己ホスティングのポリフィルを利用するよう推奨されました​​。

### セキュリティ強化:
この事件は、サードパーティライブラリの使用におけるセキュリティの重要性を改めて浮き彫りにしました。開発者は、定期的なセキュリティ監査やソフトウェア構成管理（SBOM）の導入、サードパーティライブラリの脆弱性管理を徹底することが重要です。

## まとめ
この事件は、ウェブ開発におけるサプライチェーンのセキュリティがいかに重要であるかを強調しており、外部リソースを統合する際には慎重なセキュリティ対策が不可欠です。

## 参考
- [Hackread](https://www.hackread.com/polyfill-library-injected-malware-impact-websites/)​​
- [SiliconANGLE](https://siliconangle.com/2024/06/26/supply-chain-attack-compromises-100000-websites-via-polyfill-io-domain-takeover/)
- [ThreatMon](https://threatmon.io/blog/polyfill-io-supply-chain-attack-how-over-100000-websites-were-compromised-and-what-you-need-to-know/)​​
- [Snyk](https://snyk.io/jp/blog/polyfill-supply-chain-attack-js-cdn-assets/)
- [SiliconANGLE](https://siliconangle.com/2024/06/26/supply-chain-attack-compromises-100000-websites-via-polyfill-io-domain-takeover/)
[Laravel]文字と数字が混在する場合のsort

## はじめに
こんにちは！

2024年新卒で無事エンジニアデビューしたものです。

私は私立の文系大学を卒業後、現在、株式会社ダイアログに入社し、エンジニアチームに配属されました。

自社では１ヶ月の全職種研修を終え、さらに１ヶ月のエンジニア研修を終えたのち案件にアサインされる形となっております。

そこで今回は私が初めてアサインしていただいた案件でつまづいた箇所を記載できればと思っております。

## 案件内容
衣類を扱う会社の帳票の改修

## 文字と数字が混在している場合のサイズ名の昇順
衣類を扱う中で色々なサイズ表記があります。
S・M・Lのような文字表記の場合もあれば70・100・115のような数字表記の場合、また３Lのような数字と文字の混在している表記の場合もあります。

この場合、昇順をつける上では文字列または数列のどちらかに表記を合わせる必要があります。

### 文字を数字に置き換える
例えば
サイズ表記の種類がsz_nm = [SS,S,M,L,XL,4L,90,100,120]あったとします。
・今回は[SS,S,M,L,XL,4L,90,100,120]という並び順で出力されるようにしたいのですが
　現在の状態のまま文字列でsortをすると各文字の先頭の数字を先に見てしまうため、
 　出力結果は[100,120,4L,90,L,M,S,SS,XL]となってしまいます。
　これでは想定通りの出力とならないため、
　条件分岐(CASE式)を使用して、SS~4Lの文字列を数値に変換します。

記載するコードは以下のようになります。

```
([\DB::raw('CASE sz_nm 
                      WHEN "SS" THEN 1
                      WHEN "S" THEN 2
                      WHEN "M" THEN 3
                      WHEN "L" THEN 4
                      WHEN "XL" THEN 5
                      WHEN "4L" THEN 6
                      ELSE sz_nm
                      END AS sz_nm_sort
                      ')]);
```
※sz_nmはサイズ名というカラム。（90,100,120はそもそもが数字列なのでelseの中に入っている。）

ここでは英語表記のサイズ名をDB上で全て数字に一旦置き換え、サイズの昇順をつけることが可能となります。

### 昇順に順番を変更する
また、この後の処理に数字列のsortを使用して並び替えると綺麗に並び替えることができます。
```
$hogehoge = $val['〇〇']->sort(function(Collection $d1, Collection $d2) {
?: $d1->get("sz_nm_sort") <=> $d2->get("sz_nm_sort")
)};
```
以上が文字と数字が混在している場合のサイズ名の昇順変更の流れになります。

## 最後に
今回の案件がエンジニアとして人生初案件でした。
プログラミング自体何も触れたことがない私に、優しくご教授いただきました先輩方には改めて
感謝申し上げます。
これからも精進して参ります。
Teamsで画面共有をした時に出るツールバーを非表示にしたい


タイトルの通りです。

Teams(アプリ版/Windows)で画面共有をしている時にタブを切り替えようとしたいのにツールバーが表示されてしまって押せない…

仕方なくtabキーで移動を試みたり、バーを左右に移動させたり…

Teamsで会議をするたびにストレスだったあのバーを非表示にする方法を先日知ったので、ナレッジとして残しておこうと思います。




### ①バーをクリックする
### ②[ctrl] + Wを押す

<br>

上記操作で非表示にできます。

お試しあれ！
Go言語におけるnilの構造体ポインタの扱い方：フィールドとメソッドのアクセス


Go言語では、`nil` の構造体ポインタにアクセスする際には注意が必要です。
特に、フィールドとメソッドにアクセスする場合の動作は異なるため、それぞれのケースについて詳しく解説します。

## フィールドにアクセスする場合

`nil` の構造体ポインタに対してフィールドにアクセスしようとすると、ランタイムパニックが発生します。

```go
package main

import "fmt"

type Foo struct {
	Name string
}

func main() {
	var foo *Foo
	fmt.Println(foo.Name) // panic: runtime error: invalid memory address or nil pointer dereference
}

```

このコードを実行すると `foo` が `nil` であるため、フィールド `Name` にアクセスしようとする際にランタイムパニックが発生します。
このような場合、フィールドにアクセスする前にポインタが `nil` でないことを確認する必要があります。

```go
package main

import "fmt"

type Foo struct {
	Name string
}

func main() {
	var foo *Foo
	if foo != nil {
		fmt.Println(foo.Name)
	} else {
		fmt.Println("foo is nil") // foo is nil
	}
}

```

## メソッドにアクセスする場合

Go言語では、ポインタレシーバを使用したメソッドは nilポインタでも呼び出すことができます。
これは、メソッド呼び出しがレシーバを最初の引数とする関数呼び出しに変換されるためです。

```go
package main

import "fmt"

type Foo struct{}

func (f *Foo) Bar() string {
	return "bar"
}

func main() {
	var foo *Foo
	fmt.Println(foo.Bar()) // bar
}

```

このコードでは、`foo` が `nil` であっても、メソッド `Bar` を正常に呼び出すことができます。

## エラー処理とnilチェック

レシーバが `nil` のときに発生する panic は、通常、プログラミングのミスを示すものです。
メソッドの呼び出し前に `nil` チェックを行い、事前に適切な処理を行う方法が一般的です。

```go
package main

import "fmt"

type Foo struct{}

func (f *Foo) Bar() string {
	return "bar"
}

func main() {
	var foo *Foo
	if foo != nil {
		fmt.Println(foo.Bar())
	} else {
		fmt.Println("foo is nil") // foo is nil
	}
}

```

ただし、場合によってはメソッド内でnilチェックを行い、処理することもあります。
例えば、レシーバがnilであることを特別なケースとして処理する必要がある場合です。

```go
package main

import "fmt"

type Foo struct{}

func (f *Foo) Bar() string {
	if f == nil {
		return "foo is nil"
	}
	return "bar"
}

func main() {
	var foo *Foo
	fmt.Println(foo.Bar()) // foo is nil
}

```

## まとめ

- フィールドにアクセスする場合: フィールドにアクセスする前にポインタが `nil` でないことを確認する必要があります
- メソッドにアクセスする場合: ポインタレシーバを使用したメソッドは nilポインタでも呼び出すことができますが、メソッド内で nilチェックを行い、適切に処理することが重要です

これらのポイントを理解することで、Go言語における `nil` の構造体ポインタの扱い方を正しく実装できるようになります。

## 参考

- [実用Go言語](https://amzn.asia/d/0jkScTwO) - 3.3.2 レシーバーはnilでもメソッドは呼べる
- [Go言語100Tips ありがちなミスを把握し、実装を最適化する](https://amzn.asia/d/05chIHOS) - 6.4 No.45:nilレシーバを返す
ITパスポート 損益分岐点と資産管理

・固定費
売上高とは関係なく発生する費用
・変動費
売上高に比例して発生する費用
・総費用
固定費＋変動費
・利益
売上高－（固定費＋変動費）

・損益分岐点売上高
利益と損失の分岐点にある売上高
売上高がこの点を上回れば利益が、下回れば損失が出ることになる
変動費率＝変動費÷売上高
損益分岐点売上高＝固定費÷（1-変動比率）

例：売上高が400万円、利益が50万円、固定費が150万円であるとき、損益分岐点での売上高はいくらか
利益＝売上高－（固定費＋変動費）より
変動費＝売上高－固定費－利益＝400-150-50＝200万円
変動費率＝変動費÷売上高＝200÷400＝0.5
損益分岐点売上高＝固定費÷（1-変動比率）＝150÷（1-0.5）＝300万円

・棚卸資産の評価法
・先入先出法
先に仕入れた商品から先に払い出していくと仮定して、払出単価とする方式
・移動平均法
商品の仕入れの都度、在庫商品の平均単価を算出して、直前の在庫商品の平均単価を払出単価とする方式

例：在庫評価額を考える
日付 摘要 個数 単価 金額
4/1 前月繰越 40 10 400
4/8 仕入 60 14 840
4/16 出庫 50

先入先出法
4/16の出庫は、4/1の40個のうちの40個と、4/8の60個のうちの10個を払い出したとみなす
よって、在庫は4/8の60個のうちの50個なので、在庫評価額は、50個x14円＝700円
また、売上原価は、40個x10円＋10個x14円＝540円

移動平均法
平均単価＝（在庫残高＋仕入金額）÷（在庫個数＋仕入個数）＝（40個x10円＋60個x14円）÷（40+60）＝12.4円
在庫評価額は、50個x12.4円＝620円

・在庫管理
定量発注方式
在庫が基準を下回ったら一定量を発注する
発注量は一定だが、発注の間隔はまちまち
定期発注方式
一定の間隔で発注する
発注の間隔は一定だが、発注量はまちまち

・減価償却
資産の購入にかかった金額（所得価額）を、一定の方法に従って、利用した年度ごとに減価償却費として計上する会計処理
定額法
毎年同じ金額を計上する
定率法
毎年同じ割合の金額を計上する
[mermaid] mermaidの記法

# 目次
- [まとめ](#まとめ)
- [フローチャートのフロー方向の記法](#フローチャートのフロー方向の記法)
- [フローチャートの線書式の記法](#フローチャートの線書式の記法)
- [フローチャートのノード間の記法](#フローチャートのノード間の記法)
- [フローチャートのノード図形の記法](#フローチャートのノード図形の記法)
- [GitHubにおけるmermaidの記法](#gitHubにおけるmermaidの記法)
- [Azure DevOpsにおけるmermaidの記法](#azure-devopsにおけるmermaidの記法)

# まとめ 
 > Mermaid は、Markdown にインスパイアされたテキスト定義とレンダラーを使用して複雑な図を作成および変更する、JavaScript ベースの作図およびグラフ作成ツールです。 
[Mermaid
Diagramming and charting tool](https://github.com/mermaid-js/mermaid/blob/develop/README.md)

ガントチャートや円グラフ、マインドマップも記述できるが、今回は使用頻度の高い**フローチャート**の記法を記載する。

```mermaid
 graph TD
 A[Start] --> B[fold_1]
 B --> C[fold_1_1]
 C --> D[fold_1_1_1]
 C --> E[...]
 C --> F[fold_1_1_3]
 D --> G[fold_1_1_1_1]
```

# フローチャートのフロー方向の記法
|記法|フロー方向|
|:--|:--|
|TB、TD|上から下|
|BT|下から上|
|LR|左から右|
|RL|右から左|

# フローチャートの線書式の記法
|記法|線書式|
|:--|:--|
|A --> B|矢印|
|A ==> B|太線矢印|
|A -.-> B|点線矢印|
|A --- B|線|
|A === B|太線|

```mermaid
 graph LR
 A[Start] --> B[fold_1]
 B ==> C[fold_1_1]
 C -.-> D[fold_1_1_1]
 D --- E[fold_1_1_1_1]
 F === G[fold_1_1_1_1_1]
```

# フローチャートのノード間の記法
~~~
```mermaid
flowchart TD
A-->|ここにコメントを記述|B
```
~~~

```mermaid
flowchart LR
A-->|ここにコメントを記述|B
```

# フローチャートのノード図形の記法
|記法|ノード図形|
|:--|:--|
|A[]|長方形|
|A{}|ひし形|
|A()|角丸長方形|
|A([])|楕円形|
|A(())|円形|

```mermaid
flowchart LR
Z[Start] --- A[長方形]
A --- B{ひし形}
B --- C(角丸長方形)
C --- D([楕円形])
D --- E((円形))
```

# GitHubにおけるmermaidの記法
~~~
```mermaid
 flowchart TD
 A[Start] --> B[fold_1]
 B --> C{fold_1_1}
 C --> D[fold_1_1_1]
 C --> E[...]
 C --> F[fold_1_1_3]
 D --> G[fold_1_1_1_1]
```
~~~

# Azure DevOpsにおけるmermaidの記法
1.  `~~~`や` ``` `ではなく、`:::`で`markdown`を囲む
1.  `flowchart`ではなく、`graph`で`markdown`を囲む

~~~
:::mermaid
 graph TD
 A[Start] --> B[fold_1]
 B --> C{fold_1_1}
 C --> D[fold_1_1_1]
 C --> E[...]
 C --> F[fold_1_1_3]
 D --> G[fold_1_1_1_1]
:::
~~~

# 参考リンク
- [Mermaid
Diagramming and charting tool](https://github.com/mermaid-js/mermaid/blob/develop/README.md)
- [Markdown で図が書ける！Mermaid記法の概要や書き方をご紹介](https://growi.cloud/blog/5789)
- [Azure DevOpsのWikiでmermaidを使用する際の注意点](https://techblog.ap-com.co.jp/entry/2022/02/21/143915)
Angular materialのカレンダーBodyにある日を非表示にしたい

先日、下記の記事を書いたが、localeを日本に設定すると、1日、2日と表示されるが１、２と表示したい（日を非表示にしたい）

https://qiita.com/beltway7/items/c06036973faef376290e

# localeを日本に設定すると
こんな感じ

![Screenshot 2024-07-02 at 17.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/5083046c-b773-b37d-35e5-d7744534193d.png)

# javascriptで日を''に置き換える
いろいろ調べてみたが、これ以外に方法が見つからなかった
```code
const cells = document.querySelectorAll('.mat-calendar-body-cell-content.mat-focus-indicator');
cells.forEach(cell => {
    cell.textContent = cell.textContent!.trim().replace('日', '');
})
```

日の部分は、`.mat-calendar-body-cell-content.mat-focus-indicator`で取得できる！

で、取得後は、forEachでぐるぐる回して、日を''にreplaceする

こんな感じ
![Screenshot 2024-07-02 at 17.19.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/96a8991d-69a7-1fe2-9a80-24de62d5dca2.png)

# 最後に
もっと良い方法があれば、教えて下さい

コードはこちら↓↓↓

https://stackblitz.com/edit/stackblitz-starters-czzs1g?file=src%2Fmain.ts