OmniAICreator/Qiita-1.07M huggingface dataset:
wslでelixir その98

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題、やってみた。

# 練習問題
Livebookでtensorflow.jsでsinを学習せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0325e0c4-c067-7eb3-24f1-efe0eb5e61d4.png)

# サンプルコード

```
defmodule KinoTF.Sin do
	use Kino.JS
	def new(html) do
	Kino.JS.new(__MODULE__, html)
	end
	asset "main.js" do
	"""
	import "https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js";
	function draw(ctx, data, n) {
		var hc = n * 20 + 100;
		ctx.strokeStyle = "#f00";
		ctx.lineWidth = 1;
		ctx.moveTo(0, hc);
		for (var i = 1; i < 200; i++)
		{
			ctx.lineTo(i, hc - data[i] * 30);
		}
		ctx.stroke();
	}
	export function init(ctx, html) {
		const canvas = document.createElement("canvas");
		canvas.style.width = "400px";
		canvas.style.height = "400px";
		ctx.root.appendChild(canvas);
		const ctx2 = canvas.getContext('2d');
		ctx2.clearRect(0, 0, canvas.width, canvas.height);
		ctx2.beginPath();
		tf.setBackend('cpu');
		const buffer = tf.buffer([200, 1]);
		const buffer2 = tf.buffer([200, 1]);
		var b = [];
		for (var i = 0; i < 200; i++)
		{
			var x = i / 30.0;
			var y = Math.sin(x);
			b.push(y);
			buffer.set(x, i, 0);
			buffer2.set(y, i, 0);
		}
		
		const model = tf.sequential();
		eval(html);
		const xs = buffer.toTensor();
		const ys = buffer2.toTensor();
		model.fit(xs, ys, {
			batchSize: 200,
			epochs: 6000
		}).then((d) => {
			var str = "loss = ";
			str += d.history.loss[0];
			alert(str);
			var p = [];
			for (i = 0; i < 200; i++)
			{
				var x = i / 30.0;
				var pre = model.predict(tf.tensor2d([[x]], [1, 1]));
				var f = pre.dataSync();
				p.push(f);
			}
			draw(ctx2, p, 1);
		});
    draw(ctx2, b, 0);
	}
	"""
	end
end

KinoTF.Sin.new("""
model.add(tf.layers.dense({
	units: 40,
	activation: 'tanh',
	inputShape: [1]
}));
model.add(tf.layers.dense({
	units: 1,
	activation: 'tanh'
}));
model.compile({
	optimizer: 'adam',
	loss: 'meanSquaredError'
});
""")

```


以上。
いつも忘れてしまうpyenv+poetry 環境の新規プロジェクト作成

## 背景
pyenv+poetry環境の新規プロジェクト立ち上げ手順を毎回調べては忘れてしまうので、備忘に記載

## 前提
- pyenv+poetry環境がすでに立っている
- 新しくpython3.11系が使える仮想環境を立てたい

## 手順
- pyenvの設定
    - 欲しいバージョンのPythonが使えるか確認
        ```bash
        $ pyenv versions
           system
         * 3.8.13 (set by /home/username/.pyenv/version)
        ```

    - 残念ながら3.11系のpythonが入っていなかったためインストール
        ```bash
        $ pyenv install 3.11
        ```
    - local(=このプロジェクトフォルダ)のpythonバージョンを3.11に設定
        ```bash
        $ pyenv local 3.11
        ```

    - 確認してみるとpythonのバージョンが変わっている
        ```bash
        $ pyenv versions
           system
           3.8.13
           3.11.1
         * 3.11.2 (set by /path/to/project_folder/.python-version)
        ```
- poetryの設定
    - projectの初期化→pyproject.tomlが作成されていればOK
        ```bash
        $ poetry init
        ```
    - プロジェクトフォルダ内で仮想環境を作る(=プロジェクトのディレクトリに`/.venv`を作成)
        ```bash
        $ poetry config virtualenvs.in-project true --local
        ```
    - poetryが使うpythonのバージョンを指定
        ```bash
        $ poetry env use 3.11
        ```
    - パッケージの初期インストール
        ```bash
        $ poetry install
        ```
    - 仮想環境のactivate
        ```bash
        $ poetry shell
        ```
    
## デバッグ例

- `poetry env use`で以下のようなエラーが出ることがある
    ```
    $ poetry env use 3.11
      The specified Python version (3.11.6) is not supported by the project (3.11).
    ```
    - こういう時は`pyproject.toml`の中の`tool.poetry.independencies`内のpythonバージョン指定が厳しすぎることがある（以下例）
        ```toml
        [tool.poetry.dependencies]
        python = "3.11"            
        ```
    - これを少し緩めると良い
        ```toml
        [tool.poetry.dependencies]
        python = "^3.11"
        ```

- `poetry env use`でプロジェクトフォルダ内に仮想環境を作ってくれないことがある
    ``` bash
    $ poetry env use 3.11
    Using virtualenv: /Users/username/Library/Caches/pypoetry/virtualenvs/project-name-py3.xx
    ```
    - `poetry config virtualenvs.in-project true --local`の設定をする前に仮想環境をactivateしてしまっている(=poetry shellしている)のが原因（poetryは仮想環境をデフォルトで`~/Library/Caches/pypoetry/virtualenvs/`に仮想環境を作る）
    - 一度仮想環境を削除
        ```bash
        $ poetry env list
        project-name-py3.xx (Activated)
        $ poetry env remove project-name-py3.xx
        Deleted virtualenv: /Users/username/Library/Caches/pypoetry/virtualenvs/project-name-py3.xx
        ```
    - 仮想環境を作り直し
        ```bash
        poetry env use 3.11
        ```
Python プログラムで PDF から画像を抽出する

