OmniAICreator/Qiita-1.07M huggingface dataset:
【Python入門】dictitonaryを使用した関数制御について

# はじめに
```dict```に関数を定義して、関数を呼び分ける方法について解説します。
一般的には処理を分けたい場合は分岐処理を行う必要がありますが、キーを使って処理を制御することができます。


# 一般的な関数呼び分け
関数を呼び分けたい場合、通常であればステータス毎や引数の値からどのような関数を呼び出すか判定を行い、制御する方法になるかと思います。

例えば四則演算を行う場合、引数で渡された関数名で分岐をするのが一般的かと思います。
```python
    def add(a, b):
        return a + b
    
    def sub(a, b):
        return a - b
    
    def mul(a, b):
        return a * b
    
    def div(a, b):
        return a / b
    

    if argv[1] == "add":
        print(add(int(argv[2]), int(argv[3])))
    elif argv[1] == "sub":
        print(sub(int(argv[2]), int(argv[3])))
    elif argv[1] == "mul":
        print(mul(int(argv[2]), int(argv[3])))
    elif argv[1] == "div":
        print(div(int(argv[2]), int(argv[3])))
    else:
        print("error")

```


# ```dict```を使用した関数呼び分け
```dict```のvalueに関数を定義することでdictから呼び出しが可能になります。
関数呼び出しの分岐処理をする必要がないため、見た目はすっきりします。

```python
    def add(a, b):
        return a + b
    
    def sub(a, b):
        return a - b
    
    def mul(a, b):
        return a * b
    
    def div(a, b):
        return a / b
    
    operations = {
        "add": add,
        "sub": sub,
        "mul": mul,
        "div": div
    }

    if argv[1] in operations:
        print(operations[argv[1]](int(argv[2]), int(argv[3])))
    else:
        print("error")

```


# まとめ
dictitonaryを使用した関数制御について解説しました。
```dict```に関数制御を行うのはいろいろと応用が利きますので、業務でも利用してみてください。
慣れない人が見るとが少し違和感を感じるかもしれませんが、すぐになれると思います。
MacOS 15 Sequoiaアップデート後のSSH接続問題の解決方法

MacOS 15 Sequoiaにアップデートした後、SSH接続ができなくなる問題が発生しました。SSHポートを別のポートに変更して使用していましたが、アップデート後にポート設定がデフォルトに戻ってしまったのではないかと思い、確認してみました。

```
ssh: connect to host port 00000: Connection refused
```

## /etc/sshd/sshd_configの修正

```
sudo vim /etc/ssh/sshd_config
```

確認してみると、デフォルト設定に初期化されていました。管理者権限でsshd_configファイルを開き、portの部分のコメントアウトを解除し、希望のポート番号に修正します。

sshディレクトリには、ssh_configとsshd_configの2つのファイルがあります。ssh_configは内部から外部への接続設定、sshd_configは外部から内部への接続設定です。

```
Port 00000 # 希望のポート番号に変更
PasswordAuthentication no # optional パスワード認証を無効にし、RSA鍵のみでのアクセスを強制
```

## /etc/servicesの修正

```
sudo vim /etc/services
```

ここでsshを探し、ポート番号を修正します。vimでsshという文字列を検索したい場合は、/sshと入力します。

```
# ssh 22/udp
# ssh 22/tcp
ssh 00000/udp
ssh 00000/tcp
```

## SSHポート変更の適用

```
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
# または
sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd
```

## SSH接続

sshコマンドで直接アクセスするか、~/.ssh/configファイルの設定をしてSSH接続します。

```
ssh (username)@(hostname) -p 00000
```

または

```
Host hostname
    HostName XXX.XXX.XXX.XXX
    User username
    Port 00000
    IdentityFile ~/.ssh/XXXXXXX.pem
```

以上の手順で、MacOS 15 Sequoiaアップデート後のSSH接続問題を解決することができます。ポート設定が初期化されている可能性があるため、必ず確認と再設定を行ってください。
pandas: PostgreSQL のテーブルの重複を削除

Primary Key を設定しないテーブルでは、データが重複する可能性があります。
その重複を削除するプログラムです。

## 実行前

```text
  id   |  name  | population |  date_mod  
-------+--------+------------+------------
 t3461 | 広島   |      72814 | 2001-09-14
 t3461 | 広島   |      72814 | 2001-09-14
 t3462 | 福山   |      41738 | 2001-07-21
 t3462 | 福山   |      41738 | 2001-07-21
 t3463 | 東広島 |      92513 | 2001-06-12
 t3463 | 東広島 |      92513 | 2001-06-12
 t3464 | 呉     |      93167 | 2001-09-29
 t3464 | 呉     |      93167 | 2001-09-29
(8 rows)
```

## 実行後

```text
  id   |  name  | population |  date_mod  
-------+--------+------------+------------
 t3461 | 広島   |      72814 | 2001-09-14
 t3462 | 福山   |      41738 | 2001-07-21
 t3463 | 東広島 |      92513 | 2001-06-12
 t3464 | 呉     |      93167 | 2001-09-29
(4 rows)
```

## プログラム

