OmniAICreator/Qiita-1.07M huggingface dataset:
Spannerで複数キーの値を取得する方法

# 概要

ここではSpannerのSELECT構文で、複数キーを指定する方法を記載します

よりよい書き方があれば指摘していただくとうれしいです！

# 具体的な方法
## キーが一つの場合
この場合はWHEREの条件として値の一覧を渡すだけでよく、特に複雑なことはありません

UNNEST構文を使い取得したい列のキーを配列として渡せばよいです

UNNESTとは配列を渡し展開するための構文で、IN句と組み合わせることで配列を用いた検索が可能になります
> https://cloud.google.com/spanner/docs/reference/standard-sql/query-syntax#unnest

``` SQL
WHERE key1 IN UNNEST ("test1", "test2", "test3")
```

Spannerのベストプラクティスとしてはこちらに記載があります 
> https://cloud.google.com/spanner/docs/sql-best-practices?hl=ja#optimize-range-lookups


## キーが複数の場合
この場合は単純に値を渡すのではなく、key1、key2の組み合わせとして渡す必要があります

SpannerにはWHEREでの条件として構造体（Struct）を使用することができる方法があります

``` SQL
WHERE (key1, key2) IN (("aaa", "bbb"), ("ccc", "ddd"))
```

> https://cloud.google.com/spanner/docs/reference/standard-sql/data-types#struct_type

記載の方法を使用することで簡潔にSQLを実行することが可能です

# 感想と次
今までDB周りを触ることがなかったですが、とても楽しかったです
また、調査のためにChatGPTが大いに役に立ちました
結構頓珍漢なことも言いますが、詳細に調べる前、大雑把な把握には役立つと思います

次はこの複数主キーを使用する方法をSpring Data Cloudで利用する場合、どのように行うのか記事にしようと思います
RAGの作り方

## RAGとは
Retrieval（検索） Augmented（拡張） Generation（生成）
専門知識のデータベースから検索してプロンプトに渡す仕組み。

RAG用の専門知識のデータベースとRAGは分けて考えると理解しやすい。

RAGの手法の中でも、Embedding (文章のベクトル変換)したデータをベクトルデータベース (Vector DB) に保存して類似度検索 (Similarity Search) を行う方法がある。

### ベクトルデータベース構築

元データ→Embedding (文章のベクトル変換)→ベクトルデータベース

### RAG処理

ユーザー→質問→ベクトルデータ検索→プロンプト→LLM→回答

## 参考文献

ベクトルデータベース構築とLLMの連携について参考にしました
https://qiita.com/t_serizawa/items/a2ced4441da714b3076f

RAGの仕組みを作りについて参考にしました。
https://zenn.dev/mobdev/books/da63d738595c0a/viewer/c90ada

RAGの詳細な情報
https://resources.nvidia.com/ja-jp-llm/retrieval-augmented-generation-jp?ncid=no-ncid
TCP/IPの知見を深める④　データリンク層　イーサネットフレーム編

イーサネットⅡとIEE802.3の関係
--
イーサネットⅡ規格は1982年にDEC社・Intel社・Xerox社が発表した規格
IEEE802.3は世界標準を目的にイーサネットⅡをベースとして作られたものでイーサネットⅡにいくつかの変更点が加えられている。

イーサネットⅡ
---
イーサネットⅡのフレームフォーマットは発表から30年以上たった今でも変わっておらず,
**プリアンブル・宛先/送信元MACアドレス・タイプ・イーサネットペイロード・FCS**の5つのフィールドに分けられている。

イーサネットヘッダー
--
先ほど紹介した5つのフィールドの中から**プリアンブル・宛先/送信元MACアドレス・タイプ**を合わせて**イーサネットヘッダー**と呼ぶ
`FCSに関してはイーサネットトレーラーと呼ぶ`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/3b02d5ed-bcfa-1f7b-9910-f13f16bddadd.png)

イーサネットヘッダーを構成しているフィールドの解説
---
プリアンブル
----
8biteの特別なビットパターンを送信することによって受信端末側はイーサネットフレームが届く判断を行っている
`先頭から10101010が7つ送られて最後に10101011が1つ送られてくる`

宛先/送信元MACアドレス
----
MACアドレスはイーサネットネットワークでいうところの住所のようなもの
`送信側端末`
イーサネットフレームを届けたい住所（MACアドレス）に宛先MACアドレス、送信元MACアドレスを自分のMACアドレスに設定することでイーサネットフレームを送ることが出来る
`受信側端末`
宛先MACアドレスが自分のMACアドレスと一致しているか、送信元MACアドレスをみて、どこから来たイーサネットフレームなのかを判断することが出来る。

タイプ
--
ネットワーク層（L3）でどのプロトコルを使用してきたのかを判断するためのID
↓こんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/df2ebe41-f062-a375-55ef-e41909e5edf1.png)

イーサネットペイロード
---
ネットワーク層でのデータそのものを表している
データをそのままの状態で送っているわけではなくて、イーサネットペイロードの場合46bite～1500biteまでにサイズを抑えないといけない為、パケットにしてデータを渡す場合もある。

:::note info
46bite以下であるならパディングと呼ばれるダミーデータを付加させる
:::


`L2ペイロードに格納できる最大サイズの事をMTU(Maximum Transmission Unit)と呼ぶ
イーサネットのデフォルトのサイズは1500であるが、それよりも大きくすることは可能で1500以上のサイズであることをジャンボフレームと呼ぶ`

FCS
---
**Frame check Sequence**
イーサネットフレームが壊れていないか確認するために4biteのフィールドが用意されている
仕組みとしては、送信側は宛先MACアドレス・送信MACアドレス・タイプ・イーサネットペイロードに対して計算を行う**チェックサム計算(CRC計算)**受信側の端末も送信側と同じ計算を行い計算結果が一致していればイーサネットフレームが壊れていないと判断することが出来る。
僕のrubocom設定

# はじめに
 基本のrubocop設定を自分用の備忘録として記述します。

# Rubocopとは
 RuboCop とは、Ruby のコードがコーディング規約に沿っているかを検査することができる「静的コード解析ツール」の一つです。
RuboCop をアプリケーションに取り入れることで、コードの品質を保つことができます。

# Rubocop 基本設定

```ruby:.rubocop.yml
AllCops:
  # チェック対象から除外するディレクトリ,ファイル
  Exclude:
    - "vendor/**/*"
    - "db/**/*"
    - "bin/*"
    - "node_modules/**/*"
    - "config/initializers/devise.rb"
    - "config/environments/*.rb"
    - "Gemfile"
    - "Rakefile"

# # frozen_string_literal: true というマジックコメントのないファイルの許可
Style/FrozenStringLiteralComment:
  Enabled: false

# コンパクト記法とネスト記法の両方を許可
Style/ClassAndModuleChildren:
  Enabled: false

# ドキュメントの無い public class を許可
Style/Documentation:
  Enabled: false

# config/routes.rb をブロック行数のチェックから除外
Metrics/BlockLength:
  Exclude:
    - "config/routes.rb"

# メソッドの行数40行まで許容
Metrics/MethodLength:
  Max: 40

# メソッドの複雑度の指標を40まで許容
Metrics/AbcSize:
  Max: 40
```


# 参考
公式ドキュメント
https://docs.rubocop.org/rubocop/1.15/configuration.html
【合格体験記】AWS Certified Security - Specialtyに合格しました(2024/06/30)【SCS-C02】

