OmniAICreator/Qiita-1.07M huggingface dataset:
Docker ContextとSSHでリモートのDockerを操作する

Docker ContextとSSHを組み合わせると、ローカルのDockerを操作する感覚で、リモートのDockerを操作できて非常に便利です。本記事では、Docker Contextのセットアップ方法とその使い方について簡単に説明します。


## 前提条件

- ローカルマシンにDockerがインストールされていること
- リモートサーバーにDockerがインストールされていること
- SSHでリモートサーバーにアクセスできること
- （オプション）`jq`コマンドがインストールされていること（JSON形式の出力を扱う場合に便利）

## セットアップ手順

### 1. SSH設定

まず、`~/.ssh/config`ファイルを編集し、リモートサーバーへの接続設定を追加します：

```
Host my-docker-host
    HostName example.com
    User username
    IdentityFile ~/.ssh/id_ed25519
    Port 22
```

この設定により、`my-docker-host`という名前でリモートサーバーに簡単にアクセスできるようになります。

### 2. Docker Context作成

次に、新しいDocker Contextを作成します：

```bash
docker context create my-remote-context --docker "host=ssh://my-docker-host"
```

作成したコンテキストは次のコマンドで一覧表示できます：

```bash
docker context ls
```

### 3. Context切り替え

作成したContextに切り替えます：

```bash
docker context use my-remote-context
```

コンテキストが切り替わったら、あとはローカルのDockerを操作するのと同じ方法でリモートのDockerを扱えます：

```bash
docker images
docker ps
# その他のdockerコマンド
```

## デフォルトのコンテキストに戻る

ローカルのDockerに戻りたい場合は、以下のコマンドを使用します：

```bash
docker context use default
```

## コンテキストの設定ファイルについて

Docker Contextの設定ファイルは以下の場所に保存されます：

```
~/.docker/contexts/meta/{ハッシュ値}/meta.json
```

具体的な場所は以下のコマンドで確認できます：

```bash
docker context inspect my-remote-context | jq -r '.[0].Storage.MetadataPath'
```

この出力は以下のような形式になります：

```
/home/username/.docker/contexts/meta/00e13ed7af55b27622f1d6eab5bec0147e68efe28dc2b12461117afa1a5ed40e
```

設定ファイルの内容を確認するには：

```bash
cat $(docker context inspect my-remote-context | jq -r '.[0].Storage.MetadataPath')/meta.json
```

注意: これらのコマンドを使用するには`jq`がインストールされている必要があります。

## まとめ

Docker ContextとSSHを組み合わせることで、リモートのDockerホストをローカルと同じように操作できるようになります。これにより、複数のDockerホストを管理する際の効率が大幅に向上します。

この方法を使えば、開発環境と本番環境の切り替えや、複数のサーバーでのDockerコンテナ管理が非常に簡単になります。ぜひ、みなさんの開発フローに取り入れてみてください。

## 参考リンク

