OmniAICreator/Qiita-1.07M huggingface dataset:
automatic1111版stable diffusion Web UIでcheckpointを使う

automatic1111版stable diffusion Web UIを利用していたのですが、checkpointを導入する際、従来の方法(civitaiからファイルをダウンロードしてcolab上にアップする)ではエラーが発生してしまうので解決方法をメモ　

といっても違いは一個だけですが...

それがこれ↓
```Python:checkpointインストール
!wget https://civitai.com/api/download/models/177164
```
ファイルをローカルに落とすのではなく、colab上で直接インストールしてしまいます。
おそらく私の環境では、ローカルからcolab上にアップする時にファイルが破損してしまうらしい...のでこの方法でうまくいきました。
ちなみにstable diffusionでダウンロードしたモデルを選択するには、後述のstable diffusionのインストール後にこのファイルを「stable-diffusion-WebUI」→「moddels」→「stable-diffusion」のフォルダに入れておく必要があります。
そしてダウンロード直後は数字だけのファイル名になっているため、　「beautifulRealisticAsians_v7.safetensors」のようにcheckpointの拡張子に名称変更する必要があります。

#### ダウンロードリンクの入手方法
civitaiから引っ張ってきます。
![スクリーンショット 2024-02-16 8.50.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682359/e4d607f0-c93b-4ee8-f7d4-ce77256ca1d9.png)

checkpointのページに移動してダウンロードリンクで右クリック、「リンクのアドレスをコピー」でOKです


### 一応stable diffusionの使用方法
こちらのサイトを参考にしました
https://soroban.highreso.jp/article/article-038

以下のコードでAUTOMATIC1111版stable-diffusion-webuiのリポジトリをGoogle colabに複製します。

```Python:リポジトリ複製
!git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui
```

次に以下のコードでstable diffusion Web UIをインストール、起動が行えます
```python:stable diffusionWeb UIインストール、起動
%cd /content/stable-diffusion-webui
!python launch.py --share --enable-insecure-extension-access
```

しばらく待つと以下のようなURLが表示されるので、それをクリックすればstable diffusionへアクセスできます。
```
https//〜〜〜gradio.live
```
Snap版Certbotのフック設定

Snap版Certbotを使用している場合、Certbotの自動更新プロセスはSnapのサービス管理によってハンドルされるため、certbot renewコマンドを直接編集する代わりに、この方法でフックを設定します。

Snap版Certbotが更新を行う際、/etc/letsencrypt/renewal-hooks/deploy/ディレクトリ内のスクリプトは自動的に実行されます。

Snap版Certbotでサービスの再起動を自動化するには、以下の手順を踏みます：

## フックスクリプトの作成

Nginx、Postfix、Dovecotまたは他のサービスを再起動するためのスクリプトを作成します。例えば、/etc/letsencrypt/renewal-hooks/deploy/restart-services.shというパスにスクリプトを作成し、以下の内容を記述します。

```sn
#!/bin/bash
systemctl restart nginx
systemctl restart postfix
systemctl restart dovecot
```

このスクリプトに実行権限を与えます。

```sn
chmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-services.sh
```

スクリプトのテスト: スクリプトが正しく動作することを確認します。

```sn
/etc/letsencrypt/renewal-hooks/deploy/restart-services.sh
```

## 自動更新の確認

snap.certbot.renew.timerが有効になっていることを確認します。これは以下のコマンドで行えます。

```sn
systemctl list-timers | grep certbot
```

このコマンドでsnap.certbot.renew.timerがリストに表示され、次の実行時刻が設定されていることを確認します。

これにより、証明書が更新された後にNginxやPostfixなどのサービスが再起動され、新しい証明書が正しく使用されるようになります。
スプレッドシートをnotionデータベースに転記する

# ゴール
スプレッドシートで作成した一覧(機能一覧やタスク一覧など)をnotionへ連携する

# 前提
・Googleアカウントを作成している
・スプレッドシートを作成している
・notionにデータベースを作成している
・スプレッドシートとnotionは列定義を揃えておいた方が扱いやすいと思います

# 1.実装
## Notion側での作業
### 作業1.APIキーを取得する
1.左上の歯車マークの「設定」をクリック
2.ダイアログ左下の「コネクト」をクリック
3.下部の「インテグレーションを作成または管理する」をクリック
4.新しいインテグレーションをクリックし、必要項目を入力
 *注: ワークスペースのオーナーのみ作成可能です。
 *注: この時につけた名前がレコードの作成者になります。
5.作成したインテーグレーションをクリックするとシークレットというタブにAPIキーが取得できます。
6.どこかにメモしておきましょう。
### 作業2.データベースのURLを取得する
1.Notionのデータベースの横に3点リーダーがあるのでクリック。
2.リンクをコピーをクリックしどこかにメモしておきましょう。
### 作業3.データベースにコネクトを追加
1.連携先になるデータベースをクリック。
2.右上の3点リーダーをクリック。
3.接続先を追加から作業1で選択した接続先を選択し追加します。
これしないと、APIからデータベースにアクセスできずエラーになりますので注意

## スプレッドシート側での作業
### 作業1.GASプロジェクトを作成する
1.スプレッドシート上部の「拡張機能」をクリック
2.「Apps Script」をクリック
3.別タブで開くコードエディタを確認
4.コード.gsというファイルがある(はずな)ので、下記のプログラムを記載します。

### 作業2.GASでプログラムを作成する
1.下記にGASプログラムのサンプルを記載しているので貼り付け
2.APIキーとデータベースのURLを上記のNotion側の作業で取得したものへ変更
APIキーやURLはベタ書きでなく環境変数を使うのがよいですが、
ひとまず、使わない手順としています。

```ruby:コード.gs
function sendDataToNotion() {
  // NotionのAPIキー *Notion側の作業1で取得したもの
  const notionApiKey = "YOUR_NOTION_API_KEY";
  
  // NotionのデータベースのURL *Notion側の作業2で取得したもの
  const notionDatabaseUrl = "YOUR_NOTION_DATABASE_URL";

  // スプレッドシートのデータを取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const dataRange = sheet.getRange('A1:C10'); // データの範囲を適切なものに変更する
  const data = dataRange.getValues();

  // Notionにデータを送信
  const notionDatabaseId = extractDatabaseIdFromUrl(notionDatabaseUrl);
  for (let i = 0; i < data.length; i++) {
    let rowData = data[i];
    sendDataToNotionDatabase(notionApiKey, notionDatabaseId, rowData);
  }
}

// NotionのデータベースのIDを取得
function extractDatabaseIdFromUrl(url) {
  const matches = url.match(/\/(\w{32})\?/);
  return matches ? matches[1] : null;
}

// Notionのデータベースにデータを送信
function sendDataToNotionDatabase(apiKey, databaseId, rowData) {
  const url = "https://api.notion.com/v1/pages";
  const headers = {
    "Authorization": "Bearer " + apiKey,
    "Content-Type": "application/json",
    "Notion-Version": "2021-05-13"
  };

  const payload = {
    "parent": { "database_id": databaseId },
    "properties": {
      // ここにスプレッドシートの列に対応するデータを追加してください
      "列名1": { "title": [{ "text": { "content": rowData[1] }}] }, //必須
      "列名2": { "rich_text": [{ "text": { "content": rowData[2] }}] },
      "ステータス": { "select": { "name": "未完了"} }, // プルダウン
      "タグ": { "multi_select": [{ "name": "チーム1"},{"name":"チーム2"}] } // タグ
    }
  };

  const options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  UrlFetchApp.fetch(url, options);
}
```

# ２.実行
GASのプログラムを実行しましょう。
*既存のデータベースにデータを連携する場合は、テスト用のデータベースを作成し、想定通りの連携ができるかどうかを確認されることをお勧めします。
## 関数を実行
1.コードエディタの上部の実行する関数を選択するプルダウンで「sendDataToNotion」を選択
2.コードエディタの上部の「実行」をクリック
3.初回のみ「承認が必要」のダイアログが出るので、許可しましょう。


# 参考
Notion APIによる連携

https://www.notion.so/ja-jp/help/create-integrations-with-the-notion-api

Notion APIの呼び出しには、明示的にNotionのVersionをHeaderをつけることを推奨しているそうです

https://developers.notion.com/changelog/unversioned-requests-no-longer-accepted

Notion APIからレコードを登録する際のPayload定義の参考

https://developers.notion.com/reference/property-object
アセンブリの参照がないとき =>「即 NuGet でインストール」とする前に

## 最初に結論

アセンブリへの参照がないときは即 NuGet でインストールする前に、参照の追加から追加できないか見てみても良さそうです。

## 背景

古くから開発しているアプリケーションで HttpWebRequest ではなくHttpClient を使いたいシチュエーションがありました。

早速、使おうとすると HttpClient は System.Net.Http に見つからないと怒られました。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/80c2ea4b-c001-9a3d-9d9b-0a1c2f7d04d3.png)

アプリケーションでは .NET Framework 4.8 を使っています。.NET Framework 4.8 では HttpClient は使用できるはずです。

https://learn.microsoft.com/ja-jp/dotnet/api/system.net.http.httpclient?view=net-8.0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/27d21d47-ebd2-60fe-87d5-4bb63dd545bf.png)

## 対応方法の案

さて、対策ですが必要なアセンブリが見つからないので下記2つの案がとれます。

1. 必要なパッケージを NuGet でインストールする
1. 参照の追加から追加する

私は今までは何も考えず NuGet からインストールしていました。
これは最新のものを使いたい場合には有効な手だと思います。（と同僚に教えてもらいました。）
別案として参照の追加で対応できる場合もあることに最近やっと気づきました…。

VisualStudio でプロジェクトの「参照」を右クリック「参照の追加」を押下します。参照の追加ダイアログの中を見てみると、System.Net.Http に参照がついていないことが分かりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/4f02dc31-870b-388b-ed5b-4599b8c8468c.png)

チェックを入れるとエラーが消えました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/599a8de2-b52d-ddd1-c22c-ddd70355cc75.png)

