OmniAICreator/Qiita-1.07M huggingface dataset:
別のPC（Windows）で同プロジェクトのvenvの実行

# 状況

venvで環境を作成する際，プロジェクトのホームディレクトリにて以下のようなコマンドで行う．

```shell
pyenv local 3.x.x # 使用したいバージョン（設定していなければ）
python -m venv .venv # .venvという名前でvenvのディレクトリ・ファイルが作成される
```
この時，プロジェクト内に作成される固有の.venvディレクトリは以下の通り．
```
.venv
├─Scripts
├─Lib
├─Include
└─pyvenv.cfg
```
この中で，pyvenv.cfgは以下の通り．
```pyvenv.cfg
home = C:\Users\username\.pyenv\pyenv-win\versions\3.x.x # .pyenvの場所による
include-system-site-packages = false
version = 3.x.x
```
pyvenv.cfgは作成されたファイル類の中で，このvenvの所属元となるpython.exeの場所を示すっぽい．

この時，`home = C:\Users\username\.pyenv\pyenv-win\versions\3.x.x`は`username`というようなデバイス由来のパスになってしまう．そのため，`Git`などで別のPCで同プロジェクトの開発を行う際にそのままでは実行できない．PCを変える際にいちいちpyvenv.cfgのパスを変更するのは面倒くさいし，忘れそう．
ここでは，上記を解決する．

# 解決手順

settings.jsonに手を加えずに，また，余計な環境変数を作成せずにcfgファイル内のitsutを書き換えるのみで，環境に応じてユーザー名を動的に読み替える方法に取り組む。

まず、pyvenv.cfgは静的なファイルなので、動的な読み替えが直接はできないが、仮想環境の有効化時にスクリプトを実行して適切に設定することが可能である。
pyvenv.cfg ファイル内のパスを動的に変更するためには、スクリプトを利用してユーザー名に応じてパスを書き換える方法が考えられる。

## スクリプトの作成

仮想環境を有効化する前に、pyvenv.cfg ファイルの内容をユーザー名に基づいて書き換えるスクリプトを作成する。
例えば、PowerShellスクリプトを使用する場合，もしくはコマンドプロンプトを使用する場合：

PowerShell スクリプト (update_pyvenv.ps1)
```powershell
$username = $env:USERNAME
$pyvenvPath = "プロジェクトのパス\venv\pyvenv.cfg"
(Get-Content $pyvenvPath) -replace 'C:\\Users\\.*?\\\.pyenv', "C:\\Users\\$username\\.pyenv" | Set-Content $pyvenvPath
```

cmd バッチファイル (update_pyvenv.bat)
```cmd
@echo off
setlocal enabledelayedexpansion
set "username=%USERNAME%"
set "pyvenvPath=プロジェクトのパス\venv\pyvenv.cfg"
for /f "delims=" %%i in ('type "%pyvenvPath%"') do (
    set "line=%%i"
    set "line=!line:C:\Users\=.*?\.pyenv=C:\Users\%username%\.pyenv!"
    echo !line! >> "%pyvenvPath%.tmp"
)
move /y "%pyvenvPath%.tmp" "%pyvenvPath%"
```
<br>

<details>
  <summary>スクリプトで実行する場合</summary>

仮想環境を有効化する前に、このスクリプトを実行する。以下のように仮想環境を有効化する手順の前にスクリプトを呼び出す。

PowerShellの場合
```powershell
.\update_pyvenv.ps1
venv\Scripts\activate
```

cmdの場合
```cmd
call update_pyvenv.bat
venv\Scripts\activate
```
<br>
</details>

## 一連の処理をまとめた.ps1ファイルの作成
以下はPowerShellスクリプト (setup_env.ps1) でユーザ名を書き換え、仮想環境を作成し、Pythonのパスを確認する一連のコマンドを自動化する方法である。

PowerShellスクリプト (setup_env.ps1)
```powershell
# ユーザー名を取得
$username = $env:USERNAME

# pyvenv.cfgのパスを設定
$pyvenvPath = "プロジェクトのパス\venv\pyvenv.cfg"

# pyvenv.cfgのhomeディレクトリをユーザー名に基づいて書き換える
(Get-Content $pyvenvPath) -replace 'C:\\Users\\.*?\\\.pyenv', "C:\\Users\\$username\\.pyenv" | Set-Content $pyvenvPath

# 仮想環境を再作成
python -m venv venv

# 仮想環境を有効化
. .\venv\Scripts\activate

# Pythonのバージョンを確認
.\venv\Scripts\python.exe --version
```

####  小話：.\venv\Scripts\python.exe と venv\Scripts\python.exe の違い
- .\venv\Scripts\python.exe: 現在のディレクトリにある venv フォルダの Scripts フォルダ内の python.exe を指定している。.\ は現在のディレクトリを指し示すため、WindowsのコマンドプロンプトやPowerShellで使用される。

- venv\Scripts\python.exe: 同じく venv フォルダの Scripts フォルダ内の python.exe を指定しているが、現在のディレクトリがすでに仮想環境のルートである場合は、.\ を省略しても問題ない。

実質的に、これらのコマンドは同じ場所を指し示している限り、同じ動作をする。ただし、スクリプトやコマンドラインでの明確さを保つために、.\ を付けることで、現在のディレクトリからの相対パスであることを明確にするのが一般的であるらしい。

### スクリプトの実行
PowerShellで以下のコマンドを実行してスクリプトを実行する。

```powershell
.\setup_env.ps1
```

これで、ユーザー名に基づいて pyvenv.cfg ファイルを更新し、仮想環境を再作成し、有効化してPythonのバージョンを確認する一連の操作が自動で行われるようになる。
【Dify×Notionで作るレシピ管理システム】レシピ検索・買うものリスト登録編

**生成AIを用いたワークフローが簡単に作れるDifyと、神タスク管理ツールであるNotionを連携させてレシピ管理システムを一日で作成した**ので備忘的に内容を説明します。

前回のレシピ登録機能に続いて、今回はレシピ管理システムの重要な機能である「**レシピ検索**」と「**買うものリスト登録**」機能について詳しく解説します。

https://powerplatformnikki.com/difyrecepiautomation2

## 実行結果

材料やレシピの単語を入力するとNotionからレシピを検索してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/fa6dc577-373d-4d01-cbe1-4aa5e940ec8b.png)

材料一覧を入力すると買うものリストにまとめて登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/e147bdc5-2477-c619-3454-71551f9698ba.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/b8839837-2e7b-635d-f9f2-6e2bc1e0d36c.png)

## レシピ検索機能の概要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/2c5b0cfb-9f97-d8bd-eba2-2f1016167674.png)

レシピ検索機能は、ユーザーが入力したキーワードや条件に基づいて、Notionデータベースに保存されているレシピを検索し、その結果をLLMで整形して適切な結果を返します。

### Notion検索用HTTPリクエスト

GETかと思いきやPOSTだったのでちょっとハマりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/ca7c0484-7ccf-e4e4-c987-6233a3c21419.png)

| 項目 | 値 |
|------|-----|
| POST | https://api.notion.com/v1/databases/[NOTION_DATABASE_ID]/query |
| Authorization | Bearer [NOTION_API_KEY] |
| Content-Type | application/json |
| Notion-Version | 2022-06-28 |
| ボディ | none |

https://qiita.com/__Tetsutaka__/items/1c45f463f0ff665274f4

### 検索結果解析用LLMノード

検索した結果をLLMで解析し、ユーザーへ出力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/6890def0-85a6-a407-6d9d-f515508e7ded.png)

## 材料登録機能の概要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/1b16469c-4b83-7f63-e15e-d5e7525fd502.png)

材料登録機能は、ユーザーが入力したレシピの材料を買うものリストという別のNotionデータベースに登録します。

### 材料抽出用LLM

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/e0a2c946-b0fc-5e08-b00b-4ef983c9d187.png)

入力された材料一覧をLLMで整形します。

### アレイに変換

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/d89f1144-fe3c-a8a1-4a05-1c80b5ebc664.png)

入力された材料一覧のテキストをアレイに変換して、イテレーション(繰り返し処理)できるようにします。

### イテレーション

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/eeb29ab1-0f0f-baee-788b-cbaf7f81f875.png)

イテレーションを用いてHTTPリクエストを材料ぶん実行します。

https://zenn.dev/itella_blog/articles/547f276da437cc

### 買い物リスト登録用HTTPリクエスト

繰り返し処理のアイテムを取るにはitemを変数として設定します。
エラーっぽい表示になりますが、普通に動きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/f93cfa50-6915-cd1d-69c3-070f5b3305f9.png)

| 項目 | 値 |
|------|-----|
| POST | https://api.notion.com/v1/pages/ |
| Authorization | Bearer [NOTION_API_KEY] |
| Content-Type | application/json |
| Notion-Version | 2022-06-28 |
| ボディ | 以下に記載 |