- [Docker公式ドキュメント - コンテキスト](https://docs.docker.com/engine/context/working-with-contexts/)
- [SSH Config File](https://linux.die.net/man/5/ssh_config)

以上です。質問やコメントがありましたら、ぜひ下のコメント欄でお知らせください。
Pythonで中身のある巨大なCSVファイルを作成する

## はじめに
Pythonで中身のある巨大なCSVファイルを作成する方法を紹介します。
ただし、この方法は作成するのに割と時間かかります。
もっといい方法があると思いますが、ご了承ください。

単純に中身のないモックデータを作成したいのであれば、こちらの記事で紹介した方法がおすすめです。

https://qiita.com/EveSquare/items/f80e3dd2f3f9e0c720c5


## 作り方
事前に`pip install pandas`を実行して`pandas`をインストールしておいてください。

```python
import csv

import numpy as np

column_names = ["id", "name", "price", "category"]
data_types = [np.int64, np.object_, np.int64, np.object_]
num_rows = 40000000

data = []
for _ in range(num_rows):
    row = []
    for col, dtype in zip(column_names, data_types):
        if dtype == np.int64:
            row.append(np.random.randint(low=1, high=10000))
        elif dtype == np.object_:
            row.append(np.random.choice(["A使用量", "B使用量", "C使用量"]))
        else:
            raise ValueError(f"{dtype}は定義されていません")
    data.append(row)

with open("mock_data.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(column_names)
    writer.writerows(data)
```
40000000行のデータを作成しています。
40000000行のデータを作成するのに、約10分かかりました。
40000000行のデータは約1.3GBのファイルになります。
列のデータを適用に作成しましたが、必要であれば変更して使用してください。

## おわりに
いつこのスクリプトが必要になるかわかりませんが、巨大なCSVファイルを作成する方法を紹介しました。
誰かの役に立てば幸いです。
PythonでBMIを計算するプログラムコードを作ってみた

### 前置き
今日は、PythonでBMIを計算するプログラムコードを作りました。
BMIとは、ボデイマス指数のことであり、体格を表す指標として国際的に用いられている指数です。
計算式：［体重（kg）］÷［身長（m）の2乗］身長はcmではなくmで計算します）。
引用元：https://www.e-healthnet.mhlw.go.jp/information/dictionary/metabolic/ym-002.html

### 参考に
BMIの判定基準
引用元：https://keisan.casio.jp/exec/system/1161228732
![Screenshot 2024-07-02 at 11.21.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/f504ab92-8e50-37f5-8f1a-d0b5cd53225a.png)

### プログラムコード
``` python
def calculate_bmi(weight, height):
  bmi = weight / (height ** 2)
  return bmi

# ユーザー入力を受け取る
weight = float(input("体重を入力してください（kg）："))
height = float(input("身長を入力してください（m）："))

bmi = calculate_bmi(weight, height)
print(f"BMIは{bmi:.2f}です。")
```
### プログラムコードの説明
このプログラムでは、ユーザーが体重（kg）と身長（m）を入力すると、BMIを計算して出力します。

### 実際の出力結果
``` python
体重を入力してください（kg）：50
身長を入力してください（m）：1.6
BMIは19.53です。
体重を入力してください（kg）：80
身長を入力してください（m）：1.8
BMIは24.69です。
体重を入力してください（kg）：65
身長を入力してください（m）：1.7
BMIは22.49です。
```
### 出力結果の検証（出力結果は小数点第2位までに設定しています）
1つ目の出力結果：50 / (1.6^2) = 50 / 2.56 = 19.53125
2つ目の出力結果：80 / (1.8^2) = 80 / 3.24 = 24.6913580247
3つ目の出力結果：65 / (1.7^2) = 65 / 2.89 = 22.491349481
出力結果を実際の計算式に当てはめると、数値はちゃんと一致する。

皆さんも時間がある時に、このプログラムコードを参考にして、ご自身のBMIを計算してみてはいかがでしょうか。
5年目SESエンジニア ### IT 初心者向けクラウド入門ウェビナー ’Cloud Practitioner Essentials for Entryを受講してみた

# これからやっていくこと
### IT 初心者向けクラウド入門ウェビナー ’Cloud Practitioner Essentials for Entry の受講

→今のプロジェクトに参画した当初から技術面が全く進歩していない（3年前）ので、今一度初心に戻って基礎からやっていくことにした。

# 自己紹介
・CCNA取得済み
・運用保守　半年
・ネットワーク構築　2年
・営業企画部門で建付け、PMO業務 2年
・なんもできない感がすごくある

# 実現したいこと
・わかりやすく自分を説明できるスキルが欲しい
・今後のキャリアパスにつなげていきたい
・自分でなんか（サービス）作りたい

### IT 初心者向けクラウド入門ウェビナー ’Cloud Practitioner Essentials for Entry　の構成

・クラウドの前提となる、ウェブサービスそのものについてやウェブサービスが持つべき性質、そして、サーバーを構築するCPUやメモリといったIT基礎について紹介されている

### コースの構成
| タイトル　　　　　　　　　　　　　　　　　　　　 | 内容|
| :--- | :--- |
| モジュール１：ウェブサービス<br>モジュール２：AWSクラウドの紹介| ウェブサービスやAWSクラウドがどういうものなのかといった、AWSの学習を始める際に前提となる知識について解説（1モジュールあたり 35-40分） | 
| モジュール３：コンピューティング<br>モジュール４：データベース<br>モジュール５：ネットワーク<br>モジュール６：セキュリティ | 各IT領域についての基礎的な解説と、関連するいくつかの代表的なAWSサービスについて紹介 |
| おわりに | まとめと今後の学習パス |
qlora で学習、ロードしたらsize mismatch

```python
from peft import PeftModel,PeftConfig
from transformers import AutoModelForCausalLM,BitsAndBytesConfig,AutoTokenizer

bnb_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_compute_dtype=torch.bfloat16,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_quant_type='nf4'
    )
    
model = AutoModelForCausalLM.from_pretrained(
    BASE_MODEL,
    device_map='auto',
    torch_dtype=torch.bfloat16,
    quantization_config=bnb_config,
)

# <-- ここに

model = PeftModel.from_pretrained(
    model, 
    PEFT_MODEL, 
    device_map={"":0}
)

```

```python
RuntimeError                              Traceback (most recent call last)
Cell In[9], line 1
----> 1 model = PeftModel.from_pretrained(
      2     model, 
      3     PEFT_MODEL, 
      4     device_map={"":0}
      5 )

File ~/pyenv/rag/lib/python3.11/site-packages/peft/peft_model.py:430, in PeftModel.from_pretrained(cls, model, model_id, adapter_name, is_trainable, config, **kwargs)
    428 else:
    429     model = MODEL_TYPE_TO_PEFT_MODEL_MAPPING[config.task_type](model, config, adapter_name)
--> 430 model.load_adapter(model_id, adapter_name, is_trainable=is_trainable, **kwargs)
    431 return model

File ~/pyenv/rag/lib/python3.11/site-packages/peft/peft_model.py:988, in PeftModel.load_adapter(self, model_id, adapter_name, is_trainable, torch_device, **kwargs)
    986 # load the weights into the model
    987 ignore_mismatched_sizes = kwargs.get("ignore_mismatched_sizes", False)
--> 988 load_result = set_peft_model_state_dict(
    989     self, adapters_weights, adapter_name=adapter_name, ignore_mismatched_sizes=ignore_mismatched_sizes
    990 )
    991 if (
    992     (getattr(self, "hf_device_map", None) is not None)
    993     and (len(set(self.hf_device_map.values()).intersection({"cpu", "disk"})) > 0)
    994     and len(self.peft_config) == 1
...
   2191 return _IncompatibleKeys(missing_keys, unexpected_keys)

RuntimeError: Error(s) in loading state_dict for PeftModelForCausalLM:
	size mismatch for base_model.model.model.embed_tokens.weight: copying a param with shape torch.Size([32001, 4096]) from checkpoint, the shape in current model is torch.Size([32000, 4096]).
	size mismatch for base_model.model.lm_head.weight: copying a param with shape torch.Size([32001, 4096]) from checkpoint, the shape in current model is torch.Size([32000, 4096]).
```

あうあう。

## 解決編
peft で読む前に、 # <-- ここに　に、

```python
model.resize_token_embeddings(32001)
```

で動いてる。大丈夫・・・なような
普通にバグですかね
Pythonで、日英両方で曜日を出力するプログラムコードを作ってみた

### 前置き
今日は、ユーザが年月日を入力したら、その曜日が日英両方で出力されるプログラムコードをPythonで作りました。1週間は月曜日、火曜日、水曜日、木曜日、金曜日、土曜日、日曜日の7日間あります。英語では、Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sundayの7日間で、1週間は成り立っている。

### プログラムコード
``` python
import datetime

# 曜日の日本語名と英語名のリスト
WEEKDAYS_JP = ['月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日']
WEEKDAYS_EN = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

def get_weekday(year, month, day):
    try:
        date = datetime.date(year, month, day)
        weekday_index = date.weekday()
        weekday_jp = WEEKDAYS_JP[weekday_index]
        weekday_en = WEEKDAYS_EN[weekday_index]
        return weekday_jp, weekday_en
    except ValueError as e:
        return str(e), str(e)

# ユーザー入力を受け取る
year = int(input("年を入力してください（例: 2024）："))
month = int(input("月を入力してください（例: 7）："))
day = int(input("日を入力してください（例: 2）："))

weekday_jp, weekday_en = get_weekday(year, month, day)

if "day is out of range" in weekday_jp:
    print("入力された日付が無効です。")
else:
    print(f"{year}年{month}月{day}日は {weekday_jp} ({weekday_en}) です。")
```
### プログラムコードの説明
このプログラムでは、ユーザーが年、月、日を入力すると、その日付の曜日を日本語と英語両方で出力します。入力された日付が無効な場合はエラーメッセージが表示されます。

### 出力結果
``` python
年を入力してください（例: 2024）：2009
月を入力してください（例: 7）：12
日を入力してください（例: 2）：18
2009年12月18日は 金曜日 (Friday) です。
年を入力してください（例: 2024）：2017
月を入力してください（例: 7）：2
日を入力してください（例: 2）：7
2017年2月7日は 火曜日 (Tuesday) です。
年を入力してください（例: 2024）：2022
月を入力してください（例: 7）：8
日を入力してください（例: 2）：14
2022年8月14日は 日曜日 (Sunday) です。
年を入力してください（例: 2024）：1900
月を入力してください（例: 7）：12
日を入力してください（例: 2）：22
1900年12月22日は 土曜日 (Saturday) です。
年を入力してください（例: 2024）：1976
月を入力してください（例: 7）：6
日を入力してください（例: 2）：28
1976年6月28日は 月曜日 (Monday) です。
```
### 出力したこの5つの年月日が本当に正しいかどうか検証してみました。
引用元：https://keisan.casio.jp/exec/system/1177638326
![Screenshot 2024-07-02 at 11.06.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/793ce166-96b4-ff61-7349-455f142dc7ab.png)
![Screenshot 2024-07-02 at 11.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/1b202fba-2778-32e5-6386-e5de95f321b5.png)
![Screenshot 2024-07-02 at 11.07.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/24d2f8da-1f0a-93ac-34cf-ad7ad6e0871f.png)
![Screenshot 2024-07-02 at 11.07.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/463ca2fe-314f-7927-d1f8-0b48ebfc8d49.png)
![Screenshot 2024-07-02 at 11.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/0a0cc924-6d4c-9887-2be9-4c0175ce99b8.png)

このように、実際に2009年12月18日は金曜日、2017年2月7日は火曜日、2022年8月14日は日曜日、1900年12月22日は土曜日、1976年6月28日は月曜日となっており、曜日が一致しています。

皆さんも時間がある時に、このプログラムコードを参考にして、年月日の曜日を確認してみてはいかがでしょうか。
core ファイルの解析方法メモ

# 概要
拙者「コアダンプ＝絶望」という悲しみから脱却したい侍

# ポイント
コアファイル解析のコマンドはこう：
```
$ gdb <実行ファイル> <コアファイル>
```
arm アーキテクチャ向け実行ファイルの解析時はこう：
```
$ gdb-multiarch <実行ファイル> <コアファイル>
```
**注意**

解析する実行バイナリにデバッグ情報が残ってる必要アリ。

ビルドする時は `-g` オプション、`-O0` オプションを忘れずに付けよう、ヨシ！

# 詳細
## コアダンプ？
コアダンプとは、プログラムが強制終了した時にコアファイルを吐き出すこと。

プログラムが強制終了した時のメモリ空間を保存したファイルがコアファイルで、これを解析することで、どこで止まったのか、なぜ止まったのかがふんわりわかる。

解析には `gdb` というツールを使う。

解析時には、実行バイナリのリンケージを解決できる配置にしておく必要があるっぽい。具体的には、実行時にリンクする動的ライブラリ（.so のやつ）とかが、実行環境と同じ位置関係に存在する必要があるっぽい。知らんけど。

## 例
gdb での解析を実行すると、↓のようになる。

`(gdb)` コンソールで `bt` と入力すると、バックトレースが表示され、セグメンテーションフォルト時に何が動いていたかを表示してくれる。

この例では、
- `hoge` 関数（`fuga.c` の 3353 行目）内の `pthread_sigqueue()` 関数でセグメンテーションフォルトが発生し、シグナル `SIGSEGV` が配送されていること
- `pthread_sigqueue()` 関数の第一引数が 0 となっており、スレッド識別子が不正であること

が分かる。

![InkedInkedcore解析1_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124381/e0d920d8-35a9-7c70-719b-4962544267ff.jpeg)

![Inkedcore解析2_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124381/fbfed1fa-bc5b-372d-e208-1407ddb7695f.jpeg)


## 注意

- デバッグ情報が必要
  ビルド時には `-g`, `-O0` をつけるべし。

- Git ディレクトリにコアファイルを置いちゃダメ！
  コアファイルはサイズがでっかい。うっかり Git に登録しちゃうと、「なんかデカいファイルがあってプッシュできない」現象が発生する。ダメ、ゼッタイ。（まあそんなポカをするのは俺くらいだろうけど。。。）
OpenSSHを9.8p1にアップデートする

脆弱性があったらしいので...
https://www.openssh.com/txt/release-9.8

とりあえず, リリースノートにも対策してあると書いてある9.8p1をインストールします．

## 環境
- Ubuntu 
    22.04 LTS
- OpenSSH
    OpenSSH_8.9p1 Ubuntu-3ubuntu0.10, OpenSSL 3.0.2 15 Mar 2022


## アップデート方法
こんな記事書かなくても素晴らしい記事があったので...
`wget`で落としてくるところを
 ```bash
 wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.8p1.tar.gz
 ```
 に置き換えてあげましょう．

https://qiita.com/38pinn/items/699bdf7b03bbeb9c5a74
firewalledのコマンドまとめてみた

# 概要
firewalldが使われ始めて数年が経過したので、改めて学びなおした内容を備忘録的に書いていきます。
## firewalledとは
外部からの不要なトラフィックから保護する方法です。
ルールを定義することで、ネットワークトラフィックを制御することができます。
ゾーン及びサービスの概念を使用しているので、
ルールを知っている者なら触りやすいようにできています。

# コマンド一覧
## firewalledの起動・停止
```shell:起動
systemctl start firewalld
```
```shell:再起動
systemctl restart firewalld
```
```shell:リロード（再読み込み）
systemctl reload firewalld
```
```shell:停止
systemctl stop firewalld
```
## 追加
### サービス名で追加する
コマンドは以下のようになります。
書式）firewall-cmd --add-service=サービス名
サービス名：Linuxで事前設定されているサービス名

サービス「ssh」を追加する時は、以下のようになります。
```shell:サービス追加例
firewall-cmd --add-service=ssh
```
### ポート番号で追加する
コマンドは以下のようになります。
書式）firewall-cmd --add-port=ポート番号/プロトコロ
ポート番号：0～65535まで設定できる（予約されている番号もあるので注意が必要）
プロトコロ：ここでいうプロトコロは、「TCP」や「UDP」の事を言う

ポート番号「50000」,プロトコロ「TCP」で追加する時は、以下のようになります。
```shell:ポート番号追加例
firewall-cmd --add-port=50000/TCP
```
## 削除
### サービス名で削除する
コマンドは以下のようになります。
書式）firewall-cmd --remove-service=サービス名
サービス名：Linuxで事前設定されているサービス名

サービス「ssh」を削除する時は、以下のようになります。
```shell:サービス削除例
firewall-cmd --remove-service=ssh
```
### ポート番号で削除する
コマンドは以下のようになります。
書式）firewall-cmd --remove-port=ポート番号/プロトコロ
ポート番号：0～65535まで設定できる（予約されている番号もあるので注意が必要）
プロトコロ：ここでいうプロトコロは、「TCP」や「UDP」の事を言う

ポート番号「50000」,プロトコロ「TCP」で削除する時は、以下のようになります。
```shell:ポート番号削除例
firewall-cmd --remove-port=50000/TCP
```
## 恒久的
今のままでは一時的な追加・削除になってしまいます。
なので、オプションとして「--permanent」をつけてあげると再読み込みや再起動をした時に同じ設定が反映されるようになります。
書式）--permanent
```shell:サービス追加を恒久的に行う例
firewall-cmd --add-service=ssh --permanent
```
## 参考文献
[Red Hat Document](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/7/html/security_guide/sec-using_firewalls)（セキュリティーガイド＞第5章 ファイアウォールの使用）
windowsにてファイルすべてが差分で競合してしまう。(改行コード疑い)

前提 :
環境はwindows
git bash install済み
min.css,min.jsなどの一行もののファイルではない。

以下ブランチが存在し developがおかしい場合の例
master
develop

masterで文字コード確認 これはlf
````
$ file index.html
index.html: HTML document, Unicode text, UTF-8 text, with very long lines (421)
````

developに移動
````
$ git switch develop
Switched to branch 'develop'
Your branch is up to date with 'origin/develop'.
````

developで改行コード確認 CRLFとなっていた
````
$ file index.html
index.html: HTML document, Unicode text, UTF-8 text, with very long lines (421), with CRLF line terminators
````

masterがlf , developがcrlfなのでdevelopの改行コードがおかしい
developの改行コードを以下で変換し push
````
$ dos2unix index.html
dos2unix: converting file index.html to Unix format...
````

以下コマンドにて改行コードの変換を無視することもできる
````
git config --global core.autocrlf false
````
Pythonで背景透過

## はじめに
`rembg`というPythonライブラリを使って、画像の背景を透過する方法を紹介します。

## インストール
```bash
pip install rembg
```

## 使い方
```python
from rembg import remove

input_path = "input.png"
output_path = "output.png"

with open(input_path, "rb") as i:
    with open(output_path, "wb") as o:
        input = i.read()
        output = remove(input)
        o.write(output)
```

inputの画像はwebp等でも大丈夫です。
outputの画像は背景が透過された画像になりますので、png等で保存してください。

## 使ってみる
以下の画像を使ってみます。

<!-- テーブルで画像を比較 -->
| 元画像 | 透過後 |
| --- | --- |
| ![nekocyanPAKE4524-437_TP_V4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/a167960e-e868-78e7-15dc-7832f4b67c6f.jpeg) | ![nekooutput.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/723c75b5-f9e0-e8cc-83c4-8f81977ab9a7.png) |
| ![KAZUHIRO171013027_TP_V.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/9a6ea821-9601-697c-ac79-8af22878fdfc.jpeg) | ![harioutput.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/f9df7343-5aa0-18e0-c3ea-4ea57bdc89a9.png) |
| ![ER6_1989_TP_V.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/54869fac-8576-024f-b954-07e83f961d0c.jpeg) | ![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/a77a58f6-41d4-c1a8-c026-b4f89ea694a9.png) |

動物の画像はしっかり透過されていることがわかります。
コントラストが低めの画像が若干透過されていない部分があるのがわかります。

## おわりに
ここまで簡単に背景透過できるのは便利ですね。
C 言語で現在時刻を取得する


# 概要
C 言語で現在時刻を取得し、エポック秒から時間、分などの表記に変換する方法をメモ（毎回忘れるので🙃）。

# 方法
コレ↓
```C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

int main(){
    struct timespec ts = (struct timespec){0};
    struct tm       lt = (struct tm){0};

    if(clock_gettime(CLOCK_REALTIME, &ts) == -1){
        fprintf(stderr, "clocl_gettime() failed with errno %d, line %d, file %s\n", errno, __LINE__, __FILE__);
        return -1;
    }

    memcpy(&lt, localtime(&(ts.tv_sec)), sizeof(struct tm));

    printf("Current time: %d/%d/%d, %d:%d:%d\n", lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec);

    return 0;
}
```

# スレッドセーフ版
`localtime()` はスレッドアンセーフとのこと。
`localtime_r()` というスレッドセーフ版を使うと↓のカンジ。

```C
   struct tm newtime;
   time_t ltime;
   char buf[50];

   ltime=time(&ltime);
   localtime_r(&ltime, &newtime);
   printf("The date and time is %s", asctime_r(&newtime, buf));
```
Vim入門ガイド：基本操作と便利なコマンドを学ぼう

## はじめに
自分は普段からvimを使用しているのですが、
はじめのころは特殊な操作方法に慣れるまでに時間がかかりました。
この記事では、初心者の方向けにVimの基本操作と便利なコマンドについて紹介しています。
皆さんもぜひvimmerになりましょう！

## 目次
1.Vimのインストール
2.Vimの基本操作
3.モードについて
4.基本的なコマンド
5.よく使う便利なコマンド
6.設定ファイルのカスタマイズ
7.vimtutorを使った学習


## 1. Vimのインストール

macOS
```
brew install vim
```


Ubuntu/Debian
```
sudo apt update 
sudo apt install vim
```

Windows
公式サイトからインストーラーをダウンロードするか、chocoを使用します。
```
choco install vim
```

## 2. Vimの基本操作
Vimには大きく分けて3つのモードがあります。
`ノーマルモード`、`インサートモード`、`ビジュアルモード`です。

- ノーマルモード: コマンドを実行するためのモード（デフォルトモード）
- インサートモード: テキストを入力するためのモード
- ビジュアルモード: テキストを選択するためのモード


## 3. モードについて
- ノーマルモード
  - ノーマルモードに戻るには、Escキーを押します。
- インサートモード
  - i: カーソルの前に挿入
  - ia: カーソルの後ろに挿入
  - io: 次の行に新しい行を挿入
- ビジュアルモード
  - v: 文字単位で選択
  - V: 行単位で選択
  - Ctrl + v: 矩形選択

## 4. 基本的なコマンド

### ファイル操作
- :w: ファイルを保存
- :q: Vimを終了
- :wq: 保存して終了
- :q!: 保存せずに終了

### 移動
- h: 左に移動
- j: 下に移動
- k: 上に移動
- l: 右に移動

## テキスト編集
- x: 1文字削除
- dd: 行を削除
- yy: 行をコピー
- p: 貼り付け


## 5. よく使う便利なコマンド
### 検索と置換
- /pattern: パターンを検索
- n: 次の一致箇所に移動
- :%s/old/new/g: ファイル全体でoldをnewに置換

### ウィンドウ分割
- :splitまたは:sp: 水平方向に分割
- :vsplitまたは:vsp: 垂直方向に分割
- Ctrl + w + w: ウィンドウ間を移動

### タブ操作
- :tabnew: 新しいタブを開く
- :tabnext: 次のタブに移動
- :tabclose: タブを閉じる

## 6. 設定ファイルのカスタマイズ
Vimの設定ファイル（~/.vimrc）を編集することで、自分好みにカスタマイズできます。以下はおすすめの設定例です。
```
" 行番号を表示
set number

" タブ文字をスペースに変換
set expandtab

" タブ幅を4に設定
set tabstop=4

" インデントを4スペースに設定
set shiftwidth=4

" 検索時に大文字と小文字を区別しない
set ignorecase
set smartcase

" シンタックスハイライトを有効化
syntax on
```

## 7. vimtutorを使った学習
Vimの基本操作を効率よく学ぶために、Vimにはvimtutorというチュートリアルが用意されています。vimtutorは実際に手を動かしながらVimの操作を学べるため、初心者の方に非常におすすめです。
vimtutorの起動方法
ターミナルを開きます。
vimtutorコマンドを入力して実行します。
```
vimtutor
```
![スクリーンショット 2024-06-23 20.52.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330132/b1a62234-d0a6-df5f-4906-aa2319a0fd3f.png)


## vimtutorの内容
vimtutorでは、以下のような内容を学ぶことができます。
カーソルの移動
テキストの挿入と削除
検索と置換
ファイルの保存と終了
ビジュアルモードの使い方

進め方のポイント
各セクションをしっかり読み、指示に従って実際に操作してみてください。
疑問点があれば、vimtutor内でいろいろ試してみましょう。
全体を通して約30分〜1時間程度で完了できます。


## まとめ
Vimは最初は取っつきにくいかもしれませんが、慣れると非常に効率的にテキスト編集が行えるようになります。この記事を参考に、少しずつVimに慣れていってください。
Visual Studioが起動後にすぐに落ちるようになった場合の対処例

## はじめに

Visual Studioが起動数秒後に突然落ちるようになった。
これは、試したことと解決したことのログです。

## 現象

Visual Studioが起動後突然死するようになった。
- ソリューションファイルやプロジェクトファイルを開くとほぼ確実に落ちる
- Visual Studioを空で開くと落ちるときもあるけれど、落ちない時もある

## 試してみたこと

- ReSharperの起動が遅いせいか？と思い、プラグイン関係をアンインストールしてみるが現象は変わらない
- Visual Studio Instllerを見るとVersion 17.10.3への更新があったので更新してみたが現象は変わらない

## 原因と対処

とりあえずログを出してみる。
Visual Studioのインストールディレクトリに移動して、 /log スイッチでログを出してみる。

```
❯ cd  C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE
❯ ./devenv.exe /log C:\temp\vslog.txt
```

エラーがあった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/1cf13f55-6995-5831-451c-165388b370d3.png)

ググってみると類似の事象を発見。
[Visual Studio 2022 crashing on startup](https://learn.microsoft.com/en-us/answers/questions/1116991/visual-studio-2022-crashing-on-startup)

下記のディレクトリにあるライセンスのキャッシュ情報が壊れている可能性があるのでリネームしてみろということなのでリネームしてみる。
%LOCALAPPDATA%\Microsoft\VSCommon\OnlineLicensing

無事起動するようになった♡。

## 壊れたファイル

Answersにもあった通り、何らかの原因で`default.metadata`ファイルが破損したことにより、ファイルがNULLで埋められていたのが原因っぽい（左が壊れたファイル）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/a407567a-dcb2-542d-91d9-edef0c28dc62.png)

## おわりに

何も言わずに落ちると焦る。
よくわからず更新したりすると逆に悪化することもある。まずはログ。
Python FizzBuzz問題

**FizzBuzz**問題とは、「1~100までの値で3で割り切れる場合Fizz、5で割り切れる場合はBuzz、両方で割り切れる場合FizzBuzz」と表示するものです。
多種多様な書き方があるので一部を抜粋

#### 1
```python
for i in range(1, 101):
    if i % 3 == 0 and i % 5 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)
```

#### 2
```python
for i in range(1, 101):
    if i % 3 == 0:
        print("Fizz", end="")
    if i % 5 == 0:
        print("Buzz", end="")
    if i%3 and i%5:
        print(i, end="")
    print("")
```

#### 3
```python
for i in range(1, 101):
    result = ""
    if i % 3 == 0:
        result += "Fizz"
    if i % 5 == 0:
        result += "Buzz"
    print(result or i)
```

#### 4
```python
print(["FizzBuzz" if i % 3 == 0 and i % 5 == 0 else "Fizz" if i % 3 == 0 else "Buzz" if i % 5 == 0 else i for i in range(1, 101)])
```

forやifを使用しない、演算子を使用しないという書き方もあるようです。
今回は基本例4つを紹介しました。
fail2ban sshのポート変更バージョン #メモ

sshでポートを変更した際のfail2banの設定について解説する
環境はUbuntu 22.04

#### 最初に
/etc/fail2ban/jail.confはパッケージアップデートで変わってしまう可能性があるので

```sh
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
```
でファイルをコピーして/etc/fail2ban/jail.localを編集する

### 設定
必要ならかえる
```
ignoreip = 127.0.0.1/8 ::1
bantime  = 10m
chain = INPUT
findtime  = 10m
maxretry = 5
usedns = warn
```

#### action
実際おこなわれるアクションのはここに書いてある
iptablesで特定のipからのポート0-65535へのアクセスをbanする

```
port = 0:65535
banaction = iptables-multiport
banaction_allports = iptables-allports
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action = %(action_)s
```

アクションは/etc/fail2ban/action.d/iptables-multiport.confで定義されている

##### sshd


sshdの監視を有効にするのは
```/etc/fail2ban/jail.d/defaults-debian.conf
[sshd]
enabled = true
```


/etc/fail2ban/filter.d/sshd.confでfilterしている
```
filter = %(__name__)s[mode=%(mode)s]

[sshd]
port    = $your-port
logpath = %(sshd_log)s
backend = %(sshd_backend)s
```

sshdの設定をかえておく
```/etc/ssh/sshd_config
LogLevel VERBOSE
```

そのままだと下記のエラーがでるので
```
ERROR   Failed during configuration: Have not found any log file for sshd jail.
```

```/etc/fail2ban/paths-overrides.local
[DEFAULT]
default/backend = systemd
```
とする

このファイルは以下で読み込まれている
```/etc/fail2ban/paths-common.conf
after  = paths-overrides.local

default_backend = %(default/backend)s

sshd_backend = %(default_backend)s
```

#### 起動
実際に起動して確認
```sh
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2024-06-28 17:54:26 UTC; 5s ago
       Docs: man:fail2ban(1)
   Main PID: 22196 (fail2ban-server)
      Tasks: 5 (limit: 1065)
     Memory: 16.7M
        CPU: 338ms
     CGroup: /system.slice/fail2ban.service
             └─22196 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Jun 28 17:54:26 servername systemd[1]: Started Fail2Ban Service.
Jun 28 17:54:26 servername fail2ban-server[22196]: Server ready

```

#### References
[centos - fail2ban iptables having port 22 and fails to block ssh on custom port - Server Fault](https://serverfault.com/questions/522191/fail2ban-iptables-having-port-22-and-fails-to-block-ssh-on-custom-port)

[How Fail2Ban Works to Protect Services on a Linux Server | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-fail2ban-works-to-protect-services-on-a-linux-server)

 [[BR]: fail2ban does not start on some debian/ubuntu systems - backend should probably be set to systemd on all systemd-based distros #3292](https://github.com/fail2ban/fail2ban/issues/3292)
MIMEタイプと拡張子【ブラウザ】

# はじめに

拡張子（`.js`, `.html`など）は「そのファイルが何について記述されているか / 情報があるか」を示します。

VSCodeでは、この拡張子に基づいてシンタックスハイライトやフォーマットを行います。
人間も、おおよそこの拡張子に基づいて内容を判断するでしょう。

しかし、ブラウザでは違うようです。

# MIMEタイプ

> 警告: ブラウザーは URL を処理する方法を決定するために、ファイル拡張子ではなく MIME タイプを使用しますので、ウェブサーバーは正しい MIME タイプをレスポンスの Content-Type ヘッダーで送信することが重要です。

https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types

ブラウザではMIMEタイプというものを使用し、ファイルを解釈するようです。

例えば、（バニラの）Node.jsでは以下のような記述をします。

```js
const app = http.createServer((request, response) => {

    response.writeHead(200, { 'Content-Type': 'text/html' });
    
    fs.readFile('./view/index.html', (errors, data) => {
        response.end(data)
    });
});
```

- ヘッダーに以下の２つを設定
    - HTTPステータスコード`200`
    - `Content-Type`として、MIMEタイプ`text/html`
- FileSystem`fs`を使用し、`index.html`を読み込み
- responseとして`index.html`を送信し終了


この時、MIMEタイプ`text/html`は必須です。
（`index.html`の`.html`拡張子からは判断ができない）

# MIMEタイプの構造と種類

`タイプ/サブタイプ[;引数=値]`

## 例
`.html`
> `text/html`

`.css`
> `text/css`

`.js`
> `text/javascript`

## 引数を使う例：文字コードの指定
`.txt` / 未知のテキスト形式
> `text/plain;charset=UTF-8`

## サブタイプに`+`を含む例
`.svg`
> `image/svg+xml`




# 参考

https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types

https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
Reactで可愛いアバターアイコンを自動生成しよう!

## はじめに
Reactで可愛いアバターアイコンを自動生成するためのライブラリ「boring-avatars」を紹介します。

https://github.com/boringdesigners/boring-avatars

## 使い方
非常にシンプルです!

```bash
npm install boring-avatars
```

```jsx
import Avatar from "boring-avatars";

const App = () => (
  <Avatar
    name="適当な文字列"
    size={40}
    variant="marble"
  />
);
```

`name`に入れた文字列によってアバターアイコンが変わります。
ここをユーザ名などにすれば、ユーザ名に応じたアバターアイコンを自動生成することができますね。
variantには`marble`,`beam`,`pixel`,`sunset`,`ring`,`bauhaus`があります。
それぞれのサンプルを見てみましょう。

こちらのサイトでもサンプルを試すことができます！

https://boringavatars.com/


### marble
![marble.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/43bb28e3-e2b6-5088-ef48-54feb542c8ec.png)

### beam
![beam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/8b35896e-f2e3-5a42-6e09-83d5ba763c2c.png)

### pixel
![pixel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/7237ca65-af2a-2d3f-5de0-99350e2114e4.png)

### sunset
![sunset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/d3bfe1ce-fd43-a688-2f04-f277453a26a0.png)

### ring
![ring.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/a8ad72ef-8d4a-68c3-b715-e874e7978a24.png)

### bauhaus
![bauhaus.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/1a6577d7-69bd-affc-cf54-3177c37f1fec.png)

## おわりに
Webサービスを作る際の参考になれば幸いです。
秘匿情報を gradle.properties で管理する

## 目的
外部 Webサービスの APIキーなどをソースコード中に入れておくと、うっかり githubへ pushしたときなどに悲惨なことになる。 大事な情報は gitignoreしたファイルで管理し、ビルド時にそれを参照するようにすると安全。

## 方法

### app/gradle.propertiesを作成

API KEYなど重要な情報を管理するファイル。 このファイルは .gitignoreに追加して gitの管理外にしておく。

```gradle.properties
API_KEY="xxxxxxxxxx"
```

### app/build.gradle.kts

```build.gradle.kts
android {
    defaultConfig {
        buildConfigField("String", "SECRET_API_KEY", project.properties["API_KEY"] as String) // 追加
    }

    buildFeatures {
        buildConfig = true  // 追加
    }
```

BuildConfigがデフォルトで作られなくなっているので `buildConfig = true` を設定する。

### コード中での利用

buildConfigFieldで宣言した値はコード中で `BuildConfig.SECRET_API_KEY` のように参照できる。

```Constants.kt
const val SECRET_API_KEY = BuildConfig.SECRET_API_KEY
```

## 気になったこと

いつから `buildConfig = false` が標準になったのだろう 🤔 と思って調べたところ以下の記事があった

https://takerpg.hatenablog.jp/entry/2023/04/22/210928

> BuildFeatures.ktを見るとbuildConfigのデフォルト値がfalseになっていた。 Androidの公式サイトのドキュメントはtrueのままだったが、今後更新されるのかもしれない。

今後はあまり推奨される方法ではないのかもしれない。 そのときはそのときで別の方法を調べる。
TypeScript用　型一覧【自分用】

| 1 | 2 |
|:-:|:-:|
| 真偽 | boolean |
| 数字 | number |
| 文字列 | string |
| リスト(文字列) | string[] |
| リスト(数列) | number[] |
| オブジェクト | interface |
| なんでも | any |
【BEM】Blockで使いそうなクラス名


BEMのBlockで使いそうなクラス名メモ！

- header: ヘッダーセクション
- footer: フッターセクション
- menu: メニューコンポーネント
- button: ボタンコンポーネント
- form: フォームセクション
- card: カードやパネルコンポーネント
- sidebar: サイドバーコンポーネント
- modal: モーダルダイアログ
- carousel: カルーセルコンポーネント
- avatar: アバターコンポーネント
- list: リストやリストアイテム
- tab: タブメニューやタブパネル
- slider: スライダーコンポーネント
- breadcrumb: パンくずリスト
- modal: モーダルウィンドウ
- notification: 通知メッセージ
- search: 検索フォームや検索結果
- header-nav: ヘッダーナビゲーション
- footer-nav: フッターナビゲーション
- article: 記事セクション
【BEM】Modifierで使いそうなクラス名


BEMのModifierで使いそうなクラス名メモ！

- --active: アクティブな状態を示す。
- --disabled: 無効な状態を示す。
- --hidden: 非表示状態を示す。
- --hover: ホバー時のスタイルを示す。
- --focus: フォーカス時のスタイルを示す。
- --error: エラー状態を示す。
- --success: 成功状態を示す。
- --large, --small: 大きさを変更する。
- --dark, --light: テーマや色のバリエーションを示す。
- --primary, --secondary: 要素の重要度や順序を示す。
- --rounded: 角丸のスタイルを示す。
- --uppercase, --lowercase: テキストの大文字小文字を変更する。
- --transparent: 背景が透明であることを示す。
- --animated: アニメーションを持つ要素であることを示す。
- --sticky: 要素が固定配置されていることを示す。
- --outlined: 輪郭線のスタイルを示す。
- --shadow: 影のスタイルを示す。
- --full-width: 要素が親要素の幅いっぱいに広がることを示す。
- --center: 要素が中央揃えされていることを示す。
- --gradient: グラデーションのスタイルを示す。
PowerShell で cd したら Python 仮想環境 (venv/virtualenv) に入る設定

# はじめに

毎度のアクティベートが面倒なのと、最近のバージョンでは PDM のバグの影響で、`Invoke-Expression (pdm venv activate)` を実行してもアクティベートされずに、ps1 ファイルのパスだけ返してくるのがストレスだったので、いっそのこと cd でアクティベートできるようにしてしまおうというのが最初のモチベーション。

Linux 系の記事は見つけたが、意外と PowerShell での設定の仕方がなかったので調べた。
とりあえず出来たので、メモ。

# 設定方法

## PowerShell プロファイルの確認

以下で PowerShell プロファイルのパスを確認できる。

```powershell:PowerShell
$PROFILE
```

対象のファイルをテキストエディタで開く。
(以下はサンプルとして NeoVim で開く例)

```powershell:Powershell
nvim $PROFILE
```

## スクリプトを記述する

```powershell:Microsoft.PowerShell_profile.ps1
# Cd コマンドをカスタムするための関数を作成
function Set-LocationAndActivateVirtualenv {
    # Path パラメーターを取得
    param (
      [string]$Path
    )

    # デフォルトのロケーション移動のふるまいを実行
    Set-Location -Path $Path

    # Virtualenv が存在するか確認して、アクティベート
    if (Test-Path -Path ".\.venv\Scripts\Activate.ps1") {
        & .\.venv\Scripts\Activate.ps1
    } elseif ($Env:VIRTUAL_ENV) {
        # 仮想環境に入っていると `VIRTUAL_ENV` 環境変数にパスが入っているので、
        # それを確認して `deactivate` を実行。
        deactivate
    }
}

# cd コマンドのコールバックをオーバーライド
Set-Alias -Name cd -Value Set-LocationAndActivateVirtualenv -Option AllScope
```

# 因みに他の環境では？

以下のポストらが参考になる。

## Unix Shell 系

https://qiita.com/rinodrops/items/ae598b1521b41ddfa2e1

https://qiita.com/zmtkr/items/365655fe6e2a4072e962

## direnv を使う系

よりシステマチックかつサードパーティに頼る場合はこっち。

https://qiita.com/kompiro/items/5fc46089247a56243a62

# まとめ

これで、`cd` 移動 + `.venv\Scripts\Activate.ps1` を毎度入力する必要がなくなった。小ライフハック。
基本 `.venv` を配置している個所にしか有効ではないが、基本的に `.venv` は作業スペースのルートに配置するし、そこをルートとしての作業しかしないので、とりあえずはこれで問題ないという判断。

もし、`.venv` 以外の名前を付ける習慣がある場合は、このスクリプトを改造すればいいだろう。
Proxy下でRaspberry Piのaptを使用する。

学校のネットワークでRaspberry Pi(以下RasPi)を使用する時、プロキシ下の制限がある状態で使用しなければならない状況があると思います。
プロキシ下でaptを用いたパッケージのインストールを可能にする方法を記載していきます。

1. プロキシ設定ファイルを開く
```shell
cd ~
sudo vim /etc/apt/apt.conf
```
vimでなくnanoでも構いません。

2. 以下の内容を```apt.conf```に追加する
ポート番号が8080の場合、以下のようになります。
*****の部分には、プロキシのアドレスを入力してください。
```diff_shell
+ Acquire::ftp::proxy "ftp://proxy.*********:8080";
+ Acquire::http::proxy "http://proxy.*********:8080";
+ Acquire::https::proxy "https://proxy.*********:8080";
```

プロキシ下でaptを使用することができるようになります。
試しに以下のコマンドを実行し、エラーが表示されないか確認します。
成功している場合「既に入っている」というメッセージが表示されるか、インストールが完了します。
```shell
sudo apt install vim
```
macOS: Mission Controlのデスクトップを自動で追加するAppleScript

## 概要
本記事では、AppleのMission Controlでデスクトップを自動的に10個追加するためのAppleScript（JSA: JavaScript for Automation）を紹介します。このスクリプトを実行することで、手動でデスクトップを追加する手間を省き、効率的に環境を整えることができます。

### デモ動画

<div align="center">
<iframe width="560" height="315" src="https://www.youtube.com/embed/hYowiQJjRNo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

デモはわかりやすさのために各操作ごとに１秒待つ `delay(1)` を指定しているため、ゆっくりに見えますが、実際は一瞬で終わります。

### 動作環境

おそらくUIが変更されない限り最新のmacOSでも使えると思いますが、動作確認した環境は次のとおりです。

- MacBook Pro 16-inch, 2023
- macOS Sonoma 14.5

## スクリプト内容

以下のスクリプトを使用します。このスクリプトは、Mission Controlを起動し、デスクトップを最大10個まで自動的に追加します。

```javascript:create-spaces.js
#!/usr/bin/env osascript -l JavaScript
const MAX = 10;
Application("Mission Control").launch();
const systemEvents = Application("System Events");
const { Dock } = systemEvents.processes;
const missionControl = Dock.groups.byName("Mission Control");
const spacesBar = missionControl.groups.at(0).groups.byName("Spaces Bar");
const spaceButtons = spacesBar.lists.at(0).buttons;
const addButton = spacesBar.buttons.at(0);
while (spaceButtons.length < MAX) {
  systemEvents.click(addButton);
}
systemEvents.click(spaceButtons.at(0));
```

## 使い方

ターミナルで以下のコマンドを実行します。スクリプトファイルに実行権限を付与することを忘れないでください。

```shell
chmod +x create-spaces.js
./create-spaces.js
```

このスクリプトは、Mission Controlを起動し、デスクトップを自動で追加していきます。最大10個までのデスクトップが作成されると、最初のデスクトップに戻ります。

## まとめ

今回紹介したAppleScript(JSA)を使うことで、Mission Controlのデスクトップを簡単に増やすことができます。これにより、作業環境を整えやすくなり、効率的に作業を進めることができます。ぜひ試してみてください。
AWS RDS でデータベースのバックアップ(スナップショット)からデータを復元してアプリケーションから接続する

# STEP 1. DBスナップショットでバックアップを作っておく

( 自動バックアップから復元したり「特定時点への復元」をする場合はこの手順は不要 )

- DBクラスタを選ぶ
- てきとうな名前をつけてスナップショットを作成する

![CleanShot 2024-07-01 at 11 24 50@2x](https://github.com/YumaInaura/YumaInaura/assets/13635059/7949004e-65e0-4173-8bce-9721b9b735f1)


# STEP2. 復元する

## 仕組み

AWS RDS の仕組みとして、復元操作をしても元となったDBの状態が上書きされるわけではなく、いったん別のDBクラスタが作成される。

このため、この復元操作以外にも作業が必要だが、それは次の STEP 3で説明する。


## 方法A. 手動スナップショットからの復元

### 注意

元のスナップショットから全ての設定を復元してくれるわけではなく

- セキュリティグループの設定
- スペックの設定

など、選び直さなければばいけないものもあるので、注意して適切なものを選び直す

既存DBクラスタ・インスタンスの設定と見比べてから復元した方が良いかもしれない

### 手順

- スナップショットを選んで復元する
- 適当なRDSクラスタ名をつけて復元する ( ここでは例として `recover` という名前を付けたこととする  )

<img width="1512" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/a86c4554-6322-4636-8719-a9f90ba88ee9">

## 方法B. 特定地点からの復元

- 日時を選んで復元できる
- 手動でバックアップしていなくても復元できるし、復元したいポイントが日時で分かっている場合は非常に助かる
- 手動での復元とは違って、セキュリティグループやスペックも当時のまま保持してくれているようだ

<img width="1512" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/52ebeca0-e2f3-440d-aa0f-f6eeed658120">

# STEP 3. アプリケーション 対 DB 間の接続の調整

何らかの形で、アプリケーションが復旧後のDBに紐付くエンドポイントを参照するようにする。

## 方法A - アプリケーションが参照するDBエンドポイントを変更する

DB復元後に生成されたクラスタ、インスタンス、DBエンドポイントをそのままアプリケーションから利用する方法。

この方法ではDB切断が発生しない。

まずはアプリケーションが接続するDBエンドポイントを、復元後のDBのものに差し替える。

たとえば

- BEFORE `now.cluster-*********.<region>.rds.amazonaws.com`
- AFTER `recover.cluster-*********.<region>.rds.amazonaws.com`

のように変更する。

アプリケーションの構成やデプロイの仕組みにもよるかもしれないが、この場合はアプリケーションの再デプロイ / 再起動などが必要なはずだ。なので必要があればアプリケーションの再デプロイ / 再起動をする。

ただし Terraform で AWS構築をしている場合など、RDS設定とインフラコードに差分が生じてしまう場合は、インフラコードでもつじつまを合わせるための調整が必要になる。

## 方法B - AWS で DBエンドポイントを差し替える

AWS RDS でDBの「クラスタ識別子」(またはインスタンス識別子)の命名を付け直すことで、DBに紐づくエンドポイントも入れ替えることが出来て、正しい状態に戻せる。

「アプリケーションの接続先のDBエンドポイントのパス」自体は変えずに、DBエンドポイント 対 DB の対応を変える方法。

ただしこの場合、DBクラスタ識別子を変更している最中には「アプリケーションからの接続先のDBエンドポイントが存在しない時間」が発生してしまい、DBの切断が発生する。

### 手順

たとえば RDSの DB クラスター識別子が次の命名だった場合

- `now` (以前から利用していたクラスター識別子)
- `recover` (バックアップから復元したクラスター識別子)

次のように名前をつけ直せば、

- `now` -> `old`
- `recover` -> `now`

DBエンドポイントもそれぞれ以下のように変わる

- `now.cluster-*********.<region>.rds.amazonaws.com` 
- `old.cluster-*********.<region>.rds.amazonaws.com`

すなわち、以前から利用していたDBエンドポイントのパス自体は変えずに、DBを復元後の状態に入れ替えることができる

この方法ではアプリケーションの再デプロイは必要ない

### NOTE

アプリケーションが「インスタンス識別子を使ったDBエンドポイント」を利用している場合は、インスタンス識別子の方を変更する必要がある

- DBクラスタ識別子 のエンドポイントの例: `db.cluster-********.<region>.rds.amazonaws.com`
- DBインスタンス識別子のエンドポイントの例: `db.********.<region>.rds.amazonaws.com`

# STEP 4.  復元前のRDSクラスタ・インスタンスを削除する

- DBが起動したままだとかなりお金がかかるので、きちんと削除する。
- 削除保護を無効化してから削除しよう。



# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
IBM i Services Directory : QSYS2.JVM_Info() 表関数　処理時間上限を設定できる

QSYS2.JVM_INFOビューと同じ情報を取得できます。ヒープ、GC情報の他にJVMの基本的情報を取得できます。JVM情報の取得に非常に負荷がかかる場合を想定して、最大処理時間を制限するパラメーターがあります。

## 概要
■表関数名：QSYS2.JVM_INFO
■カテゴリ：Javaサービス
■サポート：IBM i 7.4 SF99704 Level 25以降
■参照URL（IBM i 7.5）：https://www.ibm.com/docs/ja/i/7.5?topic=services-jvm-info-table-function

## 使用例

```
SELECT * FROM TABLE(QSYS2.JVM_INFO(WAIT_TIME => 10));
```

上記の例ではWAIT_TIME 10秒以下を指定します。各JVMからの情報取得が10秒より長くかかる場合、情報収集を中止します。（そのJVMについてはジョブ名、PROCESS_IDだけが返されます。

*WAIT_TIMEの値は1、2、3、4、5、10、30、60、および 120秒を指定可能です。（これ以外の値も指定可能ですが、左記の秒数に切上げされ実行します）

実行例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/b2f39aec-dc73-6981-e56a-1116ee9f662e.png)

スレッド数やGC時間、カウント（画像切れてます・・）の取得はQSYS2.JVM_INFOビューと同様ですね。

それ以外の取得データもJVM_INFOビューと同じ情報でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/4261dd56-4475-2098-b424-f10ff1da5022.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/90a274de-f782-3572-3c8a-911b6dd07232.png)

QSYS2.JVM_INFOビューではJVM情報取得に時間がかかる可能性がある場合、こちらを使用するのが適切なようです。
DDコンを手持ちの部品で作る

## はじめに
こんにちは、いつの間にか「作ろう」と思ったらそこに部品がある状態になってしまった(至って通常)bockringです。

今回はArduinoに入力した12Vの電源を昇圧するDDコンを作ります。あいにくArduino UNOが手持ちにないので**Arduino DUEで作成します**。DUEはPWMの周波数が少々高いですが3.3Vです。その点は不安ですが、気にしなかったことにします。

他の用途でも使用しますので、シールド型での自作です。

## 使用部品・回路図
部品
- 2SK3499(Nch MOSFET/400V10A Rds=0.4Ω)
- D3F60(ダイオード/600V3A)
- Inductor 1mH
- アルミ電解コンデンサ(350V 47uF) x2個(並列)
※試験時は手持ちのIRF740を使用しました。

実はこの中のインダクタ以外は抜き取った部品だったりします。詳しくは

https://qiita.com/bockring/items/3bce79b1cae3e63b1469

をご覧ください。このインバータ基板から抜き取ったMOSFETとダイオード、そして電解コンデンサです。

イチケンさんの動画でも紹介されていますので詳細は省略しますが、

インダクタに蓄える電力は
```math
W=LI^2/2
```
で、スイッチングのPWMのオン時間、オフ時間をそれぞれ
```math
Ton, Toff
```
とおくと、出力される電圧は
```math
Vo=Vi(Ton+Toff)/Toff
```
となります。ArduinoのPWMは8ビット、つまり256段階(0~255)になります。理論上の最大出力出さないというか、100Vくらいが出せたら良いです。12Vから100V、つまり8倍程度なので頑張ってもらいましょう。

では、100V出力時のデューティー比を算出します。
```M
 100=12*255/Toff
   5=3*51/Toff
   5=153/Toff
Toff=30.6
   D=(255-30.6)/255
   D=224.4/255
```
つまり、`digitalWrite(5, 225);`を実行すれば100V程度の電圧が生成できそうです。PWM的には200Vくらいまでなら行けそうですが、インダクタやキャパシタが耐えられなくなる可能性もあるので、やめておきます。というか、Arduinoで高電圧の制御を(リレーなどで)するならまだしも生成するのはマジで頭悪いなと思いつつ(ry

ここに来てようやく回路図です。昇圧方式はBoost Converterです。電圧の範囲は入力の12V〜100Vです。出力の調整は可変抵抗の電圧の読み取りで行います。この回路は画像には含んでいません。察してください。


## 試験
まずは24Vで試験します。と言いたくなりました。とりあえずコードです。
```C
#define FET 5

void setup () {
  pinMode(FET, OUTPUT);
}

void loop () {
  analogWrite(FET, 128);
  delay(1000)
}
```
ここで問題発生。使用したMOSFET(IRF740)のスレッドショルド電圧は約2.0V。そしてVgsはもっと高いのです。

　**ダメです！動作しませーん！**

ということで今度UNOを買ってやります。追記という形でやります。

## DUEでリベンジ(2024/07/04~追記)
なんとかDUEでリベンジできないかと考えた結果、なぜか
　**「リレーで代用してみようかな」**
という考えに至りました。逆にこれで成功したら笑ってしまいます。物理的に動くので、ESC、ESLなどの問題以外に、スイッチングできるのか問題があります。まぁ自己保持回路で間違った回路を組んだ時に、かなり高速でスイッチングできたので…行けるかな…**あ！これだ！(破滅の音)**

:::note info
### 自己保持回路とは
自己保持回路とは、電子部品などの自らの状態を保つ回路のことです。例えば、リレーではコイルに接続されているピンに電圧をかけることで閉じますが、その閉じた先のピンのNO(Normal Open)からコイルのピンに電流を流すことで閉じ続けることができる、そんな回路になります。
:::

ということでただひたすら意味不明な回路図です。ここでは、逆にNC(Normal Close)ピンとコイルを接続することで

NCの電流がコイルペン流れる
↓
リレーが閉じる
↓
NCから電流が流れなくなり、リレーが開く

を繰り返すというあまりにアナログ過ぎる回路です。**あれ、Arduinoである必要が無くなっちゃった。(破滅の音その2)** あまりにアナログ過ぎる昇圧チョッパになってしまいました。**てかこれじゃぁリレー的に5Vから10Vへの昇圧しかできないんですが。(破滅の音その3)**

**今度試します。**

## おわりに
**投稿数稼ぎ完了〜★**

現状すごい間違った道に進んでいる気がしますが、原理検証(?)ができればOKということでやっています。成功すればSeeed XIAOとMOSFETで昇コンバータを自作します。
Salesforce: 国税庁法人番号サイトを利用して取引先の重複を軽減しました

Salesforceで取引先が増えてくると、同じ会社が複数登録されてしまう問題がおこりがちです。そこで、極力重複を避けるため、また重複を発見しやすくするために、国税庁の[法人番号公表サイト](https://www.houjin-bangou.nta.go.jp/)というのを利用してみました。こちらのサイト、Web-APIというのが用意されていて、プログラム的にもアクセスすることができます。今回はこちらについて私どものやっている方法を紹介します。
## 取引先に「法人チェック」追加
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/b86da7bc-b22f-291e-1da2-5768b33b38ec.png)

取引先オブジェクトに「法人チェック」というボタンを追加し、取引先名から法人番号検索を行えるようにしています。該当するのが1社でない場合や間違っている場合もありますので、確認してもらってから「適用」で上の情報を取引先オブジェクトに書き込むようにしています。
## 法人番号サイトを利用するメリット
法人番号は企業をユニークに特定することができますので、取引先オブジェクトに法人番号をカスタムフィールドとして追加することで重複を検出することができます。
ただそれ以外にも、法人番号サイトは(企業が登録していれば)次の情報を提供してくれます。
* **ヨミガナ** - これ強力です。取引先にヨミガナのカスタムフィールドを追加することで、50音順にソート表示することができるようになり、企業の検索や重複の発見に役立ちます
* **住所** - 取引先の住所を埋めるのもいいですが、企業名で法人番号を検索すると同名の会社が複数出てくることがありますので、どれが目的の企業か識別するのにも役立ちます
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/2493fd92-12f6-1630-783e-6fe36eac348c.png)

* **英語名** – 英語名を登録している企業は多くありませんが、海外と取引している場合は便利です。英語の住所も登録されている場合があります

すべての企業が法人番号サイトに登録されているわけではありませんが、私の取引先のほとんどは登録されていました。
## 法人番号の取得
[Web-API](https://www.houjin-bangou.nta.go.jp/webapi/#web-api02)の利用には手続きが必要です。「法人番号システムWeb-APIのみを利用される方」だとだいぶ手続きが簡単になります。
API自体はすごくシンプルで、次のような感じで呼び出しができます。Salesforceのリモートサイトの設定もお忘れなく。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/2f995294-b10b-5ffc-dc78-bd285600dd36.png)


呼び出しが成功すると、次のようなヘッダー行つき ’/r/n’ 改行の csv形式の文字列がレスポンスボディに返されます。詳しくは Web-API の仕様書をご参照ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/75529c81-93c9-851e-d3ff-8199f05bf410.png)



## 検索する法人名について
先ほどのコードでは coreName という変数で指定している法人名ですが、いくつか注意が必要です。(私が開発していたとき(2023年10月前後)の情報ですので、変わっているかもしれません)
* 英数記号も含め全角である必要があります
* 「株式会社」など法人格がついていると検索に失敗します
* スペースなどは削除します
 
私のところではSalesforceの法人名は法人格つき半角英数記号にしているので、変換が必要です。
下はコード例です：![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/410b30d3-aa2f-a10f-10ee-433a34df48a3.png)

きれいなコードではないですが、全角に変換するコードも紹介します：![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/cf498c05-7a55-a8e7-b306-32a9bd284d93.png)


## 返される法人名について
返される法人名についてもいくつか注意が必要です
*	法人格つきの全角英数記号となります
*	記号が統一されておらず ‘-‘ など紛らわしいものがある。検索結果を表示するとき、完全一致か部分一致か区別して案内しているので厄介でした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/42978877-2eb5-7c50-a15f-b6ef6e333992.png)
Salesforceでは法人名半角英数記号にしているので変換しています。以下コード例です：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/f6fd7cca-92d2-80c8-d24a-15a54044e582.png)

