OmniAICreator/Qiita-1.07M huggingface dataset:
Macでmysql5.7をインストールする方法

# Homebrewを使ってmysql@5.7がインストールできない・・・
開発環境を構築する際に,mysql5.7をインストールしようとすると以下のようなエラーが
```
Error: mysql@5.7 has been disabled because it is not supported upstream! It was disabled on 2024-08-01.
```
どうやらサポート切れで2024年8月1日以降Homebrewを使ってmysql5.7をインストールできなくなっているようです。
ただ、そうはいっても古いシステムなどまだmysql5.7をインストールしないといけない場合もありそう。

# 解決策
まだインストールできなくなって日が浅いためか、なかなか解決策が見つからない・・・
## ソースコードからbuildしてインストールする方法
いまのところこれが唯一macにmysql5.7を入れる方法らしい。
参考:
https://zenn.dev/noraworld/articles/legacy-mysql-mac

### 必要なライブラリのインストール
以下のコマンドを実行して必要なライブラリをインストールします。
cmakeとかはコードからbuildするときに必要
```shell
xcode-select --install
brew install cmake git ncurses openssl
```
以下から5.7.44をインストール
https://downloads.mysql.com/archives/community/
Operating SystemはSource Code、OS VersionはAll Operating Systems (Generic) (Architecture Independent)を指定します。

そして今ダウンロードしたファイルをホームディレクトリに移動し、以下のコマンドを実行
```shell
tar zxvf mysql-boost-VERSION.tar.gz
```
これでアーカイブが展開されmysql-5.7.44というフォルダが生成される。

### インストール
自分の場合はホームディレクトリに展開したので、以下のフォルダをホームディレクトリに作成。
インストール時に生成されるフォルダやファイルを格納するためのものらしい。

```shell
mkdir mysql-home
mkdir boost
```
先ほど展開したフォルダに移動
```shell
cd mysql-5.7.44
```
以下のコマンドを実行
```shell-session
cmake -DCMAKE_INSTALL_PREFIX=/path/to/mysql-home \
      -DDOWNLOAD_BOOST=1                         \
      -DWITH_BOOST=/path/to/boost                \
      -DDEFAULT_CHARSET=utf8                     \
      -DDEFAULT_COLLATION=utf8_general_ci        \
      -DWITH_INNOBASE_STORAGE_ENGINE=1
```
次に以下のコマンドを実行
```shell
make
make install
```
おそらくここでかなり時間がかかります。自分の場合は15分くらいかかりました。
### データの初期化
mysql-homeディレクトリに移動します
```shell
cd mysql-home
```
そこに以下のディレクトリを作成、ここにデータが書き込まれていくらしい
```shell
mkdir mysql-files
```
所有者と権限を変更
```zsh
sudo chown mysql:mysql mysql-files
sudo chmod 750 mysql-files
```
そして以下のコマンドを実行
```
bin/mysqld --initialize --user=mysql
```
ここで以下のように初期のパスワードが発行されるので保存しておきます。
```
2024-09-03T06:30:15.306122Z 1 [Note] A temporary password is generated for root@localhost: AyVCZ+whY9R(
```
ここで先ほどのbin/mysqldなどはこのディレクトリ以外からだとこのファイルのフルパスを打たないといけないため、とても面倒です。
どこからでもmysqlコマンドを使えるようにするため、パスを通します。
```
echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.zshrc
```
普通にhomebrewでインストールする際は上のようなコマンドで問題ないのですが、今回はこれらがmysql-homeに作成されているため、以下のように変更する必要があります。
```shell
echo 'export PATH="/{mysql-homeがある場所までのパス}/mysql-home/bin:$PATH"' >> ~/.zprofile
```
設定を反映させる
```zsh
source ~/.zprofile
```
mysql --versionで確認して、version情報を取得できれば完了です。

### mysqlへのログイン
以下のコマンドでログイン
```shell
mysql -u root -p
```
passwordを求められますが、先ほど取得した初期パスワードを入力。
```mysql>```となったら以下のコマンドを実行し、初期パスワードを任意のパスワードに変更してください。
```
SET PASSWORD = PASSWORD('pass');
```
最後に以下のコマンドでホストとユーザ情報を確認し、問題なく表示されれば完了です。
```
SELECT Host, User FROM mysql.user WHERE User = 'root';
```

```sql
+-----------+------+
| Host      | User |
+-----------+------+
| localhost | root |
+-----------+------+
1 row in set (0.01 sec)
```
# 最後に
情報が少なく導入に苦労した。
古い技術を使用する上でのリスクを認識することができた。
asteriskをmakeしたときにmake: *** '.lastclean' に必要なターゲット '.cleancount' を make するルールがありません.  中止.と出たとき

```
make: *** '.lastclean' に必要なターゲット '.cleancount' を make するルールがありません.  中止.
```

英語なら↓
```
*** No rule to make target ‘.cleancount’, needed by ‘.lastclean’.
Stop. In Makefile.rules is nothing about cleancount…
```

こんなエラーが出たら
touch ./.cleancount
としてあげたらビルドが通ります。ちょっとハマったのでメモ。
空のファイルが要るっぽい。
paizaでPythonを使う時の備忘録（適宜更新）

# 入力
## 入力値を整数（int型）に変換して取得
```python
n = int(input())
```
## 複数の値を取得
```python
a,b=input().split()
```
split関数は**半角スペース、タブ、改行**で文字列を分割することができる。
## 複数の値を取得し、int型に変換
```python
n, l = map(int, input().split())
```
## 1行ずつ配列に入れる
```python
rounds_list = [input() for i in range(n)]
```
## 入力の行数が不明な場合：値を1行ずつ配列に入れる
```python
import sys
a = []
for l in sys.stdin:
    a.append(int(l))
```
### sysモジュール
- Pythonの標準ライブラリ、Pythonのインタプリタと対話するための機能を提供
### sys.stdin
- 入力を読み取るために使う
### append()
- リスト（配列）に新しい要素を追加するためのメソッド
- リストの**最後**に1つの要素を追加する
## 入力で複数の値をリスト形式で取得し、int型に変換
```python
price_list = list(map(int, input().split()))
```
# 配列の処理
## ループ処理
```python
fruits = ['みかん', 'りんご', 'ぶどう']
for fruit in fruits:
    print(fruit) 
```
**出力**
```
みかん
りんご
ぶどう
```
## 要素の合計
### for文を使ったやり方
```python
list_1 = [1,2,4,8]
total = 0

for n in list_1:
    total += n

print(total) 
# 出力：15
```
### sum()関数を使ったやり方
```python
list_1 = [1,2,4,8]
total = sum(list_1)

print(total)

# 出力：15
```
sum()関数を使うと簡単に合計を求めることができる。
## 最大値を取得するmax()関数
引数の値の中から最大値を返す
### リストの最大値を取得
```python
numbers = [10, 20, 30, 40]
max_value = max(numbers)
print(max_value)

# 出力：40
```
### key引数を用いて、特定の条件で最大値を取得
```python
words = ["apple", "banana", "cherry"]
longest_word = max(words, key=len)  # 最も長い単語を取得
print(longest_word)

# 出力：banana
```
# 文字列の処理
## 任意の文字列の置き換え、削除ができるreplace()関数
```python
s = 'aokidai'

s = s.replace('ai', '')
print(s)
# 出力：aokid
```
- 空文字列に置き換えすると削除される
## 辞書形式を用いたreplace関数による文字列の置き換え
```python
s = 'aokidai'

# 文字置換用の辞書
replace_map = {
    'a': '4',
    'o': '0',
    'k': '6',
    'i': '1',
}

# 辞書に基づいて文字を置換
for char, replacement in replace_map.items():
    s = s.replace(char, replacement)

print(s)
# 4061dai
```
- replace_map.items() は辞書のキーとバリューを取り出す
  - charはキー（置き換えされる元の文字）
  - replacementはバリュー（置き換え後の文字）
## 正規表現を使って文字列を置き換え、削除ができるre.sub()関数
```python
import re

s = 'aokidai'

# 正規表現を使って、母音（大文字・小文字）を一度に削除
s = re.sub(r'[aeiouAEIOU]', '', s)

print(s)
# 出力：kd
```
### 正規表現について
参照：https://www.megasoft.co.jp/mifes/seiki/meta.html
## 文字列の長さを取得するlen()関数
```python
s = 'aokidai'
print(len(s))
# 7
```
## 文字列の連結
```python
m = 'aoki'
n = 'dai'

m += n
print(m)
# aokidai
```
## 文字列の部分一致
```python
print('dai' in 'aokidai')
# True
```
## 文字列の中の特定の文字を抽出
```python
s = 'aokidai'

print(s[0])
# a
```
丸1日かけてAWS SAA合格した話

9月末、AWS Solution Architect Associateに合格しました✌️
丸1日勉強して768点でした！

## 元々こんなレベル

* AWSの主要サービスは普段から利用していますが、オンプレやネットワーク構成等の知識は皆無
* 上モノ開発がメインでLambdaやCodeファミリー等は触っていたものの、「OSI参照モデル？ナニソレ」状態だった
* Docker等コンテナサービスは普段から利用していた

## 学習内容

1. Udemyの以下講座で知らないサービスの概要を理解する
https://www.udemy.com/course/aws-associate/

2. ping-tで演習問題を解きまくる
→1日で5セットやりました。1セット120分ですが大体60分くらいで終わる難易度です。

https://mondai.ping-t.com/g

3. 答えを見ても理解できなかったサービスについてping-tの問題を解く
→そもそも分からないシステムや単語はさっさと飛ばし、後で掘り下げていく

