OmniAICreator/Qiita-1.07M huggingface dataset:
Rubyでの配列における |（和集合）と ||（論理演算）の違いを調べた

最近、Ruby Silverの資格試験の勉強をしています。全然Rubyのこと理解してないんだなぁと絶望しつつも伸びしろを感じております😚

以下の問題を考えていた際に、配列に対する `|` と `||` の違いが気になったので調べてみました。

---
問題:

XXXXに記述することで、実行結果が30以上になるプログラムを選択してください。

```ruby
a = [-1, 2, 3, 4, 5]
b = (4..6).to_a

puts XXXX
```

選択肢:

1. `a.inject(:+) + b.inject(:+)`
2. `(a | b).inject(:-).abs + (a & b).inject(:+).abs`
3. `(a | b).inject(:*) + b.inject(0) { |x, y| x + y ** 3 }`
4. `((a || b).map(&:succ).inject(:*) * (a && b).inject(:*).abs2 + 29)`
---

この問題の`a | b` と `a || b` の結果がどうなるか分からなかったので、調べてみました。`a || b`を配列で使うイメージがない…

## `a | b` の挙動

`|` 演算子は、配列同士の**和集合**です。
両方の配列に含まれる要素を、重複なく結合した新しい配列を返します。

```ruby
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]

result = a | b
puts result.inspect  # => [-1, 2, 3, 4, 5, 6]
```

この例では、`a` と `b` の和集合が作成され、重複する要素 `4`, `5` は一度だけ含まれる結果になります。

整数オブジェクトに対しては、ビット単位のOR演算を行います。（どっちか1なら1）

```ruby
puts 8 | 5  # => 13 (1000 | 0101 ⇒ 1101)
```

## `a & b` の挙動

`&` 演算子は、配列同士の**積集合**です。
両方の配列に共通して含まれる要素だけを持つ新しい配列を返します。

```ruby
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]

result = a & b
puts result.inspect  # => [4, 5]
```

この例では、`a` と `b` に共通する要素 `4` と `5` が結果として返されます。

整数オブジェクトに対しては、ビット単位のAND演算を行います。（どっちも1なら1）

```ruby
puts 12 & 5  # => 4 (1100 | 0101 ⇒ 0100)
```

## `a || b` の挙動

`||` 演算子は、左項 `a` が「真」と評価される場合には `a` を返し、そうでない場合には右項 `b` を返します。Rubyでは、`nil` と `false` 以外のすべての値が「真」として扱われます。

```ruby
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]

result = a || b
puts result.inspect  # => [-1, 2, 3, 4, 5]
```

この場合、`a` が配列で「真」と評価されるため、`result` には `a` が返され、`b` は評価されません。

### `a` が `nil` の場合

```ruby
a = nil
b = [4, 5, 6]

result = a || b
puts result.inspect  # => [4, 5, 6]
```

`a` が `nil` で「偽」と評価されるため、`result` には `b` が返されます。

変数がnilの時に初期値を設定する方法でよく見かけますね。

## `a && b` の挙動

`&&` 演算子は、左項 `a` が「偽」と評価される場合には `a` を返し、そうでなければ右項 `b` を返します。

```ruby
a = [-1, 2, 3, 4, 5]
b = [4, 5, 6]

result = a && b
puts result.inspect  # => [4, 5, 6]
```

`a` が「真」と評価されるため、`result` には `b` が返されます。

### `a` が `nil` の場合

```ruby
a = nil
b = [4, 5, 6]

result = a && b
puts result.inspect  # => nil
```

`a` が「偽」と評価されるため、`result` には `a` の値 `nil` が返されます。

## 短絡評価の違い

`||` と `&&` は**短絡評価（ショートサーキット）** を行いますが、`|` と `&` は短絡評価を行いません。つまり、`|` と `&` では、両方のオペランドが必ず評価されます。

### 例: 短絡評価の違い

```ruby
a = true
b = false

# 短絡評価あり (||)
result = a || (b = true)
puts b  # => false  (b は評価されない)

# 短絡評価なし (|)
result = a | (b = true)
puts b  # => true  (b は評価される)
```

`||` 演算子では、`a` が `true` なので、`b = true` は評価されず、`b` の値は変わりません。
`|` 演算子では短絡評価が行われず、`b = true` が実行されて `b` は `true` に変わります。

## まとめ

- **`||` と `&&`** は、論理演算子として条件分岐やデフォルト値の設定に使う。真偽値、配列、数字などに対して動作する。
- **`|` と `&`** は、配列に対して集合演算を行い、和集合や積集合を返す。整数に対してはビット演算を行う。
GitHubアカウントが複数あるときの/.ssh/config, git cloneコマンド

## はじめに
二つ目のGitHubアカウントを作成して.ssh内のconfigを設定して以降、git cloneができなくなったので調べた。
```:エラーした実行コマンド
git clone git@github.com:usr/***
```
```:エラー出力
Cloning into '***'...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
## 原因
config内でHostにAlice, Bobというエイリアスを設定していたのでエラーがおきた。
```:config
Host Alice
 HostName github.com
 IdentityFile ~/.ssh/id_Alice_rsa
 User git

#サブアカウント
Host Bob
 HostName github.com
 IdentityFile ~/.ssh/id_Bob_rsa
 User git
