OmniAICreator/Qiita-1.07M huggingface dataset:
SpringプロジェクトにLombokを導入【Gradle】


# Lombokの導入
build.gradleの設定
まず、build.gradleファイルにLombokを追加します。Lombokの依存関係をcompileOnlyとannotationProcessorに追加することで、Lombokのアノテーションを使用できるようになります。

```gradle
dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.24'
    annotationProcessor 'org.projectlombok:lombok:1.18.24'
}
```
# 基本的なアノテーション
@Getterと@Setter
@Getterと@Setterは、フィールドのgetterとsetterメソッドを自動生成します。

```java
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class User {
    private Long id;
    private String name;
}
```

## @ToString
@ToStringは、toStringメソッドを自動生成します。

```java
import lombok.ToString;

@ToString
public class User {
    private Long id;
    private String name;
}
```
## @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor
これらのアノテーションは、コンストラクタを自動生成します。

```java
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
public class User {
    private Long id;
    private final String name;
}
```
## @Data
@Dataは、@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructorを一括で付与します。

```java
import lombok.Data;

@Data
public class User {
    private Long id;
    private String name;
}
```
## Springプロジェクトでの使用例
エンティティクラスの例
Spring BootアプリケーションでのLombokの使用例として、エンティティクラスを紹介します。

```java
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}
```
## コントローラークラスの例
コントローラークラスも簡単に作成できます。

```java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class UserController {
    
    @GetMapping
    public String getUsers() {
        return "List of users";
    }
}
```
# 【まとめ】
Lombokは、Springプロジェクトでの開発を大幅に効率化するための強力なツールです。定型的なコードの自動生成により、開発者はビジネスロジックに集中できるようになります。
デグレードを防ぐには？

# はじめに
こんにちは。塚田と申します。

最近のお仕事では今まで自分たちが作成した機能のバグ修正を行っています。
しかし、修正を行う中でデグレを発生させてしまうこともありました。
今回は私がデグレを防ぐために行っていることを書いてみました。

# 参照先の閲覧
普段私はVisualStudioを使用しているのでVSでできることを書いてます。
VSでは修正した特定の関数が他にどこで呼ばれているのかを確認できます。この機能を活用することで変更する際に影響を受ける範囲を把握できます。
また、Ctrl + Shift + F でソリューション全体検索し、関数名やクラス名を検索することで、参照箇所を網羅的に確認できます。


# コードレビュー
自分が書いたコードを他の開発者がチェックすることです。逆も然り。
・潜在的なバグや問題が早期に発見し、修正できる。
・より効率的なコードを書くためのフィードバックをもらえる。
・チーム全体で情報を拡散することで全体のスキルアップにもつながる。
以上の利点があり、これもデグレを防ぐために必要な業務です。

# おわりに
デグレはシステムの信頼性が損なわれる危険性もあるので十分注意する必要があります。変更が既存機能に影響を与えないよう細心の注意を払って修正しましょう。
私も気を付けます。

以上、塚田でした。
PG::UndefinedTable: ERRORの解消方法

# PG::UndefinedTable: ERROR
外部キーの追加を行った際に`PG::UndefinedTable: ERROR`が発生。

# エラー内容
```
PG::UndefinedTable: ERROR:  relation "モデル名" does not exist
```

`$ rails db:migrate:status`で現在のmigrationファイルを確認
```
Status   Migration ID    Migration Name
--------------------------------------------------
　down   2024xxxxxxxxx1  Create 子
　down   2024xxxxxxxxx2  Create 親
```
外部キーを設定している場合、親のモデルからmigrationする必要があるが、デフォルトでは古い順から実行されるためエラーになる。

# 解消方法
以下コマンドで参照元である親モデルを先に実行する。
```
$ rails db:migrate:up VERSION=2024xxxxxxxxx2
```

その後、通常通り`$ rails db:migrate`を行えばOK。
WireGuard VPNとは？(簡易ver.)



#### はじめに

バーチャルプライベートネットワーク（VPN）は、オンラインでのプライバシーとデータセキュリティを提供するために広く利用されています。しかし、VPNの技術は単純ではなく、背後には複雑なプロセスがあります。本稿では、特に技術者向けに、新しい通信プロトコルであるWireGuardと、その分散型VPN（dVPN）における役割について紹介します。

#### WireGuardの概要

WireGuardは、シンプルで高速かつ安全なVPNプロトコルとして注目されています。2015年に開発が始まり、2020年にはLinux向けにリリースされました。そのシンプルさと効率性から、さまざまなオペレーティングシステムやデバイスで急速に普及しています。

#### WireGuardの技術的特徴

1. **ハンドシェイクと鍵交換**
   - WireGuardは、Noise_IKハンドシェイクを使用し、クライアントとサーバー間の鍵交換を行います。これにより、完全前方秘匿性が保証され、キーコンプロマイズ攻撃からの保護が強化されます。

2. **暗号化と認証**
   - ChaCha20-Poly1305アルゴリズムを使用してデータを暗号化し、Blake2ハッシュ関数を利用してデータの整合性を確認します。

3. **トランスポートとルーティング**
   - ユーザーデータグラムプロトコル（UDP）を使用して効率的なデータ転送を実現し、TCPのオーバーヘッドを回避します。

#### WireGuardの利点

- **速度**: OpenVPNに比べ最大50％高速で、低いデータオーバーヘッドを実現。
- **セキュリティ**: 最新の暗号化アルゴリズムを採用し、軽量なコードベースによりセキュリティリスクを低減。
- **オープンソース**: 簡潔なコードベースにより、監査が容易で、透明性が高い。

#### WireGuardの欠点

- **難読化の欠如**: トラフィック難読化機能がなく、ネットワーク監視に対する耐性が低い。
- **互換性の制限**: 一部のルーターでのサポートがまだ進んでいない。

#### 分散型ネットワークとMixnet

WireGuardのプロトコルは、分散型VPN（dVPN）で特に有用です。dVPNは、ユーザーのプライバシーを保護するための分散型ネットワークアーキテクチャを提供しますが、従来のVPNと比べて速度の問題がありました。WireGuardの高速かつ効率的なルーティングプロトコルは、この問題を軽減し、より迅速なデータ転送を可能にします。

#### 結論

WireGuardは、従来のVPNプロトコルに比べて多くの利点を提供し、分散型ネットワークにおいてもその価値を発揮します。オンラインプライバシーを強化するために、技術者はこのプロトコルを活用し、新しいdVPNソリューションの構築を検討すべきです。

# sponsor

HStorageは、高度なセキュリティ機能を提供しているオンラインストレージサービスです。

![Screenshot 2024-08-07 at 2.26.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672851/82985efd-ae04-b64f-49eb-502d257897c3.png)
https://hstorage.io/

# 参考リンク