4. 2,3の繰り返し


## 今後
SAP,DVA,DOP辺りを取得できるように学習していこうと思います。
CodeファミリーやAmplifyガッツリ触れているのでDVAから始めるのが良さそう。
【Vue】refはrefをアンラップするって理解してる？

↓refでいっぱい囲っちゃえ

```ts
const num = ref(ref(ref(ref(ref(123)))))
```
123を出力するには、、
```ts
console.log(num.value.value.value.value.value)
```
かと思いきや上記は誤りでエラーとなる。。

```ts
console.log(num.value)
```
が正解。

---

じゃあこれは？

```ts
const obj = ref({
  num: ref(123)
})
```

これもアンラップされるので、

```ts
console.log(obj.value.num)
```
が正解。

# いつ困るの？

僕の場合こんなこととしててref in refが生まれました。

```ts
const useUser = (id: number) => {
  const profile = ref<string>()
  const fetchProfile = () => {
    profile.value = 'Hello'
  }
  return {
    id,
    profile
  }
}

const id = computed(() => Number(route.params.id))
const user = ref(useUser(id.value))
watch(id, () => user.value = useUser(id.value))
```

refに囲われているものとそうでないものとでは元は同じ型だったとしても構造が異なってしまうので色々問題になります。

# shallowRefを使おう

```ts
const obj = shallowRef({
  num: ref(123)
})
console.log(obj.value.num.value) // 123
```

# 参考

https://www.reddit.com/r/vuejs/comments/180xldz/ref_of_a_ref/
SafariのみCookieからデータ取得できない現象に苦しめられた話

## 背景
toC向けのフォームにて広告等流入経路識別のために独自IDを割り振り、URLパラメータへそれぞれ埋め込んでいた。

## どんな仕組みか
各経路からWebフォームへ遷移する際にURLパラメータの各情報をCookieへ格納。その後コンバージョンでパラメータも併せて送信することで流入経路の識別に活用していた。

## 問題点

### プライバシーの観点から、トラッキングやCookie無効化設定をしているユーザが増えている
Cookieありきで構築したシステムの信頼性が揺らいでおり、フローの調整が必要

### Cookie利用可否判定のロジックが十分でない
元々は以下のようにdocuent.cookieの中身をチェックして判定していた。

```js
if(document.cookie != ""){
//処理
}
```

GTM・GAを利用していたこともあり、document.cookieが空のままフォームを訪れる状況は想定外だった。
ただし昨今のSafariではサードパーティスクリプトの呼び出しをブロック、または遅延させるようになっているようで、ユーザの初回訪問時に上記Cookie利用可否判定の時点ではCookieが空になっている割合が増加しつつあった。
(この辺りWebkit周りのリリースノート調べてもそれらしき問題が見つかりませんでした・・・有識者の方いらっしゃいましたらコメントください)


### ポイント

* ユーザがCookie無効化していることを正しく判定する
誤った判定をしてしまうと本来送信すべきでないパラメータを渡してしまう。
検証した方法は以下の2点

* navigator.cookieEnabled
対象環境でCookieが利用可能かを判定する読み取り専用プロパティ。

```js
if(!navigator.cookieEnabled){
//利用不可の場合
}
```

https://developer.mozilla.org/ja/docs/Web/API/Navigator/cookieEnabled

一部ブラウザやiframe下で利用すると利用不可でもtrueを返却してしまう場合がある。

引用
>メモ: ブラウザーがサードパーティのクッキーをブロックするように構成されていた場合で、 navigator.cookieEnabled がサードパーティの iframe の中で呼び出された場合、 Safari, Edge Spartan, IE では true を返します (この場合にクッキーを設定しようとしても失敗するにもかかわらず)。 Firefox および Chromium ベースのブラウザーでは false を返します。

対応ブラウザも一通りカバーしているが、Edge、Safari系では上記問題が発生するとのこと。
https://caniuse.com/?search=cookieEnabled

また、PC Chromeでデバイスへのデータ書き込み不可(Cookieアクセス不可)にした場合でも「true」を返却してしまっていた。
→ファーストパーティCookieの利用可否判定はしていない？

* Cookieにデータを一度格納し、再取得できるかチェックする
結果としてこれがうまくいった。

Vueを使った例 (VueUse)
```ts
import { useCookies } from '@vueuse/integrations/useCookies'

export default () => {
    const cookies = useCookies(["check-enabled"])
    
    cookies.set("check-enabled", true, { maxAge:3600 }) //3600second
    
    const cookieEnabled = cookies.get("check-enabled")

    if(cookieEnabled) {
    // Cookie利用可能な場合
    }
}
```

VueUse UseCookies

https://vueuse.org/integrations/useCookies/


## まとめ
最初にアクセスした経路を優先する制御が必要だったためCookieを利用していますが、もっとシンプルなルールならURLパラメータから直接取得するか、サーバーサイド実装する工数取れるならセッション管理の方が良さそうだと感じました。
Safariのごく一部だけで発生する現象だったことから原因特定が非常に困難でした・・・
いまだに理解できていない箇所もあるので引き続き調査していこうと思います。
【学習記録　2024-10-03】　HTML、CSS

## 使用した教材など
Udemy：【世界で70万人が受講】Web Developer Bootcamp 2023（日本語版）

## 学習内容
### 学習時間：1h
- FlexBox

## 所感
　しばらく投稿してませんでしたが、今日からまた投稿できたらと思います。学習フローを見たを修正したため、教材を変更しました。
 　Flexboxはなんとなく使ってましたが、プロパティによって具体的にどのように整列されるのかが勉強になりました。
M5Stack NanoC6でSSD1306 OLEDを使う

# 概要

0.96インチ128x64ピクセルのOLEDにM5StackのNanoC6を接続し、表示させてみました。
ちょっと手間がかかるとすればPlatformIO上でM5NanoC6でArduinoを使う設定ぐらいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111095/51636b52-e06d-2d51-ed87-8e0cb77b5c8d.png)

このOLEDは上部16ピクセルが黄色で、下48ピクセルが青色のタイプです。

ほぼ以下の記事と同じ手順でできます。

- M5Stack NanoC6購入
    - https://lang-ship.com/blog/work/m5stack-nanoc6/
- ESP32-C3-WROOM-02+SSD1306でM5Stack-Avatarを表示
    - https://qiita.com/McbeEringi/items/02eb900d701ef6dab5c1

できるだけ安価にちょっとした表示ができる組み合わせとして、M5 NanoC6とGME12864/SSD1306 OLEDで文字表示を試してみました。以下のパーツです(価格は2024年9月末時点)。

- M5Stack NanoC6 (スイッチサイエンス; 1,155円)
    - https://www.switch-science.com/products/9570
- GME12864-51/SSD1306 (Amazon; 569円)
    - https://www.amazon.co.jp/gp/product/B07J2QWF43/

ということで1,724円(+送料)で128x64ピクセルOLED表示ができてしまいます(PORT.Aと接続するケーブルも必要ですが)。AtomS3が2,783円でカラー128x128ですので、どちらがいいかということですが…

Windows 10上でVSCode + PlatformIOでビルド環境を用意し、M5Unifiedを使ってプログラムを作成しました。M5GFXを使っているので、日本語フォントなども使えて便利！

# PlatformIOの設定

[Lang-shipさんのNanoC6の記事](https://lang-ship.com/blog/work/m5stack-nanoc6/)に従ってPlatformIOでNanoC6用のビルドができるようにします。その設定にM5Unifiedを追加しますので、最終的に`platformio.ini`は以下のようになりました。

```ini:platformio.ini
[env:esp32-c6-devkitm-1]
platform = espressif32
board = esp32-c6-devkitm-1
framework = arduino
platform_packages =
	platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git
	platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1
extra_scripts = pre:custon_hwids.py
build_flags =
	-DARDUINO_USB_CDC_ON_BOOT=1
	-DARDUINO_USB_MODE=1
lib_deps = m5stack/M5Unified@^0.1.17
monitor_speed = 115200
```

# ソース

続いてプログラムを用意します。Unit GLASS2を使えば簡単に書けます。

```c++:src/main.cpp
#include <M5UnitGLASS2.h>
#include <M5Unified.h>

// Port.A SDA(G2), SCL(G1)
M5UnitGLASS2 SSD1306Display(2, 1);

void setup() {
  M5.begin();
  SSD1306Display.init();
  SSD1306Display.setFont(&fonts::lgfxJapanGothicP_16);
  SSD1306Display.println("こんにちは世界!!");
  SSD1306Display.setFont(&fonts::FreeMonoBold9pt7b);
  SSD1306Display.println("SSD1306\nGME12864-51");
}

void loop() {
}
```

NanoC6のPort.AのG1、G2はどちらをSDA、SCLに割り当てても使えるみたいですが、Core2などと互換性を持たせるためにG1をSCL、G2をSDAとしました。`M5UnitGLASS2`クラスを初期化する際にピン番号を渡します。

`setup()`内で、先ほどの`M5UnitGLASS2`オブジェクトを初期化すれば`M5.Display`と同じように使用することができます。

AtomS3でも同じコードで動作します。

# 接続

NanoC6とOLEDは以下のように接続しました。Fritzingで描画しました。OLEDパーツは、以下で公開されているものを使用させて戴きました。

- https://github.com/nekocodeX/Fritzing-Parts-SSD1306-0.96in-128x64-I2C-Monochrome-OLED-Display

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111095/c701acc3-be66-670e-e2a0-a37f050d9667.png)

# 参考

- M5Stack NanoC6購入 -- いつもお世話になっているLang-ship様のサイト
    - https://lang-ship.com/blog/work/m5stack-nanoc6/