## はじめに
時折、私たちは画像が含まれたPDF文書を受け取ることがあります。その中の画像をさらに操作したい場合、どうすればよいでしょうか？画像を抽出してフォルダに保存することは、良い選択肢です。少量の文書を処理する場合は、Adobe Acrobatのようなツールを使用して抽出することができます。しかし、大量の処理が必要な場合は、プログラミングを使用して迅速に抽出することをおすすめします。以下は、Pythonコードを例にした方法の紹介です。
## ライブラリ
* [Spire.PDF for Python](https://www.e-iceblue.com/Introduce/pdf-for-python.html)

この PDF ライブラリは、Python プラットフォームでの画像抽出をサポートしています。 
テキストを抽出したい場合は、この記事も参照してください。
[Python: Extract Text from a PDF Document](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Extract/Read/Python-Extract-Text-from-a-PDF-Document.html)
## 事前準備
* まず、[Python](https://www.python.org/downloads/) をダウンロードしてインストールします。
* Visual Studio Codeで「Extensions」をクリックし、「Python」を検索してインストールします。
* 「Explorer」-「NO FOLRDER OPENED」-「Open Folder」
* フォルダーを作成して、それに「.py」 ファイルを追加します。
* 「Terminal」-「New Terminal」
* 次のコマンドを入力して、[Spire.PDF for Python](https://www.e-iceblue.com/Introduce/pdf-for-python.html) と plum-dispatch v1.7.4 をインストールします。
```
pip install Spire.PDF
```
## サンプルコード
まず、使用する必要があるライブラリをインポートします。
```python
from spire.pdf import *
from spire.pdf.common import *
```
新しい PDF ドキュメントを作成します。
```python
#PdfDocument クラスのインスタンスを作成する
pdf = PdfDocument()
```
画像を抽出する必要がある PDF ドキュメントをロードします。
```python
#PDFドキュメントをロードする
pdf.LoadFromFile("C:/Users/Administrator/Desktop/Sample.pdf")
```
画像を保存するリストを作成します。
```python
#画像を保存するリストを作成する
images = []
```
ドキュメント内の各ページをループし、各ページから画像を抽出してリストに保存します。
```python
#ドキュメント内のページをループする
for i in range(pdf.Pages.Count):
    # Get a page
    page = pdf.Pages.get_Item(i)
    # Extract the images from the page and store them in the created list
    for img in page.ExtractImages():
        images.append(img)
```
リスト内の画像を PNG ファイルとして保存します。
```python
#リスト内の画像を PNG として保存する
i = 0
for image in images:
    i += 1
    image.Save("C:/Users/Administrator/Desktop/Images/Image-{0:d}.png".format(i), ImageFormat.get_Png())
pdf.Close() 
```
## スクリーンショット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/19566746-b1c7-d82d-f3d3-4c3579f41c88.png)
秘密鍵公開鍵方式RSA暗号化

OpenSSL使って暗号化するプログラム書いた事がなかったので何と無く書いてみました。
Pythonでcryptographyを利用しています。
秘密鍵と公開鍵はコメントに書いてある感じでサクッと作ればOK

```python
import json
from datetime import datetime

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding

# 次のコマンドで秘密鍵と公開鍵を生成
# $ openssl genrsa 2024 > private.key
# $ openssl rsa -pubout < private.key > public.key

# 秘密鍵
with open("private.key", "rb") as f:
    private_pem = f.read()
    private_key = serialization.load_pem_private_key(private_pem, password=None)

# 公開鍵
with open("public.key", "rb") as f:
    public_pem = f.read()
    public_key = serialization.load_pem_public_key(public_pem)

# 現在の時刻
dt_now = datetime.now()

# データを用意する
data_json_txt = json.dumps({
    'date': dt_now.isoformat(),
    'body': "Hello world!",
})

# 暗号化
ciphertext = public_key.encrypt(
    data_json_txt.encode(),
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# データの復号化
plaintext = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

print(ciphertext)
print(plaintext.decode())
```

できたはず！

以上
MVCモデルについて

## なぜ調べたいと思ったか？
MVCモデルを学習して実装したけど、「Model・View・Controller間でどうやりとりしているかを表した図」の理解に苦しんだ経験がありました。調べてみたら現実世界の例があって分かりやすい参考サイトがあったので、「MVCモデルとは何か？」についてまとめました。


## MVCモデルが登場した経緯について
MVCモデルは1979年に、パロアルト研究所でトリグヴェ・リーンスカウク氏によって考案されました。
「Smalltalk」というメッセージ形式で記述するプログラミング言語を開発する時に、「大規模で複雑なデータセットを制御するには、どうしたら良いだろうか？」という課題がありました。

「システムの仕組みに名前を付ける」が課題解決のヒントとなり、「Model-View-Editor」と名付けてMVEモデルが登場しました。
それから、「Smalltalk」の開発に携わったアデル・ゴールドバーグと議論した後に、「Model-View-Controller」という用語になりました。

つまりMVCモデルは、MVEモデルをベースとして出来上がったんですね。


## MVCモデルをどうやって再現しているか？
プログラムの書き方は
・全部の処理をまとめて記述する
・処理ごとに関数に分けて整理する
など、同じ処理でも人によって書き方が異なります。

そこでMVCモデルでは、プログラムを機能ごとにフォルダ分けして、どこにどんな処理をしているのかを分かりやすくしました。

Railsアプリケーションでも、Model・View・Controllerがフォルダ分けされていますね。ではModel・View・Controllerは、それぞれどんな処理を行なっているでしょうか？


## MVCモデルのそれぞれの役割とは？
①モデル(Model)
ビジネスロジックを担当する部分で、データベースとデータのやり取りを行います。やり取りというのは、「データベース内のデータの作成・参照・更新・削除」のことなんです。
**「Model = データベース」だと間違えやすい点に気をつけたいですね。**
![スクリーンショット-2019-05-22-21.46.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568357/e2053ffe-27a6-577c-fa9a-9fbb9840a704.png)
画像参照元：https://umaro.blog/mvc%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A7%A3%E8%AA%AC%E3%81%97%E3%81%BE%E3%81%99%E3%80%90%E5%88%9D%E5%BF%83/

②ビュー(View)
**普段私たちがWebブラウザを使って、閲覧している画面のこと**です。HTMLを解析して表示していますが、マイページ機能の様にデータベースで取得したデータを埋め込んで、動的ページとして表示することができます。
Viewはユーザーの画面操作として欠かせない存在ですね。

③コントローラー(Controller)
**Viewからのリクエストに応じて、Modelにデータ処理を指示したり、Viewに画面表示を指示したりします。**
処理内容が複雑に思うかもしれませんが、マイページの場合

1.入力したアカウント情報を、Modelで探索する
2.アカウントに関する情報をViewに渡して表示する

という流れになりますね。


## 飲食店の従業員を例に、MVCモデルの処理の流れをイメージしてみる
飲食店の従業員と聞いたら、以下の3人が挙がると思います。
1.ホール係⇒接客する人
2.デシャップ係⇒ホールとキッチンの仲介をする人
3.キッチン係⇒料理を作る人

以下の画像を見て、飲食店の各従業員がMVCのどれに該当するか考えてみましょう。
![スクリーンショット-2019-05-22-22.26.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568357/c812279d-1352-0156-eefb-5da8cdd1bc25.png)
![スクリーンショット-2019-05-22-22.29.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568357/71beccdc-68e5-7390-3245-6b236b7efc61.png)
![スクリーンショット-2019-05-22-22.31.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568357/2a786d42-1b72-2030-b648-afadb3a442c7.png)

画像参照元：https://umaro.blog/mvc%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A7%A3%E8%AA%AC%E3%81%97%E3%81%BE%E3%81%99%E3%80%90%E5%88%9D%E5%BF%83/

以下の答えになると思います。

1.ホール係
お客様の注文を受け取り、デシャップ係に伝える
→Viewに該当する
2.デシャップ係
ホール係から指示を受け取り、どう処理するかをキッチン係に伝える
→Controllerに該当する
2.キッチン係
デシャップ係の指示を受け取り、調理を行う
→Modelに該当する

調理が完了したら、それをデシャップ係に伝えてホール係に料理を運んで貰う。逆の流れでも「Model→Controller→View」をイメージできるかと思います。つまり**Viewの依頼内容に応じて、ControllerとModelで処理を行い、その結果をViewに返しているんですね。**


・調べてみて分かったこと
MVCモデルの理解に苦しむ方にとって、現実世界に例えたMVCモデルの説明は非常に参考になりますね。参考サイトには本当に感謝しています🙏

参考サイト
https://umaro.blog/mvc%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E8%A7%A3%E8%AA%AC%E3%81%97%E3%81%BE%E3%81%99%E3%80%90%E5%88%9D%E5%BF%83/
M1, M2 Macの環境構築はHomebrewで

## はじめに

Macを使い始めると、開発環境を構築するためにさまざまなソフトウェアやツールを用意する必要があります。そこで便利なのがパッケージ管理システムのHomebrewです。 Homebrewはユーザーがソフトウェアのインストール、アンインストール、アップデートなどを簡単に行えるように設計されています。

## Homebrewのインストール

「ターミナル」を開き、下記のコマンドを実行してください。

```zsh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

このコマンドは[Homebrew](https://brew.sh/ja/)の公式サイトからもコピーが可能です。

## パスの設定

次にパスの設定をします。Homebrewのインストールが完了すると、ターミナルに次のように出力されます。

```zsh
==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
    (echo; echo 'eval "$(/opt/homebrew/bin/brew shellenv)"') >> /Users/home/.zprofile
    eval "$(/opt/homebrew/bin/brew shellenv)"
- Run brew help to get started
- Further documentation:
    https://docs.brew.sh
```

出力が確認できたら、以下のコマンドを順番に実行してください。

```zsh
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
source ~/.zprofile
```

以上でインストールは完了です。

## 確認

正常にインストールされているか確認するには、以下のコマンドを実行します。

```zsh
brew -v
```

`Homebrew 4.1.3`のように出力されれば、正常にインストールできています。

## 追記

`eval "$(/opt/homebrew/bin/brew shellenv)"`は実行する必要ありません。このコマンドは現在のShellセッションにしか適用されないからです。
最新バージョンのgit tagを取得する方法

単純にバージョンを文字列としてソートして`tail -1`しまうと、`v.1`<`v1.10`<`v1.3`のような順序になってしまい意図したバージョンが取得できません。git versionに合ったコマンドを使うことで、ワンライナーでよしなに最新バージョンを取得できます。

## 結論
タグ名が`v`で始まることを前提にしています。そうでない場合は、オプションを適宜変更してください。

#### git 2.0以降
```
git tag -l --sort=v:refname "v*" | tail -1
```
- `"v*"`: tag名をfilterしています。この引数は無くても動作します


#### git 2.0未満
```
git tag -l | grep -P '^v' | sort -V | tail -1
```

- `sort -V`: versionを含んだ文字列をよしなにソートができます。他にも応用が効くので覚えておくと便利です
- grepは無くても動作します

## 参考
https://stackoverflow.com/a/14273595
(D⇒C)大きな数値を 3 けたごとにカンマ区切りで出力

今日はPythonでこの問題
https://paiza.jp/works/mondai/stdout_primer/stdout_primer__specific_split_step6

・出力された数値を3桁ごとにカンマ区切りするというやつ
・実はPythonには便利な関数があるが、それを使わずこれまで使ったループとrange関数と新しくでてきたlen関数で作成
　（便利な関数は後ほど）

```
input_line = input();
for i in range(len(input_line)):
    if i % 3 == 0 and i != 0:
        print(",",end="")
    print(input_line[i],end="")
```
・LEN関数で全体の桁数を調べそれでループさせる
・`print()`関数をうまく活用する
・<b>3桁ごとにカンマということは、つまり3回目は3で割り切れ、また０ではないときにコンマをプリントさせればOKということ（この考え方は重要）</b>

★もう1つの解法
・format関数で引数にコンマを使うと3桁ごとのカンマ区切りが出力される
 
 ```
input_line = int(input());
print(format(input_line,','))
 ```

 ★（2023.11.11追記）
コメントよりf-stringなる書き方もあるようです。
コメントありがとうございます！
私の方でも調べてみました。
https://realpython.com/python-f-strings/#:~:text=Also%20called%20formatted%20string%20literals,expressions%20enclosed%20in%20curly%20braces.

ただし、必ず数値型でないとだめなのがポイントです。
なのでinput()のあとに数値型に変更しないとf-stringが使えません

 ```
input_line = int(input());
print(f'{input_line:,}')
```
MInecraftServer機移行してみた ~その２~

# Minecraft Server 移行大作戦その2

## Ubuntuのセットアップ
SSDにOSをインストールをしたらアップデートをしていく。
```
$ sudo apt update

$ sudo apt upgrade -y
```

### SSHのポートを変更
```
$ sudo vi /etc/ssh/sshd_config

# Port 22 → 任意のポートに変更 
```

### ufwのインストール
```
$ sudo apt install ufw
```

### 許可されたポートだけを通すようにする
```
#許可するポート
$ sudo ufw allow #SSHポート
$ sudo ufw allow 25565

#許可されたポート以外を閉じる
$ sudo ufw default deny

#有効化
$ sudo ufw enable
```

#### ufwのstatus確認
```
$ sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
xxx                        ALLOW       Anywhere
25565                      ALLOW       Anywhere
```

### IPアドレスの確認
```
$ ip addr show


```

### IPアドレスの固定
```
$ cd cd /etc/netplan
$ ls -l   #どのファイルがあるか確認

#元のファイルが消えないようにバックアップする
$ sudo mv 01-network-manager-all.yaml 01-network-manager-all.yaml.bak

#enp89s0のところはネットワークアダプタ名になるので適宜書き換えてください
$ vi 100-enp89s0-fixed.yaml

#以下のことを書き込む

network:
   version: 2
   renderer: networkd
   ethernets:
      eno1:
         addresses: [192.168.1.26/24]
         nameservers:
            addresses: [192.168.1.1]
         routes:
            - to: default
              via: 192.168.1.1

```

書き込みが終わったらyamlファイルを反映させる
```
$ sudo netplan apply
```

反映されているか確認
```
$ ip a

2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    altname enp0s31f6
    inet 192.168.1.44/24 metric 100 brd 192.168.1.255 scope global dynamic eno1
       valid_lft 58235sec preferred_lft 58235sec
```

この後ルーターで固定したIPがDHCPで振られないようにMACアドレスと紐づけして固定することを忘れずにしましょう(再起動したときに自動DHCPで割り当てられてアクセスできなくなる可能性があります)

### ルーターのポート開放
ここに関しては以前Raspberry Pi Serverの時に開放してるので今回する作業はありませんが、やっていなければこの記事を見て設定してください。
https://qiita.com/kameee/items/f7f59c7a5efdaeb25c9d


## java のインストール
Java version17をインストールします 
```
$ sudo apt install openjdk-17-jdk
```

## タイムゾーンの設定
```
$ timedatectl set-timezone Asia/Tokyo
```

## NTPサーバーの設定(時刻同期)
```
$ sudo vi /etc/systemd/timesyncd.conf

#以下のところを#を消して書き加える
NTP=ntp.nict.jp

$ sudo timedatectl set-ntp true

#設定ができているか確認
$ sudo systemctl status systemd-timesyncd.service
```


## おわりに
これでOSのセットアップまで終わったので次回ワールドをコピーして動作確認ができれば移行作業が完了となる予定です。その３へ続く
AndroidのNativeActivityを使ってみる

# はじめに

突発的に Android の NativeActivity を使う必要があったので、公式が提供しているサンプルを使おうとしたのですが、現状（2023.11.10時点）そのままでは動かない状態になっているので、必要な修正手順を記します。

https://github.com/android/ndk-samples/tree/main/native-activity

# 修正手順

## 1. git clone

```bash
# ndk-samples を取得
git clone https://github.com/android/ndk-samples

# native-activity を AndroidStudio で開く
studio ndk-samples/native-activity
```

## 2. gradleのアップグレード

Android Studio で開いた時 `Start AGP Upgrade Assistant` が出ると思われるので、念のためアップグレードをしておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2161417/3d30c799-670f-ed77-adb8-9c638ca7b4d2.png)

## 3. AndroidManifest.xmlを修正

その後、ビルドして起動すると `androidx.startup.InitializationProvider not found` というエラーで常にクラッシュするので、`AndroidManifest.xml` から `android:hasCode="false"` という行を削除する必要があります。

```bash
% git diff
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f35e5f3..718050e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,7 +7,6 @@
     <application
         android:allowBackup="false"
         android:fullBackupContent="false"
-        android:hasCode="false"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name">
```

ここまでの修正で起動できるようになります。

# 確認

起動するとブラックスクリーンになり、画面を触ると画面の色が変わる感じで動作します。

折角なのでどういう処理をしているか覗いてみました。

[app/cpp/cpp/main.cpp](https://github.com/android/ndk-samples/blob/main/native-activity/app/src/main/cpp/main.cpp)がメインコードのようです。

`android_main` 関数がエントリポイントで、初期化 & 復帰処理後にイベントを拾って処理することを繰り返していることが分かります。

何故か（C++なのに）Cのような実装になっていたり、warningが大量に出ていて気持ち悪かったので、軽くモダン化改修しつつwarningを対処したバージョンを作ってみました。

https://github.com/suzukiplan/native-activity-android
メールサーバのテストをする時に


この記事は [一分で読める小ネタのカレンダー | Advent Calendar 2023 - Qiita](https://qiita.com/advent-calendar/2023/raki) の４日目

# メールサーバの送信テスト

```bash
date | mail -s "`uname -n` : `date --rfc-3339=seconds`" -r noreply@example.com your-mail@example.net
```

- メールサーバが複数台あったりする時に手軽に打てるワンライナー
- SPF,DKIM,DMARC,暗号化とかメールサーバのテストを何度もする時に
- ホスト名と日時をタイトルに、本文にも日時を乗せておくと、何度もテストする時に
- タイトル側だけRFC3339にしてるのは見やすいから
- hostname でも注意すればいい気がする（hostname は間違って実行するとホスト名を書き換えてしまう）
- uname -a は長すぎたり -n は値が役に立たないケースがある？

# おまけ

- メールクライアントのバージョン等によっては -s （タイトル） -r （送信元アドレス）のオプションが違ったりするけど必要に合わせて変えましょう。詳しくは `man mail`
- `tail -f /var/log/maillog`
- リレーしてる時はリレーのテストもちゃんとしましょう
- サンプルとして使うドメインは [example.com - Wikipedia](https://ja.wikipedia.org/wiki/Example.com) を参考にしましょう

# 改善依頼

- アドレス等を環境変数にする”以外の”改善案をお待ちしています
- date コマンド以外にこういうの入れる、とか
- 他の方法で送っている、とか
aws protonの環境templateバージョンアップ時の失敗

# aws protonの環境templateバージョンアップ時の失敗

protonの環境バージョンを1.xから2.xにメジャーバージョンアップした際、サービスtemplate側の互換性設定を更新しないと互換性のある環境が存在しないとみなされてサービス構築できなくなるので注意が必要。


https://docs.aws.amazon.com/ja_jp/proton/latest/userguide/create-template-sync.html

具体的には以下のファイル

```
 /templates/my-svc-template/v1/.template-registration.yaml   # service template version properties
```

```
compatible_environments:
  - env-templ-name:major-version
  - ...
supported_component_sources:
  - DIRECTLY_DEFINED
```
パイプラインで失敗しているはずなのにパイプラインが成功してしまう

# はじめに

パイプラインを動かしたところなぜか失敗しているのにその先に進んでしまう問題が起きたのでまとめます

# 問題

以下のようなパイプラインがありました

```pipleine.yml
      - label: "Run unit test"
        command:
          - cd test
          - npm install
          - npm run typecheck && lint
          - npm run test
```

しかし今パイプラインで型チェックでエラーが出るようなコードを対象に動かしてもなぜか落ちずに最後のテストまで実行されてしまいました

# 解決方法

```pipleine.yml
      - label: "Run unit test"
        command:
          - cd test
          - npm install
          - npm run typecheck
          - npm run lint
          - npm run test
```

`&&`としていたところを分けることでうまく行くようになりました
原因はよくわからないのでChatGPTにきいたところ

>通常、パイプライン内のすべてのコマンドが終了コード 0 を返す限り、パイプラインは成功とみなされます。つまり、2つのコマンドが連鎖されている場合、最初のコマンドが失敗しても、2番目のコマンドが実行され、その終了コードがパイプラインの結果に影響しない場合があります。

おそらくそんな感じの挙動なんだろうなとは思いましたが、根本的な原因をさぐらずここで解決としました

# おわりに

やっとカイゼンできたのでよかったです
【Ruby on rails】rails db:migrateできない時の対処法

# はじめに
プログラミングを勉強して3か月ほどです。
プログラミングスクールを卒業し、現在就職活動をしています。

今回はオリジナルアプリ作成時に発生したエラーで苦戦したので、その対処方法を共有したいと思います。

※@mogya(daisuke furukawa)さんの記事を参考にさせていただきました。


# 今回のエラー内容
今回発生したエラーはrails db:migrateができなくなるエラーです。
rails db:migrateを実行するとターミナルに以下のエラーログが表示されました。
私が実行しようとしているテーブルは存在していると表示されています。
[![Image from Gyazo](https://i.gyazo.com/4774393b10f185267ac7d2ff411f120a.png)](https://gyazo.com/4774393b10f185267ac7d2ff411f120a)

また、rails db:migrate:statusを使ってマイグレーションファイルの実行状態を確認したところ、実行されていないことが示されていました。
[![Image from Gyazo](https://i.gyazo.com/56c75864c23336fb6e2fb2708fb59281.png)](https://gyazo.com/56c75864c23336fb6e2fb2708fb59281)


# エラー原因（おそらく）
私はマイグレーションファイルに下記のような記述をしました。
```2023xxxxxxxxx_create_notifications.rb
class CreateNotifications < ActiveRecord::Migration[7.0]
  def change
    create_table :notifications do |t|
      t.integer :visitor_id, null: false
      t.integer :visited_id, null: false
      t.references :room, null: false, foreign_key: true
      t.string :action, default: '', null: false
      t.boolean :checked, default: false, null: false

      t.timestamps
    end

    add_index :notifications, :visitor_id
    add_index :notifications, :visited_id
    add_index :notifications, :room_id
  end
end
```
私はadd_indexの記述を初めて見よう見まねで使ってみました。
しかし、その記述方法に間違いがあったことにより今回のエラーが発生しました。

# エラー対処方法
一度マイグレーションファイルの内容をコメントアウトします。
```2023xxxxxxxxx_create_notifications.rb
class CreateNotifications < ActiveRecord::Migration[7.0]
  def change
    # create_table :notifications do |t|
    #   t.integer :visitor_id, null: false
    #   t.integer :visited_id, null: false
    #   t.references :room, null: false, foreign_key: true
    #   t.string :action, default: '', null: false
    #   t.boolean :checked, default: false, null: false

    #   t.timestamps
    # end

    # add_index :notifications, :visitor_id
    # add_index :notifications, :visited_id
    # add_index :notifications, :room_id
  end
end
```
この状態でrails db:migrateを実行します。
すると、しっかりマイグレーションファイルが実行されています。
[![Image from Gyazo](https://i.gyazo.com/7471165bd9e6a90bfbc16044de77ca6f.png)](https://gyazo.com/7471165bd9e6a90bfbc16044de77ca6f)

ここまできたら、マイグレーションファイルの中身を正しい記述に変更します。
変更後、rails db:rollbackで戻した後、rails db:migrateを実行するとエラーが解消されます。

# 終わりに
今回はrails db:migrateできない時の対処法を共有させていただきました。
エラーが発生すると、作業が滞り、気持ちも落ち込みがちですが、解決した時の喜びは計り知れません。
エラーが発生した時は、先人たちの知恵や経験から学ばせてもらいましょう！
この記事が誰かの役に立てば幸いです。

最後まで読んでいただきありがとうございました！！！
Stable Diffusion落ちる、Web UIの重さを解消するには、スワップ領域を拡張すれば解決（Intel Macbook Proでのスワップ領域の拡張方法）

以下の記事では、Intel Macbookでは使えないコマンドが記載されていたため、Intel Macbookでも叩けるコマンドで同じことを再現します。

https://kindanai.com/webui-crash-swap-solution/

---

Mac OS Xでは通常、スワップ領域の管理はシステムに任されていますが、特定の状況下で手動でスワップ領域を拡張する必要がある場合があります。以下の手順では、`fallocate` コマンドが利用できない場合の代替方法として `dd` コマンドを使用しています。

#### ステップ1: スワップファイルの作成

1. ターミナルを開き、以下のコマンドを実行して10GBのスワップファイルを作成します。
   ```bash
   sudo dd if=/dev/zero of=/var/swapfile bs=1m count=10240
   ```
   - `if=/dev/zero`: 0で埋められたデータを提供する特殊ファイル。
   - `of=/var/swapfile`: 作成するスワップファイルのパス。
   - `bs=1m`: ブロックサイズを1MBに設定。
   - `count=10240`: 10GBのファイルを作成するために10240ブロックをコピー。

#### ステップ2: スワップファイルのアクセス権限設定

2. スワップファイルのアクセス権限を設定します。
   ```bash
   sudo chmod 600 /var/swapfile
   ```
   これにより、ファイルは所有者にのみ読み書き可能になります。

#### ステップ3: スワップファイルの初期化

3. 作成したスワップファイルをスワップ領域として初期化します。
   ```bash
   sudo mkswap /var/swapfile
   ```

#### ステップ4: スワップ領域の有効化

4. 新しいスワップ領域を有効にします。
   ```bash
   sudo swapon /var/swapfile
   ```

#### ステップ5: 永続化の設定

5. `/etc/fstab` ファイルを編集して変更を永続化します。
   ```bash
   sudo nano /etc/fstab
   ```
   ファイルの末尾に以下の行を追加します。
   ```
   /var/swapfile none swap sw 0 0
   ```
   nanoを使用している場合は、Ctrl + Xを押し、Yを入力し、エンターキーを押して保存します。

#### ステップ6: スワップ領域の確認

6. スワップ領域が正しく追加されたことを確認します。
   ```bash
   swapon --show
   ```

#### 注意点

- Mac OS Xでは、スワップ領域の手動設定は一般的ではありません。システムによる自動管理が推奨されています。
- この手順は、ファイルシステムやOSのバージョンによっては適切でない場合があります。変更を行う前には十分なバックアップを取ることをお勧めします。

---

この記事が、Intel Macbook Proでスワップ領域を拡張する方法についての理解を深めるのに役立つことを願っています。
gitの使い方とコマンド一覧

## gitの大まかな流れ

1. リポジトリをコピー（clone）
1. ブランチ（update-readme）を作成
1. README.mdを更新しコミット
1. ローカルリポをリモートリポに反映する（push）
1. update-readmeブランチをmainブランチにマージする
1. リモートリポをローカルリポに反映する（pull）
1. 不要なブランチを削除する


## コマンド一覧

ブランチ情報の確認
```
git branch
```

ブランチの新規作成
```
git branch {branch name}
```


ブランチの切り替え
```
git checkout {branch name}
```

ブランチに変更内容があるか確認
```
git status
```
ローカルリポがどのリモートリポと紐付いてるか調べる
originがリファレンス名となっている
```
git remote -v

origin	git@gitlab.com:gitroom/djangoproject.git (fetch)
origin	git@gitlab.com:gitroom/djangoproject.git (push)
```

変更したファイルをステージングエリアに追加する
```
# 個別
git add {file name}

# すべて
git add .
```

ステージングエリアの内容をコミットする
```
git commit -m "{commit message}"
```

コミット履歴の表示
HEADは今いるリポジトリ
originはリモートリポジトリの状態
```
git log

commit aaaaaaaaaaa (HEAD -> update-readme)
Author: user <mail@mail.com>
Date:   Fri Nov 10 05:05:25 2023 +0000

    update readme

commit bbbbbbbbbbbbbbbbb (origin/main, origin/HEAD, main)
Author: user <mail@mail.com>
Date:   Thu Nov 9 23:51:16 2023 +0000

    Update README.md
```

リモートリポの更新をローカルリポに反映させる
```
git pull {remote_ref} {branchname}

（例）
git pull origin main
```

ローカルリポの内容をリモートリポに反映させる
```
git push {remote_ref} {branchname}

（例）
git push origin update-readme
```

ローカルリポの特定ブランチを削除する
```
通常
git branch -d {branch-name}

mainにマージされてないbranchを強制削除する場合
git branch -D {branch-name}
```
【Flutter】項目バリデーションで、項目名を埋め込んだメッセージを表示する

## やりたいこと
テキスト入力の項目で、以下のように必須エラーなどのバリデーションメッセージを出しているが、メッセージを項目ごとに定義せずに、「〜は必須です」の１種類だけを登録し、「〜」部分に項目名を埋め込みたい。
![Screenshot_1699525584.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/e454f758-7011-f857-e695-926684a482cb.png)

バリデーションで固定のメッセージを表示すること自体は、すでに以下を参考にさせていただき、「form_field_validator」を利用して、できている状態です。

https://zenn.dev/sanyatsu/articles/fce6d774396b60

## 自分で、元のValidatorを継承したValidatorをつくる
ChatGPTさんに相談しながら解決した方法です。もしかするともっと良い方法があるのかもしれないですが・・・。
例えば、RequiredValidatorのエラーメッセージに項目名を埋め込みたい場合は、RequiredValidatorを継承して、コンストラクタの引数に項目名を取る、自作のValidatorを作成しました。

```dart
///必須バリデータ（項目名をエラーメッセージに埋め込む）
class CustomRequiredValidator extends RequiredValidator {
  final String filedName;

  CustomRequiredValidator(
      {String errorText = 'この項目は必須です', required this.filedName})
      : super(errorText: '$filedName は必須です');
}
```

「form_field_validator」のライブラリで定義されている「RequiredValidator」のソースを見ると、isValidでない場合は、以下のようにerrorTextを返しているので、errorTextに項目名を埋め込んだメッセージを渡すことで、うまく埋め込まれているようです。
※RequiredValidatorのソース

```dart
class RequiredValidator extends TextFieldValidator {
  RequiredValidator({required String errorText}) : super(errorText);

  @override
  bool get ignoreEmptyValues => false;

  @override
  bool isValid(String? value) {
    return value!.isNotEmpty;
  }

  @override
  String? call(String? value) {
    return isValid(value) ? null : errorText;
  }
}
```

## 他のバリデータと組み合わせる

本来は、必須かつ２００文字以内というバリデーションをかけたかったため、同様にMaxLengthValidatorを継承して、CustomMaxLengthValidatorというものも作り、
これらを囲んだMultiValidatorを返すメソッドを新しいクラスの中に作りました。（今思うと、customMultiValidatorではなく、normalTextValidatorのような名前の方がよかったかもしれません。）

```dart
///通常の必須テキスト項目用バリデータ（必須、２００文字以内）
class CustomValidators {
  static MultiValidator customMultiValidator({required String fieldName}) {
    return MultiValidator([
      CustomRequiredValidator(filedName: fieldName),
      CustomMaxLengthValidator(filedName: fieldName, max: 200)
    ]);
  }
}
```

## 呼び出す
この新しく作ったcustomMultiValidatorを、TextFormFieldのvalidatorの値として呼び出します。「fieldName」にメッセージに埋め込みたい項目名を設定します。

```dart
 TextFormField(
                      decoration:
                          const InputDecoration(labelText: 'メールで受信した「共有ID」を入力'),
                      onChanged: (String value) {
                        setState(() {
                          listId = value;
                        });
                      },
                      validator: CustomValidators.customMultiValidator(
                          fieldName: '共有ID'),
                    ),
                  )
```
cronについて

### はじめに
cronはタイマーを設定して、決まった時間、決まった月日、決まった曜日などに、スクリプトが実行ができるデーモンです。定期的にログを取得するような場合によく使われます。デーモン名はcronですが、コマンドはcrontabになります。

### 環境
Ubuntu20.4

#### コマンド例

cronのデーモンが動作しているか確認をします。Ubuntuのデフォルトでは起動しています。
```
$service --status-all | grep cron
```

現状の設定を表示するコマンドです。
```
$crontab -l
```

設定した内容を削除するコマンドです。くれぐれも誤って実行してしまわないようにして下さい。
```
$crontab -r
```

設定内容を編集するコマンドです。エディタを終了した後、文法チェックが流れます。文法チェックで問題がなければ「installing new crontab」と表示されます。エディタでnanoが立ち上がる場合は、viに変更することができます。
```
$crontab -e
```

### 設定例
crontab -eを実行すると、上部に記述の仕方が英語で書かれています。サンプル通りに設定すると、毎日5時0分にコマンドが実行されるようになります。

設定個所のフォーマットは、「* * * * * コマンド」になっています。アスタリスク部分は、左から順番に「分、時、日、月、曜日」となります。
```
For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
```

毎月20日 23:59に実行させる例です。時刻は24時間表記です。12で設定すると昼の12時のことになります。
```
59 23 20 * * ./home/hoge.sh
```

毎週 金曜日(5) 17:00に実行させる例です。
```
00 17 * * 5 ./home/hoge.sh
```

5分間隔で実行させる例です。 /は何分間隔です。
```
*/5 * * * * ./home/hoge.sh
```

毎日 11:00に実行させる例です。
```
0 11 * * * ./home/hoge.sh
```

Rubyのスクリプトを実行したい場合、このように設定しても実行されません。
```
1 12 * * * ruby $HOME/hoge.rb 
```

Rubyのスクリプトを実行する場合は、Rubyのフルパスを指定する必要があります。Rubyがあるパスはwhichで探すことができます。
```
1 11 * * * ruby /usr/local/rbenv/shims/ruby $HOME/hoge.rb
```

### ログについて

cronを実行すると、cron.logが増大していくことになります。このように設定すると、毎月１日にログがクリアされるようになります。
```
* * 1 * * sudo cp /dev/null /var/log/cron.log
```

月～金 12時1分に、Rubyのスクリプトを実行させる例です。エラーになった場合は、ログを出力しています。
```
1 12 * * 1-5 cd $HOME && /usr/local/rbenv/shims/ruby hoge.rb >> ./log_hoge.log
```
伝わらないデザインの作り方 😈

## はじめに 🌱
みなさん、デザインって難しいですよね。
デザインに正解は無く、なにを作るのも自由！
だけど、いざ作ってみたらピンとこない！！どうすればいいの！！！と悩むことがあると思います。
（私も未だにあーでもない、こーでもないと悩みながらデザインを作ってます🤔）

そんな自由なデザインだからこそ、なにが良くないのかを改めて言語化し、体感することが大切かと思います。
なので、今回は<font color="#f00">**あえて「伝わらないデザイン」の作り方**</font>を考え、作ってみようと思います。

### 1️⃣ 伝えたい情報をとりあえず詰め込んでみよう！
まずデザインを作る際に重要なのが、”情報整理”の作業です。
何を一番ユーザーに伝えたいかを考え、優先順位をつけていく大事な作業です。

情報の優先順位を整理せずに作ったらどうなるでしょうか？

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328866/87416796-0878-7126-5890-4ec167aaa58d.png">

:::note alert
情報の整理を行わず、優先順位をしっかりと意識しないで作っているので、
なんの情報を一番伝えたいデザインなのか分からなくなりましたね。
メリハリもないので押し出したい情報が分かりづらくなっています😅
:::

### 2️⃣ 深く考えず色々なパーツを入れてみよう！
デザインを作成する際に、何も考えないで作成していると失われていく"統一感"。
伝えたいことを意識してもらうには、全体の雰囲気（フォントや画像、カラーなど）が統一されている方が良いです。

統一感を意識せず、フォントや画像、カラーを別々に使ってみましょう。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328866/edd3456a-a545-0339-3f8a-f1917eca257c.png">

:::note alert
フォントがバラバラなので、文字の内容が頭に入りにくくなりました...！
画像もクリスマスとは関係のないしろくま、リッチイラストのベル、フラットイラストの雪だるまと統一感がなく、チグハグな印象を受けます。
全体的なカラーも、赤・緑・青・黄色とバラバラなので、全体のまとまりがなくなっているかと思います。
:::

### 3️⃣ 余白が気になるなら埋めてみよう！
余白があると落ちつかず、ついつい埋めたくなってしまうことあるかと思います。

余白を埋めてしまい、空いていないとどうなるでしょうか？

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328866/34d4cd90-4cb1-1823-ae47-22d7b8b35856.png">

:::note alert
余白を埋めて作成すると、とても窮屈に感じますね。
また、要素同士がくっつきすぎて、目立たせたいものがわからなくなってしまっています。
余白がないデザインは大切な情報がどれなのかわかりにくく、読みにくいものになってしまいます😢　
余白を適切に配置して、情報の関係性がわかりやすいようにデザインしましょう。　
:::

### 4️⃣ 目立たせたい...！たくさん装飾してみよう！
ユーザーの目を止めるためには、伝えたいことを目立たせることも大切です。

要素に装飾を色々と加え、とにかく目立たせてみましょう。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328866/8462c94d-5870-1484-24ff-d1a87ca36383.png">

:::note alert
装飾が多すぎると目が散ってしまいますね...!
文字の境界線が多すぎたり、画像の加工が強すぎたりすると
デザインの印象も悪くなってしまいます😢
過度な加工やたくさんの装飾をせずに、違う方法で視線誘導できる方法を考えてみましょう！　
:::


## まとめ 📝
「伝わらないデザイン」を作ってみました。いかがだったでしょうか？
勘違いしないでいただきたいのが、上で行ったもののすべてが必ずしも駄目なわけではありません。

どの項目も**過剰に**行いすぎると伝えたかった情報が「伝わらないデザイン」に変わっていくということがお分かりいただけたかと思います。(料理と同じで足し算のしすぎは良くないということですね🍳)<br>

今後デザインを作る際に迷うことは多々あると思います。
しかし、**ユーザーに上手く伝える**という点では、今回の「伝わらないデザイン」を反面教師にすることで、伝わるデザインを作るのに役立てば良いなと思います。

最後まで見てくださった方、どうもありがとうございました！

:::note 
伝わるデザイン作成時に気をつけたいこと
- 伝えたい情報の優先順位を考える。
- フォント、カラー、画像のテイストを揃える。
- 余白はルールを決めてしっかり取る。不安になっても埋めすぎない。
- 装飾・加工はやりすぎない。
:::

## 参考サイト / 使用サイト 💻

https://tsutawarudesign.com/

https://blog.codecamp.jp/fail

https://www.canva.com/
Warpの見た目をカスタマイズする

# 背景画像を変更

1. ショートカットキー &#x2318; + &#44;を押下
1. Appearanceタブを選択し、Current themeをクリック
![Settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618505/f4b82118-b5e5-a26d-8c05-7d5bb0eab5c9.png)
1. 左ペインでThemesが表示されるので+ボタンを押下
![themes場所.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618505/967d4012-0cb8-d342-4b03-f21c1588339a.png)
1. ポップアップがでてくるのでSelect an Imageを押下して背景画像を選択
![select_an_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618505/37768b30-ac35-ba33-6211-0cf23470bc37.png)
1. 自動的にカラーテーマの候補を出してくれるので好みの色を選んでcreate theme
![color_theme.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618505/592eee67-d11f-1d16-0835-d3aaf9a0df11.png)
1. 自動でカラーテーマが作成される
1. 問題ないならこれで終了。色が気に入らないなら下記の調整を行う。(カーソルの色や文字色がなんか見づらいなど）

# 見た目を微調整する

1. ターミナルなどから`~/.warp/themes`にアクセス
1. `作成したテーマ名.yaml`ファイルを開く
1. 下記のような設定が開かれるので、変えたい箇所を編集
```yaml:作成したテーマ名.yaml
---
background: "#929c9b" # 背景色
accent: "#cbcacd" # カーソルの色はここ
foreground: "#000000" # 文字色
background_image:
  path: /Users/t-kozono/.warp/themes/test.jpeg # 背景画像
  opacity: 30 # 背景画像の透過度
details: lighter
terminal_colors:
  normal:
    black: "#212121"
    red: "#c30771"
    green: "#10a778"
    yellow: "#a89c14"
    blue: "#008ec4"
    magenta: "#523c79"
    cyan: "#20a5ba"
    white: "#e0e0e0"
  bright:
    black: "#212121"
    red: "#fb007a"
    green: "#5fd7af"
    yellow: "#f3e430"
    blue: "#20bbfc"
    magenta: "#6855de"
    cyan: "#4fb8cc"
    white: "#f1f1f1"
name: test
```

# 参考
https://docs.warp.dev/appearance/custom-themes
【ECCUBE4系】Twigで簡単！グローバル変数

今回はtwigで参照する変数を、なんとかグローバル変数にできないか？というお話です。

twigで値を参照したい場合、通常であればControllerで値を取得し、returnしてtwigに渡すようにカスタマイズするのが一般的かと思います。
でも、sessionやcookieに保持している値を全twigで表示しようと思うと、全画面のControllerとtwigのカスタマイズを行わなければなりません。
それは、非常にコストがかかる！
もっと簡単な方法はないものでしょうか。。。？

例えば、Customerがログインを行なった場合、認証が通った後で会員の今までに購入した金額によって
- 今までの購入金額が1000円未満の場合は、Aグループに所属するCustomer
- 今までの購入金額が3万円未満の場合は、Bグループに所属するCustomer
- 上記以外の場合は、Cグループに所属するCustomer
上記の範囲で会員のグループ分けします。
会員が所属しているクループによって、文言の出しわけをしてください。
こんな依頼は結構あるもので。。。

Controllerでセッション情報を取得して、文言を変数に入れてtwigにreturn。。。
そんなことはしなくても大丈夫です。

皆様はEventSubscriberをご存知ですか？
今回は、EventSubscriberの力を借りて、twigで参照できるグローバル変数を作成してみましょう。

app/Customize/EventListener配下にTwigInitializeListener.phpを作成しましょう。
TwigInitializeListener.phpの中身は、下記のようになります。

```php
<?php

namespace Customize\EventListener;

use Eccube\Request\Context;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

class TwigInitializeListener implements EventSubscriberInterface
{
    /**
     * @var bool 初期化済かどうか.
     */
    protected $initialized = false;

    /**
     * @var Environment
     */
    protected $twig;

    /**
     * @var Context
     */
    protected $requestContext;

    /**
     * TwigInitializeListener constructor.
     *
     * @param Environment $twig
     * @param Context $context
     */
    public function __construct(
        Environment $twig,
        Context $context
    ) {
        $this->twig = $twig;
        $this->requestContext = $context;
       
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        if ($this->initialized) {
            return;
        }
        if ($this->requestContext->isFront()) {
            $customerGroup = $event->getRequest()->get('customer_group');
            $this->twig->addGlobal('customerGroup', $customerGroup);
        }

        $this->initialized = true;
    }

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::REQUEST => [
                ['onKernelRequest', 20],
            ],
        ];
    }
}
```
処理が記載できたら、あとはtwigの修正をするだけです。

```twig
{% if customerGroup == 'A' %}
    <div>