# 目次
[#1.はじめに](#1はじめに)
[#2.筆者のスペック](#2筆者のスペック)
[#3.学習内容](#3学習内容)
[#4.学習期間](#4学習期間)
[#5.試験当日](#5試験当日)
[#6.あとがき](#6あとがき)

# 1.はじめに

題名の通り、AWS Certified Security - Specialtyに合格しました。

https://twitter.com/ss_IT_study/status/1807368292782460975

SCSの範囲は普段AWSを利用している範囲に近いという点もあり、
今回は短期集中で5日間の試験対策を行い受験に臨みました。


# 2.筆者のスペック

* 大学は情報系
* SIerで10年程度勤務
* AWSの利用経験は2年程度
* AWS SAA取得済み([【合格体験記】AWS Certified Solutions Architect - Associateに合格しました(2022/11/19)【SAA-C03】](https://qiita.com/ss_IT_study/items/d14b81ea4c92ced86786))
* AWS DVA取得済み([合格体験記】AWS Certified Developer - Associateに合格しました(2023/02/23)【DVA-C01】](https://qiita.com/ss_IT_study/items/ae5e612f6f0affe7bf8a))
* AWS SAP取得済み([【合格体験記】AWS Certified Solutions Architect - Professionalに合格しました(2024/03/16)【SAP-C02】](https://qiita.com/ss_IT_study/items/3f9ba1321476e2b8bc9e))

# 3.学習内容

①[Security Engineering on AWS](https://aws.amazon.com/jp/training/course-descriptions/security-operations/)

AWS公式が提供している3日間の教育となります。
講義形式で全体を把握することができました。
また、バウチャー付きの教育を会社で受講できたので、受験もセットで実施できました。

②BlackBelt

公式リソースのBlackBeltです。
セキュリティの試験なのでIAMやKMSの理解が必須となりますが、私はKMSの理解が弱かったので以下のオンラインセミナーを主に利用しました。

https://www.youtube.com/watch?v=jdX_NcNrco4&t=460s

③公式模擬試験

AWS スキルビルダーで公開されている公式模擬試験です。
試験直前の習熟度確認に利用しました。
実際の試験に近い形式で問題演習することができます。

④Cloud License

有償ですがとにかく問題演習で知識量を増やしたい場合は最適だと思います。

# 4.学習期間
|#|教材|期間　|
|:---|:---|:---|
|1|Security Engineering on AWS|3日|
|2|BlackBelt|1日|
|3|公式模擬試験|1日|
|4|Cloud License|2日|

# 5.試験当日
過去の試験と同様にテストセンターを予約の上受験しました。
予約より少し早めに到着したところ、試験自体も少し早く開始できました。
また、40分程度時間を残しての退出だったので、トータルで一時間くらい予定時間より早く完了しています。

過去のバージョンでは受験後すぐに画面上に合否が出力されたみたいですが、
私が受験した時は試験終了後即時結果が分かるわけではなく、
しばらく経ってから試験履歴が更新されました。
※ざっくりですが、11:00開始の試験を受けて19:00くらいに結果が閲覧可能になったと思います

# 6.あとがき
AWS SCS(SCS-C02)の合格体験記でした。
次回は範囲がかなり被っていそうなのでSOAの受験を考えていますが、
[ネスペの不合格](https://qiita.com/ss_IT_study/items/9a797f4505ffd813e1bc)をかなり引きずっているので、しばらくAWS認定もお休みになるかもしれないです…。
一般化傾向スコア（Generalized Propensity Score）＝３群以上の効果検証で傾向スコアを用いる方法

# 概要
・３群以上で傾向スコアを用いるIPW（Inverse probability weighting = 逆重み付け）の方法について解説する。
・結論：下記数式のように、各データの傾向スコア（＝その群に配属される確率）で逆重み付けをすれば良い。

```math
\frac{Y_{t}}{e(t,X)}
```
ここで
・$Y$はアウトカム変数
・$e(t, X)$はユーザーの属性情報$X$から計算された$t \in (0,1,,,n)$群に配属される確率＝傾向スコア

# 傾向スコアによる補正を用いる際の前提条件
2群のみの場合と3群以上の場合とで、前提とする条件が異なる。

## Strong Unconfoundedness
2群の場合にIPWで必要とされる条件のことをStrong Unconfoundedness（参考文献では”強く無視できる割り当て”と呼ばれている、直訳で強い無交絡状態）と呼ぶ。
```math
T \perp {Y_{(t)}} | X
```
これはユーザーの属性情報などのベクトルXで条件付けした時、群への割り当てTと全てのアウトカムYは独立であることを示す。
わかりやすくいうと、Xを与えた時、介入とアウトカムに関係はない。

## Weak Unconfoundedness
3群以上のIPWで用いる場合の前提条件のこと。

まず、新しい記号を定義する。
```math
D_{i}(t) = \left\{
\begin{array}{ll}
1 & (if \ \ T_{i} = t_{i}) \hspace{70mm}\\
0 & (otherwise)
\end{array}
\right.
```
$D_{i}$は$t_{i}$に配属された時には１をそれ以外に配属された場合は０を返す変数。

この時以下の条件を満たすとき、IPWを用い因果効果を不偏推定することができる

```math
D(t) \perp Y(t) | X
```
```math
for \ \ all \ \ t \in T
```
これを説明すると、Xを条件付けした時割り当て$D_{i}$と$Y_{i}$は独立である。これがWeakと呼ばれる理由は、割り当て$D_{i}$とその他のアウトカム$Y_{j}, i \neq j$は独立でもなくてもいいことを意味する。


# Strong Unconfoundedness と Weak Un confoundednessの違い

論文では2つの言及がある

1つ目がこちら

> Strong unconfoundedness requires the treatment T to be independent of the entire set of potential outcomes. Instead, weak unconfoundedness
requires only pairwise independence of the treatment with each of the p otential outcomes. 

これが意味するところは
「Strong unconfoundednessは各群への配属と全てのアウトカム変数は独立である必要があるのに対し、Weak unconfoundednessは各群とそれぞれに対応するアウトカムが独立であれば良い」

2つ目がこちら

> In addition weak unconfoundedness only requires the independence of the p otential outcome Y (t) and the treatment to be "local" at the treatment level of interest, that is independence of the binary treatment level indicator D(t), rather than of the treatment level T. This second di erence is immaterial in the binary treatment case.

意味するところが少しわからないが、Tはどのトリートメントに配属するか決める確率変数、一方DはTの結果を受けて０、１を返すダミー変数であり、Dとの独立性が満たされていれば十分ということか？

# 一般化傾向スコアによる逆重み付けが不偏推定量になる証明

```math
\begin{flalign*}
& E_{y}\Big[\frac{Y * D_{t}}{r(T, X)}\Big] = E_{x}\Big[E_{y}\Big[\frac{Y * D_{t}}{r(T, X)} | X \Big]\Big] &\\
& =E_{x}\Big[E_{y}\Big[\frac{Y}{r(T, X)} | D_{t} = 1, X \Big] * Pr(D_{t} = 1 | X)\Big] &\\
& ここで D(t)=1となっている時Y=Y_{t}, T = tとなるので &\\
& =E_{x}\Big[E_{y}\Big[\frac{Y_{t}}{r(t, X)} | D_{t} = 1, X \Big] * Pr(D_{t} = 1 | X)\Big] &\\
& ここで、Weak \ unconfoundednessよりD_{t}とY_{t}は独立しているので &\\
& =E_{x}\Big[E_{y}\Big[\frac{Y_{t}}{r(t, X)} | X \Big] * Pr(D_{t} = 1 | X)\Big] &\\
& また、Pr(D_{t} = 1 | X) = r(t, X)であるので、 &\\
& =E_{x}\Big[E_{y}\Big[\frac{Y_{t}}{r(t, X)} | X \Big] * r(t, X)\Big] &\\
& =E_{x}\Big[E_{y}\Big[{Y_{t}} | X \Big] \Big] &\\
& =E_{y}\Big[{Y_{t}}\Big] &\\
\end{flalign*}
```


# 参考文献
imbens, G. (2000). The role of propensity score in estimating dose-response in observational studies for causal effect.

https://scholar.harvard.edu/imbens/publications/role-propensity-score-estimating-dose-response-functions


傾向スコア解析法による因果効果の推定と調査データの調整について(星野崇宏，繁桝算男, 2004)

https://www.jstage.jst.go.jp/article/jbhmk/31/1/31_1_43/_pdf/-char/ja
ActionMailer Interceptorの設定

## ActionMailer Interceptorとは
Railsの標準機能です。追加のgemをインストールする必要はなく、Railsのデフォルト機能として利用できます。

ActionMailer Interceptorは、メールが実際に送信される前に、そのメールの内容を変更するための機能です。たとえば、メールの件名を変更したり、送信先を別のアドレスに変更したりすることができます。

## Interceptorの設定方法
「app/mailers/interceptors/email_interceptor.rb」を手動で作成します。

```
class MailInterceptor
  def self.delivering_email(message)
    message.to = ENV['TEST_NOTICE_MAIL']
  end
end
```

「config/initializers/mail_interceptors.rb」にを設定します。

```
class MailInterceptor
  def self.delivering_email(message)
    message.to = ENV['TEST_NOTICE_MAIL']
  end
end
```

これでメール送信時には自動的に「TEST_NOTICE_MAIL」のアドレスへメールを送信するように設定できました。
Pythonで等差数列、等比数列を出力するプログラムコードを作ってみた

### 前置き
等差数列とは、初めの数に一定の数を足し続ける法則です。
等比数列とは、初めの数に一定の数を掛け続ける法則です。
今日は、Pythonを使って、等差数列と等比数列を出力するコードを作りました。

### 等差数列のプログラムコード
このプログラムコードでは、ユーザーが初めの項、公差、項数を指定します。
その後、等差数列になります。
``` python
def arithmetic_sequence(a, d, n):
  """
  等差数列を生成する関数

  Parameters:
  a (int or float): 初項
  d (int or float): 公差
  n (int): 項数

  Returns:
  list: 等差数列
  """
  sequence = []
  for i in range(n):
      sequence.append(a + i * d)
  return sequence

# ユーザーが入力
a = float(input("等差数列の初項を入力してください: "))
d = float(input("等差数列の公差を入力してください: "))
n = int(input("等差数列の項数を入力してください: "))

print("等差数列:", arithmetic_sequence(a, d, n))
```
### プログラムコードの説明
このプログラムコードでは、aを初項、dを公差、nを項数としています。

### 出力結果
``` python
等差数列の初項を入力してください: 2
等差数列の公差を入力してください: 5
等差数列の項数を入力してください: 15
等差数列: [2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72]
等差数列の初項を入力してください: 3
等差数列の公差を入力してください: 4
等差数列の項数を入力してください: 10
等差数列: [3, 7, 11, 15, 19, 23, 27, 31, 35, 39]
等差数列の初項を入力してください: 5
等差数列の公差を入力してください: 6
等差数列の項数を入力してください: 12
等差数列: [5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71]
```
### 出力結果の確認
初項：数列において、最初となる数
公差：等差数列において、次の数までの差
項数：等差数列の合計の数

1つ目では、初項2、公差5、項数15
（2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72）数列の数が15個あります。
2つ目では、初項3、公差4、項数10
(3,7,11,15,19,23,27,31,35,39) 数列の数が10個あります。
3つ目では、初項5、公差6、項数12
(5,11,17,23,29,35,41,47,53,59,65,71) 数列の数が12個あります。

このように、このプログラムコードを使った出力結果と、実際の公式に基づいた計算で解答が一致して、ちゃんと等差数列が出力されます。


### 等比数列のプログラムコード
ここでも、ユーザーが初めの項、公比、項数を指定します。
その後、等比数列になります。
``` python
def geometric_sequence(a, r, n):
  """
  等比数列を生成する関数

  Parameters:
  a (int or float): 初項
  r (int or float): 公比
  n (int): 項数

  Returns:
  list: 等比数列
  """
  sequence = []
  for i in range(n):
      sequence.append(a * (r ** i))
  return sequence

# ユーザー入力
a = int(input("等比数列の初項を入力してください: "))
r = int(input("等比数列の公比を入力してください: "))
n = int(input("等比数列の項数を入力してください: "))

print("等比数列:", geometric_sequence(a, r, n))
```
### プログラムコードの説明
ここでは、等比数列の初項をa,公比をr,項数をnとしています。

### 出力結果
``` python
等比数列の初項を入力してください: 2
等比数列の公比を入力してください: 5
等比数列の項数を入力してください: 3
等比数列: [2, 10, 50]
等比数列の初項を入力してください: 3
等比数列の公比を入力してください: 7
等比数列の項数を入力してください: 5
等比数列: [3, 21, 147, 1029, 7203]
等比数列の初項を入力してください: 5
等比数列の公比を入力してください: 8
等比数列の項数を入力してください: 7
等比数列: [5, 40, 320, 2560, 20480, 163840, 1310720]
```
### 出力結果の確認
初項：数列において、最初となる数
公比：等比数列において、次の数までの比
項数：等比数列の合計の数列の数

1つ目では、初項2, 公比5, 項数3
(2,10,50) 数列の数は**3**個で、各項の差も**5**になっています。
50 / 10 = **5**, 10 / 2 = **5**
2つ目では、初項3, 公比7, 項数5
(3,21,147,1029, 7203)
7203/1029 = **7**, 1029 / 147 = **7**, 147/21 = **7**, 21/3 = **7**
数列の数は**5**個で、各項の差も**7**になっています。
3つ目では、初項5, 公比8, 項数7
(5,40,320,2560,20480,163840, 1310720)
1310720/163840 = **8**, 163840/20480 = **8** , 20480/2560 = **8**, 2560/320 = **8**, 320/40 = **8**, 40/5 = **8**
数列の数は**7**個で、各項の差も**8**になっています。

このように、このプログラムコードを使った出力結果と、実際の公式に基づいた計算で解答が一致して、ちゃんと等比数列が出力されます。

皆さんも時間がある時にこのプログラムコードを参考にして、等差数列、等比数列を出力してみてはいかがでしょうか。
railsでテキストの暗号化と複合化のやり方

今回「SPA」から「railsサーバー(APIモード)」へpostリクエストをする際のセキュリティを考える機会があり、そこでテキストの暗号化と複合化を行なったのでメモとして記述します。

## 経緯
今回の経緯としては、「SPA」から「railsサーバー(APIモード)」へpostリクエストをする際にCSRF対策として認証機能をつけようとしたのですが、今回のケースでは通信でクッキー、セッションが使用できませんでした。

そのため簡易的なセキュリティ対策だけでも設定しようということになりました。
そこでテキストの暗号化と複合化に手こずったので方法をメモで残します。

## 方法
今回の方法は正しい方法かと言われると少し自信がありませんので、使用する際にはご注意ください。

### 暗号化について
暗号化処理の方法としては、encrypt_and_signという暗号化するメソッドを使用できるようするために、32バイトのキーを生成し、それを元にインスタンス作成を行なっています。

ActiveSupport::KeyGeneratorについては、引数にある「keyword」の中身はどんな値でも問題ありません。理由としては、「ActiveSupport::MessageEncryptor」でインスタンスを作成するためだけに、32バイトのキーが必要になってくるためです。
```
keyword = "暗号化したいテキスト"

# 32バイトのキーを生成
key = ActiveSupport::KeyGenerator.new( keyword ).generate_key( keyword, 32 )

# インスタンス作成
instance = ActiveSupport::MessageEncryptor.new( key )

# 暗号化
encryption_key = instance.encrypt_and_sign( keyword )
```

### 複合化について
最初は暗号化と同じようにインスタンスを作成します。
その後、decrypt_and_verifyで複合化を行います。

```
keyword = params[:keyword]

# 32バイトのキーを生成
key = ActiveSupport::KeyGenerator.new( keyword ).generate_key( keyword, 32 )

# インスタンス作成
instance = ActiveSupport::MessageEncryptor.new( key )

# トークンの復号化
composite_key = instance.decrypt_and_verify( keyword )
```

この処理は少し不恰好な処理になっていますが、なんとかテキストの暗号化と複合化ができています。

もっといい方法などがあれば教えていただきたいです。
イギリスCS学士で学ぶこと

イギリスCS課程の学士は３年間で卒業できます（スコットランドは４年）。一般教養科目はなく、基本はすべて専門科目になります。学校によって自由度はかなり差があり、私の大学は自由度がかなり高い方だと思います。ですがそれでも専門科目以外はビジネスか言語を選択できる程度でした。
Hは必修を意味します。

イギリスCSで学んだ科目を以下に記します。
### 大１
・チームプロジェクトH ->基本なんでもいいから作る。ゲームとかスケジュール管理とか多そう。Backend&Frontendで分けました。
・CSのための数学H　->線形代数とか離散数学とか。
・計算基礎H　->オートマトンとか
・計算工学基礎H ->メモリ、プロセッサとか
・データサイエンスH　->統計とかCDF,ベイズ、いろいろ
・アーキテクチャH ->アセンブリとかコンパイラとか
・OS(H) ->基礎
・プログラミング１(Python)H　->基礎、ゲーム作りがコースワーク
・プログラミング２(Java)H　->基礎、ボードゲームのコースワーク。jenkinsでテストケースどれぐらい通すかで点数もらえる。満点は学年にいない。
大学対抗のプログラミングコンテストに向けて精進してる友達とかもいました！
### 大２
・データベース ->設計とか基礎
・ロジックとモデリング ->数学、アルゴリズム系
・ソフトウェア工学１H ->OSSゲームのバグ修正とか、git、チームワーク
・ソフトウェア工学２H　->OSSゲームの新機能とかgit、チームワーク
・AI入門 ->数学、基礎いろいろ。先生のアクセントと語彙がオックスフォードすぎる。
・機械学習 ->数学、統計とか
・アルゴリズムとデータ構造H ->テストだるかった、基礎。コースワークでDPとか(python,java,Cのいづれか）
・プログラミングパラダイム(C,C++,Haskel,Rust,solidityなど）H
・Visualコンピューティング ->グラフィック系の基礎、アルゴリズムとか光沢？
・分散システム ->ネットワークとか
### 大３
・卒研H ->AIからドローンからブロックチェーンとかいろいろ選べる。提案した研究も可。
・AIとゲーム ->HexでのAIコンペ、モンテカルロ木探索とかミニマックスとか。期末試験が問題多すぎて終わらない人多数。
・IoT ->基礎いろいろネットワークとか。質問かえってこない。
・セキュリティ ->リスクとか暗号とか、覚えること多すぎ。質問返ってこない。
・NLP ->NLP基礎、ドキュメント分類のタスク。授業進め方いい。
・機械学習のための数学 ->統計的機械学習、ラデマッハ複雑度とか。
・言語 ->中国語選びました。少人数(5人とか）で話すこと多め。テストも４技能全部。
・コンピューターグラフィックス ->アニメーションとかレンダリングとか。内容重め

## 大学
大学１年はすべて必修で２年は半分必修、３年は卒論が必修でした。
大学入学前に環境構築の手引きを渡されて(60pぐらい）Linux mintのインストールとgitの学習をしとくよう言われて辛かった記憶があります。イギリス人はだいたい入学する時の選択科目でCSを取ってきていて超基礎&ある程度のプログラミング経験してきてる人がほとんどでした。留学生はプログラミング初心者も結構いた記憶があります、私もそうでしたし。大学の授業は１科目でも落としたら退学です！再試で落ちたら留年なく退学です。大学最終学年では再試はなく、単位落としたらBSc(Hons)がBScの普通学位になるようです。
最近は入学水準のインフレが激しくIelts7.5だったりA-levelで全部A*が要求されるようです。IBなら41とか？

大学１年次のプログラミング１を教える先生が最悪で、１年で５０人ぐらい同級生が消えていきました。中間テストで習っていないこと出して調べて１週間以内に解け、みたいなものでした。プログラミング意欲ダダ下がりでした。５年プログラミングしてきていた同級生が満点とれないレベルのタスクが含まれていました（確か暗号系？）。授業後の授業評価５段階で１で出しました。２年次のデータベースも同じ先生で点数低く最悪やと思ってました。友達と協力するとコード類似でばれて問答無用で再試行きのようでした。マレーシアの友達が４人追試へ、、、

放校後は他大学への編入もあるようですがレベル感は下の大学に行くしかないようなのが実際です。一年浪人して他の大学に再度進学する人もいるようです。大変な学科ですが卒業後の実りもいい人は多いです。Google,MS,IBM,Mckinsey,ARM,JP Morganとか。日本人は同級生１人もいなかったですがインド人や中国人留学生がかなり多いので友達はできやすいと思います。アニメ好きな同級生も多いので第一印象は日本人良さげかもですね！中国人留学生は院進でアメリカ行ったりイギリス他大行ったりしますね。

大学入学は9月下旬ですが友人たちは夏インターンの申請とかを１１月ぐらいからし始めていて意識たけーって感じました。だいたい1月締切なのかな。プログラミング初心者はCVに書くことないのでやばいやばいと思っていて結局インターンは3月ぐらいに日本の企業に申請して夏働かせてもらいました。大学２年次にいい企業でインターンするためには大学１年でインターンしていないと厳しいのでみんな動き出しが早かったようです。
M5Stackで設定を記憶！電源オフでも安心なEEPROM活用術

## EEPROMとは？
<B>電源を切ってもデータを保持できる不揮発性メモリ</B>です。
M5Stackでも設定やデータを保存するのに使えます。

## M5flowでの使い方
<B>書き込み</B>
keyと値を指定して書き込むだけです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826679/5e443525-79c7-3d70-a61f-89b9137e7113.png)

<B>読み込み</B>
keyを指定して読み込むだけです。
読み込み時に値が存在しない場合は、変数にNullが入ります。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3826679/8ba929c8-f891-8767-1a03-df660778f05f.png)
DBMS_OUTPUT.PUT_LINEが表示されない

`DBMS_OUTPUT.PUT_LINE`を表示するには、以下を事前に実行しておく必要があります。

```
SET SERVEROUTPUT ON
```

**例:**

```sql
SET SERVEROUTPUT ON;
BEGIN
  DBMS_OUTPUT.PUT_LINE('HELLO WORLD');
END;
```

**参考:**

https://docs.oracle.com/cd/E57425_01/121/SQPUG/GUID-5EA17047-1EBC-44BA-A21A-B4CEC27FD6B0.htm

**環境:**

```
SELECT * FROM v$version;
```

|BANNER|BANNER_FULL|BANNER_LEGACY|CON_ID|
|:---|:---|:---|---:|
|Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production|Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production<br>Version 21.3.0.0.0|Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production|0|
拡張関数2

前回の投稿の続きです。実務で使いそうな関数をまとめる。

```kotlin
val numbers = listOf(1, 2, 3, "four", "five", "six", "seven")
```

### Slice

指定したインデックスのリストを返す

```kotlin
val range = numbers.slice(1..3)
val rangeSet = numbers.slice(listOf(3, 6))

println(range)    // [2, 3, four]
println(rangeSet) // [four, five, six, seven]
```

### Take

指定した数値分の要素を取得する

```kotlin
val takeList = numbers.take(4)

println(takeList)  // [1, 2, 3, four]
```

### Drop

指定した数値分の要素を除外する

```kotlin
val dropList = numbers.drop(4)

println(dropList)  // [five, six, seven]
```

### First、Last、ElementAt

最初の要素、最後の要素、指定した要素を取得する

```kotlin
val firstCut = numbers.first()
val lastCut = numbers.last()
val indexAt = numbers.elementAt(3)

println(firstCut)  // 1
println(lastCut)   // seven
println(indexAt)   // four
```


### Shuffled

リストをランダムにしたリストを作成する。

```kotlin
val shuffleList = numbers.shuffled()

println(shuffleList)   // [2, six, five, four, seven, 1, 3]
```

## 集約関数

```kotlin
val testResults = mapOf(
    "国語" to 82,
    "数学" to 88,
    "科学" to 63,
    "社会" to 87,
    "英語" to 91,
)
```
### MaxByOrNull

カスタムオブジェクトの中で最大のものを返す、`minByOrNull`は最小のものを返す

```kotlin
val maxList = testResults.maxByOrNull { it.value }

println(maxList)   // 英語=91
```
### Count

要素内の数を取得する

```kotlin
val countList = testResults.count()

println(countList) // 5
```

### SumOf

カスタムオブジェクトの合計値を返す、`average`は平均値を返す。

```kotlin
val sumList = testResults.values.sumOf { it }

println(sumList) // 411
```

#### 参考
[Kotlin Collection関数をマスター](https://speakerdeck.com/masayukisuda/kotlin-collectionguan-shu-womasuta)
【Unity】Recorderをスクリプトで制御する

# Recorderとは？

「Unity Recorder」とは、Unity のエディタ内でゲームプレイ、アニメーション、
その他のシーンコンテンツを、ビデオ・画像・オーディオ・アニメーションクリップ
などの、様々な形式でキャプチャおよびエクスポートするツールです。

# インストール方法

Unityエディタを開き、上部のメニューから
「Window」>「Package Manager」を選択します。
右上の検索バーに「Recorder」と入力し、出てきたパッケージをインストールします。

<img width="650" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470968/da262600-c99c-ddf4-08d5-6448ff560ed0.png">

# スクリプトで制御する

「Window」>「General」>「Recorder」>「Recorder Window」
の順に選択すると、画像のようなウィンドウが表示されます。
今回は、ウィンドウの各種設定と録画の開始・終了をスクリプトから制御します。

<img width="650" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470968/8b9069e8-ae8d-78c3-05c7-6f9ba9af7d0d.png">

制御するにあたって、最初にアプローチを整理します。

**『Recorderの設定 -> Controllerの設定 -> Recorderの追加 -> Controllerの作成』**

この順番で処理を書いていきます。

---

**1.「Recorderの設定」**

-> ウィンドウの左にある「Add Recorder」から追加できるレコーダー本体の設定。

```cs
// インスタンスを作成
recorderSettings = ScriptableObject.CreateInstance<MovieRecorderSettings>();

// 出力形式
recorderSettings.OutputFormat = MovieRecorderSettings.VideoRecorderOutputFormat.MP4

// ビデオ品質
recorderSettings.VideoBitRateMode = UnityEditor.VideoBitrateMode.High

// 出力設定
recorderSettings.OutputFile = $"保存先のパス/ファイル名";

// 録画設定
recorderSettings.ImageInputSettings = new GameViewInputSettings();

// 録音設定
recorderSettings.AudioInputSettings.PreserveAudio = true;

// 有効化
recorderSettings.Enabled = true;
```

---

**2.「Controllerの設定」**

-> レコーダーを管理し、レコーディングの開始・終了を行うコントローラーの設定。

```cs
// インスタンスを作成
controllerSettings = ScriptableObject.CreateInstance<RecorderControllerSettings>();

// フレームレートの制御方法
controllerSettings.FrameRatePlayback = FrameRatePlayback.Constant;

// フレームレート
controllerSettings.FrameRate = 30f;

// フレームレートを制限するか
controllerSettings.CapFrameRate = true;
```

---

**3.「Recorderの追加」**

-> 1.で作成したレコーダーの設定を、2.で作成したコントローラーの設定に追加。

```cs
controllerSettings.AddRecorderSettings(recorderSettings);
```

---

**4.「Controllerの作成」**

-> コントローラーのインスタンスを作成して、レコーディングを開始・終了させる。

```cs
// インスタンスを作成
controller = new RecorderController(controllerSettings);
// レコーディングの準備
controller.PrepareRecording();
// レコーディングの開始
controller.StartRecording();
```

---

あとは、終了したいタイミングで「RecorderController.StopRecording()」を呼びます。
録画に成功すると、OutputFile で指定したパスに新しく動画ファイルが作成されます。

以上がスクリプトによる（Movie）Recorderの制御です！
最後までご覧いただきありがとうございました :laughing:
Ethernet, PCIe, NVMeの規格別転送速度まとめ




| Category   | Standard/Version       | Max Speed (Gbps)   | Max Speed (GB/s)   |
|:-----------|:-----------------------|:-------------------|:-------------------|
| Network    | SFP                    | 1 Gbps             | 0.125 GB/s         |
| Network    | SFP+                   | 10 Gbps            | 1.25 GB/s          |
| Network    | SFP28                  | 25 Gbps            | 3.125 GB/s         |
| Network    | QSFP                   | 40 Gbps            | 5 GB/s             |
| Network    | QSFP28                 | 100 Gbps           | 12.5 GB/s          |
| PCIe       | PCIe 3.0               | 8 Gbps per lane    | 1 GB/s per lane    |
| PCIe       | PCIe 4.0               | 16 Gbps per lane   | 2 GB/s per lane    |
| PCIe       | PCIe 5.0               | 32 Gbps per lane   | 4 GB/s per lane    |
| NVMe M.2   | NVMe M.2 (PCIe 3.0 x4) | 32 Gbps            | 4 GB/s             |
| NVMe M.2   | NVMe M.2 (PCIe 4.0 x4) | 64 Gbps            | 8 GB/s             |
| NVMe M.2   | NVMe M.2 (PCIe 5.0 x4) | 128 Gbps           | 12 GB/s            |
ApacheとSSL/TLS化

## ApacheとSSL/TLS化

### 目的
* Apache + mod_ssl で HTTPSアクセスするまでの手順をまとめます
* 自己署名証明書を使います（ブラウザでセキュリティの警告が表示されます）

### 前提
* Apacheはインストール済み
* 秘密鍵（localhost.key）、証明書署名要求（localhost.crt）を作成済み
[自己署名証明書の作り方](https://qiita.com/tonoaki_sato/items/b3437d9c637b096b5b86)
* 秘密鍵（localhost.key）の保存先を /etc/pki/tls/private とします
* 証明書署名要求（localhost.crt）の保存先を /etc/pki/tls/certs とします
* サーバーのURLを 192.168.56.130 とします

### 手順
##### 1. mod_ssl インストール
```console
[root@marmoset ~]# dnf install mod_ssl
```
##### 2. 秘密鍵、証明書署名要求ファイル配置
```console
// 秘密鍵配置
[root@marmoset ~]# cp localhost.key /etc/pki/tls/private/

// 証明書署名要求配置
[root@marmoset ~]# cp localhost.crt /etc/pki/tls/certs/
```
##### 3. ssl.conf編集
```console
[root@marmoset ~]# vi /etc/httpd/conf.d/ssl.conf
```
編集内容
```diff
44c44
< #ServerName www.example.com:443
---
> ServerName 192.168.56.130:443
59c59
< #SSLProtocol all -SSLv3
---
> SSLProtocol +TLSv1.2
```
以下の設定は、各ファイルを設定に合わせて配置済みなのでパスが正しいかを確認
* 秘密鍵ファイルの格納場所
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
* 署名要求ファイル格納場所
SSLCertificateFile /etc/pki/tls/certs/localhost.crt

##### 4. httpd再起動
```console
[root@marmoset ~]# systemctl restart httpd.service
```

##### 5. httpsポート開放
```console
// ポート開放
[root@marmoset ~]# firewall-cmd --add-service=https --zone=public --permanent
success

// リロード
[root@marmoset ~]# firewall-cmd --reload
success

// 確認
[root@marmoset ~]# firewall-cmd --list-all | grep services
  services: cockpit dhcpv6-client http https ssh
```
##### 6. ブラウザから https://192.168.56.130/ にアクセスしてセキュリティの警告ページが開けば（とりあえず）OK

## 感想
* 次のステップとして、セキュリティの警告が出ない証明書の作り方を勉強する
SwiftUI 不透明度の設定方法

不透明度の設定方法です。

![Simulator Screenshot - iPhone 15 Pro - 2024-07-07 at 14.24.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/9f4750ba-7a60-ae98-d5ff-83661c8c8ac6.png)

`.opacity`を設定することで可能です。
1.0〜0.0を設定して、０に近いほど透明になります。


```OpacityView.swift

struct OpacityView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
                .opacity(1.0)
            Text("Hello, World!")
                .opacity(0.8)
            Text("Hello, World!")
                .opacity(0.6)
            Text("Hello, World!")
                .opacity(0.4)
            Text("Hello, World!")
                .opacity(0.2)
            Text("Hello, World!")
                .opacity(0.0)
        }
    }
}

```
[Dify]Discordに投稿できるようにする。

## Discord連携

まずは連携したいサーバーのチャンネルの歯車ボタンを教えてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/db78590b-2a19-6f06-bbec-e7a797a17582.png)

以下のような画面になると思うので、連携サービスから「ウェブフックを作成」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/46fefb11-e5b8-bcb0-3f76-a7485f3f47c9.png)

そしたら以下の画面になるので「新しいウェブフック」をクリックするとウェブフックが作成される
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/35921817-560a-eb58-194c-4fecc01c8147.png)

作成したら「ウェブフックURLをコピー」をクリックしてURLをコピーしておいてください。

![スクリーンショット 2024-07-07 14.08.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/1ccb548e-0636-1e4b-0679-2fa94c0267cd.png)

## Difyの設定
以下のフローを作成します。
![スクリーンショット 2024-07-07 13.57.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/f2ce0935-2dbf-6230-2499-b2fa3de96cf6.png)

### Discord連携ノード
Discord連携ノードはこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/2534e180-f009-0f8f-5f50-872a6b6b5e07.png)

JSONで以下を送信している。
```
{"content": "{{#LLM.text#}}"}
```


## 結果
では実行して見ましょう。
![スクリーンショット 2024-07-07 14.21.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/95aa647a-84ea-e8f9-4ca0-a9ad3a84955f.png)


無事連携できました！

![スクリーンショット 2024-07-07 14.18.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/c11f6f07-b985-7a9a-c741-1a264d8b30e0.png)

## 最後に

Xをやっているので気になる方はフォローお願いします。

https://x.com/hudebakonosoto
Ubuntu環境でS3バケットをマウントしてみよう

# 最初に
* AWS上に構築したEC2に対して、mount-s3の設定手順を簡単にまとめたものとなります
* AWS CLIのインストールと認証情報は設定済みで進めます
* 設定までのため、マルチパートアップロードの確認やEBSとの比較検証は未実施です
* fstabの設定は後日追記の予定です

# mount-s3とは
* [Mountpoint for Amazon S3 の使用](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/mountpoint.html) を参照
* [awslabs/mountpoint-s3](https://github.com/awslabs/mountpoint-s3)を参照

## ゴール
* `Mountpoint for Amazon S3` を使用してAmazon S3バケットを一時的にローカルディレクトリにマウントし、ファイルのアップロードやダウンロードができること

## 設定手順
### 1. mount-s3をインストール
```sh
wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.deb
sudo apt-get install -y ./mount-s3.deb
```

### 2. S3バケットをマウントするためのディレクトリ作成
```sh
sudo mkdir -p /mnt/mount-data
```

### 3. mount-s3コマンドを使用してS3バケットをマウントの設定
```sh
sudo mount-s3 mountpoint-s3 /mnt/mount-data
```

### 4. マウントしたディレクトリに事前にバケットにアップロードしたファイルがあるかを確認
注意：あらかじめ適当なファイルをアップロードした上で確認をしています
```sh
ls /mnt/mount-data
```

### 5. ファイルのアップロードとダウンロードの確認
ファイルのアップロード
```sh
echo "Hello, S3!" > /mnt/mount-data/hello
```

ファイルのダウンロード
```sh
cat /mnt/mount-data/hello
```

## まとめ
* 設定自体はとても簡単にできました。
* ただし前述の通り実務に耐える速度が出るかはこれからのため、結論はもう少し先になりそうです。
GitHub Actions で Go の静的解析実行

CI の一環として、GitHub のデフォルトブランチに PR を作成した時と、マージをした時に静的解析を行う GitHub Actions を作成します。
※本記事は[GitHub Actions で Go のテスト実行](https://qiita.com/yoshihiro-kato/items/2a3725e2b8cc1682a288)の続編です

### ファイル構成
```
.github
　　├─ actions
　　│   └─ go-ut
　　|       └─ action.yml
　　│   └─ static-check
　　|       └─ action.yml
　　└─ workflows
    　　└─ ci.yml
json
　　├─ go.mod
　　├─ go.sum
　　├─ pretty_print.go
　　└─ pretty_print_test.go
.gitignore
```
UT も GitHub Actions から行っているため、静的解析の実行は action.yml に記載しています。

### Action
```.github/actions/static-check/action.yml
name: Go static check
description: Run go unit test

inputs:
  go-directory:
    required: true
runs:
  using: 'composite'
  steps:
    - uses: actions/checkout@v4

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21'

    - name: go vet
      shell: bash
      run: |
        echo "### go vet summary" >> $GITHUB_STEP_SUMMARY
        go vet >> $GITHUB_STEP_SUMMARY
      working-directory: ${{ inputs.go-directory }}

    - name: Install staticcheck
      shell: bash
      run: go install honnef.co/go/tools/cmd/staticcheck@latest

    - name: staticcheck
      shell: bash
      run: |
        echo "### staticcheck summary" >> $GITHUB_STEP_SUMMARY
        staticcheck >> $GITHUB_STEP_SUMMARY
      working-directory: ${{ inputs.go-directory }}
```

引数には、チェック対象の Go モジュールのディレクトリ（go-directory）を定義しています。
また、解析結果を GitHub Action のサマリーとして出力しています。

静的解析は、vet と staticcheck を実行しています。
Golint は非推奨となり、staticcheck と vet が推奨されています。
https://pkg.go.dev/golang.org/x/lint

### Workflow
```.github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  CI:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Static check
        uses: ./.github/actions/static-check
        with:
          go-directory: ./json

      - name: Go UT
        uses: ./.github/actions/go-ut
        with:
          go-directory: ./json
```

### 実行結果
main ブランチに PR を作成すると静的解析が実行されます。
![スクリーンショット 2024-07-07 13.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254520/33ad9510-38c1-ed4a-5283-6d9f94374777.png)

静的解析の結果に問題があった場合は、GitHub　Action　が失敗し、Details　から結果を確認することで、問題箇所の特定ができます。
![スクリーンショット 2024-07-07 13.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254520/f687aec2-fe78-752c-591a-ed40be645c6d.png)

### TODO
- Summary を見やすくする
Ubuntu(Debian系)でGoogleChromeのインストール

# 以下スクリプトで可能

```SHELL
# パッケージの取得
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

# インストール
sudo apt install -y ./google-chrome-stable_current_amd64.deb

# 残骸を削除
rm ./google-chrome-stable_current_amd64.deb 

```
# 各コマンドの解説
1. パッケージの取得

```sh
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
```
説明:
wget: このコマンドは、ウェブからファイルをダウンロードするためのユーティリティです。
https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb: これは、ダウンロードしたいファイルのURLです。このURLはGoogle ChromeのLinux版（64ビット版）の最新の安定版パッケージ（.debファイル）を指しています。
全体の意味:
このコマンドは、Google Chromeの最新の安定版パッケージをGoogleのサーバーからダウンロードし、現在のディレクトリに保存します。

2. インストール
```sh
sudo apt install -y ./google-chrome-stable_current_amd64.deb
```
説明:
sudo: このコマンドは、管理者権限を必要とするコマンドを実行するために使います。sudoが付いているコマンドは、システムに変更を加えることができます。
apt install: これは、パッケージをインストールするためのコマンドです。aptは、Debian系のLinuxディストリビューション（例えばUbuntu）で使用されるパッケージ管理ツールです。
-y: このオプションは、インストール中に表示される全ての確認プロンプトに対して自動的に「yes」と答えるようにします。これにより、ユーザーの手動での確認なしにインストールが進行します。
./google-chrome-stable_current_amd64.deb: これは、現在のディレクトリにあるインストールしたいパッケージファイルを指しています。
全体の意味:
このコマンドは、ダウンロードしたGoogle Chromeの.debパッケージファイルをシステムにインストールします。

3. 残骸を削除
```sh
rm ./google-chrome-stable_current_amd64.deb
```
説明:
rm: このコマンドは、ファイルやディレクトリを削除するために使用されます。
./google-chrome-stable_current_amd64.deb: これは、削除したいファイルを指しています。ここでは、ダウンロードしたGoogle Chromeのパッケージファイルを示しています。
全体の意味:
このコマンドは、ダウンロードしたGoogle Chromeのパッケージファイルを削除します。インストールが完了したため、このファイルはもう必要ありません。

## 全体の流れ
Google Chromeの最新の安定版パッケージをダウンロードします。
ダウンロードしたパッケージをシステムにインストールします。
インストール後に不要になったパッケージファイルを削除します。
この一連のコマンドにより、Google Chromeがシステムにインストールされ、インストール後の不要なファイルが削除されます。
TCP/IPについて知見を深める③

SDN
--



**Software Defined Network**
ソフトウェアを用いてネットワークを制御する技術の総称
・運用管理のシンプル化を目的としていて、DCやISPで使用されている

コントロールプレーンにあるSDNコントローラーはデータプレーンにあるハードウェアに設定を送り込むことで仮想ソフトウェアを作っている


コントロールプレーン
----
SDNにおいてネットワークの全体を制御している。

データプレーン
---
SDNにおいてパケットを転送する役割を持つ

オーバーレイ型
---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/4d0a9906-66b2-74e3-94a1-9871e655a3c0.png)

スイッチ間にトンネリングを定義することで既存の物理ネットワーク環境を使用することができる仕組み
オーバーレイ型では**ハイパーバイザー**に組み込んである仮想スイッチを使用する

>**ハイパーバイザー**
>サーバー仮想化などで利用される、コンピューターを仮想化するための制御プログラム
VMwareのvSphereやマイクロソフトのHyper-V、Linuxで使われるKVM等が利用されている。

1　SDBコントローラーから両端のスイッチに対してトンネル(VXLAN)の設定を流す
2　パケットを受け取った片方のスイッチはVXLANのヘッダーを付けてカプセル化を行いトンネルに流す
3　もう片方のスイッチはVXLANを非カプセル化で外したのち、宛先端末に転送する。

**ホップバイホップ型の衰退もあり、SDNといえばほぼオーバーレイ型を指すことが多い**


ホップバイホップ型
---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/95923f8e-8ec2-c92f-d39a-396310e95bea.png)
スイッチ一つ一つに情報経路（フローエントリー）を渡すことでその情報をもとにパケットに転送する方式の事を指す
経路の配布には**OpenFrow**と呼ばれるプロトコルが使用されている
制限が多いため、商用価値がなく、採用している企業は非常に少ない

https://www.infraexpert.com/study/sdn02.html
******
CDN
----
**Content Delivery Network** の略称
Webコンテンツで利用されている様々なファイルを大量配信する為に最適化されたインターネット上のサーバーネットワークである
****
CDNはオリジナルのWEBコンテンツを持っている**オリジンサーバー**とそのキャッシュを持っている**エッジサーバー**で構成されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/d01d047f-2f9d-1834-f1f6-105c1dd5b7d8.png)

ユーザーは物理的に距離の近いエッジサーバーに接続させられる
エッジサーバーにキャッシュがなかったり、有効期限が切れている場合のみ、オリジンサーバーとキャッシュサーバーがやり取りを行う
物理的に距離が近いサーバーにアクセルするようになっていることでユーザーとサーバーの距離の影響でダウンロード速度が改善するだけではなく、サーバーの負荷の分散にも役立っている。
Goで再帰関数を作ってみる

## コード

フィボナッチ数列を計算する

```go
package main

import (
	"fmt"
)

func fibonacci(n int) int {
	if n <= 1 {
		return n
	}
	return fibonacci(n-1) + fibonacci(n-2)
}

func main() {
	n := 10
	fmt.Printf("fibonacci(%d) = %d\n", n, fibonacci(n))
}
```

## 動かしてみる
```zsh
go run main.go

fibonacci(10) = 55
```

## コード

階乗を計算する

```go
package main

import (
	"fmt"
)

func factorial(n int) int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n-1)
}

func main() {
	n := 10
	fmt.Printf("factorial(%d) = %d\n", n, factorial(n))
}
```

## 動かしてみる

```zsh
go run main.go

factorial(5) = 120
```
分からなかったトランザクション

## はじめに
今回は課題を進めていくなか、改めて「？」とかんじた`トランザクション`と関係する`ロールバック`について学んだことをアウトプットしたいと思います。

## トランザクションとは
- 意味: 一連のデータベース操作を一つのまとまった処理単位として扱うこと
- 特徴: トランザクション内で行われたすべての操作は、すべて成功するか、またはすべて失敗するかのどちらかになる。これを**ACID特性**と呼ぶ
・**Atomicity（原子性）**: 全ての操作が完全に実行されるか、全く実行されないかのどちらか。
・**Consistency（一貫性）**: トランザクションが完了すると、データベースは常に一貫した状態になる。
・**Isolation（独立性）**: 同時に実行されるトランザクションは互いに干渉しない。
・**Durability（永続性）**: トランザクションが完了した後、その結果は永続的に保存される。

## ロールバックとは
- 意味: トランザクション内でエラーが発生した場合、トランザクション開始前の状態にデータベースを戻すこと
- 機能: トランザクション内の全ての操作を無効にすることで、データの一貫性を保つ
- 使用することで得られる利点
・**データの一貫性の確保**: 複数の操作が途中で失敗した場合でも、データベースが不整合な状態になるのを防げる
・**エラーハンドリングの簡素化**: エラーが発生した場合、ロールバックを行うだけでデータベースの状態を元に戻せる
・**信頼性の向上**: データベース操作が失敗しても、安全にリカバリできるため、アプリケーション全体の信頼性が向上する


## 具体例
銀行の送金システムで、以下の2つの操作をトランザクションとして扱うとする
- 送金元の口座から指定金額を引き落とす
- 送金先の口座に指定金額を入金する

もし2番目の操作でエラーが発生した場合、1番目の操作も無効にして元の状態に戻す（ロールバック）ことで、データの一貫性を保つことができる
```
def transfer_funds(from_account, to_account, amount)
  ActiveRecord::Base.transaction do
    from_account.decrement!(:balance, amount)
    to_account.increment!(:balance, amount)
  end
rescue => e
  Rails.logger.error("Transfer failed: #{e.message}")
  raise ActiveRecord::Rollback
end
```
このようにトランザクションとロールバックを使用することで、信頼性の高いデータベース操作が実現できる

詳細なシミュレートは次の通り
```
require 'sequel'

# データベース接続（SQLiteを例に使用）
DB = Sequel.sqlite

# テーブルの作成
DB.create_table :accounts do
  primary_key :id
  String :name
  Float :balance
end

# アカウントモデルの定義
class Account < Sequel::Model
end

# アカウントの初期データを追加
account_a = Account.create(name: 'Aさん', balance: 1000.0)
account_b = Account.create(name: 'Bさん', balance: 500.0)

def transfer(from_account, to_account, amount)
  DB.transaction do
    # Aさんの口座からお金を引き出す
    from_account.update(balance: from_account.balance - amount)
    raise "残高不足" if from_account.balance < 0

    # Bさんの口座にお金を入れる
    to_account.update(balance: to_account.balance + amount)
  end
rescue => e
  puts "エラー発生: #{e.message}"
  raise Sequel::Rollback
end

# 振り込み操作
begin
  transfer(account_a, account_b, 200.0)
  puts "振り込み成功"
rescue
  puts "振り込み失敗"
end

# 結果の確認
puts "Aさんの残高: #{account_a.reload.balance}"
puts "Bさんの残高: #{account_b.reload.balance}"
```

## さいごに
ネットで何でも決済できるようになっていて、具体例のようなトランザクションとロールバックの仕組みの重要性を改めて実感しました。こういうところで活用されているとは…:open_mouth:
私もいつか世の中のためになるようなものをつくりたいです
CodeAGIとは？\nすべてである！（面白い記事）

# はじめに

-- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | --

　　　**CodeAGI** とは？
　　　　　　　　　　　　　**すべて**
　　　　　　　　　　　　　　　　　　　　　**である！**

-- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | --

ということで、今回は

**生成AIサービスを活用して完全なプログラム自動生成を実現するアプリケーションサービス**

![code_agi_big.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/d0642af5-1901-ddec-1425-bc28493db385.png)
[ source : https://www.soppradx.com/images/code_agi_big.png ]

君についての記事を作成させていただきます。
よろしくお願いします。

※筆者の想いは [ 最後に ] に **ちょこっと** 記述させていただきます。

# この記事が書きたいこと
![document.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/b8b153e8-f93d-ce4e-9783-9107bfe4f709.jpeg)
[ created by : https://designer.microsoft.com/image-creator?scenario=texttoimage ]

## CodeAGI
CodeAGI 君は、**非常におもろい** らしい
というのも、彼は **いろいろな記事で紹介** されている（ぽい）

いったい、彼の **何が** そこまで魅力的なのだろうか

そこで、**彼女もいない** 筆者は **有意義な休日を過ごすべく** CodeAGI 君についての記事を読み漁った。

結果、**私には彼（ CodeAGI ）が使えない** ということがわかってしまった…

**（だったら記事書くなよ）**

さて、**なぜ私には彼（ CodeAGI ）が使えない** のか

答えは単純である

>>>...
**私は設計書が書けない**

この絶望的状況を回避するべくするために作成されたのだろう（か？）というサイトをこの記事では紹介させていただこうと思う。

つまり！読者諸君！

ここまでは、**まだ序章にしか過ぎない** のだよ…

1. https://www.canva.com/design/DAF4DEbH03s/7hsvXXmF6B2-QWUuLkopOw/view#1
**CodeAGI とは何ぞや？** ということが、**開発背景から** 紹介されているページ
**他社生成 AI ツールとの比較** もあり、自社の製品に対する自信を感じさせてくれる
CodeAGI を使ってみようかなと思われるのであれば、**絶対に見るべき**
1. https://qiita.com/degudegu2510/items/ce11056d5fb94e3dcebd
**CodeAGI とは何ぞや？** というところももちろん初めに記載されており、主な内容として、**どのようにして CodeAGI を使用してサービスのコードを生成していくのか** が書かれている
**セットアップ** から **テストケース・データを生成する** というところ、**CodeAGI の機能の良し悪し** まで、**細かく段階的に解説** してくださっているので、**非常にわかりやすい**
1. https://www.itmedia.co.jp/aiplus/articles/2406/07/news014.html
書かれている内容は、**CodeAGI とは何たるか！** ということ
それだけに特化した記事
**CodeAGI によって実現できること** を、今の一般的な開発現場の内容と照らし合わせながら解説してくれる
筆者はこの記事を読んだら **触りたくなった**（CodeAGI を）
1. https://www.issoh.co.jp/column/details/2767/#i-22
一言で言って **神**
まさに **全知全能** レベル
「CodeAGIのセットアップ方法：初めての導入手順を詳しく解説」
といったところから
「CodeAGIでのテストケースとテストデータの自動生成方法と利点」
まで、**7 セクション × 5 項目、全部で 35 項目** という、まさに  **CodeAGI についての知識の宝庫**
プロジェクトの作成手順、要件定義書の作成方法とその重要性、機能設計書の作成手法とベストプラクティス…等々
**これさえ読んでおけばよし！**

# 最後に

実はついさっきまで異世界転生のライトノベルを読んでいまして、文面が通常とはいささか変わったものになってしまいました。
誠に申し訳ございません。

それでも、真面目に CodeAGI （私は君と呼びたい）についての紹介記事を作成しました。

最近は Youtube 等でも、「エンジニアチャンネル」などといったエンジニア関係のチャンネルにおいて、生成AI を使用したアプリケーションの作成などについての動画が公開されています。

「エンジニアの仕事は AI に奪われてしまうのではないか？」といったこともよく話題にされますが、
**エンジニアはただ単にコードを書くだけの存在ではない**
ので、どんどん生成AI を利用して、自己の生産性と価値を高めていこうと思いますね。

**楽しなきゃ**

何かしら少しでも、読んでくれたあなたの知識等々になっていただければ、何よりも幸せなことです

最後まで読んでくれてありがとう！

貴方のエンジニアリングと日々の生活に成功がいっぱいありますように！

※今日は七夕🎋
古いバージョンの Android Studio を新規にダウンロードする方法

<h2>はじめに</h2>

AndroidStudioの過去バージョンをインストールしようとしたときに以下の画像が表示され、手こずったため解決策を備忘録として書き留めたいと思います。

![スクリーンショット 2024-07-07 13.44.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/6c725a63-a5ba-b118-64a7-6fda89e58e29.png)
<h2>手順</h2>

1.AndroidStudioの英語版にアクセスする。
https://developer.android.com/studio/archive

2.上記URLにアクセスしても日本語版の以下URLに切り替わってしまう場合は、画像の四角枠の箇所をEnglishに変更する。
https://developer.android.com/studio/archive?hl=ja
![スクリーンショット 2024-07-07 13.48.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/474adcd4-2e28-3d83-c71f-cc8184038d3d.png)

3.言語設定を変更すると、利用規約とともに[ダウンロードする前に、以下の条件に同意する必要がある旨]表示されるため、下までスクロールして[I agree to the terms]をクリックする。
![スクリーンショット 2024-07-07 13.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/b4064fd9-d43f-fa97-1049-1e3dae6da3a7.png)
![スクリーンショット 2024-07-07 13.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/a8b713c5-cec4-2fba-eb3a-656d7945756b.png)

4.利用規約に同意すると過去バージョンが一覧で表示されます。
![スクリーンショット 2024-07-07 13.58.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/5abfc2fb-c145-9cbb-2dda-9acbeb9e4a13.png)

<h2>参考サイト</h2>
https://qiita.com/84d010m08/items/8ccf62940f1a6425efdc
キーボードショートカットからスリープしたときだけ即解除される(Mac)

備忘録なので簡単にメモ。

## 状況
PC(Mac mini)でシステム環境設定からスリープにショートカットを割り振った。
しかしスリープはするものの即座に解除される。
マウス操作でメニューバーからスリープしたときはそのようなことは起きない。

## 結論
AutomatorでKarabinerのプロファイルを切り替えてスリープするサービスを作成して対応した。

## 原因
Karabinerがスリープから起こしてたらしい。細かいことは不明。

## 設定手順
- Karabiner Elementsから新しいプロファイルを作る。
( ここでは既存のプロファイル`default`、新しく作ったものを`disabled`とする )
- Automator → クイックアクションを選択 → 検索窓から「シェルスクリプトを実行」を選択 → 「ワークフローが受け取る現在の項目」を「入力なし」に設定 → 以下のスクリプトを設定


```
スリープ時
/Library/Application\ Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli --select-profile 'disabled'
pmset sleepnow
```

```
スリープ解除時
/Library/Application\ Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli --select-profile 'default'
```
- システム環境設定 → キーボード → ショートカット → サービス → 一般 に作成したサービスがあるのでこれに好きなショートカットを割り振る


## メモ
`pmset -g log`  で電源関係?のログを見れる。今回はここからKarabinerが怪しいと判断した(GPTが)
スケジュール遅延の予防法と是正法(本の要約)

# 概要
本記事は情報処理教科書 プロジェクトマネージャ 2024年版
の遅延対策に関するセクションを要約したものがメインです。


# 遅延の予防策	
**監視/モニタリングを行う**	
- 遅延を防ぐ究極の目的は**納期を守る**ことです。
- そのために、**進捗遅れの予兆**をつかみ、事前に対処する(別の言い方ではリスク軽減)	。				
- 進捗遅れの検知は**早いほど良い**。早いほど、対処も早く開始できるからです。進捗が遅れる前に持ち直すより、遅れた後に挽回する方が困難です。
- 監視のための具体的なアクションは2種類あります。どちらか一方でよい、というよりはどちらも異なるメリットがあります。
    - 1つ目は**進捗管理表**などのドキュメントで監視します。これは、予定と実績を定量的指標によって表す。予実に差があれば、それが遅れです。定量的指標の例は、4種類あります。スケジュールの進捗を監視する場合は、完了予定日と実際の完了日の差分です。ドキュメントの作成の進捗を監視する場合は、完成ページ数と作成予定ページ数の差分です。プログラムの場合は、作成されたプログラムの本数/予定本数で表現できます。テストの場合は、テスト実施数/テストケース数や改修済みの不具合の数/不具合の発生数がありえます。
    - 2つ目は**直接または進捗会議にて報告**を受ける。
進捗遅れの予兆に早く気付くためには、ドキュメント上だけではなくメンバーとの会話も重要です。というのも、管理のドキュメントでは順調でも、その裏にメンバーの様子がおかしい、疲れている、悩んでいるという状況が潜んでいる可能性があるからです。ただし、個別に報告を受けるのは費用対効果が悪いので、週に1度ほどの定例進捗会議を設け、そこで報告を聞くという方法が推奨されます。
											
## 特に、重要工程の管理の注意点
- 重要工程での予兆の管理は特に重要です。
- 重要工程とは、クリティカルパス上にある工程です。このような重要工程では、遅延につながる予兆を確実に管理対象に入れる必要がある。				
- 予実管理で予実の差分を検知する前に先手を打って問題につながる**潜在要因を特定**します。それを監視項目とします。次に、それらを測定するための**定量的指標**を設定します。その後、重点的にそれを監視し、進捗遅れの予兆が見られた時点で対策を施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081780/360441ae-4cd0-f063-c231-4415462ca3a6.png)

- 管理指標の例は以下の通りです。要員の生産性を測定するために、プログラム1本あたりの作成所要時間を監視する。プロジェクトを兼任している要員の負荷を測定するために、本プロジェクトと別プロジェクトに割いている稼働時間を監視する。				
						
											
# 遅延が起きてしまった後の対処法
以下の3ステップで行います。
**1. 根本原因分析を行う									
2. 原因を解消する
3. 発生した遅延を巻き返す**

## 1. 根本原因分析を行う

根本原因分析とは、課題を分析する手法です(英語ではRoot Cause Analysisと呼ばれます)。課題に関連するデータを集め、単一または複数の原因を特定し、優先度をつけ、解決策を検討するプロセスを踏みます。
    - 課題を明確に記述します。具体的には、あるべき状態は何かを記述します。ここではSMARTというフレームワークを使うのがおすすめです。次に現状の望ましくない状態も記述します。このようにして、あるべき状態と現状のギャップを特定します。このギャップを課題と呼びます。
    - その課題に関係のあるデータや情報を集めます。それを通じて、現状の望ましくない事象がいつ、どこで起きているかなどを明らかにします。
    - 次にそのギャップが発生している原因を分析します。そのための手法には、[なぜなぜ分析](https://it-trend.jp/project_management/article/33-0064#:~:text=%E3%81%AA%E3%81%9C%E3%81%AA%E3%81%9C%E5%88%86%E6%9E%90%E3%81%A8%E3%81%AF%E3%80%81%E3%83%88%E3%83%A8%E3%82%BF%E8%87%AA%E5%8B%95%E8%BB%8A%E3%81%8C%E7%99%BA%E6%A1%88%E3%81%97%E3%81%9F,%E3%81%AB%E7%94%9F%E3%81%BF%E5%87%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82)や[特性要因図](https://sp-jp.fujifilm.com/future-clip/visualization/vol33.html)があります

## 2.原因を解消する
- ここでの目標はこれ以上遅れが悪化しないようにすることです。
- 既に判明している原因を除去します。例えば、あるメンバーの生産性が予想よりも低く、その原因が体調が悪いという場合、根本原因は要員の体調不良です。そのまま現状維持をしても生産性が上がらなさそうな場合、要員を交代する打ち手が考えられます。それにより、遅延が悪化しないようにします。
				
## 3. 発生した遅延を巻き返す
- ここでの目標は、遅延を挽回し、それにより納期を遵守することです。
- 対処法は複数持っているのが望ましいです。そこで、対処法の例を挙げます。
    - クラッシングやファストトラッキング
    - 本番稼働の時期を延伸
ただしユーザーの合意が必要。一旦延伸したら、再延長は不可であるため慎重に再スケジュールをするべきである。								
    - 部分稼働
ただし、ユーザーの合意が必要。さらに、稼働させる機能は、定量効果の出やすいものが良い。かつ、後から機能追加や変更が可能なことを事前に確認するべき。						
    - スケジュールを組み替える
    具体的には、作業順序の見直しや、作業手順の指導をする。(担当者のスキル不足で作業効率が悪い場合)			
    - 要員の追加	
    ただし、要員の追加だけで回復できる見込みがあるかを事前に確認するべき。さらに、追加要員に必要なスキルがあることを確認すべき。加えて、コスト増の負担先は明確化しておく。							
    - 環境の改善
    例えば、開発場所を移動させる、開発設備を追加するなどを行う。ただし、これはほかの対策の補助的な対策。加えて、コスト増の負担先を明確化する必要がある。								
    - 進捗確認を強化する	クリティカルパスは強化する。遅延の挽回にはつながらない。遅延が顕在化するかなり前に気づいた場合にしか効果がない。							
											
# 参考資料

https://www.shoeisha.co.jp/book/detail/9784798185750


https://revdebug.com/blog/root-cause-analysis-in-software-development/
最高のエンジニアになるために：眠気とたたかう

## はじめに
どんな環境化でも多分熟睡することができるであろうわーちゃんです。
今回は学習中、仕事中な急な眠気にどう対処すればいいかをつらつら書いてみようかと思います。最高のエンジニアに限らず、仕事のはやいひとは眠気、というか睡眠をしっかりとっているはずだと思うので、いろんなサイトを参考にし、自分なりに実践できそうなものをまとめます。

## 眠気の原因
よく言われている眠気の原因について、
- 体内の生体リズムやホルモンの変化によるもの
- 体内時計が眠る時間を知らせるためにメラトニンというホルモンを分泌ことで眠気が生じる
- 日中の活動による疲労や血糖値の低下も眠気の原因になる

## エンジニアの睡眠事情
業界ごとや働く環境により、睡眠時間は大きく異なります。しかし、オフィスで眠気を感じる人は一定数いるようです（2024年で新しい記事なので、参考程度に）

https://www.manegy.com/news/detail/9320/

## 眠気対策に
PCとずっと向き合う、同じ姿勢でずっといる、集中力が必要、細かい字をみて目が疲れる等、眠気の原因となるものにたいして、私自身できそうだと思ったアクションを紹介します。
- 1時間集中、2、3分休憩
- 外の空気を吸う
- イチロー選手がよくやっていた「シコ」をする（検索するとでてきます）
- ブラックコーヒーを飲む
- とがったもので手をさす！？
- 目薬をさす
- 仮眠をとる
![0707.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777936/0274083e-d58b-bb21-bebc-726992ad2dc3.jpeg)

## 眠気云々の前に睡眠の質向上の為できる事
- 朝起きたら朝日をあびる
- 朝食を食べる
- 夕食やお風呂は寝る2-3時間前までに（遅い夕食は避ける）
- 適度な運動習慣化
- 寝る前にスマホの画面は見ない

だいぶ前になりますが、枕のオーダーメイドを一度利用したことがあります

https://www.lofty.co.jp/

枕が変わるだけでもぐっすり眠ることができ、翌日しゃきっとするのでなかなかおすすめです。他の枕オーダーメイドのお店もあるのでいいのがあれば紹介してほしいくらいです。

## 自分の身体を今一度見直してみよう
エンジニアに限らず、普段生活する中で眠気と上手に付き合うことで最高のパフォーマンスを発揮することができます。いろんな記事を読んで「そうなんだ」だけで終わらず、行動に移してみてはじめて効果は出ます。最低でも１か月は続けてみればあうあわないがわかるかと思います。
毎日を健康に過ごすために、この記事をきっかけに見直してみましょう。
Goでメール送信をやってみる

## コード

```go
package main

import (
	"fmt"
	"net/smtp"
)

func main() {
	// SMTPサーバーの設定
	smtpHost := "smtp.gmail.com"
	smtpPort := "587"
	smtpUser := "ここに自分のGmailアカウント名@gmail.com"
	smtpPass := "ここにSMTP送信用パスワード"

	// 送信者と受信者のメールアドレス
	from := "ここに自分のGmailアカウント名@gmail.com"
	to := "ここに自分のGmailアカウント名@gmail.com"

	// メールの件名と本文
	subject := "【TEST】件名が入ります"
	body := "本文です。"

	// メールのメッセージ
	message := []byte("To: " + to + "\n" + "Subject: " + subject + "\n\n" + body)

	// SMTP認証情報
	auth := smtp.PlainAuth("", smtpUser, smtpPass, smtpHost)

	// メール送信
	err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, []string{to}, message)
	if err != nil {
		fmt.Println("エラー:", err)
		return
	}

	fmt.Println("送信成功!")
}
```

## 動かしてみる

```zsh
go run main.go
```
```zsh
送信成功!
```

## 参考
- https://support.google.com/mail/answer/185833
- https://qiita.com/morima/items/58c51f7a35af2ed80050
【2024マラソン19】 Blender Lv0でも、Shapr3Dでモデリングして人型じゃないアバターを作れる Vol1

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/a15a1bcc-b464-94dc-9ba7-c62bb8992789.gif" width=300>

# 何これ？
言わずとわかる私の本体です。
「ぐら」と描きつつ、顔とハートをイメージしたつもりなんですが……伝わりますかね?

# 何の記事？
ノット人型のVRアバターを自作した話を書きます。

# 誰向け？ どんな役にたつ？
- 人型ではないアバターを自作したい人
- blenderでゼロから作るのが難しい人
- blender以外の3Dモデリングをしたい人

どんな手順で作ったんだろう?が気になる人向けですが、手順の詳細まではここでは触れていません。
詳細もどこかでまとめる予定ですが、この記事でアバター作成に興味が湧いた方は、参考リンクなどをみながらチャレンジしてみてください。

# あらすじ
アバター作成ツールを検索しても、概ね人型を作るツールしか見つかりませんでした。
その為、色々調べながら頑張って自作することにしました。

# 具体的に何を使ったか
### shaper 3D
ipadでスケッチから3Dモデルを作るのに使いました。
今回作ろうとしたアバターは、Blenderで既存の図形から変形するよりも、スケッチから立体に起こす方が簡単だったため、このアプリを使いました。

### blender
モデルに骨格を組み合わせて、動くアバターにするのに必要でした。
逆に言えば、3Dモデルをアバターとしてではなくオブジェクトとして使う場合はUnityのみで十分かもしれません。

### Unity
骨格をつけたアバターの大きさや1人称視点の際のポジションを設定し、VRMファイルに変換するのに使います。


# ざっくり手順
#### 1. Shapr3Dで3Dモデルを作る
作成後、FBXでエクスポートします。

#### 2. 作った3DモデルをBlenderにインポートし、アバターのボーンを作る
モデルをインポートし、骨格=ポーンを設定していきます。
#### 3. アバターの動き(ウェイト)を設定する
各パーツを動かしたときに、どこがどこに追従するかを設定します。
これを適当に設定すると、歩くたびに顔が歪むなど、ヤバめのアバターが誕生するので注意です。

下記は目の部分に足のウェイトがのっていたため、歩くたびにひどくなった例

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/b389774e-900e-edad-6f88-6b061c084341.gif" width=300>

#### 4. Unityにインポートし、VRMファイルにする
インポート後、1人称視点の原点や、アバターの大きさなどを変更します。

#### 5. Clusterにアップロードして動作を確認する
エクスポートしたVRMファイルを、cluster公式サイトからアップロードします。
アップロードが完了したら、早速ログインしてホームでアバターを確認してみましょう。

# 結果

どうみてもでかい怪物、爆誕。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/fc2f81e4-8047-f997-fb89-b91cb8501e63.png" width=300>

ただ作っただけでは、サイズやいろいろなものが合いませんでした。
ここで語ると長くなってしまうので、アップ後の微調整については別記事で解説をしていければと思います。

shaper 3Dは、スケッチした図面から厚みを持たせるような立体を作るのが得意な印象を受けました。
なので、スケッチから立体にしたい場合は、ここで3Dモデリングをしてみるのもいいかと思います。

逆に、丸や四角など、一般的な図形からアバターの形にしていこうと言う場合は、blenderで1から作り始めた方が作りやすそうな印象です。

# 参考
### Blenderでアバターを作る動画

https://youtube.com/playlist?list=PLh2HlgtpWBpVI3GyRF-vBi-mqtG4ARJgc&si=Cd5JeuHbYCkcrA2l

https://youtu.be/sH802t1AEcE?si=BDW8oY4-Rn1usbk4

BlenderからUnity->clusterの流れはこの動画を参考にしました。

### シェイパー3Dのやり方をまとめているサイト

https://3d-modely.com/blog/3d-software/shapr3d-table/

https://matagotch.hatenablog.com/entry/apps/shapr3d

基本的にはアプリ内の説明動画を見るとわかるのですが、細々したところはググって対応しました。

### clusterで使えるアバターの仕様

https://help.cluster.mu/hc/ja/articles/360029465811-カスタムアバターの制限