OmniAICreator/Qiita-1.07M huggingface dataset:
【SwiftUI】AVFoundationを使って音を鳴らす

## はじめに
SwiftUIで、音を扱うことができるフレームワークである **『AVFoundation』** を利用してアプリ上で音を鳴らす方法について学習したので、内容をまとめます。

## 環境
【Xcode】16.2
【iOS】18.2
【macOS】Sequoia 15.3.1

## AVFoundationとは
Appleが提供するフレームワークの一つで、音声や動画の再生、録音、編集、ストリーミングなど、メディアコンテンツを扱うための機能を提供します。主に、iOSやmacOSアプリで音声・映像の処理を行う際に使用されます。

## AVFoundationを使って音を鳴らす処理を実装する流れ
1. Assets.xcassetsに、使用する音源ファイルを取り込む。
2. 音を鳴らすためのプログラムを記述するファイル（SoundPlayer.swift）を作成する。
3. SoundPlayer.swiftで **『AVFoundation』** を読み込む。
4. 音源データの読み込みとプレイヤーを宣言し、音を鳴らす処理を記述する。
5. 音を鳴らす処理を実装したいファイル（ContentView.swift）で、音を鳴らす処理を呼ぶ。

## 実装方法
### 1.Assets.xcassetsに、使用する音源ファイルを取り込む。
![スクリーンショット 2025-03-03 18.00.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/893a721f-368d-488d-a09b-5fd495cbaa5c.png)

Assets.xcassetsのフォルダに、使用する音源ファイルをドラッグ&ドロップで取り込みます。
ここではcymbalSoundという音源ファイルを取り込んでいます。

### 2.音を鳴らすためのプログラムを記述するファイル（SoundPlayer.swift）を作成する。
![スクリーンショット 2025-03-03 17.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/4252eb9e-e482-4108-b615-877e929d3d2e.png)

SwiftUIでは、画面を表示する部品と音などのプログラムを分けて作る必要があるので、新しく「SoundPlayer.swift」というファイルを作成します。
**command + N** のショートカットキーで、新しいファイルを作成することができます。
テンプレートは **Cocoa Touch Class** を選択します。

### 3.SoundPlayer.swiftで **『AVFoundation』** を読み込む。
![スクリーンショット 2025-03-03 17.53.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/d35ca385-be0e-48ef-a169-8b697dec2c3d.png)

音を扱うことができるフレームワークである **『AVFoundation』** を、
``` swift
import AVFoundation
```
で読み込みます。

### 4.音源データの読み込みとプレイヤーを宣言し、音を鳴らす処理を記述する。
![スクリーンショット 2025-03-03 18.02.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/d2b4c190-029e-4e14-aa78-455284c3b004.png)

まず、定数cymbalDataに音源データを格納します。
NSDataAssetが、Assets.xcassets内のファイルや画像を管理しているクラスです。
取り込んだ音源ファイル名（ここではcymbalSound）を指定し、ファイルの内容を取得します。
データは確実に存在しているため、「！」で強制アンラップしています。
続いて、AVAudioPlayerを利用して、シンバルを鳴らすインスタンス変数を用意しています。
**AVAudioPlayer** は音源ファイルを再生できるようにする機能です。

### 5.音を鳴らす処理を実装したいファイル（ContentView.Swift）で、音を鳴らす処理を呼ぶ。
![スクリーンショット 2025-03-03 19.11.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/c3ec7c0a-f831-42a2-9d1c-f54f138f2708.png)

ContentView.swift内でSoundPlayerを実行できるよう、
``` swift
let soundPlayer = SoundPlayer()
```
でインスタンス変数を用意します。
"シンバル"というボタンを押したらシンバルの音が鳴るように処理を実装します。
``` swift
soundPlayer.cymbalPlay()
```
と記述することで、SoundPlayer内のcymbalPlay()を実行します。

## まとめ
・AVFoundationは、音声や動画の再生、録音、編集、ストリーミングなど、メディアコンテンツを扱うための機能を提供するフレームワーク。
・画面を表示する部品と音などのプログラムは、ファイルを分けて作成する。
・import AVFoundationでAVFoundationフレームワークを読み込む。
atcoder_水色精進記録13_ABC222e

# Atcoder水色精進記録
ABC222
E - Red and Blue Tree
https://atcoder.jp/contests/abc222/tasks/abc222_e

# アルゴリズム・データ構造
BFS,DP

# 考察
AiからAi+1の最短経路の間に通る辺はBFSによって求めることが出来る。
各iについて上記を実施して、各辺がi=1-M-1までの通る回数をカウントしておく。

辺の通る回数がわかれば、辺を一つずつDPをすればいけそう。
DPとしては現在の辺i、現在までの赤色トータル分の配列で、格納する値は塗り方の個数
現在までの赤色トータル分のmax値は、BFSで求められるトータルの辺の個数なので
(M-1)*N→M\*N
DPのトータル計算量は
M\*(M\*N)=M\*\*2\*N

最終的に求めたい値は
R-B=KとなるDP[N-1][R]だが
R+B=S(BFSで求められる辺の個数の総和)
なのでR=(K+S)/2となる、Rが少数/0未満の場合は、組み合わせとしてあり得ない
S＝0となるinputもあるのでdpの配列外参照に注意が必要

# 提出
https://atcoder.jp/contests/abc222/submissions/63363539

# 感想
DPに配列外アクセスは注意すること。
このレベルの問題をコンテスト中に解けるようになりたい。
アフィン変換行列(2/4)「小座標→大座標」自作 def myAffine(C,D, E):

・sympyだと、普通？Pointの.rotate(angle, pt=None)でしょうか。作成未定。
https://docs.sympy.org/latest/modules/geometry/points.html#sympy.geometry.point.Point2D.rotate