　　　　<p>今月末までに1000円以上購入されると、プチクーポンをプレゼント</p>
    </div>
{% elseif customerGroup == 'B' %}
　　　<div>
　　　　<p>今月末までに3万円以上購入されると、豪華クーポンをプレゼント</p>
　　　</div>
{% else %}
　　　<div>
　　　　<p>クーポン取得済みです。</p>
　　　</div>
{% endif %}
```
TwigInitializeListener.phpを作成することで、twig側でcustomerGroupという変数をControllerを経由せずに使うことができるようになっていると思います。

Controllerの経由が不要なので、静的ページからでも参照できます。

コストを掛けずにカスタマイズできる方法があるのは、良いことですね。
【注意】npm uninstall時に考えなければいけないこと

# はじめに
package.jsonのあるライブラリのバージョンを上げたいなというプロジェクトがありまして。

古いバージョンのものを下げるにはどうすればいいんだろうなと思い、調べたことを簡潔にまとめておきます。

# package.jsonのバージョンをあげるやり方
こちらの方の記述がとてもわかりやすかったです。

https://qiita.com/sugurutakahashi12345/items/df736ddaf65c244e1b4f

# 問題
単純にパッケージマネージャーツールの`npm`を用いて、uninstallすれば良いと思っていましたが、

アンインストールするパッケージはどこに当てはまるのかを考える必要がありました。

# 考えるべきこと
アンインストールするべきパッケージは大きく分けて3つ。

1. 通常のパッケージ
1. グローバルにインストールされたパッケージ
1. 開発環境のみで使うパッケージ

## 通常のパッケージをアンインストールする場合
これは`package.json`のdependenciesに指定されたものです。

```package.json
{
    "dependencies": {
    // ここに記述されているものが通常のパッケージ
        "express": "4.71"
    }
}