半角変換は全角変換の逆をしています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/5607d5a6-d7d0-e2e8-2ce1-ea9e944c4c3b.png)


あと、Apexで CSV を扱う良い方法を知らずつい手書きしてしまいましたので、ご参考までこちらも共有します。ダブルクォーテーションで囲まれた文字列の中にカンマがあることがあるので、単純に Split(‘,’) ではうまくいきません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768107/589ec81a-b31e-f4cf-6c3f-63e1d9b0717e.png)


本日は以上です。この機能でだいぶ重複登録を減らすことができました。今回紹介した実装は Salesforceで1取引先について照合する機能ですが、実際はすでに登録済みの取引先に対してバッチ処理で企業情報を取得する Python コードも書いております。

ご意見ご感想ご指導など、コメントお待ちしております。
GoogleドキュメントでLaTexを使用する方法

GASでgoogleドキュメントにLaTexを導入することができないか検討していたら、既に拡張機能にあった。

[拡張機能のAuto-LaTeX Equations](https://workspace.google.com/marketplace/app/autolatex_equations/850293439076)を使用することでTeXを使用可能になる。

```
$$\frac{1}{2}$$

$$m(t)=K_p e (t) + K_i \int_{0}^{t} e(t)dt + K_d \frac{de(t)}{dt}$$
```
上記のように、数式に変換したい部分を```$$```で囲むことにより使用が可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/3da7eaee-7d56-3196-1e75-cc69672afb76.png)