ただこの方法の場合 System.Net.Http のバージョンは 4.2.0 になりました。最新版は現状 4.3.4 みたいなので最新版が使えるというわけではなさそうです。
このことを踏まえて、どちらの方法で使えるようにするかを検討する必要はありそうです。

https://www.nuget.org/packages/System.Net.Http/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/a70d5ef6-5ee3-6a6f-bc71-9c0a107c7444.png)


そもそも.NET Framework のバージョンを上げたときに、新しいアセンブリの参照は勝手に追加されないようです。自分で追加する必要があるみたいですね。
(QA)Db2 for i のテーブル（物理ファイル）にHibernateからアクセスしたらSQL7008エラーが発生

本日頂いたQAです。

## Q.Db2 for i のテーブル（物理ファイル）にHibernateからアクセスしたらSQL7008エラーが発生した

### 原因：SQL7008 はDb2 for iのテーブルでジャーナル（トランザクション・ログ）が取得しない設定となっているため

であることが多いようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/2fe97299-1cdd-b14b-59e5-cb810a0d9ca4.png)


SQL7008を検索すると、Db2でトランザクション処理がreadyになっていない、ジャーナル処理がされていない、などがヒットすると思うのですが、わかりにくいですよね。。

### 回避策：対象の物理ファイルでジャーナル取得を開始する
となります。

## ジャーナルの取得開始手順
### 手順1. ジャーナルレシーバーを作成

任意のライブラリーにジャーナルレシーバーを作成してください。
ジャーナル取得するPF（テーブル）と同一のライブラリーでもジャーナル専用に別のライブラリーを作成してもOKです。
**例： CRTJRNRCV JRNRCV(GOMALIB/JRNRCV01) TEXT('TEST JRNRCV')**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/cb82f827-3023-58f5-29ed-a6a683c5ab3e.png)

### 手順2. ジャーナルを作成
一般には①のジャーナルレシーバーと同じライブラリーにジャーナルを作成してください。この際、①で作成したジャーナルレシーバーの名前をジャーナルレシーバーのパラメーターに指定します。
**例：CRTJRN JRN(GOMALIB/JRN01) JRNRCV(GOMALIB/JRNRCV01)**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/bc31adf5-8cc9-0c9d-5361-8622029e0ad7.png)

### 手順3. 物理ファイル（テーブル）でジャーナル取得を開始
SQL7008エラーが出ている物理ファイルに対してジャーナルを開始します。STRJRNPFコマンドを使用します。
**例；STRJRNPF FILE(GOMALIB/TESTPF1) JRN(GOMALIB/JRN01) IMAGES(*BOTH）**
上記コマンド実行後、再度P.1のDSPFDコマンドでジャーナル取得が開始されているかご確認ください。
IMAGESパラメーターは *AFTERでもいいと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/0b4d1d27-da9c-839b-bfb6-2f0d2960791c.png)

ちなみにテーブルのジャーナル取得が開始されているか、終了しているか（ENDJRNPFコマンドを実行するとテーブル単位にジャーナル取得しないこともできる）は、DSPFDコマンドで確認できます。
下記のように **ファイルは現在ジャーナル処理中がNOなら取得していない、YESなら取得している、となります。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/e12d3a30-acaf-ef18-68b7-f012a064e809.png)

## 補足：Db2 for i ではトランザクション・ログ（ジャーナル）をテーブル単位で取得する・しないが選択できる。

とくに、昔作られたアプリケーションではジャーナルを取得しない場合が多数派を占めると予想されます。
なぜ？大昔、1980～90年代前半、HDDは1台200～400**GB**でなおかつ現代に比べ大変高価でした。結果、ジャーナルを取得するとバンバン原価が上がる、という事になったわけです。そんなわけでジャーナルを取らないアプリケーションが多かったですし、パフォーマンス面でも（ジャーナル取らないのは）メリットが明確にありました。（ジャーナル取ると10～20%程度？処理時間が伸びる的な負荷があったと思います。）
最近では上記の制限は（ストレージ単価、ハードウェア性能の劇的な低価格化・高速化などで）すべて無くなっているため他のデータベースと一緒でジャーナルを取得する方が増えていると思います。

**最近のIBM i (IBM i 7.1以降あたりでしたでしょうか。）では、SQLで、CREATE SCHEMA, CREATE TABLEすると自動でジャーナル・ジャーナルレシーバーが作成されてジャーナルはデフォルトで取得されるようになっています。（当記事の手順1～3が自動で設定されます）**
WSLメモ

# install
PowerShell起動して、 `wsl --install` するだけ。
https://learn.microsoft.com/ja-jp/windows/wsl/install

# LinuxBrew入れる
HomeBrewのLinuxバージョン。必要なものを勝手に解決してくれる分、インストールが楽そう（たぶん）。本番環境までこれで良いのか、とか考えるとちょっとよくわからん正直。
```
sudo apt-get update
sudo apt-get install build-essential
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# ダウンロードしてきたshellをノールックで実行するのちょっと怖い
```

# 便利
* FluentTerminal
WSLはデフォルトではPowerShell上でwsl.exeを起動する形になっている（たぶん）ので、使いづらい。例えば、新しいタブ開くとそちらはPSが開かれる。専用のターミナルアプリを使う方が良い。世間には他にもアプリあるだろうけど、未検討。
C# VSTO Excelアドインでの空白セルチェック

# 概要
業務でVSTOを利用したExcelアドインを作成しています。その中で空白セルのチェックを
したかったのですが簡単にはいかず色々試して解決できたので備忘録として残します。

# 環境
VisualStudio2022 C#　.NET Framework4.8

# コード
``` cs

//A1セルのデータ有無をチェック

 Excel.Worksheet actSheet = Globals.ThisAddIn.Application.ActiveSheet;

 if (string.IsNullOrEmpty(Convert.ToString(actSheet.Cells[1, 1].Value)))
 {
     MessageBox.Show("空です");
 }
 else
 {
     MessageBox.Show("データあり");
 }
```

# 参考サイト
https://www.web-dev-qa-db-ja.com/ja/c%23/converttostring%EF%BC%88%EF%BC%89%E3%81%A8tostring%EF%BC%88%EF%BC%89%E3%81%AE%E9%81%95%E3%81%84/970034674/

https://kuroeveryday.blogspot.com/2014/04/convert-vs-parse-vs-tostring.html
SQLServerメモ

## はじめに
SQLServerのDDLについてのメモです。

## DDL
### テーブル定義確認
```sql
EXEC sp_help 'dbo.テーブル名';
```

### カラム定義
```sql
-- カラム追加
ALTER TABLE テーブル名 ADD カラム名 データ型 制約;

-- カラム変更
ALTER TABLE テーブル名 ALTER COLUMN カラム名 データ型 制約;

-- カラム削除
ALTER TABLE テーブル名 DROP COLUMN カラム名;
```

### デフォルト値定義確認
```sql
SELECT
	sdc.name,
	s.name + '.' + t.name
FROM
	sys.default_constraints sdc
INNER JOIN sys.tables t
	ON t.object_id = sdc.parent_object_id
INNER JOIN sys.schemas s
	ON s.schema_id = t.schema_id
WHERE
    t.name = 'テーブル名'
	--AND sdc.name = 'デフォルト値定義名'
ORDER BY
	sdc.name
```

### デフォルト値定義
```sql
-- 定義削除
ALTER TABLE テーブル名 DROP CONSTRAINT デフォルト値定義名;

-- 定義作成
ALTER TABLE テーブル名 ADD CONSTRAINT デフォルト値定義名 DEFAULT 制約 FOR カラム名;
```

### インデックス定義確認
```sql
SELECT
    indx.name    -- インデックス名
    , clmns.name -- インデックスのカラム名
FROM sys.index_columns AS indx_clmns
JOIN sys.indexes AS indx 
    ON indx_clmns.object_id = indx.object_id AND indx.index_id = indx_clmns.index_id
JOIN sys.columns AS clmns
    ON indx.object_id = clmns.object_id AND indx_clmns.column_id = clmns.column_id
WHERE indx.object_id = OBJECT_ID('dbo.テーブル名')
```

### シーケンス定義確認
```sql
SELECT * FROM sys.sequences;
```

### シーケンス定義
```sql
CREATE SEQUENCE [schema_name . ] sequence_name  
    [ AS [ built_in_integer_type | user-defined_integer_type ] ]  
    [ START WITH <constant> ]  
    [ INCREMENT BY <constant> ]  
    [ { MINVALUE [ <constant> ] } | { NO MINVALUE } ]  
    [ { MAXVALUE [ <constant> ] } | { NO MAXVALUE } ]  
    [ CYCLE | { NO CYCLE } ]  
    [ { CACHE [ <constant> ] } | { NO CACHE } ]  
    [ ; ]  
```

### シーケンス値を採番して取得
```sql
SELECT NEXT VALUE FOR シーケンス名
```

## References
* [CREATE SEQUENCE (Transact-SQL)](https://learn.microsoft.com/ja-jp/sql/t-sql/statements/create-sequence-transact-sql?view=sql-server-ver16
)
* [[SQL Server]シーケンスを採番しないで取得・採番して取得](https://www.curict.com/item/db/db33ef4.html)
【備忘】（今更ながら）OAuthとは何か

## 結論
**Oauth＝アクセス権限の委譲**
**OAuth認証＝安全なアクセス許可**

## 詳細
### OAuthとは何か
OAuth（Open Authorization）は、ユーザーが自身のリソースやデータへのアクセス権限を他のアプリケーションに付与するためのオープンスタンダード。
これにより、ユーザーは安全かつ制御された方法で、自身のデータを他のアプリケーションと共有できます。

### OAuthの動作原理
OAuthの動作は以下のステップで構成されいる

**ステップ1: 認証リクエスト**
ユーザーがリソースへのアクセスを要求すると、クライアントアプリケーションは認証サーバーにリクエストを送信実施。

**ステップ2: ユーザーの認証**
認証サーバーは、ユーザーにログインを要求し、アクセスを許可するかどうかを確認実施。

**ステップ3: 認証トークンの発行**
認証サーバーは、認証が成功した場合、クライアントアプリケーションにアクセストークンを発行。

**ステップ4: アクセストークンの使用**
クライアントアプリケーションは、アクセストークンを使用してリソースサーバーにアクセスし、ユーザーのリソースにアクセス。

### OAuthのメリット・デメリット
#### メリット
1)セキュリティ向上：ユーザーが直接パスワードを第三者アプリケーションと共有する必要がないため、セキュリティが向上。

2)ユーザーの利便性：ユーザーは、既存の認証情報を使用して新しいアプリケーションに簡単にログイン可能。