```

### 手法
`$ npm uninstall package-name`

### 具体例
これが
　![ss-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/492b479e-0691-36de-d093-ac1c342aedb0.png)

コマンドを打つと

　![ss-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/343e2076-1100-7475-fb15-66b06dc23c6a.png)

## 開発環境のみで使うパッケージをアンインストールする場合
これは`package.json`のdevDependenciesに指定されたものです。

```package.json
{
    "devDependencies": {
    // ここに記述されているものが開発環境のみで使うパッケージ
        "nodeman": "2.0.15"
    }
}

```
### 手法
消すには、`-D`か`--save-dev`を加えてuninstall

`$ npm uninstall -D package-name`
`$ npm uninstall --save-dev package-name`

### 具体例
これが
![ss-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/b4bfeed6-bd99-4605-f606-e5eac34a50e0.png)

コマンドを打つと

![ss-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/372b897f-88cf-e9f4-26ab-7617acd2cd20.png)


## グローバルにインストールされたパッケージをアンインストール
みなさんのPC上にグローバルにインストールされたパッケージです。
そのため、プロジェクトに毎回インストールする必要がありません。


### 手法
`$ npm uninstall -g package-name`

### 具体例
これが

![ss-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/22014776-4c91-9f3d-7797-59ccdb45f9a3.png)

コマンドを打つと

![ss-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/89f0f21e-4fb2-db49-f48a-4aef2d4f1bb2.png)




# おわりに
uninstallすればいいんでしょと思ってもちゃんと言語化しないと何がアンインストの対象かわからないなと思いました。

冷静に対象を分析したいですね。

# 参考
https://www.freecodecamp.org/japanese/news/npm-uninstall-how-to-remove-a-package/
CSSでボックスの角にだけ色をつけたい


divのボックスの角にだけ色をつけたいと思い、cssをいじってみました。

![スクリーンショット 2023-11-10 15.54.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/461ffdd2-4925-2a8d-74fa-393cf2a4a64d.png)

参考になるソースを以下に記載します。

linear-gradientを使ってグラデーションを表現しました。



色をつけたい位置によって直線の角度を変える場合
- 左上 135deg
- 左下 45deg
- 右上 -135deg
- 右下 -45deg

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="NWojwYG" data-user="o-mo-t" 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/o-mo-t/pen/NWojwYG">
  Untitled</a> by omoto (<a href="https://codepen.io/o-mo-t">@o-mo-t</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

---


```css
.diagonal-shadow {
  position: relative;
  height:200px;
}