```py:db_duplicate_omit.py
#! /usr/bin/python
#
#	postgresql/pandas/db_duplicate_omit.py
#
#						Sep/16/2024
# ------------------------------------------------------------------
import pandas as pd
import sys
import os
from dotenv import load_dotenv
from sqlalchemy import create_engine
from sqlalchemy import text as q_text
#
# ------------------------------------------------------------------
def single_proc(engine,schema,table_src):
	sys.stderr.write("*** single_proc *** start\n")
	sql_str = 'SELECT * FROM ' + schema + "." + table_src
	print(sql_str)
	q = q_text(sql_str)
	try:
#
		df=pd.read_sql(sql=q, con=engine.connect())
		print(df)
		print(df.shape)
		dg = df.drop_duplicates()
		print(dg.shape)
#
		dg.to_sql(name=table_src,con=engine,schema=schema,if_exists='replace', index=False)
#
	except Exception as ee:
		sys.stderr.write("*** error *** in read_sql_query ***\n")
		sys.stderr.write(str(ee) + "\n")
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")

dotenv_path = '.env'
load_dotenv(dotenv_path)
user=os.environ.get("user")
password=os.environ.get("password")
data_base=os.environ.get("data_base")

host ='localhost'

SQLALCHEMY_DATABASE_URL = "postgresql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(SQLALCHEMY_DATABASE_URL)
#
#
schema="public"
table_src = "cities"
#
single_proc(engine,schema,table_src)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

```text:.env
user='scott'
password='tiger123'
data_base='city'
```

## SQL

テーブルの作成

```text:postgre_create.sql
drop table if exists cities;
create table cities (id varchar(10), name text, population int, date_mod date);
```

データの挿入

```text:postgre_insert.sql
insert into cities values ('t3461','広島',72814,'2001-9-14');
insert into cities values ('t3462','福山',41738,'2001-7-21');
insert into cities values ('t3463','東広島',92513,'2001-6-12');
insert into cities values ('t3464','呉',93167,'2001-9-29');
```

データの読み込み

```text:postgre_read.sql
select * from cities order by id;
```
Kubernetesことはじめ

# kubernetesことはじめ

対象読者はこんな方です。
対象読者：dockerは使ったことがある人で初めてkubernetesをいじる人
dockerの延長でkubernetesをいじりはじめた人向けのチュートリアル実行メモです。チュートリアルではpodをyamlファイルで作成しています。後半は自分で作ったcontainerからpodを作り、同じことができるかを試し、kubernetesの特徴を知るきっかけになれれば幸いです。

まずは、dockerコンテナ（pod）を作ってkubenetesを使って中に入ってみる

参考
https://kubernetes.io/ja/docs/tasks/debug/debug-application/get-shell-running-container/

# minicube起動

```
% minikube start
```

```
% minikube status 
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
```

## pod作成

podはdocker containerの集合です。containerを作成するのと同じです。

```
vi shell-demo.yaml
```

iamgeは`nginx`を使用します。

shell-demo.yaml
```
apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
```

次のコマンドでpodを作成します。
```
kubectl apply -f https://k8s.io/examples/application/shell-demo.yaml
```

作成したら中身を見てみます。
```
kubectl get pod shell-demo
```

`STATUS`を見ると実行中になっているのがわかります。
```
NAME         READY   STATUS    RESTARTS   AGE
shell-demo   1/1     Running   0          25s
```

## podの中に入る

pod名を指定して、中に入ります。`--`はこれ以降の引数がpodに渡すコマンドであることを示す区切りです。
`docker exec -it [container id] /bin/bash`でcontainerの中に入るのと同じ意味です。

```
% kubectl exec --stdin --tty shell-demo -- /bin/bash
```

## shellファイルをpod内に作成

中に入ってshellファイルを作ります

```
root@minikube:/# touch hellokitty.sh     
root@minikube:/# echo '#!/bin/bash' > hellokitty.sh 
root@minikube:/# echo "echo 'hello kitty'" >> hellokitty.sh
```

```
root@minikube:/# cat hellokitty.sh 
#!/bin/bash
echo 'hello kitty'
```
## pod上でbashをインストール
bashをインストールします
```
root@minikube:/# apt install bash
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
bash is already the newest version (5.2.15-2+b7).
bash set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
```

## pod上でbashを実行

インストールしたbashを使用して実行します。
```
root@minikube:/# bash -xe hellokitty.sh 
+ echo 'hello kitty'
hello kitty
```

実行権限を付与します。
```
root@minikube:/# chmod 755 hellokitty.sh 
```

## ホストマシンからpodのbashを実行
先ほどはpod名を指定して、podの中に入ってshellファイルを実行しました。
ホストマシンからpodを指定して直接実行してみます。
```
% kubectl exec shell-demo -- /bin/bash hellokitty.sh  
hello kitty
```

無事表示されました。成功です！

# docker containerをもとにpod作成

docker containerを使って同じことをしてみます。

```
docker pull ubuntu:24.04
```

container名を`pompompurin`にして、上記でダウンロードしたイメージ`ubuntu:24.04`にcontainerを作成します。
```
docker container create -it --name pompompurin ubuntu:24.04
```

containerからpodを作成します。
```
kubectl run pompompurin --image=ubuntu:20.04 --restart=Never
```

podリストを見るといます。
```
% kubectl get pod                                   
NAME          READY   STATUS      RESTARTS   AGE
shell-demo    1/1     Running     0          29m
pompompurin   0/1     Completed   0          50m
```

Pod内でプロセスが起動しているものは`Running`になります。`STATUS`が`Running`ではないPodにはアクセスができないようです。
試しに入ろうとすると次のようなエラーメッセージが出力されます。

```
% kubectl exec --stdin --tty pompompurin -- /bin/bash
error: cannot exec into a container in a completed pod; current phase is Succeeded
```
個の力が欲しいか？

# 今一度問いたい。個の力、本当に大事か？

AIの発展、フリーランス新法、芸能人の事務所独立…。  
これからの時代、「個の力」は本当に重要なのか、個の力とはなんなのかを改めて考えてみたい。

## はじめに

:::note warn
この記事は、あくまで個人の見解です。
書き殴りなのでまとまりがないです。
:::

## きっかけ

### 本田圭佑選手の言葉が私に与えた影響

2014年W杯ブラジル大会出場を決めた本田圭佑選手の名言が、私のエンジニア人生に大きな影響を与えました。
「シンプルに言えば個。最後は個で試合を決することがほとんどなので！」  
この言葉は、新米エンジニアだった私にとって、能力主義を意識するきっかけとなりました。

エンジニアの世界でも、最終的には「個の力」がプロジェクトの成否を左右します。これが私のキャリアの原点です。

## エンジニア人生を振り返る

私がこれまで歩んできたエンジニアとしての道を振り返ると、節目ごとに「個の力」が試され、その限界にも直面してきました。以下に、その経験と教訓を振り返ります。

- **IT系専門学校**  
  IT全般を学び、基本情報技術者試験に合格。しかし、ここで学んだのは基礎的な知識であり、実務に直結するスキルではありませんでした。**技術スキルは現場で磨かれる**という現実を突きつけられました。

- **中小SES企業でのキャリアスタート**  
  大手ベンダーの一次受け案件で、基本設計から総合テストまで幅広い業務を経験しました。2年目にはエンドユーザーとの設計レビューや仕様調整も担当し、早い段階で責任ある仕事を任されました。しかし、**コーディングスキルは依然として低く、「何でもできる」と勘違いしていた**ことに後から気づきました。

- **スタートアップSES企業での成長と限界**  
  1人目の社員として参画し、エンドユーザーとの調整を通じて仕様整理や設計工程に自信を持つようになりました。しかし、コーディングスキルは未熟なままで、**業務知識や設計力を重視するあまり、実力と自信のバランスを見失っていた**のです。この経験を通じて、**過信が実力不足を隠す危険性**を実感しました。

- **一部上場SES企業でのマネジメント経験**  
  転職後、大規模な炎上プロジェクトのリーダーを任され、すぐにマネージャーに昇格。さまざまなプロジェクトに参画し、最終的には部長候補にまで昇進しましたが、あと一歩で部長というところでキャリアは終わりました。ここで直面したのが、**能力の低いメンバーをマネジメントする難しさ**でした。「個の力」に頼りすぎた結果、すべてを抱え込んでしまい、ストレスが蓄積。最終的に2度の休職を余儀なくされました。この経験から、**「個の力」だけではなく、チームとの協力がいかに重要か**を痛感しました。また、自身がマネジメント業務に適していないことにも気づかされました。

これらの経験を経て、私は「個の力」を重視しながらも、その限界を痛感しました。苦手なマネジメント業務から離れ、他者に頼らず、自分の力で勝負できるフリーランスという道を選んだのです。

## フリーランスという選択

会社の方針に縛られることなく、自分の力で結果を出す――フリーランスはまさに「個の力」を重視し、自分の責任で仕事に挑む選択です。

Web系自社開発企業のプロジェクトに参画した際、最初はコーディングスキルの低さに苦しみましたが、半年後にはスキルが向上し、周囲と肩を並べるレベルに達しました。今では、アプリ基盤の開発や業務ロジック以外の設計、フレームワーク構築を担当し、メインの業務ロジックも手掛けています。チームメンバーのコードレビューや方針決定にもリーダーシップを発揮し、全体の技術品質向上にも貢献しています。

しかし、再び問題が発生しました。**メンバー間のスキル差やコミュニケーションの難しさ**により、再び「個の力」と向き合うことになったのです。

## 振り返ってみて

フリーランスになっても、マネジメントの悩みから完全に解放されたわけではありません。特に、自走力のないメンバーをフォローすることが課題でした。この経験を通じて、私は改めて、**自走力が「個の力」を強化する**ことを実感しました。自走力とは、単なる技術力やスキルではなく、**主体的に動き、自ら問題を解決していく能力**を指します。

本田圭佑選手も「日本の最大の強みはチームワークだ。しかし、それは生まれ持った能力であり、そこからいかに自立し、個を高めるかが重要だ」と語っています。つまり、**チームワークは基盤として不可欠**であり、その上に立つ個々の力がチーム全体をさらに強くするのです。チームワークに依存し、他人の力ばかりを頼るエンジニアよりも、主体的に行動し、チームに貢献できるエンジニアこそが真に「個の力」を強めていけるのです。

チーム内で協力関係が成立するのは、各メンバーが自走力を持っているからこそです。自ら動けるメンバー同士が集まることで、不協和音が生じることなく、自然と協力し合える環境が生まれます。一方で、**自走力が欠如していれば、他人の助けを求め続けることで、チーム全体のパフォーマンスが低下**してしまいます。

まずは、各メンバーが自律的に動ける自走力を育て、その上で強固な協力関係を築くことが、チーム全体の力を引き出す鍵だと考えています。

## まとめ：自走力が強化する本当の「個の力」

最も重要なのは、**「個の力」の根底にある自走力**です。技術力や知識だけでは「個の力」とは言えません。主体的に動き、問題解決に取り組む力こそが真の「個の力」を強化します。自走力があって初めて、エンジニアとしての「個の力」が発揮され、成長し続けることができるのです。

本田圭佑選手の言葉にもあるように、**「チームワーク」は生まれ持った強みかもしれませんが、それに依存していては成長はありません**。自走力を持ち、自己を高めることで、真の「個の力」が発揮され、チーム全体が強くなるのです。

自走力を持ったメンバーが集まることで、自然と協力関係が生まれ、不協和音なく最大のパフォーマンスを発揮できるチームが期待できます。「個の力」とは、チームを支え、同時にチームによって磨かれるものでもあります。

私は今後も、個の力を追求しつつ、自律的に動けるエンジニアとして、またその力を持つチームを作り、より高いパフォーマンスを実現していきたいと考えています。**未来を切り開くのは、**自走力に裏打ちされた**「個の力」であり、その力こそが、エンジニアとしての成長と成功を支えると信じています
opennssl csr作成

## はじめに
SSL証明書を手にいれる過程でCSRを作成する必要があります。
通常はopensslで作成されることが多いですが、その際のコマンドを備忘録として残します。

## 前提
OpenSSL version: 3.3.1 4 Jun 2024

## 2種類の方法
opensslを利用してCSRを生成する手順は2通りあります。

1. 秘密鍵の生成とCSRの生成を1度に行う (一括生成)
2. 秘密鍵の生成とCSRの作成を分けて行う (段階生成)

前者は手順が簡略化され、後者はより柔軟な設定が可能とのことです。
当記事では手順1を紹介します。

## 一括生成
秘密鍵, CSRを生成 ※ 公開鍵はCSRの中に含まれています。
```shell
$ openssl req -newkey rsa:2048 -nodes -keyout <file名>.key -out <file名>.csr
```

```
req: X.509証明書署名要求（CSR）を行うための引数
-newKey: 新しい秘密鍵とCSRを生成する
-nodes: 秘密鍵を暗号化しない設定 ※ これによりサーバーを起動する際にパスフレーズを手動で入力する手間がなくなる
-keyout: 秘密鍵のファイル名
-out: CSRのファイル名
```

必要な作業はここまでで完了です

---

以下は知ってると便利なコマンドです

## CSRの内容を確認
```shell
$ openssl req -text -noout -in <PATH_TO_CSR_FILE>

