OmniAICreator/Qiita-1.07M huggingface dataset:
Apexのガバナー制限

Apexは、Salesforceプラットフォーム上で動作するサーバーサイドプログラミング言語であり、Salesforceデータと操作を自動化するために使用されます。Apexには多くの制限（ガバナ制限）があり、これらの制限は、プラットフォームのパフォーマンスを保護し、他のユーザーに悪影響を与えないようにするために設けられています。

以下に、いくつかのApex制限と、それぞれの制限がどのような影響を与えるかを具体的な例を使って説明します。

### 1. **SOQLクエリの制限**
   **制限**: 1回のトランザクションで実行できるSOQLクエリの数は、最大100件までです。

   **例**: 
   ```apex
   public void myMethod() {
       for (Integer i = 0; i < 150; i++) {
           List<Account> accounts = [SELECT Id, Name FROM Account WHERE Name LIKE 'Test%'];
           // ここで、他の処理を実行
       }
   }
   ```
   このコードは、SOQLクエリを150回実行しようとしていますが、Apexでは1回のトランザクションで100回以上のSOQLクエリを実行することができないため、ガバナ制限を超えてエラーになります。

   **解決策**:
   クエリをループの外に移動し、リストを使ってバッチで処理します。
   ```apex
   public void myMethod() {
       List<Account> accounts = [SELECT Id, Name FROM Account WHERE Name LIKE 'Test%'];
       for (Account acc : accounts) {
           // ここで、他の処理を実行
       }
   }
   ```
   これにより、クエリは1回だけ実行され、制限を超えることはありません。

### 2. **DML操作の制限**
   **制限**: 1回のトランザクションで実行できるDMLステートメントの数は、最大150件までです。

   **例**:
   ```apex
   public void myMethod() {
       for (Integer i = 0; i < 200; i++) {
           Account acc = new Account(Name='Test' + i);
           insert acc;
       }
   }
   ```
   このコードは、200回のDML操作を実行しようとしますが、150回の制限を超えているため、エラーになります。

   **解決策**:
   バッチインサートを使用して、複数のレコードを一度に挿入します。
   ```apex
   public void myMethod() {
       List<Account> accounts = new List<Account>();
       for (Integer i = 0; i < 200; i++) {
           accounts.add(new Account(Name='Test' + i));
       }
       insert accounts;
   }
   ```
   これにより、DMLステートメントの回数を1回に減らすことができ、制限を超えません。

### 3. **CPU時間の制限**
   **制限**: 1回のトランザクションで使用できるCPU時間は、最大10秒（同期トランザクションの場合）です。

   **例**:
   ```apex
   public void myMethod() {
       Long sum = 0;
       for (Long i = 0; i < 1000000000; i++) {
           sum += i;
       }
   }
   ```
   このループは大量のCPU時間を消費し、10秒の制限を超えてしまう可能性があります。

   **解決策**:
   ロジックを最適化するか、バッチApexを使用して処理を分割します。
   ```apex
   public void myMethod() {
       Long sum = 0;
       for (Long i = 0; i < 1000000; i++) {
           sum += i;
       }
   }
   ```
   ループの範囲を小さくするか、バッチApexで大規模な処理を分割します。

### 4. **コレクションの制限**
   **制限**: リスト、セット、マップに保存できる項目の最大数は、50,000件です。

   **例**:
   ```apex
   public void myMethod() {
       List<Account> accounts = new List<Account>();
       for (Integer i = 0; i < 60000; i++) {
           accounts.add(new Account(Name='Test' + i));
       }
   }
   ```
   60,000件の項目をリストに追加しようとしており、50,000件の制限を超えています。

   **解決策**:
   コレクションのサイズを縮小し、必要な項目だけを保持するようにするか、必要に応じて処理を分割します。
   ```apex
   public void myMethod() {
       List<Account> accounts = new List<Account>();
       for (Integer i = 0; i < 50000; i++) {
           accounts.add(new Account(Name='Test' + i));
       }
   }
   ```
   制限内で動作するように項目の数を調整します。

### まとめ

Apexでは、Salesforceのプラットフォームのリソースを公平に使用し、システムの安定性を確保するために、さまざまなガバナ制限が設けられています。これらの制限を理解し、適切にコーディングすることで、エラーを回避し、パフォーマンスを最適化することができます。

従来の開発は、プロジェクトのデータ量によって、パフォーマンスに触ることが少ないかもしれません。
SaaSのサービスを使うと、実感しました。エンドユーザーの体験など、常にパフォーマンスを頭に入れて開発しましょう。
【CSS】data属性を擬似要素で指定する方法


CSSの擬似要素でHTMLのdata属性が指定できる！

```
<ul>
    <li data-count="1">hoge</li>
    <li data-count="2">hoge</li>
    <li data-count="3">hoge</li>
</ul>
```

```
ul li::before {
    content: attr(data-count);
}
```
私の資格勉強法

システムエンジニア 4 年目になり、これまでいくつかの資格を取得してきたで、その勉強方法を整理しました。

この記事で紹介する勉強方法は私の個人の経験に基づいた私が良いと考えるものです。1 つの例として読んでください。

## 対象読者

システムエンジニア 1, 2 年目くらいでこれから資格勉強をしようと思っている方。

## 著者について

以下の資格を取得済みです。

- IPA
  - 基本情報
  - 応用情報
- AWS
  - SAA
  - DVA
  - SOA
  - SAP
- Azure
  - AZ-900
  - AZ-104

## 勉強法

ここから本題です。  
著者が現在資格取得に向けて勉強中のデータベーススペシャリストを具体例として、勉強法をご紹介します。

勉強の流れは以下の通りです。

1. 試験概要の確認
2. 合格体験談を読む
3. 勉強計画を立てる
4. 勉強計画の実行

それぞれ詳しく解説します。

### 試験概要の確認

まずは公式サイトで出題内容、出題形式（選択 or 記述）、試験日程、免除の有無などを確認します。