```
よって実行するコマンドは以下。
```:正しい実行コマンド
git clone git@Alice:usr/***
```

## 補足
### configのUserがcharleの場合は以下になる
```:実行コマンド
git clone charle@Alice:usr/***
```
### ssh接続テストのコマンドも同様にconfigに合わせる
```:ssh接続テスト
ssh git@github.com
```
```:Host Alice
ssh git@Alice
```
僕はエラー処理当時これも分からなくて、sshの再生成と再登録は完了しているのに接続エラーが出まくり5時間くらい迷わされました。バカすぎる...

### その他
リモートリポジトリとの接続も同じ
```
 git remote add origin git@Alice:usr/***
```
VRC_AvatarParameterDriver

# VRC_AvatarParameterDriver

- 割とよく使うので覚書
- Local Onlyの定義がちょっと特殊（Avatar装着者のみでしか処理されなくなる）。注意
- Random
    - Int,Float … min max valueの間でセット
    - bool … Chanceに設定した確率で1にセット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935918/686bf4d8-a03b-1e61-5146-bf7a82f4f141.png)

## Set int
- parametersはlist

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935918/f625bae6-283c-92fe-d001-f7b140b5e37e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935918/358aaf94-f113-fb29-5bdf-62f947db8d48.png)




```
using System;
using System.Collections.Generic;
using UnityEngine;

namespace VRC.SDKBase
{
    public abstract class VRC_AvatarParameterDriver : StateMachineBehaviour
    {
        public enum ChangeType
        {
            Set,
            Add,
            Random,
            Copy
        }

        [Serializable]
        public class Parameter
        {
            [Tooltip("The type of operation to be executed")]
            public ChangeType type;

            [Tooltip("Parameter that will be written to")]
            public string name;

            [Tooltip("Source parameter that will be read")]
            public string source;

            [Tooltip("The value used for this operation")]
            public float value;

            [Tooltip("Minimum value to be set")]
            public float valueMin;

            [Tooltip("Maximum value to be set")]
            public float valueMax = 1f;

            [Tooltip("Chance the value will be set.  When used with a Bool type, defines the chance the value is set to 1, otherwise it's set to 0.")]
            [Range(0f, 1f)]
            public float chance = 1f;

            [Tooltip("If true, we convert the range of the source and destination values according to the ranges given.")]
            public bool convertRange;

            public float sourceMin;

            public float sourceMax;

            public float destMin;

            public float destMax;

            public object sourceParam;

            public object destParam;
        }

        public List<Parameter> parameters = new List<Parameter>();

        [Tooltip("When true, only the client who is wearing this avatar will use this ParameterDriver.  This option is useful to avoid conflicts from non-deterministic operations like Random or Add across multiple clients.")]
        public bool localOnly;

        [Tooltip("Custom debug message that will be written to the client logs when the ParameterDriver is used.  Be careful to remove these before your final upload as this can spam your log files.")]
        public string debugString;

        [NonSerialized]
        public bool isLocalPlayer;

        [NonSerialized]
        public bool isEnabled;

        [NonSerialized]
        public bool initialized;

        public static Action<VRC_AvatarParameterDriver, Animator> OnApplySettings;

        public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            OnApplySettings?.Invoke(this, animator);
        }
    }
}
```
【ローカル5G】 free5GCとリアルgNBでiPhone接続を試す。⑥

* * *
※本記事は2024年9月9日時点の内容です。
この記事は私がfree5GCとリアルgNB(ローカル5G用小型基地局= Small Cell）を使ってiPhone接続を試す機会があり、その過程をまとめたものです。
free5GCのインストールについては基本的には全てfree5GCプロジェクトのWEBサイトを参考に進めました。

https://free5gc.org/

インストールしたバージョンは以下の通りです。
OS　: 　Ubuntu 20.04.6 LTS
Linux Kernerl　:　5.4.0-193-generic
free5GC　:　v3.4.2
<br>
過去記事はこちら
[① Ubuntuインストール編](https://qiita.com/Takashi_Eifuku/items/133b26da9013f35cdf68 "【ローカル5G】 free5GCとリアルgNBでiPhone接続を試す。①")
[② free5GCインストール編](https://qiita.com/Takashi_Eifuku/items/c13b8ecb499f1a3b3c38 "【ローカル5G】 free5GCとリアルgNBでiPhone接続を試す。②")
[③ free5GC設定変更編](https://qiita.com/Takashi_Eifuku/items/f89b6ddffc9969de3f5a "【ローカル5G】 free5GCとリアルgNBでiPhone接続を試す。③")
[④ SUCI SIM編](https://qiita.com/Takashi_Eifuku/items/b92d5e1cb87e985dcf73 "【ローカル5G】 free5GCとリアルgNBでiPhone接続を試す。④")
[⑤ gNB接続編](https://qiita.com/Takashi_Eifuku/items/c1a8d63d820960036139 "【ローカル5G】 free5GCとリアルgNBでiPhone接続を試す。⑤")
<br>
# iPhone接続
### iPhone設定とAttach
作成したSUCI SIMをiPhoneへ挿入します。
今回用意したのはiPhone13 mini
MNO eSIM (au) が入っていて、ローカル5G物理SIMを入れてDual SIM状態にします。
<br>

SIMを挿入すると「Non-Public Network」との表示。
ガイドに従ってローカル5G回線を優先回線に設定します。
<br>


次に「設定」 → 「モバイル通信」 → 「SIM」 で挿入したSIMを選択。
「この回線をオンにする」をON。
![タイトルなし2_サイズ変更.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883115/40762201-05e7-b630-b098-71c10acc082d.png)
<br>


「音声通話とデータ」で5GスタンドアローンもONに。
![タイトルなし3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883115/6dfc5bf2-95c5-fd57-c112-1b8c95eba3be.png)
<br>

次にAPNを「internet」に設定。
![タイトルなし4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883115/2ff0458e-3efb-c982-8ce0-1eed951e3356.png)
<br>
「モバイル通信」に戻って、
「モバイルデータ通信」→「モバイルデータ通信の切替を許可」をON。
そしてローカル5G回線にチェック。
![タイトルなし4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883115/dace9af4-0e97-f9dd-8a3b-cf0d7c04105d.png)


![タイトルなし5_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883115/5cd60cb1-124a-6d7b-13ea-63a5c715c066.png)

これで設定完了。

free5GC側のログを確認すると、Initial UE Messageを受信。
```
[INFO][AMF][Ngap][ran_addr:172.16.60.3:38412] Handle InitialUEMessage
...
...
[INFO][AMF][CTX] New AmfUe [supi:][guti:999002xxxxxxxxxxxxxx]
[INFO][AMF][Gmm] Handle event[Gmm Message], transition from [Deregistered] to [Deregistered]
[INFO][AMF][Gmm][amf_ue_ngap_id:RU:65537,AU:1(3GPP)][supi:SUPI:] Handle Registration Request
```
<br>
認証処理が進み、、

```
[INFO][AMF][Ngap][amf_ue_ngap_id:RU:65537,AU:1(3GPP)][ran_addr:172.16.60.3:38412] Send PDU Session Resource Setup Request
[INFO][AMF][GIN] | 200 |       127.0.0.1 | POST    | /namf-comm/v1/ue-contexts/imsi-999002xxxxxxxxx/n1-n2-messages |
[INFO][AMF][Ngap][ran_addr:172.16.60.3:38412] Handle PDUSessionResourceSetupResponse
[INFO][AMF][Ngap][amf_ue_ngap_id:RU:65537,AU:1(3GPP)][ran_addr:172.16.60.3:38412] Handle PDUSessionResourceSetupResponse (RAN UE NGAP ID: 65537)
```
<br>

Attach完了しました。
![タイトルなし6_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883115/7254f52b-1f32-a5f2-42ab-1f03d3ac5dc5.png)

iPhoneからpingアプリでgoogle(8.8.8.8)へpingを実行してインターネット接続の確認もOKでした。

以上でiPhone接続は完了です。

次の記事ではスループット測定とデュアルスタンバイの動作関連の検証についてまとめる予定です。
オフライン環境のPostgreSQLを13から15にアップグレードする

前提条件
- オフライン環境である（インターネットに接続できない）
- OS: RHEL8
- DB: PostgreSQL13（現在）

# 1. 事前準備
__必要なファイルを取得__
- 【インターネット接続環境：なし】
    - PostgreSQL 15のRPMパッケージおよび依存パッケージをダウンロードします。
    - ダウンロードしたファイルはオフライン環境に持ち込む必要があります。
- 【インターネット接続環境：あり】
    - インターネット接続ができない場合、PostgreSQL 公式リポジトリ (https://yum.postgresql.org/) から、PostgreSQL 15のパッケージをダウンロードします。
    - 以下のようなコマンドを使用してダウンロードします。
    ```bash
    yumdownloader --resolve postgresql15-server postgresql15 postgresql15-contrib
    ```
    - --resolve オプションを使うと依存パッケージも一緒にダウンロードできます。

__バックアップ__
- アップグレード前に、データベース全体のバックアップを取得することを強く推奨します。
    ```bash
    # データベース全体のバックアップ
    pg_dumpall > /path/to/backup.sql
    ```

# 2. PostgreSQL 13の停止
アップグレードを行う前に、現在動作しているPostgreSQL 13を停止します。

```bash
sudo systemctl stop postgresql-13
```

# 3. PostgreSQL 15のインストール
オフライン環境にダウンロードしたパッケージを持ち込み、インストールします。

```bash
sudo yum localinstall postgresql15-server-15.x.x.rpm postgresql15-15.x.x.rpm postgresql15-contrib-15.x.x.rpm
```

# 4. PostgreSQL 15の初期設定
新しいPostgreSQL 15のデータベースクラスタを初期化します。

```bash
sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
```

# 5. PostgreSQL 13のデータをPostgreSQL 15に移行
pg_upgradeツールを使用してPostgreSQL 13のデータをPostgreSQL 15に移行します。

```bash
sudo /usr/pgsql-15/bin/pg_upgrade \
    --old-datadir=/var/lib/pgsql/13/data \
    --new-datadir=/var/lib/pgsql/15/data \
    --old-bindir=/usr/pgsql-13/bin \
    --new-bindir=/usr/pgsql-15/bin
```

# 6. PostgreSQL 15の起動
データ移行が完了したら、PostgreSQL 15を起動します。

```bash
sudo systemctl start postgresql-15
```
- 起動時に問題がないか確認しましょう。

# 7. PostgreSQL 15の有効化
再起動時にもPostgreSQL 15が自動的に起動するように有効化します。

```bash
sudo systemctl enable postgresql-15
```

# 8. 古いバージョンのクリーンアップ（オプション）
移行が成功した場合、PostgreSQL 13の不要なデータやパッケージを削除することができます。

```bash
sudo yum remove postgresql13-server postgresql13
```
次に、古いデータディレクトリを削除します。

```bash
sudo rm -rf /var/lib/pgsql/13/data
```

# 9. PostgreSQLのバージョン確認
最終的に、正しくアップグレードされているかバージョンを確認します。

```bash
psql --version
```

以上
ねえ、知ってた？ 次世代AIの到来：OpenAI o1モデルが複雑な問題解決に革命をもたらす！

こんにちは、拓也です。
OpenAI が発表した最新モデル o1 は、AI 技術の新たな水準を示す重要な進化です。特に数学、プログラミング、科学といった複雑な分野で、卓越した推論力と問題解決能力を発揮する o1 モデルは、今後の技術的な課題解決において欠かせないツールとなることが期待されています。
![图片3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/737e20b2-3e55-c6ac-5b27-05db199e029f.png)


o1 モデルは、従来の AI モデルとは一線を画す性能を備えています。最大の特徴は、問題に対して深い考察を行い、複数の戦略を試みることで、より高い精度で解を導き出せる点にあります。また、モデルは自らの誤りを認識し、修正する能力も持っており、物理学、化学、生物学といった分野では、博士課程の学生と同等のレベルで問題解決が可能です。これは以前の GPT-4 モデルと比べても、特に高度な推論能力において大きな進化を遂げています。


さらに、OpenAI は o1 モデルの2つのバージョンをリリースしています。まず、より強力な推論能力を備えた o1-preview モデル。そして、より軽量でコスト効率が高く、特にプログラミングやデバッグに適した o1-miniモデルです。これにより、ユーザーは必要に応じて適切なモデルを選択し、さまざまなタスクに応用できるようになっています。


現在、o1 モデルはプレビュー版として提供されており、ファイルアップロードやウェブ閲覧などの一部の機能はまだ未対応ですが、その革新的な問題解決能力により、特に科学技術分野において複雑な課題の解決を目指しています。また、安全性にも配慮されており、従来のモデルを上回るパフォーマンスをセキュリティテストで実証しています。


このように、o1 モデルはその高度な推論力と問題解決能力から、今後日本の IT 業界でも複雑な技術的課題に対する強力なツールとして注目されるでしょう。
WindowsでOCamlを使う方法

# インストール環境
| OS | Windows 11 Home 23H2 |
|:-:|:-:|
| コマンドライン シェル | PowerShell||

# Visual Studio Build Toolsのインストール
プログラムのビルドを行えるようにするためのもの。
```
winget install Microsoft.VisualStudio.2019.BuildTools --override "--wait --passive --installPath C:\VS --addProductLang En-us --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
```
![スクリーンショット 2024-04-11 200624.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3642100/0480035f-d450-326f-bc2e-ced2112bb7c9.png "実行中の様子")

# Gitのインストール
```
winget install Git.Git
```
ソース管理システムのこと。すでにインストールされている人は当然スキップ。

# DkMLのインストール
Windows環境下でOCamlをインストールするためのインストーラー。
OCaml公式ドキュメントでは、別に新しくターミナルを起動したうえでインストールを実行することを推奨している。
```
dkml init --system
```
![スクリーンショット 2024-04-11 212622.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3642100/113edac5-b984-4297-83a7-6a2d75133aa6.png)

# OPAMの初期化
先ほどDkMLをインストールしたことでOPAMというOCamlのパッケージマネージャーをインストールすることができた。
今度はそのOPAMを以下のコマンドで初期設定する。
```
opam init --disable-sandboxing --bare --switch=playground --shell=pwsh  -a
```

# OCamlの実行
以下のコマンドを入力することで、OCamlの対話環境に入ることができる。

```
ocaml
```
![スクリーンショット 2024-04-11 221301.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3642100/37bbf0fc-b172-ae5e-eaa9-21f62a056f8f.png)

以下が実行例

![スクリーンショット 2024-04-11 232522.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3642100/2b52152f-3c38-6ec2-b571-634aac97aadd.png)



# OCamlの開発で使えるツールのインストール
以下のツールをインストールすることで、より高度な開発環境を構築することができる。

>UTop: モダンな対話型システム (REPL: Read-Eval-Print Loop)
Dune：高速かつ高機能ビルドシステム
ocaml-lsp-server：言語サーバプロトコルを実装し、VS Code, Vim, Emacs などのエディタで OCaml をサポートするもの。
odoc：OCaml コードからドキュメントを生成するもの。
OCamlFormat：OCamlコードを自動的にフォーマットするもの。
>> https://ocaml.org/docs/installing-ocaml より引用（筆者が翻訳済）
```
opam install ocaml-lsp-server odoc ocamlformat utop
```
インストール完了まで筆者の環境ではかなり時間がかかった。

# VSCodeでOCamlを扱う
VSCodeのOCaml Platformという拡張機能をインストールすることで、VSCodeをOCamlのエディターとして使うことができる。
なおこの拡張機能を使うには、先程紹介したocaml-lsp-serverとOCamlFormatが必要になる点は注意である。
この2点は以下のコマンドでインストールできる。

```
opam install ocaml-lsp-server ocamlformat 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3642100/9a9467a9-13aa-33e5-fc26-2eb070e49ec0.png)

# 最後に
いかがだっただろうか。
OCamlという比較的かなりマイナーな言語な上に、Windowsでの導入方法が記載された記事はなかなか出てこなかったので、今回取り上げさせてもらった。
筆者の大学やその他いくつかの大学ではOCamlを授業内で取り扱っているようなので、Windows民でどうしてもローカル環境で動かしたい、WSLなどを使わずに直接Windows環境で動かしたいなどといった方々にとって、少しでも有益な記事になっていることを願う。
Flutter - Dart開発の初心者Tips【今さら】

初歩の初歩で必要だったことをまとめます

## バージョンによって動く動かないがある
スマホ系はあるあるで、つまづきがちですが、Flutterは2系と3系で大きな違いがあるため、要チェック
また、[AndroidStudio](https://developer.android.com/studio/archive?hl=ja)や[Xcode](https://developer.apple.com/download/all/?q=xcode)も特定バージョンをインストールしないと動作しないとかもよくある話。

## エディタはVSCode、Android Studioのどちらか
Android Studioを利用中
また主な違いなどがわかっていない
ただ個人的にはVSCodeの見た目が好きでプラグインで誤魔化している

余談だが、Xcodeにはターミナルがついていないので、すごく不便だと思っている

## fvm
Flutterの細かいバージョン管理が必要ならfvmを使う
色々な入れ方があるが、基本下記で良いのだと思う。
```sh
brew tap leoafarias/fvm
brew install fvm
fvm --version
```
パスを通すことでfvmでインストールしたFlutterを使える
```
export PATH="$PATH":"$HOME/fvm/default/bin"
```

VScode、Android Studioのエディタでも指定が可能(バージョン管理不要とのこと)
```json
{
  "dart.flutterSdkPath": ".fvm/flutter_sdk"
}
```

## 基本的にlib配下を触る
PJの設定による部分でもあるが、基本的にルートの`lib`配下に`.dart`のファイルを置いて編集する
`android`配下、`ios`配下はFlutterのビルド時に生成されるファイル群
ちなみに`main.dart`がエントリーポイント

## ビルドするデバイスが選べない時
これは最新のAndroidStudioでは起きない可能性もありますが、地味にハマったので載せます。
たまにこの`<no device selected>`の部分が、下記のように表示されない場合があります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798970/243b7d55-614f-9e44-0c6e-cfa75f4f0a2b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798970/1c9b1606-bb61-88d5-ed22-e6928a458e37.png)

この時は下記のように`「Dart support is not enabled for the module 'アプリ名'」`が表示されているので、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798970/adaf910c-7cd9-8433-84ec-670d32da69ee.png)
`「Enable Dart support」`を押すと選べるようになります
Sync Gradleをすると起きることを確認しています。

## Debugモードでビルドし特定の変数をデバッグしたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798970/2c569292-b7d8-a047-a385-1602894a915c.png)
上記画像の一番右のDartマークを押すとWebのFlutter Dev Toolsが立ち上がる
ここでクロームのコンソールのように値をいじれる
```dart
import 'dart:convert';
import 'dart:io';
```
がされているdartファイル内でのブレークポイントで処理を止めている場合、
```dart
var params = {
  'user_name': userName,
  'password': password,
};
print(jsonEncode(params));
```
でMap型になっている`params`をJSONで出力可能
`jsonEncode`の部分はdart:convertのimportの仕方で呼び出し方が異なるので注意

## ネットワークで送っている内容をみたい
ネットワークタブを見ればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798970/da046e17-b91a-4308-f22a-9503db603bf9.png)

## この辺を参考に勉強中です！
https://qiita.com/mkosuke/items/42c19d7edbf111f7fb71
https://qiita.com/tokkun5552/items/4649478803be47cd488c
インフラのコード化とは？

## コード化するきっかけ

「会社で開発チームのためにAWS環境をテンプレート化して、気軽にデプロイ出来る状態にしておいてほしい」　という依頼が来ました。

というのも、私はWEB系企業の人間でも無いですし、AWS自体割と自由に触らせてもらえる環境でかつ、設定変更などに厳しいレビューも無いのでコード化する理由もあまりなかったんですよね～。

## コード化とは
サーバーやネットワーク、ストレージなどのインフラ構成をコードとして記述し、そのコードを使ってインフラを構築・管理する手法　ということです。

## コード化の種類
大きくわけて、２つあると認識しています。
1. リソースのデプロイをコード化する
1. リソースの設定をコード化する

## 1.リソースのデプロイをコード化するとは
これは、簡単に言うとクラウドサービスであったり、Dockerなどインフラリソースそのものを構築・管理を目的としてコード化する　ということです。
なので例えば
```
VPC 172.168.1.0/24 外部公開サブネット 172.168.1.0/25 プライベートサブネット 172.168.1.128/25
```
のような構成をコードで書いてデプロイすることで、アカウント上にこの環境が作成されます。

## 2.リソースの設定をコード化するとは
リソース自体の作成はコードもしくは手動で行うが、その後の初期設定であったり
他のサーバ群と同じ設定状況にしたい場合などに使用します。
なので例えば、
```
ユーザー名 test1 test2 test3 グループ testgroup
```
下記のように全てのサーバーに共通の設定を入れたい場合などに利用されます。
他人(ヒト)からされて面倒だなと思うことは貴方で止めよう！

## はじめに
社内でいろんなイベントがありますが、最近は
Formsを使って参加者を募集されるものが多いですよね。

:::note
勉強会、ラウンドテーブル、情報交換会 等など
:::
せっかく申し込んでも、その予定をご自身のスケジュールに入れ忘れて、他の予定を入れてしまったり、他の人に予定をおさえられたり

そんな時に無精で他力本願な私はすぐに思います。

:::note warn
自分でスケジュール入れるの面倒だなぁ～！
せっかくFormsに参加って入れたんだから、私の予定をおさえてよ。
:::

今回は、私と違って、お・も・て・な・しの心あふれる貴方が、この面倒な作業をやってくれるように、Formsで参加と回答したら、参加者のカレンダーに予定を入れてくれる仕組みの作り方を紹介します。

**そう。私が楽をするために:sweat_smile:**

----------
### 大雑把な手順

大雑把な手順としては次の通りです。

1. 宛先は誰かモルモットを召喚し先に会議の予定を入れる
1. 発信した招集メールのIDを取得する
1. イベント募集用のFormsを作成する
1. Formsトリガーで会議の予定を転送するフローを作る

順番に見ていきましょう。

#### 手順1:誰かモルモットを召喚し先に会議の予定を入れる

Outlookのスケジュール機能を使って、誰か身近な人(実際は参加しなくても可。あとで取り消せばいいので)を召喚してイベントの予定を作成し発信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/29639409-48b9-6dfe-dc9e-ba5828de9297.png)

このようにすると、送信済みフォルダに会議招集メールが保管されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/8125a12a-a06d-5c58-f760-e0f8ea233504.png)




#### 手順2:発信した招集メールのIDを取得する
ここからは、Power Automateの登場です。
https://make.powerautomate.com/ にアクセスしたら、
左側の【+ 作成】 ⇒ 【インスタントクラウドフロー】を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/88a01c7d-9e1d-7668-82b6-e92df90c529a.png)

インスタント クラウド フローを構築するというダイアログが表示されたら、フロー名を付けて、トリガーする方法は『フローを手動でトリガーする』をひとまず選んでおきます。
(最終的には変更します)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/058afed2-f74d-7754-84cd-d8a6b10a3bc7.png)

新しいフローの作成画面が表示されたらアクションの追加から、Office 365 Outlookを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/c5391895-fc41-cf05-36b6-c904fb0d153a.png)

するとこのコネクタで利用可能なアクションの一覧が表示されるので、【メールを取得する(V3)】を選びます。

:::note alert
イベントの取得 (Vx)ではないです。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/eb826881-5ed7-8f47-bc5a-d10499f13e7a.png)

アクションを追加すると、パラメータ設定ペインが左側に表示されるのでフォルダに『送信済みアイテム』、未読メッセージのみを取得するに『いいえ』を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/a7646b6d-7fee-449e-8aef-badbfe0ba62a.png)

そこまで設定出来たら、一度テスト実行してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/be90c1b7-f071-8c9d-e0ce-d18ee712efab.png)

フローはすぐに完了しますので結果を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/2a79bf83-c22c-ca96-54da-4f7ae7cd3a99.png)
先ほど追加したメールを取得するアクションをクリックすると左側に結果が表示されます。その出力セクションの【未加工出力の表示】をクリックすると右側に取得したメッセージの一覧がディフォルトだと10件JSONの形式で取得出来ているはずです。その中から件名や宛先などから会議招集の送信結果を選び、"id"の値をすべてコピーします(長いです)

**これでメッセージIDの取得は完了です。**

続いて、このメールを転送するようにフローを改修していきます。編集モードにしたら、メールを取得アクションは削除しちゃってください。かわりに【メールの転送(V2)】アクションを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/9b4e208c-c1bf-f54c-75c2-7f8f309458c0.png)



パラメータのメッセージIDには先程、JSONからコピーしたIDの値をペーストします。
そして、宛先欄にご自身のメールアドレスをセットしたら、またテスト実行してください。
Outlookを開いて、正しく送信されているかを確認します。
ご自身にメールすると受信フォルダではなく、送信済みフォルダに保管されるので要注意です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/66bc9516-f2b7-68a5-3afc-63e3f64df482.png)
このように件名の先頭に"FW:"がついて、会議招集メールが転送されたことを確認できます。

## To be Continued...
長くなってきたので続きは次回公開とします。

https://qiita.com/yamachan67/items/e78f012ca24aa5e06874

お楽しみに！
UICollectionViewCell をキレイに並べるのに苦労した話

# 背景
UICollectionView 内に、1行につき4つずつセルを並べようとしてもなぜか画面の外まではみ出してしまい苦労したので解決方法を残します。

# 元のコード

```swift
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let sectionInsets = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset ?? .zero
    let interItemSpacing = 10.0 // セル間のスペース
    let numberOfItemsPerRow = 4.0
    
    // Safe Area を考慮した幅から、左右のインセットとセル間のスペースを引く
    let totalSpacing = sectionInsets.left + sectionInsets.right + (interItemSpacing * (numberOfItemsPerRow - 1))
    let availableWidth = collectionView.safeAreaLayoutGuide.layoutFrame.width - totalSpacing
    
    // セルの幅を計算
    let width = availableWidth / numberOfItemsPerRow
    return CGSize(width: width, height: 80)
}
```

# 原因
`collectionView(_:layout:sizeForItemAt:)` でセルのサイズを指定するだけでは、レイアウトが自動的に再描画されないためでした。
`collectionView(_:layout:sizeForItemAt:)` は、セルのサイズを要求されたときにそのサイズを提供するためのメソッドであり、再レイアウトや再描画をトリガーするメソッドではありません。

# 対応
`viewDidLayoutSubviews()` でレイアウトを無効化し、再度レイアウトを計算することで、最終的な正しいレイアウトが適用されます。
`invalidateLayout()` を呼び出すことで、コレクションビューが表示された後に正しいサイズで再レイアウトされます。

```swift
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    // レイアウトを再計算
    collectionView.collectionViewLayout.invalidateLayout()
}
```
CakePHP2でコマンドラインからテストを起動

ごくまれにCakePHP2系のテストを走らせることがあります。実行時のパラメタの渡し方を忘れるのでメモしておきます。

自作部分のテストは

```bash
# ./Console/cake test app Model/Behavior/SimpleStatusBehavior
```

プラグインのテストは

```bash
# ./Console/cake test Cakeplus Model/Behavior/AddValidationRule
```

自作部分のファイルはここにあります

```
./Test/Case/Model/Behavior/SimpleStatusBehaviorTest.php
```

プラグインファイルはここにあります

```
./Plugin/Cakeplus/Test/Case/Model/Behavior/AddValidationRuleTest.php
```

公式マニュアル
https://book.cakephp.org/2/ja/development/testing.html
PostgreSQLを使ってみた

## はじめに
　インターンで環境構築したサーバーを使ってデータベースと通信する機会がありました。その際にいろいろ行き詰ったりしたので同じような境遇の方に少しでも参考になるようにとしたことを書き綴っていこうと思います。
 　初めての経験だったので無駄なことやおかしなことを言っているかもしれませんがもしあった場合はコメント欄で優しく指摘していただけると幸いです。
### 実行環境
- OS: AlmaLinux 8.10
- PostgreSQL: 12.20

## 実際に使ってみる
まずはユーザーとデータベースを作成するところから
まずはコマンドの画面を開きユーザー資格をpostgresに変更するために
```
$ su - postgres
```
を実行して変更します。

さて今回は適当にユーザー名は```user1```、パスワードは```test_pass```、データベース名は```test```で作っていこうと思います
```
$ psql template1
```
を実行して
```
$ psql template1
psql (12.20)
"help"でヘルプを表示します。

template1=#
```
と表示されれば成功です。
ちなみに```psql```コマンドは簡単に言うと普段私たちが使っているようなパソコンの操作している画面のコマンドバージョンです。
次にこの画面上でつぎのプロンプトを打ち込みます。
```
create user1 with password 'test_pass'
create database test owner user1 encoding 'UTF-8'
```
これでユーザーとデータベースができましたね。
ちなみに抜け出すには
```
template1=# \q
```
を実行すればできます。
では次にデータベース上にテーブルを作っていこうと思います。
テーブル名は適当に```sample_table```とかで...
```
$ psql test

create table sample_table  (
    id serial primary key
    , name text
    , age integer
    , birthday timestamp with time zone
);
```
これらを打ち込むとデータベース上にテーブルが作成されます。
実際に確認してみましょう
```
$ psql test
```
と打ち込むと、
```
psql (12.20)
"help"でヘルプを表示します。

test=#
```
と表示されるので次に、
```
test=# \d sample_table
```
を実行すると
```
                                       テーブル"public.sample_table"
    列    |            型            | 照合順序 | Null 値を許容 |
フォルト
----------+--------------------------+----------+---------------+------------------------------------------
 id       | integer                  |          | not null      | nextval('sample_table_id_seq'::regclass)
 name     | text                     |          |               |
 age      | integer                  |          |               |
 birthday | timestamp with time zone |          |               |
インデックス:
    "sample_table_pkey" PRIMARY KEY, btree (id)
```
と表示されます。うまく作成できていることがわかりましたね。

では次に、実際にテーブル上にデータを入力していきたいと思います。
まずはいつも通りPostgreSQLに接続するために、
```
$ psql test
```
を実行します。
まずはデータが何もないことを確認するために、
```
test=# SELECT * FROM sample_table;
```
を実行します。すると、
```
test=# SELECT * FROM sample_table;
 id | name | age | birthday
----+------+-----+----------
(0 行)
```
と表示されました。まだなにもデータがないことが確認できましたね。
では実際にデータを入力していきたいと思います。
```
test=# INSERT INTO sample_table (id,name,age,birthday) VALUES (1,'user1',20,'2000-01-01 12:00:00');
```
このようなSQL文を実行すると、
```INSERT 0 1```と返ってくると思います。その場合は成功で、データベースに追加できています。
```SELECT * FROM sample_table;```を実行して確認してみましょう。
```
test=# SELECT * FROM sample_table;
 id | name  | age |        birthday
----+-------+-----+------------------------
  1 | user1 |  20 | 2000-01-01 12:00:00+09
(1 行)
```
実際に追加できていることがわかりましたね。

## 最後に
　やっていることは割と単純だと思うのですが実際にしているとセミコロンが抜けていたり、誤字があったりとつまらないミスをしてしまったりしました。
　普段私はGUIばかりつかっていたので今回CUIをつかうことでいい刺激になりました。さいごまで読んでいただきありがとうございます。
GCP e2-micro インスタンスでJenkins buildが停止する問題

# Jenkinsでyarn buildを試してみよう

Jenkinsのインストールが完了し、CD設定のためにまずNodejsプラグインをインストールしました。

## Nodejsプラグインの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880966/e8a086a1-3386-e533-7f15-71191203592b.png)

1. プラグインをインストールして再起動した後、Global Tool Configurationに移動してプラグインの設定を行います。
2. NodeJS項目で適当な名前を付け、NodeJSのバージョンを選択します。
3. yarnを使用するため、yarnも追加します。

## パイプラインプロジェクトの作成

1. 新しいパイプラインプロジェクトを作成し、Gitと連携します。
2. Project URLにGitHubリポジトリのアドレスを入力します。
3. ビルドトリガーの設定で、GitHub hook triggerにチェックを入れます。
4. Pipeline script from SCMを選択し、リポジトリURLにはGitHubリポジトリのHTTPS URL（.gitで終わるアドレス）を入力します。
5. ビルドトリガーを設定するブランチを選択します。

## パイプラインスクリプトの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880966/db1b9ec8-7b49-d512-292f-0e77f881d459.png)


ビルドまでのパイプラインテキストを作成し、保存してからビルドを実行してみましょう（JenkinsfileをGitHubにプッシュ）。

## 問題発生：ビルドが終わらない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880966/03aa09a2-64a7-0ee2-566d-d971fbd31696.png)


このように実行したところ、Jenkinsが非常に遅くなり、ページの読み込みができなくなりました。e2-microのパフォーマンスが低いためだと思いましたが、3〜4時間経っても接続できませんでした。

### メモリ不足が原因？

GCPのe2-microのメモリが1GBしかないため、メモリ不足が原因ではないかと考え、メモリスワップの設定を試してみました。AWSの公式サイトでも紹介されていました。

[スワップファイルを使用してAmazon EC2インスタンスのスワップスペースにメモリを割り当てる](https://aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-memory-swap-file/)

## メモリスワップの設定手順

1. ルートにスワップファイルを作成

   ```
   $ sudo dd if=/dev/zero of=/swapfile bs=128M count=32
   // bsはブロックサイズ
   // countはブロック数、ここでは4GB割り当て
   ```

2. スワップファイルの権限を変更

   ```
   $ sudo chmod 600 /swapfile
   ```

3. Linuxスワップ領域を設定

   ```
   $ sudo mkswap /swapfile
   ```

4. スワップスペースにスワップファイルを追加

   ```
   $ sudo swapon /swapfile
   ```

5. プロセスが成功したか確認

   ```
   $ sudo swapon -s
   ```

6. /etc/fstabファイルを編集して起動時にスワップファイルを開始

   ```
   $ sudo vi /etc/fstab
   ```

   最後の行に以下を追加

   ```
   /swapfile swap swap defaults 0 0
   ```

これらの手順を実行した後、`free`コマンドで確認するとスワップメモリが割り当てられていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880966/82783ef1-11d9-1e4f-3bd5-5f48cc58f7a0.png)


## 問題解決！

これでビルドを実行すると、遅いですが正常に終了することが確認できました。AWS EC2 t2.microでも同様の症状が発生するため、VPCのスペックを上げるか、このようにスワップメモリを設定することで解決できます。
PhpStorm カーソルをファイルの先頭行、末尾行へ移動する(Mac)

- 先頭行へジャンプ: `Command` + `fn` + `←`
- 末尾行へジャンプ: `Command` + `fn` + `→`

他のエディタだと `Command` + `↑` or `↓` で行けるので毎回忘れてしまうので備忘録として書く
wslでmanim その18

# 概要
wslでmanimやってみた。
練習問題やってみた。

# 練習問題
ロータリーエンジンを図解せよ。

# 参考にしたページ

https://qiita.com/masudaryo/items/29537e98220ed9c8bc0a

# 成果物

![test_ManimCE_v0.18.1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a8027c09-849c-d302-891d-77305141bc0f.gif)


# サンプルコード

```

from manim import *

R = 3
e = 0.7
n = 0
u = 0

def f1(t):
	return np.array((e * np.cos(3 * u) + R * np.cos(u + 2 * n * np.pi / 3) + R * np.sqrt(3) * np.cos(u + t), e * np.sin(3 * u) + R * np.sin(u + 2 * n * np.pi / 3) + R * np.sqrt(3) * np.sin(u + t), 0))
def f2(t):
	return np.array((e * np.cos(3 * t) + R * np.cos(t), e * np.sin(3 * t) + R * np.sin(t), 0))
def f3(t):
	return np.array((2 * e * np.cos(3 * t), 2 * e * np.sin(3 * t), 0))
def f4(t):
	return np.array((e * np.cos(3 * u) + e * np.cos(3 * t), e * np.sin(3 * u) + e * np.sin(3 * t), 0))

class test(Scene):
	def construct(self):
		global n, u
		grid = NumberPlane()
		self.add(grid)
		func2 = ParametricFunction(f2, t_range = (TAU * 0, TAU), fill_opacity = 0)
		self.add(func2)
		func3 = ParametricFunction(f3, t_range = (TAU * 0, TAU), fill_opacity = 0)
		self.add(func3)
		self.wait()
		for u in TAU * np.arange(0, 0.4, 1 / 40):
			func4 = ParametricFunction(f4, t_range = (TAU * 0, TAU), stroke_color = PINK, fill_opacity = 0)
			self.add(func4)
			n = 0
			rot0 = ParametricFunction(f1, t_range = (np.pi / 6 * (4 * n + 5), np.pi / 6 * (4 * n + 7)), stroke_color = PINK, fill_opacity = 0)
			self.add(rot0)
			n = 1
			rot1 = ParametricFunction(f1, t_range = (np.pi / 6 * (4 * n + 5), np.pi / 6 * (4 * n + 7)), stroke_color = PINK, fill_opacity = 0)
			self.add(rot1)
			n = 2
			rot2 = ParametricFunction(f1, t_range = (np.pi / 6 * (4 * n + 5), np.pi / 6 * (4 * n + 7)), stroke_color = PINK, fill_opacity = 0)
			self.add(rot2)
			self.wait()
			self.remove(rot0)
			self.remove(rot1)
			self.remove(rot2)
			self.remove(func4)






```

以上。
wslでmanim その17

# 概要
wslでmanimやってみた。
練習問題やってみた。

# 練習問題
パーセプトロンを図解せよ。

# 参考にしたページ

https://www.xeex-ti.jp/rndblog/2024/manim-generativeai/

# 成果物

![ThreeLayerPerceptron_ManimCE_v0.18.1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/98e3351e-f444-8007-b8d9-57f25cbcf96c.gif)


# サンプルコード

```
from manim import *

class ThreeLayerPerceptron(Scene):
	def construct(self):
		num_inputs = 3
		num_hidden = 4
		num_outputs = 2
		node_radius = 0.3
		layer_spacing = 2
		node_spacing = 1
		input_layer = VGroup(*[Circle(radius=node_radius, fill_color=BLUE, fill_opacity=1) for _ in range(num_inputs)])
		input_layer.arrange(DOWN, buff=node_spacing)
		input_layer.shift(layer_spacing * LEFT)
		hidden_layer = VGroup(*[Circle(radius=node_radius, fill_color=GREEN, fill_opacity=1) for _ in range(num_hidden)])
		hidden_layer.arrange(DOWN, buff=node_spacing)
		output_layer = VGroup(*[Circle(radius=node_radius, fill_color=RED, fill_opacity=1) for _ in range(num_outputs)])
		output_layer.arrange(DOWN, buff=node_spacing)
		output_layer.shift(layer_spacing * RIGHT)
		lines = VGroup()
		for i in input_layer:
			for j in hidden_layer:
				lines.add(Line(i.get_center(), j.get_center(), buff=0.1))
		for i in hidden_layer:
			for j in output_layer:
				lines.add(Line(i.get_center(), j.get_center(), buff=0.1))
		self.play(LaggedStart(*[GrowFromCenter(node) for node in input_layer], lag_ratio=0.2))
		self.play(LaggedStart(*[GrowFromCenter(node) for node in hidden_layer], lag_ratio=0.2))
		self.play(LaggedStart(*[GrowFromCenter(node) for node in output_layer], lag_ratio=0.2))
		self.play(LaggedStart(*[Create(line) for line in lines], lag_ratio=0.05))
		self.wait(3)




```

以上。
新規サイトを開発した話

## 作成したサイト
今回開発した「トレオタ」は、トレーディングカード専門の通販サイトです。このサイトでは、中古や新品のトレーディングカードの販売に加えて、ネット上でオリパガチャが楽しめる「トレオタガチャ」、さらに自宅から手軽にトレーディングカードを売却できる「宅配買取」サービスを提供しています。トレーディングカード愛好者にとって、ワンストップであらゆるニーズを満たせるプラットフォームを目指しています。

![スクリーンショット 2024-09-13 16.37.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635181/174134ca-67a1-b92b-d670-5964962f4d50.png)

https://www.toreota.com/

## サイト構成
サイトのフロントエンドは、Next.jsをベースとしたReactアプリケーションで構築されています。開発にはTypeScriptを用い、型安全性と開発効率を向上させています。また、Tailwind CSSを活用することで、デザインのカスタマイズを効率的に行い、統一感のあるユーザーインターフェースを実現しました。

バックエンドはDjangoフレームワークを使用し、インフラストラクチャはAmazon EKS（Elastic Kubernetes Service）を利用しています。

## 構築していくうえでの一番大変だった箇所
特に困難だったのは、カード検索機能の実装です。この機能はOpenSearchを用いて構築しましたが、インデックスの設計にいくつかの課題がありました。具体的には、カードが重複して検索結果に表示される問題や、特定のキーワードで検索しても意図しない結果が表示されるという現象が発生しました。これらの問題を解決するために、インデックスの設計を見直し、クエリのロジックを最適化する作業が必要でした。特に、ユーザーが期待する検索結果を得られるように、フィルタリングや検索アルゴリズムの調整に多くの時間を費やしました。

![スクリーンショット 2024-09-13 16.39.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635181/2df82126-b402-4857-ed92-dc35990ea275.png)


## まとめ
今回のサイト開発は、私にとって初めて会社での完全新規サイトの開発でした。そのため、設計から実装、運用に至るまで、多くの課題に直面しました。
サイト公開するまでに、いくつかのトラブルがありサイト公開してしばらく経つまで、大きなエラーがないか何度も受注や検索、ページの表示処理の確認を何度も行っていました。
幸い、大きなエラーは発生せずサイトが止まるようなことはなかったですが、今後はエラー等の発生が少ないまたは無いように努力していきます！
AnsibleからWindows Server 2022を設定自動化するまでのセットアップ手順

# はじめに
- AnsibleからWindows Serverの自動化を行う。その際のセットアップ手順を実際に実行してみたのでまとめておく。
- なお、筆者の環境ではAnsibleサーバは既にセットアップ済みのためAnsibleのインストール手順は割愛する。
- また、あらかじめターゲットサーバにWindows Server 2022をインストールしておく必要がある。

# 公式ドキュメント
- 基本的に以下のドキュメントに従って設定を行う。
- [Windows ホストのセットアップ — Ansible Documentation](https://docs.ansible.com/ansible/2.9_ja/user_guide/windows_setup.html)

# 環境
- Ansibleサーバ
    - OS: AlmaLinux 9.4
    - Ansible: 2.15.12
    - Python: 3.9.18
    - pywinrm: 0.5.0
- ターゲットサーバ
    - OS: Windows Server 2022

# WinRMの設定
- AnsibleからWindowsホストに接続するために必要なWinRMの設定を行う。
- 設定には公式ドキュメントに記載されているスクリプトを実行するが、筆者が実行しようとした際、```$url```のリンクが404 not foundになっていた。
- 削除された理由は不明だが、設定に必要な```ConfigureRemotingForAnsible.ps1```が最後に存在した```stable-2.112```ブランチのものを使用することにする。
```sh
PS > $url = "https://raw.githubusercontent.com/ansible/ansible/stable-2.12/examples/scripts/ConfigureRemotingForAnsible.ps1"
PS > $file = "$env:temp\ConfigureRemotingForAnsible.ps1"
PS > (New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
PS > powershell.exe -ExecutionPolicy ByPass -File $file
```

# WinRMリスナーの確認
- 上記のスクリプトにより、HTTP経由のポート```5985```、HTTPS経由のポート```5986```で要求をリッスンしていることを確認する。
```sh
PS > winrm enumerate winrm/config/Listener
Listener
    Address = * 
    Transport = HTTP 
    Port = 5985 
    Hostname 
    Enabled = true 
    URLPrefix = wsman 
    CertificateThumbprint 
    ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80:ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7

Listener
    Address = * 
    Transport = HTTPS 
    Port = 5986 
    Hostname = SERVER2016 
    Enabled = true 
    URLPrefix = wsman 
    CertificateThumbprint = E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE 
    ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80:ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7
```

# pywinrmのインストール
- AnsibleサーバーにWinRMを操作するための```pywinrm```をインストールする。
```python
$ pip install pywinrm
$ grep pywinrm
pywinrm             0.5.0
```

# インベントリファイル作成
- インベントリファイルにWindows Serverについて定義する。
```
[windows]
<Windows ServerのIPアドレス> ansible_user=<Windows Serverのユーザ名> ansible_password=<Windows Serverのパスワード>

[windows:vars]
ansible_port=5985
ansible_connection=winrm
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore
```

# 実行
- 今回は"pong"を返してくれるだけの[win_pingモジュール](https://docs.ansible.com/ansible/2.9/modules/win_ping_module.html#win-ping-module)を実行する。
```
$ ansible windows -i hosts -m win_ping
SUCCESS => {
    "changed": false,
    "ping": "pong"
}
```

# Windowsモジュール
- 今回は```win_ping```モジュールを試したが、以下のドキュメントから様々なモジュールを参照できる。
- [Windows modules — Ansible Documentation](https://docs.ansible.com/ansible/2.9/modules/list_of_windows_modules.html)

# 参考
- [AnsibleでWindowsサーバーを設定してみた-環境準備編- - JBS Tech Blog](https://blog.jbs.co.jp/entry/2023/05/30/135558)
- [Windowsサーバ2016をAnsibleで設定してみた](https://qiita.com/ksawada1979/items/31214d147277042f1e32)
docker-compose.ymlを書いてみる

# 1､目的
valkeyコンテナをrunで立ち上げる際､毎回portなどを指定するのが大変だったため､docker-compose.ymlを作成した｡

# 2､事前知識
### 1､docker-compose.ymlとは
から調べました｡｡｡笑

dockerはコンテナを立ち上げてその中でアプリケーションやDBを取り扱えるようにするのですが､docker-composeを使うと､なんと､複数のコンテナ(image)を立ち上げられるのです｡すご｡

で､今回はvalkeyのみなので､runでもいいのですが､毎回portを指定するのも大変で､dockerfileよりもdocker-compose.ymlのほうがやりやすそうだったので､こちらにしました｡

### 2､docker-compose.ymlを記載する場所
初心者すぎて､ここに手間取りました｡
結論をいうと､
```
docker compose up
```
を行いたいディレクトリ(正確にはプロジェクトのディレクトリというらしい)に記載しましょう｡


# 3､作業
### 1､docker-composeをインストール
公式から取ってきたのですが､バージョンが古い｡｡｡新しいものを入れたかったのですが､わからなかったので､諦めました｡｡｡
```
curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```

インストールできているか確認
```
docker-compose --version
```

### 1､docker-compose.ymlを書く
先程のdocker-composeを起動させたいディレクトリでvi を起動します｡

```
sudo vi docker-compose.yml
```

立ち上がったら下記を記載( (Ctrl) + (Shift) + (V) で貼り付け可能)
※タブはスペース4つ｡:の後ろにはスペース
```
version: '1.6.2'

services:
    valkey:
        image: valkey/valkey:7.2.6
        container_name: valkey
        ports:
            - "6379:6379"
        volumes:
            - /data:/data
```
補足:
version: '1.6.2'
    Docker Compose ファイルのバージョンを指定します。このバージョンによって利用できる機能が異なります。

services:
    サービスを定義するセクションです。ここでは、valkey という名前のサービスを1つ定義しています。

valkey:
    サービス名です。この名前でコンテナを識別します。
    image: valkey/valkey:7.2.6
        使用するDockerイメージを指定します。ここでは、valkey/valkey というリポジトリの 7.2.6 タグのイメージを使用します。
    container_name: valkey
        コンテナの名前を指定します。この名前でコンテナを直接参照できます。
    ports:
        コンテナ内のポートとホストのポートのマッピングを指定します。
            6379:6379: コンテナ内の6379番ポートを、ホストの6379番ポートにマッピングします。
    volumes:
        ホストのディレクトリとコンテナ内のディレクトリをマウントします。
            /data:/data: ホストの/dataディレクトリを、コンテナ内の/dataディレクトリにマウントします。これにより、コンテナ内のデータはホストの/dataディレクトリに保存されます。


### 2､立ち上げる
まず､｢valkey]
という名前のコンテナを削除しておきます｡
```
docker rm valkey
```

docker-composeを立ち上げます
```
docker compose up
```

止めるときは
(Ctrl) + (C)
で止まります｡

# 3､まとめ
docker-composeを使うことで､コンテナが統一できなおかつ､省力化できました｡
vimで5分後の時刻を挿入する

### やりたかったこと
入力：Ctrl + S
出力：2024/09/13(Fri) 09:00

### 解決方法
~/.vimrcに下記追加
```viml
nmap <silent> <C-S> <ESC>i<C-R>=strftime("%Y/%m/%d(%a) %H:%M", localtime() + 300)<CR><CR><ESC>
```

### 目的
日報に記入する現在時刻を毎回打つのが面倒なので一発で入力したかった。

### なぜ５分後？
丸め処理を行おうとして
2024/09/13(Fri) __08:59__
の最後でインクリメント(Ctrl+A)しても
2024/09/13(Fri) __08:60__
となってしまう。

そこで予め５分後を出力しておき
2024/09/13(Fri) __09:04__
からデクリメント4回(4+Ctrl+X)したほうが楽だった。

### 参考
https://hyuki.hatenablog.com/entry/20130714/vim
https://nanasi.jp/articles/code/date/localtime.html
RPCエンドポイントを利用してウォレットを実装してみる　＃２送金

# テーマ設定
RPCエンドポイントを利用してウォレットの送金機能を実装してみる。

# 前提環境
+ Node.js がインストールされている。
+ Web3.js ライブラリがインストールされている。

+ RPCエンドポイントを取得（無料）
https://cabinet-node.com/ja/docs/user-guide/create-access-token

### web3のインストール
```bash
npm install web3
```

# 実装
以下の内容で.envファイルを作成してください。
```bash
PRIVATE_KEY=*********** # 送信元アドレスにペアリングする秘密鍵
```
以下の内容でsend_transaction.jsファイルを作成してください。
 ```js
require('dotenv').config(); // dotenvの読み込み
const { Web3 } = require('web3');

// RPCエンドポイント
const rpcURL = 'https://gateway-api.cabinet-node.com/{access_token}';
const web3 = new Web3(rpcURL);

// ウォレット情報
const senderAddress = ’SENDER_WALLET_ADDRESS'; // 送信元アドレス
const privateKey = process.env.PRIVATE_KEY; // 環境変数から秘密鍵を取得
const toAddress = ’RECEIVER_WALLET_ADDRESS'; // 送信先アドレス
const amountToSend = '0.01'; // 送金額（Ether）

async function sendTransaction() {
    try {
        // nonce を取得
        const nonce = await web3.eth.getTransactionCount(senderAddress, 'latest');

        // トランザクションオブジェクトを作成
        const tx = {
            from: senderAddress,
            to: toAddress,
            value: web3.utils.toWei(amountToSend, 'ether'),
            gas: 2000000, // ガスリミット
            gasPrice: await web3.eth.getGasPrice(),
            nonce: nonce,
            chainId: 11155111 // Ethereum Sepolia
        };

        // トランザクションに署名
        const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);

        // トランザクションを送信
        const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
        console.log('Transaction receipt:', receipt);
    } catch (error) {
        console.error('Error sending transaction:', error);
    }
}

sendTransaction();
 ```

 # 実行
  ```
node send_transaction.js
  ```

### 結果の例

```
Transaction receip: ********************
```
PowerAppsアプリにおしゃべりさせたい

<S>
動画：PowerAppsアプリにおしゃべりさせたい
を公開しました。</S>

### ※MicrosoftTranslatorを使用しておしゃべりさせることはできなくなりました。

※ 以下のコードは現在(2024/11/14)使用できません。 

MicrosoftTranslatorコネクタを使用してアプリ内でおしゃべりさせることができる

今回の動画で使用した数式を以下に記載しておきます。

データ接続：MicrosoftTranslator
必要なコントロール：Timer、Audio

Audioは自動再生・ループはオフ
Startプロパティに変数「_speak」
Mediaプロパティに以下の数式

```
If(
    !IsBlank(_speaktext), //変数が空ではなくなったら実行
    MicrosoftTranslator.TextToSpeech(_speaktext,"ja")
)
```

Timerは繰り返し・自動開始をオン
期間に1000（1秒毎にループ）
OnTimerEndプロパティに以下の数式

```
UpdateContext({_nowtime: Now()}); //現在時刻を格納

//0分になったら時刻を知らせる
If(
    Text(_nowtime,"mmss") = "0000", //0分0秒になったら
    UpdateContext({_speaktime: Blank()});//一度空にする
    UpdateContext({_speaktext: Blank()});//一度空にする
    UpdateContext({_speaktime: _nowtime});//現在時間を格納
    UpdateContext({_speaktext: Text(_speaktime,"h時になりました。")});
    UpdateContext({_speak: true}) //しゃべらせる内容
);
//30分になったら時刻を知らせる
If(
    Text(_nowtime,"mmss") = "3000",
    UpdateContext({_speaktime: Blank()});
    UpdateContext({_speaktext: Blank()});
    UpdateContext({_speaktime: _nowtime});
    UpdateContext({_speaktext: Text(_speaktime,"h時mm分になりました。")});
    UpdateContext({_speak: true})
);
```
UiPath Studio マウスとキーボードの長押し自動化

お客様との会議で「長押しの自動化はどう実現するのか？」と質問されましたが、すぐには解決策が思い浮かばず、ググっても見つかりませんでした。
さらに調べてテストして、解決方法を実現できたので、本記事にまとめました。もし同じ悩みを持っている方がいれば、ご参考になれば幸いです。

# やりたいこと

以下のようなサイト（[リンク](https://junli-web-host.s3.ap-northeast-1.amazonaws.com/LongPressTest.html)）を対象にして、ロボットがシフトキーと左マウスキーを長押しする動作を自動化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/bccaa0d1-35f5-6213-c38c-15963b75fefe.png)

# 左マウスキーの長押し

複数のアクティビティを組み合わせることで、マウスボタンの長押しを実現できます。まず、マウスボタンを押下し、指定した待機時間まで押し続けた後、ボタンを離します。
1. **「クリック」 アクティビティ**（入力モード：ハードウェア イベント、クリックの種類：NClickType.Down）
1. **「待機」 アクティビティ**（期間に長押しの時間を設定）
1. **「クリック」 アクティビティ**（入力モード：ハードウェア イベント、クリックの種類：NClickType.Up）

クリックアクティビティの入力モードのデフォルト設定（Chromium API）ではうまく動作しなかったため、手動操作を最も忠実に再現できる「ハードウェアイベント」の入力モードを使用しました。各入力モードの違いについては、以下の図をご参照ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/866bea57-45ca-ff4a-1e0d-7cd704fc997a.png)
(出典：[【UiPath】入力モードの違い](https://qiita.com/miya_gis/items/4fc94d999a016c3d19dd) miya_gis(みやぎ)さん ありがとうございました。)

ワークフローは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/6ee3ce8a-f61b-e9f4-c3f7-25ce9d9dac3a.png)

ワークフローを実行すると、マウスボタンが自動的に長押しされ、画面は以下のように変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/b5e48328-882d-a587-9750-f2db089e7888.png)

# キーボードの長押し

キーボード操作の場合、「キーボードショートカット」アクティビティが使えますが、何秒間キーを押し続けるといった操作ができないため、別の方法を選びました。
選んだのは「文字を入力」アクティビティです。このアクティビティは文字の入力だけでなく、特殊なキーもサポートされています。さらに、キーの上げ下げ操作の送信もできます。例えば、
- `%[d(ctrl)]` - 特定のボタン(Ctrlキー)を押し下げます。
- `%[u(ctrl)]` - 特定のボタン(Ctrlキー)を持ち上げます。

詳細な内容はUiPathの公式ページをご参照ください。

https://docs.uipath.com/ja/activities/other/latest/ui-automation/type-into

実現方法は、マウスボタンの長押しと同じ流れです。
1. **「文字を入力」アクティビティ**（入力モード：ハードウェア イベント、テキスト：`%[d(Shift)]`）
1. **「待機」 アクティビティ**（期間に長押しの時間を設定）
1. **「文字を入力」アクティビティ**（入力モード：ハードウェア イベント、テキスト：`%[u(Shift)]`）

ワークフローは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/51508620-3860-9c9f-e7c1-136b11ccd569.png)

ワークフローを実行すると、シフトキーが自動的に長押しされ、画面は以下のように変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/b15fca89-109d-a8fc-02e1-71ab45c960bb.png)

# 終わり

今回ご紹介した方法が、UiPath Studioの自動化における小技として、皆様の仕事の効率化に少しでも役立てば幸いです。今後も、役に立つ情報をお届けしていきますので、ぜひ参考にしてみてください。
【就活生向け】■とれ

# 資格なんて飾りだと思ってる
これまでいた会社では、全然強制されたりなかったため **【資格】** を全然取ってこなかったわけで、
別にこれからも進んで取りに行こうなんて思わないくらい向上心がありません!!
どうも、え～すけさんです。

# そもそも持ってても使いこなせてるの？
例えばJavaの資格があるかとおもいますが。。。
コレまで自分の周りでこの資格持ってる人で、
きちんと実装できる人って余りいなかったこともあり、
**資格を持ってる = バリバリにプログラム組める**
という固定概念が大きく覆ってしまったため、
別に資格を持ってるからって仕事に役に立ってないんだから、
高い金払って必死に取る必要はないんじゃないかという結論にいたり、
**資格否定派** になっているわけです。

## Javaの資格だけで言うならば。。。
ナニカのプロジェクトで【**Java単品で何かを作る**】なんてほぼありえなくて、
普通はSpringだったりmybatisだったりopencsvだったりpoiだったり、
何かしらのライブラリを組み合わせてシステムを構築していくわけで、
それらのライブラリ固有の書き方が基本構文＋αで覚えないといけないことになるため、
資格ではそこら辺のライブラリの使い方までは対象外となるため、
資格を持っていれば大丈夫と余裕かましてるとアサインされた時に痛い目を見るわけです。

# じゃあ、なんで資格って有るの？
ココからは就活生向けの話になりますが、
企業としては採用するに当たり面接だけでは見えない部分を知りたいというのもあり、
表立っては言わないですが学歴フィルターだったり資格フィルターだったり経歴フィルターを設けて、
この人はコレまでちゃんとしてきたのかなどを総合的に判定して採用を決定しているものだと思います。
※自分は人事でも営業でもない、ただのペーペー社員なのでウチの採用基準の詳細までは把握していませんが、世間一般的にはこういった採用基準があるんじゃないかなぁっていうイメージなので全部の企業がこんなフィルターかけてるっていうことではないとは思うので全部鵜呑みにはしないでね（保険

## 資格を持ってると何がいいか？
資格を取るためには **【ある程度のお勉強】** が必要かと思いますが、
資格を持っていることにより、その **【ある程度のお勉強】** をちゃんと出来るのか・やってきたのかという点が測れるため、
企業としても **【コイツ、ちゃんと勉強してきたやんけ！】** という明確な指標となるため、
資格の有無を大事にしてるところとかが多いのかなって思います。

特にIT系の場合、コレ！といった書き方の答えのないプログラムとかだと、
**【如何に自分で学べる・考えられるか】** がとても重要になるため、
資格を持っていることで自分で学べるという点においては課題点かなってなる気はしてます。

## ただし新卒・第2新卒に限る
新卒・第2新卒に関しては業務実績なんかないか、
やってても内容がたかが知れてるということもあり、
資格を持ってることで採用時の加点にはなりそうですが。。。

### 同業種からの転職（社会人大体3年目以降）の場合
企業は中途採用の場合は即戦力が欲しいという部分に重きが出てくるため、
**資格を何個持ってる**　っていう事よりも、
**コレまでどんなことやってきたの？**　っていう事が重要になってくるため、
資格の保持による加点数はだいぶ低くなるのかなって気がします。

# そんなわけで
就活生はちゃんとやってるよアピールするために、
頑張って資格取っておくのもありかなっていうお話でした。
試験が年に数回しかないとかのテストも有るので、
面接前に取得をしておいたほうがいいということを
早ければ早く取っておくのに越したことはないよ！
C#でPDFのページを切り抜く

PDF文書を扱うとき、広告や背景情報を削除したり、単に文書の内容を単純化したりするなど、特定のニーズに合わせてページを正確に切り抜く必要があることがあります。

この記事では、**C#を使用してPDFページを切り抜く**ために無料の.NETライブラリを使用する方法をご案内します。


## 無料の.NET PDFライブラリ
無料のチャージライブラリ[**Free Spire.PDF for .NET**](https://www.e-iceblue.com/Introduce/free-pdf-component.html)は、.NET（C#、VB.NET、ASP.NET、.NET Core）プログラムでのPDF文書の作成、操作、変換、印刷などの操作をサポートします。

以下のリンクからパッケージをダウンロードし、手動で参照を追加するか、NuGet経由で直接インストールすることができます。

https://www.e-iceblue.com/Download/download-pdf-for-net-free.html


## C#でPDFページを切り抜く 
Free Spire.PDF for .NET ライブラリは、PDF ページの指定された領域を切り抜くための非常にシンプルなインターフェイスを提供します。詳しい手順は以下の通りです：

1.	**`LoadFromFile()`** メ ソ ッ ド で PDF 文書を読み込みます；
2.	指定されたPDFページを取得します；
3.	矩形を指定し、**`PdfPageBase.CropBox`** プロパティを通して指定された領域を切り取ります；
4.	切り抜き PDF 文書を、 **`SaveToFile()`** メ ソ ッ ド を使っ て保存 し ます。

**サンプルC#コード:**
```csharp
using System.Drawing;
using Spire.Pdf;

namespace CropPDFPage
{
    class Program
    {
        static void Main(string[] args)
        {
            //PDF文書を読み込む
            PdfDocument pdf = new PdfDocument();
            pdf.LoadFromFile("新聞.pdf");

            //最初のワークシートを取得する
            PdfPageBase page = pdf.Pages[0];

            //PDFページを指定領域で切り抜く
            page.CropBox = new RectangleF(30, 950, 720, 350);

            //トリミングした文書を保存する
            pdf.SaveToFile("CropPDF.pdf");
            pdf.Close();
        }
    }
}
```

![CropPdfPage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/f222ff9b-40e6-33de-c356-87e17c447b83.png)

* * *

> **質問があれば、フォーラムにどうぞ。**

https://www.e-iceblue.com/forum/spire-pdf-f7.html