# Subjectの部分を確認する
$ penssl req -text -noout -in <PATH_TO_CSR_FILE> | grep Subject
```

## 秘密鍵が暗号化されていないか確認する
暗号化されていない場合、"RSA key ok"と表示されます
```shell
openssl rsa -in <PATH_TO_SECRET_KEY> -check -noout
```

## 秘密鍵とCSRの対称性を確認
CSRが任意の秘密鍵から生成されたものかを確認します
これには両者のModuleが同一かどうかで判断可能です
```shell
diff <(openssl rsa -noout -modulus -in "PATH_TO_SECRET" | openssl md5) <(openssl req -noout -modulus -in "PATH_TO_CSR" | openssl md5)
```
mysql系でUUIDを処理するための戦略

# MySQLでUUIDをPrimary Keyとして使用する際の問題と解決方法

## 1. UUIDをPKとして使用した場合の問題

- **UUIDの特性**: UUIDは時間とランダム性に基づいて生成されるため、無作為に分布します。このため、インデックス構造上、データがB-Treeに挿入される際に、データがソートされる必要があり、多くのディスクI/Oが発生します。
  
  - **ディスクI/Oの非効率性**: MySQLでは、PKは基本的にクラスター化インデックスを使用するため、データ挿入時にソートが維持される必要があります。UUIDの無作為性が、クラスター化インデックスの効率を低下させます。その結果、挿入パフォーマンスが低下し、ディスクI/Oのコストが増加します。

  - **パフォーマンス問題**: UUIDをPKとして使用した場合、ディスクI/Oの増加によりパフォーマンスが大幅に低下し、挿入速度が遅くなり、テーブルサイズが不必要に大きくなります。

![UUIDパフォーマンス問題図](https://planetscale.com/_next/image?url=%2Fassets%2Fblog%2Fcontent%2Fthe-problem-with-using-a-uuid-primary-key-in-mysql%2Fuuid-v6-diagram.png&w=2048&q=75)

![UUIDパフォーマンス比較表](https://files.programster.org/tutorials/mysql/uuid-performance/01.png)

## 2. UUIDをPKとして使用しない解決方法

UUIDの一意性を保ちながら挿入パフォーマンスを向上させるための解決策は、**自動増加するBIGINTタイプのPK**を使用することです。

### 修正されたテーブル構造の例

```sql
CREATE TABLE `users` (
    `pk` BIGINT NOT NULL AUTO_INCREMENT,
    `uuid` BINARY(16) NOT NULL,
    `name` VARCHAR(20) NOT NULL COLLATE 'utf8mb4_general_ci',
    `email` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
    `password` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_bin',
    `is_delete` TINYINT(1) NOT NULL,
    `create_data_at` TIMESTAMP NOT NULL,
    `update_data_at` TIMESTAMP NOT NULL,
    PRIMARY KEY (`pk`) USING BTREE,
    INDEX `uuid` (`uuid`) USING BTREE,
    INDEX `idx_users_name` (`name`) USING BTREE
)
COMMENT='users'
COLLATE='utf8mb4_bin'
ENGINE=InnoDB;

```

- PKとしてBIGINTを使用: 自動増加するBIGINTをPKとして使用し、データ挿入時のソートを容易にします。
- UUIDは補助インデックスとして使用: UUIDフィールドは補助インデックスとして使用され、データの検索や関係性を保つために使用されます。
この方法により、挿入パフォーマンスを改善しながらUUIDの一意性を保つことができます。

## 3. KotlinでのUUID処理

KotlinでUUIDを簡単に使用できるようにした例は以下の通りです。

```@MappedSuperclass
@EntityListeners(AuditingEntityListener::class)
abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    var uuid: UUID? = null

    @Column(name = "create_data_at", updatable = false)
    @CreatedDate
    lateinit var createdAt: Instant
        protected set

    @LastModifiedDate
    @Column(name = "update_data_at")
    lateinit var updatedAt: Instant
        protected set

    @Column(name = "is_delete")
    var isDelete: Boolean = false
}

@Entity(name = "users")
class UsersEntity(
    @Column
    var name: String = "",

    @Column
    var email: String = "",

    @Column
    var password: String = ""
): BaseEntity()
```

**BaseEntity**クラスではUUIDを使用し、UsersEntityクラスはこのクラスを継承して、作成日時、更新日時、削除フラグを管理します。
これにより、プログラム上でUUIDを簡単に扱える環境が提供されます。
SSHでgit cloneをする方法

# はじめに
こんにちは。ponponnsanです。最近遊びすぎると翌日に響くことが増えてきました。今年から考え始めたジムにそろそろ行く時がきたのか...

今回は、ssh接続でgit cloneする方法を紹介します。

# 経緯
githubのhttpsでのcloneが一般的ですが、社内サーバーだと個人アカウントでgit loginする必要があります。それだと他の人がcloneできないので、sshで接続してcloneさせようという試みです。

# 手順
1. .ssh/configファイルを作成
1. 公開鍵と秘密鍵を作成する
1. githubに公開鍵を登録する
1. ~/.ssh/configの設定をする
1. sshでgit cloneする

それぞれの手順を追って見ていきましょう。

### .ssh/configファイルを作成
最初に.ssh/configというファイルを作成していきます。
configはssh接続の設定を保存するファイルです。大体はホームディレクトリに.sshというファイルを作成し、その下にファイルを作成して行きます。

ファイルがある場合はこの手順を飛ばしても大丈夫です。
作成してあるかどうかは以下のコマンドで確認してください。

```bash
# configファイルがあるかどうかを確認
cat ~/.ssh/config

# .sshファイルを作成
mkdir -p ~/.ssh
chmod 700 ~/.ssh
```

`mkdir -p ~/.ssh`
`mkdir`: ディレクトリを作成するコマンド
`-p`: 親ディレクトリが存在しない場合は作成する
`~/.ssh`: ホームディレクトリ直下に.sshディレクトリを作成

`chmod 700 ~/.ssh`
`chmod`: ファイルやディレクトリの権限を変更するコマンド
`700`: 所有者にのみ読み取り、書き込み、実行の権限を与える

`700`のパーミッションの内訳を表で示します:

| 所有者 (User) | グループ (Group) | その他 (Others) |
|---------------|------------------|-----------------|
| 7 (rwx)       | 0 (---)          | 0 (---)         |

この表の詳細説明:

- 所有者 (7):
  - r (読み取り): 4
  - w (書き込み): 2
  - x (実行): 1
  - 合計: 4 + 2 + 1 = 7

- グループ (0):
  - すべての権限なし

- その他 (0):
  - すべての権限なし

700のパーミッションでは、ファイルやディレクトリの所有者にのみフルアクセス権（読み取り、書き込み、実行）が与えられ、グループメンバーやその他のユーザーにはアクセス権が一切与えられません。このパーミッション設定は、セキュリティが重要な場合や、特定のユーザーのみがアクセスできるようにしたい場合に使用されます。

### 公開鍵と秘密鍵を作成する

`ssh-keygen -t ed25519`で鍵を生成します。
するとfile_nameは何にするか、パスワードは何にするか聞かれます。

:::note info
- ファイルの名前は混同しないように変えておくと便利
- passphraseは空(Enter押すだけ)でもいい
:::

```bash
ssh-keygen -t ed25519

Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa): file_name
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
```

` ls -al ~/.ssh`でちゃんと~/.ssh配下にあることを確認します。
```bash
ls -al ~/.ssh

-rw------- 1 user user  411 May 12 15:09 file_name
-rw-r--r-- 1 user user   96 May 12 15:09 file_name.pub
```


### githubに公開鍵を登録する

:::note warn
別リポジトリと同じデプロイキーは「Key is already in use」となり使えません。
:::

登録したいリポジトリの Settings > Deploy keys > Add deploy key から
公開鍵`file_name.pub`を登録します。

![スクリーンショット 2024-04-12 15.23.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/8b2da0b8-32f6-b81e-ae2c-298d9c250a0c.png)


### ~/.ssh/configの設定をする
configファイルに鍵の設定をします。

```config
Host github.com
  User git
  HostName github.com
  IdentityFile ~/.ssh/file_name
  IdentitiesOnly yes
```

:::note info
デフォルトは`git@github.com:user/project.git`なのですが、
configのUser,Hostを変更を変えると、git cloneをするURLも変わります。
:::

```
# デフォルト
git clone git@github.com:gituser/project.git

# configのUser,Hostを変更した場合
git clone [User]@[Host]:[リポジトリアドレス]