```json
{
  "parent": { "database_id": [NOTION_DATABASE_ID] },
  "properties": {
    "Name": {
      "title": [
        {
          "text": {
            "content": "材料名"
          }
        }
      ]
    }
  }
}
```

## まとめ

これで一通り機能紹介は終わりです。今後も実際に使いながら機能追加したり修正したりすると思います。

みなさんも参考にDifyで遊んでみましょう！

https://powerplatformnikki.com/difyrecepiautomation1

https://powerplatformnikki.com/difyrecepiautomation2
Apple Intelligenceの概要まとめ

iOSアプリは年々進化を遂げており、ユーザ体験を向上させるための新しい技術が次々と登場しています。その中でも、Apple Intelligenceはアプリの操作性を飛躍的に向上させるための重要な技術です。

# Apple Intelligenceとは

Apple Intelligenceは、iOSアプリの操作性を向上させるための一連の技術とAPIです。これにより、アプリがユーザのコンテキストを理解し、自然な対話や予測的な操作を提供できるようになります。主な機能には、音声認識、自然言語処理、機械学習による予測、そしてSiriとの統合が含まれます。これにより、ユーザは音声コマンドや自然言語入力を使ってアプリを操作できるようになります。

Apple Intelligenceの特徴として、iPhoneだけでなく、iPadやMacでも同じ機能が搭載される点が挙げられます。これはApple製品間でのシームレスな体験を提供するもので、ユーザはどのデバイスを使っても一貫した操作性を享受できます。また、M2搭載iPad Proでは、Apple Intelligenceが他社のAI（例えばGalaxy AI）のおよそ30倍の性能を発揮することが[確認](https://wccftech.com/m2-ipad-pro-apple-intelligence-rewrite-and-proofread-nearly-15000-characters-on-device/)されており、その性能の高さが注目されています。

# SiriやChatGPTとの関係
## Siriとの関係
Apple IntelligenceはSiriの機能を拡張したものであり、Siri単独の音声アシスタント機能に加えて、より高度な自然言語処理や機械学習を活用した予測機能を提供します。これにより、アプリはユーザの意図をより正確に理解し、適切なアクションを実行できます。例えば、Siriは特定の音声コマンドに対して応答する一方、Apple Intelligenceはユーザの行動パターンを学習し、予測的な提案を行うことができます。

## ChatGPTとの関係
ChatGPTはOpenAIが開発した高度な自然言語処理モデルであり、Apple Intelligenceと共に使用されることで、ユーザインターフェースをさらに強化することができます。例えば、アプリ内でのチャットボット機能や複雑な質問応答システムを構築する際に、ChatGPT-4の能力を活用することが可能です。これにより、ユーザはより自然で人間らしい対話をアプリ内で体験できるようになります。

# Apple Intelligenceの登場によるユーザ体験の変化

## ユーザ体験の変化
Apple Intelligenceの登場により、ユーザとの接点がさらに広がり、アプリはAPIとして機能を提供する役割を強化しています。これにより、ユーザ体験は従来のアプリ内に閉じたUIベースの体験から、よりシームレスで統合された体験へと進化しています。

従来、ユーザ体験はアプリ内で完結していました。ユーザはアプリを起動し、画面を操作することで目的の機能にアクセスしていました。Siriを通じてAppIntent(*1)を提供することで、アプリの一部機能を外部から操作することは可能でしたが、Apple Intelligenceの登場により、これがさらに進化しています。

Apple Intelligenceを活用することで、アプリはユーザの行動やコンテキストをより深く理解し、必要なタイミングで適切な情報や機能を提供できます。例えば、ユーザが日常的に利用する機能を学習し、予測的に提案することで、ユーザはアプリを直接操作せずとも必要な情報やサービスにアクセスできるようになります。

*1: AppIntentは、iOSアプリがSiriや他のApple Intelligence機能と統合するための主要なコンポーネントです。AppIntentを使うことで、アプリはユーザの音声コマンドや自然言語入力に対して特定のアクションを実行できます。これにより、ユーザはアプリの特定の機能を音声コマンドで直接操作できるようになります。

# Apple Intelligenceの現状と将来

Apple Intelligenceは現在、iOS 18.1 BetaおよびiPadOS 18.1 Betaでテスト中であり、現時点では英語版のみが提供されています。これを使用するには、デバイスの地域設定を「US」、言語設定を「En」にする必要があります。また、現時点では一部機能のみが試験運用中であり、以下のような改善が[確認](https://www.businessinsider.jp/post-291468)されています。

- 音声アシスタントSiriの改善
- 文章生成・要約
- 写真アプリのキーワード検索の改善
- 音声通話の文字起こし

一方、以下の機能はまだ搭載されていません：

- 画像生成
- オリジナル絵文字生成（Genmoji）
- 通知の優先順位付け
- 個人的なアプリ利用状況を加味したSiriでの対話
- ChatGPTとの連携

Appleは、Apple Intelligenceの正式リリースを「秋」としており、iOS 18のリリース後、iOS 18.1が11月あたりに登場する見込みです。これにより、Apple Intelligenceの完全な機能が提供される予定です。

当初はアメリカ向けの提供ですが、iOS 18ベータをインストールした対応機種で、言語設定をEnglish（US）、地域設定をUSに変更すれば対象地域外でも使用可能です。しかし、中国とEUでは、言語と地域の設定を変更してもApple Intelligenceの機能は利用できません。これは、中国は政府によるAIに関する厳しい規制が存在することと、EUではデジタル市場法（DMA）による規制の影響があるためです。

Appleは声明の中で、EUにおいては「プライバシーとセキュリティの懸念」により機能が制限されると述べています。これは、Appleが現地のAI規制によりApple Intelligenceの動作を変更せざるを得ない可能性があるためです。また、中国では、データが他国のサーバーに送信されずに中国国内のサーバーで処理されることを要求する現地法に従う必要があります。

ティム・クックCEOは、アナリストからの質疑応答で、中国やEUでのApple Intelligenceの提供について、規制当局と協議を進めていると述べ、全世界のユーザに早期に機能を提供できるよう努力していることを強調しました。

また、Apple Intelligenceに対応するのは、iPhoneならiPhone15 Pro/iPhone15 Pro Max、MacとiPadならM1以降搭載モデルに限られます。

Appleは全世界のユーザーにApple Intelligenceを早期提供できるよう、規制当局と協議を進めているようなので、その日が早く来るとよいですね！
AWS EC2からDynamoDBテーブルにアクセスする方法(IAM設定)


内容:
Amazon DynamoDBテーブルにアクセスする必要があります。しかし、このアクセス権限をどのように設定すればよいか分からないという声がありました。そこで、今回はEC2からDynamoDBテーブルにアクセスする方法について解説します。

IAMロールの作成:
まず最初に、DynamoDBテーブルにアクセスするためのIAMロールを作成します。IAMコンソールにアクセスし、「ロールの作成」を選択します。その後、DynamoDBへのアクセス権限を含むポリシーをアタッチした新しいロールを作成します。

EC2インスタンスプロファイルへのIAMロールの割り当て:
次に、作成したIAMロールをEC2インスタンスに割り当てます。EC2コンソールにアクセスし、対象のインスタンスを選択します。その後、インスタンスの詳細ページで「アクション」を選択し、「インスタンス設定」>「IAM ロールの関連付け」を選択します。ここで、先ほど作成したIAMロールを選択し、関連付けを行います。

EC2インスタンスは、IAMロールに付与された権限を使用してDynamoDBテーブルにアクセスすることができます。この方法を使用することで、セキュリティを確保しながら、アプリケーションが必要とするデータに効率的にアクセスすることができます。
RDSを自動起動する際にKMSは考慮しなくていい話


気になったので残しておきます。

KMS で作成した CMK で暗号化している RDS インスタンスを一時停止の状態から起動する場合、または一時停止を行う場合、起動/停止を実施するユーザまたはロールには KMS へのアクセス許可は不要です。
【Dify×Notionで作るレシピ管理システム】概要＆セットアップ編

生成AIを用いたワークフローが簡単に作れるDifyと、神タスク管理ツールであるNotionを連携させてレシピ管理システムを一日で作成したので備忘的に内容を説明します。

今回は、Difyを使って作成したレシピ管理システムのセットアップ方法と基本的な機能について解説します。このシステムを使えば、レシピの登録、検索、買い物リストの作成が自動化され、日々の料理がもっと楽しくなりますよ。

## システム概要

### 機能

https://twitter.com/PowerPlatform4/status/1820040693773193267

このレシピ管理システムは、以下の3機能で構成されています。

1. 記事からNotionにレシピ登録
2. Notionからレシピ検索
3. レシピの材料から買うものリストに登録する

入力を質問分類器によって分類し、入力に応じて上記の三機能のフローを実行します（クラス1とクラス2は集約される）。

## 使用コンポーネント

このワークフローでは、以下のコンポーネントを使用しており、Dify上でGeminiとNotion APIを実行することで機能を実現しています。

- **Dify**：ワークフローの中心となるプラットフォーム
- **Google AI Studio (Gemini Pro 1.5 Flash)**：自然言語処理とテキスト生成
- **Notion (API)**：レシピと買い物リストのデータベース

モデルにGeminiを選んだのは、現在一定無料で使用できるからです。

## セットアップ方法

Dify、Gemini、Notionのセットアップ方法です。

### Difyアカウントの作成

1. Difyのウェブサイトにアクセス
2. 「Get Started」をクリックしてGoogleなどでアカウントを作成

詳細なセットアップ手順は以下の記事を参照してください。

https://qiita.com/minorun365/items/4c5dba1de7977c386249

### Google AI Studio APIキーの取得

1. Google AI Studioにアクセス
2. APIキーをコピーしておきます

詳しくは以下の記事を参照してください。

https://auto-worker.com/blog/?p=8667

注意：APIキーは機密情報です。Githubなどの公開リポジトリにアップロードしないようご注意ください。

### Notion APIの設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/224ef86b-89b6-4663-ade4-2a4ed64a58ad.png)

[Notion API を使用してデータベースを操作する](https://zenn.dev/kou_pg_0131/articles/notion-api-usage)を参考に、インテグレーションを作成してキーをコピーしておきます。

注意：Notionのシークレットキーも機密情報です。適切に管理してください。

以下の記事の通りDifyにはデフォルトでNotionとの連携機能もありますが、**ナレッジは手動更新しかできずデータの登録はAPIでしかできない**ようでしたので、HTTPリクエストを使用します。

https://note.com/jolly_dahlia842/n/n7b8b029316cd

### Notionデータベースの作成

[ガイドとチュートリアル：Notion (ノーション)の使い方](https://www.notion.so/ja-jp/help/guides)を参考に、レシピと買い物リストの2つのデータベースを作成します。

- **レシピDB**：
  - タイトル（タイトル型）
  - 材料（リッチテキスト型）
  - 手順（リッチテキスト型）
  - タグ（マルチセレクト型）
  - 時間（数値型）
  - URL（URL型）

- **買い物リストDB**：
  - (タイトルなし)（チェックボックス型）
  - Name名（タイトル型）
  - レシピタイトル（テキスト型）

各データベースのIDを控えておきます。以下画像の黒塗り部分(/~?)がデータベースのテーブルIDです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/90b09833-b9b5-14bf-f04b-37ac5d172f11.png)

## つづき

需要とやる気があれば機能ごとに記事を書くかも…

Claudeなど生成AIチャットボットに聞きながらではありましたが、Difyを通じて前から使いたいと思っていたGeminiやNotionのAPIを勉強できたのでよかったです。

https://powerplatformnikki.com/difyrecepiautomation2

## 元記事

https://powerplatformnikki.com/difyrecepiautomation1/
【備忘録】Python：*argsと**kwargsはどのようなものなのか

# *argsと**kwargsはどのようなものなのか

*argsと**kwargsは、Pythonの関数定義において可変長の引数を受け取るために使われます。これにより、関数に渡される引数の数が不定であっても対応することができます。

## *argsの使い方
*argsは、関数に任意の数の位置引数を渡すために使われます。関数定義において*argsと書くと、渡されたすべての位置引数がタプルとして関数内で利用可能になります。

例：
```python
def print_args(*args):
    for arg in args:
        print(arg)

print_args(1, 2, 3)
```

上記のコードの実行結果は次の通りです：

```console
1
2
3
```

## **kwargsの使い方
**kwargsは、関数に任意の数のキーワード引数を渡すために使われます。関数定義において**kwargsと書くと、渡されたすべてのキーワード引数が辞書として関数内で利用可能になります。

例：
```python
def print_kwargs(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_kwargs(a=1, b=2, c=3)
```
上記のコードの実行結果は次の通りです：

```
a: 1
b: 2
c: 3
```

## *argsと**kwargsを組み合わせた使い方
*argsと**kwargsを組み合わせて使うことで、関数に任意の数の位置引数とキーワード引数の両方を渡すことができます。

例：
```python
def print_args_kwargs(*args, **kwargs):
    print("args:")
    for arg in args:
        print(arg)
    print("kwargs:")
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_args_kwargs(1, 2, 3, a=4, b=5, c=6)
```

上記のコードの実行結果は次の通りです：

```
args:
1
2
3
kwargs:
a: 4
b: 5
c: 6
```

## 使用例と実用性
*argsと**kwargsを使うことで、関数がどのような引数を受け取るか事前に知らなくても、柔軟に対応することができます。
特に以下のような場合に有用です：

1. 可変長の引数を受け取る関数：引数の数が異なる場合でも同じ関数を使いたいとき。

2. デコレータ：デコレータは元の関数がどのような引数を受け取るか知らない場合が多いため、*argsと**kwargsを使ってすべての引数を受け取れるようにします。

3. 引数のラップ：複数の関数に共通の前処理や後処理を追加したいときに、*argsと**kwargsを使って関数をラップします。

例：デコレータでの使用
```python
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before the function call")
        result = func(*args, **kwargs)
        print("After the function call")
        return result
    return wrapper

@my_decorator
def my_function(a, b, c):
    print(f"a: {a}, b: {b}, c: {c}")

my_function(1, 2, 3)
```

このコードの実行結果は次の通りです：
```
Before the function call
a: 1, b: 2, c: 3
After the function call
```

このようにして、*argsと**kwargsを使うことで関数の柔軟性が大幅に向上し、さまざまな状況に対応できるようになります。
テストについてまず知っておきたい用語

# テストについてまず知っておきたい用語

## なぜこの記事を書こうと思ったのか
フロントエンドエンジニアとしての経験が一年となり、いよいよ自動テストなどの知見も付けていきたいなぁと思っていたところ、
テストの中にも種類があったりでなかなか脳内に浸透せず、
ちょっとここで用語の整理を忘備録として残しておきたいと思います。

## 私の経験について
React　TypeScriptの経験が一年ほど。
ローカル環境での開発、実施経験はあるがデプロイやビルドに関する知見が無い。
テストに関しては想定ケースを考えてテストケースをエクセル上に書き出し、手動テストのみの実施経験。

### なので、テストに関することのまとめとして今回記事を書いています。
それではよろしくお願いします。


## そもそも何で自動テストが必要なんだ？という話。
・　テストコードを書くのは工数がかかる
・　テストに関することもそれなりの知見が必要になる

こういうところがあるのですが、それを差し引いてもテストコードがあることで、
作業におけるバグなどの手戻りも、発生しづらくなるということがあるみたい。
手動テストでも都度都度バグ見つけては直したりしてたけど、そういうのがもしかしたら減ってたのかな。

自動テストで防げる点、防げない点があるので、可読性の高いコードを書くとか、手動テストでの網羅性みたいなものを意識してあげてチームでケース考えて取り掛かるのが一番いいんじゃ無いかと思う。
もちろん使えたら便利だし、技術に関するニーズもあるのが現状。あとはテストってどんな種類があるのかってことを覚えておきたい。

## テストは主に4種類なので下記について
- Static Test (静的テスト)
- Unit Test (単体テスト)
- Integration Test (結合テスト)
- End to End Test (E2Eテスト)

## Static Test(静的テスト)
これはJSやReactでのTypeScriptでの実装最中に起こる型エラーなどが主なものになります。
変数名の書き間違い、型の不一致の可能性などを表示してくれるものですね。

他にもESLintやコードフォーマッタの「Prettier」なども、静的テストに含まれるそうです。
なのでローカル環境での開発をしながら検出されるエラーが、「静的テスト」という認識でいれば問題はなさそう。

## Unit Test(単体テスト)
これはvitestやjestなどで扱われれる、ユーティリティ関数やカスタムフックなどの単体での動作確認をテストする際に行われるテストです。（期待値などを設定できる）
これらを使用する場合にテストコードの作成が必要があります。

## Integration Test (結合テスト)
それぞれのコンポーネントや関数を組み合わせた時に機能が問題なく使用可能かどうかをチェックするテストのこと。
結合なので、「組み合わせて」使えるかどうかをチェックします。
testing-libraryが割と使われていますね。

## End to End Test (E2Eテスト)
E2EテストはAPIやブラウザ等の環境でアプリケーションを開始、システム全体が正しく動くかをチェックします。
フロントエンドのエンドツーエンド（E2E）テストは、手動でテストケースを考え、それを自動化するためにスクリプトを書く必要があります。E2Eテストは、ユーザーが実際にアプリケーションを操作するシナリオをシミュレートするため、手動でのテストケースの設計が不可欠です。
大規模アプリケーションの場合は回帰テストの実施などが省略できるため、自動化実装が出来ると便利。（ただしこちらも工数がかかる）

Cypressなどのライブラリがあるみたいなんですが、もう少し学習は先かなぁ、　まずは小さくvitestかな。

## 補足
ステージング環境での手動テストは、結合テストの一部としてみなすこともできますが、通常はエンドツーエンドテストに分類される。


## よく聞くけどよくわからない「パイプライン」ってなんだ？
A ソフトウェア開発やデプロイの一連操作のプロセスを自動化してくれるもの。

一連操作の例としては、ビルド→テスト→デプロイを自動的に実行してくれる。
各ステージは前のステージが成功した後にのみ実行され、失敗するとその時点で停止します。

この、パイプライン内の「テスト」に失敗したりする場合は、前述の通りでデプロイが行われず処理が停止する。

## CI/CDって何？
CI/CDは、継続的インテグレーション（Continuous Integration）と継続的デリバリー（Continuous Delivery）または継続的デプロイメント（Continuous Deployment）の略。

継続的インテグレーション（CI: Continuous Integration）
**継続的インテグレーション（CI）**は、開発者がコードを頻繁にリポジトリに統合（マージ）するプラクティスです。このプラクティスの主な目的は、コードの変更を早期に検出し、統合時の問題を迅速に解決することです。

継続的デリバリー（CD: Continuous Delivery）
**継続的デリバリー（CD）**は、ソフトウェアを常にデプロイ可能な状態に保つプラクティスです。CIの後に続くプロセスで、リリースの自動化と承認を含みます。
### つまり
何やら難しく書いてしまいましたが要するにあれです。
git-flowで管理してるリモートリポジトリ内のstgブランチやmainブランチに変更がかかった際に自動的にデプロイがかかる処理のことです。

## 最後に
アウトプット目的となってしまいましたが多少用語のイメージはつきやすいんじゃ無いかと思います。
知見をつけていきたいですね。
vitestを覚えたい。けど個人開発の小規模アプリだとユーティリティ関数そんなに使わないんだよなぁ。
ありがとうございました。
imagemagick(convert)で画像からPDFへの変換のエラーの対処

## 環境
* Linux Mint 21.1
Version: ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25
```
sudo apt-get install imagemagick
```

## 使用方法

```
convert input1.jpg input2.jpg input3.jpg output.pdf
```
```
convert *.jpg output.pdf
```

## 実行中のエラー
```
convert-im6.q16: DistributedPixelCache '127.0.0.1' @error/distribute-cache.c/ConnectPixelCacheServer/244.
```
```
convert-im6.q16: not authorized
```
## エラー対応
いずれも/etc/ImageMagick-6/policy.xmlの変更を行う｡
```
前 <policy domain="resource" name="memory" value="256MiB"/>
後 <policy domain="resource" name="memory" value="1GiB"/>
```
```
前  <policy domain="coder" rights="none" pattern="PDF" />
後
<!--
    <policy domain="coder" rights="none" pattern="PDF" />
-->
```


## 参考リンク
Linux で JPG 画像ファイルを PDF 形式に変換する方法
https://ja.linux-console.net/?p=9092

ImageMagickのconvertコマンドで「cache resources exhausted」エラーの解消方法 – myaNOTE
https://blog.myanote.com/post/529

ImageMagickでPNGをPDFに変換する
https://zenn.dev/yakumo/articles/702d816f8f8f4676a480ca4081627a8c

Linux環境設定/ImageMagickのconvertコマンドでエラーが出る場合の対処方法 - Linuxと過ごす
https://linux.just4fun.biz/?Linux%E7%92%B0%E5%A2%83%E8%A8%AD%E5%AE%9A/ImageMagick%E3%81%AEconvert%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95
2024/8/5主にITとかセキュリティの記事

AndroidのSMSメッセージ狙い、10万以上のマルウェア拡散(8/2)
https://news.infoseek.co.jp/article/mynavi_2797197/

タレス、2024年度版「クラウドセキュリティ調査」を発表(8/3)
https://japan.cnet.com/release/31007265/

未然に防ぐのは厳しい？「ぶいすぽっ！」での情報流出問題、原因は“グーグルの予告なき仕様変更”の可能性　調査結果で判明(8/3)
https://news.yahoo.co.jp/articles/a0c8921074fc5010e9a3ca95ffe4bc3a2eb68c86

Kasperskyレポート：パリの公衆Wi-Fiスポットの約25%でセキュリティが不十分と判明(8/3)
https://www.jiji.com/jc/article?k=000000431.000011471&g=prt

フランス、「MiCA」に基づく仮想通貨取引所の認可申請を受付開始(8/3)
https://coinpost.jp/?p=549296

米国 NIST SP 800-231 バグフレームワーク（BF）： サイバーセキュリティの弱点と脆弱性の公式化(8/3)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/08/post-04e69c.html

結局「Copilot+ PC」で何ができる？　Microsoftの“新AI PC”向け機能群(8/3)
https://techtarget.itmedia.co.jp/tt/news/2408/03/news01.html

経済的支援受ける子どもの個人情報を誤掲載、栃木県教委がＨＰに(8/2)
https://news.yahoo.co.jp/articles/6cea246132c81341d75d63ac234512162bdac2bb

新潟県三条地域振興局が誤って個人情報流出、道路台帳図面に担当者の氏名掲載したままホームページ公開(8/3)
https://www.niigata-nippo.co.jp/articles/-/452004

銀行口座から金銭を窃取するAndroidマルウェアに注意、データ消去の恐れ(8/3)
https://news.mynavi.jp/techplus/article/20240803-2996931/

AIモデルの「モデル崩壊」に対する脆弱性が判明　他のAIモデルが生成したデータを学習することのリスク(8/3)
https://ledge.ai/articles/ai_models_collapse_when_trained_on_recursively_generated_data

乗っ取られていた「長崎市の観光情報」SNSが回復(8/2)
https://www.fnn.jp/articles/-/738310

当行を名乗ったショートメールによるログイン通知に注意願います 北海道銀行(8/3)
https://www.hokkaidobank.co.jp/news/campaign/detail.php?id=3658

【サイバー攻撃図鑑 ファイル16】水飲み場攻撃とは？巧妙なサイバー攻撃の手口と防御策を解説
https://cybersecurity-park.com/2430/

パソコン画面に「ウイルス感染」四国中央の会社員男性３２万円特殊詐欺被害【愛媛】(8/2)
https://www.fnn.jp/articles/-/738379

「乗っ取りは現実的ではない」アインシュタイン稲田　DMで“わいせつ画像要求疑惑”の弁明にホワイトハッカーが異論(8/3)
https://news.yahoo.co.jp/articles/8cf1550733829ed406eb82a0eeeaf6f6d4d19e40

次期欧州委、「防衛相」を新設　ロシアの脅威に備え
産業後押し、加盟国との調整役　NATOと連携、知見共有(8/3)
https://www.nikkei.com/article/DGKKZO82537560S4A800C2FF8000/

小学生が生成AIをツールとして活用――学びの充実につなげる狙いは(8/3)
https://news.ntv.co.jp/category/society/a96d7a6a70094e0798ec97e8b241b2d0

息子に「iPhone」を買い与えようと思うのですが、「ネット詐欺」が心配です。どんなものに気をつけるべきでしょうか？(8/3)
https://financial-field.com/living/entry-313600
Javaで「パターンとマッチした部分文字列の情報を取得する」の動作を確認してみた

# 概要

Javaで「パターンとマッチした部分文字列の情報を取得する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/regex/index5.html

# 実装

以下のファイルを作成しました。
```JSample5_1.java
import java.util.regex.*;

class JSample5_1{
  public static void main(String[] args){
    String regex = ".区";
    Pattern p = Pattern.compile(regex);

    Matcher m = p.matcher("東京都港区赤坂");
    if (m.find()){
      System.out.println("Start : " + m.start());
      System.out.println("End   : " + m.end());
      System.out.println("Match : " + m.group());
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample5_1.java 
$ java JSample5_1 
Start : 3
End   : 5
Match : 港区
```

# まとめ

何かの役に立てばと。
ゲーム製作が上手く行かない時に気を付けていること

自分が作業する際に気を付けている事などをまとめてみました。

## 本を読む事に集中出来ない時
本を落ち着いて読めない時には、まず、パソコンをスリープモードにして本に集中すると解決する事があります。
また、疲れていたりストレスがある時なども本を読むのは難しいです。

本が難しくて先に進まないと感じた時などには、勇気を出して少しレベルを下げた本を選ぶと意外とスムーズに進みます。

遠回りする事で自分が前に進む力を蓄えられているのかも知れません。

## 行き詰まった時
### エラーなどで行き詰まった時
まず、頭の中がごちゃごちゃになっていないか振り返ってみると解決する事があります。

頭の中がごちゃごちゃしている時には頭を整理します。

散歩をしたり、トイレに入ったり、睡眠を取ったり、風呂に入ったりしてみます。
それでもダメな時には頭の中にある物を全部紙に書き出して何が問題か整理してみると解決の糸口が見えてくるかも知れません。

### 根本的にどうにもならなそうな時
設計をし直す、リファクタリングをする、勉強をし直すなど一つに決め、それに集中出来ると先に進める気がします。
集中出来ないと先に進まないと思うので、とにかく何か一つに決めて雑念を出来る限り減らす事を意識いているかも知れません。

## モチベが出ない
### 先に進んでる気がしない
作業日誌を書いたり、予定表を組んで、作業を行ったらチェックをする、仕様書を細かく書き出して作業が済んだ物をチェックするなどしてやった事を見える化するとモチベになります。

また、仕様書などを予め作っておき、後は作業をやるだけにしておいたり、コードを記述しながらリファクタリングを行ったりする事で作業を単調にしないようにしているのも影響があるかも知れません。

但し、イラストに関してはブランクが発生するので、まとめて時間を取って描いています。

また、好みが分かれるかも知れませんがバージョン番号を付けたりもしています。

また、それでも達成感が得られない場合には、とにかく薄い入門書を一冊終わらせる事に集中してみるのも手かと思います。

自分はプライドが高く、最初に難しい本などを選んで挫折する傾向があるので、とにかく簡単そうな入門書を一冊終わらせるようにしています。そうすると自信が付いたり、ツールや言語の作法などが身に付き、その後が動きやすくなります。

### 何をやっているか分からなくなった。
作業日誌を付けると改善する事があります。
今何をしていて、なぜそうなったのか、次回何をしようと思ったのかなどをメモをしています。
ToDoリストでも、メモ帳でも、一週間後に見て思い出せるように出来ていると上手く出来たと感じます。

## あとがき
大事なのは、小さなコツを一つずつ積み重ねる事だと思うので、気長に取り組むと幸せになれるかと思います。

今は AI が色々と助け船を出してくれる時代にもなりましたので、自分なりのやり方を探すのも面白いと思います。

皆さんのゲーム製作ライフに幸がありますように！
Framer-motionを使って、簡単にフェードインフェードアウトを実装する

# はじめに
あるとき、Next.jsでの開発をして見たいと感じ、ポートフォリオサイトのようなものを作っていました。
フロントエンド開発とかほとんどやったことのない自分がQiitaのアイコンとしても使っているアイコンをフェードインさせたらオシャレなんじゃねと、デザインセンスないながらも感じました。
そういう経緯からどうやるのか調べて見たところ、どうやら`Framer-motion`というライブラリがあるそうなので、使ってみました。

# そもそもFramer-motionって？
React用のオープンソースアニメーションライブラリです。

https://www.framer.com/motion/

# 使ってみる

### まずはセットアップ

:::note
next.jsのセットアップは省きます。
:::

まずインストールします。

- npmの場合

```
npm install framer-motion
```

- yarnの場合

```
yarn add framer-motion
```

### framer-motionを使ったフェードインを実装していく
今回はアイコンと名前をフェードインさせるコードを書いてみました。

```typescript
<AnimatePresence mode="wait">
                <div className="relative grid grid-cols-4">

                    <div className="main col-span-4 mx-auto my-10">
                        <motion.div
                            initial={{opacity: 0}}
                            animate={{opacity: 1}}
                            transition={{duration: 0.5, delay: 0.5}}
                            key="image-container"
                        >
                            <Image
                                src={`${BASE_PATH}/images/img.png`}
                                alt="icon"
                                width={500}
                                height={500}
                            />
                        </motion.div>

                        <motion.div
                            className="flex items-center justify-center my-5"
                            initial={{opacity: 0}}
                            animate={{opacity: 1}}
                            transition={{duration: 1, delay: 1}}
                            key="image-container"
                        >
                            <div className="name text-center text-9xl">
                                <h1>MAOZ</h1>
                            </div>
                        </motion.div>

</AnimatePresence>
```

使い方としては`AnimatePresence`で、アニメーションしたいコンポーネントを囲います。
`mode="wait"にすることで、アンマウント時にはアニメーションをさせないようにしています。

```typescript
<AnimatePresence mode="wait">
</AnimatePresence>
```

そして、今回フェードインをさせたいもの(今回だとアイコン)を、`motion.div`で下のように指定します。
`initial`で初期状態(waitさせているのでアンマウント時）の設定をしていて、opacityを0にすることで透明にしています。
`animate`でマウント時の設定を行なっていて、opacityを1にすることで完全にアイコンが見える状態にしています。
`transition`でどのようにanimationをさせるかを指定しています。`duration:0.5`にすることで`initial`から`animate`の状態に移るまでの感覚を0.5sとしています。`delay:0.5`で、マウントされてからどのくらいでアニメーションを遅延させるかを設定していて、0.5sとしています。

:::note
上のコードでは`key`をつけていますがなくても動きます。
調べてみると別コンポーネントで定義する場合はつける必要があるそうです。
:::

```typescript
<motion.div
        initial={{opacity: 0}}
        animate={{opacity: 1}}
        transition={{duration: 0.5, delay: 0.5}}
>
    <Image
        src={`${BASE_PATH}/images/img.png`}
        alt="icon"
        width={500}
        height={500}
    />
</motion.div>
```

# 実装結果
結果こんな感じにフェードインします。

![qiita用.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/e05b3751-787f-c0d0-8b25-ed6076772adf.gif)

ぜひ使って見てください。
SharePoint のファイルを Microsoft Graph API を使用してダウンロードする(C#)　～実装編～

## 1. はじめに

本記事では、SharePointに格納してあるドキュメントを Microsoft Graph API を使用してダウンロードする方法をご紹介します。
最近では、ネットワーク共有フォルダを廃止し、SharePointに移行するといった傾向がみられます。
今回はそんな SharePoint のドキュメントのダウンロードの実装をします。  
なお、 Microsoft Graph API の利用はAzureの登録が必須になるため、実装をする場合は、併せて[こちら](https://qiita.com/Takuma_Kondo/items/3746c67b0b4f01f4e42f)もご確認ください。

また、この記事は以下の続きになります。
よろしければ先にこちらもご確認ください。
[SharePoint のファイルを Microsoft Graph API を使用してダウンロードする　～API理解編～](https://qiita.com/Takuma_Kondo/items/af11257b3e2dcb9d8869)

※なお、本記事の開発言語はC#でデスクトップアプリケーションの開発を目的としております。

## 2. Graph Client Service を使ってAPIを実行

[SharePoint のファイルを Microsoft Graph API を使用してダウンロードする　～API理解編～](https://qiita.com/Takuma_Kondo/items/af11257b3e2dcb9d8869)で
SharePointのファイルをダウンロードする際に使用する以下のAPIを紹介しました。  
今回はこちらのAPIを実行して情報を取得しようと思います。

必要になるのは、 Graph Client Service というライブラリです。  
インストールについては、公式ページにありますので、[こちら](https://learn.microsoft.com/ja-jp/graph/sdks/sdk-installation)からインストールして下さい。

インストールが完了したら、さっそくGraphClientのインスタンスを生成して、APIを実行しようと思います。

### 2.1. GraphClientインスタンスの生成

実は、インスタンスの生成方法はいくつか種類があります。 
もう少し具体的に説明すると、どの認証プロバイダーを選択するかで、インスタンスの生成方法が変わります。
本題ではないのでここは、デスクトップアプリケーションの開発で今回使用する対話型のフローを選択した場合の実装を紹介しておきます。

```C#
var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

// using Azure.Identity;
var options = new InteractiveBrowserCredentialOptions
{
    TenantId = tenantId,
    ClientId = clientId,
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    // MUST be http://localhost or http://localhost:PORT
    // See https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core
    RedirectUri = new Uri("http://localhost"),
};

// https://learn.microsoft.com/dotnet/api/azure.identity.interactivebrowsercredential
var interactiveCredential = new InteractiveBrowserCredential(options);

var graphClient = new GraphServiceClient(interactiveCredential, scopes);
```
上記以外の認証方法については[公式ドキュメント](https://learn.microsoft.com/ja-jp/graph/sdks/choose-authentication-providers?tabs=csharp#interactive-provider)を参照してください。

### 2.2. Graph APIの実行

今回実行するのは、以下のAPI
```
GET /sites/{siteId}/drive/items/{item-id}/content
```

2.1章で生成したインスタンスを使用して、以下のように実行します。  
```C#
await graphClient.Sites["{siteid}"].Items["{itemid}"].GetAsync();
```
これで完了です。

後はレスポンスからダウンロードUrlの値を取得するだけです。
ちなみにこんな感じでダウンロードUrlは取得可能です。  
```C#
   var drive = await AuthenticationInfo.Instance.GraphClient.Sites["{siteId}"].Items["{itemId}"]. GetAsync();
   var downloadUrl = drive.AdditionalData["@microsoft.graph.downloadUrl"].ToString();
```

### 2.3. ファイルのダウンロード

ダウンロードUrlさえ取得してしまえばあとはダウンロードするだけです。
Microsoft Graph APIはもう関係ないので、実装だけ紹介します。
```C#
   var webClient = new WebClient();
   webClient.DownloadFile(downloadUrl, {"ダウンロード先のファイルパス"});
   webClient.Dispose();
```
上記はわかりやすいために、WebClientを使用していますが、HttpClientを使用する方法もあります。


### 3. おわり

今回は、siteIDやitemidを使用して、ファイルのダウンロードを実施しましたが、他のアプローチでもファイルのダウンロードを実施できます。
他の方法については、随時更新していきますので、よろしければご覧ください。
また、Graph Client Serviceを利用せずに、実施するケースも紹介する予定です。
【UE5】UE5でPerforceを使用する際の用語集

# 0. 最初

今回は「Perforce」を使用する際に理解しておくべき用語について解説をします
(以下P4Vとします)

業務中によく使用する順から書きました
経験則から解釈が間違っている場合はコメントにて指摘していただけると助かります


2024/8/4では「文章」のみだけ更新します
これから「画像」や「Gif」等でわかりやすく修正していきます

# CheckOut 
```
自分が編集を行うと宣言し、他人からの編集を防いでいる状態
```
◯手順
 1. 編集したいファイルを右クリック「Check Out」を選択
 2. 右画面の「Pending」に「CheckOut」されたファイルが表示される

# Submit 

```
「CheckOut」したファイルをサーバーへアップロードすること
　成功した時点で「CheckOut」は解除される
```
◯手順
 1. 「CheckOut」したファイルを右クリック
 1. 「Submit」を選択
 1. 変更コメントを入力し「Submig」を選択

# Revert 
```
「CheckOut」を解除し変更差分を破棄すること（他人が編集可能になる）
````
◯手順
1. 「CheckOut」したファイルを右クリック



:::note warn
注意
UEと接続している場合、エディタからも操作は可能だが
クラッシュすることがあるためP4Vから操作を行うことが望ましい
:::

# Get Latest Revision 

```
 サーバーとローカルを比較し最新ファイルとの差分を取得する
```
◯手順
1. 差分を取得したいファイルを右クリック
1. 「Get Latest Revision」を選択

:::note info
 完全に取得できない場合があるので
 Logに「no file updated」と表示されるまで行うのが良い
:::

# ChangeList 

```
1回のサブミット単位として作られるリスト
「CheckOut」したファイルを一覧して表示する場所
```

# Shelve 
```
変更差分をサーバーへ一時的に保存する
Submitとは別なので、本筋には反映されない
```
:::note info
使用ポイント
 ・変更差分を共有したい際に使用する
 ・変更差分をセーブする際に使用する
:::
 
# Unshelve
``` 
「Shelve」したファイルをローカルへダウンロードする
 コピーしてダウンロードされるのでサーバーの「Shelve」は削除されない
```

:::note warn
注意
「Unshelve」したファイルは「CheckOut」になるので注意！
:::

# Force Operation 

```
指定したフォルダをサーバーから強制取得をすること
```
◯手順
 1. 強制取得したいフォルダを選択
 1. 「Get Revision」を選択
 1. 「Force Operation」にチェックをつけた状態で「Get Revision」を選択
 ![スクリーンショット 2024-08-05 000520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918199/20ea7c7a-5f9f-2a98-be09-a0ec676612ec.png)

:::note alert
指定したフォルダをサーバーから強制的に取得を行うので普通は使用しない
:::

# Move to Another ChangeList 
```
「CheckOut」されたファイルを「ChangeList」事を分けること
```
◯手順
1. 「CheckOut」されたファイルを右クリック
1. 「Move to Another ChangeList」を選択
1. 「Changelist description」に「Submit」を行う時のコメントを入力
1. 「OK」を選択
 
# BackOut 
```
「Submit」した「ChangeList」を削除して各ファイルを前の状態に戻すこと
```
◯手順
1. 「History」から取り消したい「ChangeList」を選択
1. 右クリックから「Undo Chnages in Changelist '****'」を選択
1. 「Save to Changelist」を選択
1. 「Pending」から削除したい「Changelist」を「Submit」を行う

:::note info
「History」に「BackOut」した履歴が残る
「BackOut」を「BackOut」を行うと何もしていないことになる
:::
propertyに向かってsetattrする

またpythonの小ネタです。
## 概要
1. クラスのプロパティに`setattr`してもプロパティのsetterは起動する
2. おまけ要素：`__dict__`に書き込んでもプロパティに書き込めない

落ち着いて考えてみれば「そりゃそうだろうな」って話ですがちょっと試します。

## 実験してみる
```python
class PropClass:
    """プロパティvalueを持つクラス"""
    def __init__(self) -> None:
        """プロパティの初期化"""
        self._value = 'no changed.'
    
    @property
    def value(self):
        """ getter プロパティをそのまま返す"""
        return self._value
    
    @value.setter 
    def value(self, v:str) -> None:
        """ setter vを加工してsetする"""
        self._value = f'"{v}"がsetterに渡された'

    def __repr__(self) -> str:
        return f'{self.value}'

if __name__ == '__main__':

    # 普通に代入する
    instance = PropClass()
    instance.value = '普通に代入する'
    print(instance)
    
    # setattrで書き込む
    instance = PropClass()
    setattr(instance, 'value', 'setattrで書き込む')
    print(instance)
```
もちろん出力はこうです。
```
"普通に代入する"がsetterに渡された
"setattrで書き込む"がsetterに渡された
```
そもそもpythonのドキュメントにはこう書いてあります。

> setattr(x, 'foobar', 123) は x.foobar = 123 と等価です。

なので、素直に読めば`instance.value = '文字列'`と`setattr(instance, 'value', '文字列')`は等価です。しかし「プロパティの場合でもそう」とは書いていないので、「本当にそうなのか」と試してみました。結果はそのままドキュメントの通りでした。
実際に使うシーンはあまりないと思いますが、pythonの標準ライブラリの中でも任意に与えたオブジェクトに`setattr`してくるケースはあります。例えば`argparse`なんかがやってきます。 [^action]

その他には、使う機会はあまりないはずですがこんなケースも考えられます。

```python
for k,v in somedict.items():
    setattr(obj, k, v)
```
dictの中身を一方的に`setattr`されるコードなので何を書きこまれるか解ったものではありません。この動作に対して**propertyのsetterによって介入する**ことができます。[^必要な処置]

## おまけの検証 propertyと__dict__
さて、ここまでのテストコードで`setattr`はpropertyのsetterと共存可能だと解りました。
しかし、pythonには他にもpropertyに侵攻できそうな方法があります。そのうちのひとつとして、`instance.__dict__`からアクセスする方法を試しました。
```python
    instance = PropClass()
    instance.__dict__['value'] = 'dictにプロパティ名を指定して書き込む'
    print(instance)
```
出力は`no chabged.`となり、プロパティのsetterも呼ばれません。しかし、`instance.__dict__['value']`には`dictにプロパティ名を指定して書き込む`の値が設定されています。ここは詳しく調べると何故こうなるかわかるはず。なお
元々`__dict__`には書き込むべきではないので、やらないのが無難でしょう。なお書き込み前に`instance.__dict__['value']`を呼び出すと`KeyError`が返ります。プロパティは最初から`__dict__`には含まれていません。


[^必要な処置]: こんな手が必要な設計自体が若干疑問ではありますが、時にはあると思うので知っておいて損はないかなと。
[^action]: しかしargparseには別途Actionクラスの仕組みがあるので、そっちを使った方がいいでしょう。
mysql transaction logの書きかけメモ

ちょっと書いたんだけど、課題と全然違うことしてたことに気づいた。もったいないのでここに残しておく。推敲なしのメモです。英語も書いただけで直してない



## How MySQL Shows Transaction Log 
MySQL does not allow us to see the transaction log directly. However, we can see the summary of transaction status. First, I start a transaction and execute some queries. 

```rb
mysql> START TRANSACTION;
mysql> SELECT * FROM Patients WHERE PatientID = 1;
mysql> UPDATE Patients SET Name = 'Updated User' WHERE PatientID = 1;
```

Before COMMIT, I can see the status of the transaction by the following command:

```rb
mysql> SHOW ENGINE INNODB STATUS \G;
```

The output includes the following lines:

```rb
------------
TRANSACTIONS
------------
Trx id counter 2015
Purge done for trx's n:o < 2009 undo n:o < 0 state: running but idle
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 281480098585592, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
...
...
...
---TRANSACTION 2014, ACTIVE 33 sec
2 lock struct(s), heap size 1128, 1 row lock(s), undo log entries 1
MySQL thread id 17, OS thread handle 6330691584, query id 334 localhost root
Trx read view will not see trx with id >= 2014, sees < 2014
```

```rb
---
LOG
---
Log sequence number          20810214
Log buffer assigned up to    20810214
Log buffer completed up to   20810214
Log written up to            20810214
Log flushed up to            20810214
Added dirty pages up to      20810214
Pages flushed up to          20810214
Last checkpoint at           20810214
Log minimum file id is       6
Log maximum file id is       6
438 log i/o's done, 0.07 log i/o's/second
```

The TRANSACTIONS section indicates a transaction is active and it's holding 2 locks. Since COMMIT has not been executed, the undo log has one entry. The current checkpoint is 20810214 in the LOG section.
Let's close the transaction.

```rb
mysql> COMMIT;
```

After COMMIT, the transaction is closed and the transaction log is written to the disk. Here is the result after COMMIT. The checkpoint is updated to 20810529, and the transaction log is cleared. 

```rb
------------
TRANSACTIONS
------------
Trx id counter 2016
Purge done for trx's n:o < 2016 undo n:o < 0 state: running but idle
History list length 1
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 281480098585592, not started
...
...
...
---TRANSACTION 281480098580048, not started
0 lock struct(s), heap size 1128, 0 row lock(s)


---
LOG
---
Log sequence number          20810529
Log buffer assigned up to    20810529
Log buffer completed up to   20810529
Log written up to            20810529
Log flushed up to            20810529
Added dirty pages up to      20810529
Pages flushed up to          20810529
Last checkpoint at           20810529
Log minimum file id is       6
Log maximum file id is       6
442 log i/o's done, 0.17 log i/o's/second
```

The `Trx id counter` is increased when a transaction is started and increases again when a transaction is closed. This is the Transaction ID that Vidhya et al. mentioned in the text.



ここで気づいた。課題で求められてるのは全然違うことだった
私が0からMacの開発環境を整え得るまで(セットアップ)


今後インターンなどでPCを会社から付与された際に、0からMacの設定をする機会が多くなりそうなので、開発環境を整える手順をまとめておきます。


## Homebrew関連

https://brew.sh/ja/

Homebrew経由でインストールをするとデフォルトでパスが通るのでなるべくHomebrewを使っています。
公式に従って以下を実施します。


1. Homebrewのインストール

2. Homebrewのパスを通す

3. Homebrewからアプリをインストール

私はgit、bat、eza、iterm2、tmux、cmake、make、gcc、postgresql、table plus、vs code、chrome、slack、notion、docker desktopをインストールします

※ 最後に`brew list`で入っているパッケージを確認すると安心です


## 設定ファイル関連

1. 設定ファイルの設置

自分が使いやすいように設定ファイルを設置してカスタマイズします。以下は私が普段使っている設定ファイルをまとめたリポジトリです。設定ファイルは使いまわすことが多いと思うのでgitで管理するのはおすすめです。

https://github.com/taiyo2001/config-repo

2. Gitの補完を有効にする

以下の記事を参考にして下さい。

https://qiita.com/Ping/items/234b8974bdf2a5e618a5


## バージョン管理ツールのインストール

私はasdfを使っているので環境に合わせて入れていきます。

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

asdfをHomebrewからインストールしても良いですが、公式に以下のように記載されているので、私はgitから入れてます。

> 理由がない限り、gitコマンドを使用した公式ダウンロードの手順を使用することを強く推奨します。

https://asdf-vm.com/ja-jp/guide/getting-started.html#%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3%E3%81%8B%E3%82%99%E3%82%B5%E3%83%9B%E3%82%9A%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B%E3%82%BF%E3%82%99%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%88%E3%82%99%E6%96%B9%E6%B3%95


## Macの設定

システム設定で最低限、以下をポチポチして変更してきます。

* デフォルトのブラウザを変更
* 起動アプリの設定
* 通知アプリの設定
* Finderの設定(拡張子やサイドバーを変更)


## 最後に

他にも余裕があれば、インフラ関係(azure-cli、awscli、awsume)、postman、Clipy、Rectangle、RunCatあたりを入れてみるのがいいと思います。
【ワンライナー】CPUのコア数分、空のループを回してCPUを100%にしたい、メモ

# はじめに

Macbookで `CPU使用率` を `100%` にしたいなぁ

Macbookの消費電力を多くして、アダプタの電圧の上限を知りたいなぁ

ということから、CPUのコア数分、空のループを回してCPUを100%にしたい、メモ

# 環境

bash

# CPUのコア数分、空のループを回す

`for i in $(seq 1 $(nproc)); do (while : ; do : ; done) & done`

:::note info
`for i in $(seq 1 $(nproc)); do (yes > /dev/null) & done`

とかでもできるけど、 `yes > /dev/null` より `while : ; do : ; done` のほうが消費電力が大きかったので採用
:::

# とめかた

`kill $(jobs -p)`

:::note warn
jobs -p でプロセスIDのみが取れない場合は、`kill $(jobs -p | awk '{print $2}')` とかすればいい
それか、`fg` して `ctrl+c` を繰り返すとか
:::

# さいごに

かんたんでしたね

# 参考リンク

- [ubuntu manuals 24.04 | nproc](https://manpages.ubuntu.com/manpages/noble/ja/man1/nproc.1.html)
- [ubuntu manuals 24.04 | jobs](https://manpages.ubuntu.com/manpages/noble/en/man1/jobs.1posix.html)
AtCoder 勉強記録[C++] その41

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

int main() {
  ll h, w;
  cin >> h >> w;
  vector<string> c(h);
  rep(i, h) cin >> c[i];
  vector<ll> x(w);
  for(int i = 0; i < w; i++){
    for(int j = 0; j < h; j++){
      if(c[j][i] == '#') x[i]++;
    }
    cout << x[i] << " ";
  }
}
```
### 解法
グリッドの横軸を固定して縦方向に探索を行うことで結果が求まる。
【学習記録　2024-08-04】

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

## 学習内容
### 学習時間：3h
- #を使用したプライベートなプロパティ
- クラスの継承方法
- super.の仕組み
- コンポジションと継承の違い
- instanceof演算子とisPrototypeOf()を使用した比較方法。

## 所感
　Javaと似た部分があったためなんとなく概要は理解できましたが、動作原理を理解するのは大変でした(泣)
　特にクラス継承時のsuperがかなり複雑だったので繰り返し学習したいと思います！
言語処理100本ノック 第3章 解いてみた

# はじめに
* No.20でいきなり手が止まりました
* 何とか最後まで解いたものの、No.25がだいぶ怪しいです  
必要以上に情報を削ってしまっている気がするので、後で解きなおします
* 名前しか聞いたことのなかったpandasを初めて使いました
* 次章以降も頑張ります

# 20. JSONデータの読み込み
```python
import pandas as pd

df = pd.read_json(f"{dirpath}/jawiki-country.json.gz", lines=True)
uk_data = df[df.title == 'イギリス']
uk_text = uk_data['text'].values[0]
print(uk_text)
```

# 21. カテゴリ名を含む行を抽出
```python
import re

pattern = "\[\[Category:.*"
categories = re.findall(pattern, uk_text)
for line in categories:
  print(line)
```

# 22. カテゴリ名の抽出
```python
pattern = "\[\[Category:(.*)\]\]"
categories = re.findall(pattern, uk_text)
for category in categories:
  print(category.replace("|*", ""))
```

# 23. セクション構造
```python
pattern = "={2,}.*={2,}"
sections = re.findall(pattern, uk_text)
for section in sections:
  count = 0
  for c in section:
    if c == "=":
      count += 1
  print(f"レベル：{(count - 2) // 2} {section.replace('=', '')}")
```

# 24. ファイル参照の抽出
```python
pattern = "\[\[ファイル:(.*?)\|"
media_files = re.findall(pattern, uk_text)
for media_file in media_files:
  print(media_file)
```

# 25. テンプレートの抽出
```python
pattern = "\|(.*?) = (.*)"
info_list = re.findall(pattern, uk_text)
info_dict = {}
for info in info_list:
  info_dict[info[0]] = info[1]
print(info_dict)
```

# 26. 強調マークアップの除去
```python
pattern = "\|(.*?) = (.*)"
info_list = re.findall(pattern, uk_text)
info_dict = {}
for info in info_list:
  info_dict[info[0]] = re.sub("'{2,5}", "", info[1])
print(info_dict)
```

# 27. 内部リンクの除去
```python
pattern = "\|(.*?) = (.*)"
info_list = re.findall(pattern, uk_text)
info_dict = {}
for info in info_list:
  txt = re.sub("'{2,5}", "", info[1])
  if re.search("\[\[(?!ファイル)(.*?)\]\]", txt):
    txt = re.sub("\[\[(?!ファイル)(.*?)\]\]", "\\1", txt)
  info_dict[info[0]] = txt
print(info_dict)
```

# 28. MediaWikiマークアップの除去
```python
pattern = "\|(.*?) = (.*)"
info_list = re.findall(pattern, uk_text)
info_dict = {}
for info in info_list:
  txt = re.sub("'{2,5}", "", info[1])
  if re.search("\[\[(?!ファイル)(.*?)\]\]", txt):
    txt = re.sub("\[\[(?!ファイル)(.*?)\]\]", "\\1", txt)

  txt = re.sub("\{\{.*?\}\}", "", txt)
  txt = re.sub("<.*?>.*?<.*?>", "", txt)
  txt = re.sub("<.*?>", "", txt)
  txt = re.sub("\[\[ファイル:.*?\]\]", "", txt)

  info_dict[info[0]] = txt

for k in info_dict.keys():
  print(k, " : ", info_dict.get(k))
```

# 29. 国旗画像のURLを取得する
```python
import requests

session = requests.Session()

url = "https://ja.wikipedia.org/w/api.php"

image_name = info_dict.get("国旗画像")

params = {
    "action": "query",
    "format": "json",
    "prop": "imageinfo",
    "titles": "File:" + image_name,
    "iiprop": "url"
}

response_json = session.get(url=url, params=params).json()
image_url = response_json["query"]["pages"]["-1"]["imageinfo"][0]["url"]

print(image_url)
```
【react native Redux 簡単デバック】`redux-devtools-expo-dev-plugin` 導入方法 in Expo 50

# はじめに
今回は、react nativeでReduxを使ううえで簡単にデバック可能な`redux-devtools-expo-dev-plugin`の紹介と導入手順を紹介していきます。

## どんなことができるのか
`redux-devtools-expo-dev-plugin`を使用すると、存在するstoreの状態とその変化を確認できたり(下記画像参照)
![スクリーンショット 2024-08-04 22.42.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/1d1deb69-28ce-e067-9806-d958fe629a20.png)

rtk Queryを使用したweb APIリクエストのレスポンス、リクエストの詳細などを確認することができます。
![スクリーンショット 2024-08-04 22.46.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/e612380e-b186-4d7e-2b7f-5e43d22725e8.png)

storeをいじった際にいちいち`console.log`で確認する、といった手間がないので、非常に便利なデバックツールです。

## 導入手順
今回はRedux toolkitが導入されている前提で進めていきます。

### 1. パッケージのインストール
`redux-devtools-expo-dev-plugin`をプロジェクトにインストールします。

```bash
npm install redux-devtools-expo-dev-plugin

// yarn を使用する場合は↓
yarn add redux-devtools-expo-dev-plugin
```

###  `configureStore`に設定する
`configureStore`に、`redux-devtools-expo-dev-plugin`を使用するための`enhancers`を追記します。

```ts
export const store = configureStore({
  // 省略
  enhancers: (getDefaultEnhancers) =>
    getDefaultEnhancers().concat(devToolsEnhancer()),
});
```

もし、型エラーが出てしまう場合は`// @ts-ignore`を一つ上の行に追記してみてください。

### Expoアプリを立ち上げ、Dev toolsを選択
![RJjPSnpfCqDta0V1722779849_1722779866.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/77ccc5a5-31bb-3cfb-ec59-61c41601ba86.png)

いつものこの画面が表示されたら、`shiftz + m`を押下します。

選択肢の中に`Open devtools plugin - redux-devtools-expo-dev-plugin`があったら導入は成功です！ 矢印キーでカーソルを合わせて起動します。

![スクリーンショット 2024-08-04 23.00.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/c726efd7-8dc5-f8f5-6200-d43e81bb9ba2.png)

![スクリーンショット 2024-08-04 23.01.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/d25f9dc6-9594-c15d-f16b-53575034dfbb.png)

この画面が表示されれば、あとはデバックしていくだけになります。お疲れ様でした！

### おわりに
redux-devtools-expo-dev-plugi もとい react native、まだまだ慣れないことは多いですがなかなか便利なもんですね。
また、便利なことや情報が少ないことにかんして記事にしていけたらいいなと思います...
javaScriptとtypeScriptのcomponentsの書き方

# TypeScriptのcomponentsの書き方

JavaScriptでは型定義がない。

このため、通常はJSDocコメントを使用して型情報を提供するか、動的型付けのまま進行

今回は動的型付けのまま進行

```jsx
export const IncompleteTodos = () => {
  const  [todos, onClickComplete, onCLickDelete] = props
```

`type` キーワードを使ってプロパティの型を定義

```tsx
type IncompleteTodosProps = {
  todos: string[];
  onClickComplete: (index: number) => void;
  onClickDelete: (index: number) => void;
};

```

型注釈がないため、動的型付けのまま進行

```jsx
export const IncompleteTodos = (props) => {
```

`IncompleteTodos`コンポーネントが`IncompleteTodosProps`型のプロパティを受け取るのを指定

`React.FC<IncompleteTodosProps>`は、`IncompleteTodosProps`型を持つReact関数コンポーネントを定義

参考動画
[最新ver対応済】モダンJavaScriptの基礎から始める挫折しないためのReact入門](https://www.udemy.com/course/modern_javascipt_react_beginner/?couponCode=KEEPLEARNING)
FactoryBotの基本的な使い方

# はじめに

こんにちは！
社会人一年目の石川です。
記事をご覧いただきありがとうございます。

現在、私はRSpecを使ってモデルのテストコードを書いています。その際にFactoryBotを活用しているため使い方をまとめます。

## 目次
1. [FactoryBotとは？](#factorybotとは)
1. [Gemfileの設定](#gemfileの設定)
3. [FactoryBotの設定](#factorybotの設定)
3. [基本メソッドの使用](#基本メソッドの使用)
・[buildメソッド](#buildメソッド)
・[createメソッド](#createメソッド)
3. [モデルのテストコード](#モデルのテストコード)
4. [最後に](#最後に)

## FactoryBotとは？
FactoryBotは、テスト用のデータを簡単に作成するためのライブラリです。テストケースごとにデータを手動で作成するのは面倒ですが、FactoryBotを使うことで、再利用可能なテンプレートを使って効率的にデータを生成できます。

:::note info
#### メリット
・テストデータを簡単に生成でき、コードが簡潔に保たれる。
・デフォルト属性を設定し、必要に応じてカスタマイズ可能。
・データ生成方法が統一され、テストの整合性が保たれる。
・可読性が向上する。
:::


## Gemfileの設定
まず、GemfileにFactoryBotとRSpecを追加します。これにより、テスト環境でこれらのライブラリが利用可能になります。

```
group :development, :test do
  gem 'rspec-rails'     # RSpecをRailsプロジェクトで使えるようにする
  gem 'factory_bot_rails' # FactoryBotをRailsプロジェクトで使えるようにする
end
```
設定後、ターミナルで```bundle install```を実行して、これらのgemをインストールします。


## FactoryBotの設定
FactoryBotを使うためには、テスト用のファクトリファイルを設定する必要があります。ファクトリファイルは、テストで使用するデータのテンプレートを定義します。

#### ファクトリファイルの作成
```spec/factories```ディレクトリにファイルを作成します。例えば、ユーザーモデルのファクトリファイルを ```spec/factories/users.rb```とします。

```
FactoryBot.define do
  factory :user do
    # デフォルトの属性値を定義
    nickname { "TEST" }
    email { "test@example.com" }
  end
end
```

#### FactoryBotの記法の省略

```rails_helper.rb```に設定を追加することで、FactoryBotのメソッドを簡単に使えるようにします。

```
RSpec.configure do |config|
  # FactoryBotのメソッドを直接使えるようにする設定
  config.include FactoryBot::Syntax::Methods
end
```

この設定により、```FactoryBot.create(:user)```を単に ```create(:user)```と書けるようになります。

## 基本メソッドの使用
### buildメソッド
build メソッドを使うと、指定したファクトリに基づいたオブジェクトを生成しますが、データベースには保存されません。

```
# factory_botを利用しない場合
user = User.new(nickname: "TEST", email: "test@example.com")

# factory_botを利用する場合
user = build(:user)
```

### createメソッド
create メソッドを使うと、ファクトリに基づいたオブジェクトを生成し、データベースにも保存します。テスト後にデータベースの内容はロールバックされるので、テストが終了するごとに状態がクリーンに保たれます。
```
user = create(:user)
```

## モデルのテストコード
FactoryBotを使って、モデルのテストを簡単に書くことができます。以下に、Userモデルのテストコードの例を示します。

```spec/models/user_spec.rb```というファイルを作成し、以下のように記述します。
```
  describe '#create' do
    context 'when nickname is empty' do
      it "should be invalid" do
        # nicknameを空にしてユーザーを生成
        user = build(:user, nickname: '')
        expect(user).not_to be_valid
        
        # nicknameが空の場合にエラーメッセージが含まれていることを確認
        expect(user.errors[:nickname]).to include("が入力されていません。")
      end
    end
  end
end


```
build(:user, nickname: '') で、nickname が空のユーザーインスタンスを生成します。
nickname が空の場合にエラーメッセージが正しく表示されることを確認します。


## 最後に

最後まで読んでいただきありがとうございました。
この記事を読んでFactoryBotの基本的な使い方の理解が少しでも深まれば幸いです。