データベーススペシャリストの場合は、[IPA の公式サイト](https://www.ipa.go.jp/shiken/kubun/db.html)で確認します。  
IPA の高度試験では、午前 Ⅰ を免除できる場合があるので対象の人は忘れずに申し込みましょう。また、試験申し込みが 2, 3 ヶ月前に締め切られるので注意してください。

### 合格体験談を読む

次に Qiita などで合格体験談の記事を読み、参考になる教材や勉強計画、試験当日についての情報を収集します。

ここで注意したいのは、最近執筆された記事を読むことです。特に AWS 資格などは試験内容に変更があるため、自分が受験する試験と同じバージョンの体験談を読んでください。

データベーススペシャリストの場合は、合格体験談の記事を 3, 4 つほど読みました。

### 勉強計画を立てる

情報収集ができたら受験までのざっくりとした勉強計画を立てます。

10 月のデータベーススペシャリスト受験に向けた私の勉強計画は以下の通りです。

| 月   | 平日にやること(30 分程度)                     | 土日にやること(2 時間程度)                    |
| ---- | --------------------------------------------- | --------------------------------------------- |
| 7 月 | データベーススペシャリスト対策の Udemy を受講 | データベーススペシャリスト対策の Udemy を受講 |
| 8 月 | 午前 Ⅱ の過去問を解く                         | 午後 Ⅰ の過去問を解く                         |
| 9 月 | 午前 Ⅰ と午前 Ⅱ の過去問を解く                | 午後 Ⅱ の過去問を解く                         |

月ごとに平日と土日にやることを決めます。  
ポイントは平日と土日でやることを分けることと、バッファを設けた現実的な計画を立てることです。

私は社会人 1 年目の頃、平日も 1, 2 時間程度勉強する計画を立てていましたが、日中の業務の疲れでそこまで勉強できなかったです。  
なので余裕のある計画を立てて、受験日までに間に合わないと感じたら受験日を変更することを考えるべきです。

### 勉強計画の実行

計画を立てたらあとは実行するだけです。  
ここでお伝えしたいポイントは 3 つあります。

#### とにかく過去問を解く

資格勉強では多くの過去問を解くことが合格への近道です。  
本や Udemy でのインプットよりも、問題を解くアウトプットに時間をかけた方が効率的です。

選択式の問題では、過去問と同じ問題や似た問題が出題されやすいので効果的です。  
また、試験によっては読解力を必要とする文章問題があります。この場合もとにかく過去問を解いて問題に慣れましょう。

#### 間違えた問題は深掘り

過去問を解いて間違えた問題は解説を読んで、解けなかった理由を明らかにします。

解けなかった理由は「知識が足りなかったから」か、「問題をよく読んでいなかった」のどちらかになることが多いです。

足りなかった知識に関しては教材を読んだり調べたりして理解し、同じようなことを聞かれても答えられるようにします。  
ここで大事なのは、同じ問題を解けるようにすることではなく、「同じことを聞かれている別の問題」も解けるようになるということです。

#### 単語帳をつくるのは非効率(個人の見解です)

私は以前間違えた問題を単語帳にまとめていましたが、これは非効率でした。  
単語帳自体を作ることに時間がかかるし、ただの丸暗記なので応用が効かないというデメリットがあります。  
単語帳を作る時間があったら 1 問でも多くの過去問を解く方が良いです。

## 余談

資格勉強法の記事を読むのが好きなので、自分の勉強法も書いてみました。  
ぐだぐだ書きましたがこの記事で言いたいことは「ひたすら過去問を解いて理解するまで解説を読む」です。
【Next.js】状態管理ライブラリについて


# Next.jsにおいての状態管理
Next.jsでの状態管理は大きくわけて２つ。
useStateを利用するローカルな状態管理とグローバルな状態管理。

useStateはコンポーネント単位で状態を管理してコンポーネントが破棄されると管理していたStateもすべてクリアされる。

一方でグローバルな状態管理はアプリ全体で状態を管理するためコンポーネントに依存しない。
ユーザーのログイン情報などアプリで共有したい情報を扱う時に使う。


グローバルな状態管理で有名なライブラリはRedux。
他にも下記のようなライブラリがある。

- Recoil
- Zustand
- Jotai
- Valtio
- Nano stores
- Hookstate
- Elf
- Rematch

https://npmtrends.com/jotai-vs-mobx-vs-nanostores-vs-recoil-vs-redux-vs-valtio-vs-zustand
ZIPファイルをまとめて展開するPowerShell - How to Automatically Extract ZIP Files Using PowerShell

# How to Automatically Extract ZIP Files Using PowerShell

PowerShell is a very useful tool for automating tasks in a Windows environment. In this article, we'll explore how to use PowerShell to automatically extract multiple ZIP files stored in a specific directory to another directory.

# Overview of the Script

This script automates the process of retrieving all the ZIP files from a specified directory and extracting each one into a destination directory. The destination directory name is derived from the ZIP file name, excluding the extension.

# Script Details

```powershell
# Path to the directory where ZIP files are stored
$sourceDirectory = "c:/work1"

# Path to the parent directory where files will be extracted
$destinationRoot = "c:/work2"

# Get all ZIP files
$zipFiles = Get-ChildItem -Path $sourceDirectory -Filter *.zip

# Loop through each ZIP file and extract it
foreach ($zipFile in $zipFiles) {
    # Determine the extraction directory name by removing the extension from the ZIP file name
    $folderName = [System.IO.Path]::GetFileNameWithoutExtension($zipFile.Name)
    $destinationFolder = Join-Path -Path $destinationRoot -ChildPath $folderName

    # Create the extraction directory if it doesn't exist
    if (-not (Test-Path -Path $destinationFolder)) {
        New-Item -Path $destinationFolder -ItemType Directory
    }

    # Extract the ZIP file
    Expand-Archive -Path $zipFile.FullName -DestinationPath $destinationFolder -Force
}
```
# Explanation of Each Step

## Specify the Directory Containing the ZIP Files:

The script processes all the ZIP files located in the path c:/work1. This path is stored in the $sourceDirectory variable.

## Specify the Destination Directory:

The extracted files will be saved in the parent directory set to c:/work2, stored in the $destinationRoot variable.

## Retrieve ZIP Files:

The Get-ChildItem cmdlet is used to get all ZIP files in the specified directory.

## Extraction Process:

The script loops through each retrieved ZIP file using a foreach loop.

- The extraction directory name is determined by removing the extension from the ZIP file name.
- If the specified extraction path does not exist, a new directory is created.
- Finally, the Expand-Archive cmdlet is used to extract the ZIP file into the specified directory.

# Conclusion

By using this script, you can save time and effort by avoiding the manual extraction of multiple ZIP files. PowerShell makes task automation easy, helping to improve work efficiency. Give this script a try and see how it can benefit your workflow.


---

以上.
[備忘録 その１７] Java Silver ～モジュールシステム～

# モジュールシステム
コードをモジュールという単位で構成し、管理するための仕組みです。モジュールシステムは、大規模なアプリケーションの開発やライブラリの再利用を容易にし、依存関係の管理を強化することを目的としています。
## 1\.モジュールシステムの基本概念
#### モジュール
モジュールは、クラスやパッケージをグループ化し、明確に定義された境界を持つ単位です。各モジュールは、他のモジュールに対して何を公開するか(エクスポートするか)を指定できるため、アクセス制御が可能です。
__module-info.java__
モジュールシステムの中心にあるのが、__module-info.java__ というモジュール定義ファイルです。このファイルは、モジュールの名前、依存関係、およびエクスポートされるパッケージを定義します。__module-info.java__ はモジュールのルートに配置されます。
## 2\.module-info.javaの構造
module-info.javaの基本構造は次の通りです。
```java
module com.example.module {
    // このモジュールが依存する他のモジュール
    requires java.base;
    requires com.example.othermodule;

    // このモジュールから外部に公開するパッケージ
    exports com.example.module.api;

    // 特定のモジュールに対してのみ公開するパッケージ
    exports com.example.module.internal to com.example.specificmodule;

    // サービスを提供するモジュール
    provides com.example.service.MyService with com.example.module.MyServiceImpl;

    // サービスを使用するモジュール
    uses com.example.service.MyService;
}
```
#### 主なキーワード
* __module：__ モジュールの名前を定義します。

* __requires：__ このモジュールが依存する他のモジュールを指定します。requires transitiveを使うと、そのモジュールをいぞんするモジュールに再エクスポートします。

* __exports：__ モジュールの外部に公開するパッケージを指定します。これにより、他のモジュールがそのパッケージにアクセスできるようになります。

* __exports ... to：__ 特定のモジュールにのみパッケージを公開するために使用します。

* __provides ... with：__ サービスを提供するクラスを指定します。Javaのサービスプロバイダインタフェースを使う場合に使用します。

* __uses：__ サービスを使用することを宣言します。

## 3\.モジュールシステムのメリット
#### 依存関係の明確化
モジュールシステムにより、依存関係が明確に定義され、どのモジュールがどの機能に依存しているかが簡単に追跡できます。これにより、モジュール間の結合度を下げ、システム全体の構造がわかりやすくなります。
#### 強化されたカプセル化
パッケージをモジュールごとにエクスポートすることで、不要な部分を隠蔽し、外部からの不正アクセスを防止します。これにより。内部実装が外部に影響を与えにくくなります。
#### 依存性の解決とコンパイルの高速化
モジュールシステムを使用すると、コンパイル時に必要なモジュールだけをコンパイルすることができるため、ビルド時間が短縮されます。また、ランタイム時に不要なモジュールがロードされないため。メモリ消費を抑えることができます。

## 4\.モジュールシステムの使用例
#### 基本的なモジュール定義
次に示すのは、基本的なモジュール定義の例です。

##### モジュールA: module-info.java
```java
module com.example.moduleA {
    requires java.sql;
    exports com.example.moduleA.api;
}

```

##### モジュールB: module-info.java
```java
module com.example.moduleB {
    requires com.example.moduleA;
    exports com.example.moduleB.api;
}

```
この例では、moduleAはjava.sqlに依存しており、moduleBはmoduleAに依存しています。moduleAはcom.example.moduleA.apiパッケージを公開しており、moduleBはcom.example.moduleB.apiパッケージを公開しています。



最初のページ
[[備忘録 その１] Java Silver ～Javaプログラミング基礎～](https://qiita.com/MagicShowTime/items/9fcf3a2cb4a7162aafcf "[備忘録 その１] Java Silver ～Javaプログラミング基礎～")

前のページ
[[備忘録 その１６] Java Silver ～例外～](https://qiita.com/MagicShowTime/items/ec5beac17041b7fa47e9 "[備忘録 その１６] Java Silver ～例外～")
JavaScript HTTPリクエスト GET/POST

## GETリクエストを使い、テキストデータを取得する
JavaScriptを使い、HTTP通信によって、テキストデータを通信先から取得する。

### GETコード
```js
function fetchUserInfo() {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "http://127.0.0.1:8080/page.html");
    xhr.send();
    xhr.responseType = "text";
    xhr.onload = () => {
        if (xhr.readyState == 4 && xhr.status == 200) {
            console.log(xhr);
            const data = xhr.response;
            console.log(data);
        } else {
            console.log(`Error: ${xhr.status}`);
        }
    };
}
```

### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850581/d10e2690-2cfb-e4e3-0c0f-65249d5357de.png)


※responseTypeを対応した値に指定しないとエラーが発生する。
　GETではなく、POSTになると実装が変わる。

### POSTコード
```js
function HttpPostRequest() {
    let txt_name = document.getElementById('name');
    let txt_age = document.getElementById('age');
    let txt_email = document.getElementById('email');

    const xhr = new XMLHttpRequest();
    xhr.open("POST", "http://127.0.0.1:8081/");
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    const body = JSON.stringify({
        name: txt_name.value,
        age: txt_age.value,
        email: txt_email.value,
    });
    xhr.onload = () => {
    if (xhr.readyState == 4 && xhr.status == 201) {
        console.log(JSON.parse(xhr.responseText));
    } else {
        console.log(`Error: ${xhr.status}`);
    }
    };
    xhr.send(body);
}
```

### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850581/929885f9-dab9-4a39-cec1-050a8db5047d.png)

```
C:\work\開発\test_javascript>py tcp_server.py
host:127.0.0.1 port:8081
Waiting for connection
Established connection
b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nContent-Length: 40\r\nsec-ch-ua: "Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"\r\nContent-Type: application/x-www-form-urlencoded\r\nsec-ch-ua-mobile: ?0\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36\r\nsec-ch-ua-platform: "Windows"\r\nAccept: */*\r\nOrigin: http://127.0.0.1:8080\r\nSec-Fetch-Site: same-site\r\nSec-Fetch-Mode: cors\r\nSec-Fetch-Dest: empty\r\nReferer: http://127.0.0.1:8080/\r\nAccept-Encoding: gzip, deflate, br, zstd\r\nAccept-Language: ja,en-US;q=0.9,en;q=0.8\r\n\r\n{"name":"aaa","age":"bbb","email":"ccc"}'
```

送信/受信もできているが、サーバからクライアントに返信できていないようみ見える。

## 参考

https://kinsta.com/jp/knowledgebase/javascript-http-request/

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
SQLファイル編集ようVBSサンプル

Option Explicit

Const FOLDER_PATH = "C:\a"
Const STRING_TO_REMOVE = "AAA"  ' 削除する特定の文字列
Const CUTOFF_STRING = "BBB"    ' この文字列以降を削除

Dim fso, folder, file, content, newContent, filesProcessed
Set fso = CreateObject("Scripting.FileSystemObject")

' フォルダが存在するか確認
If Not fso.FolderExists(FOLDER_PATH) Then
    WScript.Echo "指定されたフォルダが存在しません: " & FOLDER_PATH
    WScript.Quit 1
End If

Set folder = fso.GetFolder(FOLDER_PATH)
filesProcessed = 0

' SQLファイルを処理
For Each file In folder.Files
    If LCase(fso.GetExtensionName(file.Name)) = "sql" Then
        ' ファイルの内容を読み込む
        content = ReadFile(file.Path)
        
        ' 特定の文字列を削除
        newContent = Replace(content, STRING_TO_REMOVE, "")
        
        ' CUTOFF_STRING以降の記述を削除
        Dim pos
        pos = InStr(1, newContent, CUTOFF_STRING, vbTextCompare)
        If pos > 0 Then
            newContent = Left(newContent, pos - 1)
        End If
        
        ' 内容が変更された場合のみファイルを更新
        If StrComp(content, newContent, vbBinaryCompare) <> 0 Then
            WriteFile file.Path, newContent
            filesProcessed = filesProcessed + 1
            WScript.Echo "処理済み: " & file.Name
        End If
    End If
Next

WScript.Echo filesProcessed & " 個のSQLファイルの処理が完了しました。"

' ファイルの内容を読み込む関数
Function ReadFile(filePath)
    Dim objFile, content
    On Error Resume Next
    Set objFile = fso.OpenTextFile(filePath, 1)
    If Err.Number <> 0 Then
        WScript.Echo "エラー: ファイルを読み込めません - " & filePath
        WScript.Quit 1
    End If
    On Error Goto 0
    
    content = objFile.ReadAll
    objFile.Close
    ReadFile = content
End Function

' ファイルに内容を書き込む関数
Sub WriteFile(filePath, content)
    Dim objFile
    On Error Resume Next
    Set objFile = fso.OpenTextFile(filePath, 2, True)
    If Err.Number <> 0 Then
        WScript.Echo "エラー: ファイルに書き込めません - " & filePath
        WScript.Quit 1
    End If
    On Error Goto 0
    
    objFile.Write content
    objFile.Close
End Sub
【Unity】RawImageをクロマキーする便利ツールを作った。

# 経緯
RawImageをクロマキーする必要があったので作った。
CameraのSolid Colorも変更出来る便利機能付き。

# 開発環境
Windows 10
Unity 2022 3.22f1
URP

# 導入
https://github.com/ArG0rithm-Ace/ArG0rithm-Ace_ChromaKeyRawImage

上記のGitHubでChromaKeyRawImageのフォルダをまるまるUnityにぶち込むだけ。

# 内容物の説明
スクリプト本体: (ChromaKeyRawImage.cs)
スクリプトで使うシェーダー: (ChromaKeyRawImage.shader)
インスペクターでボタンなどを表示するEditor拡張: (ChromaKeyRawImageEditor.cs)

# 使い方 1
RawImageが付属しているゲームオブジェクトにAddComponentするだけ。

# 使い方 2
カメラの背景を設定して切り抜く色を選択、しきい値とスムーズで調節。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1974158/437cf1a6-2e55-aa52-ad1d-ea7d551d24b9.gif)

# 便利機能
一発で背景色と切り抜く色を同期するボタンと、色を自動同期する機能付き。

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1974158/7ca1d5d2-bc5a-3205-299c-a74e0f46de81.gif)

# 今後も便利ツール公開してきます。作者の動向確認したい方は↓
https://x.com/ArG0rithm_Ace

(趣味でEditor拡張とかツール作ってたけど、今まで公開してなかったのマジで勿体ないね。)

# 履歴
2024/0815/1447 執筆
AndroidでGoogle検索時にうざいウェブサイトをブロックする方法

## 概要
Google検索したときに興味のないサイトが毎回上位に表示されるのが嫌なので、これをなんとかしたい。たとえば、お気に入りの漫画や映画のキャラクターをGoogleで画像検索する。すると色々画像が表示されるんだけど、結果にPinterestの画像が相当数まざる。Pinterestの画像はほとんどの場合ダウンロードできない。気に入った画像があればPinterestにアカウントを作って"Pin"とかいうのをしないといけないらしい。Pinしても画像はダウンロードできなかった気がする。ダウンロードをしてローカルに持っておきたいときに不便。
あとは大谷翔平のホームラン映像がみたくて動画を検索するときも、Youtubeのようなサイトの動画に混ざってtiktokの動画が相当数引っかかる。たまにアカウントなしで見られる動画もあるようだけど、結構な割合の動画がtiktokアプリをいれてアカウントを作らないと見られないようになっている。自分はアカウントを持ってないので、誤って開くと動画をみたいのに再生できずにストレスを感じる。
こういうサイトが最初から検索結果にでないように検索時に-tiktok -piterestを指定して検索すればいいんだけど、それを毎回やるのは面倒くさいのでデフォルトでGoogle検索のクエリに-tiktok -piterestを指定することにした。

追記：
書いてから思ったけど、この指定の仕方だと"tiktok"が記事名に入っているニュース記事とかQiitaの記事も弾いちゃうので単純なtiktokじゃなくてURLを指定したほうがいいかも。-inurl:tiktokみたいな感じで。
この辺が気になる人はこれを試して見てください。
```
https://www.google.com/search?q=-site:tiktok.*+-site:*.tiktok.*+-site:pinterest.*+-site:*.pinterest.*+%s
```

## やり方
### Android
1. デフォルトのAndroidのChromeアプリの設定画面を開く方法がわからないので同じChromium派生ブラウザのkiwiブラウザをつかう。エストニアのエンジニアが作ったらしい。PlayStoreからダウンロードできる。
(詳細) https://kiwibrowser.com/about/
1. `chrome://settings/`をkiwiブラウザのURL・検索バーに入力
1. 以下の画面がでるので、画面左上の三アイコンをタップ<br/><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260163/b4084906-bb17-02fd-7514-f2cbb58ea7b9.png" width= "300px" ><br/>
1. `Search engine`をタップし、出てきた画面の`Manage search engines..`をタップ
1. `Site search`の`Add`から新しい検索方法を追加する。名前・ショートカットキーワード・検索エンジンのURLを指定する必要があるので、今回は適当に名前を「noiseless google」、キーワードは「@nggl」にする。検索エンジンのURLは「 https://www.google.com/search?q=-tiktok+-pinterest+%s 」にする。できたら保存する。<br/><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260163/c3d0fdf2-9f2b-dd92-45b5-38be450a5c3d.png" width= "300px" ><br/>
1. 作ったものをデフォルトの検索方法にする
<br/><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260163/f2047a70-498c-5a2d-eda5-868edfd63323.png" width= "300px" ><br/>
1. 試しに検索してみると設定が反映されていることがわかります。
<br/><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260163/496a9bd9-9c52-7922-ea95-03d9b8278fcf.png" width= "300px" ><br/>
もし気に入らなかったらkiwiブラウザの設定のここからデフォルトの検索エンジンの設定を元に戻してください。
<br/><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260163/b7d32959-242e-ad9a-66f8-5c20de37b81b.png" width= "300px" ><br/>

## PCのChromeの場合
同じようなやり方でできると思います。
https://conpath.net/columns/filter-google-search-results-by-default/ 

## いかがでしたか系のサイトのブロック
PCの場合、このChrome拡張（uBlacklist）でブロックできる。なお、通常のAndroidアプリのChromeブラウザにこういう拡張は入らないが、kiwiブラウザは頑張れば入れられる。
https://chromewebstore.google.com/detail/ublacklist/pncfbmialoiaghdehhbnbhkkgmjanfhe

## 参考文献
* https://conpath.net/columns/filter-google-search-results-by-default/
zodベースでschemaを作成できるzgok-api

zodベースでschemaを作成できるzgok-apiフレームワークを作成しました。

- フロントエンド・バックエンドをTypeScriptで高速開発
- Zodでスキーマを定義することで、フロント・バックのクライアントが自動生成されます
- リクエスト送受信時にはZodによるバリデーションが実施され、安全が保たれます
- TypeScriptのIDE補完ききます

# schema作成
こんな感じで作成します。
front / backend双方から参照可能な位置に保存してください。

```schema.ts
import { z } from "zod";
import { postFunction, getFunction, patchFunction } from "@zgok-api/zgok-core";

export const SampleSchema = {
  dir1: {
    hoge1: postFunction({
      req: z.object({ id: z.number() }),
      res: z.object({ name1: z.string() }),
    }),
    hoge2: getFunction({
      req: z.object({ id: z.number() }),
      res: z.object({ name2: z.string() }),
    }),
  },
  dir2: {
    moge: patchFunction({
      req: z.object({ key: z.string() }),
      res: z.object({ kind: z.object({ name: z.string() }) }),
    }),
  },
};
```

# backend側
```
npm install zgok-express
```

先ほどのSchemaをZgokExpressに渡すと、handler functionとrouteが生成出来るようになります。
以下の処理では post "/api/dir1/hoge1" が生成されます。

```.ts
const router = express.Router();
import { ZgokExpress } from "@zgok-api/zgok-express";

const zgokExpress = ZgokExpress(SampleSchema);
router.use(
  zgokExpress.dir1.hoge1(async (req, res) => {
    console.log("hoge3 zbody", req.zbody);
    return { name3: `${req.zbody.id}さん` };
  })
);
app.use("/api", router);
```

# front側
```
npm install zgok-express
```

先ほど作成したSchemaを、ZgokAxiosに渡してクライアントを生成します。
```.ts
import { ZgokAxios } from "@zgok-api/zgok-axios";

export const zgokAxios = ZgokAxios(
  Axios.create({ baseURL: "http://localhost:3000/api" }),
  SampleSchema
);
```

リクエストを送ると、expressで作成された　post "/api/dir1/hoge1"　へリクエストが送られます。
```.ts
const hoge1 = async () => {
  const res = await zgokAxios.dir1.hoge1({ id: 1 });
  console.log("res", res);
};
```

# その他
## zgokDate
レスポンスにDateが含まれている場合、JSONの仕様上、文字列として返却されます。
そのままzodで検証すると型エラーとなってしまいます。
zodDateを使うと、レスポンスを自動的にDateへ変換します。

```.ts
import { zgokDate } from "@zgok-api/zgok-core";

...

hoge3: postFunction({
  req: z.object({ id: z.number(), date1: zgokDate() }),
  res: z.object({ name3: z.string(), date2: zgokDate() }),
}),
```
Unityに自動セーブ機能を追加する

## 目的
tsubakiさんが作られた UnityEditor におけるシーンのオートセーブ機能(https://gist.github.com/tsubaki/8709502) を紹介した記事が多いが、最新バージョン(2022.3.40f.1)だとエラーが出たので、同じエラーが出た場合の対処方法を紹介します。

## 環境
* Unity(2022.3.40f.1)

## とりあえず今までやり方でやってみる
こちらのサイトを参考にそのまま導入する

https://styly.cc/ja/tips/unity-autosave/#AutoSavecs

1.tsubakiさん(https://gist.github.com/tsubaki/8709502) のGithubにとび、右上の「Download ZIP」でダウロード&解凍

![スクリーンショット 2024-08-15 123211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3861800/833ea443-6b98-94f7-988e-e11aac11a915.png)

2.解凍すると「AutoSave.cs」と「SceneBackup.cs」が出てくるのでUnityのEditorに「AutoSave.cs」をインポート

![スクリーンショット 2024-08-15 123809.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3861800/6278a3a7-89fe-ca48-293a-0d20a783dca9.png)

しかし、ここでエラー発生がしてしまう。エラー内容は
```
Assets\AutoSave.cs(24,6): error CS0619: 'EditorApplication.SaveAssets()' is obsolete: 'Use AssetDatabase.SaveAssets instead (UnityUpgradable) -> AssetDatabase.SaveAssets()'
Assets\AutoSave.cs(44,7): error CS0619: 'EditorApplication.SaveAssets()' is obsolete: 'Use AssetDatabase.SaveAssets instead (UnityUpgradable) -> AssetDatabase.SaveAssets()'
```
とのことで、どうやらEditorApplication.SaveAssets()の書き方は現在だと使えないみたい。AssetDatabase.SaveAssets()のほうを使ってねとのこと。

## 修正してみる
```C#
public class AutoSave
{
	public static readonly string manualSaveKey = "autosave@manualSave";

	static double nextTime = 0;
	static bool isChangedHierarchy = false;

	static AutoSave ()
	{
		IsManualSave = true;
		EditorApplication.playmodeStateChanged += () =>
		{
			if ( IsAutoSave && !EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode) {

				IsManualSave = false;

				if (IsSavePrefab)
					AssetDatabase.SaveAssets()//<-EditorApplication.SaveAssets ();
				if (IsSaveScene) {
					Debug.Log ("save scene " + System.DateTime.Now);
					EditorApplication.SaveScene ();
				}
				IsManualSave = true;
			}
			isChangedHierarchy = false;
		};

		nextTime = EditorApplication.timeSinceStartup + Interval;
		EditorApplication.update += () =>
		{
			if (isChangedHierarchy && nextTime < EditorApplication.timeSinceStartup) {
				nextTime = EditorApplication.timeSinceStartup + Interval;

				IsManualSave = false;

				if (IsSaveSceneTimer && IsAutoSave && !EditorApplication.isPlaying) {
					if (IsSavePrefab)
						EditorApplication.SaveAssets ();
					if (IsSaveScene) {
						Debug.Log ("save scene " + System.DateTime.Now);
						AssetDatabase.SaveAssets()//<-EditorApplication.SaveScene ();
					}
				}
				isChangedHierarchy = false;
				IsManualSave = true;
			}
		};
```
これでエラーが解消されるはず。

## AutoSaveの設定
「編集」->「環境設定」->「自動保存」にとび、「auto save」から始まる4つすべてにチェックを入れる。

![スクリーンショット 2024-08-15 144057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3861800/de5abf2e-6721-7b73-6df6-a9e5eb05154d.png)

Auto Saveの設定は完了です。これでUnityが落ちて今までの作業がパー👐になる事故が防げるので、プロジェクト作ったら皆さん絶対に入れましょう。

:::note warn
AutoSaveはプロジェクトを新規作成するごとに毎回入れる必要があります。
面倒くさいですが、新規プロジェクトを作成した際は、AutoSaveの導入を忘れないようにしましょう。
:::
blastengine VBA SDKを使って購読停止（List-Unsubscribe）ヘッダを付けたメールを送信する

[blastengine](https://blastengine.jp/)はシンプルに使える開発者向けメールサービスを提供しています。何かと面倒なメール配信をシンプルに、かつ確実に送信先へ届くようになります。

今回は今開発中のVBA用SDK（以下VBA SDK）を使って、List-Unsubscribeヘッダーを付けたメールを送信する方法を解説します。

## コードについて

コードはGitHubにアップしてあります。ライセンスはMIT Licenseになります。

[blastengineMania/blastengine-vba: blastengineのVBA SDKです](https://github.com/blastengineMania/blastengine-vba)

## ユーザ登録する

blastengineにユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

![getting-started-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/5c6c8cb0-9ad1-0a6d-88fe-e24bc3ee7b17.jpeg)

## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

## APIキーを取得する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/78a4eeb3-4649-149f-8246-44f83d03a0cf.jpeg)

そして設定の中で、APIキーを取得します。

![getting-started-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/d21fc4e3-36f0-6f5c-23e3-8c675e16f538.png)

## SDKのインストール

[SDKは リリースページでマクロ付きExcelファイルをダウンロードする](https://github.com/blastengineMania/blastengine-vba/releases)か、リポジトリの内容をvbacでコンパイルしてください。

[blastengineMania/blastengine-vba: blastengineのVBA SDKです](https://github.com/blastengineMania/blastengine-vba)

## 参照設定について

VBAエディタで、ツール > 参照設定 から、以下の参照設定を追加してください。

- Microsoft ActiveX Data Objects 6.1 Library
- Microsoft XML, v6.0

※ 将来的には、参照設定を不要にする予定です。

## 初期化

先ほどのAPIキーとユーザIDを使って初期化します。

```vb
Dim client As new Blastengine
client.ApiKey = "YOUR_API_KEY"
client.UserId = "YOUR_USER_NAME"
```

## メールの送信

### メール送信時のクラス

blastengine VBA SDKでメール送信を行う際には、3つのクラスが利用できます。

- **Transaction:**  
都度配信用クラス
- **Bulk:**  
一括配信用クラス
- **Mail:**  
Transaction/Bulk双方を必要に応じて使い分けるクラス

基本的にはMailクラスを利用していれば問題ありません。以下のメソッド名は共通です。

## List-Unsubscribe用の情報設定

List-Unsubscribeヘッダーを使う際には、 `ListUnsubscribe` メソッドを使います。

```vb
Dim Mail as Mail
Set Mail = client.Mail

Dim InsertCode As Dictionary
Set InsertCode = New Dictionary
InsertCode.Add "name", "Test"
InsertCode.Add "code", "123456"

Mail.Email "user@example.jp", InsertCode

Dim ListUnsubscribe As ListUnsubscribe
ListUnsubscribe.Url = "https://example.com/unsubscribe/__code__"
ListUnsubscribe.Email = "unsubscribed+__code__@example.com?subject=unsubscribe"
Mail.ListUnsubscribe = ListUnsubscribe
```

`ListUnsubscribe` は `Url` と `Email` をオプションに取ります。どちらもオプションです。`__code__` は置換文字列になります。 `Email` の第2引数に指定したキーで置換されます（実際には `__キー__` と置換されます）。今回の例であれば、URLは `https://example.com/unsubscribe/123456` 、メールアドレスは `unsubscribed+123456@example.com?subject=unsubscribe` になります。

## メールの送信

メールの送信は `send` メソッドを使います。

```vb
If Mail.Send Then
		MsgBox "送信しました"
Else
		MsgBox "送信に失敗しました"
End If
```

## まとめ

List-Unsubscribeヘッダーは、Gmailのガイドライン変更に伴って、対応が必須になっている機能になります。blastengineの場合は、APIとSMTP両方でList-Unsubscribeヘッダーに対応しています。

現在はGmailのみですが、他のメールプロバイダーについても対応が進んでいくことでしょう。blastengineを使って、配信したメールを確実に受信者に届けるためにも、List-Unsubscribeヘッダーの対応を行ってください。

[blastengine API](https://blastengine.jp/documents/)
Azure Fundamentals AZ-900の合格記

先日AZ−９００を受験し、無事合格しました。
715/１０００点で合格しました。危なかった。。。
何はともあれ合格であることに変わりはないので、素直に喜びたいと思います！
受験するまでの流れを簡単にまとめたいと思います。

## 学習方法

学習方法は書籍とUdemyとMicrosoftの公式サンプル問題をやりました。

### 書籍
これを書店で購入。
https://amzn.asia/d/6Fd8CZV
シンプルな解説で記載されており、図解もあり個人的に読みすやい内容でした。
読み方としてはじっくり読むよりも、ぱーっと読んで色付けされてるところのみ前後の内容を読んだ感じです。
あと読破してないです。モッタイネ

### Microsoftのサンプル問題
サンプル問題を周回しました。
https://learn.microsoft.com/ja-jp/credentials/certifications/azure-fundamentals/practice/assessment?assessment-type=practice&assessmentId=23&practice-assessment-type=certification
不正解だった箇所の解説で読みづらい（翻訳のあれ）ところは書籍を辞書がわりにしました。

### オンライン学習
利用したのはUdemyのこれです。
https://www.udemy.com/course/microsoft-ai-900-l/?couponCode=JUST4U02223
学習動画ではなく、模擬問題集を何回か周回しました。
どういった文章で出題されるかを掴むのと、書籍で読んだ内容をアウトプットする意味でもやってよかったと思います。
ちなみにこの模擬問題集をAZ-900の知識を全く入れずにやって半分は正解できました。(あてずっぽうはあるが)
難易度はそこまで高くないと感じたのと、クラウドの基礎知識とAzureについて理解すればできる内容だなと感じました。

### 学習時間と期間

期間としては１ヶ月はかかってないです。多分２週間とかそれぐらいでした。
学習時間も合間にやっていたので、そこまで時間はかけてないです。
というか時間かけたからできるって考えが好きじゃないというのもあって測ってないです。
時間云々よりもウトプットをすることを多くしました。

### 当日
試験センターで受けました。
模擬とサンプルでやった形式（画面の違い）ではなかったのですこし違和感がありましたが、ゆっくり時間をかけて解きました。
知識不足なのかわからないですが、初見では？？？という内容の問題がありました。
そんなことないとは思うのと、ただの知識不足だろ。。。と思って解きました。

### 感想

やることやれば受かるし、得点もギリギリでヒヤヒヤすることはないんだろうと思いました。
今後AWSのPLF、SSAの受験を検討しているので、同じように受けると次は落ちると思いました。
Emacs風のCUIエディタを作った話

# はじめに
自作のEasy-ISLispの開発もほぼ完成しました。ISLisp基準準拠のほかに並列機能、TCP/IP通信の機能拡張も終えました。やり尽くしました。さて、それではLisp遊びをしましょうか、と始めてみると適当なエディタがないのです。CでEasy-ISLispを開発してる時にはマイクロソフトのVSCodeを使っていました。ところがこれのLispサポートが私好みではないのです。そしてCommonLispのサポートのみでISLispはサポートされていません。よっしゃ、いっちょ、自分で作るか！とCUIのEmacs風のエディタを作りました。

# 土台
もともとEdlisというCUIエディタを付属させていました。これは入門用の簡易エディタです。Emacs風のキーバインドながら最小限の機能しかないものでした。Emacsはとても多機能なのですが、設定が面倒臭く、Lisp初心者はEmacsの設定でLisp熱が冷めてしまうような気がしました。そのために用意してあったものです。

今回、このEdlisを大幅に改良拡張しました。Scheme用のエディタであるEdwinと互換性を持たせています。私は1980年代にテキサスインスツルメント社のPC-SchemeでSchemeを経験しました。Edwinに馴染みがあるのですね。それを思い出しつつ、Edlisを実用的に使えるように改良しました。ver5.25で機能アップしてあります。

# キーバインディング
PC-Schemeのマニュアルを参照しつつ次のようになっています。

```
CTRL+F move to right in character units → key
CTRL+B move to left in character units ← key
CTRL+P move to up in line ↑ key
CTRL+N move to down in line ↓ key
CTRL+J move to end of line
CTRL+A move begin of line
CTRL+E move to end of line
CTRL+D delete one char Back Space key
CTRL+O return Enter key
CTRL+V display next page Page Down key
ESC V display previous page Page Up key
ESC < goto top page Home key
ESC > goto end page End key
ESC f Move forward in word units
ESC b Move backward in word units
ESC CTRL+F Move forward in S-expressdion units
ESC CTRL+B Move Back in S-expression units
ESC CTRL+N Move forward in list units
ESC CTRL+P Move back in list units
ESC CTRL+U Move up a level in the list structure
ESC STRL+D Move down a level in the list structure
Insert Switch insert-mode and overwrite-mode
TAB insert spaces as lisp indent rule
CTRL+X CTRL+C quit from editor with save
CTRL+X CTRL+Z quit from editor without save
CTRL+X CTRL+F load from file to editor
CTRL+X CTRL+V load from file to editor
CTRL+X CTRL+I insert buffer from file
CTRL+X CTRL+S save file
CTRL+X CTRL+W save file as
CTRL+X CTRL+L save region to file as
CTRL+S search a word forward
CTRL+R search a word backward
CTRL+T replace a word
ESC TAB complete builtin function name
ESC I info of function
ESC ^ mark(or unmark) row for selection
CTRL+K cut one line
CTRL+W cut selection
ESC W save selection
CTRL+Y uncut selection
CTRL+G cancel command

```


# ISLispサポート
ISLispはコンパクトなため組込み関数は少ないのですが、それにしても全部を覚えてはいられません。そこでEdlisに組込関数の仕様を検索する機能を追加してあります。関数名にカーソルを合わせてESC i と押すと最下行に関数の説明がでるようにしてあります。

![bandicam 2024-08-15 13-56-26-606.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/ef99b9f1-519c-96ce-82b0-e766c6bcc52e.jpeg)


# お望みのままに
EdlisはすべてC言語で書かれています。およそ3800行ですが、そのうちヘルプデータを除くとコアな部分は3000行程度です。データ構造は極めて単純にしてあります。容易に改造することができます。EmacsだとEmacs-Lispを覚えてそれで機能拡張をしていきます。EdlisはC言語そのものを弄れるのでこっちの方が楽な人もいるかもしれません。

# ターミナル機能
Edlisはターミナルの機能はもっていません。Tmuxと合わせて使います。EdlisとEasy-ISLispを分割画面に起動しておけば、Emacs風な使い方ができます。

![bandicam 2024-08-15 14-01-33-838.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/07d10c9e-f1a1-6fab-45f2-9bd69fe150f7.jpeg)


# おまけ
かれこれ8年くらい開発を継続してきたEasy-ISLispですがGNUのGuixにパッケージとして採用されていたことがわかりました。感無量です。広く使われてISLispの普及にお役に立てれば幸いです。

![bandicam 2024-08-15 14-04-28-366.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/44aef5e9-959c-3358-ed9c-54680bf8cf90.jpeg)


https://github.com/sasagawa888/eisl
blastengineのVBA SDKを使ってメールの詳細の取得・削除を行う

[blastengine（ブラストエンジン）](https://blastengine.jp/)はシンプルに使える開発者向けメールサービスを提供しています。何かと面倒なメール配信をシンプルに、かつ確実に送信先へ届けられます。

現在、[VBA向けのblastengine SDK](https://github.com/blastengineMania/blastengine-vba)を開発しています。Excelを利用していますが、Accessなどでも使えるはずです。この記事では、その使い方を解説します。今回は一回の宛先数が50通を超える場合の一括配信メールの送信方法を解説します。

## ユーザ登録する

blastengineにユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ece1bb6d-4f02-aba3-4197-9c9826ce3f29.png)

## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

## APIキーを取得する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/47b2b2ac-2e41-77fe-d84f-0ae0b7541f36.jpeg)

そして設定の中で、APIキーを取得します。

![getting-started-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2b5ca124-3020-1d39-84e4-911cd4db27e2.png)

## 必要な情報について

SDKを使う上で必要なのは、先ほどのAPIキーとユーザIDになります。

## SDKのインストール

[SDKは リリースページでマクロ付きExcelファイルをダウンロードする](https://github.com/blastengineMania/blastengine-vba/releases)か、リポジトリの内容をvbacでコンパイルしてください。

[blastengineMania/blastengine-vba: blastengineのVBA SDKです](https://github.com/blastengineMania/blastengine-vba)

## 参照設定について

VBAエディタで、ツール > 参照設定 から、以下の参照設定を追加してください。

- Microsoft ActiveX Data Objects 6.1 Library
- Microsoft XML, v6.0

※ 将来的には、参照設定を不要にする予定です。

## 初期化

先ほどのAPIキーとユーザIDを使って初期化します。

```vb
Dim client As new Blastengine
client.ApiKey = "YOUR_API_KEY"
client.UserId = "YOUR_USER_NAME"
```

## トランザクション・バルクオブジェクトの作成

メール詳細を取得する際には、トランザクションまたはバルクオブジェクトを利用します。

```vb
Dim Bulk As Bulk
Set Bulk = client.Bulk

Dim Transaction As Transaction
Set Transaction = client.Transaction
```

## 必要な情報をセットする

続けて、メールのデリバリーIDをセットします。

```vb
Bulk.DeliveryId = 2769
Transaction.DeliveryId = 2771
```

## メールの詳細を取得する

メールの詳細を取得するには、 `Info` メソッドを使います。返り値は `True` または `False` です。

```vb
Bulk.Info
Transaction.Info
```

## 情報を確認する

取得した情報は、以下のように取得できます。

```vb
' Transactionも共通のプロパティを持っています
Debug.Print Bulk.DeliveryType
Debug.Print Bulk.SentCount
Debug.Print Bulk.DeliveryTime
Debug.Print Bulk.DeliveryId
Debug.Print Bulk.Status
Debug.Print Bulk.UpdatedTime
Debug.Print Bulk.CreatedTime
Debug.Print Bulk.ReservationTime
Debug.Print Bulk.OpenCount
Debug.Print Bulk.TotalCount
Debug.Print Bulk.DropCount
Debug.Print Bulk.SoftErrorCount
Debug.Print Bulk.HardErrorCount
```

## メールの削除

メールを削除するには、 `Delete` メソッドを使います。

```vb
' または Transaction.Delete
If Bulk.Delete Then
	' 削除成功
Else
	' 削除失敗
	' Bulk.Error でDirectory型のエラーメッセージ
End if
```

## コードについて

コードはGitHubにアップしてあります。ライセンスはMIT Licenseになります。

[blastengineMania/blastengine-vba: blastengineのVBA SDKです](https://github.com/blastengineMania/blastengine-vba)

## まとめ

blastengineには他にも即時送信メールを使ったり、ListUnsubscribeヘッダー機能などもあります。これらの機能も随時実装していきますので、ぜひ皆さんのシステム開発に役立ててください。

[エンジニア向けメール配信システム「ブラストエンジン」](https://blastengine.jp/)
Visual Studioの参照設定は鵜呑みにするな

備忘録

DebugとReleaseでデバッグ実行した際、何故かDebugだけ通らなかった。
プロパティ一式確認したが問題なし。
結果、参照設定で設定してるファイルをアプリと同じ階層（設定値とは異なるディレクトリ）にぶち込んだら動いた。
インピーダンスマッチ

```
import numpy as np
import matplotlib.pyplot as plt

# Constants
beta = 2 * np.pi / 0.3  # Assuming a wavelength λ = 0.3 for demonstration
z_values = np.linspace(0, 0.3, 500)  # Position along the transmission line
ZL = 50 + 30j  # Load impedance (example values)
ZS = 75  # Source impedance (example value)
Gamma_0 = 0.2 + 0.6j  # Initial reflection coefficient (example value)

# Calculating input impedance Z_in(z) and reflection coefficient Gamma(z)
Z_in = ZS * (ZL + 1j * ZS * np.tan(beta * z_values)) / (ZS + 1j * ZL * np.tan(beta * z_values))
Gamma = Gamma_0 * np.exp(-2j * beta * z_values)

# Normalize the input impedance for Smith Chart
Z_norm = Z_in / ZS

# Plot Reflection Coefficient
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(z_values, np.abs(Gamma), label='Reflection Coefficient |Γ(z)|')
plt.xlabel('Position z (m)')
plt.ylabel('Magnitude of Γ(z)')
plt.title('Reflection Coefficient |Γ(z)| vs Position z')
plt.grid(True)
plt.legend()

# Plot Input Impedance Z_in(z)
plt.subplot(1, 2, 2)
plt.plot(z_values, np.real(Z_in), label='Real(Z_in(z))')
plt.plot(z_values, np.imag(Z_in), label='Imag(Z_in(z))')
plt.xlabel('Position z (m)')
plt.ylabel('Impedance Z_in(z) (Ω)')
plt.title('Input Impedance Z_in(z) vs Position z')
plt.grid(True)
plt.legend()

plt.tight_layout()
plt.show()

# Alternative Smith Chart Plot using Polar Coordinates
plt.figure(figsize=(8, 8))
plt.polar(np.angle(Z_norm), np.abs(Z_norm), label='Normalized Impedance Z_norm(z)')
plt.title('Alternative Smith Chart (Polar Plot) of Normalized Impedance')
plt.legend()
plt.show()

# Impedance Chart (Real vs Imaginary parts)
plt.figure(figsize=(8, 6))
plt.plot(np.real(Z_in), np.imag(Z_in), label='Z_in(z)')
plt.xlabel('Real Part of Z_in(z) (Ω)')
plt.ylabel('Imaginary Part of Z_in(z) (Ω)')
plt.title('Impedance Chart')
plt.grid(True)
plt.legend()
plt.show()
```
NavigationMixin(LightningElement) VS LightningElement

Salesforce Lightning Web Components (LWC) では、`NavigationMixin` はナビゲーション関連の機能を提供するツールで、`LightningElement` クラスと一緒に使用されることが多いです。これにより、`Lightningアプリケーション内でのナビゲーション機能が有効になります。`

以下は、`extends NavigationMixin(LightningElement)` と `extends LightningElement` の違いです。

### `extends LightningElement`

`LightningElement` を拡張すると、コンポーネントは Lightning Web Components フレームワークが提供する`基本的な機能`を継承します。これには、コンポーネントのライフサイクルの処理、レンダリング、標準のコンポーネント機能が含まれますが、ナビゲーション機能は含まれません。

**例:**

```jsx
import { LightningElement } from 'lwc';

export default class MyComponent extends LightningElement {
    // コンポーネントのロジック
}
```

### `extends NavigationMixin(LightningElement)`

`NavigationMixin(LightningElement)` を拡張すると、`LightningElement` と `NavigationMixin` を組み合わせて、追加のナビゲーション機能を追加できます。`NavigationMixin` を使用すると、`navigate` メソッドを使って、Salesforce アプリケーション内の異なるページやコンポーネントにプログラム的にナビゲートできます。

**例:**

```jsx
import { LightningElement } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';

export default class MyComponent extends NavigationMixin(LightningElement) {
    handleNavigation() {
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: '001XXXXXXXXXXXXXXX',
                objectApiName: 'Account',
                actionName: 'view'
            }
        });
    }
}
```

この例では、`NavigationMixin` を使用してコンポーネントにナビゲーション機能を含めています。`handleNavigation` メソッドは、`NavigationMixin.Navigate` メソッドを使用してレコードページにナビゲートする方法を示しています。

### まとめ

- **`extends LightningElement`**：コンポーネントには基本的な Lightning Web Component の機能がありますが、ナビゲーション機能はありません。
- **`extends NavigationMixin(LightningElement)`**：基本的な Lightning Web Component 機能に加えて、ナビゲーション機能があり、アプリケーション内のナビゲーションをプログラム的に制御できます。

ナビゲーション機能（ユーザーを異なるページやレコードに誘導するなど）が必要な場合は、`NavigationMixin` を使用します。ナビゲーションが不要な場合は、`LightningElement` の拡張で十分です。


### 補足情報

- **`Mixinにイメージをつける`**：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514843/ea4a5a80-562d-b3de-3f91-ac715a44bd3e.png)
RailsアプリケーションでAWS Parameter Storeを使用する方法

AWS Parameter Storeは、アプリケーションの設定値や機密情報を安全に管理するための便利なサービスです。
この記事では、Railsアプリケーションのproduction環境設定でAWS Parameter Storeの値を使用する方法について説明します。

**前提条件**
- AWSアカウントがあること
- AWS CLIが設定されていること or EC2などに適切なロールが割り当てられていること
- Railsプロジェクトがあること

# 1. AWS SDKのセットアップ
まず、AWS SDKをプロジェクトに追加します。Gemfileに以下を追加し、bundle installを実行します。
```ruby
gem 'aws-sdk-ssm'
```

# 2. パラメータ取得用のヘルパーメソッド
次に、AWS Parameter Storeから値を取得するためのヘルパーメソッドを作成します。config/application.rbに以下のコードを追加します。
```ruby
require 'aws-sdk-ssm'

module ParameterStoreHelper
  def fetch_parameter(name)
    ssm_client = Aws::SSM::Client.new(region: 'your-aws-region')
    response = ssm_client.get_parameter(name: name, with_decryption: true)
    response.parameter.value
  rescue Aws::SSM::Errors::ParameterNotFound
    nil
  end
end

class Application < Rails::Application
  # 既存の設定...
  
  extend ParameterStoreHelper
end
```

# 3. production.rbでの使用
config/environments/production.rbで、AWS Parameter Storeから取得した値を設定に使用します。
```ruby
Rails.application.configure do
  # 既存の設定...

  config.secret_key_base = Rails.application.fetch_parameter('/your_app/production/secret_key_base')
  
  config.action_mailer.smtp_settings = {
    address: Rails.application.fetch_parameter('/your_app/production/smtp_address'),
    port: Rails.application.fetch_parameter('/your_app/production/smtp_port'),
    user_name: Rails.application.fetch_parameter('/your_app/production/smtp_username'),
    password: Rails.application.fetch_parameter('/your_app/production/smtp_password')
  }

  # その他の設定...
end
```

# 注意点
- IAMロールの設定
    - EC2インスタンスやECSタスクに適切なIAMロールを割り当て、Parameter Storeへのアクセス権限を付与する必要があります。
- パフォーマンスへの影響
    - 起動時にParameter Storeから値を取得するため、アプリケーションの起動時間が若干長くなる可能性があります。
- エラーハンドリング
    - パラメータが見つからない場合のエラーハンドリングを適切に行うことが重要です。
- 環境変数との併用
    - 一部の設定は環境変数で、機密性の高い情報はParameter Storeで管理するなど、柔軟に組み合わせることができます。
    - この方法を使用することで、AWSのParameter Storeに保存された値をRailsのproduction環境設定で安全に利用できます。
    - セキュリティと設定管理の両面で有効な手法です。 

これで、RailsアプリケーションでAWS Parameter Storeを使用する準備が整いました。
ぜひ試してみてください！
Udemy で Python 入門してみた その1 ~変数の基本~

## 前置き

業務ではローコード開発、SharePointだったり PowerAppsだったりが主だって、
プログラミングの勉強が疎かになっている最近。
PowerAppsではCRUDを自分で実装したりはしてるものの、それとこれは話が別なわけで。
ひとまずずっと気になっていたPythonを一から勉強していきます。

## 目的

とりあえずは学習したことを備忘録的にメモしておこうと思い、久しぶりにQiitaで記事を投稿しようと。
ただこの入門コース、プログラミング未経験者も対象にしていて、ちょっとイントロダクションが冗長に感じてしまったり。
まぁ、それはそれ。どんどん学習を進めていきたいと思います。

## IDE
PyCharm を使って勉強を進めます

## 勉強になったところ
・データ型は型推論、動的型付け

・インデントでエラーになる(姿勢矯正みたいな印象を受けた)

・定数の宣言に関する修飾子はなく、全て大文字で表現する

```Python
TAX_RATE = 0.1
```

・`input`の戻り値は `str`型

・エスケープシーケンス`\`や改行の`\n`のほかに、タブ`\t`が存在する(文字列を整形してくれる)

```Python
print('Name\tAddress\tAge\n'
      'Taro\tTokyo\t20')
```

・日時の差分は`datetime.timedelta()`
```Python
import datetime

now = datetime.datetime.now()
ten_days_later = now + datetime.timedelta(days=10)
```

## 気になったところ
### `None`について
まだ序章だからなのか、他言語の`null`のようなもの、とあったけれど、
他にも`Nothing`や`undefined`のようなものが返ってくることはあるんだろうか
全て`None`でひとくくりにしていいのか、気になった

ひとまず実際に動くプログラムを書いていって確かめるのが早い
講座を進めるしかない


## まとめ
とりあえず、あくまでも備忘録な感じで。
まとまってきたらまた書き出すと思います。
あと、かなりマイペースになりそう
キャンプで例えるプロジェクト見積りとリスク管理

## はじめに
この記事は
(PMO1年生の)私の
プロジェクトマネジメントについてのまなびをみなさんと共有するものです。
プロジェクト管理における重要なテーマ「見積りとリスク」についてキャンプで例えてみたので、
身近なテーマとして考えるきっかけにしていただければと思います。

## まず
一般的に
システム開発プロジェクトの成功確率は約30％とされています。
多くのプロジェクトが失敗に終わる一因として、**予期せぬリスク**が挙げられています。

### 課題は初期見積りにあり!?
プロジェクトの初期段階では、**未知の要素**が多く、正確な見積りが困難です。
そのため、見積もりプロセスにおいて**見えないリスクをどのようにして反映させるか**が重要になります。
過去のプロジェクトのデータや市場の動向を分析し、予測外の変動に備えることが求められます。

### 不測の事態に備える予備資産を
予測不可能な事態が発生する可能性に対して、予備資産を見積もることがプロジェクト管理において不可欠です。
過去のプロジェクトから学んだ教訓を活用し、リスクバッファとしてのリソースを設けることで、未来の不確実性に柔軟に対応することが可能になります。

## そこで

### 三点見積り手法
三点見積り手法は、
・最可能値（最も起こり得る見積もり）
・楽観値（最良のシナリオ）
・悲観値（最悪のシナリオ）
の三点から期待値を算出します。

![プロジェクト見積りとリスク管理の重要性_page-0003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552881/64d00675-096d-8d0d-b486-9a1f54e17a83.jpeg)

この方法により、
プロジェクトの不確実性を定量的に評価し、より現実に近い見積もりを行うことができます。

### コンティンジェンシー予備とマネジメント予備
#### ・コンティンジェンシー予備（＝既知の未知）
→**特定のリスク**が現実化した場合に備えた予備資産です。
#### ・マネジメント予備（＝未知の未知）
→**プロジェクト全体**のリスクに備えるための予備資産です。

![プロジェクト見積りとリスク管理の重要性_page-0004.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552881/2d30c89a-d276-112d-27ce-1db3e3d3ca60.jpeg)

## キャンプで例えてみた
1. **初期見積りの課題**→キャンプの計画
キャンプを計画する初期段階では、参加者の数、予算、天候など、確定していない要素が多いです。
(主に「行けたら行く」が原因)
このように、プロジェクトの見積もりも、最初に完全な情報を得ることは難しいため、
可能な限り多くの情報を集め、過去のキャンプの経験を生かして計画を立てることが重要です。

2. **三点見積り手法**→天候の予測
キャンプでは、最良（晴れ）、最悪（雨）、そして最も可能性の高い天候を予測します。
(天気アプリ3つくらい比較します)
プロジェクトではこれを三点見積り手法と呼び、各タスクの楽観的、悲観的、そして最も可能性の高い時間やコストを推定します。
これにより、実際のところどれくらいのリソースが必要かをより正確に見積もることができます。

3. **コンティンジェンシー予備とマネジメント予備**→天候が変わりやすい地域でのキャンプ
コンティンジェンシー予備は、予想外の雨が降ったときのためにレインコートやタープを用意するようなものです。
一方、
マネジメント予備は、予期せぬ事態全般に備えて余分な食料や燃料を用意しておくことに似ています。
どちらも予期せぬ事態に柔軟に対応するために重要です。
（「夜は寒いよ」って言っても薄着でくるやつなんなの）

4. **リスク管理プロセス**→野生動物のリスク
キャンプ地で野生動物に遭遇するリスクがある場合、まずはそのリスクを特定し、次にどのように対応するか計画を立てます。
（例えば、食料は車内に保管する、ベルを持って歩くなど）
プロジェクトにおけるリスク管理も同様に、リスクを特定し、分析した後、優先順位をつけて対応策を実行し、継続的に監視するプロセスです。
（ちなみに熊は会ったことないけど鹿はあります）

![auroras-ga153ddd1e_640.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552881/2930184b-60b1-2ad2-e24d-50a44568c28a.jpeg)

## まとめ
プロジェクトマネジメントにおいて
リスクは単なる失敗の要因と捉えがちですが、
リスク管理は**不確実性に効果的に対応するための戦略を練るプロセス**です。
リスクを認識し、それに対するコストを適切に設定することが重要なため
適切な見積りとリスク管理によって、プロジェクトの成功確率を向上させることができます。

## 参考リンク
[「既知の未知」と「未知の未知」に備える！](https://www.it-innovation.co.jp/2014/04/22-134214/)

## さいごに
弊社のご紹介もさせてください！

「日本で一番エンジニアが成長できる会社を創る」
[株式会社PRUM](https://prum.jp/)

エンジニアリングの募集
[いつから挑戦しても遅くない！Webアプリ開発エンジニアを目指しませんか？](https://www.wantedly.com/projects/1771548)
PM・Webディレクションの募集
[プロジェクトの企画・要件定義から携わりたいPMを募集しています！！](https://www.wantedly.com/projects/1355235)
セールス・事業開発の募集
[RA・CAの両面型で、自社従業員に寄り添い成長を見届けることができる営業！](https://www.wantedly.com/projects/1792065)
コーポレート系の募集
[育ち盛りのエンジニアたちを支えてくれる労務経験者を大募集！](https://www.wantedly.com/projects/1752874)
コンサルティングの募集
[システム開発の失敗を極限まで減らすことができるITコンサルに挑戦しませんか](https://www.wantedly.com/companies/company_8173074/projects)

弊社メンバーは日々学習した内容をアウトプットしております！
ちょこっとでもご興味を持たれた方は求人を見てみてください！
（ご応募もお待ちしております！）

### 最後までご覧いただき、ありがとうございました！
ファイル書き込みにTaskを使う　（ｃ＃）

### やりたいこと
テキストボックスに入力した文字列をボタン操作で.\example.txtへ書き込む処理を作る。
このとき、書き込む処理をTaskを使って実行する。

### 特徴
ボタンを押すとラベルに「処理を開始しました。」と表示される。
書き込む処理が別のタスクとして実行される。
入力欄は初期化される。
入力チェックを行うことでボタンの二重操作は無視される。
保存処理が完了する前に別の操作が可能となる。

### コード
```  
 private async void button1_Click(object sender, EventArgs e)
 {
     label1.Text = "処理を開始しました。";
     Debug.WriteLine("処理を開始しました。");

     var txt = textBox1.Text;
     if (String.IsNullOrEmpty(txt)) {
         MessageBox.Show("入力必須です");
         return;
     }
     
     Task.Run(async () =>
     {
         using (StreamWriter reader = new StreamWriter("example.txt"))
         {
             await reader.WriteLineAsync(txt);
             await Task.Delay(3000);
             label1.Invoke(() =>
             {
                 label1.Text = "処理が終了しました。";
             });
             Debug.WriteLine("処理が終わりました。");

         }
     });
     textBox1.Text = "";
     return;
 }

 ```

 ###　感想
画面がフリーズせず、処理を可視化しながら次の操作を行うことができるためUXに良い影響を与えると思われる。
rails simple_calendar実装メモ

■ インストール
GemFileに以下記述
```
#calender ui
gem "simple_calendar", "~> 2.0"
```
bundleで installをする
```
bundle install 
```
■ 実装してみる(scssで)
ファイル作成
app\assets\stylesheets\custom_calendar.scss
```
@import "simple_calendar";
.simple-calendar{
    thead {
・・・その他記述可能
```
■ erbファイル実装
.erbファイル　にscss読み込み
```
  <%= stylesheet_link_tag "custom_calendar", media: "print, screen", "data-turbo-track": "reload" %>
```
実装こういう感じ
```
<%= month_calendar do |date| %>
  <%= date %>
<% end %>
```
■ イベントなど設定
controller
```
  def calendar
    start_date = params.fetch(:start_date, Date.today).to_date
    @event_days = EventDay.where(start_time: start_date.beginning_of_month.beginning_of_week..start_date.end_of_month.end_of_week)
  end 
```
表示
```
  <%= month_calendar(events: @event_days) do |date, event_days| %>
        <div class="day_block">
            <div>
            &nbsp;
            </div>
            <div class="day_num">
              <%= date.day %>
            </div>
            <div class="day_text  ">
            <% if event_days.length > 0 %>
             <%= event_days[0].name %>
            <% elsif date.wday == 3 %>
              休業日
            <% else %>
            &nbsp;
            <% end %>
            </div>
        </div>
    <% end %>
```


■ カスタムで実装する
テンプレート生成
```
rails g simple_calendar:views
```
ファイル作成される
```
create  app/views/simple_calendar
create  app/views/simple_calendar/_calendar.html.erb
create  app/views/simple_calendar/_month_calendar.html.erb
create  app/views/simple_calendar/_week_calendar.html.erb
```

■祝日などを独自に定義
app/helpers/holiday_helper.rb
```
module HolidayHelper
  def holiday_class(day, current_month)
      "holiday" #modelなどをよんで条件による実装など
  end
 end
```

app/views/simple_calendar/_month_calendar.html.erb
元ソースに holiday_class として追加した。 start_date.monthは選択されている月
```
            <%= content_tag :td, class: [calendar.td_classes_for(day), holiday_class(day, start_date.month)].compact.join(' ') do %>
```
元ソース
```
            <%#= content_tag :td, class: calendar.td_classes_for(day) do %>
```