```

# 参考文献
https://qiita.com/ponponnsan/items/e983126f3e912a973f33

https://qiita.com/tamorieeeen/items/c24f8285448b607b12dd

https://qiita.com/kawahara_hiroyuki/items/3ad35c548d1007c12109
pnpmというパッケージマネージャーについて

## 初めに
現在、Next.js(TypeScript)でclient側のアプリ開発をしています。
私は今までnpmというパッケージマネージャーを利用していたのですが、今回pnpmという存在を知ったのでそれぞれの違いをまとめてみました。
あくまで初心者の見解ですので、もし間違っていたら指摘していただけると幸いです。
## パッケージマネージャーとは
パッケージマネージャーとは、ソフトウェアのインストール、更新、削除、依存関係の管理などを行うことのできるツールであり、開発者がソフトウェアパッケージを効率的に管理し、特定のバージョンや依存関係を確保するのに役立ちます。

#### 代表的なパッケージマネージャー
以下のものが挙げられます。(他にもたくさんあります。)

・npm : Node.jsのパッケージを管理する。
・pip : Pythonのパッケージを管理する。
・Homebrew : macOS用のパッケージマネージャー。

#### 主な機能
1. インストール
必要なソフトウェアパッケージを簡単にインストールできる。
2. アップデート
インストールされているパッケージを最新バージョンに更新できる。
3. アンインストール
パッケージを削除できる。
4. 依存関係の管理
パッケージが他のパッケージに依存している場合、適切なバージョンを自動でインストールし、依存関係を解決する。
5. リポジトリの管理
ソフトウェアパッケージのリポジトリ(ソース)を管理し、複数のリポジトリからパッケージを取得することができる。

## npm vs pnpm
どちらもNode.jsのパッケージマネージャーですが、いくつかの違いがあります。
#### 主な違い
1. ディスク使用量とインストール速度
・npmは各プロジェクトのnode_modulesフォルダーに直接パッケージをインストールします。これによって、同じパッケージが複数回インストールされ、ディスク使用量が増加する可能性があります。
・pnpmは、パッケージをグローバルストアに保存し、各プロジェクトにシンボリックリンクを作成します。これによって、同じパッケージをインストールすることはなくなり、ディスク使用量を節約することができます。また、この方法によりインストール速度も高速化されます。

2. 依存関係の解決
・npmは依存関係をフラットにインストールしてしまうため、依存関係の競合を発生させる可能性があります。
・一方、pnpmはストリクトな依存関係を行います。各プロジェクトのnode_modulesフォルダにシンボリックリンクを使用して依存関係を配置するため、依存関係の競合やバージョンの不一致が発生しにくくなっています。
3. ワークスペースのサポート
・pnpmはモノレポ(単一のリポジトリに複数のプロジェクトを含む構成)を強力にサポートしています。ワークスペース機能を使用して、複数のパッケージ間で依存関係を簡単に管理することができます。
4. パフォーマンス
・npmは小規模なプロジェクトでは十分なパフォーマンスを発揮しますが、大規模なプロジェクトでは速度や効率の面がネックになってしまいます。
・pnpmは大規模なプロジェクトやモノレポで特に優れたパフォーマンスを発揮することができます。インストールやアップデートの速度が非常に早く、ディスク使用量も効率的です。

:::note warn
注意
多くの場合、npmでインストール可能なパッケージはpnpmでもインストールできるが、特定のパッケージやプロジェクトの設定によっては、できない場合があります。また、一部のビルドスクリプトやツールは、node_modulesのフラットな構造を前提としているため、pnpmのシンボリック方式では動作しないことがあります。
:::

#### インストール
```bash
npm install
pnpm install
```
#### パッケージの追加
```bash
npm install
pnpm add
```
#### スクリプトの実行
```bash
npm run
pnpm run
```
:::note info
コマンドの実行方法は多少違う部分がありますが、開発方法やコードの記述自体に大きな違いはありません。つまり、違いはパッケージの管理や依存関係の解決におけるパフォーマンスと効率的かという点です。
:::

## まとめ
pnpmは、高速で効率的なパッケージマネージャーである。
高速なインストール・効率的なディスク使用・依存関係の管理・モノレポのサポートという点において非常に特化しています。
大規模な開発をする際にはパッケージマネージャをpnpmにして、小規模な開発ではnpmを利用して使い分けるとそれぞれのメリットを享受することができると思いました。
私自身、今までnpmしか使ってこなかったのでこれからpnpmも視野に入れていきたいです。
褒めて褒めて褒めまくってもらえるプロンプトを公開！　OpenAPIを使ってLINE Botを動かす

# ちょこっと業務を簡略化したい


　この記事では、ちょこっと効率化させたいことをプログラミングやツールをつかって解決していきます
ちょこっと削減した時間を、もっと人生楽しくなることに使いましょう！
今回は、ちょっとコンセプトを変えています

# 本日のお題

　「社会的孤立」
 １人ではない、友人や、家族はいる　でも本音や不満をうまく話すことができない。これが社会の課題だといわれいています。
 どこか心の中で、他人に話したところで解決してくれない　話すことをやめていないでしょうか。　孤立‥
 「他人に、モヤモヤを言語化して伝える」簡単なことではあるが意外と難しい。だって、聞かされた相手の気持ちも考えてしまうから。



今回作りました。「何を言っても褒めてくれる、慰めてくれる、自己肯定感上げてくれるLINE Bot」

 

## LINE Bot × OpenAPI

こちらの記事を参考にしています。↓

https://qiita.com/yutowac/items/102d119ab583a8ab930c

以下が、褒めてもらうためのプロンプトです。

```
## あなたは、日本人でとても褒めるのが上手いプロです。
## マイナスな言葉や弱音を感じるような言葉、相手を皮肉する言葉は禁止です。
## どんなに弱音を言われたとしても、相手がやる気をやる気にさせるような言葉を言ってあげてください。
## 応答の冒頭は、「打ち明けてくれて、ありがとう」と言ってください。
## 上辺だけの励ましの言葉はいりません。相談に乗ってあげるような根拠のある著名人の言葉を言ってあげてください。
## メンタルが弱っていそうな時は、寄り添う言葉をかけてください。
```

## 😡実装例😡

💢😡① 生理がくる人にならわかること気持ち。とってもむかついているが何にむかついているのか自分でもわからないから対処できない。　それで単発的に他人へこのイライラをぶつけるのもおかしいし、この世で一番落ち込んでいるのではないかと思うそんな日にくれたお言葉。
　
![スクリーンショット 2024-09-16 13.02.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/cf7114a4-aad3-4a63-f890-40290a902366.png)
　
　
　
  　
💢😡② 1年に数回、息をしているだけで何もかもついてない日ありませんか？
ほんの些細なことが気になっちゃう。そんな日にくれたお言葉。
　
![スクリーンショット 2024-09-16 13.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/62bb949b-5b6b-5627-1b1b-cb1b8687c332.png)
　
　
　

💢😡③ とても大好きでラブラブなカップルでも、この問題は起こりますよね。今回は同棲中の彼女→彼氏で考えましたが、彼氏→彼女でも同じです。　結婚前に価値観を合わせておきたいところですね。悩みを相談しずらい回答にも答えてくれた。
　
![スクリーンショット 2024-09-16 13.23.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/2339bc24-bd9e-5482-50fd-1e87b89a5fc2.png)



# 🧡最後に

ストレスのない社会はないのでうまく付き合っていくしかないですね
でも少しでもあなたの気持ちが晴れること願っています✨🌞
これを使って、あなたの悩みでどう返答がきたか教えてほしいです！

今後、このようにちょっとした効率化のための情報を載せます。あなたの業務でも役立つこと願っています💓
GitHubのアカウント別にコミットアカウントを切り替えてpushする設定

特定の用途にGitHubアカウントを分けたものの
コミッターが元のGitHubアカウントのcommitterのままpushされてしまい困ったので、
GitHubアカウント別にそれぞれのアカウントでcommitしてpushしたい。
<font color='lime'>ディレクトリ毎に自動でGithubアカウントを切り替え設定してcommit＆pushできる方法。</font>
意外に面倒だったのでやり方メモ


# sshの設定
２つのgithubアカウントのため、sshを別々に用意します
ssh秘密鍵公開鍵キーペアを払い出ししている前提とします。

```
$ cd ~/.ssh
$ ssh-keygen
```

`./ssh/config`を編集します。

```ssh
ServerAliveInterval 30000
TCPKeepAlive yes

Host github
  HostName github.com
  IdentityFile ~/.ssh/id_rsa_github
  User git
  IdentitiesOnly yes

Host sub.github
  HostName github.com
  IdentityFile ~/.ssh/id_rsa_sub_github
  User git
  IdentitiesOnly yes
```

Hostのエイリアスを変えてサブアカウントのものを作成します。
（HostNameは同じ）
IdentityFileはssh秘密鍵を指定します。


# 切り替え用の.gitconfigを用意

サブアカウント用に`~/.gitconfig_sub`を作成します。
urlにはサブGithubアカウントを指定し、
push時のssh認証をサブアカウントのもので行う。

```
[user]
	email = sub@gmail.com
	name = sub
[url "ssh://sub.github/"]
	insteadOf = git@github.com:
 ```

特定のディレクトリのみ、
（今回は`~/Desktop/sub/`で切り替える想定）
サブGithubアカウントの`~/.gitconfig`の設定を適用します
（この例だと、`~/Desktop/sub`にサブGithubアカウントのリポジトリをクローンしている想定）

```
[user]
 email = main@gmail.com
 name = main

[includeIf "gitdir:~/Desktop/sub/"]
 path = ~/.gitconfig_sub
 ```

 # 動作確認
`~/Desktop/sub/`にて
`github config user.name`と`ssh -T (Host)`で
GitHubアカウントが切り替わっているか確認
 

 ```
 $ git config user.name
 main
$ ssh -T github
Hi (メインGitHubのアカウント名)! You've successfully authenticated, but GitHub does not provide she
ll access.

 $ cd ~/Desktop/sub
 $ git config user.name
 sub
 $ ssh -T sub.github