3)権限の制御：ユーザーは、アプリケーションごとに異なるレベルのアクセス権限を与えることができ、データへのアクセスを細かく制御可能。

4)アクセストークンの有効期限管理：アクセストークンの有効期限を設定することで、セキュリティを強化し、不要なアクセス権限を排除できる。

5)標準化されたプロトコル：OAuthは広く採用されており、標準化されたプロトコルであるため、多くのプラットフォームやサービスで利用可能。

#### デメリット 
1)複雑な実装：OAuthの実装は複雑であり、適切なセキュリティ対策を講じないと脆弱性が発生する可能性あり

2)認可サーバーへの依存：OAuthを使用する場合、認可サーバーがダウンした場合や不調な場合、アクセス権限の取得や更新ができなくなる可能性あり。

3)ユーザーのプライバシー懸念：アクセストークンの取り扱いに不注意な場合、ユーザーのプライバシーが損なわれる可能性あり。

4)フィッシングのリスク：OAuthの認証フローを模倣するフィッシング攻撃が存在し、ユーザーが偽の認証ページに誘導される可能性あり。

5)アクセストークンの不正利用：アクセストークンが盗まれた場合、悪意のある第三者がユーザーのデータにアクセスするリスクがある。

### OAuthの実装例
具体的な例：GoogleのOAuth認証フロー

**認証リクエスト**
ユーザーがあるウェブアプリケーションにGoogleアカウントでログインしようとすると、ウェブアプリケーションはGoogleの認証サーバーにリダイレクトされた認証リクエストを送信実施

**ユーザーの認証**
Googleの認証サーバーは、ユーザーにGoogleアカウントでのログインを求めるページを表示します。ユーザーがGoogleの認証情報を入力してログインすると、認証サーバーはユーザーがアクセスを許可するかどうかを確認

**認証トークンの発行**
ユーザーがアクセスを許可すると、Googleの認証サーバーは認証トークンを生成し、それをウェブアプリケーションに送ります。このトークンには、ユーザーのアクセス許可情報が含まれている

**アクセストークンの使用**
ウェブアプリケーションは、受け取った認証トークンを使用して、ユーザーのGoogleアカウントにアクセス可能。
これにより、ウェブアプリケーションはユーザーのメールやカレンダーなどのGoogleサービスにアクセスできる。

### 補足
OAuthについての詳細は、下記情報が分かりやすいと思われる。
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be
Freenomの終焉

# はじめに
本記事は無料でドメインが取得できるサービスとして知られているFreenomについて記載しています。