- ESP32-C3-WROOM-02+SSD1306でM5Stack-Avatarを表示
    - https://qiita.com/McbeEringi/items/02eb900d701ef6dab5c1
    - この方法でも動きますが、直接インスタンスを扱ってシンプルにしてみました
【TypeScript】オブジェクトのキーをキャメルケースに変換した型を生成する方法【camelcase-keys】

## `camelcase-keys`をインストールする

以下のコマンドを実行して `camelcase-keys` をインストールします。

```terminal:ターミナル
npm install camelcase-keys
```

https://github.com/sindresorhus/camelcase-keys

## 型を生成する

以下のように記述することで `camelcase-keys` を使用してキーをキャメルケースに変換した場合のオブジェクトの型を生成できます。

```ts
type SampleObject = {
  snake_case_a: string
  snake_case_b: string
  snake_case_c: {
    snake_case_a: string
    snake_case_b: string
  }
}

type CamelCaseObject = CamelCaseKeys<SampleObject, true>  // { deep: true }を使用する場合に true を記述する
// {
//   snakeCaseA: string;
//   snakeCaseB: string;
//   snakeCaseC: {
//     snakeCaseA: string;
//     snakeCaseB: string;
//   }
// }

```

https://github.com/sindresorhus/camelcase-keys/pull/90
ECSの基本

## ECSとは
ECSはフルマネージドのコンテナオーケストレーションサービス。
コンテナ化されたアプリケーションをより効率的にデプロイ、管理、スケールするのに役立つ。
マルチAZでコンテナを実行することができ、より可用性の高い運用が可能。


https://aws.amazon.com/jp/ecs/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3871776/db50a7a8-2676-f80f-4f80-b6120b6516f5.png)

### 1.タスク定義とは
**タスクを定義するためのJSONテンプレート。**

タスク定義内では以下を設定し、タスクに必要なコンテナを 1 つ以上指定できる。
- Docker のリポジトリとイメージ
- メモリと CPU の要件
- 共有データボリューム
- コンテナどうしのリンク方法

### 2.タスクとは
タスク定義によって定められた、1つ以上のコンテナの集まり。

### 3.サービスとは
1つ以上のタスクから構成されており、実行中のタスクを管理する

### 4.クラスターとは
1つ以上のサービスから構成されており、タスクとサービスの基盤となる。

## 料金
|  | Right align |
|:-----------|:------------|
| EC2起動タイプ | 追加料金なし。<br>アプリケーションの保存や実行のために作成したリソースに対してのみ、料金が発生。|
| Fargate起動タイプ |コンテナ化されたアプリケーションに必要な vCPU とメモリリソースに対する料金が発生。<br>コンテナイメージを取得した時点から、ECS タスク*が終了するまで1 分単位の料金が適用される。 |
p5.js の v1.11.0 で追加された「paletteLerp()」を試す

[p5.js の release のページ](https://github.com/processing/p5.js/releases)で、v1.11.0 のリリース情報を見ていたら「paletteLerp()」というのが気になって、この記事を書きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/10c566d9-82ee-ae02-cf6a-64201217b10b.png)

## paletteLerp()
paletteLerp() の詳細は、以下を見ると情報が書いてあります。

●paletteLerp
　https://p5js.org/reference/p5/paletteLerp/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/654b3b24-a5bb-f4ca-709f-bc272d5edabf.png)

サンプル等は、以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/df14f8c4-c5ac-0f99-a5e9-efd11435c980.png)

以下の部分が要となる部分です。
この部分で、特定の色から別の色へと、間を線形補間した形で変化させる、という設定になるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/82c2e5df-4c6d-2748-c79e-b51e4bedb836.png)

### p5.js Web Editor で試す
p5.js Web Editor で試してみます。

デフォルトで読みこまれるバージョンは、記事執筆時点では「v1.10.0」で、この部分の数字を書きかえても「v1.11.0」は今の時点では使えないようでした。
（そのうち、新しいバージョンも使える状態になるかとは思います）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/39f446b2-2383-d653-3c91-475e19632931.png)

そこで、以下のページに書かれた `https://cdn.jsdelivr.net/npm/p5@1.11.0/lib/p5.min.js` を使って試すことにします。

●Download
　https://p5js.org/download/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/5ae638a4-829d-126b-5627-37296077c338.png)

とりあえず公式サンプルを動作させられました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/84f72e9a-2b6f-a724-f4c0-3608b81ee427.png)

### p5.js Web Editor で試す - その2
次に、サンプルを書きかえたものを試します。

コードは以下のようにしました。

```javascript
function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(
    paletteLerp(
      [
        [[100, 120, 250], 0],
        [[0, 0, 0], 0.1],
        [[250, 220, 220], 0.3],
        [[0, 0, 0], 0.5],
        [[220, 100, 220], 1],
      ],
      (millis() / 20000) % 1
    )
  );
}
```

また、それを動作させた時の様子は、以下の通りです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/BsVcmh6Zgb8?si=27tXGoZ_LDRrxz2i" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

色と変化にかかる時間が、自分で設定したとおりになっていることが確認できました。
【SwiftUI】sheetでモーダル遷移する



## まえがき
この記事はSwift独学者による備忘録です。
万が一誤った記載がある場合は、コメントでご指摘いただけると幸いですm(_ _)m

## 確認環境
XCode Version 15.4
MacOS Sonoma 14.4.1

## Swiftにおける画面遷移について
Swiftの画面遷移には代表的なものが２つあり、そのうちの一つがモーダル遷移(表示)と呼ばれる遷移方法です。
モーダル遷移では、下から画面がスワイプアップで表示されます。
いくつか方法はあるのですが、この記事ではsheetのモディファイアを使用した例を簡単にまとめます。