Hi (サブGitHubのアカウント名)! You've successfully authenticated, but GitHub does not provide shell
 access.
 ```
ターミナル上でディレクトリ構造を視覚的に確認する方法

```bash
# パッケージリストを最新の状態に更新
sudo apt update

# tree コマンドをインストール
sudo apt install tree

# tree コマンドを実行して、ディレクトリ構造を表示
tree
```
**参考**

https://askubuntu.com/questions/1147854/install-latest-version-of-tree-command

https://qiita.com/wildmouse/items/4821ff338dd80d3c3881
[学習ログ]フレックスボックスを学んでflex-directionの大事さに気づいた

# はじめに

フレックスボックスが良くわかってなかったので調べてみた。
MDNにちゃんと書かれていたのでちょっと意味わかった。
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox

# flex-directionは主軸と交差軸を決めるもの

flex-directionでrowやcolumnを選べるが、これは「主軸と交差軸をどうするか」で考えるのが大事だと理解した。

以下のようなコードを書き、入力フォームをフレックスボックスを使い、主軸を垂直方向にし、align-itemsで交差軸を真ん中寄せにすることで、全体を真ん中寄せにした。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="mdZYLxG" data-pen-title="Untitled" data-user="syo-tokeshi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/syo-tokeshi/pen/mdZYLxG">
  Untitled</a> by syo-tokeshi (<a href="https://codepen.io/syo-tokeshi">@syo-tokeshi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# まとめ

最初に全体のレイアウトを決め、UIをどのような配置にするか決める時にフレックスボックスで上手く取り扱えるようにdivなどのブロック要素で部品を囲むのが大事だと分かった(htmlの仕様に則るなら、もっと正しいタグで囲むべきだが)

部品をグルーピング化することで、全体を上手く操作することができる。

全体を操作するには
- フレックスボックスを使い、子要素を設定する
- フレックスボックスを使わず、親要素にスタイルを当てて子要素に[継承](https://beginners-hp.com/create_css_inherit.html)させて設定する

方法がある。

なるべく単純化した方が良いと思うので、なるべくはフレックスボックスを使って全体を上手くコントロールし、それでは対処できない系は、親要素を操作して子をコントロールする感覚が良さそう。

# 学習する前とした後の変化

学習する前はノリでcssを書いてて、上手くスタイリングできずに困っていた。
それは当然で、cssには

- ブロック or インライン要素
- ボックスモデル
- フレックスボックス

などの概念があり、それを理解してないと配置すらままならないからである。
個人開発レベルだと、SEOを意識しなければ、HTMLのタグ付けは曖昧で良いと思うけど、cssは出来なきゃそもそも見た目が変でまともなアプリが作れない。

cssフレームワークを使えば部品はある程度まともなものが簡単に作れるが、配置は自力でやるしかない。
最初はTailwind CSSを使おうとしたが、cssを知らない人間が適当に使っても混乱を生みそうな気がして、cssから学ぼうと思った。

# 今後の学習方針

遊びと作品作りの両方を利用しながら、地道に学んで行こうと思う。
教科書や動画でふむふむしながら学んでも、いざ作ろうとした時に自分の思い描いたスタイリングができない問題が発生するので、手を動かさないといけないのは分かった。

なので、手を動かす動機付けを自分に課すのが大事な気がする。

また、「概念を知っている」という状態さえ作っておけば、困った時にググれば良いだけ、という状態になりそうなので、なるべく全体像は把握したいと思った。

ただ、ここに関してはそこまで身構えなくても良い気がしている。
「progateをちゃんと理解していればWEB制作の案件を実際にやってみる」という方法で上手くいっている人達を何人か聞いたので、めっちゃ細かいチップス知らなくても、大まかなスタイリング出来るだけでもある程度何とかなるのかな？と思ってる
【Rails】delete_allでエラーが発生する

## はじめに
Railsのアップデート中にdelete_allを使用している箇所でエラーが出たので、その対応をまとめます。

## 問題
コード
```ruby
User.delete_all(company_id: company.id)
```

エラー文
```ruby
wrong number of arguments (given 1, expected 0)
```

## 解決方法
Rails7では、delete_allに引数を取れなくなっているので、whereを使用するように修正します。
```ruby
User.where(company_id: company.id).delete_all
```

## 参考
https://qiita.com/migaruna_debu/items/ad685c6d75d7af5fa7d9
Raspberry PiでHDMI-CECを出力し、テレビの操作を行う

テレビに接続しているゲーム機には、本体を起動するとテレビも連動して起動させて、HDMIの入力も自動で切り替えてくれる機能を持っています。
我が家ではPCもテレビに接続しているのですが、PCからはそういったテレビ連動はできません。
そこを何とかできないか、ということで家に転がっていたRaspberry Piで何とかする、というのがこの記事の内容です。

# 外部機器がテレビを操作する「HDMI-CEC」について
Nintendo Switchのようなゲーム機はテレビとの電源連動機能を持っており、本体を起動すると「テレビの電源を入れて」「HDMIの入力切替を行って」自動的にゲーム画面がテレビに表示されます。
この機能は **HDMI CEC（Consumer Electronics Control）** という規格に基づく信号を送信することで実現しています。
で、ゲーム機がCECを送信出来るのならPCでもCECを送信できるだろうと思ったのですが、[ハードウェアレベルで実装してないためできない](https://forums.developer.nvidia.com/t/hdmi-cec-support/31445/57)らしいです。
そしてPCはCECの信号を送信できないのですが、実はRaspberry PiはCECの信号を出力することができます。

# やりたいこと
テレビに接続したPCを起動したら
* テレビをつける
* PCを接続しているHDMI入力に切り替える

PCがシャットダウンしたら
* テレビの電源を落とす

# Raspberry Piの準備
OSはRaspbianを使用。
CECの使用するために`cec-utils`をインストールしてください。
```bash
apt update
apt install cec-utils
```

# CECの使用方法
cec-utilsでCECフレームを送信する方法はいくつかあるのですが、ここではechoで必要なメッセージを出力して、single-commandモード(`-s`)で実行する`cec-client`に渡す方法を使います。
```bash:サンプル：TVの電源を付けるコマンド
echo "tx 10:04" | cec-client -s
```

`tx`を先頭に入力し、続けて引数としてCECフレームを入力します。
CECフレームの先頭2バイト部分`10`は、1バイト目が送信元論理アドレス、2バイト目が送信先論理アドレスとなります。
テレビの論理アドレスは`0`で固定、送信元となるRaspberry Piの論理アドレスは`cec-client -l`コマンドで出力されるdevice情報から確認できます。
この記事では、Raspberry Piの論理アドレスは`1`であるものとしてCECフレームを作成します。
```bash
# cec-client -l
libCEC version: 6.0.2, compiled on Linux-5.10.63-v8+ ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, Linux, AOCEC
Found devices: 1

device:              1
com port:            RPI
vendor id:           2708
product id:          1001
firmware version:    1
type:                Raspberry Pi
```

HDMIの入力切替を行う際には、「物理アドレス」も指定しなくてはいけません。
調査方法は割愛しますが、基本的に「HDMI 1：`1.0.0.0`」～「HDMI 4：`4.0.0.0`」というようなアドレッシングになっています。

この記事で使用するCECフレームの内容は以下の通り。
|CECフレーム|機能|備考|
|:-:|:-:|:-:|
|10:04|テレビの電源をONにする|`echo "on 0"`と同値|
|10:36|テレビの電源をOFFにする|`echo "standby 0"`と同値|
|1f:82:20:00|いわゆる"HDMI 2"をアクティブにする|宛先論理アドレスはTVの`0`ではなく、ブロードキャストの`f`を指定する必要がある<br>3-4バイト目はアクティブソースを指定する宣言<br>5-8バイト目は対象となるHDMI入力の物理アドレスを指定する|

# PC(Windows)との連動
本当はWindowsのタスクスケジューラーを使い、起動時/終了時にRaspberry PiにHTTPアクセスをしてCECの操作をしたかったのですが、どうしてもタスクスケジューラーが機能してくれませんでした。
（たぶん私の知識不足）
そのため、「Raspberry PiからPCに定期的にpingを打ち、その結果でCECの操作を行う」という方法としました。

具体的に、以下のようなシェルをRaspberry Pi上に配置し、systemdにてサービス化させました。
1. 1秒周期でWindowsPCにpingを打つ
1. ping応答があればカウント変数をデクリメント。ただしカウント変数がすでに"0"なら何もしない
1. デクリメントした結果が"0"になった場合、TVの電源をON＋"HDMI 2"をアクティブにする
1. ping応答がなければカウント変数をインクリメント。ただしカウント変数がすでに"3"なら何もしない
1. インクリメントした結果が"3"になった場合、TVの電源をOFFにする
```bash
#!/bin/bash

CNT=0