:::note info
[4部作 アフィン変換行列](https://qiita.com/tags/%e3%82%a2%e3%83%95%e3%82%a3%e3%83%b3%e5%a4%89%e6%8f%9b%e8%a1%8c%e5%88%97) 上のタグと同じです。
:::

# sympyで
**・正三角形の2つの頂点A,B=map(Point,[(1,1),(3,3)])、第3の頂点を求める。**
```python
from sympy import *
import sympy as sp
from sympy.geometry import Point

def compute_transformation_matrix(A, B, C, D):
    """
    点A, Bの座標が点C, Dへ移動する際の2D座標変換行列（スケーリング・回転・平行移動）を求める関数
    
    引数:
        A, B : 移動前の2点（SymPyの Point オブジェクト）
        C, D : 移動後の2点（SymPyの Point オブジェクト）
    
    戻り値:
        transformation_matrix : 3×3の座標変換行列 (SymPy Matrix)
    """

    # 座標の取得
    x_A, y_A = A.coordinates
    x_B, y_B = B.coordinates
    x_C, y_C = C.coordinates
    x_D, y_D = D.coordinates

    # --- 1. スケーリング係数 sx, sy を計算（等方的スケール）---
    AB_length = sp.sqrt((x_B - x_A)**2 + (y_B - y_A)**2)  # |AB|
    CD_length = sp.sqrt((x_D - x_C)**2 + (y_D - y_C)**2)  # |CD|
    s = CD_length / AB_length  # スケール（sx = sy）

    # --- 2. 回転角 theta を計算 ---
    theta = sp.atan2(y_B - y_A, x_B - x_A) - sp.atan2(y_D - y_C, x_D - x_C)

    # --- 3. 平行移動 dx, dy を計算 ---
    dx = x_C - (s * sp.cos(theta) * x_A - s * sp.sin(theta) * y_A)
    dy = y_C - (s * sp.sin(theta) * x_A + s * sp.cos(theta) * y_A)

    # --- 4. 変換行列を作成 ---
    transformation_matrix = sp.Matrix([
        [s * sp.cos(theta), -s * sp.sin(theta), dx],
        [s * sp.sin(theta),  s * sp.cos(theta), dy],
        [0, 0, 1]
    ])

    return transformation_matrix

def transform_point(T, E):
    """
    変換行列Tを使って、点E(x_E, y_E)の新しい座標を求める関数

    引数:
        T : 3x3の座標変換行列 (SymPy Matrix)
        E : 変換前の点（SymPyの Point オブジェクト）

    戻り値:
        E' : 変換後の点（SymPyの Point オブジェクト）
    """

    x_E, y_E = E.coordinates
    E_h = sp.Matrix([x_E, y_E, 1])  # 同次座標 (x, y, 1)

    # 変換後の座標
    E_h_prime = T * E_h

    # 新しい座標を取得
    x_E_prime, y_E_prime = E_h_prime[:2]

    return Point(x_E_prime, y_E_prime)
# 
A,B=map(Point,[(1,1),(3,3)])
AB =A.distance(B)
T  =compute_transformation_matrix(Point(0,0),Point(AB,0),A,B)
print("#",transform_point(T, Point(Rational(1,2)*AB, Rational(1,2)*AB*sqrt(3))))
print("#",transform_point(T, Point(Rational(1,2)*AB,-Rational(1,2)*AB*sqrt(3))))
# 
print("#","-"*30) 
def myAffine(C,D, E):
    return transform_point(compute_transformation_matrix(Point(0,0),Point(C.distance(D),0),C,D),E)
A,B=map(Point,[(1,1),(3,3)])
AB =A.distance(B)
E  =Point(Rational(1,2)*AB,Rational(1,2)*AB*sqrt(3))
print("#",myAffine(A,B, E))
print("#",myAffine(A,B,-E))
# Point2D(sqrt(3) + 2, sqrt(3))
# Point2D(2 - sqrt(3), -sqrt(3))

# Point2D(sqrt(3) + 2, sqrt(3))
# Point2D(-sqrt(3), 2 - sqrt(3))
```

# 作図
・作成未定

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

# いつもと違うおすすめです。
Claude DesktopのMCPがうまくいかないとき

Mac環境でClaude DesktopのMCPを試そうとしましたが，npxコマンド周りでうまくいかずつまづいてしまった．
うまくいった方法をメモしておく．

# つまづいたこと
例えば，[公式](https://modelcontextprotocol.io/quickstart/user)や[この記事](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)を参考にすると，Node.jsをインストールした上で，

`~/Library/Application Support/Claude/claude_desktop_config.json`
の設定ファイルに，以下を書く．
```
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/username/Desktop",
        "/Users/username/Downloads"
      ]
    }
  }
}
```

しかし，Claude Desktopを再起動しても，エラーメッセージが出てうまくいかない．
`node -v`や`npm -v`で確認して，npmやNode.jsはインストールされているのだが．．．

# 解決方法
[この動画](https://www.youtube.com/watch?v=6TRv5pYyUzA)にあるように，nodeコマンドを使うと，うまくいった．

1. ライブラリをグローバルにインストール
    ```terminal
    npm i -g @modelcontextprotocol/server-filesystem
    ```
1. npxでなく，nodeを使うようにclaude_desktop_config.jsonファイルを書き換え
    ```
    {
      "mcpServers": {
        "filesystem": {
          "command": <which nodeコマンドで表示されるパス>,
          "args": [
            <1でインストールしたライブラリのパス>,
            "/Users/username/Desktop"
          ]
        }
      }
    }
    ```
    <which nodeコマンドで表示されるパス>は，自分の場合，
    ```"/Users/username/.nodebrew/node/v22.14.0/bin/node"```
    で，
    <1でインストールしたライブラリのパス>は，自分の場合，
    ```"/Users/username/.nodebrew/node/v22.14.0/lib/node_modules/@modelcontextprotocol/server-filesystem/dist/index.js"```
    でした．

1. Claude Desktopを再起動
Dockerによるrails環境構築の際につまずいたこと

<h3>
問題
</h3>
以下の記事を参考に環境構築をした際、service内のファイルを Windows 上の VS Code で保存しようとした際に、権限 (EPERM: operation not permitted) の問題が発生しました

https://qiita.com/crawling_cat/items/501fac2d7296f901f1f4


<h5>1. service ディレクトリの所有者とパーミッションを確認</h5>
まず、所有者と権限を確認します。

```
ls -ld ~/environment/service
ls -l ~/environment/service
```
出力を確認し、自分が所有者 (owner) になっているかを確認してください。
もし root など別のユーザーになっている場合、次の手順で変更が必要です。

<h5>2. service の所有者を変更</h5>
もし service の所有者が root などになっていた場合、以下のコマンドで自分に変更できます。

```
sudo chown -R ユーザー名:ユーザー名 ~/environment/hello_app
```
-R オプションをつけることで、hello_app 内のすべてのファイルの所有者を変更します。

<h5>3. service のパーミッションを変更</h5>
所有者を変更してもアクセスできない場合、パーミッションを適切に設定します。

````
sudo chmod -R 755 ~/environment/service
````
この設定では、所有者が読み書き・実行でき、他のユーザーは読み取りと実行のみ可能になります。
もし書き込み権限も必要なら、以下のように変更できます。
```
sudo chmod -R 775 ~/environment/service
````
<h5>4. sudo でアクセスできるか確認</h5>
もし、所有者変更やパーミッション変更ができない場合、sudo を使ってアクセスできるか確認します。

```
sudo ls -l ~/environment/service
```

このコマンドでファイルが表示される場合、権限の問題が確定しますので、上記の chown や chmod で修正してください。

<h5>5. Cloud9 環境の問題の可能性</h5>
もし AWS Cloud9 などのクラウド環境を使用していて、上記の変更が反映されない場合、Cloud9 の設定によって制限されている可能性があります。
その場合は、Cloud9 のターミナルを再起動するか、Cloud9 の設定を確認してください。

<h3>まとめ</h3>
<p>1. ls -ld ~/environment/service で所有者・権限を確認</p>
<p>2. sudo chown -R ユーザー名:ユーザー名 ~/environment/service で所有者を変更</p>
<p>3. sudo chmod -R 755 ~/environment/service で適切なパーミッションを設定</p>
<p>4. sudo ls -l ~/environment/service でアクセス可能か確認</p>
<p>5. 必要なら Cloud9 の設定やターミナルを再起動</p>
includes()で文字列検索をスッキリ解決！

Paizaの問題を解いていて、文字列検索でハマった話。includes() という便利メソッドがあるらしいけど、最初はゴリ押しで書いたらミス連発。結局、シンプルに includes() を使えば解決する話だった。

<br>❌ NGコード：無駄なループ & バグ
```js
const charA = lines[0]();
const stringS = lines[1].split('');

let found = false;
for (let i = 0; i < stringS.length; i++) {
    if (stringS[i] === charA) {
        found = true;
        break;
    }
}
console.log(found ? "YES" : "NO");
```
🚨 ループ不要 → includes() なら一発で判定
🚨 変数管理が面倒 → found いらない
🚨 コードが長い → 三項演算子でスッキリ

<br>✅ OKコード：スマートに解決！
```js
const charA = lines[0].trim();
const stringS = lines[1].trim();

console.log(stringS.includes(charA) ? "YES" : "NO");
```
✨ includes() で即判定！
✨ trim() でバグ防止！
✨ 三項演算子 (? :) で簡潔！

「特定の文字が含まれるか？」を判定するときは、迷わず includes() を使おう！🔥

<br>[僕の失敗談と解決話！](https://paizabeginner.wordpress.com/2025/03/03/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%9aincludes%e3%81%a7%e6%96%87%e5%ad%97%e5%88%97%e6%a4%9c%e7%b4%a2%e3%82%92%e3%82%b9%e3%83%83%e3%82%ad%e3%83%aa%e8%a7%a3/)
【PHP】array_filterで取得したいデータが取れない！！

## 何があったの？
array_filterでアホを炙り出そうとした時、
```php
$data = ['バカ', '天才', 'アホ', '秀才'];
$aho = array_filter($data, fn($o) => $o ?? '' === 'アホ');
print_r($aho); //結果 → ['バカ', '天才', 'アホ', '秀才']
```
自称アホが多すぎる、、、そんなはずはない。
原因は至って単純でした。
~~``$o ?? ''``の比較と``'' === 'アホ’``の比較では``'' === 'アホ’``が優先され結果全てに``false``が返った結果自称アホが多くなってしまったようです。~~

①``$o ?? ''``の比較と``'' === 'アホ'``の比較で、``'' === 'アホ'``が優先される。（比較の結果はfalse)
②``$o ?? false``で比較される。
③``$o``が``null``でない限り、``$o``がそのまま条件に（結果true)

これで全部の条件がtrueとなって返ってくるようです。

``??``を便利ツール的な立ち位置に錯覚してましたが、``===``と同じ演算子に変わりないので、注意が必要ですね、、、

~~ちなみに、
https://www.php.net/manual/ja/function.array-filter.php
array_filterの仕様で、フィルターにかける変数がfalseを返すもの(false, NULL, ''）は自動で削除してくれるみたい。。。~~
→これは明確に間違いで、第２引数に何も入れない場合に自動で消してくれるようです。
【例】
```php
$data = ['バカ', '天才', null, 'アホ', false, '秀才'];
const $aho = array_filter($data); // ['バカ', '天才', 'アホ', '秀才'];
```
第２引数を使う場合、条件の結果**true**のものが配列に格納されるので、自動で消してくれるのは今回は関係ないです。
``$o ?? ''``で気を利かせてましたが、``??``を入れなくてもエラーは出ないようです。
## 解決策
変に気を利かせなくてもいいみたい。
```php
$data = ['バカ', '天才', 'アホ', '秀才'];
$aho = array_filter($data, fn($o) => $o === 'アホ');
print_r($aho); //結果 → ['アホ']
```
無事、アホを炙り出すことに成功しましたね。（やったー😆）

## 追記
比較する値が配列だった場合は注意が必要です。
```php
<?php

$data = [
    ['title' => 'バカ'],
    ['title' => '天才'],
    ['title' => 'アホ'],
    null,
    ['title' => '秀才'],
];

var_dump(array_filter($data, fn($o) => ($o['title'] ?? '') === 'アホ'));

var_dump(array_filter($data, fn($o) => ($o['title']) === 'アホ'));
```
この場合()で括ってNULLチェックを入れないとエラーが出るようです！（実際にはこっちのパターンが多いのでわかって助かりました。。。）
``null``ではなく``['title' => NULL],``の時はNULLチェックはいらないですね。（この辺の概念難しい、、、セブンでファミチキ頼む〜みたいなのをXで見た気がする。。。）
[コメント参照](https://qiita.com/hayuse/items/ac4867ffaef66c96c404#comment-c4db6b8bba7c4458c515)
Terraform 入門：S3バケット"Warning: Argument is deprecated"の警告文を修正して作成してみた

## はじめに
Terraformを使ってAWS S3バケットを作成する際に、仕様変更によりエラーや警告が発生することがあります。

本記事では、その中でも `aws_s3_bucket` の `acl` 属性が非推奨になった警告の詳細と、修正方法について解説します。

## 書こうと思ったきっかけ
Terraformのバージョンアップに伴い、S3バケットの `acl` 属性が非推奨となり、新しいリソース `aws_s3_bucket_acl` を使用する必要が出てきました。

この変更に気づかずに既存のコードを適用すると警告が表示されるため、同じ問題に直面する人のために記事を書こうと思いました。

## 警告の内容
TerraformでAWS S3バケットを作成する際に、以下のような警告が発生することがあります。

```
│ Warning: Argument is deprecated
│
│   with aws_s3_bucket.example,
│   on main.tf line 7, in resource "aws_s3_bucket" "example":
│    7:   acl    = "private"
│
│ Use the aws_s3_bucket_acl resource instead
│
│ (and one more similar warning elsewhere)
```

この警告は、Terraformのバージョンアップにより `aws_s3_bucket` リソース内の `acl` 属性が非推奨になったことによるものです。代わりに `aws_s3_bucket_acl` リソースを使用する必要があります。

## 修正方法

### 修正前のコード

```hcl
resource "aws_s3_bucket" "example" {
  bucket = "my-example-bucket"
}

resource "aws_s3_bucket_acl" "example_acl" {
  bucket = aws_s3_bucket.example.id
  acl    = "private"
}
```

### 修正後のコード

```hcl
resource "aws_s3_bucket" "example" {
  bucket = "my-example-bucket"
  force_destroy = true
}

resource "aws_s3_bucket_ownership_controls" "example" {
  bucket = aws_s3_bucket.example.id

  rule {
    object_ownership = "BucketOwnerEnforced"
  }
}
```

### 修正のポイント
1. `aws_s3_bucket_acl` リソースを削除し、新しい `aws_s3_bucket_ownership_controls` リソースを使用。
2. `object_ownership = "BucketOwnerEnforced"` を設定して、ACL を不要にする。
3. `force_destroy = true` を追加し、削除時の管理を簡単に。

## 修正後の適用手順
修正後のTerraformコードを適用するには、以下のコマンドを実行します。

```sh
terraform init
terraform plan
terraform apply
```

`terraform apply` 実行時に `yes` を入力すると、修正後の設定が適用されます。

**実際のターミナル画面**

![Screenshot 2025-03-03 at 18.20.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/ed1b8ea0-c1a4-449e-b411-d717acfa8a7c.png)

## まとめ
Terraformの新しい仕様に対応するため、S3バケットのACL設定を削除し、`aws_s3_bucket_ownership_controls` を使用することで、最新のTerraformのベストプラクティスに準拠した構成が可能になります。
ABテストの結果を意思決定者に報告する（ECサイトの商品ページ改善）

# はじめに
今回は、「ChatGPTに意思決定者に説明する時のロープレ台本を作らせてみた」の第2弾になります。

第1弾はこちら↓

https://qiita.com/UKI_datascience/items/2ff34d7a51997df701e3

データ関連に明るくない田中部長に対して、ECサイトの商品ページに関するABテストの結果を、データアナリストの鈴木さんが報告しています。
※この記事は、ChatGPTの出力を基に作成しています。

---

# 登場人物（架空）
- 田中部長：EC事業部の部長であり、こんかいのしさくにおけ意思決定者。
- 鈴木さん：データアナリスト。できるだけ分かりやすく説明したい。

---

**👨‍💼 意思決定者（EC事業部 部長・田中）**  
「鈴木さん、今回のABテストの結果はどうだった？」  

**📊 データアナリスト（鈴木）**  
「はい、今回は **商品ページの購入ボタンの色** を変更した場合の影響を検証しました。  
Aパターン（従来の青色ボタン）とBパターン（目立つオレンジ色ボタン）を比較したところ、Bパターンの方が **購入率が12%向上** しました。」  

**👨‍💼 田中**  
「購入率が12%向上…それって、売上にどれくらい影響があるんだろう？」  

**📊 鈴木**  
「今回のテスト対象は **サイト全体の30%のユーザー** で、1週間のデータを見たところ、Bパターンの購入率が **3.5%から3.92%に改善** しました。  
もしサイト全体に適用した場合、**月間売上が約240万円増加する** と見込まれます。」  

**👨‍💼 田中**  
「おお、結構な額だね。でもこれは統計的に信頼できる数字なの？」  

**📊 鈴木**  
「はい、統計的な有意差を検定したところ、**p値は0.03** でした。これは、偶然ではなく **97%の確率でこの変更が効果的** だったと判断できます。」  

**👨‍💼 田中**  
「なるほど、結構信頼できるデータだね。でも、オレンジ色のボタンに変更することで何かリスクはあるの？」  

**📊 鈴木**  
「はい、一部のユーザーからはデザインが派手すぎると感じられる可能性があります。そのため、**まずはトラフィックの50%に適用して、1ヶ月間モニタリングしながら全体展開を決める** 方法がリスクを抑える上で有効です。」  

**👨‍💼 田中**  
「なるほど、じゃあまずは50%に適用して様子を見ようか。モニタリングの結果をまた報告してくれる？」  

**📊 鈴木**  
「承知しました！ 1ヶ月後にデータを分析して、最終判断の材料をご提供します。」
PHPで「if文」の動作を確認してみた。

# 概要

PHPで「if文」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/php/if/index1.html

# 実装

以下のファイルを作成しました。

```sample.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
<?php
$old = 25;

if ($old >= 20){
  print '年齢は20歳以上です';
}
?>
</p>

</body>
</html>
```

以下のコマンドを実行しました。

```
$ php sample.php 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
年齢は20歳以上です</p>

</body>
</html>
```

# まとめ

何かの役に立てばと。
C#でAIをローカルで動かして会話するまでに躓いたこと

# はじめに
本記事は「[中年男は電気彼女の夢を見る](https://ai.3ddoghouse.com/%E7%B0%A1%E5%8D%98%E3%81%AA%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0/)」というブログで解説されている，C#でのローカルAIチャットボットの作り方を筆者が実践し，躓いた点を記事にしようというものです．大変わかりやすい記事でした．[そちらの記事](https://ai.3ddoghouse.com/%E7%B0%A1%E5%8D%98%E3%81%AA%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0/)を読んでいただいたうえで，以下の内容を見てください．

# プロジェクトにパッケージをインストール
ブログに掲載されているサンプルコードを動かすには，LLamaSharp と LLamaSharp.Backend.Cpuというパッケージをインストールする必要があります．ここで筆者はまず躓きました．

筆者は普段からvisual studio 2019を使用しているのですが，visual studio 2019には，LLammaSharpに必要な「Microsoft.Extensions.AI」が無いのです．

それをnugetする必要がありますが，プレリリース扱いになっているので，そのチェックボックスにチェックを入れて検索しなければなりません．

# サンプルコードを最新バージョンに対応させる
最新のLLamaSharpではInferenceParamsのメンバの構成が変わっているようです．該当箇所を以下の様に書き換えてください．
```
InferenceParams infPara = new()
{
    SamplingPipeline = new DefaultSamplingPipeline
    {
        Temperature = 0.6f
    },
    AntiPrompts = new List<string> { "User:" }
};
```

# メインにふさわしいファイルをロードする
筆者は「.gguf」ならなんでもいいんやろ，と思ってmmprojモデルを指定していました．
だめです．
mmprojって書いてないggufをメインに用意してください．
私は hugging face から良さげなものをダウンロードしました．
Anthropicの新技術：Hybrid Reasoning AI Modelとは？

# 🚀 **Anthropicの新技術：Hybrid Reasoning AI Modelとは？** 🧠
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917980/65d8a64c-3cf6-438b-ade6-82442b6dd25f.png)

人工知能（AI）の進化は目覚ましく、特に大規模言語モデル（LLM）の開発は急速に進んでいます。その中でも、**Anthropicが発表した最新の「Hybrid Reasoning AI Model（ハイブリッド推論AIモデル）」** は、従来のAIとは一線を画す技術革新です。🧐

本記事では、この新しい技術の特徴、仕組み、利用方法、そして具体的なコードサンプルを交えて解説します！💡

---

## **🌟 Hybrid Reasoning AI Modelとは？**

AnthropicのHybrid Reasoning AI Modelは、**本能的な推論（Intuitive Reasoning）と論理的な推論（Deliberative Reasoning）を組み合わせたAIモデル**です。従来のLLMでは、質問に対する直感的な回答を素早く出すことができるものの、論理的な思考や深い推論には限界がありました。

この新しいAIは、 ✅ **直感的な素早い回答が可能（本能的推論）** ✅ **深い分析や思考が必要な場合は詳細な推論を行う（論理的推論）** ✅ **ユーザーが推論のレベルを調整可能** ✅ **「Scratchpad（メモ帳）」機能でAIの思考プロセスを可視化**

という特長を持っています。

**要するに、ユーザーが求める「速さ」と「精度」のバランスを自由に調整できるAI** なのです！

---

## **🛠️ 仕組み：本能的推論 vs. 論理的推論**

### **1️⃣ 本能的推論（Intuitive Reasoning）**

直感的な推論は、AIが最小限の処理時間で迅速に回答を生成するプロセスです。

- ✅ FAQや簡単な質問への応答
- ✅ 一般的な知識に基づく即答
- ✅ 簡単な判断が求められるケース

**例:**

```python
question = "2025年のオリンピック開催地は？"
response = hybrid_ai_model.answer(question, reasoning_level="fast")
print(response)
```

🟢 **出力:**

```
2025年のオリンピックはフランス・パリで開催されます。
```

### **2️⃣ 論理的推論（Deliberative Reasoning）**

論理的推論は、AIがより複雑な質問や意思決定を行う際に用いるプロセスで、時間はかかるものの、より深い分析や論理的な検討を行います。

- ✅ 複雑な議論や計算が必要な問題
- ✅ 証拠や根拠に基づく詳細な推論
- ✅ 計画立案や意思決定サポート

**例:**

```python
question = "AIの倫理的課題とその解決策を述べよ。"
response = hybrid_ai_model.answer(question, reasoning_level="deep")
print(response)
```

🔵 **出力:**

```
AIの倫理的課題には、バイアス、プライバシーの侵害、説明可能性の欠如などが含まれます。
解決策として、
1. 公開されたデータセットの透明性向上
2. AI倫理ガイドラインの制定
3. 人間による監視の強化
が考えられます。
```

---

## **💻 使い方：Anthropic Hybrid Reasoning AIの実装**

このAIモデルは、AnthropicのAPIを通じて利用できます。

### **🔹 1. インストール**

まずはAPIクライアントをインストールします。

```bash
pip install anthropic
```

### **🔹 2. APIキーの取得**

Anthropicの公式サイトでAPIキーを取得し、環境変数に設定します。

```bash
export ANTHROPIC_API_KEY="your_api_key_here"
```

### **🔹 3. 基本的な使用方法**

以下のPythonコードで、Hybrid Reasoning AIを使って質問に応答させます。

```python
import anthropic

# APIクライアントの初期化
client = anthropic.Client(api_key="your_api_key_here")

def ask_hybrid_ai(question, reasoning_level="fast"):
    response = client.completions.create(
        model="claude-3.7-hybrid",
        prompt=f"質問: {question}\n推論レベル: {reasoning_level}",
        max_tokens=300
    )
    return response.text

# テスト実行
print(ask_hybrid_ai("AIの未来について論じてください。", reasoning_level="deep"))
```

---

## **📊 どのような場面で活用できるのか？**

### **1️⃣ 企業の意思決定サポート**

経営戦略や市場分析のレポート生成に活用し、迅速な意思決定をサポート。

### **2️⃣ AIによるカスタマーサポート**

簡単なFAQは本能的推論、高度な問い合わせは論理的推論で対応。

### **3️⃣ 研究・教育分野**

学生の質問に素早く回答し、詳細な説明を提供。

---

## **🎯 まとめ：AnthropicのHybrid Reasoning AIがもたらす未来**

✅ **直感的な即時回答と、詳細な論理的推論のハイブリッドAI！** ✅ **ユーザーが「推論のレベル」を調整可能で、柔軟な応用が可能！** ✅ **企業、教育、カスタマーサポートなど、多くの分野で活用が期待される！**

この技術の登場により、AIとの対話がよりスムーズで、より高度な意思決定が可能になるでしょう。🚀

あなたは、この技術についてどう思いますか？ **コメントで意見を聞かせてください！😊**
3DCGのBend機能を実装する

![loop2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/75e90676-1eea-43d6-b623-7929dd3c4cbf.gif)

# はじめに
3DCGにおいて、変形させる機能をdeformerと呼んだりします。その中で、「曲げ」Bendツールをプログラムした話です。chatGPT利用。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/14ce4fbf-a573-47a4-a646-d1cd9cc59ea7.png)

# 環境
Processing 4

# アルゴリズム
点P(x,y)をbend関数でθ曲げることを考えます。

Bend変形のカギとなるのは、x座標を円周上の角度にマッピングすることです。

Bend適用前のグリッド全体の長さをL、bend角度をθとしたとき、円弧上での対応する角度θxは次式であらわすことができます。
```math
\theta_x=\frac{\theta}{L}x
```
次に、yを円弧の半径へマッピングします。円の基準半径をRとし、点Pの半径をrとし次式を定義します。
```math
r=R+y
```
bend変形後の座標をP(x',y')とすると、
```math
x'=r\sin(\theta_x)
```
```math
y'=R-r\cos(\theta_x)
```
となる。
このとき、
```math
\sin(\theta_x)は円周方向の移動を表し、
```
```math
\cos(\theta_x)は円の高さの変化を表す。
```
最終的な変換式は、以下となる。
```math
x'=(R+y)\sin(\frac{\theta}{L}x)
```
```math
y'=R-(R+y)\cos(\frac{\theta}{L}x)
```

# プログラム

```java
int gridWidth = 32;  // X方向の点の数
int gridHeight = 6; // Y方向の点の数
float cellSize = 20; // 格子のサイズ
float length = gridWidth * cellSize;  // グリッドの全長
PVector[][] originalGrid = new PVector[gridWidth+1][gridHeight+1];
PVector[][] bentGrid = new PVector[gridWidth+1][gridHeight+1];
float bendAngle;  // 曲げ角度（度）

void setup() {
  size(600, 600);
  generateGrid();
}

void draw() {
  background(255);
  translate(width / 2, height / 2);  // 画面中央に配置

  // ベンド処理
  applyBend(bendAngle);

  // 曲げた後のグリッドを描画（黒）
  stroke(0);
  drawGrid(bentGrid);

  // 角度を変化させてアニメーション
  bendAngle = 360*sin(frameCount*0.01);

}

// **長方形のグリッドを作成**
void generateGrid() {
  for (int x = 0; x <= gridWidth; x++) {
    for (int y = 0; y <= gridHeight; y++) {
      float posX = (x - gridWidth / 2) * cellSize;   // 中心を0にする
      float posY = (y - gridHeight / 2) * cellSize;  // 中心を0にする
      originalGrid[x][y] = new PVector(posX, posY);
    }
  }
}

// **Bend処理**
void applyBend(float angle) {
  float theta = radians(angle);
  float R = (theta != 0) ? length / theta : Float.POSITIVE_INFINITY;  // 曲げる半径

  for (int x = 0; x <= gridWidth; x++) {
    for (int y = 0; y <= gridHeight; y++) {
      PVector p = originalGrid[x][y];

      // **X軸方向の回転角（円周上の位置）**
      float localAngle = p.x*theta/length;

      // **Y軸方向の半径変化（各層が均等にカーブする）**
      float r = R + p.y;  // 層ごとに異なる半径

      // **円弧上に変換**
      float newX = r * sin(localAngle);
      float newY = R - r * cos(localAngle);  // 円の中心基準に配置

      bentGrid[x][y] = new PVector(newX, newY);
    }
  }
}

// **グリッドを描画**
void drawGrid(PVector[][] grid) {
  for (int x = 0; x <= gridWidth; x++) {
    for (int y = 0; y <= gridHeight; y++) {
      PVector p = grid[x][y];
      ellipse(p.x, p.y, 3, 3);

      if (x > 0) {
        PVector prevX = grid[x - 1][y];
        line(prevX.x, prevX.y, p.x, p.y);
      }
      if (y > 0) {
        PVector prevY = grid[x][y - 1];
        line(prevY.x, prevY.y, p.x, p.y);
      }
    }
  }
}
```

https://dl.acm.org/doi/pdf/10.1145/800031.808573
Terraform 入門："Failed to load plugin schemas"エラーをM1 Macで解決する方法について解決してみた

## はじめに
M1 MacでTerraformを実行すると、エラーが発生したり、発生しなかったりと原因が分からず、非常に困っていました。

:::note alert
***特に、同じ環境で何度か試してもうまく動く時と動かない時があり、再現性が低いため原因特定が難しかったです。***
:::

そんな状況の中、解決策を見つけることができたので、同じように困っている方の参考になればと思い、この記事を書くことにしました。

## 発生したエラー
M1 MacでTerraformを実行した際に、以下のエラーが発生しました。

```sh
 ~/Desktop/terraform-aws   terraform apply
╷
│ Error: Failed to load plugin schemas
│
│ Error while loading schemas for plugin components: Failed to obtain provider
│ schema: Could not load the schema for provider
│ registry.terraform.io/hashicorp/aws: failed to instantiate provider
│ "registry.terraform.io/hashicorp/aws" to obtain schema: timeout while waiting
│ for plugin to start..
╵
```

## 解決方法
結論から申し上げますと、以下の環境変数を設定することでエラーが解消されました。

```sh
export GODEBUG=asyncpreemptoff=1
```

### zshを利用している場合の設定方法
以下の手順で環境変数を設定してください。

1. `~/.zshrc` に以下の1行を追加します。
   
   ```sh
   export GODEBUG=asyncpreemptoff=1
   ```

2. 変更を適用するために、以下のコマンドを実行します。
   
   ```sh
   source ~/.zshrc
   ```

## まとめ
M1 Mac環境でTerraform実行時に「Failed to load plugin schemas」エラーが発生した場合、`GODEBUG=asyncpreemptoff=1` を環境変数に設定することで解決できます。

TerraformがM1 Macのネイティブ環境で動作する際に、Goランタイムの非同期プリエンプション機能が影響を及ぼすことがあるため、この設定を行うことで安定して動作するようになると思っています。

***同様の問題に遭遇した場合は、ぜひ試してみてください！***

## 参考文献

https://zenn.dev/bun913/articles/m1-mac-terraform-unstable

https://github.com/hashicorp/terraform/issues/27350#issuecomment-751213404

https://github.com/hashicorp/terraform/issues/27350#issuecomment-751269666
【Automate/Office スクリプト】SharePointリストのデータをExcelの表に行追加したい[25年3月時点]

# 【概要】PowerAutomateとExcelスクリプトでSPOリストを取得
SharePointリストのデータを取得し、シェアポイントのドキュメントにあるExcel(Online)ファイルのテーブルに流しこみたい。
(できるだけ、早い処理)

他のやり方として、シェアポイントリストのデータを取得してAutomateのExcelコネクタの「表に行を追加」を使う方法もあるけど、処理時間がかかりすぎて使い物になりませんでした。

## 1.SharePointのリストの用意
シェアポイントのサイトコンテンツに新規でリストを作成してください。
今回のサンプルとしては、
・No.(数値) 
・名称(Title:テキスト)
・類別(テキスト)
の3つの列名です。この辺りは任意の列名、列の種類を設定ください。

## 2.SharePointドキュメントにExcel作成
シェアポイントのドキュメントにExcelファイルを作成。
シート名は「sheet1」
テーブルも作成しておく。
今回だと、例としてテーブル名「table1」

## 3.Excelにスクリプト記述

```typescript:ImportData
function main(workbook: ExcelScript.Workbook,
    arrayfromflow: arrayofdata[], sheetName: string,
    tableName: string) {

    // Automateからシート名を受け取る
    let sheet = workbook.getWorksheet(sheetName);
    // Automateからテーブル名を受け取る
    let existingTable = workbook.getTable(tableName);


    //JSON文字列をオブジェクトに変換。
    let parsedArray: object[] = (typeof arrayfromflow === "string") ? JSON.parse(arrayfromflow) : arrayfromflow;


    // 配列を行データとして成形
    let formattedRows = parsedArray.map(item =>
        [item["No."], item["名称"], item["類別"]]
    );

    // 既存のテーブルにデータを追加
    existingTable.addRows(0, formattedRows);
}

// データ型（インターフェース）定義
interface arrayofdata {
    No: number,       // No.(文字列)
    Name: string, // 名称(文字列)
    Category: string, // 類別(文字列)
}
```



## 4.Automateのフロー作成
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10433/eeaaf0fc-c25a-4ebd-b02d-7cb18e3d9181.jpeg" alt="Automateのフロー">


 **①[PowerApps]トリガー** 
Power Apps(V2)
↓↓↓

 **②[SharePoint]複数の項目の取得**
サイトのアドレス：任意のサイトを選択してください。
リスト名：SharePointのリスト名を選択してください。
↓↓↓

 **③[データ操作]選択**
開始：(複数の項目の取得)欄から valueを選択。

マップ：出力したい項目に応じて設定・紐づけしてください。
キー：Excel側のテーブルの列名
値：(複数の項目の取得)欄から紐づけたい値を選択。
※注意として、●● Valueってのが時々あります。
　それは、シェアポイントリストの列が選択式形式の場合は
　●●valueを選んでください。
↓↓↓

 **④[Excel Online]スクリプトの実行**
場所：任意のSharePointのサイトを選択してください。
ドキュメントライブラリ：Excelが保存されてるとこ。自動で表示されるの選択。
ファイル：上記のドキュメントライブラリ以降のFull Pathを記述。
/エクセル名.拡張子
スクリプト：上記を選択すると、選べるようになる。

下記は、スクリプトに渡す引数。
スクリプト側に記述してあれば、上記のスクリプト選択後に入力できます。

arrayfromflow：アレイ全体の入力に切り替えて、
(選択)で取得した出力を選ぶ。
sheetName：Excelの任意のワークシート名を記述。例：sheet1
tableName：Excelの任意のテーブル名を記述。例：table1

## 以上です。
2025年3月 AIOps 定点観測

# 概要
AIOps の動向や学習のため、Google で AIOps を検索した結果を記録している記事です。

# 2025年3月3日の検索結果 (広告(スポンサー))

![スクリーンショット 2025-03-03 165402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/e59f382f-32d0-454c-8db2-33c7d7ec12f8.png)


* クロス・マーケティング
* hightech-armenia
* インターネットアカデミー
* VALT JAPAN株式会社

今月はどうしちゃったんでしょうか？ まったくしらない企業が表示されています。

先月の結果はこちら --> [2025年2月 AIOps 定点観測](https://qiita.com/mkodera/items/49e891c9d5373f61dbd4)



# 2025年3月3日の検索結果 (広告以外)

![スクリーンショット 2025-03-03 165435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/a40ec422-36ce-461a-840a-795e90d24857.png)


* HPE
* AWS
* IBM
* 日立ソリューションズ・クリエイト


今月は HPE が TOP で、AWS と IBM が続いています。

先月の結果はこちら --> [2025年2月 AIOps 定点観測](https://qiita.com/mkodera/items/49e891c9d5373f61dbd4)
カオス・コーディングとは何か

Grok3に"What is "chaos coding" in terms of software development in 2025 based on AI coding assistant and agents?"と質問した回答をDeepLで翻訳したものを備忘録として下記に貼り付けておく：

2025年のソフトウェア開発、特にAIコーディングアシスタントやエージェントの影響における「カオスコーディング」とは、開発者が最小限の構造や事前定義されたルールで高度なAIツールの力を活用する、プログラミングへの創発的で実験的なアプローチを指す。

AI主導型開発の進化する状況や、Xへの投稿で表明された感情に基づくと、開発者がコーディングアシスタントや自律エージェントなどのAIシステムに漠然とした、あるいは高レベルのプロンプトを提供し、満足のいく結果が現れるまで、人間の介入をほとんど行わずにコードを反復的に生成、改良、拡張させるプロセスとして理解できる。

このパラダイムでは、AIコーディングアシスタント（GitHub Copilot、Cursor、Amazon Q Developerなど）やエージェント（Devin AIやReplit Agentなど）がより積極的な役割を担い、自然言語を解釈し、膨大なコードベースから学習し、複雑なタスクを自律的に実行する能力により、しばしば予期せぬ、あるいは創造的なソリューションを生み出す。

この 「カオス 」は、コーディング・プロセスに対する従来の厳格なコントロールを放棄することに起因する。つまり、詳細な仕様や段階的な監視を避け、AIに 「任せる 」ことを優先するのだ。開発者はシンプルなアイデアから始め、「続ける」と言ったり、設定を切り替えたりして（例えば、Cursorのようなツールの「Yoloモード」）、AI主導の生成の予測不可能性と反復性を受け入れながら、出力を繰り返し洗練させていくかもしれない。

2025年までに、このアプローチは、様々な情報源で強調されているAIツールの能力によって増幅される。例えば、CodeGPTやAmazon Qのようなエージェントは、コードの記述、デバッグ、テスト、さらにはデプロイといった複数ステップのタスクを自律的に処理することができ、TabnineやCodyのようなアシスタントは、コードベース全体にわたってリアルタイムでコンテキストを認識した提案を提供する。

カオス・コーディングは、これらの進歩を活用し、当初は正確さよりもスピードと実験を優先し、カオスな初期出力を機能的なソフトウェアに適応させ洗練させるAIの能力に頼る。これは、構造化された開発から、より流動的で探索的なプロセスへのシフトであり、最小限の人間のガードレールで複雑性をナビゲートするAIの能力への信頼の高まりを反映している。

しかし、この方法に課題がないわけではない。厳密なガイドラインがないため、開発者は実行可能な解決策を見つけるために反復をふるいにかける必要があり、また、ジェネレーティブAIツールをめぐる議論で指摘されているように、「幻覚」（AIが正しくないコードや無関係なコードを生成すること）のリスクもある。

それでも2025年、カオス・コーディングは、ソフトウェア開発をより直線的でなく、よりダイナミックな技術に変えるAIの可能性を大胆に受け入れることを意味する。Xへの投稿は、この時代のAI支援コーディングの興奮と野性的で未知の性質を反映し、この用語と考え方が支持を集めていることを示唆している。

DeepL.com（無料版）で翻訳しました。

Grokの英語回答は以下リンク：
https://grok.com/share/bGVnYWN5_e60d2f48-c467-43b1-987e-b3841f547d12
Ubuntu24 Hyper-vのコンソールを xrdp と統合して使用する 拡張セッション使えずに困っている人へ

Hyper-V コンソールで拡張セッションが有効にならず、リモートディスクトップ接続していたが、もっと楽な方法はと探していたら Hyper-V コンソールと xrdp を統合する方法があった。  

Hyper-V コンソールが xrdp 経由でログインすることができるようになる。  

**１か月ほど使ったけれど、いまいち安定しないケースがある。原因がわからない。同じOSでも安定しているのとしていないのに分かれる。今のところ素直にリモートディスクトップ接続の方が精神安定上良いとおもう。**

## ゲスト側（Ubuntu）

### xrdp をインストール

```bash
sudo apt update
sudo apt install xrdp xorgxrdp
sudo vim /etc/xrdp/xrdp.ini
port=3389
↓
# vsock でホスト側（拡張セッション側 HvSocket）からの通信を 3389 ポートで待ち受ける（おそらく）
port=vsock://-1:3389

# xrdp 有効化
sudo systemctl enable xrdp

# xrdp 再起動
sudo systemctl restart xrdp

# シャットダウン
sudo shutdown now

```

## ホスト（Windows側）
以下のコマンドで拡張セッションを有効にすることで RDP を使えるようになる  
Set-VM -VMName <作成した仮想マシン名> -EnhancedSessionTransportType HvSocket    
作成した仮想マシン名は、Hyper-V マネージャー画面の仮想マシンの名前  

### powershell を管理者で開きコマンド実行
変更前の設定確認  
```powershell
(Get-VM -VMName "ubuntu24_test").EnhancedSessionTransportType

VMBus
```
設定変更  
```powershell
Set-VM -VMName ubuntu24_test -EnhancedSessionTransportType HvSocket
```
変更後の確認  
```powershell
(Get-VM -VMName "ubuntu24_test").EnhancedSessionTransportType

HvSocket
```
元に戻す場合  
```powershell
Set-VM -VMName ubuntu24_test -EnhancedSessionTransportType VMBus
```

## Hyper-V で Ubuntuを起動する

Ubuntu を起動すると画面設定のポップアップが表示されるのでお好みのサイズ（1920*1080）に指定して「接続」をクリック。  

Session: Xorg  
username: 作成したUbuntuのユーザ名  
password: 作成したUbuntuユーザのパスワード  

でログインする。


## ディスクトップ環境を Gnome-Shell にしたい場合

ディスクトップ環境を Gnome-Shell にしたい場合は、ログイン後に画面の左上をクリックして　メニュー＞端末　をクリックし以下を xrdp の設定を変更する  

この2行を追加する  
export GNOME_SHELL_SESSION_MODE=ubuntu  
export XDG_CURRENT_DESKTOP=ubuntu:GNOME  

```bash
sudo vim /etc/xrdp/startwm.sh

#!/bin/sh
# xrdp X session start script (c) 2015, 2017, 2021 mirabilos
# published under The MirOS Licence

# Rely on /etc/pam.d/xrdp-sesman using pam_env to load both
# /etc/environment and /etc/default/locale to initialise the
# locale and the user environment properly.

# 先頭に追加
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_CURRENT_DESKTOP=ubuntu:GNOME

if test -r /etc/profile; then
        . /etc/profile
fi

```
以上
学習記録　その2


### **学習テーマ:**

Swift, SwiftUI、GitHub

### **使用した教材:**

Swiftful Thinking (YouTube)


 ✏️ 学んだこと
 --
Github の使い方

- Github のリポジトリをクローンするやり方と作成のしかた
- Github のコミットの仕方
- Github のステージングの仕方
- Githubの**Stage, Unstage, and Stash のやり方**
- Githubの**Push and Pull の仕方**
- Githubの**Branches and Merge のやり方**
- Githubの**Pull Requestsのやり方**

### Swift UI とSwift の学習

- **Swift UI のTextの使い方(font size, font weight)**
- **Swift UI のshapesの使い方(Rectangle, RoundedRectangle, Circle, Ellipse  と Capsule)**
- **Swift UI のColorの使い方**
- **Swift UI のLinear Gradients, Radial Gradients and Angular Gradientsの使い方**
- **Swift UI のImage基礎の使い方**
- **Swift UI のFrames と Alignments の使い方**
- **Swift UI のFrames と Alignments の使い方**
- **Swift UI のBackgrounds と Overlaysの使い方**
- **Swift UI のVStack, HStack, と ZStack の使い方**
- **Swift UI の Padding 使い方**
- **Swift UI のSpacerの使い方**
- **Swift UI のLazyVGrid, LazyHGridの使い方**
- **Swift UI のignoresSafeArea()と.ignoresSafeArea(edges: )の使い方**
- **Swift UI のScroll Viewの使い方**
- **Swift UI のButtons基礎の使い方**
- **Swift UI のSubviewの使い方**
- **Swift UI の@Bindingの使い方**
- **Swift UI のif else (論理演算子)の使い方**
- **Swift UI のTernary Operators(三項演算子)の使い方**
- Swift UI の **Animations　基礎 の使い方**
- Swift UI の Linear Animation とSpring Aniamtionの使い方
- Swift UI の**Transitionの使い方**
- Swift UI の**Sheets 使い方**
- Swift UI の **NavigationView and NavigationLink使い方**
- Swift UI の edit, move, add,や deleteの基礎の使い方
- Swift UI の Alert の使い方
- Swift UI の**TextFieldの使い方**
- Swift UI のToggle の使い方
- Swift UI のPickerとPickerStyle の使い方
- Swift UI の Color Pickerの使い方
- Swift UI の Data Pickerの使い方
- Swift UI の Stepの使い方
- Swift UI の Sliderの使い方
- Swift UI の TabViewの使い方
- Swift UI のDarkModeの使い方
- Swift UI の OnAppearとOnDissapearの使い方
- Swift UI の**Tap Gestureの使い方**
- Swift UI の@ObservableObject and @StateObject の使い分け
- Swift UI の@EnvirormentObjectの使い方
- Swift UI の **Button styles, border shapesの使い方**
- Swift UI の .swipeActionsの使い方
- Swift UI の Badgeの使い方
- Swift UI の**@FocusStateの使い方**
- Swift UI のonSubmitの使い方
- Swift UI のNavigationStack の使い方
- Swift UI のToolBarの使い方
- Swift UI のGroupの使い方
- Swift UI のMenuの使い方
- Swift UI のPopoverの使い方
- Swift UI のGridの使い方
- Swift UI のControl Groupの使い方
- SwiftUI を使って小さなアプリを作る
- GitHub を活用してプロジェクト管理を実践する

---

### **学び・反省点**

💡 **学び**

今回は SwiftUI の基礎をしっかり学ぶことができた。特に、レイアウト関連（VStack、HStack、ZStack など）やアニメーション、ナビゲーションの使い方を体系的に学べたのは大きな収穫だった。また、GitHub の基本的な操作も身につけられたことで、コード管理やチーム開発の準備が整ってきたと感じる。

⚠️ **反省点**

学習内容が多かったため、インプットに偏ってしまいがちだった。実際に小さなアプリを作ってアウトプットする時間が少なかったので、今後はただインプットするだけではなく、学んだことを活かして実際にコードを書き、手を動かすことを意識したい。また、GitHub の操作も基本的な使い方は理解できたが、実際のプロジェクトでどのように活用するかがまだ曖昧なので、実践を通して理解を深める必要がある。

---

### **今後の予定**

🎯 **目標**

- SwiftUI を使って小さなアプリを作る
- GitHub を活用してプロジェクト管理を実践する
- ポートフォリオの作成

📌 **行動計画**

- 小さいアプリを作る際にGitHub を使ってコード管理を行い、定期的にコミット＆プッシュを実践
- SwiftUI のアニメーションやジェスチャーを活用した UI の作成に挑戦する
- 反復復習

---

### 振り返り

今回は SwiftUI の基礎をしっかり学べたことで、アプリ開発のイメージが具体的に持てるようになった。特に Swiftful Thinking の動画は分かりやすく、学習の助けになった。またインプットだけでなくアウトプットを意識し、実際にアプリを作ることで理解を深めたい。また、GitHub の活用も積極的に行い、実践的な開発の流れを身につけていきたい。
学習記録　その1


### **学習テーマ:*

Swift, SwiftUI

### **使用した教材:**

Udemy, Swiftful Thinking (YouTube)

---

### **🔍 学習内容**

### **✏️ 学んだこと**

- `HStack`, `VStack`, `ZStack` の基本的な使い方
- `Spacer` の役割とレイアウト調整
- `TextField` の使い方
- `If Statements` の基礎
- `Variables and Constants`（変数と定数）
- `Arrays`（配列）の基本操作（追加・削除）
- `For Loops` と `While Loops` の違い


- Swift 基礎の徹底学習へ移行
- `Bool`, `String`, `Int` のデータ型
- `Variables and Constants`（値の上書き可/不可）
- `Operators`（演算子）
- `If Statements` と `Operators` の組み合わせ
- `Function`（関数）の基礎
- `Optional`（オプショナル）の使い方と安全なコードの書き方 (`if let`, `guard let`, `??`)
- `Tuple`（タプル）の使い方
- `struct`　の使い方
- `enum`　（**列挙型**）の使い方
- `class` の使い方
- `public` と `private` (**アクセス修飾子)**の使い方
- `Array` (配列)の基礎
- `For loops` (**繰り返し処理**)の基礎
- `Filter , Sort,  Map`の使い方

---

### **💡 学び・反省点**

💡 **学び**

- Swift の基本文法を理解し、実際に `HStack`, `VStack`, `ZStack` を使って簡単な UI を作成できるようになった。
- `Function` の概念は重要であり、今後のプロジェクトでも頻繁に活用するため、さらに深く理解する必要がある。
- `Optional` の考え方を理解し、`if let`, `guard let` を適切に使うことでクラッシュしにくいコードを書けるようになった。
- **`struct` の使い方を理解し、値型の特徴を活かして安全なデータ管理ができるようになった。**
- **配列（Array）の基本的な使い方を学び、リストにアイテムを追加したり削除したりできるようになった。**
- **繰り返し処理（Forループ）を使って、同じ処理を何度も自動で実行できるようになった。**
- **Filter・Sort・Map を使って、リストの並び替えや特定のデータだけを取り出す方法を覚えた。特に Map を使うと、リストのデータを簡単に別の形に変えられて便利だった。**

⚠️ **反省点**

- `If Statements` や `Function` の理解がまだ不十分な部分があるため、繰り返し復習が必要。
- `HStack`, `VStack`, `ZStack` の使い方はわかったが、より複雑なレイアウトの作成練習が必要。
- `struct` と `class` の違いを理解できたが、実際のプロジェクトでどのように使い分けるかの実践が不足している。
- `Filter`, `Sort`, `Map` の活用方法は理解したが、より実用的なシナリオでの応用力を高めるために実際のコードで試す必要がある。


行動計画
--
- Swift の基礎（関数・オプショナル）をさらに深掘りする
- SwiftUI で簡単なアプリの UI を作成する
- 反復練習をする
- YouTube の教材を活用しながら、毎日少しずつ学習を継続する
- 日々学んだことをただ覚えるのではなく、実際にコードで試しながら、手を動かして覚えいく

---

### 振り返り

Udemy から Swiftful Thinking へ教材を切り替えたことで、より効率的に Swift の基礎を学べるようになったと感じた。SwiftUI でのレイアウトの仕組みが少しずつわかってきたので、今後は SwiftUI 積極的に取り組み実際に簡単なアプリを作りたい。また、関数やオプショナルなど、プロジェクトでよく使う機能をしっかり理解することが重要だと再認識した。
root で git 操作しないとならんときのちょっと便利な小ネタ

## これなに

`sudo git` みたいなことをしないとならならい極々一部のインフラエンジニア向けの小ネタ。
小粒過ぎて誰も記事にしてないので書いてみた。


## 対象

`sudo git commit` みたいなことをしないとならないケースが若干ながらあり、その際にどうやってコミッターとオーサーを記録するか？という疑問を持ってる人。ニッチ。


## 注意

`sudo -E` についての是非はここでは取り扱いません。


## 結論（なんか TL;DR は正しくないらしいですね）

環境変数を正しく設定して、 `sudo -E git` でこの環境変数が正しく渡るようにしましょう。

```
GIT_AUTHOR_EMAIL=your_mail_address@example.com
GIT_AUTHOR_NAME=Your Name
GIT_COMMITTER_EMAIL=your_mail_address@example.com
GIT_COMMITTER_NAME=Your Name
GIT_CONFIG_GLOBAL=/path/to/your/gitconfig
```


## 解説

通常の `sudo git commit` では、コミッターとオーサーが `root` になってしまいます。
これを避ける設定が流石にどこかにあるだろ、あるはず！ ...と思って探した結果、これらの環境変数にたどり着きました。

あとは `-E` オプション付きで sudo を実行し、ローカル環境変数を引き継いで git を実行しましょう。

```sh
$ sudo -E git commit -m '俺の仕業です`
```


なお、各環境変数について詳しくは下記に書いてあります。

https://git-scm.com/docs/git-config
* `GIT_CONFIG_GLOBAL` について書かれてるドキュメントこれしかない？

https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables
* こちらの一覧に `GIT_CONFIG_GLOBAL` が載ってないのでそのうち非推奨になるんかなー...
Terraform 入門：Terraformを使ってAWS S3バケットを作成する"main.tf"の内容を解説してみた

## **はじめに**
Terraform は、インフラをコードとして管理できるツールです。***本記事では、Terraform を使用して AWS 上に S3 バケットを作成する方法を解説します。***

## **書こうと思ったきっかけ**
Terraform を使って AWS のリソースを管理する方法を学ぶ中で、S3 バケットの作成手順をまとめることで、同じように学びたい人がスムーズに理解できるようになると考えました。

Terraform を使うことで、手作業のミスを防ぎ、再現性の高いインフラ管理が可能になります。

## **Terraform 設定ファイル (`main.tf`) の内容と解説**

以下の `main.tf` ファイルを使って、AWS に S3 バケットを作成します。

```hcl
provider "aws" {
  region = "ap-northeast-1"  # 東京リージョン
}

resource "aws_s3_bucket" "example" {
  bucket = "my-terraform-bucket-xxx"
  acl    = "private"
}

output "bucket_name" {
  value = aws_s3_bucket.example.bucket
}
```

### **1. AWS プロバイダーの設定**

```hcl
provider "aws" {
  region = "ap-northeast-1"  # 東京リージョン
}
```

- Terraform に **AWS を使用することを指定**
- `region = "ap-northeast-1"` → **AWS の東京リージョン** を指定

### **2. S3 バケットの作成**

```hcl
resource "aws_s3_bucket" "example" {
  bucket = "my-terraform-bucket-xxx"
  acl    = "private"
}
```

- **AWS S3 バケットを作成するリソース**
- `bucket = "my-terraform-bucket-xxx"` → **バケット名（AWS 全体でユニークである必要がある）**
- `acl = "private"` → **バケットのアクセス権限をプライベートに設定（外部からアクセス不可）**

### **3. 作成した S3 バケットの出力**

```hcl
output "bucket_name" {
  value = aws_s3_bucket.example.bucket
}
```

- `terraform apply` 実行後、**作成された S3 バケットの名前を表示**

## **Terraform の実行手順**

### 1. 初期化 (`terraform init`)
Terraform を初期化し、必要なプラグインをダウンロードします。

```sh
terraform init
```

### 2. 計画の確認 (`terraform plan`)
どのような変更が適用されるかを確認できます。

```sh
terraform plan
```

### 3. 実際に適用 (`terraform apply`)
S3 バケットを作成します。

```sh
terraform apply
```
実行後、以下のような出力が表示されます。

```sh
aws_s3_bucket.example: Creating...
aws_s3_bucket.example: Creation complete after 2s [id=my-terraform-bucket-haihiahiaoihoaino]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:
bucket_name = "my-terraform-bucket-xxx"
```
✅ これで **AWS 上に S3 バケットが作成** されます。

### 4. リソースの削除 (`terraform destroy`)
作成した S3 バケットを削除するには、以下のコマンドを実行します。

```sh
terraform destroy
```

`yes` を入力すると、AWS 上のリソースが削除されます。

## **まとめ**
Terraform を使うと、**コードで AWS のリソースを管理できる** ため、手作業を減らし再現性のあるインフラ運用が可能になります。

### **Terraform の基本操作**
| コマンド | 説明 |
|----------|------|
| `terraform init` | Terraform の初期化 |
| `terraform plan` | 変更点の確認 |
| `terraform apply` | AWS 上にリソースを作成 |
| `terraform destroy` | 作成したリソースを削除 |

**この手順を実行することで、AWS S3 バケットを Terraform で簡単に管理できます！**
Salesforce Platform デベロッパー試験 合格体験記

Salesforceの Platform デベロッパー試験 に合格したので、その学習方法や試験の感想をまとめました。これから受験する方の参考になれば幸いです。
## 前提
アプリケーションビルダー試験に合格した直後から、Platform デベロッパー試験の学習を開始しました。
## 勉強法
[Trailhead 【Salesforce公式】Salesforce 認定 Platform デベロッパー 資格 対策
](https://trailhead.salesforce.com/ja/users/welcome4/trailmixes/salesforce-platform-dev-1)

まずは定番のTrailheadを進めました。
アプリケーションビルダー試験と同様に、どうしても理解しづらい部分がいくつかあったため、後述の Udemy で補完しました。

## 問題集
個人ブログで公開されている問題集（暗記カード）を繰り返し解き、正解の根拠を確認しながら学習しました。
### 学習フロー
１．問題集を解く
２．ChatGPTで解答の妥当性を確認
３．ChatGPTと問題集の回答が異なる場合は、公式ドキュメントで検証

使用した問題集：
[TysonBlog](https://tysonblog-whitelabel.com/salesforce-dev-practice1) 
アプリケーションビルダー試験でもお世話になりました。

[Salesforce 認定 Platform デベロッパー試験対策 Ankilot](https://ankilot.com/view/?id=MwVHVHK9ev)
ページ遷移なしに閲覧できるため、ストレスフリー。

[ヨリユログ](https://yoriyulog.com/salesforce-certified-platform-developer-%E2%85%B0-q10/)

## Udemy
日本語のプログラム開発講座が見つからなかったため、日本語字幕対応の英語講座を選びました。
特に役立ったのは以下の2つの講座です。

[１．The Complete Salesforce Development Course](https://www.udemy.com/course/salesforce-development/?couponCode=ST10MT30325G1)

LWC や Visualforce を除く 基本的な開発スキル を幅広く学習できる講座です。
特に、各単元の 演習課題（Boss Level Challenge） をこなすことで実践力が身につきます。ただし、問題文を英語字幕で理解するのが難しく、私は途中で断念しました。

[２．Learn Salesforce (Admin + Developer) with LWC Live Project](https://www.udemy.com/course/learn-salesforce-admin-developer-with-lwc-live-project/)

LWCはこちらで学習。
基本概念の学習後に収録されている「Salesforce LWC Real Time Project」では、実践的な開発プロジェクトを学ぶことができ、非常に役立ちました。

## 受験結果と感想

試験は全60問を105分で解きますが、40分ほどで見直しまで完了しました。
各セクション毎の想定得点は下記の通り。

※単元ごとの問題数と結果得点は公表されないため、結果は計算により求めた想定値となります。

| セクション| 配点 (%) | 問題数（想定） | 得点率 (%) | 得点数（想定） |
|------------------------------|--------|------------|--------|------------|
| Developer Fundamentals（デベロッパーの基本） | 23% | 14問 | 100% | 14問 |
| Process Automation and Logic（プロセスの自動化とロジック） | 30% | 18問 | 77% | 14問 |
| User Interface（ユーザインターフェース） | 25% | 15問 | 86% | 13問 |
| Testing, Debugging, and Deployment（テスト、デバッグ、リリース） | 22% | 13問 | 92% | 12問 |
| **合計** | **100%** | **60問** | **88%** | **53問** |
## 終わりに
問題集を繰り返し解くだけでも 合格点には十分到達可能 だと思います。
特に、理解が曖昧な部分は 公式ドキュメントでの確認 が重要でした。

また、私はこれまで Web開発の経験がほぼなかった ため、LWC を通じて 標準的なWeb開発技術を学べたこと は貴重な経験でした。
なぜ「」「」や（「」）で文字が重なってしまうのか。

本記事は、テキスト入力フォームで<b><font color="Red">約物（日本語の文章における、カッコや点などの記号のこと）</font></b>が重なってしまう現象について、その理由を記載しただけの記事です。

解消することを目的としません。

<br>

ただ、理由が分からないとモヤモヤしますよね。

すこし前の私と同じようにモヤモヤしている人は、続きを読んでいただき、「だから重なっていたのかー！」とスッキリしていただければと思います。

<br>

# 事象 - 文章の「美しさ」を損ねる
まずは、事象について再現してみます。

特に発生しやすいケースは以下の 3 つでしょうか：
><b><font color="DarkSlateGray">①「」「」とカッコが続く場合</font></b>
><b><font color="DarkSlateGray">②箇条書き（・）が「」からはじまる場合</font></b>
><b><font color="DarkSlateGray">③『』の中に「」を含む場合</font></b>

<br>

ChatGPTで①②③を試してみます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/b503eec0-3565-488b-bf07-05052b8724ae.png" width="80%">

こんな感じの重なり、よくありますよね。③なんて重なり過ぎて、もうワケ分かんないことになっています。

<br>

Microsoft Teams などの『相手に読まれるための文章』が重なってしまうと、美しさが損なわれたように感じて、ついイラッとしてしまいます。

<br>

# なぜ、文字が重なってしまうのか
結論、CSS プロパティで約物の間をつめるようになっているからです。

<br>

例えば、text-spacing-trim というプロパティがあるようです。”とほほのWWW入門”という、Web 作成関連総合サイトの説明が分かりやすかったので参照します。

>日本語/韓国語/中国語における 約物文字(句読点や括弧文字)の幅が広くなりすぎないよう、全角の約物文字を半角に変換するなどの調整を制御します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/8c36e36a-d8fe-4e5c-b3d0-7dd1a49b0896.png" width="80%">

text-spacing-trim のリファレンスについてはこちら

https://drafts.csswg.org/css-text-4/#text-spacing-trim-property

<br>

各アプリや Web サイトでこのプロパティが使われているのかは分かりませんが、このプロパティのように約物をつめる設定にしているため、カッコが重なってしまうのです。

<br>

--

<br>

ふむふむ、なるほど。───ということは、ブラウザは CSS を変更できるので、CSS プロパティで約物の間をつめないようにできるか試せるはず。

今回は、ChatGPTの入力項目でやってみました。

<br>
 
まず、text-spacing-trim: の値を「space-first」で試します。この値は<b>約物の間をつめる設定</b>ですので、既存と同じように約物がつめられてしまいます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/c78d8d9e-1469-4d3b-9e57-43f71407194c.png" width="70%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/2c3a76dc-d3f5-4743-b78c-faec6d2214c9.png" width="90%">

<br>

<br>

次に、text-spacing-trim: の値を「space-all」にしてみましょう。この値が、<b>約物の間をつめない設定</b>です。結果は───

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/41eb158c-8920-48e1-af06-c852a4098af9.png" width="70%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/441d091d-533e-4539-921e-9017477fe568.png" width="90%">

<br>

<br>

おおー👏、約物がつめられておらず、私の理想になっています。

<br>

# おわりに
ということで、原因については上記のとおりで「全角の約物文字を半角に変換するから」でした。さいごに「なぜ、こんな処理が必要なのか？」をAIに聞いて、この記事を締めたいと思います。

<br>

■理由①
日本語の文字詰めを自然にするため、らしいです。日本語の文章では、全角文字の間に不要な空白が生じることがあるようで、意図しない広がりを防いでいます。

■理由②
デザインの統一感を出すため、らしいです。Web フォントやブラウザのレンダリングによって、文字間隔が微妙に異なることがあるようで、デザインの一貫性を保つことができます。

■理由③
レイアウトの崩れを防ぐため、らしいです。スペースを適切に制御しないと、改行時に不自然な余白ができることがあるようで、文字間のズレを抑える調整をしています。

<br>

要するに「日本語は表示が崩れやすいので、工夫しないといけない。」と。

<br>

以上です。


## 追記
Qiitaコメント（@smbd 様）より、以下の情報をいただきました。

Yu Gothic UI フォント固有のバグだそうです。
https://issues.chromium.org/issues/331123676

発生する文字は〈〉《》「」『』【】〔〕で
日本語 Windows の Teams と Loop に影響するようです。

<br>

また、今月（2025/3）のWindows Updateで直るかもしれないとのことでした。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/48ea20fb-cdc0-4a40-9b88-cb60aacc2767.png" width="90%">
プロジェクトの振り返り～採用サイト開発

## はじめに

3か月間、採用サイトの開発プロジェクトにバックエンドエンジニアとして参加しました。

このプロジェクトは、毎週のリリースを行い、CI/CD（継続的インテグレーション/継続的デリバリー）環境を活用しているのが特徴でした。久々にウォーターフォール以外の開発体制で、頻繁なリリースサイクルの中で、効率的に開発を進めるための工夫が求められました。また、Go言語を使った開発も初めての経験だったため、新しい技術に触れる機会にもなりました。

## 担当業務

主な役割は、既存機能のリファクタリングやシステムの保守でした。
リファクタリングでは、既存コードの可読性や保守性を高めることに重点を置き、特に繰り返し処理の最適化や、関数の整理を行いました。

加えて、コードの修正時には影響範囲を慎重に確認する必要がありました。
プロジェクト全体の構成を把握するために、関連するドキュメントを参照したり、ログを活用して挙動を追う工夫をしました。特に、呼び出し元の特定が難しい場面では、テスト環境での動作確認を行いながら、コードの動きを細かく検証しました。

## 技術的な学び

### Go言語の習得

今回のプロジェクトでは、新たにGo言語を使用しました。（これまでは主にPHPを用いて開発していました。）
特に、lo関数を用いたリファクタリングを行い、PHPにはないスライスやマップの使い方を学びました。Goでは、データ構造の扱い方やエラーハンドリングの考え方がPHPとは異なり、最初は戸惑う部分もありましたが、実際に手を動かすことで徐々に慣れていきました。

また、Goのシンプルな構文や並行処理の仕組みについても学ぶことができ、特にgoroutineの概念は今後の開発に活かせる知見となりました。

### テストコードの導入

「AAA」（Arrange-Act-Assert）パターンを意識したテストコードの作成を初めて行いました。これは、現場の社内Wikiを通して初めて知った概念でした。

> では、AAA とは何なのでしょう？
> それは、テストコードを読みやすくするための指針です。AAA は arrange, act, assert の略語で、arrange は『準備』、act は『実行』、assertは『検証』を表します。
参考：https://tech.pepabo.com/2021/08/23/writing-unit-test-with-aaa/

テストコードを書くことで、開発のたびに手動で動作確認を行う手間が省け、開発速度の向上につながりました。最初はテストの書き方に迷う場面もありましたが、実際に試行錯誤を繰り返しながら、徐々に書き慣れていきました。

特に、既存のコードに対してテストを追加する際には、影響範囲を考慮しながら進めることが重要だと実感しました。テストの自動化が進めば、将来的な開発コストの削減にもつながるため、今後も積極的に取り入れていきたいと考えています。

## 成果と工夫

### ドキュメント整備

プロジェクト中に直面した課題や解決策を社内Wikiに詳細に記録しました。
ドキュメントがあまりない現場だったため、今後の開発メンバーの負担軽減につながると考えました。短い期間の中でもいくつかスターをもらっており、他のメンバーが同様の問題に直面した際の参考資料として活用されたと思います。

チーム内での知見共有の重要性を改めて実感する機会になりました。

### コミュニケーションの工夫

フルリモートでの作業環境下、即時のレスポンスや積極的な質問を心掛け、コミュニケーションの円滑化に努めました。これにより、チーム全体の連携が強化され、スムーズなプロジェクト進行に寄与できたと感じています。
特に、分からないことを早めに質問することで、開発の手戻りを防ぐことができました。

## 課題と今後の展望

### 技術的課題

修正箇所の呼び出し元（画面やバッチ）の特定が難しい場面がありました。
ログを活用しながら調査を進めることはできましたが、システムの全体像を把握するのに時間がかかることが課題でした。今後は、より効率的にコードの影響範囲を特定できるよう、リファクタリング時の設計やドキュメントの活用を意識していきたいと考えています。

加えて、社内MTGではクリーンアーキテクチャや設計のベストプラクティスについての議論が行われることが多く、自分の理解が追いつかないこともありました。
今後は、Goの知識をより深めるとともに、設計の原則やベストプラクティスについても学び、よりスムーズに議論に参加できるようになりたいと考えています。
また、CI/CDの設定や運用についても理解を深め、環境構築の効率化やトラブル対応のスキルを向上させていきたいです。

### 次のステップ

今回の経験を活かし、今後も即時のレスポンスや積極的な質問を続け、チーム内外でのコミュニケーションを深化させていきたいと考えています。
また、Go言語のさらなる習熟を目指し、次のプロジェクトでも積極的に活用していきたいです。

特に、Goでの開発経験を積み重ねることで、より効率的なコードの書き方や設計の考え方を学んでいきたいと考えています。また、テストの重要性を再認識したため、今後はより多くのプロジェクトでテストコードの作成に取り組みたいです。

## おわりに

短期間のプロジェクトでしたが、多くの学びと成長を実感することができました。これからも新しい技術や手法に挑戦していきたいと思います。
また、今回の経験を活かし、より多くのプロジェクトで技術的な貢献をしていきたいと考えています。今後も積極的に学び、経験を積み重ねていくことで、さらに成長していければと思います。

## 採用案内

株式会社TechReisでは、一緒に成長できるエンジニアを募集しています！

- エンジニアが案件を選択できる制度
- 契約時の単価を完全公開
- 単価に連動した給与設定

などの仕組みがあり、自身のキャリアプランやライフスタイルに合わせた案件選びが可能です。

興味のある方は、[Green](https://www.green-japan.com/company/9886)または[HP](https://techreis.co.jp/)をチェックしてみてください！お問い合わせお待ちしています。