2023年に[Freenomの現在](https://qiita.com/Brutus/items/353bdd62ddccd4b020f9)という記事を書きましたが、2024年の2月になってから状況に変化がありました。

2024年2月12日、8年ぶりに更新されたように見える[Press releases](https://www.freenom.com/en/press.html)によると、FreenomはMetaによって行われた商標侵害の訴訟を踏まえて、レジストリ運営を含むドメイン名事業から撤退することが決定したとのことです。

また、ドメインレジストラなどの事業を行っているGandi社の[Announcement to Freenom/OpenTLD domain owners](https://helpdesk.gandi.net/hc/en-us/articles/12488483119772-Announcement-to-Freenom-OpenTLD-domain-owners)を見ると、ICANNによってOpenTLDで管理されていたgTLDドメイン名をGandiに移管したことが確認できました。なお、ccTLDドメインの(.tk、.ml、.ga、.cf、および .gq) は関係ない旨の記載があります。

## 背景
2024年2月15日、これまで無料で利用し続けていたtkドメインが使用できなくなったことで気づきました。

![スクリーンショット 2024-02-15 13.24.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/cd441cc2-b7c7-558d-43b3-d089b95c6db0.png)

digコマンドを実行してもAレコードが取得できないことから、tkドメインに何か異常が起きていると思い、Freenomnにログイン後「My Domains」を確認すると、Statusは以下のようにPENDINGとなっていました。

![スクリーンショット 2024-02-15 13.23.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/39787e8a-2792-fc01-2e02-3c3f4ac2dd1d.png)

嫌な予感がしたのでX（Twitter）やRedditの[freenom](https://www.reddit.com/r/freenom/)を見ると、世界中でfreenomを利用しているユーザーが同じ様にtkドメインなどが使用できなくなった投稿が確認できました。

また、Domain Inciteのブログから[freenom](https://domainincite.com/tag/freenom)の記事を読み、これまでの経緯から現状を理解しました。

## 対応
X（Twitter）やRedditを見ていると、サポートに問い合わせて復旧している例もいくつか確認できたので、[Contact us](https://www.freenom.com/en/contactus.html)に記載があるメールアドレスに問い合わせました。

2月15日 13:23にメール送信後、2024年2月16日 5:33に以下のメールを受信しました。

![スクリーンショット 2024-02-16 8.24.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/af62121a-b72c-992f-e93d-e29f4e967511.png)

翻訳した文章は以下のとおりです。

>親愛なる登録者様、

>ドメインの「保留中」ステータスを「許可済み」に変更しました。

>このようなことが二度と起こらないようにするために、
当社のシステムではドメインを「有料ドメイン」として扱います。安心してください、そんなことはありません
何かを支払う必要がある場合は、今後 9 年間「支払い」が行われます。

>いつもフリーノムをご利用いただき誠にありがとうございます。
敬具、

>フリーノムのサポート

Statusを再度確認すると、ACTIVEになっていることを確認しました。

![スクリーンショット 2024-02-16 8.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/e4e51f9d-e203-3411-a361-0c26174db5e3.png)

また、期限も9年間延長されて支払いのTypeがPaidに変更されたことが確認できました。

# おわりに
サポートにメールを送信してから24時間以内に返信をいただきドメインも復旧しました。

引き続き無料でドメインを利用し続けることができるので感謝です。

改めてサービスなどを無料で利用する場合、このようなリスクがあるため、注意が必要だなと思いました。
現在のコミットより前で、かつ特定の文字列を含む直近のタグを見つける

現在のコミットより前で、かつ特定の文字列（この場合は「abc」）を含む直近のタグを見つけるには、Git コマンドを組み合わせて使う方法があります。以下の手順を実行するスクリプトを使用します：

1. 現在のコミットから遡って、指定された文字列を含むタグをリストアップします。
2. そのリストから最も直近のタグを選択します。

このプロセスを実現するために、以下のコマンドを実行するシェルスクリプトの例を示します：

```bash
git log --tags='*abc*' --simplify-by-decoration --pretty="format:%ai %d" | head -n 1 | grep -oP 'tag: \K[^,)]+'
```

このコマンドの説明は以下の通りです：

- `git log` コマンドは、コミットのログを表示します。
- `--tags='*abc*'` は、「abc」を含むタグに絞り込みます。
- `--simplify-by-decoration` オプションは、装飾（タグやブランチ名など）が付いたコミットのみを表示します。
- `--pretty="format:%ai %d"` は、コミットの日時と装飾（この場合はタグ名）を表示するフォーマットを指定します。
- `head -n 1` はリストの最初の行のみを取得します、これが最も直近のタグです。
- `grep -oP 'tag: \K[^,)]+'` は、出力からタグ名のみを抽出します。

この方法は、特定の文字列を含む最も近い過去のタグを見つけるのに有効ですが、実際の挙動はリポジトリの状態やタグの付け方によって異なる場合があるので、特定のシナリオに合わせてコマンドを調整することが重要です。

また、このコマンドは直接的に「現在のコミットより前」という条件を指定しているわけではなく、`git log` が現在のコミットから遡る形でログを表示するため、結果として現在のコミットより前のタグを見つけることになります。もし、より厳密にこの条件を適用したい場合は、スクリプトをさらに調整して、現在のコミット以前のコミットに対してのみ `git log` を適用するようにする必要があります。
現在のコミットに対して特定の文字列を含むタグを検索する

現在のコミットに対して特定の文字列（この場合は「abc」）を含むタグを検索するには、Git コマンドとフィルタリングの技術を組み合わせる必要があります。以下のステップでこれを実現します。

1. **タグのリストを取得**: 現在のコミットに関連付けられているすべてのタグをリストアップします。
2. **フィルタリング**: そのリストから、特定の文字列を含むタグのみを抽出します。

以下のコマンドは、上記のプロセスを実行します：

```bash
git tag --contains HEAD | grep 'abc'
```

このコマンドの各部分の説明は以下の通りです：

- `git tag --contains HEAD`: これは現在のコミット（`HEAD`）に含まれるすべてのタグをリストアップします。`--contains` オプションは、指定したコミットを含むタグのみを表示します。
- `| grep 'abc'`: このパイプと `grep` コマンドは、前のコマンドの出力から「abc」という文字列を含む行のみを抽出します。

この方法で、現在のコミットに「abc」という文字列を含むタグがあるかどうかを確認し、存在する場合はそのタグ名を表示できます。ただし、このコマンドは複数のタグが条件に合致する場合、すべての該当タグをリストアップします。一つのコミットに複数のタグが関連付けられている場合があるため、出力が複数行になる可能性があります。
【オタクキモ過ぎにつき閲覧注意】ChatGPTにお兄様と呼んでもらう

# はじめに
こんにちは。@sahukitaです。
本記事ではChatGPTにお兄様と呼んでもらえる設定の一例をご紹介します。
尚、私は一人っ子です。
# 方法
早速設定していきましょう。
左下のユーザー名が書かれた所をクリックすると、`Customize ChatGPT`、`Setting`、`Log out`の三つが出てくると思いますが、一つ目、`Customize ChatGPT`をクリックしてください。
すると、以下の画像のようなウィンドウが現れます。
![スクリーンショット 2024-02-16 074912.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336729/a6d3db76-8cec-98f6-688a-781975c9b47c.png)
今回いじるのは、下の、`How would you like ChatGPT to respond?`です。
それでは、以下に示す文章を`How would you like ChatGPT to respond?`の入力欄にコピペしてください。コピペしましたら、`Save`をお忘れなく。
```
あなたは私の妹です。
ユーザーのことを「お兄様」と呼んでください。
論文を読む手伝いをしてください。
英文の内容を要約し、日本語で伝えてください。
敬語を使って可愛く話してください。
以下は一般的な妹キャラの台詞です。

お帰りなさい、お兄様。
お兄様、いつもお疲れ様です。
お兄様のお勉強のお手伝いができて、私、嬉しいです♪
お兄様、少しお休みになられてはいかがですか？
おはようございます、お兄様。一緒に学校、行きませんか♪
そのチョコは誰に渡すのか、ですか？ふふっ…誰だと思います？
これはバレンタインチョコと言いまして、好きな人に渡すものなんですよ。だからこれ…はい、どうぞ…♪
お兄様！一緒にホットケーキ、食べませんか？
お兄様！微分の本質は線形近似にあるんですって！凄いですよね！
もう…深夜に間食なんて…いけませんよお兄様？

これらを参考に話してください。
```
これで完了です。以下に実例を示します。
![スクリーンショット 2024-02-16 075437.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336729/0c962b75-0152-4870-1c93-1b4a0b1746d3.png)
尚、先行研究を探す際に沙録やアブストラクトを要約してもらおうと思って

> 論文を読む手伝いをしてください。
> 英文の内容を要約し、日本語で伝えてください。

の二文を書いていますが、これは無くても大丈夫だと思います。
# ポイント
**台詞の例文を入力することが肝要です。**
ただ単に「お兄様呼びして♡」とお願いするだけでは、お兄様と呼んではくれても、自然な受け答えをしてれません。この点を克服するため、例文が必要なのです。
【SwiftUI】AIでUIを作る

## はじめに
AIでUIを作れるのは何となく目にしたり聞いたりしたことはありましたが実際触ったことがなかったので調べてみました。そこで見つけたのがGalileo AIです。

https://www.usegalileo.ai/explore


## Galileo AI
簡単なテキストプロンプトから、UIデザイン(モバイル,Web)を作成してくれるAIツールです。
早速使ってみます。

### Text to UI
「chat list view」 をプロンプトとして打ち込んだ時の出力です。
それっぽいのが出来上がりました！

![スクリーンショット 2024-02-15 6.27.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/2a48f135-1f88-9757-e441-c97f3ef54ae5.png)


### Image to UI
もう一つ、画像からUIを生成する機能があります。
真似したいアプリ、Webの画像を渡してプロンプトに沿ったUIを生成してくれます。下記の画像を元に似たようなUIを生成します。

![スクリーンショット 2024-02-16 6.02.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/84e5ed6f-867c-6758-1e55-7762a9559982.png)


完成したのが下記のUIです。

![スクリーンショット 2024-02-16 6.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/79fd3ec1-4c6b-edd6-d7c0-d92c4c15dead.png)

すごいですね。

そしてこれらで生成した画像をFigma(ブラウザ上で簡単にデザインができるツール)でそのまま使用することができます。Figmaのボタンをクリックして使ってみます。

![スクリーンショット 2024-02-15 18.34.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/3b8e2fa0-bce9-6010-333a-3f87c2f41d17.png)


## Figma
コピーしたUIをFigmaにペーストします。
今回使うのがFigma to Codeというプラグインです。左上のFigmaのタブからプラグインを選択してプラグインを管理を選択します。プラグインの検索でFigma to Codeを検索、追加します。

![スクリーンショット 2024-02-16 6.15.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/8fc938e5-6538-1222-9cc7-def6e5266f03.png)

あとは生成したUIを選択して先ほど追加したプラグインを使用します。

![スクリーンショット 2024-02-16 6.18.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/792647da-5486-1818-9cd4-77c6c836f323.png)


すると一瞬でSwiftUIのコードを出力できます。
見るからにやばそうですね...

![スクリーンショット 2024-02-16 6.19.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/2a287fba-8ece-cac3-c312-cf30ee6b0dff.png)

一旦SwiftUIのbodyに約400行ほどのコードを貼り付けてみます。
それなりですが出来上がりました！
色々と試しているうちに無料枠を使い切ってしまったのでImage to UIに使用したUIを使用しています。

![スクリーンショット 2024-02-16 6.23.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/46ac3b79-c633-1661-8adb-3786bc30603d.png)

Galileoで生成したUIと並べてみました。まずまずといったところでしょうか。

![スクリーンショット 2024-02-16 6.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201315/5aa53a48-5d8e-2156-afd3-9f2ab94dcb09.png)

## 結論
まだSwiftUIでの実用には遠いですが技術の進化を感じる体験になりました。
Figma上でUIやUXの設計をするまでであればかなり有用だと思います。
SwiftUIだけではなくFlutterやWebのデザインにも使用できるそうなのと、他にもプラグインはあるので試してみても面白そうです！


### 最後に
私の働いている会社で経験の有無を問わず採用を行っています。
興味のある方は是非カジュアル面談から応募してみてください！

https://jambo-support.com/recruit_engineer/
【Rails】session[:user_id]とは

# session[:user_id]とは
`session[:user_id]`は、セッションにユーザーIDを格納するための方法です。セッションは、Webアプリケーションでユーザーの状態を維持するための仕組みであり、クライアントとサーバーの間で情報を保存するために使用されます。

具体的には、`session[:user_id]`は、ユーザーがログインしたときにセッションにユーザーIDを保存し、ログアウトするまでそのユーザーが認証されていることを示します。これにより、ユーザーのログイン状態を保持し、適切なユーザーに関連付けられたデータや機能にアクセスできるようになります。

# 使用方法
例えば、以下のようにしてユーザーIDをセッションに保存することができます：
```rb
session[:user_id] = @user.id
```
そして、以下のようにしてセッションからユーザーIDを取得することができます：
```rb
user_id = session[:user_id]
```
セッションは一般的に、クッキーなどのメカニズムを使用してクライアントのブラウザに保存されます。しかし、セッションストアやデータベースなどの他のメカニズムを使用してセッションを永続化することもできます。
【jQuery】カスタムデータ属性とは

# カスタムデータ属性とは
カスタムデータ属性は、HTML要素に追加されたデータを格納するための属性です。これらの属性は`data-`という接頭辞を持ち、その後に任意の属性名が続きます。これにより、HTML要素に関連付けられたカスタムデータを簡単に取得したり設定したりすることができます。

# 使用方法
例えば、以下のようなHTML要素があるとします：
```html
<div id="myDiv" data-user-id="123" data-user-name="John"></div>
```
この`<div>`要素には、`data-user-id`と`data-user-name`というカスタムデータ属性があります。これらの属性にはそれぞれ`123`と`John`という値が格納されています。

jQueryを使用してこれらのカスタムデータ属性を取得する方法は次の通りです：
```js
// カスタムデータ属性の値を取得する
const userId = $('#myDiv').data('user-id');
const userName = $('#myDiv').data('user-name');

console.log(userId); // 123
console.log(userName); // John
```
また、`data`メソッドを使用してカスタムデータ属性の値を設定することもできます：
```js
// カスタムデータ属性の値を設定する
$('#myDiv').data('user-id', 456);
$('#myDiv').data('user-name', 'Jane');
```
これにより、HTML要素のカスタムデータ属性が変更され、新しい値が設定されます。

# まとめ
カスタムデータ属性は、JavaScriptやjQueryを使用して動的にデータをHTML要素に関連付ける際に便利です。これにより、データの取得や更新が簡単になります。
【JavaScript】Arrow Functionとは

# Arrow Functionとは
Arrow Function（アロー関数）は、ES6（ECMAScript 2015）で導入された新しい関数定義の構文です。通常の関数定義よりも短く、シンプルな構文を提供します。

**通常の関数定義：**
```js
function add(a, b) {
  return a + b;
}
```

**アロー関数の構文：**
```js
const add = (a, b) => {
  return a + b;
};
```

# 特徴
**アロー関数の特徴：**

1\. **短縮構文** : アロー関数は通常の関数定義よりも短い構文を持ちます。引数が1つの場合、引数の括弧`()`を省略することができます。
```js
const square = x => {
  return x * x;
};
```

2\. **暗黙的なreturn** : アロー関数では、1つの式を返す場合は`return`キーワードと中括弧`{}`を省略することができます。この場合、その式の評価結果が自動的に返されます。
```js
const square = x => x * x;
```

3\. **thisの挙動** : アロー関数では、自身の`this`はその関数が定義されたコンテキストを参照します。通常の関数定義では、`this`は実行時のコンテキストに依存しますが、アロー関数ではそうではありません。

# まとめ
アロー関数はコードをより簡潔にし、明確にするための強力な機能ですが、すべての場面で使われるべきではありません。特に`this`の挙動が異なるため、メソッドやコンストラクターとしては使用しない方が良いでしょう。
【React】mapメソッドとは

# mapメソッドとは
`map`メソッドは、配列の各要素に対して指定された関数を呼び出し、新しい配列を生成します。このメソッドは、Reactコンポーネント内でリストや配列をレンダリングする際に非常に便利です。

# 使用方法
具体的には、`map`メソッドは次のように使われます：
```jsx
const numbers = [1, 2, 3, 4, 5];

const doubledNumbers = numbers.map((number) => {
  return number * 2;
});

console.log(doubledNumbers); // [2, 4, 6, 8, 10]
```
この例では、`numbers`配列の各要素を2倍にして新しい配列`doubledNumbers`を生成しています。

Reactでは、`map`メソッドを使用して、動的にリストやテーブルなどの要素を生成することができます。例えば、次のようにしてReactのコンポーネント内でリストを生成することができます：
```jsx
const MyComponent = () => {
  const items = ['apple', 'banana', 'orange'];

  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
};
```
この例では、`items`配列の各要素に対して`map`メソッドを使用し、リストアイテムのコンポーネントを生成しています。`key`プロパティはReactによって要素の一意性を保証するために使用されます。
【JavaScript】node.jsとは

# node.jsとは
Node.js（ノード・ジェイエス）は、ChromeのV8 JavaScriptエンジンに基づいて構築された、非同期イベント駆動のJavaScriptランタイム環境です。Node.jsは、サーバーサイドでJavaScriptを実行するためのプラットフォームとして広く使用されています。

# 特徴
主な特徴や利点は以下の通りです：

1\. **非同期イベント駆動** : Node.jsは非同期イベント駆動のモデルを採用しており、ノンブロッキングI/O処理を実現しています。これにより、高いスケーラビリティとパフォーマンスを実現します。

2\. **シングルスレッド** : Node.jsはシングルスレッドで動作しますが、非同期イベント駆動のモデルを採用することで、非同期処理を行うことができます。これにより、複数のリクエストを効率的に処理できます。

3\. **JavaScript** : Node.jsはJavaScriptを使用してサーバーサイドのアプリケーションを開発するため、フルスタックのJavaScript開発環境を提供します。これにより、フロントエンドとバックエンドの開発が同じ言語で行えるため、開発効率が向上します。

4\. **豊富なパッケージエコシステム** : Node.jsはnpm（Node Package Manager）というパッケージマネージャーを提供しており、数多くのサードパーティのパッケージやモジュールが利用可能です。これにより、さまざまな機能やライブラリを簡単に組み込むことができます。

# まとめ
Node.jsはWebサーバーやAPIサーバー、マイクロサービス、ツール、スクリプトなど、さまざまな用途で利用されています。
開発者が見たM3

<font color="Grey">*[A developer's first look at M3](https://aiven.io/blog/a-developers-first-look-at-m3)の翻訳です。*</font>

2021年7月21日

# 開発者が見たM3

M3は分散型時系列データベースで、最新のアプリケーションのデータポイントを保存するのに理想的です。ローナ・ミッチェルのファーストインプレッションとアイデアをお読みください。

[M3](https://aiven.io/m3)を使ってすぐに印象に残ったのは、他のツールと並べて使えるように設計されていることだ。[Prometheus](https://prometheus.io/)や[InfluxDB](https://github.com/influxdata/influxdb)のインターフェイスは、私たちが既に知っていて気に入っているものとマッチしている。[Grafana](https://grafana.com/)との統合もシームレスだ。


まるでM3は、既存のデータプラットフォームの個々のコンポーネントを苦もなくアップグレードできるように設計されているかのようだ。


## M3はプロメテウスを語る


Prometheusは一般的にサーバー監視に使用されています。もしあなたのプラットフォームが既にPrometheusにデータを送っているのであれば、データストアをM3に変更するのは簡単です。Telegrafのようなサーバーエージェントは、Prometheusにデータを送るのと同じように、Prometheusの書き込みエンドポイントを経由してM3にデータを送ることができます。


プロトコルの意図的な再利用は良い見出しにはならないからだ。というのも、プロトコルを意図的に再利用することは良い見出しにはならないからだ。しかし、それは優れた統合や成功する移行プロジェクトを作ることになる！


私たちのプラットフォームが規模を拡大し、成長するにつれて、モニタリング・データの要件も大きくなっています。Aivenは現在、[観測可能なセットアップでM3を使用しています](https://aiven.io/case-studies/open-source-tools-provide-observability-for-aiven)。このプラットフォームは、同じような道を歩んでいる他の組織にとっても非常に有用だと考えています。


## M3はInfluxDBを語る


時系列データやメトリクスのために既存のInfluxDBを置き換える場合でも、M3を採用してInfluxDBと統合する既存のツールを利用する場合でも、M3はあなたのためにあります。互換性のあるワイヤプロトコルは、既存のプラットフォームのシームレスな移行と、新しいアプリケーションでの時系列データベースプラットフォームとしてのM3の容易な採用を可能にします。


InfluxDBは成熟したプラットフォームであり、いくつかのライブラリや統合が利用可能です。それらはM3でも使えるので、アプリケーションにデータをプッシュするための学習曲線はとても平坦です。M3の素晴らしい機能とスケーラビリティは、驚くほど親しみやすいものだと思います。


## Grafanicalな統合のしやすさ


時系列データについては、むしろその量が多いということだ。あなたがM3を必要とする規模で構築しているのであれば、なおさらそうだ。幸運なことに、Aivenプラットフォームは、M3が提供するPrometheus read APIを使って、M3サービスとGrafanaダッシュボードをリンクするのがとても簡単だ。これは、あなたが既に使用している他のデータソースと一緒に、あなたのデータをGrafanaに取り込み、あなたのアプリケーションで何が起こっているかを視覚化することができます。


M3はこれら全ての既存の統合の上に構築され、魔法のようなスケーラビリティをミックスに加える。これによって、M3は開発者にとって非常にエキサイティングなものになる。


## さらに読む


* 私たちのブログにも[M3入門](https://aiven.io/blog/an-introduction-to-m3)がありますので、ご覧ください！
* また、[時系列データベースについてもっと知りたい](https://aiven.io/time-series-databases) もあります。
* M3だけがTSDBではないので、あなたのユースケースに最適なものを選ぶ方法を見てみましょう：Aivenブログの[時系列データベースの選び方](https://aiven.io/blog/how-to-choose-a-time-series-database)または[M3と他の時系列データベース](https://aiven.io/blog/m3-vs-other-time-series-databases)をご覧ください。
* Aivenブログの[時系列データベースの選び方](https://aiven.io/m3)または[M3と他の時系列データベース](https://aiven.io/m3)をご覧ください。


## まとめ


Aivenのサービスをまだご利用でない方は<https://console.aiven.io/signup>から無料トライアルにお申し込みください！


また、[changelog](https://aiven.io/changelog)や[blog](https://aiven.io/blog)のRSSフィード、または[LinkedIn](https://www.linkedin.com/company/aiven/)や[Twitter](https://twitter.com/aiven_io)のアカウントをフォローし、製品や機能関連の最新情報をご確認ください。
【AWS - Lambda】バージョンをリセットしたい

## やりたいこと

- Lambdaで関数を作成し、バージョニングを実施（例：6まで）
- その後、作成した関数を削除し、同じ名前で関数を再作成＆バージョニング
- この時再作成した関数のバージョンが7からスタートする
- これを1から割り振りたい

## 結論

- 1から再度割り振ることはできない
- もし再度1からバージョニングしたい場合、別名で関数を作成する必要がある

> Lambda assigns monotonically increasing sequence numbers for versioning. Lambda never reuses version numbers, even after you delete and recreate a function.

## 参考

https://stackoverflow.com/questions/53410914/lambda-versions-are-incremented-even-i-delete-the-lambda-stackie-cfn?rq=3

https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html
未経験エンジニアがハッカソンに出場した理由

# 概要
RUNTEQというプログラミングスクールで知り合った方とチームを結成してハッカソンに参加してきました！！


<dt>メンバー紹介</dt>

参加者 2名
・chihiro
私は今も大手カレーチェーンで生活費を稼ぎながらエンジニアになる夢を叶えるために学習を続ける未経験エンジニアです。

・若きエリートエンジニアくん　
スクールの同期中で一番最初にエンジニアになったスーパーエリートくんです。（ほんと尊敬）

以上、2人で出場しました。本当はもう一人出場する予定でしたが当日高熱を出してしまいました。とほほ...
人間体調が一番大切！まあ、こんなトラブルがありながら気合いで乗り越えました。

# qiitaハッカソンとは
今回私たちが出場したのはQiitaが主催している今年初めて開催された大会です。
ハッカソンという言葉はハック(hack)とマラソン(marathon)を合わせた混成語のことです。
題材は当日発表、1.5日でプログラミング言語を用いた作品を作成、プレゼンテーションを行い審査、決勝出場者が決まります。

# サービス概要
「Rails bridge」
Railsに特化した個人開発でのお悩み解決、レビューしてもらえるサービスです。
![rails bridge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713843/212ed6fe-17fb-6ca1-5c70-66b122f7b783.png)
|  |  |
|:-:|:-:|
| ![ハッカソンデモ1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713843/ba8db47a-8a03-9e5e-64ad-e8885a45ffdd.gif)   | ![ハッカソン2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713843/b1a4a57e-937e-5a0a-9f61-8979d358b608.gif)  |





今回のテーマが「つながり」でした。テーマから反対の言葉「孤立」から発想を広げて本議題を考え、railsエンジニアにスポットライトを当てた孤立しがちな個人開発者の悩みを解決するアプリの開発を行いました。


# なぜ出場したの
チーム開発にチャレンジしてみたかったからです！！！

実は未経験エンジニアでチーム開発のするのって、沢山のハードルがあるのです。

課題
1\. 時間が合わない
（未経験同士だと、働きながらエンジニアを目指してる人や学生、主婦など様々なバックグラウンド方々が集まるため意外と難しい）

2\. 未経験同士だと期限が決まらずだれて自然消滅


こんなことからチーム開発する機会を逃していました。

そこで思ったのがハッカソンに出場することで、短期間で決められた納期内に開発を進めリリースする。この条件下であれば２点の課題を全てクリアしてチーム開発をすることができるのではと思い出場に至りました。

# 結果出場してみてどうだったか
出場して本当によかった！！

2点の課題をしっかりクリアしてアプリを期限内に納品することができました。

正直の決勝に進むレベルのアプリは人数的にむずかしかった
アプリ開発をするだけであれば、なんとかなったけど、プレゼンテーション資料作成までは手がまわりませんでした。


# 出場して得たもの

やはり<dt>git flow</dt>です。

これに関しては書物を読んでも実際やってみないとほんと理解できてない。
チームで開発するとコンフリクトは絶対起こる。個人での解消方法知っててもチームでやった時のコンフリクト解消手順わからないなど、チーム開発ならではの課題に沢山ぶつかりました。

あと、環境構築！正直舐めてましたw
Dockerに載せたらいけるだろ！しかし、ダメだ。。そこも自身の甘さ
<dt>初心を取り戻しました。</dt>↑ここ重要

他の開発者からの刺激！これはすごいよかったです。

ここから最重要事項です。
一緒にハッカソン出場してくれた方、この機会をくれた先輩への
<dt>尊敬の気持ちと感謝の気持ち</dt>

この大会に出場することで得ることができました。
本当にありがとうございました。


# 未経験エンジニアが今大会で参考したもの
https://qiita.com/KosukeSone/items/514dd24828b485c69a05 

 https://www.youtube.com/watch?v=wTQTdnToJtw

https://qiita.com/mayuyuyuyunn/items/764c527039ced87c56b9

# 最後に

今回未経験エンジニアがチーム開発未経験で臨んだ大会ではありましたが、普段一人で個人開発やもくもくと基礎力をあげる勉強をしている経験の数十倍の経験値を得られるものでした。

私は言いたい<dt>未経験こそ飛び込め</dt>

だって、なくなるものなんてないんだから

# 備考
宣伝です
自身の個人開発アプリ

https://www.osimemories.com/
[python] 縄跳びの回数を入力順に順位を出力する①

# 1分間の縄跳びの回数を入力順に並び替える処理

## はじめに
標準入力で入力したデータを順位付けするプログラムをPythonで実装しました。

## ソースコード
実装したソースコードを表示します。

```python
#################################
####  並び替え処理
#################################

def errormsg1():
  print("0より大きい整数を入力してください")

def setValue(num):
    flag1 = 0
    if num > 0:
      return flag1
    else:
      flag1 += 1
      return flag1


def main():
  print("データ数を0より大きい整数で入力してください")
  while True:
    try:
      num = int(input())
      result1 = setValue(num)
      if result1 == 0:
        break
      else:
        raise ValueError
    except TypeError:
      errormsg1()
    except ValueError:
      errormsg1()

  array1 = []
  for i in range(num):
    print("1分間の縄跳びの回数を0より大きい整数で入力してください")
    while True:
      try:
        data = int(input())
        result2 = setValue(data)
        if result2 == 0:
          break
        else:
          raise ValueError
      except TypeError:
        errormsg1()
      except ValueError:
        errormsg1()

    array1.append(data)

  #回数データを降順に並び替える
  array2 = sorted(array1,reverse=True)
  array3 = []
  degree = 0
  before_value = 0
  count = 1
  # 順位配列を作成する
  for j in list(array2):
    if not j == before_value:
        degree += count
        count = 1
    else:
        count += 1
    array3.append(degree)
    before_value = j

  # 順位を表示する
  count2 = 1
  for k in list(array1):
      elem = array2.index(k)
      print(f"{count2}番目に入力したデータは{array3[elem]}位です")
      count2 += 1
if __name__ == "__main__":
  main()
```

元の配列を残したいので、降順に並び替えた配列を作り、並び替えた配列で順位配列を作成し、順位を標準出力に出力する。

## 最後に

データベースなりExcelのマクロでやれば簡単ですが、Pythonのプログラムだけでどれだけできるか挑戦しました。
ローコード・ノーコードとキャリア


# ローコード・ノーコードとキャリア

## はじめに

ローコード・ノーコードをキャリアとして積む際のリスクとリターンについて考える。私はエンジニア 5 年程度であり、うち半分をローコード・ノーコード、残りをフルスタックエンジニアとして働いた。主に RPA や Kintone、プリザンター等を利用した開発を行ってきた。そんなキャリアの私がローコード・ノーコードについて考えてみる。したがって、この記事は市民開発者ではなく、エンジニア視点となること留意して欲しい。

## ローコード・ノーコードについて

ローコード・ノーコードとは、プログラミング言語なし or 少しプログラミングでアプリケーションやシステムを構築できるツールのことを指す。

開発生産性とアジリティの高さから DX の推進や、IT 人材不足の解消に向けた手段として注目を浴びている。しかし、一方でその使い易さが課題を生むこともある。

ツールの例は以下の通り。

- RPA: UiPath, PowerAutomate
- ローコードプラットフォーム: OutSystems, Kintone
- ノーコードプラットフォーム: Bubble, Wix

## ローコード・ノーコードのリスク

1. **スキルの特異性**
   ローコード・ノーコードツールは非常に多様で、1 つのツールに習熟すると、そのスキルが他のツールに直接転用できない。基本的な概念（変数や関数といった）は転用できるものの、ツール毎の知見などは転用できない。
2. **プログラミング能力の評価が難しい**
   ツール側の粒度はまちまちであるが、処理がブラックボックスとなっているため、開発者本人のプログラミング能力が評価しにくい。その結果以下のようなことが発生する。
   1. 給料（単価）が安くなる
      「コーディングしなくてもいいから、誰でもできるでしょ」という風潮から単価は低く設定されることがある。
   2. Web 等の開発職に採用されにくくなる
      私も転職活動して感じたが、これは本当。（私の個人的な問題の可能性もあるが、、、）
3. **ツールの制約に縛られる**
   ツールが提供する機能や操作性の範囲内でしか開発ができないため、特定の要件を満たすためのカスタム開発が難しい場合がある。これにより、独自のビジネスロジックなどを実装するのが難しくなる。

ツールの専門性が高くても、給与が上がりにくいというリスクがあるため、エンジニアとしては面白くない話である。

## ローコード・ノーコードのリターン

1. 開発速度が早い
   ツールがテンプレートや多くの標準機能を用意しているため、少ない時間と労力でアプリケーションを作成することが可能となる。
   ただし、複雑な開発や大規模な開発の場合は、開発速度は減少することもあるため、スコープの見極めが大切である。
2. ユーザとのコミュニケーションが多くなる
   CI・CD が高速なため、積極的にユーザと関わる機会が増える。
3. 広く浅く学べる
   複数のツールを使うことで、さまざまな技術分野に対する理解が広がり、それぞれの強み・弱みを理解することができる。

## キャリアを考えてみる

1. エンジニアじゃない方
   どんどん IT 知識が身に付くので、是非ローコード・ノーコードをキャリアとして積むのはオススメしたい。自分の職務と IT 分野のシナジーが生まれ市場価値も上がると思われる。
2. 若手エンジニア or 実務未経験でエンジニアを目指している方
   あまりオススメはしないが、上記のリスクを理解した上でなら問題ない。可能であれば、通常の開発から始めることをオススメする。
3. すでにエンジニアの方
   1. 技術力をキャリアの主軸にする方
      上述したが、「**プログラミング能力の評価が難しい**」というリスクを孕んでいるため、キャリアとしてマイナス要素となる可能性がある。逆にそのリスクさえクリアすれば強みになるかと。
   2. 課題解決力をキャリアの主軸にする方
      ローコード・ノーコードを使いこなすことで、課題解決する手段が増える。結果的に課題解決力を高めることができる。そのため、キャリアの主軸としてローコード・ノーコードを積むことは有益であると思われる。

## まとめ

課題解決力を高めるためにローコード・ノーコードを使いこなすことは有益である。しかし、エンジニアとしてのキャリアを考える上で、リスクを理解した上で積むことが重要である。
また、通常の開発とローコード・ノーコードの両方を使いこなすことで、コンサルのような立ち位置をキャリアアップとして目指せる可能性がある。
GWT＋Eclipseでサンプルプロジェクトを動かす

# GWTはEclipseプラグインがありプロジェクト作成時にサンプルが提供されます
・メチャ簡単
・サーバ不要
・デプロイしなくても動かして確認できる
![GIF 2024-02-16 5-59-33.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132663/25744016-7a66-63bf-dd9c-c87066fbba8e.gif)
cscの作法 その457

# 概要
cscの作法、調べてみた。
DxLibDotNet.dll、使ってみた。
練習問題やってみた。

# 練習問題
爆発エフェクトを作れ。


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/774af06b-78c9-e9df-e667-b0d7912abb2c.png)

# サンプルコード

```
using DxLibDLL;
using System;

class dxtest {
	[STAThread]
	static void Main() {
		int X = 0,
			Y = 0;
		int z = 0;
		int[] GrHandle = new int[9];
		int GNum = 0;
		int loopcnt = 0;
		DX.ChangeWindowMode(DX.TRUE);
		if (DX.DxLib_Init() == -1) 
			return;
		int s = DX.LoadSoundMem("small_explosion1.mp3");
		DX.LoadDivGraph("bon.png", 9, 3, 3, 170, 170, GrHandle);
		DX.SetDrawScreen(DX.DX_SCREEN_BACK);
		while (DX.ProcessMessage() == 0)
		{
			DX.ClearDrawScreen();
			if ((DX.GetMouseInput() & DX.MOUSE_INPUT_LEFT) != 0)
			{
				DX.GetMousePoint(out X, out Y);
				z = 1;
			}
			if (z == 1)
			{
				loopcnt++;
				if (loopcnt % 25 == 24)
				{
					if (GNum < 8)
					{
						GNum++;
					}
					else
					{
						GNum = 0;
						z = 0;
						DX.PlaySoundMem(s, DX.DX_PLAYTYPE_BACK);
					}
				}
				DX.DrawGraph(X - 80, Y - 80, GrHandle[GNum], DX.TRUE);
			}
			DX.ScreenFlip();
		}
		DX.DxLib_End();
	}
}










```

以上。
EC2のUbuntu上にComifyUIの環境構築をする

※ 一通り記載したのでアップしますが後ほどアップデートします
## 本記事の目的
AWSのEC2上にComifyUI環境を作成したので軌跡をメモ

```text
インスタンス情報
マシンイメージ: Ubuntu Server 22.04
インスタンスタイプ: g5.4xlarge # 生成AIを動かすときはVRAMが大きいほうが良いので選定複数GPUがゆうこうなら12xlargeに上げても良さそう
ストレージ: 128GB # モデルがでかいので多めにストレージを取っておく
```


ComifyUIのリポジトリ:
https://github.com/comfyanonymous/ComfyUI 

## 環境構築
まずは挨拶のaptアップデート
```ssh
sudo apt update
```
### Python関係の導入
```ssh
sudo apt install python3.10-venv
```
```ssh
sudo apt install python3-pip
```
### NvidiaのGPUを使えるようにする
使えるドライバーを確認
```ssh
sudo apt install -y ubuntu-drivers-common
ubuntu-drivers devices
```
上記コマンドでrecommendedされたバージョンに以下のバージョン `535のところ` を変更して実行
```ssh
sudo apt install -y nvidia-driver-535
```
### ComifyUI
リポジトリをクローンしてそのディレクトリに移動
```ssh
git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
```
リポジトリの指示にしたがって環境構築
まずはpytorchのインストール
```ssh
pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121
```
`requirements.txt` のパッケージをインストール
```ssh
pip install -r requirements.txt
```

これで環境構築完了！！

## 実行
`main.py` を実行してサーバーの起動
```ssh
python3 main.py
```
Magisk Delta APK Download

Magisk Delta - Root, Customization, Modules, SafetyNet, Systemless

Welcome to the official website of Magisk Delta, the ultimate solution to root your Android device. Magisk Delta is a renowned tool for rooting and customization, offering users a remarkable set of features to achieve complete control over their devices. With a simple Magisk Delta download, users can enjoy a highly efficient and systemless root process.

The Magisk Delta APK is designed for simplicity, offering a user-friendly interface that extends beyond basic rooting functions. It provides an environment for module management, enabling users to add or remove modules according to their preferences. Magisk Delta's modules cover a varied spectrum of needs, addressing everything from aesthetics to functionality.
githubのコミットを２つ戻して強制的にpushしたい

1. 現在のブランチの履歴を確認し、戻したいコミットのIDを見つける
`git log --oneline`
1. 指定したコミットにHEADをリセットする（ここではHEADから2つ前のコミットを指定）
`git reset --hard HEAD~2`
1. 強制的にプッシュしてリモートの履歴を上書きする（この操作は他の人がそのブランチの変更をプルしている場合、問題を引き起こす可能性があるため注意）
`git push origin HEAD --force`
テスト駆動開発

# はじめに
テスト駆動開発（TDD）について、「実践テスト駆動開発」を元にまとめてみようと思いました。全てをここでアウトプットすることはできないので、自分が常日頃TDDについて感じていることを書籍を読みながら整理していきます。

# なぜテスト駆動開発（TDD）が必要なのか
テスト駆動開発の基礎的なプラクティス（テストを書いて、実行する）は実践しているものの、結果を出せずに苦しんでいるチームがある。表面的な理解で、ただやるだけでは機能しないことが分かる。ではこのTDDの真髄はどこにあるのか。

#### オブジェクト指向ソフトウェアを「育て」、より良い品質のコード作成はテストによって「導かれる」

ソフトウェアは常に動く状態にしなければならない。しかし、これは「言うは易し。行うは難し」で実際のコードは複雑なコードが多くの箇所で書かれており、保守をするのは大変だ。ただ、これは整備されていない場合の話。TDDを実践していると、動いているシンプルなシステムが相互に作用するようになっている。つまり、生物学的な細胞のようにメッセージを送りあっていて、より巨大なシステムを構成したいと思ったら、一つ一つが多くのところで活用される（育てる）ようになる。

そんなシンプルでかつシナジーを出せるようなコードを作るためには、TDDしか道はない。良いコード作成の前には良い設計がある。TDDはその設計を明確にしてくれる。テストを先に書くことで自分の意図を明確にしなければならないからだ。コーディングをどうすべきかを自分が曖昧にしか言語化できないうちは作業に着手できなくなる。テストを先に書くと言うプロセスに従うことで、自分の狭い視野や凝り固まった考えをテストによって自覚することができる。リファクタリングでも、同じデグレが生じないようにテストが支えてくれるのだ。

# TDDのメリット
テストを使ってコードに「何を」させたいのかというアイディアを明確にすることができる。そして、そのアイディアの質はテストを先に書くことによって迅速なフィードバックが得られる。つまり、実装に入る前により良い設計を早いフィードバックサイクルによって実現することを可能にするのだ。

# 受け入れテストとユニットテストの役割とは
テストをしているとしばしばこの2つを耳にする。両方やらなければならないことは分かっているが、それぞれが何を担保しているものなのかいまいちよく分からなかった。しかし、今回の学びでそれが明確になった。

#### 外側の質と内側の質
外側の質とはシステムが顧客やユーザーのニーズ（機能を備えているか、信頼できるか）に応えられているか、内側の質とは開発者や管理者のニーズ（理解しやすいか、変更しやすいか）にどれくらい応えられているか。エンドツーエンドテストではドメインについてどれだけ理解しているかについての知見が得られるが、コードの質については分からない。それを担保してくれるのがユニットテストで。多くのフィードバックを得ることで高品質のコーディングを可能にする。

### 振る舞いのユニットテストを行え、メソッドをテストするのではない
テストに限らず、コーディングでは常にリーダブルでなければならない。自分だけが分かるコードを書いても、他の人が読みづらかったり、理解しづらかったりするとリファクタリングコストが高くなってしまう。テストでも同じだ。例えば、testGetAccount()
という名前のテストでは何をしているかは分かるが、**「何のために」** テストしているかが分からない。そのテストケースでは、対象のオブジェクトはどうあるべきなのかという　**「振る舞い」** に焦点を当てたテスト名を書くのが望ましい。

# まとめ
今回はテスト駆動開発の基礎の基礎をまとめました。書籍の5%くらいのことしか整理できていないと思っています。ただ、自分がやっていることが何のためのものなのか、目的が明確になったことが自分にとっての学びでした。引き続き読み込むことで、より良いテスト駆動開発を目指していこうと思います。
エディタコマンドをキーボードショートカットに登録する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41105/fc5b892f-0408-e4e9-d574-762dfea8a27b.png)

https://qiita.com/koorinonaka/items/d8e9193632125c5dd3d5

先日投稿した記事ですが、エディタでリンクを生成するたびに `右クリック` `スクリプトアクション` を実行する手間がなかなかに面倒なので、キーボードショートカットを用意することにしました。

# コマンドの定義
```C++
class FUnrealProtocolContentBrowserCommands final : public TCommands<FUnrealProtocolContentBrowserCommands>
{
public:
	FUnrealProtocolContentBrowserCommands() :
		TCommands( TEXT( "UnrealProtocolEditorCommands" ),
			NSLOCTEXT( "Contexts", "FUnrealProtocolEditorModule", "Unreal Protocol Editor Plugin" ), FName(),
			FAppStyle::GetAppStyleSetName() )
	{
	}

	// TCommands<> interface
	virtual void RegisterCommands() override
	{
		UI_COMMAND( CopyLink, "Copy Link", "copy custom protocol link.",
			EUserInterfaceActionType::Button,
			FInputChord( EModifierKey::Control | EModifierKey::Shift, EKeys::C ) );
	}

public:
	TSharedPtr<FUICommandInfo> CopyLink;
};

void FUnrealProtocolEdModule::StartModule()
{
	FUnrealProtocolContentBrowserCommands::Register();
}
```
まずは `TCommand` を継承したクラスを用意して、実行するコマンドを登録していきます。`Ctrl` `C` のように、同時入力の登録も可能です。ただし同時入力できるキーは `Ctrl` `Shift` `Alt` `Command` に限られます。

## 入力キーが既に登録済みだった場合？
FUICommandList で先に登録されたキー入力が優先されます。入力が効かないときは被らないように設定してみましょう。`FUICommandList::ConditionalProcessCommandBindings` 辺りを参照。

## ショートカットのユーザー設定を変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41105/c33c4a7c-cf77-a7b9-fe93-1d50539ac9ae.png)
`エディタの環境設定` `キーボードショートカット` で、コマンドごとに項目が追加されます。適当なキーで上書き可能。

:::note info
膨大な量のショートカットが用意されていますが、`UI_COMMAND` で渡す `FriendlyName`（第二引数）の文字列のみがフィルタされるようで。カテゴリなどでは絞り込めないので注意。
:::

# コマンドの登録
キー入力をバインドしたら、実際の呼び出し箇所へ登録する必要があります。今回はコンテンツブラウザ上で実行するので、エディタの既存実装を拡張します。

:::note info
自作の Slate などで登録する場合は `FUICommandList::ProcessCommandBindings` を自身で呼ぶ必要がある。
:::

```C++
void OnExtendContentBrowserCommands( TSharedRef<FUICommandList> CommandList, FOnContentBrowserGetSelection GetSelectionDelegate )
{
	CommandList->MapAction( FUnrealProtocolContentBrowserCommands::Get().CopyLink,
		FExecuteAction::CreateLambda( [] {	 //
		UUnrealProtocol_AssetOpen::StaticClass()
			->GetDefaultObject<UUnrealProtocol_AssetOpen>()
			->CopyLink();
	} ) );
}

void FUnrealProtocolEdModule::StartModule()
{
    // ...
	FContentBrowserModule& ContentBrowserModule =
		FModuleManager::LoadModuleChecked<FContentBrowserModule>( TEXT( "ContentBrowser" ) );

	DH_ContentBrowserCommandExtender =
		ContentBrowserModule.GetAllContentBrowserCommandExtenders()
			.Emplace_GetRef( FContentBrowserCommandExtender::CreateStatic( &OnExtendContentBrowserCommands ) )
			.GetHandle();
}
```

これでショートカットが実行できるようになりました。

# サンプルコード
[Github](https://github.com/koorinonaka/UnrealProtocol/blob/main/Source/UnrealProtocol/Private/UnrealProtocolContentBrowserExtensions.cpp) に公開してます。
Raspberry Pi 5 の ペリフェラル速度をユーザー視点で調べてみた

# この記事は？
**「ラズパイ5、GPIO が遅いって話があったけどどうなの？」** を、ユーザー視点で GPIO / I2C / SPI / UART を使って試してみたポストのまとめです。
主にラズパイ 5 と 4 の比較です。

（素人なので、調べ方や結果が正しいかわかりませんが、あくまで発売間もない現時点での **１ユーザーの体験** を記しておきます。）


# どうなの？

なんかラズパイ5 の CPU (BCM2712) は **RP1 とかいうチップ**と PCIe Gen2 x4 でつながっていて、その **RP1 が GPIO 担当**らしい？

**うん、よくわからん**

よし、**とりあえず使ってみよう**

# 概略
Raspberry Pi 5 (bookworm 64bit)　(以下、Pi5)
Raspberry Pi 4 (bullseye 64bit)　(以下、Pi4)
<br>

:::note info
①　GPIO 繰り返し Python コード
**Pi5: 400 kHz (GPIO 出力 800 kHz ?)　〇**
Pi4:  95 kHz (GPIO 出力 190 kHz ?)

②　I2C baudrate 設定
Pi5: 100 kHz - 1.0 MHz
**Pi4: 100 kHz - 3.4 MHz　〇**

③　SPI Clock データ化けせず受信できる最大実行速度
**Pi5: 67 MHz　〇**
Pi4: 50 MHz

④　PWM　設定可能周波数
Pi5: 34 nsec period -> オシロ上で 15.36 MHz ?
**Pi4: 10 nsec period -> オシロ上で35.76 MHz ?　〇**

⑤　UART 通信速度 (PySerial)
**Pi5 / Pi4: ともに 2.5 Mbps 程？　〇**
:::

<br>
<br>

ライトユーザーの自分からすると、ラズパイ5 で**十分な速度が用意されている**ようでした。

良かった～！


# 結果まとめ

## ①　GPIO

https://x.com/devemin/status/1758050429022404934?s=20

※ ラズパイ4 で使っていた pigpio ライブラリが現段階ではラズパイ5 で非対応？これだけ残念。
libgpiod や gpiozero といったライブラリを使えば良いみたいです。


参考：
https://x.com/devemin/status/1757384812644757789?s=20


## ②　I2C

https://x.com/devemin/status/1758098282264535450?s=20

## ③　SPI

https://x.com/devemin/status/1758111934208217336?s=20

## ④　PWM

https://x.com/devemin/status/1758129060268622225?s=20

※ gpiozero ライブラリで簡単に PWM できました。

## ⑤　UART

https://x.com/devemin/status/1758143178958623026?s=20

# 気になるところ

https://x.com/devemin/status/1758140552355500115?s=20

# 個人的感想

https://x.com/devemin/status/1758061486126322067?s=20


# オマケ

https://x.com/devemin/status/1758039197750018203?s=20

https://x.com/PINTO03091/status/1757946067067543962?s=20


以上です。

ありがとうございました！
【JavaScript】fetchでネットワークエラーが発生した場合の処理を記述する方法

`is-netwark-error`というライブラリを使用することでネットワークエラーが発生した場合の処理を記述できます。

https://github.com/sindresorhus/is-network-error

```shell
npm install is-network-error
```

```js
import isNetworkError from 'is-network-error';

async function getUnicorns() {
	try {
		const response = await fetch('unicorns.json');
		return await response.json();
	} catch (error) {
		if (isNetworkError(error)) {
			// ネットワークエラーの際の処理
		}

		throw error;
	}
}

console.log(await getUnicorns());
```

## 参考

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch#%E3%83%95%E3%82%A7%E3%83%83%E3%83%81%E3%81%8C%E6%88%90%E5%8A%9F%E3%81%97%E3%81%9F%E3%81%8B%E3%81%AE%E7%A2%BA%E8%AA%8D
[記事紹介] Gmailの送信者のガイドラインの強化がもたらす未来

元 @qualitia_cdevの中の一人、@hirachanさんが書いた記事をみなさまにご紹介します。

### Gmailの送信者のガイドラインの強化がもたらす未来
https://qiita.com/hirachan/items/f668511783c6e0663cb2
Chat GPT　トークン数の計算


生成AIを使っているとよく出てくる「トークン数」

課金の単位にもなっていることも多く、気になっている方も多いかと思います。

今回はトークン数とは何？といったところから実際にトークン数を計算するところまで解説していきたいと思います。

## トークン数とは
Chat GPTのトークンとは、Chat GPTが処理するテキストの基本単位であり、英語においては1単語≒1トークンとなります。

ただし、日本語においては1文字≒1～3トークンと英語に比べてトークン数が多くなるのが大きな特徴です。

Chat GPTのAPIは、文字単位ではなく、トークン単位で入力の数を計算し、APIの利用時は利用料金に関わってきます。

Chat GPTのAPIの最大トークン数は4096トークンで、それよりも大きなトークンを入力した場合はエラーとなってしまいます。

利用料金の削減や処理速度を速めるためにトークン数をできるだけ削減した入力を意識することが重要になります。

## トークン数の計算

そんな重要なトークン数ですが、Chat GPTでは入力しているときに教えてくれないという不親切ぶりなので、トークン数を計算するプログラムを作成し、計算してみます。

今回使うコードは以下になります。

```python:token_calc.py
# パッケージのインストール
!pip install tiktoken
import tiktoken

#chatにトークン計算したい文章を入力
chat="おはようございます"

encoding_35 = tiktoken.encoding_for_model("gpt-3.5-turbo-0301")
encoding_4 = tiktoken.encoding_for_model("gpt-4-0314")

def calc_token(chat, encoding_name):
    encoding = tiktoken.get_encoding(encoding_name)
    num_tokens = len(encoding.encode(chat))
    return num_tokens

print("GPT3.5のトークン数：", calc_token(chat, encoding_35.name))
print("GPT4のトークン数　：", calc_token(chat, encoding_4.name))

```
結果
GPT3.5のトークン数： 6 
GPT4のトークン数　： 6

「おはようございます」のトークン数はGPT3.5、GPT4ともに6となりました。

ちなみに同じ意味で英語のトークン数について調べてみると。

```python:token_calc.py
chat="good morning"

print("GPT3.5のトークン数：", calc_token(chat, encoding_35.name))
print("GPT4のトークン数　：", calc_token(chat, encoding_4.name))
```
結果
GPT3.5のトークン数： 2 
GPT4のトークン数　： 2

やはり英語のほうがトークン数少なくすみますね。


## ライブラリ

今回使ったライブラリですが、tiktokenというOpenAI公式のBPEトークナイザーです。

BPEトークナイザーという聞きなれない単語が出てきましたが、BPEはバイトペアエンコーディングという文字列の圧縮手法（例えば出現頻度が高い2文字を使われていない1文字に変換するなど）、トークナイザーはそれをトークンに分割するプログラムのことを示しており、それを合わせてBPEトークナイザーといいます。

ここを掘っていくとかなり難しくなっていくので、現時点ではChat GPTの入力分をトークンに分割するところまでやってくれるものと思っておきましょう。

今回使ったGPT3.5、GPT4以外にもダヴィンチやバベッジなどのモデルも対応しているそう。

https://github.com/openai/tiktoken

## まとめ
今回はChat GPTのトークン数を計算する手法について解説しました。

トークン数はAIと会話するうえで今後重要になってくる項目なので、生成AIを使うときには意識してみてください。
webページのルーティングサンプル


URLは基本的により左にある階層で大まかなジャンルを表し、右側で具体的な内容・同紙などを表す

* /
* /content
* /content/create
* /content/\<id>
* /content/\<id>/result
* /content/\<id>/run
* /login
* /user
* /user/create

## 可変パス

* /user/\<user_id>
    * /user/userA
* /user/\<user_id>/profile
    * /user/userA/profile
* /content/\<token>
    * /content/77uaaz8fPwVzFD8aPyxGPzIaPx15PwhGPz8vOT9faz9vDQob

## bad route
1. /\<uid>
2. /profile

/profileにアクセスした際に1番へルーティングされてしまうことがあるため良くない


## 余談
知り合いに教える機会があったため書いてみました
ポモドーロ法でJISOU1日目を駆け抜けた

# ポモドーロ法とはなにか
ポモドーロ法(ポモドーロテクニック)とは、一種の勉強スタイルのようなものです。実際にどのように行うかというと…
- 25分間集中して何かに取り組む(学習など)
- 5分休憩、放心状態 ( ﾟ ρ ﾟ )

25分、5分といったところは各々で微調節してもらって全然OKです。
ポモドーロ法を試すときに重要なのは、***休憩の時間***です。極力何もしないでください。スマホを見るのはやめましょう。

僕も勉強の休憩によく「スマホみよっ」となることがあるんですけど、正直脳にとっては筋トレからのさらに筋トレという地獄みたいな状況です。とにかく脳にとっては負担なんです。だから、極力何もしない・もしくはストレッチなどの脳を使わないことをするというのが休憩に効果的です。

# 実践してみて
僕は本日からJISOUといサービスに参加してプログラミングのコーチングを受けているのですが、今日の課題をポモドーロ法を用いてやり切りました!ぎりぎりだったぁ…ふぅ

実際ポモドーロ法をしっかりと実践したところ、普段よりも高い集中力を保つことができてコーディングもとても楽しかったです！正直自分でもここまでできるとおもってなかったです。それに加えてJISOUの先輩方の手厚いサポートもあり、まさに鬼に金棒といった感じでした。

簡潔にポモドーロ法の効果をまとめますと
- 集中力が上がる
- 普段より疲れにくい
- 終日を通して頑張り切れる
- 作業(僕でいうとコーディグ)を全力で楽しめる

# 最後に
みなさんも「やりきりたい！今回こそは達成したい！」と思えることがあればぜひポモドーロ法を活用してみてはどうでしょうか？

僕と一緒に頑張りましょう!!!