while true
do
  ping -c 1 -w 1 <WindowsPCのIPアドレス> > /dev/null
  BUF=$?
  if [ $BUF -eq 0 ]; then
    if [ $CNT -gt 0 ]; then
      CNT=`echo $(($CNT-1))`
      if [ $CNT -eq 0 ]; then
        echo "tx 10:04"|/usr/bin/cec-client -s -d 1 > /dev/null
        echo "tx 1f:82:20:00"|/usr/bin/cec-client -s -d 1 > /dev/null
      fi
    else
      CNT=0
    fi
  else
    if [ $CNT -lt 3 ]; then
      CNT=`echo $(($CNT+1))`
      if [ $CNT -eq 3 ]; then
        echo "tx 10:36"|/usr/bin/cec-client -s -d 1 > /dev/null
      fi
    else
      CNT=3
    fi
  fi
  sleep 1
done
```
[ARK] 洞窟内で飛行生物に騎乗できない

# 結論
次の二つを実施します。

- `GameUserSettings.ini`の`ServerSettings`項目に次を追加
```ini
ForceAllowCaveFlyers=True
```

- 起動オプションに`-ForceAllowCaveFlyers`を追加
  - Steamの場合は、ライブラリ→設定→プロパティ→起動オプション に記入してください
  - サーバーの場合は起動コマンドラインに記入してください

# 経緯
2024/9/16現在、ソロプレイの洞窟内で飛行生物に乗れない問題が発生。  
調べた次を実施したが解決されなかった。
- ゲーム設定で「生物の洞窟内飛行を有効化」にチェック
- GameUserSettings.ini`の`ServerSettings`項目に`ForceAllowCaveFlyers=True`を追加
- GameUserSettings.ini`の`ServerSettings`項目に`bForceCanRideFliers=True`を追加

探し回った挙句[Redditの記事](https://www.reddit.com/r/ARK/comments/og2nt2/why_doesnt_force_allow_cave_flyer_not_work/)に当たった。  
Redditの内容を見る感じサイレントアップデートでこういう仕様になった旨が皮肉られてるのでまあそういうことなんじゃないかなぁ。。。
Apple SiliconのMacでIntel x64アーキテクチャのアセンブラを動かす

低レベルプログラミングという本の勉強のため、M1 Mac上でIntel x64アーキテクチャのアセンブラを動かす環境構築をした時のメモ。

# 前提
* M1 Mac

Docker Desktopをインストールし、起動してから手順を行う。Dockerfileを使ったほうがいいかもしれないが、今回は手動で環境構築した後にイメージを作る手順とした。

# イメージの作成手順

## 1. x86_64ベースのDockerコンテナを用意（ホスト）

一応ホストと共有ディレクトリを作るようにしている。これを共有したいディレクトリ上で実行する想定。

```zsh
docker run --rm -it --platform linux/amd64 -v $(pwd):/workspace ubuntu bash
```

## 2. コンテナ内で必要なツールをインストール（ゲスト）

```bash
apt update
apt install -y nasm gcc locales
```

## 3. 動作確認用のコードを生成（ゲスト）

```bash
echo 'section .data
    msg db "Hello, World!"
section .text
    global _start
_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, 13
    syscall
    mov rax, 60
    xor rdi, rdi
    syscall' > hello.asm
```

## 4. アセンブル（ゲスト）

```bash
nasm -f elf64 hello.asm -o hello.o
```

## 5. 実行ファイルを生成（ゲスト）

```bash
ld -o hello hello.o
```

## 6. 実行（ゲスト）

```bash
./hello
```

## 7. 日本語を扱えるようにロケールを設定（ゲスト）

```bash
sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen
locale-gen
update-locale LANG=ja_JP.UTF-8

echo 'export LANG=ja_JP.UTF-8' >> ~/.bashrc
echo 'export LANGUAGE=ja_JP:ja' >> ~/.bashrc
echo 'export LC_ALL=ja_JP.UTF-8' >> ~/.bashrc
```

## 8. Python2のインストール（ゲスト）

普通なら不要だが、前述の「低レベルプログラミング」の本でテストを実行するにはなんとPython2が必要なので、その場合はインストールが必要。

`apt install` でインストールできないのでソースからビルドする。以下を参考にしたらうまくいった。

https://stackoverflow.com/questions/69295076/how-to-install-python2-7-5-in-ubuntu-docker-image


## 9. イメージを作るためのコンテナIDを調べる（ホスト）

```zsh
docker ps
```

ここで出力されたCONTAINER IDをひかえる。

## 10. イメージを生成（ホスト）

`<container_id>` は上でひかえたコンテナIDに置き換える。

```zsh
docker commit <container_id> my_assembly_image
```

# 以降

前述の手順でイメージが作成できる。以降はイメージを使って実行する。（ホスト）

```zsh
docker run --rm -it -v $(pwd):/workspace my_assembly_image bash
```

以下の警告が出るが無視しても問題ない。

```
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
```

警告が出てほしくなければ `--platform linux/amd64` を指定すればいいはず。
JavaScript オブジェクトから特定のプロパティを変数へ取り出す方法

## JavaScript オブジェクトから特定のプロパティを変数へ取り出す方法

スプレッド構文と分割代入を応用すると、あるオブジェクトからほしい値だけを、変数代入することができる（学習メモ）

```javascript
const profile = {
    name: 'taro',
    age: 27,
    address: 'tokyo'
};

const {address, ...other} = profile;
console.log (address);  // => tokyo
console.log (other);    // => {name: 'taro', age: 27}

```
初学者向け text-alignについて

# はじめに

text-alignは「ブロック要素または表のセルボックス内におけるインラインレベルコンテンツの水平方向の配置を設定」するプロパティである。
https://developer.mozilla.org/ja/docs/Web/CSS/text-align

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="QWXRrPb" data-pen-title="text-alignを理解する" data-user="syo-tokeshi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/syo-tokeshi/pen/QWXRrPb">
  text-alignを理解する</a> by syo-tokeshi (<a href="https://codepen.io/syo-tokeshi">@syo-tokeshi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 個人的反省点

mdnにちゃんと

> ブロック要素または表のセルボックス内におけるインラインレベルコンテンツの水平方向の配置を設定

と書かれているので、表のセルボックス内ではないインライン要素やインラインブロックでは試す必要がなかった。

ネットの記事ググるのは良いが、正式な仕様はMDNを参照しないといけないので、きちんとMDNの言っている意味を理解して、それを根拠に実装する癖をつけなくてはいけない

# 学習動機

よく真ん中寄せにしたい時に`text-align: center;`を脳死で試すことがあった。

個人開発をする上で、UIフレームワークにスタイリングを丸投げすることはできない事に気づき、自分で根拠を持ってcssを書きたいと思うようになった。
[ Rails ] アプリ内のコメント通知をLINEで行う方法

<h3>はじめに</h3>
こんにちは！<br>
個人開発アプリの通知機能のまとめ記事です。<br>
全3回構成となっており、今回は最終回として、アプリ内のコメント通知をLINEで行う方法について説明します。<br>

個人開発のまとめ記事はこちらからご覧ください。

https://qiita.com/CarBoss1996/items/63c14260fc7fe65da78e

前回記事たちはこちらからご覧ください。

https://qiita.com/CarBoss1996/items/e619335206076301e00f

https://qiita.com/CarBoss1996/items/fba0f499160f0d4530d7


<h3>開発環境</h3>
・Ruby on Rails 7.1<br>
・Ruby 3.2.3<br>

<h3>完成物</h3>
ユーザーの投稿に新規コメントが作成されると、LINEに通知が送られます。<br>
通知にはリダイレクトURLも含まれており、簡単にアプリに戻ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3871424/da6f9fac-63f8-21a6-2c07-ee07691d889a.png)


<h3>手順</h3>
1. post_id に line_user_id を紐付ける<br>
2. コメントモデルに通知設定をする

<h3>1. post_id に line_user_id を紐付ける</h3>
まずは post_id に line_user_id を紐付けます。<br>
Postモデルに以下のメソッドを追加します。

```post.rb
class Post < ApplicationRecord
  has_many :comments, dependent: :destroy
  
  def line_user_id
    user.line_user_id
  end
end
```
これにより、line_user_id メソッドを通じて、アプリのユーザーIDとLINEアカウントIDを投稿に紐付けることができます。
このメソッドを、後ほどコメントモデルから呼び出します。

<h3>2. コメントモデルに通知設定 </h3>
次に、コメントが作成された際にLINE通知を送る機能を実装します。

```comment.rb
class Comment < ApplicationRecord
  validates :body, presence: true, length: { maximum: 255 }
  belongs_to :user
  belongs_to :post
  after_create :send_line_notification

  private

  def send_line_notification
    # postの所有者のline_user_idを取得
    line_user_id = self.post.user.line_user_id

    # line_user_idが存在する場合のみ、LINE通知を送信
    if line_user_id.present? && line_user_id.is_a?(String)
      post_url = "https://kousiennow.onrender.com/post/#{self.post.id}"
      message = "#{self.post.user.user_name}さん、あなたの投稿に#{self.user.user_name}さんからコメントがあります。\n\"#{self.body}\" \n#{post_url}"
      Notification.create_and_send_line_notification(line_user_id, message)
    end
  end