「拡張機能」→「Auto-LaTeX Equations」→「Start」で以下のようなUIが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/1b4bf6fa-d038-77b0-fdec-745af4eabcda.png)

「Render Equations」で数式の変換
「DE-RENDER ALL EQUATIONS」で数式を元の文字列に戻す
「Select Size」でフォントサイズの指定

ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/c2e84338-10f9-2189-1ea9-04f5c65173d9.png)
これが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/083160d7-87f8-a5ee-4d11-5d8b7ab8581d.png)
こうなる。
Mendixとエンジニアのお話〜第1.5章：サンプルアプリを準備するぞ〜

# 今回はこんな記事を書いていきます
Mendixの説明用に、サンプルアプリを作成する回です。
Mendixの機能的な部分には触れないので、見なくても大丈夫！
UIの説明をするためにMendixでサンプルアプリを作成したり、Mendix Proをインストールする必要があったりで、その過程が結構長くUIの説明をする前に結構文量が多くなってしまい、急遽1.5章と言う位置付けにした訳ではないですからね。本当に。違いますからね。
※手順や方法は随時更新されている可能性もあるため、最新の情報を合わせてご確認ください。

# まず動かすアプリを作ってみよう
今後の説明用に、とりあえず動かすアプリを作成します。
Mendixのアカウントを作成後、「Create App」を押します。
（登録手順を色々省いてしまってすみませんという気持ち。道なりに手順を踏めば大丈夫のはず。）
![サンプルアプリ新規作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/0375e30e-caad-106a-be36-a8af37d12cb1.png)