.diagonal-shadow::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%; 
  height: 100%;
  background: linear-gradient(
    135deg, 
    rgba(255, 0, 0, 1), 
    transparent 20px
  );
  border: 1px solid black;
  z-index: -1;
}

```
超単純なPythonのDevcontainer

# 目的
超単純（できるだけ最小構成）のPython開発環境（Docker）を作りたい

# devcontainer.jspn

```json
{
	"name": "Python 3.12 Dev",

	"dockerFile": "Dockerfile",
	"customizations": {
		"vscode":{
			"settings": {
				"terminal.integrated.shell.linux": "/bin/bash",
				"python.pythonPath": "/usr/local/bin/python"
			},
			"extensions": [
				"ms-python.python"
			]
		}
	}
}
```

書いてあることは名前・ドッカーファイル指定・vsコードのカスタマイズのみ

# Dockerfile

```dockerfile
FROM python:3.12
```
バージョン指定のみ

これでリビルドすれば動きます。
スクロールしたときに下から出てくるアニメーションをつける方法

こんにちはAtsu1209です

いきなりですが色んなサイトを見て研究してたときに、一つ気付いたことが..
それは、スクロールした時に下からフワって文字とかが出てきてること
今回はそれをやる方法について書いていきます。

# 実装場所
今回は、僕のホームページにこの機能をつけたいと思います。

https://atsu1209.github.io/home/

jQueryとCSSを使っていきます。

# CSS
まず下から出すための準備をします。

 ```css:ScrollIn.css
 .scrollClass{
    opacity: 0; 
    transform: translateY(100px); 
    transition: opacity 0.5s, transform 0.5s; 
    }
 ```

# jQuery

```javascript:ScrollIn.js
$(window).scroll(function() {
        var element = $(".scrollClass");
        var scrollPosition = $(window).scrollTop() + $(window).height();
        var elementPosition = element.offset().top;
        if (scrollPosition > elementPosition) {
            element.css({
                "opacity": "1", 
                "transform": "translateY(0)" 
            });
        }
        if (scrollPosition < elementPosition) {
            element.css({
                "opacity": "0", 
                "transform": "translateY(100px)" 
            });
        }
    });