end
```
after_create により、コメントが作成されると自動的に send_line_notification メソッドが呼び出され、LINE通知が送信されます。
通知は、LINEアカウントと連携している場合のみ送信されるため、連携していない場合でもエラーは発生しません。
LINEメッセージを送る処理は、notification.rb にすでに記述済みです。
そのため、この部分では、誰にどのような内容のメッセージを送るかを定義するだけで済みます。

これで、投稿に新規コメントがついた際にLINE通知が送信されるようになりました！

<h3>最後に</h3>
最後までお読みいただきありがとうございます！<br>
これで公式LINE追加からコメント通知を送るまでの流れをまとめることができました。<br>
備忘録ですが、参考になれば幸いです。<br>
初学者ゆえ、誤解や説明不足があるかもしれませんが、ご指摘いただければ幸いです。
CUE言語でmap、filter的な記法

`cue`言語にmapやfilterという関数型プログラミングの関数はありません。`for`文を使って行います。

```golang
vals: [ "a","b","c","d","e" ]

map: [ for _, n in vals {
    "[ " + n + " ]"
}]

filter: [ for _, n in vals if n > "c" { n } ]
```

```bash
$ cue export list.cue
{
    "map": [
        "[ a ]",
        "[ b ]",
        "[ c ]",
        "[ d ]",
        "[ e ]"
    ],
    "filter": [
        "d",
        "e"
    ]
}
```

# 参考

https://cuelang.org/docs/tour/expressions/listcomp/

https://cuetorials.com/overview/expressions/#comprehensions
【OpenAI o1】にDALL-E3の縦長画像について相談しました。


　どうも、カーブミラーです。

　今回は、OpenAI o1にDALL-E3の縦長画像について相談しました。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
あります。　あしからず。
:::

　まずは、ニュースです。

　OpenAI o1（o1-Preview）、
　　メンサのＩＱテストで
　　　ＩＱ120と判明。
　　　　[TrackingAI](https://trackingai.org/IQ)

　“人類の90%より
　　賢いことが証明された”

　“人間の平均IQは
　　90〜100なので、圧倒的”

　とX-Twitter上で騒がれています。

　とはいえ、
　　理系に強いだけで
　　　文系が弱いんだから
　　　　ダメじゃんって話ですけどね😸

　まぁ、
　　知能レベルが上がったのは
　　　確かなので、我々も頑張んべぇ〜
***
　iekyさんという方が
　　メリットデメリットを
　　　書いてくださいました。
　　　　そのまま出します。
```Text:iekyさんポスト内容
OpenAIの新モデルo1(preview)のメリット・デメリット👇

1. メリット
・複雑なタスクに強い
・簡潔な指示で済む
・思考の可視化でブラックボックス解消

2. デメリット
・簡単なタスクでは旧モデルと大差なし
・料金高、使用回数制限
・速度が遅い
・ファイルアップロード、ブラウジング等機能制限
```
　[iekyさんポスト](https://x.com/ieky0223/status/1835107583792972101?t=YeUljYTao_r5TEeN6E-IFw&s=19)

　このデメリットを受容しても
　　メリットの方が大きい、と
　　　思う思わない、は
　　　　それぞれの判断に
　　　　　お任せします。

　私は、
　　やりたいことの
　　　道筋を立ててもらえるので、
　　　　メリットあり、ですね😸

　それでも
　　早く、Web、ADA、画像生成を
　　　接続して欲しいところです。
***
　さて、本題です。

　今回は、
　　久々にDALL-E3ネタをやります。

　とはいえ、
　　やはり流行りの
　　　OpenAI o1を使ってみないと
　　　　いけませんよね😸

　実は、
　　前々から
　　　縦長の画像を生成すると
　　　　縦長だけど横長画像になる
　　　　　という問題があり、
　　　　　　辟易しておりました。

　それで
　　o1に相談してみたわけです。

　ではやり取りをどうぞ。
***
***user***
DALL-E3に与えるPromptについて相談したいです。
アスペクト比を縦長で指定するのですが、確かに縦長で出てきます。
しかし、画像は横倒しになってしまうことが多いです。
例えば、女性の全身を出したいのに、どうしても横倒しになってしまい、せっかくの縦長指定が横長指定と同じになってしまうのです。
解決方法はあるでしょうか？

***o1-mini***
DALL-E 3で縦長の画像を正しく生成するためには、プロンプトに具体的な指示を追加することが重要です。以下の方法を試してみてください：

1. **明確な指示を追加する**:
   - 「縦向き」や「ポートレート形式」といったキーワードをプロンプトに含めることで、縦長の画像を生成しやすくなります。
   - 例: 
     ```
     縦向きのポートレート形式で、全身が映る女性のイラスト
     ```

2. **構図を具体的に指定する**:
   - 「立っている姿」や「全身がフレームに収まっている」といった具体的な姿勢や構図を記述すると、横倒しになるリスクを減らせます。
   - 例:
     ```
     縦向きのポートレート形式で、立っている女性の全身像
     ```

3. **アスペクト比の指定を明確にする**:
   - アスペクト比を明示的に指定することで、縦長の画像生成を促します。例えば「9:16のアスペクト比」など。
   - 例:
     ```
     9:16の縦長アスペクト比で、全身が映る立っている女性のポートレート
     ```

4. **視点や方向性を指定する**:
   - 「正面から見た」や「縦方向に配置された」といった視点を追加することで、意図した向きでの画像生成を助けます。
   - 例:
     ```
     正面から見た縦向きのポートレート形式で、全身が映る女性
     ```

5. **不要な回転を避ける指示を加える**:
   - 「横向きにしない」や「回転させない」といった指示を追加することで、横倒しを防ぐことができます。
   - 例:
     ```
     縦向きのポートレート形式で、回転させずに全身が映る女性のイラスト
     ```

6. **具体的な例を参考にする**:
   - 他の成功例や参考画像のスタイルをプロンプトに含めると、より期待に近い結果が得られる可能性があります。
   - 例:
     ```
     縦向きのポートレート形式で、ファッション雑誌風の全身が映る女性
     ```

**まとめ**:
プロンプトを作成する際には、縦向きやポートレート形式を明確に指定し、全身が映るような具体的な構図や姿勢を詳細に記述することが重要です。これにより、DALL-E 3が意図した通りの縦長画像を生成しやすくなります。試行錯誤しながら、最適な表現を見つけてください。
***

　「縦向きのポートレート形式」が
　　キーワードのようですね。

　６番のPromptを
　　GPT-4oに渡してみました。
![1726457674662.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/3e0bda66-5f62-bdf9-bdf8-fc5952b6914f.jpeg)

　そのまま、
　　少しずつ指示を出して
　　　変更していきますが、
　　　　縦長画像ばかりになりました。

　しかし、
　　人物に踊らせると
　　　縦長に横長画像で描画されます。
　　　　うまくいく場合もありますが。

　ようするに
　　横長になりやすい画像を
　　　得ようとすると
　　　　ダメなようですね。

　それでも
　　キーワードがわかっただけでも
　　　ありがたいです。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
入力フォームを画面中央に縦に配置する方法

# はじめに

入力フォームを画面中央に縦に配置する方法が分からなかったのでまとめてみた。
flex-directionが鍵だと思います。

 ## flex-directionで主軸の方向を縦にし、`align-items: center;`を指定すると、画面中央にフォームが行く

 理由としておそらく、`align-items`が垂直方向への操作であり、flex-directionで`column`を選択すると、主軸が垂直方向に整列されるからだと思う。
 この状態で `justify-content`を指定しても反映されない(justify-contentは水平方向への操作だからだと思われる)

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="mdZYLxG" data-pen-title="Untitled" data-user="syo-tokeshi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/syo-tokeshi/pen/mdZYLxG">
  Untitled</a> by syo-tokeshi (<a href="https://codepen.io/syo-tokeshi">@syo-tokeshi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 真ん中寄せにした時にボタンのコンテンツが長く、真ん中寄せを維持しようとして整列できなくなった場合の対処法

全体を真ん中寄せをした際、文字数が多いなどでコンテンツが長くなると、widthが広がり、整列が崩れます。
![スクリーンショット 2024-09-16 12.31.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/80b76e8d-4bd4-09b6-94b3-374319769f3d.png)

正しい対処かは分かりませんが、
入力フォームの親ブロック要素に、子要素のコンテンツより多めのwidthを指定すると、レイアウト崩れを回避できます
![スクリーンショット 2024-09-16 12.35.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/47de4be6-2af4-d74d-2128-223045bdb3a0.png)

```css
.child{
  width: 300px;
} 
```
Drupal既存のテーブルにカラムを追加する

# 注意点

まず初めに、他のcmsでもそうだと思いますが、ベースのテーブルに対してカラムを追加するやり方は良くないと思っています。
何らかのカラムを追加したい場合はオリジナルのテーブルを使ってjoinするやり方が良いでしょう。または、カスタムフィールド的なものがある場合は、そこにいれる。

(例外としてeccubeだけは、ベースのテーブルにカラムを追加するやり方のほうがシンプルに済む場合も多いですし、公式的にもTraitを使って、拡張できるようにする解説が出ています。）


## 本題
注意点ではそう書きましたが、シングルサインオンのような機能を作りたい場合は、joinさせるより、
常に1対1の関係ですし、デフォルトテーブルにシングルサインオン判定用のカラムを追加したほうが便利ですし、ログインという重要な機能において、カラムを追加するやり方を取ったほうが良いと考えました。
Drupalの既存テーブルはエンティを使って書かれているため、そのまま「hook_install」などを使って無理やりカラムを追加した場合、不具合が生じる可能性が高いと思いました。

なので、公式ドキュメントや海外の記事を探すと、「hook_entity_base_field_info」フックを利用して追加するのが良いようです。(モジュールを削除する場合は、自動的にカラムも削除されるようです。)


https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_base_field_info/10

https://www.reddit.com/r/drupal/comments/rp6xny/change_the_write_destination_between_different/

### 参考コード
```php:line_login.module
/**
 * Implements hook_entity_base_field_info().
 */