少し待つと、テンプレートなどを選ぶことができる画面に変わるので、使用したいテンプレートを選択します。はい、適当にこれで。
![テンプレート選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/7160e977-4eaf-864d-1bfe-648e18e45fd5.png)
![chooseTemplate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/2aa1e20f-3007-441a-bc11-136fe2ff5d3f.png)

アプリに名前を付けてあげて「Create App」をクリックします。
![createApp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/35f11ca2-39dc-f742-7d4d-95ffbbfbf253.png)

　しばし待たれよ状態です。
 ![buildingApp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/f1ef689b-c623-6940-0da5-b3a2391b265a.png)

ちょっと前までブラウザ版でアプリを編集できるみたいだったのですが、フォーラムのQAによるとブラウザ版は無くなったようで...Mendixのデスクトップ版をダウンロードしました...

▼公式ページの「Start for free」もしくは「Try Mendix for free」をクリック
https://www.mendix.com/
![スクリーンショット 2024-07-02 16.31.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/a4a998c3-ba27-ca9a-26b6-2358d9cf85c8.png)

インストーラーがダウンロードできたら、各自Mendixのインストールを行います。
がんばれ自分のPCちゃん...

Studio Proきたよ〜
![スクリーンショット 2024-07-01 16.22.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/b370425b-03f4-79f2-d750-e1208c88e357.png)