```
とりあえず下から出したいオブジェクトのクラスを取得させて、
CSSを変更するようにしました。

# 実装
今ホームページに実装してあるので、挙動をみてみてください。

# 最後に
今回 jQueryを勉強しながら作ったので、ちょっと時間がかかりました。
結構頑張った。
ではまた次の記事で
VSCodeでのDevcontainerにおけるextentions関連エラー

# エラー内容

```json
{
	"name": "Python Sample",
	// Dockerfileでイメージ・コンテナを作成
	"dockerFile": "Dockerfile",
	// リモート先のVS Codeにインストールする拡張機能
	"extensions": [//←ここがエラーになる
		"ms-python.python"
	]
	}	
}
```

自分もどこを参考に作ったのか覚えていないのだが、なぜかここで波線表記になる。

# 解決

```json
{
	"name": "Python Sample",
	// Dockerfileでイメージ・コンテナを作成
	"dockerFile": "Dockerfile",
	// リモート先のVS Codeにインストールする拡張機能
	"customizations":{
		"vscode":{
			"extensions": [
			"ms-python.python"
		]
	}
	}
	
	
}
```

こんな感じ
(リンクだけです)「発散定理(英:Divergence theorem)」を調べた。

・ガウスの定理（ガウスのていり、英: Gauss' theorem）とも呼ばれる。
　<　wikipedia より
・**おすすめの文献を教えて下さい。**

# wikipedia

https://en.wikipedia.org/wiki/Divergence_theorem

https://ja.wikipedia.org/wiki/発散定理

# mathematica
・検索だけです。

https://www.google.com/search?q=mathematica+Divergence+theorem&rlz=1CAUHAM_enJP1038JP1038&oq=mathematica+Divergence+theorem&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQABiiBDIHCAIQABiiBDIHCAMQABiiBNIBCDI4MzRqMGo3qAIAsAIA&sourceid=chrome&ie=UTF-8

# youtube
・途中28:20より。「...この式の形は、ガウスの発散定理が使えますよ。...」

https://youtu.be/R88Uj08248I?t=1700

# Qiita内

https://qiita.com/search?q=%E7%99%BA%E6%95%A3%E5%AE%9A%E7%90%86
【自己紹介】Webエンジニアを目指して学習中です

# 自己紹介
はじめまして、Takayuki（@takapontype0924）です。  
現在Webエンジニアを目指している26歳です。

以前は、SESで運用監視やヘルプデスクを担当していました。  
お客様が運用するシステムが正常に動いているかのチェックや障害の際に他部署にエスカレーションしていました。

現在は、前職の業務を通してアプリの設計や開発をしてみたいと思うようになり、フロントエンドやバックエンド、インフラについて学習を進めています。

## プロフィール
|  | 詳細 |
|:-|:-|
|名前|Takayuki|
|年齢|26歳|
|性別|男|
|出身地|兵庫県|
|趣味|ゲーム、釣り、料理|
|前職|SESで運用監視・ヘルプデスク|
|保有している資格|普通自動車第一種運転免許証<br>シスコ技術者認定試験（CCNA）|

仕事関係の経歴は以下の通りです。
|期間|経歴|
|:-|:-|
|2016年3月<br>〜<br>2019年3月|大学受験のために浪人(3浪)|
|2019年3月<br>〜<br>2022年3月|個人事業主でWeb記事やWebページの制作を受託|
|2021年5月<br>〜<br>2021年6月|短期の派遣社員としてWebデザイナー|
|2022年9月<br>〜<br>2023年7月|SESで大手食品会社やセキュリティ会社の運用監視|

## ポートフォリオ
ポートフォリオは制作した背景などを説明した記事のリンクを後日掲載する予定ですので、しばらくお待ちください。

## Webエンジニアを目指したいと思ったきっかけ
先ほど記載した通り、前職の業務を通してアプリの設計や開発をしてみたいと思うようになったのがきっかけです。

前職では運用監視というシステムの正常性の監視や障害時に決められた対応をする業務に従事していて、多くのユーザーが利用していることを知りました。
運用監視の業務はユーザーのシステムを安定的に動かすために必要な仕事ですが、よりユーザーの課題に向き合う仕事をしたいと思うようになりました。

そのため、設計や開発に携わることができるWebエンジニアを目指したいと思いました。

## なぜWeb系？
元々、私は個人事業主としてWeb記事やWebページの作成を受託していました。

そのため、これまでの経験を活かしやすいWeb系のエンジニアを目指すことにしました。
大きく分けて以下の3つを勉強しています。

- フロントエンド 
- バックエンド
- インフラ（クラウド）

### フロントエンド 
個人事業主や派遣のときはWebページの作成をしていたので、持っていたスキルセットは以下の通りです。

- Webデザイン（PhotoShop、Illustrator）
- HTML・CSS（Sass）
- JavaScript（jQuery）

当時の私はJavaScriptをあまり学習していなかったため、コピペで進めることが多かったです。
Webエンジニアとして活躍するためにはJavaScriptは必須ですので、理解できてない部分から学習し、現在では処理の流れを考えながらコードを作成することができます。

JavaScriptが理解できるようになると、以下の学習にも役立ちます。

- React
- TypeScript
- Next.js

実際に以下のようなアプリやブログを作れるようになりました。

![free_search2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617758/3a36b69e-14b2-57b8-00bd-e5777fd48850.png)

[ラクマネイングリッシュ](http://e-rakumane.com/)

![code-deblog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617758/5035df2d-dd3f-07fa-84d4-ea589cc25c5b.png)

[Code Deblog](https://code-deblog.vercel.app/)
（ちなみに、記事の内容は適当です...）

いずれもJavaScriptが基礎ですので、自分でコードが書けるようになってから取り組むことをおすすめします。最終的には以下を用いてフロントエンドの実装が可能です。

- Webデザイン（PhotoShop、Illustrator）
- HTML・CSS（Sass）
- JavaScript
- React
- TypeScript
- Next.js

### バックエンド
バックエンドはフロントエンドの学習で簡単なアプリが作れるようになってから学習を始めました。
そのためゼロから以下を学習しました。

- Node.js
- Express
- TypeScript

保守性を高めるためにもタイプを意識した方が良いと思い、TypeScriptを利用してコードを書きました。Axiosを利用したフロントエンドからのリクエストを処理する内容を書くことが主です。

### インフラ
アプリを起動するにはネットワークとサーバーが必要なので、AWSを学習しました。

最初に学習した内容がVPCやEC2、RDSなので、それらを使った簡単なネットワークを構成し、ポートフォリオで運用しています。
ネットワークは以下のように簡単なものです。

![rakumane-aws.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617758/fe5b4533-319e-012a-8139-9b7238c622f1.png)

しかし、現在はそれら以外にもAWSのサービスが存在しますので、そのようなAWSサービスが要件となるアプリも設計・開発できるように学習中です。

現在、私が学習しているAWSサービスは以下の通りです。

- IAM
- VPC
- EC2
- RDS
- Route 53
- S3

## なぜ幅広く学習するのか？
1つの技術を身につけるだけでは、異なるチームでのコミュニケーションコストが増えるからです。

企業が開発するアプリはフロントエンドからインフラまで要件であることが多いので、1つの技術で完結することはあまりないでしょう。

また、小規模な企業やプロジェクトではチームをまたいでコミュニケーションや施策を考える機会が多いです。

チームやプロジェクトを超える職場であっても活躍できるように幅広く技術について学んでいます。

## 最後に
私は1つの領域だけでなくさまざまな技術を学習していますが、実装できない点は多くあります。
そのため、日々技術について学習し、Qiitaで発信していければと思います。

よろしくお願いします！
InSpec に重大な脆弱性 – CVE-2023-42658

InSpec CLI に重大な脆弱性があることがアナウンスされています。[公式アナウンスリンク）](https://www.chef.io/blog/important-security-update-for-chef-customers)
脆弱性の内容、対処方法、Fix バージョンについて説明します。

#### CVE-2023-42658
公式 CVE リンク：
https://nvd.nist.gov/vuln/detail/CVE-2023-42658
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-42658
重大な脆弱性として報告されており、早急な対処が必要であることがわかります。

#### 影響範囲
InSpec CLI の archive check export コマンド実行時に、InSpec テストコードに悪意のある Ruby コードが実行されてしまう危険性があると説明されています。特に CI/CD パイプラインの中で InSpec がテストとして組み込まれている場合は、特に注意する必要があります。知らぬ間に、意図しない Ruby コードが実行されてしまう危険性があります。

さらに詳しくは、以下の技術ブログで説明されていました。

https://www.chef-sec.com/?p=405
ChatGPTにデータベースを扱わせてみる(プロトタイプ)

# 概要
タイトル通り,ChatGPTにDBを扱わせたい.  
理想的な最終目標としては,適当にデータを入れたらAIが整理してDB化してくれて,必要な時に出せる仕組み.
ほんとは[機械学習の自動化みたいなこと](https://www.itmedia.co.jp/news/articles/2311/09/news106.html)をしたかったけど,めっちゃむずいので保留中.

# 今回実装するもの

画像を置く

ChatGPTのAPIを用いて状況に応じた3通りの回答を生成してもらう.
また,それらはJson形式で出力する.
1. 通常の回答
そのままクライアントへ送信されます.
例 : {type:"answer","message":"回答が入力されます."}
2. DBのテーブル,カラム名の候補を列挙
DBアクセスに必要な可能性のある情報を出力します.
例 : {"type":"db_info","message":[users,members,id,user_id]}
3. SQL文
SQL文を出力し,回答に必要なデータを取得します.
例 : {"type":"sql","message":"SELECT * from users"}


これを用いれば,ChatGPTに質問するだけで,SQL文を書かずに必要なデータを取得できます.

ChatGPT自身に情報を再検索させることが今回の肝


# 実際にやってみた.

 - 全体画面 : ChatGPT4のMyGPTs Create a GPT を使用しています.

## 命令内容

Webサーバー上で管理しやすいようにJson形式の出力を要求する.
また,条件によって分岐できるように,タイプとメッセージの2つを出力させる.

プロンプト例
```
あなたの回答はJson形式で行い,3通り存在する.
1. 適切な回答
正解がわかる内容は,その通りに回答します.
例 : 
{"type":"answer","message":"ここに回答が入る."}
2. DBにアクセスすべきかの判断
足りない情報を取得するために,DBへのアクセスを要求できます.
要求するために,テーブル名になりえる候補,必要なカラム名の候補を配列で出力する必要があります.
例 : 
{"type":"db_info","message":[users,members,id,user_id]}
3. DBにアクセスするSQL文
DBから任意の情報を取得できます.
例 : 
{"type":"sql","message":"SELECT * from users"}
```


## 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/97ab6fd1-beff-a72a-f185-2a65b7b78795.png)

見ずらいので解答欄だけ.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/2e5ba88b-320b-b01c-3b89-1785042c0aed.png)

<details><summary>ログ詳細</summary>
You
こんにちは

DBにアクセスできるChatGPT
{"type":"answer","message":"こんにちは！どのようにお手伝いしましょうか？"}

User
You
山田さんのIDを教えてください
DBにアクセスできるChatGPT
{"type":"db_info","message":["users","members","id","user_id","name"]}

User
You
山田さんのIDを教えてください
{"type":"db_info","message":["users","members","id","user_id","name"]}
DBにアクセスできるChatGPT
{"type":"sql","message":"SELECT id FROM users WHERE name = '山田'"}

User
You
山田さんのIDを教えてください
{"type":"db_info","message":["users","members","id","user_id","name"]}
id:21
DBにアクセスできるChatGPT
{"type":"answer","message":"山田さんのIDは21です。"}

</details>

このように必要な情報をChatGPT自身が取得してくることができる.
なお,`id:21`は指定されたSQL文をDBに充てた場合の出力を想定.


# 今後の展望
Webサーバーにこの機能を実装し,データベースと連結させることによって,将来的にSQLやデータベース知識の必要ないデータ構築が可能になるはずだ！

# Webサーバーへの実装時の注意点
 - 例外処理を必ず書くこと
Json形式で出力と命じているが,100％その通りにしてくれるというわけではない.
失敗した場合の処理を考慮するべき.

 - 生成されたSQL文が正しいとは限らない.
理想は,SQLを実行してみて,その結果が確からしいかAIに判断してもらって,そのあとに初めてユーザーに返答する,みたいな流れがいいかと思う.
というか,作成したいデータごとにプロンプトを変えて実行するべき.

 - SQL文がCREATE文やDELETE文を使用する可能性がある.
言わずもがな,DB接続時のユーザー権限設定を忘れてはいけない.