function line_login_entity_base_field_info(EntityTypeInterface $entity_type)
{
    $fields = [];

    // ユーザーエンティかチェック
    if ($entity_type->id() === 'user') {
        $fields['line_user_id'] = BaseFieldDefinition::create('string')
            ->setLabel('LINE User ID')
            ->setSettings([
                'max_length' => 255,
            ])
            ->setDefaultValue(null)
            ->setRequired(false);
        return $fields;
    }
}


/**
 * Implements hook_install().
 */
function line_login_install()
{
    // データベーススキーママネージャを取得
    $schema = \Drupal::database()->schema();
    $table = 'users_field_data';

    // テーブルにユニークキーが既に存在しない場合、追加
    if ($schema->tableExists($table) && !$schema->indexExists($table, 'line_user_id_unique')) {
        $schema->addUniqueKey($table, 'line_user_id_unique', ['line_user_id']);
    }
}
```

↑エンティを使ったやり方だと、バリデーションレベルでだとユニークにできるようですが、テーブルレベルでユニークに出来ない？(やり方あるのかもしれないですが...)と思ったので、「hook_install」を使ってユニークにしています。


## 作ったモジュール
「hook_entity_base_field_info」を使ってLINEログインモジュールを作成

https://github.com/teratai3/line_login
【備忘録】Github Pagesデプロイ失敗

先日個人ページを初めてGithub Pagesを利用して作成したのですが、デプロイに失敗するというエラーに直面したので、その解決策の備忘録です。

# 問題
ディレクトリ構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3884848/aede0abc-5ea0-c39b-42a1-8d54d062fc38.png)
こんな感じでディレクトリを作っていたのですが、デプロイに失敗しました。

# 解決策
問題は、レポジトリのSettings→Pages→Build and deploymentに移動して、Branchが"mainの/docs"になっていたことでした。"mainの/(root)"に変更したら、ビルドとデプロイが成功しました。とてもシンプルなミスですね。
node.jsのDocker環境を作成する

### はじめに

こんにちは,Mottyです。今回はnode.jsのDocker環境を作っていく手順を説明します。

### Dockerで環境構築するためのモチベーション

Dockerではコンテナ内にNode.jsと依存ライブラリがすべて閉じ込められているので、どの環境でも一貫して動する。開発者のローカル環境に依存せず、すべての依存関係が同一バージョンで実行されるため、"It works on my machine"問題を防ぐことができる、とのこと。

### 構築方法

WSL上のどこかのプロジェクトのルートディレクトリに以下２つを作成
・Dockerfile
・package.json

### Dockerfileの構築方法

```Dockerfile
# ベースイメージとしてNode.jsの公式イメージを使用
FROM node:16

# 作業ディレクトリを設定
WORKDIR /usr/src/app

# package.jsonをコピーして依存関係をインストール
COPY package*.json ./
RUN npm install

#コンテナを終了させないためのコマンド
CMD tail -f /dev/null
```


```package.json
{
    "name": "my-node-app",
    "version": "1.0.0",
    "description": "A simple Node.js app",
    "main": "app.js",
    "scripts": {
      "start": "node app.js"
    },
    "author": "Your Name",
    "license": "ISC",
    "dependencies": {
      "express": "^4.17.1"
    }
  }
  
```

この状態でDockerをビルドする。具体的には、以下のコマンドで↓
```
docker build -t my-node-app .
```


そのままコンテナ立ち上げ
```
docker run -d my-node-app
```

立ち上がっているコンテナのリストをみて、my-node-appがあればOK
```
docker ps
```


## コンテナを終了させないための仕掛け

Dockerコンテナは通常、メインプロセスが終了するとコンテナも停止します。例えば、node app.jsなどのプロセスが終了した場合、コンテナ自体も停止します。

CMD tail -f /dev/null は、この動作を防ぐためのコマンドです。

tail コマンド は通常、ファイルの末尾を監視するために使います。-f オプションをつけると、指定したファイルに新しい行が追加されるたびに、その内容を表示し続けます。

/dev/null は、特殊なファイルで、どんなデータを書き込んでも捨てられ、空のままになります。つまり、読み出しても何も返ってきません。

tail -f /dev/null の意味は、「何もない空のファイルを永遠に監視し続ける」ということです。このプロセスは何もしないため、終了せずにずっと動作し続けます。

上記コマンドを使うと、Dockerコンテナの中で何もしないプロセスがずっと実行され続けることになり、コンテナも終了しません。つまりコンテナを終了させずに待機状態にしておき、他の操作（例えば、後からコンテナ内に入って作業をするなど）が可能になります。

### 検証

package.jsonがコピーされているのを確認します。
その後、app.jsを作成しpackage.jsonに定義したnpm startを走らせることでコンソールに出力結果が表示されればOKです

 ![スクリーンショット 2024-09-16 120704.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302420/42a91dc6-571d-8521-e652-ced24f684331.png)
このままではまずいと思ってQiitaはじめました

# 現状打破のために
エンジニア歴1年半にしては経験値、技術力が低くにかなり焦っています。
成長のために少しずつ学んだことをアウトプットとして投稿していきます。

温かい目でよろしくお願いします。。。
最小努力と最短時間でMB-910合格記

前回(AI-900)に引き続きFundamentals制覇に向けて受験し、無事に合格いたしました。
実は1回不合格となり今回が2回目の受験でした。（前回は当日2時間しか勉強しなかったため当然の結果…）
Dynamics 365については人生で一度も関わりがなかったため、
前提知識0だったことが非常にきつく、Fundamentalsの中で最も難しく感じました。

過去の体験記はこちら：

https://qiita.com/ponponmikankan/items/fd363bb0323569d3676f

https://qiita.com/ponponmikankan/items/77202be0de32cda5893d

https://qiita.com/ponponmikankan/items/4b64124be47a34467019

https://qiita.com/ponponmikankan/items/c27d6db74bac7cb44fef

https://qiita.com/ponponmikankan/items/f25fa53b13f10df574d6

https://qiita.com/ponponmikankan/items/95790b6892a3c6d3e285

https://qiita.com/ponponmikankan/items/d19606c99f902f57a4ca

## 前提
MB-910はDynamics 365の中のCRM機能にフォーカスした試験となっています。
残念ながら私自身は業務では使っておらず、Learnで初めて学びました。
もともと営業部にいたのでCRMの考え方については知っていました。

## 参考にした勉強法

MB-910は非常にマイナーな試験なためかあまり合格記が落ちていません。

https://kanbyo.com/archives/mb-910/

一応こちらを参考にさせていただきましたが、
いつも通りLearnから実施しました。

## 実際の勉強でやったこと

### Learnを読む（5時間程度）

https://learn.microsoft.com/ja-jp/training/courses/mb-910t00/

初回は2時間の飛ばし読みで落ちたため、2回目はもう一度最初から丁寧に読みました。
実際の画面を見たことがないためイメージしにくいのですが、途中に出現するサンドボックスを使っていろいろ操作を行いました。普段は読み飛ばしているクイックスルーも参考になりました。
Virtual Training Daysの動画がYouTubeに上がっていたりするので、それも併せて参照しました。

### プラクティス評価の実施（7周くらい）

https://learn.microsoft.com/ja-jp/credentials/certifications/d365-fundamentals-customer-engagement-apps-crm/practice/assessment?assessment-type=practice&assessmentId=53&practice-assessment-type=certification

とにかく最初から正答率が低かったため7周くらいはやりました。
1回目は正答率3割とかでした(笑)

基礎的な理解が足りておらず、Learnで読んだはずの部分も抜け落ちていくので、
Notionに間違えたところのスクショをはっておぼえました。
ただ、このプラクティス評価は本番とかなり内容が違うため、あくまでも基礎知識習得として使ったほうが良いです。

### Udemyの模試の購入

https://www.udemy.com/course/mb-910-microsoft-dynamics-365-fundamentals-crmmock-tests/?couponCode=ST11MT91624B

上記合格記で記載があったので買ってみましたが、マジで意味なかった！！！
プラクティス評価をただ有料で買っただけでした…1500円無駄にした…。
皆さんは絶対に購入しないようお気を付けください。

### 試験の感想

試験時間は1時間で、40分くらいかかりました。（見直し1周）。
ほかの900系同様、択一やドラッグドロップ系なので焦ることはないです。

にしても、ほかの試験と異なり、プラクティス評価の問題がほとんど出てこないので、
どれだけきちんと機能や言葉を理解しているかが問われます。

ううう、Fundamentals制覇に向けて次回が最終回！
次回はMB-920(ERP)を受けてきます。

マジで次回もマイクロソフト製品としてはまったく関わりのないジャンルなので苦行！