もう一つはプッシュ遷移と呼ばれるNavigationLinkを用いた遷移方法で、画面が右から左に切り替わります。
プッシュ遷移については[こちらの記事](https://qiita.com/komkom2/items/0bf992f6dc20e2408a1c)に簡単に概要をまとめています。

## コード例

```Swift:ContentView.swift
import SwiftUI

struct ContentView: View {
    @State private var isShowingModal = false

    var body: some View {
        VStack {
            Text("メイン画面です")
                .font(.title)
                .fontWeight(.bold)
                .padding()

            Button(action: {
                isShowingModal = true
            }) {
                Text("モーダルを表示")
                    .padding()
                    .background(Color.purple)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
            .sheet(isPresented: $isShowingModal) {
                ModalView(isShowingModal: $isShowingModal)
            }
        }
    }
}

struct ModalView: View {
    @Binding var isShowingModal: Bool

    var body: some View {
        VStack {
            Text("モーダル画面です")
                .font(.title)
                .fontWeight(.bold)
                .padding()

            Button(action: {
                isShowingModal = false
            }) {
                Text("閉じる")
                    .padding()
                    .background(Color.gray)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
    }
}
```


| メイン画面 | モーダル画面 |
| ---- | ---- |
| <img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805527/342f2dfa-c52d-1e6a-92fa-a87829644802.png"> | <img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805527/00ace6ca-b4fa-f240-ebcc-d75f78e20ebe.png"> |


## あとがき
簡単にsheetでのモーダル遷移(表示)の使用例をまとめました。
今後も捕捉事項があれば随時更新していきます。
Pythonのprint文を使ってためしてみた。(20/30)

前回からの引き続きです。

https://qiita.com/y_haruki/items/3d670f6ce0ab3e4cf115



### 11\. 数値と文字列の組み合わせ
```py
valuation = 1000000000
print("The company's valuation is $" + str(valuation))
```
変数 valuationは半角英数数字が代入されているので、int型に変換されます。
print文の()内に、文字列とint型を一緒に使うとエラーとなります。
変数 valuationを一度str()型に変換してから文字列を表示させています。

:::note info
※変数 valuation内に代入されているデータの確認方法は、type()関数を使います。
使い方は、type(valuation)を実行すると、データの方が確認できます。

str()型:文字列に変換する関数です。
:::

実行結果:
```
The company's valuation is $1000000000
```

### 12\. 小数点以下の桁数を指定
```py
roi = 15.7892
print(f"Return on Investment: {roi:.2f}%")
```
print文の()内に、f"○○○"となっている。f""と指定すると、""内は文字列として
扱うことができる。呼び方は **f文字列（f-strings）** といいます。
また、小文字fを大文字Fに変更して、F"○○○"としても利用できます。

f文字列内に存在してる{}は{}内に変数を代入することによって、変数内の値を
表示されることができます。

roi:.2fの.2fは小数点第二位までを表示して、以下四捨五入の処理をします。
%はそのまま表示されます。

実行結果:
```
Return on Investment: 15.79%
```

### 13\. ゼロ埋め
```
employee_id = 42
print(f"Employee ID: {employee_id:04d}")
```
「:04d」の部分について説明します。
「04」は数字が4桁になるまで、左側に「0」で埋めます。
変数 employee_idに代入されている値は、2桁の「42」なので、
4桁の表示になるよう、左側に残り2桁「0」を埋めます。
「d」は、整数（digit）型にフォーマットします。


実行結果:
```
Employee ID: 0042
```

### 14\. 辞書の内容を出力
```py
stock_prices = {"AAPL": 150.25, "GOOGL": 2800.75, "AMZN": 3300.00}
print(stock_prices)
```
実行結果:
```
{'AAPL': 150.25, 'GOOGL': 2800.75, 'AMZN': 3300.0}
```
辞書型は簡単に説明すると、キーの値を指定すると、キーのペアとなっている値が表示される方です。
ここでキーに当たるのは、'AAPL'、 "GOOGL"、"AMZN"に該当し、
値は、150.25、2800.75、 3300.0です。

これだけだと分かりにくいですが、例えば以下のように、キーを'AAPL'を指定して、
print文を実行させます。
```py
print(stock_prices['AAPL'])
```
実行すると、'AAPL'のペアに設定されている、 150.25が表示されます。

実行結果
```
150.25
```
:::note info
'AAPL'、 "GOOGL"、"AMZN"はそれぞれ、
Apple、Google、Amazonのティッカーシンボルです。
ティッカーシンボルは、
株式市場などで銘柄を識別するために使われる略称のことです。

:::


### 15\. 繰り返し文字列の出力
```py
print("Innovate " * 3)
```
" "内の文字列が指定した数だけ繰り返されます。
この場合、3回繰り返し表示されます。

実行結果:
```
Innovate Innovate Innovate 
```


### 17\. 2進数に変換する
```py
dig = 10
print(f'bin: {dig:b}')
```
実行結果:
```
bin: 1010
```
1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 0 : 2^0
= 8 + 0 + 2 + 0
=10
となり、正しく変換されています。


### 18\. πの出力
```py
import math
print(math.pi)
```
円周率の値を出力します。
実行結果:
```
3.141592653589793
```

### 19\. 科学的表記法での出力
```py
market_cap = 1.5e9
print(f"Market Cap: {market_cap:e}")
```
実行結果:
```
Market Cap: 1.500000e+09
```

「market_cap = 1.5e9」の1.5e9は1.5 * 10^9 を表します。
{market_cap:e} の :e 部分は、数値を指数表記でフォーマットします。


### 20\. ブール値の出力
```py
is_profitable = True
print(f"Is the company profitable? {is_profitable}")
```
実行結果:
```
Is the company profitable? True
```
is_profitable = True　の「True」は真理値を表します。


### 参考：

https://magazine.techacademy.jp/magazine/20606
WordsAPIを使って英単語の詳細情報を取得し、Next.jsのアプリ画面に表示するまで

# 記事内容
WordsAPIを使って英単語の詳細情報を取得し、Next.jsのアプリ画面に表示するまでの備忘録

# WordsAPIについて
WordsAPIと検索すると
https://www.wordsapi.com/
この画面がgoogleのトップ検索で出てくるが、こちらはMashape（現在はRapidAPI）が提供していたAPIにアクセスするためのものです。

MashapeはRapidAPIに取って代わられ、新しいエンドポイントやセキュリティ仕様が導入されたため、新しいプラットフォームを使用することが推奨されているとのこと。

なのでWordsAPIを使用するには、RapidAPIというプラットフォームを通じてアクセスする必要があります。

## WordsAPIのAPIキー取得手順
RapidAPIにサインアップします。
ログインしたら、WordsAPIのページにアクセスします。

"Pricing" タブをクリックして、適切なプランを選択します。一部の利用は無料ですが、プランによっては有料となります。

"Subscribe" ボタンをクリックして、WordsAPIをサブスクライブします。
サブスクリプションが完了したら、RapidAPI ダッシュボードの右上にあるプロファイルアイコンから "My apps" をクリックします。

WordsAPIがリストされているはずです。"Show API Key" をクリックして、APIキーを取得します。
取得したAPIキーをコード中のWORDS_API_KEYの部分に代入してください。これにより、WordsAPIへのリクエストが有効になります。

あとはこういうふうにAPI叩くだけです。
```tsx
const getWordDetails = async () => {
    try {
      const WORDS_API_KEY = process.env.NEXT_PUBLIC_WORDS_API_KEY;
    
      const response = await axios.get(
        `https://wordsapiv1.p.rapidapi.com/words/${englishWord}`,
        {
          headers: {
            "X-RapidAPI-Host": "wordsapiv1.p.rapidapi.com",
            "X-RapidAPI-Key": WORDS_API_KEY,
          },
        }
      );
      console.log("wordsAPI", response);
    } catch (error) {
      console.error("データの取得中にエラーが発生しました:", error);
    }
};
```

以下サイトのサンプルに載っている通り、意味、例文、対義語、類義語などの情報がレスポンスに入ってます。
https://www.wordsapi.com/
基本情報技術者に向けて　Part.4

# パリティチェック
送信するビット列に対して、**パリティビット**と呼ばれる検査用のビットを付加することでデータの誤りを検出すること
**奇数パリティ**の時はビットの中にある『1』の数が奇数になっているかを判断する
逆に、**偶数パリティ**の時はビットの中にある『1』の数が偶数になっているかを判断する
奇数か偶数化を判断するだけなので、どのビットが誤りかなどは判断できない

# 水平垂直パリティチェック
データを２列２行以上で並べた時の水平方向のパリティチェックを**水平パリティ**、垂直方向のパリティチェックを**垂直方向パリティ**という
この二つを合わせて、**水平垂直パリティ**という
このパリティチェックなら１ビットの誤りなら位置を特定できる

# CRC（巡回冗長検査）（Cycle Redundancy Check）
ビット列を特定の式で割り、その余りをチェック用のデータとして付加する方法
送信側は、計算で得た余りを、元のビット列に合わせて送信データとする
受信側は、受け取ったデータに問題が無ければ商の部分が割り切れる数字になっているか判断する
このようにして、商の部分に余りが出るか出ないかで誤りの判断をする

_______________________________________________________________________________________


# TCP/IP(デファクトスタンダード)
**デファクトスタンダード**とは、大勢がその規格を使うようになったので、それを標準にしましょう、という事実上の標準のこと
### イントラネット
企業や組織内などの限られた範囲で利用できるネットワーク環境のこと
いわゆる内部ネットワーク
### インターネット
世界中のコンピュータや情報機器を接続して、情報をやり取りできるようにしたネットワークのこと

## IP(Internet Protocol)
ネットワーク層（３層）に位置している
経路制御を行い、ネットワークからネットワークへとパケットを運んで相手に送り届けるもの
割り振った、**IPアドレス**という番号を割り当てて管理している
コネクションレス型の通信プロトコル

### IPアドレス
個別に識別しているので、一意の番号が割り振られている
IPアドレスはネットワークごとに分かれる**ネットワークアドレス部**と、そのネットワーク内でコンピュータを識別するための**ホストアドレス部**に分かれている
例）192.168.1.3(10進数)
192.168.1・・・ネットワークアドレス部
3・・・ホストアドレス部

### グローバルIPアドレス
インターネットの世界で使用するIPアドレスのこと
世界中で一意であることが保証されていないといけないので、地域ごとのNIC(Network Information Center)で民間の非営利機関によって管理されている
### プライベートIPアドレス
企業内などLANの中で使えるIPアドレス
LANないで重複が無ければ、システム管理者が自由に割り当てて使える


## TCP(Transmission Control Protocol)
ネットワーク層（４層）に位置している
通信相手とのコネクションを確立してから、データを送受信する**コネクション型**の通信プロトコル
パケットの順序や送信エラー時の再送などを制御して、送受信するデータの信頼性を保証する

## UDP(User Datagram Protocol)
ネットワーク層（４層）に位置している
事前に送信相手と接続確認を取ったりせず、一方的にパケットを送り付ける**コネクションレス型**の通信プロトコル
パケットの再送制御などは一切行わないため、信頼性に欠けるが高速

## ブロードキャスト
同一ネットワーク内のすべてのホストに対して、一斉に同じデータを送信することをいう
ホストアドレス部がすべて『1』となるIPアドレスを指定する

## ユニキャスト
ブロードキャストとは対照に、特定の一台にのみ送信すること

## マルチキャスト
決められた範囲内の複数ホストに送信する場合のこと
VSCodeでインデント合わせをしたいだけなのに

# VSCodeでPython書いてたらスペースだけのインデントがどうやっても消される件

なんだろう、私だけだろうか。。。

よくクラスオブジェクトの関数と関数の間をスペースだけのインデントで揃えたくなるんだけど
それやるとどうしてか、違う個所にカーソル移って作業している間に
勝手に消されるんです。
いやなんなん？


```py: 拡張機能によって "@@@" で改行すると自動インデントが入る
class A():
    def __init__(self):
        self.a = 'a' #"@@@"
    def printA(self):
        print(f'a is {self.a}'

```

```py: こんな感じ
class A():
    def __init__(self):
        self.a = 'a'
        # ここまで空白埋めされる。
    def printA(self):
        print(f'a is {self.a}'

```

しかし、自動補完によるインデントを使わず自分でタブキーを使ってインデントをそろえておくと
何度かEnterキー押したり、ほかを編集している間にこの空白埋めが消えるのだ。

```py: 勝手に消える。
class A():
    def __init__(self):
        self.a = 'a'
# こんな感じ
    def printA(self):
        print(f'a is {self.a}'

```

なんなん、すごい気になるんだけど。。。
タブで空白4個入れる設定にはなっているのに何かよくわからん。

せっかくそろえた気でいたのに勝手に消さんでくれ。

とりあえず、タブでインデントそろえるのはやめて、直前の行から改行して自動インデントするか
スペースキー連打したりコピペとかで回避。。

何だったんだ、いったい・・・。
拡張機能の問題か？？
Synology NAS への SSH認証（公開鍵方式）

Gitサーバー構築の前段階として「SSH接続を公開鍵方式に変更」を試みました。
が、見事に一週間ほどハマってしまったので、備忘録的な記録を残しておきます。
　※ 解決した時は、本当にガックリと項垂れました。 ＿|￣|○
 
## 環境について
今回の環境は下記のとおりです。
特に Synology NAS については、製品やDSMバージョンの違いにより
挙動に差があるかもしれません。

<table>
  <caption><b>クライアント側</b></caption>
  <tr>
    <td> エディション </td> <td>Windows 11 Pro</td>
  </tr>
  <tr>
    <td> バージョン </td> <td>23H2</td>
  </tr>
  <tr>
    <td> OSビルド </td> <td>22631.4169</td>
  </tr>
  <tr>
    <td> エクスペリエンス </td> <td>Windows Feature<br> Experience Pack 1000.22700.1034.0</td>
  </tr>
</table>

<table>
  <caption><b>Synology NAS側</b></caption>
  <tr>
    <td> 製品 </td> <td>DiskStation DS420J</td>
  </tr>
  <tr>
    <td> DSM バージョン </td> <td>DSM 7.2.1-69057 Update 5</td>
  </tr>
  <tr>
    <td> uname -a </td> <td>Linux DS420J 4.4.302+ #69057 SMP Fri Jan 12 17:01:55 CST 2024 aarch64 GNU/Linux synology_rtd1296_ds420j</td>
  </tr>
</table>

## 実施した手順
[SSH 経由で root 権限により DSM/SRM にサインインする方法は？](https://kb.synology.com/ja-jp/DSM/tutorial/How_to_login_to_DSM_with_root_permission_via_SSH_Telnet#x_anchor_id5)
[SSH 経由で RSA キー ペアで DSM にサインインする方法](https://kb.synology.com/ja-jp/DSM/tutorial/How_to_log_in_to_DSM_with_key_pairs_as_admin_or_root_permission_via_SSH_on_computers#x_anchor_ida0ce680a9e)

上記 Synology ナレッジセンター の記事を参考に設定を進めました。
ただ、何度繰り返しても「ssh」コマンドで接続した際にパスワードを要求される状況で、ほとほと困ってしまいました。

```powershell
＜イメージ図＞
PS C:\Users\●●●●\.ssh> ssh ●●●●@192.168.0.1 -p 22
●●●●@192.168.0.1's password:
```
.ssh フォルダや 公開鍵ファイルのパーミッションを変更しても挙動が全く変わらず、もう諦める寸前でした。


## 解決した方法
[Synology DS218+ ssh 公開鍵認証で接続する際の注意点](https://hiro20180901.com/2023/02/18/synology-ds218plus-ssh-public-key-authentication/)
たまたま見つけた上記サイトに、下記の記述がありました。
```
「/home/(ユーザー名)/」のフォルダのパーミッションが「755」より厳しいこと
```
これは今まで一度も試していませんでした。
サイト記載内容に従い、以下のようなコマンドを実行してみました。
```
$ pwd
/var/services/homes
$ chmod 755 ●●●●
$ chmod 700 ●●●●/.ssh
$ chmod 600 ●●●●/.ssh/*
```

```powershell
＜イメージ図＞
PS C:\Users\●●●●\.ssh> ssh ●●●●@192.168.0.1 -p 22

Using terminal commands to modify system configs, execute external binary
files, add files, or install unauthorized third-party apps may lead to system
damages or unexpected behavior, or cause data loss. Make sure you are aware of
the consequences of each command and proceed at your own risk.

Warning: Data should only be stored in shared folders. Data stored elsewhere
may be deleted when the system is updated/restarted.

●●●●@DS420J:~$
```

なんということでしょう。
一撃で解決してしまいました。
どうやら、「ユーザーのホームフォルダ」のパーミッション変更を行っていなかったのが原因だったようです。

## あとがき
今どきの NAS 管理ソフトは ほとんどの操作が GUI 化されていて、操作・設定が非常に容易です。
ただ、今回のようなケースもあるので、ベースOS（例えば Linux）の理解は やはり 必要との印象です。

この記事が、同じような事象で苦しんでいる人の参考になれば幸いです。
Google Meetで会議中にマイクの音量が下がる問題の対応

# マイクの音量が勝手に下がる
Web会議をしているとよく声が遠いと指摘され、マイクの音量を確認するといつの間にか下がっている。
マイクのプロパティで100%にしていても
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136449/fa36f002-b625-bf4d-8bb6-81918b3d0409.png)
大きな音や声を出すと下がってしまう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136449/29c25336-786b-cb55-0b07-8b0e98b2da4c.png)


# 対処方法を調べると
対処方法として出てくるのはマイクのプロパティで排他モードの`アプリケーションによりこのデバイスを排他的に制御できるようにする`のチェックボックスを外すというもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136449/d12137f5-5aba-a583-0c35-46e4c6285cc6.png)
でも、これじゃ解決しなかった。

# 解決策
結論としてはEdgeの設定で回避できた（多分chromeでも同じ）。

1. Edgeのアドレスバーに`edge://flags`と入力。
1. フラグを検索できるので`microphone`で検索すると **Allow WebRTC to adjust the input volume.** というのが見つかる。
1. 設定値が`Default`になっているので`Disabled`に変更し、ブラウザを再起動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136449/782129e5-55f1-560b-d43e-8704deff7e5d.png)

これで、EdgeでGoogle Meetに参加してもマイクの音量が勝手に下がることはなくなった。
逆に、音割れするような事の起こる可能性が高くなるのだと思うが、今使っているマイクはサイドトーンが聞けるので問題があれば分かるはず。
今にして思うと音量が低いと指摘を受けて性能の高いマイクを用意したのが逆効果だったのかもしれない。
モブプロ初体験！めっちゃ緊張したけど勉強になった話

# はじめに:sunny:
こんにちは！プログラミングを始めて5ヶ月の新人です。
今回は、仕事で初めてモブプロ（モブプログラミング）をやったので、その感想や学びをまとめます。プログラミング初心者の勉強方法としても役に立つかもです！

## モブプロって何？🤔
モブプロって、簡単に言うと1つのPCをみんなで使ってプログラミングする方法です。イメージとしては、運転席に1人座ってるけど、後ろからみんながナビしているドライブみたいな感じ。

## モブプロの流れ
1つのPCをみんなで共有します。
ドライバー役（キーボードを操作する人）を15〜20分ごとに交代。
他のメンバーはナビゲーターとしてドライバーに指示を出します。
ナビゲーターは「こうした方がいいよ！」とか「ここ間違ってるよ！」ってアドバイスを送ります。
ちなみに私がやった時は、3人で1台のPCを使ってコードを書きました。最初は緊張したけど、みんなで作業するので、分からないところはすぐ聞けるのがモブプロのいいところです。

![モブ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3829046/aa484cb5-09a4-b268-345f-545ff006706a.png)


## やってみた感想！良かった点としんどかった点
###### ★良い点✨
・直接先輩に教えてもらえるので、学びがめちゃくちゃ早い！
分からないこともみんなで解決できるので、進みが早い。
・知識の共有ができて、チーム全体のスキルがアップ。
・集中して作業しやすい。みんなでやってるからサボれないし！
###### ★悪い点🥵
・めっちゃ緊張する…。先輩の前でコードを書くのは心臓バクバクです。
先輩がいると自分の意見が言いづらい時がある。
・じっくり調べたり考えたりする時間が少ない。スピード感が大事なので、ペースが合わない時は焦ります。
・疲れる…。集中しっぱなしなので、作業後は結構ぐったり。

## モブプロをやった感想：超緊張したけど燃えた🔥
モブプロ初体験の感想は、とにかくめちゃくちゃ緊張しました。ドライバー役になった時は、特に先輩が見てるとプレッシャーがすごくて、**間違えたらどうしよう…**って思いました。けど、その分たくさんのフィードバックをもらえたし、自分の成長にもつながった気がします。

初めてのモブプロは超ドキドキだったけど、すごく燃えました！
もっともっと上手くなって、いつか先輩に堂々と意見できるように頑張ろうと思いました。

###### 初学者へのメッセージ
プログラミングを始めて5ヶ月の私でも、なんとかやれました！
最初は緊張するし、間違えもたくさんしましたが、失敗を恐れずにどんどんチャレンジしていくことが大事だと思います。モブプロやペアプロを経験して、もっとプログラミングを楽しみながら学んでいきましょう！

お互いに頑張りましょう！🔥

## もっと詳しく知りたい方へ
こちらはペアプロについても書いてます、ペアプロについても知りたい方は、こちらのブログで書いていますので、よければ覗いてみてください😊 
[ブログはこちら](https://programcube.blogspot.com/2024/10/blog-post.html#more)
ゼロからのOS自作入門　EDK2 build bad interpreter~みたいなエラーについて

pyenvでpythonのバージョン管理をしていると、wsl2(Ubuntu 20.04.6 LTS)環境でEDK2ビルドエラーが出たので一応解決策を残しておきます。

## エラー内容
![スクリーンショット 2024-10-02 222407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3572216/f9cb9ce8-b979-10fe-44db-fa576b143a70.png)

~/edk2$ build に対して bad interpreter: No such file or directoryというエラー

## エラー原因
wsl2内の環境変数　$PYTHON_COMMAND　が　windows上のpyenvでバージョン管理しているpythonインタプリタのディレクトリになっていること。
書き換えてあげれば動きます。
$ export PYTHON_COMMAND=/usr/bin/python3.8 
一応pythonバージョンが異なるかもしれないので確認してください。

pyenvでwsl2環境にもカーネルが共有されるのは、ちょっと面白い。もしかしたらpyenv globalを指定してたからかも？
sslハンド

質問
上記の続きですが、送信元のjavaとUbuntuの条件は以下の通りです。何かsslハンドシェイクに影響を与える可能性はありますか？

■java側の設定
java11
sun.security.ssl.allowLegacyHelloMessages=false
sun.security.ssl.allowUnsafeRenegotiation=false

■ubntu側の設定
openssl 3.0.14
kong ver3.4.2

解答
提供されたJavaとUbuntuの設定条件に基づき、SSLハンドシェイクに影響を与える可能性のある要因を以下に詳述します。

### Java側の設定
- **Javaバージョン：Java 11**
  - Java 11は、TLS 1.2およびTLS 1.3をデフォルトでサポートしています。これにより、古いバージョンのTLS（例えば、TLS 1.0や1.1）はデフォルトで無効化されており、これ自体は問題ではありません。ただし、サーバー側でTLS 1.2や1.3がサポートされていないと、接続が失敗します。

- **`sun.security.ssl.allowLegacyHelloMessages=false`**
  - この設定は、TLSハンドシェイクの初期メッセージで使用される古い形式の「ClientHello」メッセージを許可しないという設定です。TLS 1.2以降のプロトコルでは、通常「レガシーハンドシェイク」は必要ありませんが、サーバーが古いプロトコルや非標準の実装をしている場合、これが原因でハンドシェイクが失敗する可能性があります。
  
  しかし、Ubuntu側のOpenSSL 3.0は新しいTLS仕様に準拠しているため、**この設定が直接問題を引き起こす可能性は低い**です。

- **`sun.security.ssl.allowUnsafeRenegotiation=false`**
  - この設定は、SSL/TLS接続の再ネゴシエーションにおける「安全でない再ネゴシエーション」を許可しない設定です。再ネゴシエーションは、通信中に暗号スイートなどを再交渉するプロセスですが、この設定によって安全性の高い再ネゴシエーションのみが許可されます。最近のTLS実装では、再ネゴシエーションの脆弱性に対処するため、この機能はほとんど無効化されています。

  OpenSSL 3.0は安全な再ネゴシエーションをサポートしているため、**この設定が問題を引き起こす可能性も低い**です。

### Ubuntu側の設定
- **OpenSSL 3.0.14**
  - OpenSSL 3.0はTLS 1.3とTLS 1.2をサポートしており、セキュリティやパフォーマンスが向上した最新のバージョンです。TLS 1.2以降のプロトコルに対応しており、セキュアな通信が可能です。Java 11と互換性のある暗号スイートをサポートしているため、大きな問題は想定されません。

  ただし、暗号スイートの設定が適切でない場合、ハンドシェイクに失敗する可能性があります。たとえば、サーバー側（Kongの設定やNginxの設定）でサポートする暗号スイートがJava側のTLSクライアントと一致しない場合、ハンドシェイクに失敗することがあります。Kongの設定ファイルやNginxの設定を確認し、暗号スイートがJava側と互換性があるか確認してください。

- **Kong ver3.4.2**
  - KongはNginxをベースにしたAPI Gatewayであり、TLSの設定は主にNginxに依存します。Kongのデフォルト設定では、モダンなTLSバージョンや暗号スイートがサポートされていますが、設定によっては特定のTLSバージョンや暗号スイートに制限がかかっている場合があります。

  Nginxの設定ファイル（`nginx.conf`や`kong.conf`）に記載された以下の項目を確認してください：
  - **`ssl_protocols`** が TLS 1.2およびTLS 1.3をサポートしているか。
  - **`ssl_ciphers`** がJava側と互換性のある暗号スイート（例えば、AES、ECDHEなど）を含んでいるか。

### SSLハンドシェイクに影響する可能性のあるポイント

#### 1. **TLSバージョンの不一致**
   - **Java 11**ではTLS 1.2および1.3がサポートされていますが、Kong（Nginx）がTLS 1.3のみを許可していると、ハンドシェイクに失敗する可能性があります。**`ssl_protocols`**の設定を確認し、両方のバージョンがサポートされているかを確認してください。
   
   例：
   ```bash
   ssl_protocols TLSv1.2 TLSv1.3;
   ```

#### 2. **暗号スイートの不一致**
   - Java 11でサポートされている暗号スイートが、KongまたはNginx側で許可されていない場合、ハンドシェイクに失敗します。NginxやKongの**`ssl_ciphers`**の設定を確認し、Java側と互換性がある暗号スイートがサポートされているか確認します。

   例：
   ```bash
   ssl_ciphers HIGH:!aNULL:!MD5;
   ```

#### 3. **証明書の問題**
   - サーバー側（Ubuntu/Kong）のSSL証明書に問題がある場合、例えば、自己署名証明書や証明書チェーンの不備がある場合、Javaクライアントが証明書を受け入れずにハンドシェイクが失敗します。
   - サーバー証明書がJavaクライアントで信頼されているか、証明書チェーンが正しく設定されているかを確認してください。

#### 4. **ファイアウォールやネットワークの問題**
   - SSLハンドシェイクそのものに影響を与えるものではありませんが、Ubuntuのファイアウォール（`ufw`や`iptables`）がポート443などをブロックしている場合、接続が拒否されることがあります。ファイアウォール設定も併せて確認してください。

### まとめ
Java 11とUbuntu（Kong & OpenSSL 3.0.14）間でのSSLハンドシェイクにおいて、以下の項目が特に影響を与える可能性があります：
1. **TLSバージョンの不一致**：Nginx/Kongの`ssl_protocols`がJava側と一致しているか。
2. **暗号スイートの不一致**：`ssl_ciphers`の設定が互換性のあるものか確認。
3. **証明書の問題**：サーバー証明書が正しく設定され、クライアント（Java）で信頼されているか。
4. **ファイアウォールやネットワーク**：適切なポートが開いているか。

これらの項目を確認することで、SSLハンドシェイクの問題を解決できる可能性があります。
[Python / Mac] PyOpenGL-accelerate の pip install に失敗する時の対策

# 環境

item|version など
--|--
OS|MacOS Ventura 13.6
CPU|Apple M2
Python|3.10

# 1. エラー発生時の状況

## 1-1. requirements.txt からインストールしようとして失敗

```:requirements.txt
PyOpenGL==3.1.5
PyOpenGL-accelerate==3.1.5
```

```zsh
% pip install -r requirements.txt
```

`PyOpenGL-accelerate` のインストールに失敗した。

## 1-2. 直接 pip インストールしようとして失敗

```zsh
% pip install PyOpenGL-accelerate
```

失敗したのだけど、以下のようなエラー文が気になった。

```bash
src/numpy_formathandler.pyx:22:42: 'Py_intptr_t' is not a type identifier
```

# 2. 解決策

`'Py_intptr_t' is not a type identifier` の解決策は以下の記事に記されていた。

https://github.com/mcfletch/pyopengl/issues/118#issuecomment-2351365603

以下のように requirements.txt を修正して、

```:requirements.txt
# PyOpenGL==3.1.5
# PyOpenGL-accelerate==3.1.5
PyOpenGL @ git+https://github.com/mcfletch/pyopengl.git@release-3.1.8#egg=PyOpenGL
PyOpenGL_accelerate @ git+https://github.com/mcfletch/pyopengl.git@release-3.1.8#egg=PyOpenGL_accelerate&subdirectory=accelerate
```

再度 requirements.txt 経由で install したところ、 install build に成功した。

```zsh
% pip install -r requirements.txt

...

Building wheels for collected packages: PyOpenGL, PyOpenGL_accelerate
  Building wheel for PyOpenGL (pyproject.toml) ... done
  Created wheel for PyOpenGL: filename=PyOpenGL-3.1.7-py3-none-any.whl size=2416925 sha256=799e60055ec527f35e8b8034be4be6d5df5555b52d7e454a58f8e333bd4cbc45
  Stored in directory: /private/var/folders/7r/d08538nj63ncgxpk9jwhpxsc0000gp/T/pip-ephem-wheel-cache-qinpz9cd/wheels/31/bb/6f/04b0198944916ae4cf032a6516ab8ed05dbf57a4f7def5ab40
  Building wheel for PyOpenGL_accelerate (pyproject.toml) ... done
  Created wheel for PyOpenGL_accelerate: filename=PyOpenGL_accelerate-3.1.7-cp310-cp310-macosx_13_0_arm64.whl size=442786 sha256=dd68ae1bb9376176b59f03b1df5afc5e69cfaf6e31a65548858683f09cf8fea0
  Stored in directory: /private/var/folders/7r/d08538nj63ncgxpk9jwhpxsc0000gp/T/pip-ephem-wheel-cache-qinpz9cd/wheels/a5/37/11/3ff3b1dc61f82d1a206303cd3aeda375c65dac6d7334f6b62e
Successfully built PyOpenGL PyOpenGL_accelerate

...
```
Soracom LTE-M Button の記事についてのお知らせ

2024/10/02 株式会社ソラコムさんから以下のようなアナウンスがありました。

https://soracom.com/ja/news/20241002-1

このアナウンスにより、Soracom LTE-M Buttonについては、日本国内では購入および利用できないことになりましたので、以下の3つの記事については削除しました。

- Soracom LTE-M Buttonを買ってみた -開封の儀-
-  Soracom LTE-M Buttonを買ってみた -スペック比較と通信する-
-  Soracom LTE-M Buttonを押して、Slackにメッセージを送るのを作ってみた(今後の布石)

Soracom LTE-M Button自体は、海外では利用できるデバイスですので、もし海外で使われる予定がある方は、以下の記事を参考にしていただければと思います。

https://kizawa.info/escape-meeting-button

https://zenn.dev/showm001/articles/2023-11-14-01

なお、アナウンスにもありますが、
日本国内で発売されている
- 「SORACOM LTE-M Button powered by AWS」(※)
- 「SORACOM LTE-M Button for Enterprise」
- 「SORACOM LTE-M Button Plus」
について問題なく使えますので、ご安心ください。

※ SORACOM LTE-M Button powered by AWS については、AWS IoT 1-Clickのサービス終了に伴い、SORACOM LTE-M Button for Enterpriseへの移行がアナウンスされていますので、お待ちの方は移行をお勧めします。
方法は拙筆ですが、以下の記事をご覧いただければと！
https://qiita.com/keni_w/items/c48191d20d094f77d1ad

-------

国内で発売されているボタンとは大きさとか挙動とか違う面白いボタンだっただけに残念です。
ソラコムさんにはまた面白いデバイス出していただけるのを期待しています。
投稿 94 サブネットマスク他 2024/10/02

本日の勉強時間　4H

▪️IPアドレス：
ネットワークに繋がっている機器（スマホやPCなど）に割り振られた番号　TCP/IPを使う際、ホストを識別するための値　32bit


▪️サブネットマスク：
ネットワーク部分のビットが1、ホストアドレス部のビットが0になっているビット列
同じLAN（同じネットワーク）にいる相手なのかどうかを判断するために利用される


▪️ネットワークアドレス：
ネットワーク自体を表すアドレスでホスト部がすべて0

▪️ブロードキャストアドレス：
あるネットワークに接続されている全てのホストを表すアドレス　ホスト部がすべて1
Goのポインタ

Goの学習を行った記録としてこの記事に残す。
この記事では Goのポインタについてまとめていく。

## ポインタとは
ポインタとは、ある値が保存されているメモリ内の位置を表す変数。
変数の型が異なれば保存に使うメモリの量は異なるが、ポインタはどのような型を参照していてもサイズが同じ。メモリ内のデータが保存されている位置を（アドレス）を示す値だから。

ポインタのゼロ値はnil

nilはスライス、マップ、関数のゼロ値でもあるが、これらの型は全てポインタで実装されているから。
「＆」はアドレス演算子で、変数の前につけるとその変数のアドレスを返す。返された値はポインタ型の値となる。
「＊」は間接参照のための演算子。ポインタ型の変数の前につけると、そのポインタが参照するアドレスに保存されている値を返す。デリファレンスという。
nilのポインタを参照しようとするとパニックになるので必要ならnilかどうかチェックする必要がある。

ポインタ型の変数をvarで宣言するには、次のようにそのポインタが指す領域に保存される値の型の前に「＊」をつける。
```Go:ポインタとは
x := 10
var pointerToX *int
pointerToX = &x
```

構造体については、構造体リテラルの前に「＆」をつけてポインタのインスタンスを作る。
基本型のリテラル（数値、真偽、文字）や定数の前に「＆」をつけることはできない。
基本型へのポインタが必要な場合は、まず基本型の変数を宣言し、それから参照するポインタ変数を宣言する。
```Go:ポインタ（基本型）
var y string
z := &y
```

## ポインタはイミュータブルの印
イミュータブルな型はバグが起こりにくく、理解しやすく、変更がしやすい。

逆にミュータブルであるとプログラムが何をしているか理解しにくくなり、動作の保証をするのが困難になる。

Goは値渡しの言語なので、関数に渡される値はコピー。基本型、構造体、配列といった非ポインタ型では、関数は元のデータを変更できない。呼び出される側の関数が持っているのは元データのコピーなので、元データがイミュータブルであることは保証されている。

それに対し、関数にポインタを渡すと、関数が受け取るのはポインタのコピーなので、同じデータを参照する。なので呼び出された関数で元のデータが変更可能になる。ぜ

補足として、関数にポインタとしてnilを渡した場合、その値をnil以外に変更はできない。ポインタに値を代入し直せるのは、すでに値が入っている場合に限る。

もうひとつ、ポインタ型の引数に代入された値が関数を終了してもそのままにしたい場合、ポインタをデリファレンスして値を設定しなければならない。

ポインタがコピーされて渡されているので、渡されたポインタを変えてもコピーを変えているのであり、元のデータを変えているわけではない。でリファレンスすれば、元のポインタとコピーのポインタの両方が参照しているメモリアドレスに値を入れることができる。


## ポインタは最後の手段
変数を変更するのにポインタ引数を使わなくてはならないのは関数がインターフェースを受け取るときだけ。JSONを扱う場合にこのパターンが出現する。

関数から値を返す場合は、ポインタではなく値として返すべき。

パフォーマンスの観点で、構造体のサイズが大きくなると関数の引数や、戻り値で値を渡すより、ポインタを使った方がパフォーマンスは良くなることがある。

関数が何メガバイトものデータを扱うのであれば、データがイミュータブルでも使用の検討をするのも手。
Deviseを利用した会員機能の実装手順

初めまして、これから自分が学習した内容をまとめていこうと思い、投稿を始めました。
まず最初は、Deviseを利用した会員機能の実装です。

# １.deviseをインストールする
Gemfileに`devise`を追加し、インストールします。
```:Gemfile
gem 'devise'
```
次に以下のコマンドで `bundle install`を実行します。
```ruby:bash
bundle install
```
# 2.deviseのセットアップ
`devise`をrailsアプリにセットアップします。
```:bash
rails g devise:install
```
＊g はgenerateのg です。
このコマンドは、deviseの設定ファイルを作成し、初期設定を行います。
# 3.Flashメッセージの設定
`devise`では、フラッシュメッセージがログインやサインアップの成功/失敗時に表示されます。以下をの記述をapplication.html.erbに追加します。
```erb:app/views/layout/application.html.erb
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
```
# 4.ユーザモデルを作成
`devise`を使って、ユーザモデルを作成します。例えば、`User`モデルを作成する場合は次のコマンドを実行します
```:bash
rails g devise User
```
これにより、`User`モデルと`devise`関連のマイグレーションファイルが作成されます。
# 5.マイグレーションの実行
作成されたマイグレーションファイルをデータベースに反映させます。
```:bash
rails db:migrate
```
# 6.ルーティングの設定
`routes.rb`ファイルに`devise`のルーティングを設定します。この設定は`devise`が自動で行いますが、確認のために以下の記述があるか確認しておきましょう。
```ruby:routes.rb
devise_for :users
```
# 7.ビューのカスタマイズ（必要に応じて）
デフォルトの`devise`のビューを編集したい場合は、以下のコマンドを生成します。
```:bash
rails g devise:views
```
これにより、`app/views/devise/`以下に各種フォーム（ログイン、サインアップ、パスワードリセットなど）のテンプレートが生成され、カスタマイズできるようになります。
# 8.　ログイン必須ページの設定
コントローラーで認証が必要なアクションを指定するには、`before_action :authenticate_user!`を使用します。
```ruby:ruby
class SomeController < ApplicationController
  before_action :authenticate_user!, only: [:show, :edit]
  
  # 他のアクション
end
```
# 9.サインアップやログインの確認
アプリケーションを起動して、以下のパスで`devise`が提供するサインアップやログインページが機能しているかを確認します。

・`/users/sign_in`（ログイン）
・`/users/sign_up`（サインアップ）
# 10.その他の設定やカスタマイズ
ストロングパラメーター：サインアップ時に追加の情報（名前やプロフィールなど）を許可したい場合、`ApplicationController`にストロングパラメーターを設定します。
```ruby:ruby
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end
```
これにより、`name`というフィールドがサインアップフォームで許可されます。
cp932のMySQLが欲しいときのdocker-compose


```
+-- client-character-set.cnf
+-- docker-compose.yml
+-- docker-entrypoint-initdb.d
    +-- 01_shows_status.sh  // docker-entry_point-initdb.d実行時の文字コード確認用
    +-- 02_mysql_native_password.sql   // native_passwordパスワード追加
    +-- 03_create_db.sql    // cp932でDBを作り直す
    +-- 04_user_data.sql    // cp932文字コードで保存
```

```yml:docker-compose.yml
services:
  mysql:
    image: mysql:8.4.2
    container_name: mysql
    command: --mysql-native-password=ON --character-set-server=cp932 --collation-server=cp932_japanese_ci
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: testdb
    volumes:
      - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
      - ./client-character-set.cnf:/var/lib/mysql/.my.cnf
      - ./client-character-set.cnf:/root/.my.cnf
```

```ini:client-character-set.cnf
[client]
default-character-set=cp932
```

```sh:01_shows_status.sh
echo $HOME
mysql -uroot -ppassword -e 'status'
```

```sql:02_mysql_native_password.sql
ALTER USER `root`@`%` IDENTIFIED WITH mysql_native_password BY 'password';
ALTER USER root@localhost IDENTIFIED WITH mysql_native_password BY 'password';
```

```sql:03_create_db.sql
DROP DATABASE testdb;
CREATE DATABASE testdb CHARACTER SET cp932 COLLATE cp932_japanese_ci;
```

```sql:04_user_data.sql　(CP932)
CREATE TABLE user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) CHARACTER SET cp932 COLLATE cp932_japanese_ci,
    email VARCHAR(100) CHARACTER SET cp932 COLLATE cp932_japanese_ci
);
INSERT INTO user (name, email) VALUES ('山田太郎', 'taro@example.com');
INSERT INTO user (name, email) VALUES ('鈴木一郎', 'ichiro@example.com');
```

```sh
$ docker --version
Docker version 27.1.1, build 6312585
$ docker compose up -d
$ docker compose exec mysql mysql -uroot -ppassword -e 'status'
Server charcterset:    cp932
Db     charcterset:    cp932
Client charcterset:    cp932
Conn   charcterset:    cp932
$ docker compose exec mysql mysql -uroot -ppassword testdb -e 'select * from user' | iconv -f cp932
id     name      email
1      山田太郎   taro@example.com
2      鈴木一郎   ichiro@example.com
```

## ポイント

* MYSQL_DATABASEに指定していたtestdbを一度Dropし、CREATE DATABASEすることで文字コードを指定のものとして再作成
* docker-entrypoint-initdb.dで実行される際に読み込むmy.cnfは/var/lib/mysql/.my.cnf
* 完了後のmysql cliで読み込まれるmy.cnfは/root/.my.cnfになる
Mysql(RDS)でホスト名を変更しようとしたら諸問題が発生した


# 問題１：DROP USERで「the user specified as a definer」というエラーが発生した

## 背景

下記のようにホスト名を指定したユーザーを作成した後、ホスト名を指定していないユーザーをDROP USERしようとした。

```
username@% <- DROP USERの対象
username@192.168.1.1
```

## 原因
既存のviewのdefinerに指定されていたため、該当ユーザーを削除できなかった
  > MySQL 8.0.22 では、削除するアカウントの名前がストアドオブジェクトの DEFINER 属性として指定されている場合、DROP USER はエラーで失敗します。

https://dev.mysql.com/doc/refman/8.0/ja/drop-user.html

## 対応策
削除しようとしているユーザーがviewのdefinerに定義されていることが原因であるので、definerを変更することで回避できます(?)

> 別の定義者でオブジェクトを再定義するには、ALTER EVENT または ALTER VIEW を使用して、イベントおよびビューの DEFINER アカウントを直接変更できます。

https://dev.mysql.com/doc/refman/8.0/ja/stored-objects-security.html

# 問題２：マイグレーション時に「」というエラーが発生した

## こんな時系列
1. マイグレーション専用のMysqlユーザーを使用し、スキーマを渡すことで機械的にマイグレーションができるようにしていた
1. viewのdefinerに指定されているユーザーのホスト名指定verユーザーを作成した
1. マイグレーション実行時にエラーが発生

## 原因
ログイン時にはより具体的なユーザーがログイン対象となるため、作成ユーザーと変更ユーザーが異なりマイグレーション時に失敗した。

```
mysql > SELECT Host, User FROM mysql.user;
+-------------+------------------+
| Host        | User             |
+-------------+------------------+
| %           | migrationer      |
| 192.168.1.1 | migrationer      |
+-------------+------------------+

definer...migrationer@%
ログインユーザー...migrationer@192.168.1.1
```
https://dev.mysql.com/doc/refman/8.0/ja/connection-access.html

## 対応策
問題１と同様に、viewのdefinerを変更することで回避できます(?)

# たぶん最適解
RDSではMysqlのホスト名を指定するのはやめて、おとなしくセキュリティグループで管理しよう
ラズパイを使ってDiscordBotの常設

<!-- ラズパイを使ってDiscordBotの常設 -->

## はじめに

この記事は以下の記事の続きなので、先に読んでおくことをおすすめします。

[Dockerを使ってDiscord Botを常設する #docker-compose - Qiita](https://qiita.com/Q_Udon/items/35cf098bdec0a6a2204a)

ここでは、実際にDiscord Botを常設する場所として、ラズパイを使うこととします。

## 準備

まず、お手持ちのラズパイにOSをインストールしてください。インストール方法などは割愛しますが、Raspberry Pi OSを使うこととします。

次に、ラズパイにログインし、以下のコマンドでDockerをインストールします。

```bash
curl -sSL https://get.docker.com | sh
```

これによって、Dockerがインストールされます。

次に、dockerグループに入っておきましょう。これによって、sudoを使わずにdockerコマンドを使えるようになります。

```bash
sudo usermod -aG docker [Username]
```

[Username]には、自分のユーザ名を入れてください。

そして、任意のディレクトリに、上記の記事にあるような構成を立てます。

```bash
.
├── .env
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
└── bot
    └── main.py
```

この構成を作る方法としては、FTPソフトを使ってファイルをアップロードする方法や、ラズパイ上で直接ファイルを作成する方法、gitを用いてリモートからクローンしてくるなどがあります。

Docker関連ファイルの構成は上記の記事に書いてあるので割愛します。

最後に、イメージをビルドして、コンテナを立て、Botを起動します。

```bash
docker-compose build
docker-compose up
```

これによって、Botが起動しました。以下のコマンドで動作確認ができます。

```bash
docker ps -a
```

## おわりに

これによって、ラズパイ上でDiscord Botを常設することができました。これで、ラズパイが止まるなどのトラブルがなければいつでもDiscord Botを使うことができます。

ラズパイをLANにつないでいれば、特にポート開放などの設定は必要ないようでした。

Discord Botは処理が軽いことが多いので、とりあえずラズパイを何かに使ってみたい、というときにはおすすめです。
【Qiita歴半年】獲得した「知識」と「いいね数」

# はじめに
こんにちは、Zukki2です。
Qiitaを始めて約半年が経ちました。この半年で得た知識・スキルをまとめることで、自分の成長を可視化するために本記事を執筆しています。

また、半年間で頂いた「いいね」や「ストック」「Contributions」の数も載せています。
Qiitaでアウトプットしている皆さんはお分かりだと思いますが、時間をかけて書いた記事でも一つも「いいね」が付かないこともあります。

半年間のQiitaでどれくらい反応をもらえたかを載せることで、これを読んでくれている皆さんの参考に少しでもなればと思っています。

# 簡単な自己紹介
### Qiitaモチベーション
- 完全独学でWEBアプリケーションを開発を行っており、先人の知恵を貰いたい
- 現業で生成AI活用のプロジェクトを推進しており、最低限のAI知識を身につけたい

### 経歴
早慶理工学部卒業後、外資系コンサルファームに就職。現在は、事業会社にてDXやデータマーケティングのプロジェクトを推進中。

### 元々あったスキル（2024年4月時点）
- 言語：Python、Java
- インフラ：
apache tomcatで一度だけ阿部寛のサイトみたいなWEBページを作った経験のみ。AWSは一度だけ触ってみて意味が分からず諦めたレベル。
- プロマネ：
システム開発経験はないもののウォーターフォール、アジャイルのPMは座学レベルでは理解している

# 半年間の成果
### 身についたスキル（2024年10月時点）
- 言語：React, Flask
- インフラ：aws, vercel, render, heroku, pinecone, github
- プロマネ：MVP開発やCPF実践

# 獲得した「いいね数」など
### 主要指標
「自分がつまづいた」かつ「どこにもまとまっていない」情報を中心にアウトプットしてきました。いいねやストックしてくれた方には、少しは役に立ったのかなと嬉しく思います。
- 投稿：8
- Contributions：64
- いいね：30
- ストック：51
- views：14,500
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/e534e789-d6be-4855-d691-4cfdb239ed01.png)

# 最も反応頂いた記事
「【15分】ベクトルデータベース&RAG爆速入門」という記事が、15いいねで最も反応いただけました。
RAGやベクトルデータベースについては、気になる方が多かったのだと思います。
私もかなり調べた上で、本記事を書いているため反応いただけて嬉しいです。

https://qiita.com/zukki2/items/80ad06781ce33f526373

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/876d9e95-336d-b2d2-db73-63c99dee30ec.png)

### Google Analytics
Qiita開始時に登録したGoogle Analyticsによると、イベント数は3.2万回でした。記事を投稿した分だけ積み上がっていくことが分かります。色々な方に見てもらえるのは嬉しいですし、自分の財産になっていると実感できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/a5ef6aec-44c3-8bdf-f410-4d18bdf6bacf.png)

# 今後に向けて
今後も少なくとも月１ペースでアウトプットしていこうと思います。
応援してくれる方、少しでも参考になった方、私と同じような境遇の方がいたら、是非「いいね」頂けると今後もQiitaを続けていく励みになります！
Kali LinuxのVMインストール

# VMをダウンロード
https://www.kali.org/get-kali/#kali-installer-images
からVirtualBoxのイメージをダウンロードする。
# イメージの展開
イメージを右クリックして、「すべて展開」を選択する。
# 仮想マシンを作成
展開したフォルダを仮想マシンのフォルダに移動する。
C:\Users\<ユーザー名>\VirtualBox VMs
VirtualBoxの追加をクリックする。
移動した仮想マシンファイルを選択する。
# アップデート
Kali Linuxを起動し、ユーザー名：kali、パスワード：kaliでログインする。
ルートのターミナルを起動し、以下のコマンドを実行する。
```
apt update
apt upgrade
```
# ネットワーク設定
以下のネットワーク設定を行う。
```
vim /etc/network/interfaces
```
以下を追加する。
```
allow-hotplug eth0
iface eth0 inet dhcp

allow-hotplug eth1
iface eth1 inet static
address <IPアドレス>
netmask 255.255.255.0
```
# キーボード設定
日本語キーボードに設定する。
```
dpkg-reconfigure keyboad-configuration
```
Generic 105-key PCを選択する。
Japaneseを選択する。
The Default for keyboard layoutを選択する。
No compose keyを選択する。
Noを選択する。
# タイムゾーンを設定
タイムゾーンを日本にする。
```
dpkg-reconfigure tzdata
```
Asiaを選択する。
Tokyoを選択する。

# 再起動
シャットダウンする。
VirtualBoxの設定をクリックする。
ネットワークを選択する。
アダプター1をNATにする。
アダプター2を有効化して、ホストオンリーアダプターに設定する。
ホストオンリーアダプターがない場合は、ツールからホストオンリーアダプターをDHCP無しで作成する。

# 追記
一時的にApacheを有効にする場合
```
service apache2 restart
```
一時的にOpenssh Serverを有効にする場合
```
service ssh restart
```