アプリをダブルクリックすると起動してくれるので、もうしばし待ちます。
![スクリーンショット 2024-07-01 16.23.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/9a4cec48-35b7-486a-ada5-fd2646673b3a.png)

起動できたよ〜
↓の状態になったら。右上の緑色の三角(カーソルを合わせると「Run localy」と表示されるよ)を押すと、ブラウザで表示できるように準備してくれます。(ビルドと言います)
![スクリーンショット 2024-07-01 16.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/032c55bd-04e3-4946-5375-fc6b644618d1.png)

ビルドできたよ〜
ビルドが完了したら、右上にある「View App」をクリックすると、アプリがブラウザで確認できます。
今回はテンプレートを選択してアプリを作成したので、すでにある程度ページが出来上がっています。
![スクリーンショット 2024-07-01 16.43.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717305/a5eeb428-293d-1aaa-8456-5e508d568916.png)

今後はこのサンプルアプリを使って色々説明していこうかと思います。



未来の自分へ：Mendix Proを起動したらMacが悲鳴を上げたので、そろそろ新しいMacを買ってください。何年使っているんですか。
扉絵の作成手順


:::note warn
自分用です。
:::

https://qiita.com/nomurasan/items/b478340d3d3d05370710

みたいな扉絵を作りたい、という要望を満たした話がメイン。

## やりかた
### 1. AIイラスト生成サービスにアクセス
色々あるが、ここではSeaartを採用。

https://www.seaart.ai/ja

アカウントがなければ作成のこと。（無料）

### 2. プロンプトを書いて画像を生成する
いつものあの感じ。箇条書きで要素を散りばめると精度が上がるらしい。

### 3. 画像をアップロードする
https://qiita.com/settings/uploading_images

### 4. 記事に組み込む
アップロード時にリンク用のテキストをコピーしておくと楽

## 応用・動画の作り方
まずは画像を作るところまでは同じ

### 1. 作った画像を選択して、動画を生成
元画像を使って動画用に何枚か作られてそう。リテイクの技術を応用した？

### 2. 動画をmp4でダウンロード
これは普通

### 3. mp4をQiitaにアップロードするためにgifに変換する
変換の方法はなんでもよさそう

https://convertio.co/ja

### 4. 動画をアップロードする
以下、画像の手順と同じ。

## 注意
- 1日200トークン使える（らしい）
  - 実はまだ確認中の段階であるため、この辺りは怪しい。