- [Nym公式サイト](https://nymtech.net/)
- [Nymのミキシングネットワーク - Wikipedia](https://ja.wikipedia.org/wiki/Nymミックスネット)
- [Nymホワイトペーパー](https://nymtech.net/nym-whitepaper.pdf)
- [分散型VPN と中央集権型VPN:違いの全て](https://note.com/koko_crypto/n/n71fe7e92b68a)
- [ミックスネットとは何か？ VPNによる比類なきオンラインプライバシー](https://note.com/koko_crypto/n/n302e7516f691?magazine_key=m0129d65e3526)
- [Sphinx暗号-Nymを支える匿名データフォーマット](https://qiita.com/pseudonym2/items/107cf005e9cab0b165b6)
- [ココナッツ認証（Coconut Credentials）とは？- プライバシーを保護するゼロ知識証明技術](https://qiita.com/pseudonym2/items/b2739ae32f4fb29de0b6)

# コミュニティ

- [Nym日本コミュニティ - Telegram](https://t.me/nymjapanese)
- [Nym日本コミュニティ - Discord](https://discord.com/invite/nym)
- [Nym日本コミュニティ - LINEオープンチャット](https://line.me/ti/g2/0YGYYq4EoQZ8fL5FYQmqU4O9SRuE_a6YX19GtA?utm_source=invitation&utm_medium=link_copy&utm_campaign=default)
- [Nym 公式LINE(現在非稼働)](https://line.me/R/ti/p/@986ytsdx?from=page&accountId=986ytsdx)
- [Nymプロジェクト日本語アカウント - X](https://x.com/nymproject_jp)
numpy.cov(X.T) 分散共分散行列について

## 背景
dataframeをndarrayへと変換した後、分散教分散行列を求める方法が調べても見つからなかったため、以下に方法を示す。
（見つからなかっただけで、絶対にどこかの記事に書いてあると思う...）

## 分散共分散行列
```python
import numpy as np
x = np.array([1,2,3,4,5,6,7,8,9])
y = np.array([9,8,7,6,5,4,3,2,1])
```

上記のデータxおよびyの分散共分散行列はどのように求めることができるだろうか。

```python
np.cov(x,y)
```

![スクリーンショット 2024-07-31 20.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845905/02c1ae0f-2e52-5509-2390-ab196603e563.png)

上記の通り書くことで分散共分散行列を求めることができる。
では、一方で以下のようなデータの場合どうだろうか。

```python
X = np.vstack((x,y)).T
X
```

![スクリーンショット 2024-07-31 20.40.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845905/7970336e-b6fe-091f-ba8b-9365e5198afa.png)

xとyをそれぞれ列に持ち、各行に値が格納されている場合だ。
（単純にDataFrameと同じ構造だと思って欲しい）

先ほどと同様に以下の通りプログラムを動かしてみる。
```python
np.cov(X)
```

この場合9x9の行列が返ってくる。
（コメントでこの行列が何をしてしているのか教えて欲しい...）
/*以下追記
@WolfMoon さん、ありがとうございます。
これはcov関数の引数「rowvar」がデフォルトでTrueであり、
この場合行を変数として認識してしまう。
そのため、9個の変数を持つと認識し、9x9の行列が作成されてしまう。
以下のように記載することで、正しく分散共分散行列を求めることもできる。
```python
np.cov(X, rowvar=False)
```
*/

これはXが9x2の行列のため、9x9の行列が返ってきてしまっている。
では、以下のように書いてみたらどうだろうか。

```python
np.cov(X.T)
```

![スクリーンショット 2024-07-31 20.55.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845905/d97e6683-7288-ef7a-ae46-4d583352071b.png)

問題なく求めることができたようだ。

## まとめ
dataframeと同様の構造を持つndarrayより分散共分散行列を算出する場合は、
np.cov(X.T)のように、転置した行列をcov関数の引数に格納するようにすれば良い。
東京と沖縄の２拠点生活が私の夢。

自分向けメモです。

## こんな生活がしたい

・東京　家族と生活する場
・沖縄　遊ぶ場

## 東京で週5稼働・8時間の仕事をしている間は無理？

週5稼働でも、テレワークで自由に場所を選んで良いなら、
月曜日に沖縄行って、月〜金は仕事。
金夜〜日まで遊んで、日夜に東京に帰る。
ということもできなくはない。

東京で東京の仕事する　おもろない・高単価
東京で沖縄の仕事する　まあまあ・低単価
沖縄で沖縄の仕事する　おもろい・低単価
沖縄で東京の仕事する　おもろない・高単価

東京の仕事（今と同じ仕事）しても、おもろないわな。

## 沖縄に仕事しに行く体制にすれば？

法人化して、沖縄へは仕事をしに行く体にすれば良い。
・旅費
・宿泊費
は経費になる。
オフィス借りたら家賃全部経費にできる。
旅費規定を作れば、行くごとに給与も出る。

### オフィス

・せっかくなら海に近い場所をオフィスにしたい。
・最初はボロくて我慢。5万円で1LDK。

## 意味、ある？

沖縄に行ったとして・・・
部屋に閉じこもってテレワークして、意味ある？
土日だけ沖縄に遊びに行けばいいじゃない。

## 甘い

・華々しいこと
・楽すること
・遊ぶこと
しか考えてないのではないか。

何するにしても、泥臭いことを想定せよ。
泥臭いことをする覚悟があれば、何やってもうまくいく。
泥臭いことを避けていたら、何もうまくいかない。

## 何がしたいか？

・休みの日、海遊びしたい。スキューバダイビング。
・沖縄に関する本を書きたい。
　文化に関すること、現代の沖縄生活に関すること。
 　沖縄に行きたくなるような本を書きたい。
・沖縄に住んでる人と仕事してみたい。
・沖縄経済に貢献できる仕事してみたい。
・家族を呼んで沖縄で遊びたい。
・夕日を見ながら浜辺でご飯食べたい。

## 大学のつながり

大学の繋がりを活かして仕事を創出できないだろうか。
・マーケティング（Web企画・制作）
・企画
・販売（企画）
Docker 環境で binding.pry を使ってデバッグする方法


## 初めに
Ruby アプリケーションを Docker コンテナ内でデバッグする際に、`binding.pry` を使いたいと思ったことはありませんか？この記事では、Docker 環境で `binding.pry` を設定する手順を解説します。



## ステップ 1: Gemfile に pry を追加

まず、`Gemfile` に `pry-byebug` を追加します。

```ruby
gem 'pry-byebug'
```

これで、`bundle install` を実行

```bash
bundle install
```



## ステップ 2: docker-compose.yml の設定

`docker-compose.yml` ファイルを作成または編集して、デバッグ用の設定を追加します。

```yaml
docker-compose.yml
web:
build: .
command: bash -c "rm -f tmp/pids~

/////↓この2文を追加
stdin_open: true
tty: true
```

## ステップ 4: binding.pry の追加

デバッグしたい箇所に `binding.pry` を追加します。

```ruby
def some_method
  # ここでデバッグを行う
  binding.pry
end
```

## ステップ 5: コンテナの起動とデバッグ

コンテナを起動し、デバッグを行います。

```bash
docker-compose up -d
```

`binding.pry` に到達すると、コンソールでデバッグセッションが開始されます。コンテナのログにアタッチするためには、別のターミナルで以下のコマンドを実行します。

```bash
docker attach <コンテナ名>
```

`<コンテナ名>` は `docker ps` コマンドで確認できます。

---

これで、Docker 環境内で `binding.pry` を利用してデバッグができるようになりました。ぜひ試してみてください！
【非公式】shodanに見るServiceNow導入顧客数

ServiceNow導入顧客数は440ほど？
shodanで外部公開サーバーを検査できるため、ServiceNowでググる。
2019年のNow at workでは120社とか聞いた記憶がおぼろげにあるので、割合に妥当な数値なのかな？🤔
![Screenshot_2024-07-31-20-46-58-09_abb9c8060a0a12c5ac89e934e52a2f4f.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/133f03cc-73d5-5e83-cb17-5c61316f991b.jpeg)


![Screenshot_2024-07-31-20-47-18-26_abb9c8060a0a12c5ac89e934e52a2f4f.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/6fc59668-0dc7-11aa-96e3-bc27c5f4a31c.jpeg)
MongoDB,Postmanを使ってweb開発環境を作る

どうしてもデータベースとAPIを使ったweb開発がしたかったので、
shincodeさんの動画を参考にやってみました。
https://www.youtube.com/watch?v=JBCykXLfvv0

データベースにデータ送信をするまでにかなりの量のコードを書くので、どこに問題があるのかわからないです。
VScodeではエラーが出なかったのでなおさらわからないです。

そういった点がweb開発の難しさかなあと思います。
ある程度javascriptのライブラリに関する基礎が必要で、この動画を見ただけだと仕組みがわからない関数をたくさん使用することになると思います。また動画内でも〇〇が抜けていたのでエラーが出ましたというような補足もあり、ある程度経験のある人向けだと感じました。

就職活動をするならポートフォリオとしてwebアプリやサイトを作りましょうとよく聞きますが、そう簡単ではないのでプログラミングスクールに通うのは悪くないかと思います。

下の画像について、データを送信しましたがデータベースに送信できなかった時に出たエラーです。一応エラーを読んでいますがどう対処するべきなのかわかりません。一般的なエラーメッセージ、具体的なメッセージが適切ではないとのことですが、何を伝えてくれているのかわからないです。

調べてみたところサーバー側のエラーでユーザーが対処できる問題ではないみたいです。
https://baremetal.jp/blog/2022/06/06/1210/
より
web開発は難しいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828982/a09e6bab-54bc-cfbd-2617-08c0c9ffbbd9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828982/f559306b-3fd6-479e-09d1-8fe92be22f8c.png)
LS220D を手に入れたので、sshでログイン

# LS220D入手

とあることから、LS220Dを手に入れました。
ラズパイでNASとか言って遊んでましたが、やっぱりちゃんとしたNASはちゃんとしてました！
RAID1に対応し、ラズパイの100MbpsのLANと違い1000BASEで高速、外部からのアクセスにも対応しています。

# SSHを有効化する
とまるまるラズパイと同じような仕様になりかねませんが、
将来やBCPを見据えた結果、LS220D自身で色々できると便利になると思っています。
具体的には、AWS S3へのバックアップの自動化などをすることで、
冗長性の確保ができます。

# 現在の仕様
LS220D (LS220DF6B) Version 1.73-0.02 DTCP-IP 5.2.133-20151113

# やりかた
https://huruyosi.hatenablog.com/entry/2015/06/27/211813

を参考にしました。
使うものは下記を、JAVA環境のある端末から操作する。
けど、javaを唯一入れてる端末は、一番古いラズパイなので、これから対応する。

https://github.com/1000001101000/acp-commander

ポートを開放していなかったので、開けろと言われる。

    sudo ufw allow 22936

でとりあえず、ポート開放、または必要に応じて、無効化する。

    java -jar acp_commander.jar -t 192.168.x.xxx -ip 192.168.x.xxx -pw xxxxx -c "sed -i 's/UsePAM yes/UsePAM no/g' /etc/sshd_config"
    Welcome to ACP Commander v0.6 (2021), the tool for Buffalo stock firmware control!
    
    OK (ACP_STATE_OK)Changing IP... ACP_STATE_PASSWORD_ERROR
    
    Please note, that the current support for the change of the IP is currently very rudimentary.
    The IP has been set to the given fixed IP, however DNS servers and the gateway have not been set.
    Use the WebGUI to make appropriate settings.
    osmc@osmc-Gilbert:~/works$ java -jar ./acp_commander.jar -t 192.168.x.xxx -ip 192.168.x.xxx -pw xxxx -c "(echo yyyy; echo yyyy) | passwd"
    Welcome to ACP Commander v0.6 (2021), the tool for Buffalo stock firmware control!
    
    OK (ACP_STATE_OK)Changing IP... ACP_STATE_PASSWORD_ERROR
    
    Please note, that the current support for the change of the IP is currently very rudimentary.
    The IP has been set to the given fixed IP, however DNS servers and the gateway have not been set.
    Use the WebGUI to make appropriate settings.



https://qiita.com/ikeisuke/items/96a5fbdf823e04fbc2f7

https://huruyosi.hatenablog.com/entry/2015/06/28/004847

なんかIPアドレス、パスワードがどうのこうの言われますが、
を参考にすると、ルートでログインすることができました。

ACP_STATE_PASSWORD_ERRORなどとエラーが出ていますが、無視していいようです。


とりあえず今日は、はここまで！

    [root@LS220DF6B ~]# cat /proc/version
    Linux version 3.3.4 (root@nasbuild) (gcc version 4.6.2 (Linaro GCC branch-4.6.2. Marvell GCC 201201-883.01c949de) ) #1 Mon Nov 18 21:33:52 JST 2019


他に参考になりそうなページ

https://nagamitsu1976.hatenadiary.jp/entry/2020/09/02/150136

https://itlogs.net/buffalo-terastation-acp-commander/?amp=1
パソコンについて

# パソコンについて
ITといったらパソコンだと思います！
パソコンはおもに5つの要素で構成されています。

１、入力装置
２、記憶装置
３、制御装置
４、演算装置
５、出力装置
* * *
1、入力装置
入力装置は、コンピュータに情報を送るためのものです。例えば、キーボードやマウスがあります。キーボードでは文字を入力し、マウスではポインタを動かしたりクリックしたりします。
* * *
２、記憶装置
記憶装置は、大切なデータを保存する場所です。コンピュータが電源を切ってもデータが消えない安全な場所です。ハードディスクやCD-ROM、そしてメモリーも記憶装置に含まれます。
* * *
３、制御装置
制御装置は、コンピュータの「頭脳」のようなものです。全体や一部の処理を管理し、コンピュータが正しく動作するようにします。プロセッサの一部であり、CPUとも呼ばれます。
* * *
４、演算装置
演算装置は、数学的な計算や論理的な処理を行う部分です。四則演算（たし算、ひき算、かけ算、わり算）や、論理演算（ANDやORなど）を行います。これにより、コンピュータはさまざまな問題を解決します。
* * *
５、出力装置
出力装置は、コンピュータが処理した結果を人が見たり、印刷したりするための装置です。例えば、ディスプレイで画面に表示される文字や画像、プリンタで紙に印刷されるものなどがあります。
* * *

## ハードウェアとは

パソコンのハードウェアは、物理的な部品や装置のことを指します。これらの部品が協力して、コンピュータが機能する仕組みです。

## ソフトウェアとは

コンピュータの動作や振る舞いを制御するプログラムやデータのことを指します。ハードウェアが物理的な部品や装置であるのに対し、ソフトウェアはその動作を可能にする「ソフト的な部分」と言えます。
* * *
### システムソフトウェア

役割: コンピュータ全体の動作や管理を担う基本的なソフトウェアです。
例: オペレーティングシステム（OS、Windows、macOS、Linuxなど）、デバイスドライバ（ハードウェアとのインターフェースを提供）、システムツール（ファイル管理、ネットワーク設定などを行うソフトウェア）などがあります。
* * *
### アプリケーションソフトウェア

役割: 特定の作業や目的に応じて設計されたプログラムで、ユーザーが直接使用します。
例: ワードプロセッサ（Microsoft Word、Google Docsなど）、スプレッドシート（Microsoft Excel、Google Sheetsなど）、ウェブブラウザ（Google Chrome、Firefoxなど）、メディアプレーヤー（VLCメディアプレーヤー、iTunesなど）、ゲーム、写真編集ソフト（Adobe Photoshopなど）などがあります。
* * *
### 開発ツール

役割: ソフトウェア開発者がソフトウェアを作成するための支援をするツールや環境です。
例: 統合開発環境（IDE、Visual Studio、Eclipseなど）、コンパイラ（ソースコードを機械語に変換するプログラム）、デバッガ（プログラムのバグを発見・修正するツール）などがあります。
VCとVPについての現状を考察してみる

## 初めに

VCとVPの違いについて、現状の自分の理解を備忘として記録します。

## 前提知識
Issuer：VCを発行する対象
Holder：VCを保持し、自分のデジタルウォレットへ格納する対象
Verifier：Holderから提示されたVCについて、VCが有効的かを確認する対象

## VC

VC（Verifiable Credential）とは、検証可能な資格情報のことを指します。

[IPA](https://www.ipa.go.jp/)が実施している資格試験を例に出すと、
IPAが発行している、受験者本人の資格試験に関する情報（登録した氏名/住所/合格者番号など）のことを指します。

## VP
VP（Verifiable Presentation）とは、検証可能なプレゼンテーションのことを指します。

上述同様、[IPA](https://www.ipa.go.jp/)の資格試験の合格証書と、併せて就職活動を例に出してみます。
合格証書（VC）を受け取った就活生（Holder）が、企業の採用面接において、資格試験に合格した証明として、VCを企業の採用担当者（Verifier）へ提示します。
その際に、採用担当者へVCを提示する際に、Verifier向けにVCを変換すること（HolderがVCをVerifier向けに利用すること）をVPと理解しました。

## まとめ
VCに関する記載はネット上でも確認ができましたが、VPについてはこれといった断定的な情報がなく、自分の理解もあまり自信がないため、引き続き学習を進め理解を深めていきます。
起動中のシェルで入力されているコマンド情報を取得する

Linux環境において、あるユーザーが入力したコマンド履歴を取得するには、以下のように~/.bash_historyファイルを参照するといいです。

```bash
[root@ip-192-xxx ~]# cat ~ec2-user/.bash_history
sudo su -
ls -ld /bin
ls -l /
```

しかし、この情報は入力済みのコマンド履歴の参照となります。
現在、起動しているシェル上で入力されているコマンドをリアルタイムに監視したいという場合、straceコマンドを利用し、以下のように確認することができます。
まずは、監視対象となるシェルのプロセスを確認します。
例えば、sshで接続しているあるユーザーが入力しているコマンドを確認するという場合、whoコマンドで、端末名を確認します。

```bash
[root@ip-192-xxx ~]# who
ec2-user pts/0        2024-07-30 23:52 (153.242.xxx.xxx)
ec2-user pts/1        2024-07-31 00:21 (153.242.xxx.xxx)
ec2-user pts/2        2024-07-31 07:15 (192.0.xxx.xxx)
```

ユーザー名やログインした日時、接続元のIPアドレスにより、監視対象のユーザー端末を確認します。
今回は、pts/2端末のユーザーが入力したコマンド情報を監視します。
以下のコマンドを実行し、シェルのPIDを確認します。

```bash
[root@ip-192-xxx ~]# ps -ef | grep 'pts/2'
ec2-user  312776  312773  0 07:14 ?        00:00:00 sshd: ec2-user@pts/2
ec2-user  312777  312776  0 07:14 pts/2    00:00:00 -bash
root      313161  295368  0 07:23 pts/1    00:00:00 grep --color=auto pts/2
```

端末名が表示されているシェル（今回の場合bash）のPIDを確認します。
ps -efコマンド実行時、2列目の値がPIDになるため、今回は312777というのが監視対象のPIDとなります。
そして、以下のようなstraceコマンドを実行します。
```bash
[root@ip-192-xxx ~]# strace -p 313673 -e trace=write
strace: Process 313673 attached
write(2, "l", 1)                        = 1
write(2, "s", 1)                        = 1
write(2, "\n", 1)                       = 1
write(2, "\33[?2004l\r", 9)             = 9
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=313702, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
```

行末に「= 1」という記述がある部分が監視対象となっている端末でキー入力された内容です。
入力されたキー1つにつき、1行結果が表示されます。
上記はlsコマンドを引数なしで実行したという例です。
"\n"は改行情報ですので、enterキーが押されているということがわかります。

:::note warn
この方法でのコマンド情報の監視、取得は、もちろん対象となるユーザーの承諾を得るなど、合法的な状態で行うようにしましょう。
:::
ChatGPTにVBAを教わりました。

こんにちは、普段はヘルプデスク業務を実施している水野と申します。

文系出身の自分は、現在のプロジェクトに参画して以来
プログラミング等から一切離れてしまっていたので、
通常業務でも役立つ、VBAから少しずつ触っていこうかと思います。


### 勉強方法について
まずは”VBAってどんなことが出来るのか”というところから知るために
特定のサイトに記載されている情報の内、特定のクラスを含む要素だけを
表示させるという処理をChatGPT先生に教わりつつ、初歩的な質問からぶつけていきます。

ChatGPTから返ってきたコードが以下になります。
```
Sub GetClassDataFromHTMLFile()
 Dim htmlFilePath As String
 Dim htmlDoc As Object
 Dim elements As Object
 Dim element As Object
 Dim className As String
 Dim output As String

 'HTMLファイルのパスを設定
　htmlFilePath = ""  '任意のパスを設定
　className = ""  '取得したいクラス名を指定

　'HTMLファイルを読み込む
　With CreateObject（"Scription.FileSystemObject"）.OpenTextFile(htmlFilePath)
   　 Set elements =body.innnerHTML = .readAll
    　.close
　End With

　'指定されたクラス名の要素を取得
　Set elements = htmlDoc.getElementsByClassName(className)

　'取得した要素のテキストを出力
　For Each element In elements
　　　output = output & element.innnerText & vbCrLf
 　 Next element

　'結果を表示
　 MsgBox output
 End Sub


```

※今回は諸事情によりインストール関連の作業が一切できないので、
静的なHTMLコンテンツに限るという条件でお願いした結果になります。

### 質問をしていく
このような回答が出てきたので、それに対して実際にどんな動きになるのか確かめる。
また、「Subってなに？」「Dimってなに？」みたいな形で、
根掘り葉掘り質問していきます。
実際Subってなに？って質問をした際の回答を一部紹介します。
```
Subは、VBA（Visual Basic for Applications）における「サブルーチン(Subroutine)」を定義するためのキーワードです。サブルーチンは一連のコードブロックで、特定のタスクを実行するために使用されています。
----------------------------------
Sub SubName（）
　　　　'ここにコードを記述
End Sub
----------------------------------
・Sub:サブルーチンの開始を示すキーワード。
・SubName：サブルーチンの名前。任意の名前を付けることができます。
・End Sub：サブルーチンの終了を示すキーワード
```
あくまで一部ではありますが、結構丁寧に教えてくれるので、
どんどん質問をしていき、基礎的なところを抑えていきます。

### 今後について
来月は、このコードを活用して、出力結果をExcelのシートに記載してもらい、
それをOutlookのテキスト内に代入できないか。
というのを試していこうと思います。
論文よみよみ : RWKV

2023年に公開された論文 [RWKV: Reinventing RNNs for the Transformer Era](https://arxiv.org/abs/2305.13048) を読んでみた。もしかするとAIに詳しくない人も耳にするかもしれない、現在多用されているAIモデル "Transformer" と、昔ながらのモデル "RNN" を組み合わせて、より精度良くしたものと言える。

この論文は何を言ってるんだろう？何がすごいんだろう？ということが伝わるといいなと、書いてみることにする。

# RWKVとは？
RWKV (Receptance Weighted Key Value) は、新たなシステムを導入した機械学習モデルのこと。これを理解するにはまず、TransformerとRNNを知っておく必要がある。

![RWKV_model](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3849476/01c70de9-8495-c2be-a39d-4fb981667d6b.png)
(図の左側がRWKVを導入している部分、図の右側が入力から出力までのモデル)

## Transformerとは
自然言語処理に革命をもたらしたとされるモデルである。最近よく聞くChatGPTや生成AIも今やこれが使われている。
自然言語処理の精度が飛躍的に向上したと言われるこのTransformerであるが、配列の長さに応じて必要メモリ量や計算量が2次関数的に増加してしまう。
つまり、Transformerは『高精度だけど複雑』なモデルといったところだろう。

## RNNとは
RNN (Recurrent Neural Network) はある入力して出力するだけでなく、その出力をまた学習に戻して、といったように再帰的なシステムを導入したモデルである。以前からあるモデルであり、必要メモリ量や計算量は線形性がある。しかし、並列化等に限界があるためTransformer程の精度を出すことは難しい。
つまり、RNNは『単純だけど低精度』なモデルといったところだろう。


整理すると、
Transformer : 『高精度だけど複雑』
RNN : 『単純だけど低精度』
といったようになっています。これらのいいとこ取りをしたのが、このRWKVである。


# 何がいいの？
Transformerの『高精度』という部分と、RNNの『低計算量』という2つのメリットを掛け合わせたものである。この2つの観点からいい点を説明することとする。

## 精度
ChatGPTに使われているモデルをRWKVに変更したところ、性能が44.2%から74.8%に向上した。
その他にも、以下のようにいろいろなタスクについて学習が行われた。
![RWKV_performance](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3849476/df99d40c-86d8-9dc9-25ff-5e04c2d5692d.png)
オレンジ色で示すのが、RWKVの正答率である。

## 計算量
Transformer等と異なり、トークン(単語)数と時間が比例している。Transformerなどではトークン数が増加すると2次関数的に計算時間が増加するため、自然言語処理で扱う文章が長くなると計算時間が大幅に増加してしまう。しかし、RWKVはこのトークン数と時間が線形のため、扱う文章が長くなったとしても計算時間の増加は比例関係である。そのため、長い文章を扱うときにその計算量の速さがメリットとして現れる。

![RWKV_time](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3849476/940d2617-0b39-9a53-a5ab-7534d6bd6e4c.png)
紫色で示すのが、RWKVの計算時間である。

# 結論

RWKVを使うことにより、Transformerの『高精度』と、RNNの『低計算量』を兼ね備えた新たなモデルとなった。より長い文章を扱えることになったことにより、応用することで今後の自然言語処理の精度向上が見込まれる。
PowerBIにおけるデータモデリングの重要性

PowerBIでのダッシュボード作成において、個人的に一番重要、力を入れるべきところはデータモデリングだと思っています。

今回はデータモデリングの重要性について述べています。

## 目次
[PowerBIにおけるデータモデリングとは](#PowerBIにおけるデータモデリングとは)
[データモデリングの重要性](#データモデリングの重要性)
[データモデリングの基本要素](#データモデリングの基本要素)
[まとめ](#まとめ)

## PowerBIにおけるデータモデリングとは
データモデリングは、データの可視化や分析の前段階の作業にあたり、データの構造を設計し、データ同士の関係を提議するプロセスです。
データソースから取得したデータを意味のある形式に整えることで、視覚化や分析の精度を高め、PowerBIのパフォーマンスを最大限に引き出すことができます。

データの構造を設計し、データ同士の関係を定義するプロセスです。Power BIでは、これによりデータソースから取得したデータを意味のある形式に整え、視覚化や分析をスムーズに行うための土台を作ります。

具体的には、以下のような作業が含まれます：
**テーブルの設計：** データをどのようにテーブルとして整理するかを決める
**リレーションシップの設定：** テーブル間の関係を定義し、データの統合を行う
**計算列とメジャーの作成：** データの集計や計算を行い、分析に必要な指標を作成する

## データモデリングの重要性
データモデリングは以下の観点から非常に重要な工程です。

**パフォーマンスの向上：** 適切なデータモデリングにより、大量のデータでも迅速に処理し、パフォーマンスを最適化できる
**精度の高い分析：** データの関係性を正しく設定することで、分析結果の精度を高めることができる
**ユーザー体験の向上：** 視覚化やレポートの構築がスムーズになり、ユーザーの操作性が向上する

## データモデリングの基本要素
データモデリングにはいくつかの基本的な要素があります。ここでは、主要な要素を紹介します。

**テーブルの設計**
データソースからインポートしたデータは、通常は「テーブル」という形式でPower BIに取り込まれます。テーブルの設計には、どのデータをどのテーブルに配置するかを決定することが含まれます。データが適切に分割され、意味のある形で整理されていることが重要です。

**リレーションシップの設定**
異なるテーブル間の関係を設定することで、データの統合を実現します。たとえば、売上データテーブルと顧客データテーブルをリンクさせることで、売上の分析を顧客ごとに行うことができます。

**計算列とメジャー**
計算列はテーブル内で各行に対して計算を行い、メジャーは集計された結果を計算します。これにより、売上の合計や平均、割合などの重要な指標を容易に分析できます。

## まとめ
Power BIのデータモデリングは、データの分析をより効果的に行うための工程です。テーブルの設計、リレーションシップの設定、計算列とメジャーの作成といった要素を理解し、実践することで、データの価値を最大限に引き出すことができます。データモデリングのスキルを磨くことで、より精度の高い分析とインサイトを得ることができます。
リーダブルコード備忘録

# はじめに
今回は、リーダブルコードを読んで備忘録としてメモしておいた内容を共有します。
自分はエンジニア１年目の時に実装時のチートシートとして使用してました。


## 良いコードとは

プログラミングにおいて、短い行で書かれた頭のいいコード＝いいコードではない。
理解しやすいコードこそが良いコード。
読みやすいコードを書くことによって、バグを減らし保守性を高めることができる
自分しか理解できないコードを書くとコードの内容を忘れた頃の自分も苦労する

## 名前について
- 汎用的な名前を避ける。
- スコープが小さければ短い名前も可。
- 不要な単語を捨てる。例: `convertTostring` → `ToString`
- エンティティごとに異なるフォーマットを使用する。例: インターフェースはアッパーキャメル。
- 他の意味と間違えられない名前を付ける。
- Booleanの意味を明確にする。
- 名前を複数検討し、機能を知らない人にも伝わるかどうか確認する。

## コードの見た目

- 一貫性のある改行をする
- 重複を削除
- 大切な部分を見やすく
- 縦の線を揃える
- 似ているコードは似ているように見せる
- 一貫性と意味のあるコードにまとめる

## コメント

- コードを段落ごとに分割して要約コメントを入れる
- コードからすぐわかることは書かない
  - 名前でわかりやすくできる場合は名前を変える。
- コードの欠陥にコメントをつける
- なぜその定数にしたか背景をコメントするとわかりやすい
- 初めて読んだ人が疑問に思う箇所にコメントを入れる
- コードの全体像のコメントを入れる
  - 新たにプロジェクトに参加した人にわかりやすくする。
- コメントするよりも優れたコード
  - ひどいコードを補うコメントよりもコードを改善する。
- コメントは領域を取りすぎないように
  - 情報の濃度を濃くする。
- 曖昧な表現を避ける
- よくわからない引数はインラインコメントを付ける

## ロジックの単純化

- 条件式の引数
  - 調査対象を左、比較対象（変化する値）を右で統一する。
- 条件は肯定系を使用
- 三項演算子
  - デバッガを使うときも使い辛くなるし、理解しにくいから普通に書く（賛否両論）。
  - 三項演算子を使用して簡潔になるときは使う。
- ネストは浅く
  - 早めに返してネストを浅くする。
- 巨大な式に対して
  - 式の意味を説明する変数を使用する。

例:

```javascript
// 改善前
if(line.split(":")[0].trim() === "admin"){
  // 処理
}

// 改善後
const user_authority = line.split(":")[0].trim();
if(user_authority === "admin"){
  // 処理
}
```

## 変数

- 役に立たない一時変数は使用しない
- 変数のスコープを縮める
- グローバルな変数をクロージャで包んでプライベートにする
- 変数操作の場所が多くなると判断が難しくなる

## コードの抽出

- 関数に無関係な部分は切り出す
- 関数が独立すると汎用コードになり得る
  - テストが楽になるかつ、他のプロジェクトでも使用できる。


## まとめ
エンジニアなりたての時にリーダブルコードを読み、実装時にチートシートとして使用しながら実装を行ってました。
こちらが読んでくださったみなさんの役に立てば幸いです。

https://www.oreilly.co.jp/books/9784873115658/
GoとRedisで作る簡単従業員管理アプリ

# GoとRedisの勉強のために作りました

こんにちは！今回は、Go言語とRedisを使って、シンプルだけど便利な従業員管理アプリを作っていきます。プログラミング初心者の方も、ベテランの方も、一緒に楽しく学んでいきましょう！

## 1. 環境設定

まずは開発環境を整えましょう。GoとRedisをインストールして、必要なパッケージも用意します。

```go
go mod init employee-app
go get github.com/go-redis/redis/v8
```

これで準備オッケーです！さぁ、コーディングを始めましょう。

## 2. Redisクライアントの設定

次に、Redisに接続するためのクライアントを設定します。

```go
package main

import (
    "context"
    "github.com/go-redis/redis/v8"
)

var ctx = context.Background()

func newRedisClient() *redis.Client {
    return redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })
}
```

これで、Redisとの通信準備が整いました。簡単でしょう？

## 3. 従業員データ構造の定義

従業員の情報をどう保存するか考えましょう。構造体を使うと便利ですよ。

```go
type Employee struct {
    ID        string
    Name      string
    Position  string
    Salary    int
}
```

シンプルだけど、必要な情報は押さえていますね。

## 4. 従業員の追加機能

さて、従業員を追加する関数を作りましょう。

```go
func addEmployee(client *redis.Client, emp Employee) error {
    key := "employee:" + emp.ID
    return client.HSet(ctx, key,
        "name", emp.Name,
        "position", emp.Position,
        "salary", emp.Salary,
    ).Err()
}
```

この関数を使えば、簡単に従業員をRedisに追加できますよ。

## 5. 従業員情報の取得

追加した従業員の情報を取得する関数も必要ですね。

```go
func getEmployee(client *redis.Client, id string) (Employee, error) {
    key := "employee:" + id
    val, err := client.HGetAll(ctx, key).Result()
    if err != nil {
        return Employee{}, err
    }

    salary, _ := strconv.Atoi(val["salary"])
    return Employee{
        ID:       id,
        Name:     val["name"],
        Position: val["position"],
        Salary:   salary,
    }, nil
}
```

これで、IDを指定するだけで従業員の情報が取得できます。便利ですね！

## 6. 従業員リストの表示

全従業員のリストを表示する機能も作りましょう。

```go
func listEmployees(client *redis.Client) ([]Employee, error) {
    keys, err := client.Keys(ctx, "employee:*").Result()
    if err != nil {
        return nil, err
    }

    employees := []Employee{}
    for _, key := range keys {
        id := strings.TrimPrefix(key, "employee:")
        emp, err := getEmployee(client, id)
        if err != nil {
            continue
        }
        employees = append(employees, emp)
    }
    return employees, nil
}
```

これで全従業員の情報が一覧で見られますよ。

## 7. メイン関数とアプリの実行

最後に、これまでの機能を組み合わせてアプリを実行しましょう。

```go
func main() {
    client := newRedisClient()
    defer client.Close()

    // 従業員を追加
    addEmployee(client, Employee{ID: "001", Name: "山田太郎", Position: "エンジニア", Salary: 350000})
    addEmployee(client, Employee{ID: "002", Name: "佐藤花子", Position: "デザイナー", Salary: 320000})

    // 従業員情報を取得
    emp, _ := getEmployee(client, "001")
    fmt.Printf("従業員ID 001: %+v\n", emp)

    // 全従業員リストを表示
    employees, _ := listEmployees(client)
    fmt.Println("全従業員リスト:")
    for _, e := range employees {
        fmt.Printf("%+v\n", e)
    }
}
```

これで完成です！実行すると、従業員の追加、情報取得、リスト表示ができるシンプルな従業員管理アプリの完成です。

いかがでしたか？GoとRedisを使えば、こんなに簡単に従業員管理アプリが作れるんです。ぜひ、このコードを基に自分なりにアレンジしてみてくださいね。楽しいコーディングライフを！
[paiza×Qiita記事投稿キャンペーン] Rubyでmod7占いを解いてみた

この記事は **paiza×Qiita記事投稿キャンペーン「プログラミング問題をやってみて書いたコードを投稿しよう！」** キャンペーンへの参加記事です。

https://paiza.jp/pages/campaign/paiza-qiita

今回キャンペーンの候補問題の中から、ランクSの「mod7占い」を解いてみました。

https://paiza.jp/works/mondai/s_rank_skillcheck_sample/mod7

解いたソースコードの全体像は以下にあります。

https://github.com/Umekawa/paiza-open-problem/blob/main/mod7.rb

## 問題分

問題文の詳細ははPaizaの記事の方を読んでいただくとして、要点は

- 最初にカード数が与えられ、その後カードの数だけ入力が与えられる
- すべて異なるカードがn枚与えられる (nは3以上)
- 与えられたカードから同時に3枚選び、3枚のカードの和が7の倍数になる組み合わせ数を出力する

の3点です。

では実際に作成していきましょう。

## 実装

実装は大きく分けて以下のように分割できます。

- 入力を受け取る
- 組み合わせ数を計算し出力する

### 入力を受け取る

まずは入力を受け取りましょう。

```ruby
card_num = gets.chomp.to_i
mod7_result = {}
7.times {|i| mod7_result[i.to_s] = 0}

card_num.times { mod7_result[(gets.chomp.to_i % 7).to_s] += 1 }
```

1行目はカードの取得として、2~3行目で変数`mod7_result`というハッシュを定義しています。
これは与えられた数の剰余の出現回数をカウントするためのものです。
今回はすべて異なる数という前提が今回は存在するため、重複を考える必要がなく、mod7の値のみの情報で完結することができます。

入力例を実際に入れてみると`mod7_result`の中身は以下のようになります。

```:入力
10
1
2
3
4
5
6
7
8
9
10
```
```ruby:mod7_result
{"0"=>1, "1"=>2, "2"=>2, "3"=>2, "4"=>1, "5"=>1, "6"=>1}
```

### 組み合わせを計算する

それでは組み合わせを計算します。
mod7の値は0~6の値の範囲であるため、mod7の値を3足して生成される7の倍数は0も含めて0,7,14となります。
また、3枚のカードの組み合わせを今回以下のように分割します。

- mod7した値がすべて異なる値である
- mod7した値の同じ組が一つ存在する
- mod7した値が3枚すべて同じである

それぞれの場合についてみていきましょう。

#### 全て異なる場合
3つのmod7された値が異なりかつ、7の倍数になるのは以下の組み合わせです。(左から小さい値)
```
[0,1,6]
[0,2,5]
[0,3,4]
[1,2,4]
[3,5,6]
```

この場合は純粋な掛け算で良いのでそれぞれの出現回数の積を計算します。

```ruby
sum = 0
[[0,1,6],[0,2,5], [0,3,4] ,[1,2,4],[3,5,6]].each do |a,b,c|
  sum += mod7_result[a.to_s] * mod7_result[b.to_s] * mod7_result[c.to_s]
end
```

#### mod7した値の同じ組が一つ存在する場合

2枚が同じmod7の値かつ、1枚は違うmod7の値かつ相和が7の倍数になるのはmod7が以下のような組み合わせです。
```
[1,1,5]
[2,2,3]
[3,3,1]
[4,4,6]
[5,5,4]
[6,6,2]
```

今回は重複が1回出現するので組み合わせ数は同じ組が存在する方の出現回数を`a`、しない方の出現回数を`b`としたとき、以下のようになります。
```math
\frac{a * (a-1) }{2} * b
```

これをコードに落とし込むと以下のようになります。

```ruby
[[1,5], [2,3], [3,1], [4,6], [5,4], [6,2]].each do |a,b|
  sum += (mod7_result[a.to_s] * (mod7_result[a.to_s]-1)/2) * mod7_result[b.to_s]
end
```

#### 全て同じmod7の値になる場合
全てmod7で同じ値になるのは、mod7=0、つまりすべて7で割り切れる値の時のみです。
重複が2回存在する組み合わせなので、mod7が0になる数の出現回数をaとして、組み合わせ数は以下のような式になります。
```math
\frac{a * (a-1) * (a-2)}{6}
```

これをコードに落とし込むと以下のようになります。

```ruby
sum += mod7_result['0']*(mod7_result['0']-1)*(mod7_result['0']-2)/6
```

最後にここまで足してきた組み合わせ数を格納した変数sumを`p`や`puts`などの関数を使って出力することでこの問題は完了となります。

## 解いてみた感想
入力された値をmod7に落とし込むことと、組み合わせを分解することに気が付けばあとはスッと解くことができました。きちんと計測はしてないですが、20分くらいで提出したかと思います。
自分はPaizaの会員でSランクも取得していたりするのですが、通常のpaizaの問題はクローズドなので、こうしてQiitaの記事を書いたりGitHubにコードを上げたりというのは不思議な体験に感じました。

今回問題なくテストケース自体は突破しましたが、もっと良い方法などがあればコメントいただけると幸いです。
遺失物取扱所～繰り返すミスの備忘録～

## 総合案内
なぜか見つからないミス、見つけたら全く大したことないのに、、、
そんな見落としがちなミスを拾い集めておけば少しは見つける手助けになる？？
そんな思いつきで書き連ねてみました。初学者のミスなんで大したものはないですがだからこそあるあるなんじゃないかと思います。




## お探しの方向け窓口

#### 取り扱い物
私はプログラム未経験でこの春入社したところなのでまともに触れたのがJavaしかありません。そのため、このブログは**Javaの落とし物限定**です。

#### 拾得状況・拾得物一覧
###### Scannerクラスのメソッド利用時
<table>
<tr><th></th><th>改行文字の入力によるずれ</th></tr>
<tr><th>例</th><td>`nextInt()`実施後に`nextLine()`を実施した時</th></tr>
<tr><th>発見方法</th><td>入力から受けとった値の表示</td></tr>
<tr><th>修正方法</th><td>`nextLine()`を追加し改行文字を除く</td></tr>
<tr><th></th><td>`nextLine()`ではなく`next()`で受け取る</td></tr>
</table>


<table>
<tr><th></th><th>()の付け忘れ</th></tr>　
<tr><th>例</th><td>`next()`を`next`と表記</td></tr>
<tr><th>発見方法</th><td>`next`の行にエラーがあるときに確認</td></tr>
<tr><th>修正方法</th><td>()をつける</td></tr>
</table>

###### インスタンス化実行時 (new 演算子利用時）
<table>
<tr><th></th><th>クラス名の誤り</th></tr>
<tr><th>例</th><td>ArrayListをArraylistと表記、Stringをstringと表記</td></tr>
<tr><th>発見方法</th><td>色が変わっているかインスタンス化の文を確認</td></tr>
<tr><th>修正方法</th><td>正しい表記に戻す</td></tr>
</table>

<table>
<tr><th></th><th>ジェネリクスで基本型を指定</th></tr>
<tr><th>例</th><td>`List < Integer > list`を`List < int > list`と表記</td></tr>
<tr><th>発見方法</th><td>エラー行に`< >`の形が含まれるとき、中身が参照型であることを確認</td></tr>
<tr><th>修正方法</th><td>ラッパークラスに修正する</td></tr>
</table>




###### for文実施時
<table>
<tr><th></th><th>ループが終わらない</th></tr>
<tr><th>例</th><td>`i++`を書いていない
</td></tr>
<tr><th>発見方法</th><td>Runtimeエラーが出るときに確認</td></tr>
<tr><th>修正方法</th><td>`i++`を書きいれる</td></tr>
</table>

###### 変数代入時
<table>
<tr><th></th><th>意図した値を持つ変数ではないものを代入してしまう</th></tr>
<tr><th>例</th><td>`[]`に入れるindexの値が入力値に対して1小さいことを加味せずそのまま代入した</td></tr>
<tr><th>発見方法</th><td>エラーの行で参照されている変数の中身を確認</td></tr>
<tr><th>修正方法</th><td>正しい値を代入するよう修正、変数名を工夫したり複雑な部分は変数に置きなおしたりすると吉。</td></tr>
</table>

###### 条件式の定義時
<table>
<tr><th></th><th>条件文で代入してしまう</th></tr>
<tr><th>例</th><td>`if(num==1)`を`if(num=1)`と表記</td></tr>
<tr><th>発見方法</th><td>typeがあっていないと表示されたら各引数を確認</td></tr>
<tr><th>修正方法</th><td>＝を追加する</td></tr>
</table>

###### 貼り付けや切り取り時
<table>
<tr><th></th><th>'}'の数が違う</th></tr>
<tr><th>例</th><td>ｺﾋﾟﾍﾟする時にブロックの最後の}を入れ忘れる</td></tr>
<tr><th>発見方法</th><td>最後の}にエラーがあると出る</td></tr>
<tr><th>修正方法</th><td>数を確認して追加または削除する</td></tr>
</table>



## お届けの方向け窓口
ぜひ記事を投稿してください。もっとピンポイントなもの、より網羅的なものどちらにしてもあったらなぁ、と自分は思っていました。

書き方はこちら→[記事を投稿する | Qiita ヘルプ](https://help.qiita.com/ja/articles/qiita-post "記事を投稿する | Qiita ヘルプ")
Go | 同じ名前の関数で引数の数を変える


雑めも

- https://xuri.me/excelize/en/sheet.html#SearchSheet を使ってて

`f.SearchSheet(sheet, kw, true)`
と
`f.SearchSheet(sheet, kw)`

が許容されてるのに気づいたのでメモ


## 末尾に１つ要素の有無をコントロールする

- [Playground](https://goplay.tools/snippet/qLiuZ23dLjM)

```go
package main

import (
	"fmt"
)

func main() {
	// opt arg なし
	fmt.Println(">> no opt arg")
	f1(":D")
	fmt.Println()

	// false
	fmt.Println(">> false")
	f1(":D", false)
	fmt.Println()

	// true
	fmt.Println(">> true")
	f1(":D", true)
	fmt.Println()

	// invalid
	fmt.Println(">> invalid")
	f1(":D", false, false) // 複数入れられちゃうけど意味がない
	fmt.Println()
}

func f1(txt string, arg ...bool) {
	if len(arg) > 1 {
		fmt.Println("<invalid arg>")
		return
	}
	willUpdate := len(arg) > 0 && arg[0]

	fmt.Println(txt, "f1 starting...")
	if willUpdate {
		// 何かupdate 処理
		fmt.Println(txt, "f1 update!")
	}
	fmt.Println(txt, "f1 done...")
}
```

## 末尾にN個の要素を追加する

同じノリでロジックを拡張する

- [Playground](https://goplay.tools/snippet/iDVZtFuzums)

```go
package main

import (
	"fmt"
)

func main() {
	// Update / noDelete
	fmt.Println(">> Update / no Delete")
	f1(":D", true, false)
	fmt.Println()

	// no Update / Delete
	fmt.Println(">> no Update / Delete")
	f1(":D", false, true)
	fmt.Println()
}

func f1(txt string, arg ...bool) {
	if len(arg) > 2 {
		fmt.Println("<invalid arg>")
		return
	}
	willUpdate := len(arg) > 0 && arg[0]
	willDelete := len(arg) > 1 && arg[1]

	fmt.Println(txt, "f1 starting...")
	if willUpdate {
		// 何かupdate 処理
		fmt.Println(txt, "f1 UPDATE!")
	}

	if willDelete {
		// 何かupdate 処理
		fmt.Println(txt, "f1 DELETE!")
	}
	fmt.Println(txt, "f1 done...")
}

```


## Functional Option Pattern

型が違ったりロジックが多くなってきたら `Functional Option Pattern` にする

- [go-patterns/idiom/functional-options.md at master · tmrts/go-patterns · GitHub](https://github.com/tmrts/go-patterns/blob/master/idiom/functional-options.md)
ChromeDriverManagerで【OSError】が出た件

# はじめに
seleniumを使用したプログラムでエラーが発生しました。
とりあえずエラーは消えたので、備忘録として記事に残します。

解決にあたり、下記記事を参考にさせていただきました。
ありがとうございました。

https://yuki.world/python-selenium-chromedriver-auto-update/


# 内容
exe化し、常時動かしていたプログラムを少し内容変更した際にエラーが発生してしまいました。
そこでエラー文を見てみるとWebDriver周りでエラーが出ていることがわかりました。

エラー文一部抜粋
```
  File "xxxxx", line 250, in xxxxxx
    driver = webdriver.Chrome(service=service, options=options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             
OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
```
中身のコード
```py
        service = Service(ChromeDriverManager().install())
        options = webdriver.ChromeOptions()
        options.add_argument('--start-maximized')
        options.add_experimental_option('prefs', profile)
        driver = webdriver.Chrome(service=service, options=options)
        driver.get(URL)
```
開発時、Chrome側のバージョンを気にするのが面倒だったので、自動でドライバをダウンロードしてくれるwebdriver_managerを使用していました。
当初はエラーもなく動いてくれていたので、これでプログラムを組んでいました。

そこで参考記事を確認してみると
>Selenium 4.6から、Selenium自体にChromeDriver自動更新機能「Selenium Manager」が搭載されたことで、このシンプルな記述だけで済むようなりました。

と書かれており、serviceの記述がもう必要ないことがわかったので、
下記のようにコードを書き換えました。

```py
        options = webdriver.ChromeOptions()
        options.add_argument('--start-maximized')
        options.add_experimental_option('prefs', profile)
        driver = webdriver.Chrome(options=options)
        driver.get(URL)
```
この書き換えにより、問題なく処理が走りました。

# 終わりに
exe化やスクレイピングは便利ですが、正しく知識をつけないとたびたびエラーになるイメージがあります。
私自身これからも精進します。
【備忘録】メソッドの返却値を自由に設定する方法

# はじめに
テストソースの特定メソッドの返却値を自由に設定する方法を下記に記述します。

## ソース
本来であれば絶対に通らないルート("失敗ルート")でも返却値を任意に設定することができるので挙動を確認することができます。

```ruby:junit
public class Simplecode {

    public String stringReturn() {
        return "成功ルート"; 
    }

    public static void main(String[] args) {
        if ("成功ルート".equals(stringReturn())) {
            System.out.println("成功ルート");
        } else {
            System.out.println("失敗ルート");
        }
    }
}
```
下記設定により、simplecode.stringReturn()を呼び出した際、"テスト"を返却値として返してくれるようになります。
```ruby:java
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class SimpleTest {

    @Mock
    private Simplecode simplecode;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testCalculateMethodReturnsSuccessRoute() {
        // "テスト"を返却値に設定する
        when(simplecode.stringReturn()).thenReturn("テスト");
    }
}
```
## おわりに
仕様の段階でありえない値だったとしてもソースで2重に確認することがあります。
その際のテストにすごく便利で、カバレッジを100%にする際もとても便利でした。
MUIのPopoverをonMouseLeaveで閉じるようにしたら高速開閉し続けてしまう問題の解決方法

# 現象
アイコンにマウスオンでPopoverを表示、マウスを外したときに非表示にしたかったので、このように実装した。

結果、高速でPopoverが無限に開閉し続け、表示されない状態になった。

補足：
WebComponentとして実装しており、親コンポーネント側にPopoverが出てスタイルが無効化されるのを防ぐため、div要素にrefを使用しています。


```typescript
const MyComponent: React.FC = () => {
  const popoverRef = useRef<HTMLDivElement>(null);
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const handleClose = (): void => {
    setIsOpen(false);
  };
  const handleOpen = (): void => {
    setIsOpen(true);
  };

  return (
    <div ref={popoverRef}>
      <PsychologyIcon 
        onMouseOver={handleOpen}
        onMouseLeave={handleClose}
      />
      <Popover
        open={isOpen}
        anchorEl={popoverRef.current}
        onClose={handleClose}
        container={() => {
          return popoverRef.current;
        }}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'left',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}>
        <div style={{ padding: '5px' }}>Popoverに表示するテキスト</div>
      </Popover>
    </div>
  )
```

# 原因と対応
## １． フォーカス可能な要素にaria-hidden="true"を設定してはならない
コンソールを見ると、このようなエラーが出ていた。
```text
Blocked aria-hidden on a <div> element because the element that just received focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden. 
```

[MDN Web docs](https://developer.mozilla.org/ja/docs/Web/Accessibility/ARIA/Attributes/aria-hidden) にも警告が書いてあるとおり、aria-hidden="true"をフォーカス要素に使用することはできません。
Popoverコンポーネントが動作するときに自動でaria-hidden="true"が挿入されますが、今回、上述の事情によりdivの中に挿入していたので、このようなエラーが発生したようです。

解決策として、inert属性を使う方法もあるようですが、今回は、Popoverコンポーネントが表示されたときに自動的にフォーカスを取得しないように、`disableAutoFocus`と`disableEnforceFocus`を追加しました。

```typescript
      <Popover
        open={isOpen}
        ...
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        disableAutoFocus // Popoverが表示される際にフォーカスを自動的に取得しないようにする
        disableEnforceFocus // フォーカスの強制を無効にする
      >
        <div style={{ padding: '5px' }}>Popoverに表示するテキスト</div>
      </Popover>
```

## 2. マウスイベントがPopover上で発生してしまっている
さて、１の対応でコンソールのエラーは表示されなくなりましたが、Popoverが高速で開閉してしまう問題は解決しませんでした。
マウスイベントがPopover上で発生しないように、`sx={{ pointerEvents: 'none' }}`を追加したところ、正常に表示されるようになりました。

```typescript
      <Popover
        open={isOpen}
        ...
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        disableAutoFocus
        disableEnforceFocus
        sx={{ pointerEvents: 'none' }}  // Popover上でマウスイベントが発生しないようにする
      >
        <div style={{ padding: '5px' }}>Popoverに表示するテキスト</div>
      </Popover>
```
株式市場APIサービスに求めるべき重要な機能は？

![DALL·E 2024-07-22 15.48.32 - A dynamic financial scene showcasing Bitcoin and Forex trading. The background features digital charts and graphs with green and red candlesticks, dep.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841131/d067fb66-d101-d0ea-6573-e7ecb15e9910.jpeg)

こんにちは！株式市場APIを探してるんだね。いい選択だよ！APIは手間をかけずに株データを取得するのにとっても便利なんだ。でも、どれがいいのかどうやって選ぶの？一緒に見ていこう。

株式市場APIが重要な理由
まず最初に、株式市場APIは魔法の橋みたいなもの。必要なすべての株市場データにつながってる。開発者、トレーダー、またはただの好奇心からでも、良いAPIがあれば生活が簡単になるよ。

求めるべき重要な機能
1. リアルタイムデータ
H2: リアルタイムデータ

最新のデータが欲しいよね。リアルタイムデータは迅速に賢い動きをするのに役立つ。株を取引してるなら、タイミングが全てでしょ？

H3: 重要な理由
データが遅れると、良い取引を逃しちゃうかもしれない。リアルタイムデータなら、常に最新の情報を把握できる。

2. 過去データ
H2: 過去データ

振り返ることも未来を見据えることと同じくらい重要。良いAPIはたくさんの過去データを提供してくれる。これがパターンを見つけて、より良い選択をするのに役立つ。

H3: 役立つ理由
過去のデータを調べることで、次に何が起こるかを予測できる。それはまるで水晶玉を持っているみたいだ！

3. 幅広い市場カバー
H2: 幅広い市場カバー

すべての基本をカバーするAPIが欲しい。株、外為、商品、暗号通貨 – 多ければ多いほど良い。

H3: 重要な理由
多くの市場があると、もっと多くのチャンスが生まれる。一種類のデータだけに制限されたくないよね。

4. 簡単な統合
H2: 簡単な統合

APIはあなたのアプリやウェブサイトに簡単に追加できるべきだ。良いドキュメントと多くのプログラミング言語に対応しているものを探してね。

H3: 良い理由
問題を解決するのに時間をかけるよりも、データを使ってクールなことをする時間を増やせる。

5. 信頼性と稼働時間
H2: 高い信頼性と稼働時間

常に稼働しているAPIが必要。ダウンタイムはお金と機会を失う原因になる。

H3: 重要な理由
APIがダウンすると困るよね。信頼性の高いAPIはスムーズな運用を意味する。

6. カスタマイズ可能なデータフィード
H2: カスタマイズ可能なデータフィード

欲しいデータを選べるAPIを選ぼう。分単位の更新でも、終日の要約でも、カスタマイズが鍵。

H3: 利点
必要なデータだけを取得できる。それが分析をよりクリーンで早くする。

7. セキュリティ
H2: セキュリティ

データは安全であるべき。暗号化や他のセキュリティ機能を使用しているAPIを探してね。

H3: 重要な理由
データがハッキングされるのは嫌だよね。セキュリティはすべてを保護してくれる。

8. サポートとドキュメント
H2: サポートとドキュメント

良いサポートと明確なドキュメントは生活を楽にする。問題が発生したら、すぐに助けが欲しいよね。

H3: 重要な理由
良いサポートがあれば、問題を素早く解決して進み続けられる。

9. コスト
H2: コスト

価格をチェックしよう。無料のAPIもあるし、そうでないものもある。支払う価値があるか確認してね。

H3: 重要な理由
時々、少し多く支払うことで、より良い機能とデータが得られることがある。

10. レートリミット
H2: 適正なレートリミット

APIはしばしば、どれだけのリクエストを行えるか制限がある。リミットが自分に合っているか確認しよう。

H3: 重要な理由
大事な途中でリクエストが止まるのは困るよね。良いリミットはスムーズな使用を意味する。

正しい株式市場APIの選び方
何が必要か考えよう。開発者？トレーダー？それとも他の人？自分のニーズが選ぶのに役立つ。

例えば、FCS APIは素晴らしい。リアルタイムデータや過去データ、金融ニュース、分析を提供してる。株、外為、商品、暗号通貨をカバー。使いやすくて信頼性も高い。価格も手頃で、月10ドルから始まるし、無料バージョンもあるよ！

FAQs
H2: FAQs

Q1: 株式市場APIとは？
A: 株市場データを簡単に取得できるツールです。

Q2: なぜリアルタイムデータが重要？
A: 最新の情報に基づいて素早く決定を下せるからです。

Q3: 過去データの良い点は？
A: トレンドを見て予測を立てるのに役立ちます。

Q4: 市場カバーとは何ですか？
A: 多くの市場からデータを提供することです。

Q5: なぜ簡単な統合が重要？
A: プロジェクトにAPIを追加する時間と労力を節約できます。
GPT-4o-miniのファインチューニングが無料でできるらしいので調べてみた

## はじめに
この記事は社内の業務効率化でChatGPTを使おうとしたところGPT-4o miniのファインチューニングが良さそうだったので調べてみたメモです。
弊社CDOの@__Kat__ と一緒に調べました。

## 出会い
当初、今まで通りGPT-4またはGPT-4oを使うことを考えていました。

しかし、格安爆速のGPT-4o miniが出てきたのでサイトを徘徊しているとファインチューニングの欄に2024年9月23日まで1日2Mトークン以下無料とのことだったので試してみたくなり調べてみました。
[公式サイト価格表](https://openai.com/api/pricing/)

![2024/7/27時点でのサイト上での記載](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2756391/d62985c3-2575-36bc-4f6c-af2aa7434cba.png)

コスト面を考えるとGPT-4o miniは他のモデルに比べて圧倒的に安いです。
また、ファインチューニングはプロンプトが長くなる場合には有効な手段だと考えられます。
(今回の業務効率化はこの側面が強いのでピッタリそう)

## 今回のタスク
詳細は割愛しますが、顧客から来たメール文章から特定の情報を抽出してスプレッドシートに保存するというタスクです。

今回メールはスプレッドシートに入力されている状態を想定してそこから自動で情報を抽出してセルを充足するというコードを書いていきます。

お客さんごとにメールの傾向に偏りがあるため追加のファインチューイニングをスプレッドシート上から営業が行えるようにファインチューニング/テスト用のシートも用意します。
![ファインチューニング/テストUIイメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2756391/6faf3a53-9f09-8c58-e87b-24a90ada63b2.png)

## 注意点
GPT-4o miniのファインチューニングを行うには現在、Tier4以上である必要があるようなのでご注意ください。
> Customize GPT-4o mini for your application with fine-tuning. Available today to tier 4 and 5 users, we plan to gradually expand access to all tiers. First 2M training tokens a day are free, through Sept 23.
[引用 X](https://x.com/OpenAIDevs/status/1815836887631946015)

## 最後に
今回はGPT-4o miniのファインチューニングが無料で行えるとのことで調べてみたメモでしたがまた機会があれば具体的なファインチューニングの過程についても記事を書いてみようと思います。
弊社Engineeでは生成AIに限らずレコメンド、マッチングシステムを中心としたAIに強みを持って活動しています。
常に仕事とエンジニアを探しているのでお気軽にお声がけください。
【備忘録】NestJSにPOST送信する時はContent-Typeを必ず設定する

# はじめに
どうやっても`request body`が受け取れない時の解決した備忘録です。
APIテストはうまくいくのにBFFからは送信出来ない時の解決策です。

# 実装例
```ts
const response = await fetch(`${process.env.API_URL!}/products`, {
    method: "POST",
    body: JSON.stringify({
        imageSrcPath,
        deployUrl,
        productName,
        overview,
        mainTechnology,
        subTechnology,
        productLinks,
    }),
    headers: {
        "Content-Type": "application/json"
    },
});
```

# さいごに
`CORS`全然関係なかったです；；

https://x.com/ecccompsenyou/status/1818327621438201930
rails7でActive Storageの導入方法

# 初めに
Active Storageをrails7で導入する機会があったためアウトプットも兼ねてまとめてみました。細かい設定やコードの意味や機能などは省略しておりますのでより詳細に知りたい方はご容赦お願い致します🙇
また、今回はローカルストレージを使用するのでdevelopment.rbの設定などは省略しています！
# 概要
Active Storageは簡単にいうとファイルのアップロード、保存、管理を簡単に行うための機能！！
# 導入方法
## ①Active Storageをインストールする
``` 
rails active_storage:install
``` 
## ②マイグレーションする
```
rails db:migrate
```
## ③モデルへの記述
### 一枚のみアップロードする場合
```
has_one_attached :image
```
### 複数枚アップロードする場合
```
has_one_attached :images
```
## ④ビューへの記述(カラム名はモデルに記述したものを使用)
### 入力フォーム
```
<%= form_with(model: @user, local: true) do |form| %>
  <div class="field">
    <%= form.label :image %>
    <%= form.file_field :image %>
  </div>
  <div class="button">
    <%= form.submit %>
  </div>
<% end %>
```
### 登録した画像の表示
```
<% if @user.image.attached? %>
  <%= image_tag @user.image %>
<% end %>
```
## ⑤コントローラーへの記述(パラメーターの許可)
### 一枚のみアップロードする場合
```
  private

  def user_params
    params.require(:user).permit(:name, :email, :image)
  end
```
### 複数枚アップロードするアップロードする場合
```
  private

  def user_params
    params.require(:user).permit(:name, :email, images: [])
  end
```
## 最後に
以上がActive Storageの設定になります。
簡単な内容になりますがここまで読んでいただきありがとうございます🫡
VPC、オンプレミスとの接続まとめ（SAA-C03）

SAA-C03向けメモ

## VPC
構成要素
茶色のリソースはVPC作成時に自動で作成される

- インターネットゲートウェイ or　仮想プライベートゲートウェイ
- サブネット
- <font color=Peru>ルートテーブル
- <font color=Peru>ネットワークアクセスコントロールリスト（NACL）
- <font color=Peru>セキュリティグループ(SG)

ポイント
- 1サブネットは常に1AZのみに存在
- IPv4の範囲 /16〜/28
- インスタンスを起動するときにセキュリティグループを指定しないと、そのインスタンスは VPC のデフォルトのセキュリティグループに自動的に関連付けられる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950120/678dc9ca-8091-ec28-5175-1a30a83ef663.png)


参考：https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/default-custom-security-groups.html

## VPCとの接続

### 複数接続
|名称|接続対象|概要|
|---|---|---|
|Amazon VPCのVPCピアリング|VPCと他のVPC|同じプライベートネットワークであるかのように動作|
|AWS Private Link|VPCとAWS/オンプレミスでホストされているサービス間|他企業へサービスとして提供する場合、IPアドレスの重複があっても問題ない|
|AWS Transit Gateway|中央ハブを介して VPC とオンプレミス ネットワーク|IPアドレスの重複がない場合に使用できる|
|AWS VPC Lattice|複数のアカウントとVPCにわたるすべてのサービス|接続、保護、監視に使用できる、完全マネージド型のアプリケーションネットワーキングサービス|

参考：
https://docs.aws.amazon.com/vpc/


#### VPCピアリング
AWSの別アカウントや、リージョン間でも可能
CIDRアドレスは重複できない
VPCピアリングは双方向通信可能だが、AWS Private　Linkは一方通行のみ

VPC3からVPC1へ、VPC2を跨いで通信はできない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950120/55ef6298-6733-44cf-1f14-54843c890cb2.png)


### １対１の接続

|名称|概要|専用ネットワーク接続か|暗号化|
|---|---|---|---|
|AWS Direct Connect|オンプレミスとAWSへのプライベートな専用ネットワーク接続|◯|デフォルト暗号化なし|
|AWS VPN|オンプレミスとVPC間の接続|×|あり（IPsecとTLSによるセキュアでプライベートな接続）|

#### AWS Direct Connect
ネットワークのスループット向上

- 専用接続（Dedicated）： 単一顧客との物理イーサネット接続
- ホスト接続： パートナーがプロビジョンした物理イーサネット接続

#### VPN
VPCとVPNの違い=VPCはAWSネットワーク空間、VPNはネットワーク経路

- AWS Site-to-Site VPN：　仮想プライベートゲートウェイ/トランジットゲートウェイとカスタマーゲートウェイで接続
- AWS Client VPN： OpenVPNベースのVPNクライアントを使用して接続

##### AWS Site-to-Site VPN
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950120/8be50c9d-1dfa-ebdc-b1c4-a19f4d16c6bd.png)

##### AWS Client VPN
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950120/cb642184-92c4-6b0b-6cb2-d978076ba207.png)

##### AWS VPN CloudHub
複数のAWS Site-to-Site VPN接続がある場合は、 AWS VPN CloudHubサイト間の安全な通信を提供できる
→　便利で低コストの hub-and-spoke モデルを実装したい場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950120/e811fb85-d079-04f1-57ae-ed5c8fd4e91f.png)


参考：
https://docs.aws.amazon.com/vpn/latest/s2svpn/how_it_works.html
https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/scenario-peered.html
https://docs.aws.amazon.com/ja_jp/vpn/latest/s2svpn/VPN_CloudHub.html
OpsRamp カスタム属性について

本記事では、OpsRampにおけるカスタム属性について説明します。

# 概要
OpsRampでは、カスタム属性と呼ばれるユーザーが任意でリソースに割り当てることができる属性を付加することが可能です。これにより、OpsRamp Agent / Gatewayが取得したリソースの情報以外の情報を付加できます。また、カスタム属性は、アラートエスカレーションポリシーやデバイス管理ポリシーなど様々な機能のフィルター条件として使用することが可能です。
パブリッククラウドから検出されたリソースのようないくつかの場合、自動で追加情報としてカスタム属性を付加されることもあります。

# 設定
カスタム属性は、Setup > カスタム属性から設定することが可能です。
カスタム属性のタイプを定義します。
![custom-attribute_1_marked1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/38dfe0a2-df0b-30d3-3357-bd77fe8b867c.png)
![custom-attribute_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/7587b6eb-19d3-42fc-0c6e-c8fb222da2e6.png)
定義したタイプに対して、値を定義します。
![custom-attribute_1_marked2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/0fa0efbe-a208-c02a-e759-0f27b5ad6661.png)
![custom-attribute_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/474f6389-be49-da8f-bac2-70e9d00d8258.png)
定義したタイプおよび値をリソースに割り当てます。
![custom-attribute_1_marked3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/8fe5b1f7-0d04-4744-ea68-5cf165ae924f.png)

割り当てたカスタム属性は、対象リソースの詳細ページのCustom Attributesタブから参照することが可能です。
![customer-attribute_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/6613b015-ff09-fc96-1e53-be6e11ea889f.png)

サンプル: アラートエスカレーションポリシー
![custom-attribute-sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/074f7497-8e41-48e6-c8f4-190b54b5d557.png)


---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)