OmniAICreator/Qiita-1.07M huggingface dataset:
大きさNの文字列の部分文字列はいくつあるか？

# 考える問題
**大きさ（長さ）$N$の文字列の部分文字列の数は？**（ただし，空文字列を含まない．）

:::note warn
連続した文字列であることに注意してね
:::

# 結論
部分文字列の数は，
``` math
\frac{N (N+1)}{2}
```
となります．

# 考え方
## ポイント
部分文字列を一つに決めるためには，その部分文字列の**最左端の位置と最右端の位置**を決めればいいです．

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457534/6be9b5cc-5840-e865-db44-d2e7bba106b5.png)

ここで注意したいのは，**最左端と最右端の位置は重複してもいい**ということです．理由は，部分文字列の大きさが1の場合を考えればおわかりいただけると思います．

![図1のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457534/872cb0ad-9b19-d423-795e-90877fe395c9.png)


つまり，
``` math
(部分文字列の選び方)=(重複を許してN個から2個選ぶ場合の数)
```
となります．

## 重複組合せ
では，「重複を許して$N$個から2個選ぶ場合の数」はどのように表されるでしょうか？このような問題は**重複組合せ**とよばれます．重複組合せの考え方は2つあります．

### 考え方1（公式を使う）
$n$個から重複を許して$r$個選ぶ組み合わせの数を${}_n \mathrm{H}_r$と表すと，以下の公式が成り立ちます．

``` math
{}_n \mathrm{H}_r = {}_{n+r-1}\mathrm{C}_r
```

この公式において　$n=N, r=2$とすれば，

```math
{}_N \mathrm{H}_2 = {}_{N+2-1}\mathrm{C}_2 = \frac{N(N+1)}{2}
```
となります．

### 考え方２（原理的に考える）
重複組合せの原理は，**仕切りの考え方**を用いることで説明できます．今回のような問題においては，部分文字列の選び方の数は，「2つの仕切りを異なる文字列間（両端含む）に入れる場合の数」に一致します．仕切りをいれる位置は以下の図に示すとおりです．
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457534/726c227c-f864-3f8a-6b21-efc2e6987b81.png)
部分文字列を仕切りに挟まれた部分の文字列と考えれば，部分文字列と仕切りの選び方が1対1に対応します．
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457534/bc4425b3-dc60-e749-3533-9ff809ca5344.png)

仕切りをいれることのできる位置の場合の数は，文字列の大きさ$N$を用いて，$N+1$と表せます（図の例で言うと，文字列数8に対して，仕切りをいれることのできる場所の数は8+1=9箇所となります）．

よって，仕切りの選び方の場合の数は，$N+1$個の箇所から，重複をせずに2箇所選ぶ組み合わせの数となるので，
``` math
{}_{N+1}\mathrm{C}_2 = \frac{N(N+1)}{2}
```
となります．したがって，大きさ$N$の文字列の部分文字列の数が$\frac{N (N+1)}{2}$となることが導けました．

ここで重要なのは「重複組合せ問題から重複を排除し，単純な組み合わせ問題に帰着させた」という点です．考え方1の公式と本質的な考え方は同じです．考え方2では$n=N, r=2$の場合においてのみ，原理的に考えるという方法を用いましたが，任意の$n, r$において同様の考え方が可能です．
Pendulum使って簡単日時実装③ プロパティ

# Pendulumとは
日時の操作を容易にするPythonパッケージ

https://pendulum.eustace.io/

# 前回
[Pendulum使って簡単日時実装①](https://qiita.com/i-am-misaki/items/2ad110049ee541c4c3ee)
[Pendulum使って簡単日時実装②](https://qiita.com/i-am-misaki/items/abccb3b5c592f029771c)

# プロパティ
>Pendulumはdatetime クラスよりも多くの属性とプロパティにアクセスできます。

#### プロパティとは
>どんなやつかを表す情報

https://wa3.i-3-i.info/word11066.html

```python
dt = pendulum.now()
# 2024-06-23 14:09:31.460621+09:00

>>> dt.year  # 年
2024
>>> dt.month  # 月
6
>>> dt.day  # 日
23
>>> dt.hour  # 時
14
>>> dt.minute  # 分
12
>>> dt.second  # 秒
21
>>> dt.microsecond  # マイクロ秒
967079
>>> dt.day_of_week  # 曜日
WeekDay.SUNDAY
>>> dt.day_of_year  # 年の日数
175
>>> dt.week_of_month  # 月の週
4
>>> dt.week_of_year  # 年の週
25
>>> dt.days_in_month  # 月の日数
30
>>> dt.timestamp()
1719120513.403804
>>> dt.float_timestamp
1719120513.403804
>>> dt.int_timestamp
1719120513
```

>These properties specifically return integers

とのことですがday_of_weekは文字列返ってきたんやが......??
ドキュメントでは数値が返ってる...

<br></br>
## .age
###### 同じtzで計算された対現在の比較
年齢調べる際にとっても便利 ♪
やけん、ageなんかな
```python
>>>pendulum.datetime(1980, 11, 28).age
43
```

## .quarter
四半期
```python
>>>dt.quarter
2
```


## is_dst()
サマータイムがオンかどうかを示す
```python
>>> dt = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
>>> dt.is_dst()
False
>>> dt = pendulum.datetime(2012, 9, 1, tz='America/Toronto')
>>> dt.is_dst()
True
```



## .offset
###### UTC からの秒の差を int で返す (+/- の符号を含む) 
UTCからの時間差を秒単位で指定

```python
>>> pendulum.from_timestamp(0).offset
0
>>> pendulum.from_timestamp(0, 'America/Toronto').offset
-18000
# 1970 年 1 月 1 日、「アメリカ/トロント」はUTC-5 時間
# Unixエポック時間における「America/Toronto」タイムゾーンのUTCからの時間差を秒単位で示す
```

###### UTC(協定世界時)
>世界の標準時刻の基準として用いられる時刻

https://e-words.jp/w/UTC.html

###### UNIX時間
>コンピュータにおける日時の表現規則の一つで、主にUNIX系OSで標準的に用いられている形式。時刻を協定世界時(UTC）1970年1月1日午前0時ちょうどからの経過秒数で表す。

https://e-words.jp/w/UNIX%E6%99%82%E9%96%93.html


## .offset_hours
###### UTC からの時差を float で返します (+/- 記号を含む)
```python
>>> pendulum.from_timestamp(0, 'America/Toronto').offset_hours
-5.0
>>> pendulum.from_timestamp(0, 'Australia/Adelaide').offset_hours
9.5
```

## .is_local()
###### インスタンスがローカルのタイムゾーンと同じタイムゾーンにあるかどうかを示す
```python
>>> pendulum.now().is_local()
True
>>> pendulum.now('Europe/London').is_local()
False
```


## .is_utc()
###### インスタンスがUTCタイムゾーンにあるかどうかを示す
```python
>>> pendulum.now().is_utc()
False
>>> pendulum.now('Europe/London').is_local()
False
>>> pendulum.now('UTC').is_utc()
True
```
なぜforEachメソッドを多用することってダメなの？

# はじめに
Vue.jsを学習中のエンジニアです👩🏻‍💻

現在、予約管理システムを開発中なのですが、コードを見直していると forEach メソッドを多用していることに気づきました。上司からのPR（プルリクエスト）レビューにも **「forEach 以外の書き方を覚えよう」** とコメントをいただいたほどです😅

当時はなぜforEachメソッドの多用が推奨されないのか、あまり理解できていませんでした。
そこで、forEachについての理解を深め、自分自身のアウトプットとしてこの記事を書こうと思います!

# ■forEachメソッドを多用することが良くないとされる理由
### 副作用の可能性
`forEach` は、各要素に対して指定された関数を実行しますが、その関数内で副作用が発生する可能性があります。副作用とは、関数が外部の状態を変更することです。副作用が多いコードはバグを引き起こしやすく、テストやデバッグが難しくなります。
```javascript
let total = 0;
const numbers = [1, 2, 3, 4, 5];

numbers.forEach(num => {
  total += num;
});

console.log(total); // 出力: 15
```
この例では、forEach内でtotalが変更されます。
totalの変更はforEach内で行われているため、コードを読む人はtotalの値がどのように変わるのかを理解するために、forEachの内部を追う必要があります。

### 非同期処理に不向き
forEach は同期的に動作するため、非同期処理を必要とする場合には適していません。forEach 内で非同期処理を実行すると、全体の処理が完了する前に次のステップに進んでしまうことがあります。

```javascript
const fetchData = async (url) => {
  const response = await fetch(url);
  return response.json();
};

const urls = ['url1', 'url2', 'url3'];

urls.forEach(async (url) => {
  const data = await fetchData(url);
  console.log(data);
});
```
この例では、forEach 内で async/await を使用していますが、非同期操作の完了を待たずに次の url に進んでしまいます。


### 戻り値がない
forEach メソッドは戻り値を持たないため、処理の結果を配列として取得することができません。そのため、結果をどこかに保存する必要があります。コードを読んでいる人は、forEach の内部でどのような操作が行われているかを逐一追いかけなければならず、これは可読性を低下させる一因となります。

**読みやすさとメンテナンス性**
コードの意図を明確にするためには、適切な高階関数を使用することが重要です。例えば、配列の要素を変換したい場合は `map`、フィルタリングしたい場合は `filter` を使う方が読みやすく、メンテナンスしやすいコードになります。
以下のコード例を比較してみます。
#### `forEach` の例
```javascript
const numbers = [1, 2, 3, 4, 5];
const doubled = [];
numbers.forEach(num => {
  doubled.push(num * 2);
});
console.log(doubled);
```
#### `map` の例
```javascript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled);
```
`forEach` を使用した例では、`doubled` 配列を外部で宣言し、`forEach` 内で値をプッシュする必要がありますが、`map` を使用する例では、より簡潔で読みやすいコードになります。

### まとめ
ここまでお読みいただき、ありがとうございます🙇🏻‍♀️
`forEach`を多用することがダメなわけではなく、コードを書く際に、実行する処理に適したメソッドを選択できることが重要であると学びました。
次回の開発では、様々なメソッドを適切に使用することを意識して取り組んでいきたいと思います！
DBについての個人的メモ📝

随時更新

## SQL
- SQLのインデックスの貼り直し程度の改修なら、10mm～20mm秒くらい処理速度が改善されればいい方

# A5mk2
- A5mk2の機能で、テストデータを入れることができる機能がある
# PostgreSQL
- PostgreSQLはデータとして配列を持てる
- SQLは、大文字で書いた方がいい
→色が付かないエディタでも命令文とテーブルの区別がつきやすくなる

# SQLite
- (1回目)Androidアプリで画面初期表示時
→データをSQLiteから取得する
(2回目)別画面に遷移したりしてから、画面を再表示
→View Modelにキャッシュされたstateのデータを見に行く
そのため、初期表示時よりも処理速度(画面描画)が早くなることが多い
(SQLiteから実際にデータを取得するのではない)
↑DBの処理速度を計測する際は、アンインストールしてからアプリをインストールし直したりすらことでアプリを初期化（DBの内容を1度全削除して、再度DBにデータを登録しなおす）して、画面初期表示時のタイミングで計測する必要がある
Blender 4.2のアドオン事情

# Blender 4.2のアドオンについて

2024/07/16リリースのBlender 4.2 LTSからアドオン周りが変わるようです。

https://code.blender.org/2024/05/extensions-platform-beta-release/

実際に確認してみた結果を紹介します。

## エクステンション

4.2では、**エクステンション**という機能でサイト上のアドオンやテーマをインストールできるようになります。

https://extensions.blender.org/

エクステンション（Extensions）は、プリファレンスから使うことができます。
実際に使うには、オンラインアクセスを許可する必要があります。

![スクリーンショット 2024-07-17 6.41.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/06172f8b-b487-f8fd-6310-ce50b0fa982e.png)

以下は日本語表示です。「オンラインアクセスを許可」を押すと使えるようになります。
なお、「オンラインアクセスを許可」を押したあとに戻したい場合は、システムタブのネットワークの「オンラインアクセスを許可」をオフにします。

![スクリーンショット 2024-07-17 6.41.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/02e1a66b-05e6-040b-1e17-6651a1201b0c.png)

エクステンションをインストールするには、検索で絞り込んで「Install」を押します。あるいは、下記のようにドラッグ＆ドロップでもインストールできます。

https://extensions.blender.org/about/

## 従来のアドオン

従来のアドオンも引き続き使えました。

![スクリーンショット 2024-07-17 6.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/a26ecc0f-b96e-8677-3ca7-ee01846805b9.png)

- 4.1で有効にしていた公式アドオンのいくつかは「ビルトインアドオンが行方不明」になっていました。行方不明になったアドオンは、手動で再インストールが必要なようです
- アドオンをファイルからインストールするには、右上の「`v`」の「ディスクからインストール…」で可能です
- 4.1で表示されていた「公式、コミュニティ」などのカテゴリはなくなっています。そのかわり「Testing」のアドオンも表示されるようになっています。公式のものはBlenderのアイコンに、コミュニティのものは人のアイコンに、以前のバージョンから引き継いだものはフォルダのアイコンのようです
- 参考までに、4.1のアドオンは下記のようになっています

**4.1のアドオンの画面**

![スクリーンショット 2024-06-23 15.27.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/0e842626-5420-2ca8-2549-e66807c1f5fb.png)

## エクステンションの作り方

エクステンションの作り方は下記を参照してください。

https://docs.blender.org/manual/ja/4.2/extensions/getting_started.html

エクステンションでは、`blender_manifest.toml`が必要です。
`blender_manifest.toml`の書き方については、下記を参照してください

https://docs.blender.org/manual/ja/4.2/extensions/getting_started.html#manifest

また、`blender_manifest.toml`があると、たとえば、下記のようにしてエクステンションの要件を満たしているか確認できます。

```
blender --command extension validate ZIPファイル
```

自作のエクステンションを公式サイトにアップロードできるようです（下記は**ログインが必要**です）。

https://extensions.blender.org/submit/

ただし、公開されるためには審査が必要なようです。詳しくは、上記リンク先のguidelinesやterms of serviceを確認してください（ライセンスを下記から選ぶことなどが書いてあります）。

https://docs.blender.org/manual/ja/4.2/extensions/licenses.html

## アドオンとエクステンションに必要なもの

アドオンからインストール、あるいは、エクステンションからインストールするのに必要なものは、下記のようです。

|  | bl_info（辞書） | blender_manifest.toml（ファイル） |
|:-:|:-:|:-:|
| アドオンに必要なもの | ◯ | ― |
| エクステンションに必要なもの | ― | ◯ |

※ bl_infoとblender_manifest.tomlがあるとどちらからもインストールできました。

## インストール先

アドオンとエクステンションではインストール先が違います。下記はディスクからインストールしたときのmacOSの例です。

* アドオン：`~/Library/Application Support/Blender/4.2/scripts/addons/`
* エクステンション：`~/Library/Application Support/Blender/4.2/extensions/`

## まとめ

* Blender 4.2ではエクステンションという機能により、Blender上からアドオンを検索してインストールが可能
* エクステンション用のアドオン作成では`blender_manifest.toml`が必要
* 従来のアドオンも引き続き使用可能

以上
【Pybulletサンプル解説】物体の動力学特性を変更する【changeDynamicsMass.py】

お疲れ様です。秋並です。

Pybullet公式gitリポジトリのサンプルコードを解説するシリーズです（一覧は[こちら](https://qiita.com/akinami/items/7b433b60aeb5115ba4d7)）。

<br>

今回は、changeDynamicsMass.pyを解説します。（コードのリンクは[こちら](https://github.com/bulletphysics/bullet3/blob/master/examples/pybullet/examples/changeDynamicsMass.py)）

本コードを実行すると、2つのオブジェクトが生成され、そのうち片方のオブジェクトの動力学特性を変更します。

![changeDynamicsMass.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/7c71f599-8cd3-08d1-1cb2-f91ec99c2b3e.gif)


# 使用している機能
本コードは、以下の機能を使用して「オブジェクトの動力学特性の変更」を実現しています。
- 動力学特性の変更


## 動力学特性の変更

pybulletでは、`changeDynamics`関数を使用することで「物体の指定したリンクの動力学特性」を設定することができます。

```python
pybullet.changeDynamics(objectId, linkIdx, mass)
```
- `objectId`：動力学特性を変更したいオブジェクトのID
- `linkIdx`：オブジェクトのリンクのインデックス
    - ベースリンクの場合は、`-1` を指定
- `mass`：重量（kg）

今回の場合、`loadURDF`関数で`cube2`のベースリンクを空間上に固定した状態（`useFixedBase=True`）で生成しています。

そのため、このままの状態では`cube2`は重力の影響を無視し、空間上に固定されたままなのですが、そのあとに **`changeDynamics`関数を使用することで重力の影響を受け落下するようになります**。

（ただし、サンプルコードでは、時間を待たずにすぐに`changeDynamics`関数を呼び出しているため、コードを実行した際は、すぐに`cube2`が落下しているように見えます。）


# コメントをつけたサンプルコード
サンプルコードにコメントをつけたものが以下になります（もともとあった不要と思われるコメント等については削除しています）

```python
import pybullet as p
import time
import pybullet_data

# PubulletをGUIモードで接続
p.connect(p.GUI)

# Pybulletに関するデータのパスを取得
p.setAdditionalSearchPath(pybullet_data.getDataPath())

# 箱形のオブジェクトを2つ生成する（ベースリンクを空間に固定した状態で生成）
cube2 = p.loadURDF("cube.urdf", [0, 0, 3], useFixedBase=True)
cube = p.loadURDF("cube.urdf", useFixedBase=True)

# 重力を設定
p.setGravity(0, 0, -10)

# シミュレーションの時間ステップ（1ステップあたりに経過する秒数）を設定
timeStep = 1. / 240.
p.setTimeStep(timeStep)

# cube2の動力学特性を変更
p.changeDynamics(cube2, -1, mass=1)

# Pybulletが接続されている間ループを継続
while (p.isConnected()):

  # シミュレーションを1ステップ進める
  p.stepSimulation()

  # 1ステップ分スリープ
  time.sleep(timeStep)
```
QiitaCLIで記事投稿の自動化：GitHubリポジトリからの新規作成とプッシュまでの手順

## はじめに
本記事は下記記事の続きになります

https://qiita.com/t1k2a/items/d219514e7ddab821fe5b

今回はQiitaCLIをセットアップしてから記事をを投稿まで行おうと思います


## 記事を新規作成
以下のコマンドで新規記事を作成できます
```bash
npx qiita new {記事のファイル名}
```

記事のファイル名を`testNewArticle001.md`にしたい場合は`testNewArticle001`にします

```bash
例): $ npx qiita new testNewArticle001
```

作成されたファイルは`public/testNewArticle001.md`に配置され画像のような内容になります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/b11901fe-bdd6-ba42-c9fc-91625fb657ab.png)


```markdown
---
title: testNewArticle001.md
tags:
  - test
private: false
updated_at: ''
id: null
organization_url_name: null
slide: false
ignorePublish: false
---
# new article body
```

## QiitaCLIリポジトリにプッシュする
前回作成したリポジトリに変更内容をプッシュします

```bash
git remote add origin {リポジトリのURL}
git push -u origin main
```

## エラーが出る
上記の内容のままプッシュするとActionsのWorkflowでエラーが出てしまいます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/a78cbcc4-912a-b42a-9eb0-60622279c793.png)

```bash
testNewArticle001.md: タグを入力してください
```

具体的なエラー文を出してくれるのはありがたいですね～！
なので修正いたしました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/45e2695f-9666-72b8-1422-ce412df71c89.png)

上記の内容でプッシュしたら通りました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/0d15b621-3e97-e812-9450-a82076e28131.png)

そして反映されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/54b79028-4d95-8f99-2e22-9585bc7f0548.png)
（この後削除しました）

## QiitaCLIから記事を投稿
下記コマンド実行で投稿することもできます
```bash
npx qiita publish testNewArticle001
```

```bash
$ npx qiita publish testNewArticle001
Posted: testNewArticle001 -> {記事ID}
Successful!
```

ActionsのWorkflowほど具体的ではないけどエラーも出ます
```bash
npx qiita publish testNewArticle001
QiitaBadRequestError: {"message":"Bad request","type":"bad_request"}
    at QiitaApi.request (/work/node_modules/@qiita/qiita-cli/dist/qiita-api/index.js:79:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async QiitaApi.patch (/work/node_modules/@qiita/qiita-cli/dist/qiita-api/index.js:114:16)
    at async QiitaApi.patchItem /work/node_modules/@qiita/qiita-cli/dist/qiita-api/index.js:190:16)
    at async /work/node_modules/@qiita/qiita-cli/dist/commands/publish.js:82:28
    at async Promise.all (index 0)
    at async Object.publish (/work/node_modules/@qiita/qiita-cli/dist/commands/publish.js:108:9)
    at async exec (/work/node_modules/@qiita/qiita-cli/dist/commands/index.js:41:9)
Qiita APIへのリクエストに失敗しました
  記事ファイルに不備がないかご確認ください
  ```

これならプッシュしてActionsのWorkflowで詳しいエラーが見れた方が良いかもですね～・・・


また、pushしてからActionsのWorkflowが実行されて内容のチェックが始まるので、できればコミットの段階でわかれば便利そうだなと感じました
いつかprecommitでチェックできたらよいなと思います
構想を練ってみるので可能なら記事にしてみようかと思います

## 記事の削除
記事の削除はWeb上でのみ可能ですのでQiitaCLIからは削除できないようになっておりますのでご注意ください
【ChatGPT＋DALL-E3】【Dream Machine】の動画から指定箇所を抜き出します。


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

　今回は、Dream Machineの動画から指定箇所を抜き出します。たぶん、ほかの動画も可能（未確認）

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

　まずは、ちょっとニュース？

　DALLE3 ですが、
　　先日から、
　　　処理速度が
　　　　早くなっているようです。
　　　　　計ると、10〜15秒で一枚。

　待ち時間を示す時計？も
　　半分くらいまでしか行きません。

　たまに長くて、
　　時計を一周する場合も
　　　ありますが、
　　　　これは生成に失敗している
　　　　　可能性が高いです。

　いつもなら
　　遅くなる時間帯でも
　　　ふつうに早かったですね。

　ありがたい😸
***
　さて、本題です。

　今回は、
　　動画の特定箇所を
　　　抜き出します。

　動画のその場所だけが
　　欲しいときがありますよね。

　そんなときに
　　使います。
***
　やり方です。

　まずは、セッションが
　　GPT-4oであることを
　　　確認します。

　次に、
　　動画をアップロード。

　下記のPromptを入力。
　　ここでは、2秒目から4秒目を
　　　指定していますので、
　　　　必要に応じて変えてください。
```Text:指定箇所を取り出すPrompt
MoviePyを使って、2秒目から4秒目をカットして、ファイルにしてください
```

　これで、送信。

　しばらくすると
　　ダウンロードリンクが
　　　出てきますから、
　　　　ダウンロードします。

　出来上がった動画を
　　確認してください。

　はい、終了。
***
　なお、
　　人様の動画を
　　　カットして、アップするのは
　　　　楽しくてもやってはいけません。

　悪意はなくとも
　　その行為自体が
　　　それを行なわれた人の
　　　　気分を削ぐことです。

　悪用禁止ですよ。
　　ご注意くださいね。

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

　今回は、ここまで。
16の倍数となる条件「1997 一橋大学 前期【1】」をChatGPTとsympyでやってみたい。

# オリジナル
・ KATSUYA【東大数学9割】様 (0:00〜13:39) 

https://youtu.be/0yA6BOPjpXQ

・大学入試数学問題集成 様＞ 前期【1】　テキスト
　＞犬プリの世界さんの解答(PDF)へ

https://mathexamtest.web.fc2.com/1997/199710272/1997102720100mj.html

# ChatGPT-3.5先生へ。
・回答は英語です。
　はじめから、「日本語で」を追加してもいいです。
・ページのソースを表示です。MathMLです。
　省略しようと思いましたが、大学入試数学問題集成 様 の全文から必要部分の抜粋です。
```
<div class="qbody">
<p class="slevel"><a name="q-0101" id="q-0101"></a><span 
class="qnum">【１】</span>　すべての正の整数<math>
<mspace width=".2em"></mspace><mi>n</mi>
<mspace width=".2em"></mspace>
</math>に対して<math>
<mspace width=".2em"></mspace><msup><mn>5</mn>
<mi>n</mi></msup><mo>+</mo><mi>a</mi><mo>&it;</mo>
<mi>n</mi><mo>+</mo><mi>b</mi><mspace width=".2em"></mspace>
</math>が<math>
<mspace width=".2em"></mspace><mn>16</mn>
<mspace width=".2em"></mspace>
</math>の倍数となるような<math>
<mspace width=".2em"></mspace><mn>16</mn>
<mspace width=".2em"></mspace>
</math>以下の正の整数<math>
<mspace width=".2em"></mspace><mrow><mi>a</mi>
<mspace width=".2em"></mspace><mtext>，</mtext>
</mrow><mi>b</mi><mspace width=".2em"></mspace>
</math>を求めよ．
</p>
</div>
</div>
```
回答省略(英語です)
```
日本語で
```
...
したがって、条件を満たす解は次の通りです。
a=12,b=15
これらの値は問題の条件を満たしています。
# ChatGPT-3.5先生へ。sympyで
```
sympyで
```
・(抜粋)
・print文を、私が追加しています。
```python
import sympy as sp

# 変数を定義
a, b = sp.symbols('a b')

# 方程式を定義
eq1 = sp.Eq(a + b, -5)
eq2 = sp.Eq(2 * a + b, -9)

# 方程式を解く
solution = sp.solve((eq1, eq2), (a, b))

# 解を16の範囲内の正の整数に変換
a_solution = solution[a] + 16
b_solution = solution[b] + 16

# a_solution, b_solution

print("#",a_solution, b_solution)
# 12 15
```

# sympyで(オリジナル 様の方法で)
???勉強中です。??? mod も
16✕16 の全数チェックしか思いつきませんでした。

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

# いつもと違うおすすめです。
・以下ができたら、助かります。

https://qiita.com/mrrclb48z/items/555d85face87552c34fb
ユーザーベース協調レコメンドをpythonで

# はじめに
ユーザーベース協調レコメンドにチャレンジ。
とりあえず動くものができたのでUP。
細かい説明は後日ゆっくりと。

# githubにおいといた

https://github.com/watyanabe164/Introduction-to-Recommendation-Algorithms

# 実行結果
詳細はgithubのコードをみたらよいことにしておいて、
実行結果がどんな感じかだけ残す。

実行すると、類似の高いユーザーが読んでいる書籍からおすすめ書籍のIDを10個出すようになってる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/f09c61eb-eef6-b139-894c-989837736bce.png)

お試しで作ったので超粗削りだけど、動くものができたので満足です。

# メモ：Geminiに元ネタを考えてもらったときのプロンプト

プログラム作成に際してGeminiには世話になったのでそのときに書いたプロンプトおいとく

```
以下の仕様に基づいて貸し出し図書の履歴情報を使ったユーザーベース協調レコメンドの処理をpythonで実装してください

## 要件
・SQLiteにデータを実装
・履歴情報テーブルには以下のトランザクション情報が保管されています
　- 本を借りた人の会員ID
　- 借りた本の書籍ID
　- 貸出日
・お勧めする本の優先順位は、本マスタテーブルに登録されている、レーティング情報を参考にします。
　- 書籍ID
　- レーティング値(1～5で設定）
```

今日、やりきれなかったけど書籍の推奨度計算に機械学習の要素を取り入れたく
プロンプトを考えておいた。後で再開するときの参考材料のために残しておく。

```
以下の仕様に基づいて、scikit-learnの機械学習を使って履歴情報と書籍情報、ユーザー情報から貸出される確率を算出する処理を実装してください

・ユーザー情報は以下の属性をパラメータとして使用
　- 年齢
　- 性別
・書籍情報は以下の属性をパラメータとして使用
　- カテゴリ
　- ページ数
```
KaggleのLLMのRLHFコンペ：LMSYS - Chatbot Arena Human Preference Predictions

最近、KaggleでLLMのRLHF（人間のフィードバックによる強化学習）に関する新しいコンペが開催されました。コンペ名は「LMSYS - Chatbot Arena Human Preference Predictions」です。

https://www.kaggle.com/competitions/lmsys-chatbot-arena

このコンペの目的は、異なるモデルが生成した回答のうち、どれが人間に好まれるやすいかを予測するモデルを作ることです。LLMのトレーニング中におけるRLHFの「報酬モデル」に近いイメージです。
コンペのデータは、LLMのベンチマークを行うサイト「Chatbot Arena」から提供されています。このサイトでは、ユーザーが質問すると、ランダムに選ばれた2つのLLMが同時に回答します。ユーザーはこの2つの回答を比較し、どちらがより優れているかを選びます。選ばれたモデルは加点する仕組みによって、LLMのランキングが作成されています。（もちろん自分でチューニングしたモデルをアップロードして他のモデルと競わせることもできます）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/ad4c3f13-2658-8d8b-972b-ec27bd3de03a.png)

最終的な提出データは、ID、モデルAが勝つ確率、モデルBが勝つ確率、引き分けの確率の4列で構成されます。これら3つの確率の合計は1になり、実際の結果との対数損失で評価されます（なぜ対数損失取るかはよくわかりませんが、おそらく実際の結果に近いほど評価が高いと思います）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/86665617-f0f6-0c4f-0200-5a0efa0e9949.png)

コンペのルールはシンプルで、現在参加者のアプローチも大きく分けて二つです。一つは大規模言語モデル（LLM）を直接トレーニングする方法、もう一つはLightGBMなどの従来型の機械学習アルゴリズムを使用して予測モデルを構築する方法です。

私もこのコンペに最近参加したばかりで、まだ不明な点が多いのですが、RLHFには結構興味ありますので、このコンペを通じてRLHFについて詳しく学びたいと思います。
Intellij IDEAでtypo検出の緑の波線を消す方法

## 症状

![スクリーンショット 2024-06-23 14.26.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3172801/2b43ba70-e7ae-bbd5-4011-3902661687c2.png)

邪魔ですね。

## 対策

Settings（command + ,）　→　Editor →　Inspections　→ Proofreadingのチェックを外せばオーケーです。

![スクリーンショット 2024-06-23 14.29.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3172801/f0129423-e192-6e8f-be4f-7b3011534982.png)

![スクリーンショット 2024-06-23 14.33.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3172801/6f4a303d-1fad-f3ad-4210-3daf26664a17.png)
PERT図を書こう

## 主張すること
- PERT図を書かずに、ガントチャートもどきを作ってもプロジェクト管理に失敗する。

## ガントチャートもどき
### ガントチャートもどきの特徴
- 各作業間の依存性が明示されていない。
- どのような依存性の結果、最終目標につながっているのかが見えてこない。
- 最終目標までの作業の分析が、このガントチャートで適切に表示されているのかがわからない。
    - 欠落している作業の存在を見失う。

- 担当分のガントチャートもどきに従っていることによる正当性の主張
    - 「それは私の仕事じゃない。」、「私は提示した計画通り進めている。」
- 外部への製造委託、開発委託などのクリティカルなイベントとの関係が人によって不明確になる。
- 各作業の成果物が不明確
- 各作業の成果物の可否の判定基準が不明確 

## PERT図とは
https://ja.wikipedia.org/wiki/PERT

![](https://upload.wikimedia.org/wikipedia/commons/b/b9/Pert_chart_colored.gif)
5つのマイルストーン（10から50）と6つの作業（AからF）がある7カ月間のプロジェクトのPERT図
上記のWIKIから引用


## PERT図を書こう
- ガントチャートよりもPERT 図の方がいい。
　依存関係が明確になる。
- 組織としてのゴール
　製品の設計完了、試作完了、動作試験完了、出荷　などのイベントが各タイミングのゴールとして存在する。
- 各人の作業は、そのゴールつながるものでなくてはならない。
　そのなかで、メンバー間の作業の依存関係が明確になる。
- PERT図の◯（ノード）が他のノードとつながっていなければ、
　途中の作業が抜けているため、つながっていない。
　抜けている作業を足していこう。
- どの作業を優先させればよいのかが明確になる。
- どの作業とどの作業が無関係に並行して進められるのかが明確になる。
　人を投入して結果を前倒しできるようになる。
- それぞれの作業の入力データ・出力データが明確になっていれば、外部への発注で社内のリソースを補える。
- チェックポイントとチェック内容を意識するようになる。


### PERT図を書かない場合に生じること
- どのようにそれぞれの作業が最終目標に関係しているのかが見えない。
    - 知っているつもりの（わかっていてもらえているはずの）暗黙の依存性は、明示化しない限り伝わらない。
    - 作業の依存関係が、その分野以外の人（非エンジニア）にとっても分かる状況にならない。
- その作業の流れを組織として、妥当なものとして承認をしたかどうかが欠け落ちる。
- Aさんの作業とBさんの作業との依存関係が見えない。



## 不幸な状況に陥ったプロジェクト
- 自分たちのプロジェクトの勝利条件を明確にしていない。
    - すること、しないことの区別を明確にできていない。
- すでに露見している「不幸な状況の始まり」に対して対策を準備しない。
    - そのことに対する対策を行わなかったという判断ミス。
- 商利用を目的とした研究開発で、製品に利用するための判断基準を、開発者に提示しないという問題点
    - どういう条件を満たせば、産業的に意味が出て事業化をできるのかを示さない。
    - そういう条件のまま、大勢を投入しても、事業化できる技術は開発できない。
    - 多額の開発投資を行なったあとに、つまらない理由による開発の断念。
- 「目標設定じたい**無理**なんじゃね」
    - 目標設定じたいが、実現不可能な妄想をであるというプロジェクト
    - そういうプロジェクトに配属されてしまっても、どうしようもない。
    - 実現可能でかつ意味がある目標への修正を受け付けてもらえない。
- 「目標設定じたい**無意味**なんじゃね」
    - 今の技術では、実現不可能なこと、あるいは、とっくに別の技術で達成されている場合
    - 目標は、まだできていないことで、今後の開発期間の中で実現可能なことを目標に設定しないと意味がない。

- 関係者が適切に動機づけられていない。
    - 「その問題は、私の知ったことじゃない」とより大きな問題に対して関与することを避けてしまう。
    - 「そこに問題があっても、言われた通り実現すればいい。」と考える。
    - 「自分より前の工程で失敗してくれるなら、自分の作業が問題にならなくてラッキー」などいう不誠実な考え方。
    - 「給料さえちゃんと貰えればOK」
    - 「最悪、別の会社に転職するし」
- 担当者の失敗をたたいてしまう。
    - 適切な判断をするための情報が共有されなくしてしまう。 
    - うまくいかなくて手助けを必要としている人が、手助けを求められない。
- 現在進行中の技術の進展を見誤る。
    - そのため、その技術を取り入れることが必要なのに、その技術を無視してしまうことで、今までのその分野での実績を無意味なものにしてしまう。
- そのタスクをこなせる人の重要性を理解しない。
    - そのタスクをこなせる人の重要性を理解しないので、見解の不一致などで、その人を簡単に捨ててしまう。
    -  
- なんでも自前で作りたがる。
    - 購入すれば十分のものを自前で作ることで、不十分な実装を持ち込んでしまう。

- 「このままじゃ失敗する」という直感を無視する
    - 「このままじゃ失敗する」という直感は多くの場合妥当です。
    - 必ず対策をとりましょう。

## 成功したプロジェクトの特徴
- なにが達成したら成功であるのかがはっきりさせてある。
    - すること・しないことの区別ができている。
    - することの範囲でも、優先順序が設定されている。
    - MUST(必須)とshould better（あったらのぞましい）の区別
- 開発期間の中で可能になることと、可能にならないこととの区別がついている。
    - 技術動向を理解しており、開発期間内に利用可能なこととそうでないことの区別がついている。
    - そのため同一の開発目標の設定でも、「３年前には無理だった」が十分に起こる。
- 成果物がどのように使われるのかを明確に理解できている。
    - 成果物を利用する側の利用シーンをスケッチできている。
    - そのため、その利用シーンで満たされる必要がある条件について明示できる。 
- 関係者が動機づけられている。
- 力関係で支配しようとしない。
    - 自分の実現できないことを実現できる人に対する敬意を失わない。
- 信頼関係と論理的な説明によって協力を引き出す。
- そのために必要なことを分析してあり、それぞれの作業の依存関係は、知るべき人が知っている状況にある。
- どのようにしたら、プロジェクトが失敗してしまうのかを、担当者が知っている。
- 担当者が抱えている課題をチームの課題としてチームとして解決できる。
- 間違えた判断に対して誠実に向き合う。
    - 例：間違えた判断をして担当者への作業を増やしてしまったとき、非を認められる。


## 注意
上記は、すべて個人的な経験の範囲で気づいたことです。たくさんのことが抜け落ちています。
TypeScript: ヘッダーを考慮した csv ファイルの読み込み

こちらのプログラムを[リートン](https://wrtn.jp/)で変換しました。
[Python3: ヘッダーを考慮した csv ファイルの読み込み](https://qiita.com/ekzemplaro/items/aabc6e3b9ac71e242d06)

## 準備

```bash
npm i --save-dev @types/node
npm install --save csv-parse
npm install --save json
```

## プログラム

```ts:csv_header.ts
#! /usr/bin/env node

import * as fs from 'fs';
import * as csv from 'csv-parse/sync';
import * as json from 'json';

function fileWriteProc(fileName: string, strOut: string): void {
  fs.writeFileSync(fileName, strOut);
}

const [, , fileCsv, fileJson] = process.argv;

const csvData = fs.readFileSync(fileCsv, 'utf8');
const rows = csv.parse(csvData, { columns: true, skip_empty_lines: true });
const outStr = JSON.stringify(rows);

fileWriteProc(fileJson, outStr);
```

## Node.js に変換

```bash
tsc csv_header.ts
chmod +x csv_header.js
```

## 実行

```bash
./csv_header.js cities_header.csv cities.json
./csv_header.js cities_ex02.csv cities_ex02.json
```
順伝播を用いたKANによるニューラルネットワークのフレームワーク

import numpy as np
from typing import List, Callable

class KATFunction:
    def __init__(self, func: Callable[[float], float]):
        self.func = func

    def __call__(self, x: float) -> float:
        return self.func(x)

class KATLayer:
    def __init__(self, input_dim: int, output_dim: int):
        self.input_dim = input_dim
        self.output_dim = output_dim
        self.weights = np.random.randn(input_dim, output_dim)
        self.biases = np.random.randn(output_dim)
        self.kat_functions = [KATFunction(np.sin) for _ in range(output_dim)]  # 例としてsinを使用

    def forward(self, inputs: np.ndarray) -> np.ndarray:
        linear_output = np.dot(inputs, self.weights) + self.biases
        return np.array([kat_func(x) for kat_func, x in zip(self.kat_functions, linear_output)])

class KATNeuralNetwork:
    def __init__(self, layer_dims: List[int]):
        self.layers = [KATLayer(layer_dims[i], layer_dims[i+1]) for i in range(len(layer_dims)-1)]

    def forward(self, inputs: np.ndarray) -> np.ndarray:
        for layer in self.layers:
            inputs = layer.forward(inputs)
        return inputs

    def train(self, X: np.ndarray, y: np.ndarray, epochs: int, learning_rate: float):
        for epoch in range(epochs):
            for x, target in zip(X, y):
                # Forward pass
                output = self.forward(x)
                
                # Backward pass (簡略化された例)
                error = output - target
                for layer in reversed(self.layers):
                    # ここで実際のバックプロパゲーションを実装する
                    # KAT関数の導関数を考慮する必要がある
                    pass

    def predict(self, X: np.ndarray) -> np.ndarray:
        return np.array([self.forward(x) for x in X])

# 使用例
nn = KATNeuralNetwork([2, 5, 3, 1])
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])

nn.train(X, y, epochs=1000, learning_rate=0.01)
predictions = nn.predict(X)
print(predictions)
この実装には以下の特徴があります：

KATFunction: 個々のKAT関数を表現するクラスです。現在は単純な例としてsin関数を使用していますが、より複雑な関数や学習可能なパラメータを持つ関数に拡張できます。
KATLayer: KAT関数を用いた層を表現します。従来の線形変換に加えて、KAT関数による非線形変換を適用します。
KATNeuralNetwork: 全体のネットワーク構造を管理します。順伝播、学習、予測の機能を提供します。
学習プロセス: 現在の実装では簡略化されていますが、実際にはKAT関数の導関数を考慮したバックプロパゲーションアルゴリズムを実装する必要があります。

この基本的なフレームワークを拡張するためのいくつかの改善点：

より複雑なKAT関数の実装: 学習可能なパラメータを持つKAT関数を導入する。
効率的なバックプロパゲーション: KAT関数の導関数を正確に計算し、効率的な学習アルゴリズムを実装する。
正規化技術の導入: KAT層に適した正規化手法を開発する。
最適化アルゴリズムの改善: KAT関数の特性に適した最適化アルゴリズムを実装する。
GPU対応: NumPyの代わりにCUDAを使用して、GPU上での並列計算を可能にする。
モデルの解釈可能性: KAT関数の特性を利用して、モデルの決定プロセスをより解釈しやすくする方法を開発する。

このフレームワークは、KATの理論的基盤を活用して、より効率的で解釈可能なニューラルネットワークモデルを構築することを目指しています。ただし、実際の性能向上や解釈可能性の改善には、さらなる理論的研究と実験的検証が必要です。
[Python] [python-pptx] Powerpointのノートをエクセルに出力し、変更して、戻す

PPTをプレゼンするときに、自分の手元で表示できるノートですが、英語の文章を日本語に変えることになりました。しかし、１枚づつ変更するのはけっこう面倒です。

そこで、一旦エクセルに書き出して、Google翻訳したものを、また戻すというコードを書いてみたら、思ったよりうまくいったので、備忘録を兼ねて記事にします。

なお、私はJupyter Notebookでこの作業を行っていますので、他の環境の方は工夫してみてください。

まず、読み込みたいパワーポイントファイルは、同じディレクトリに入れておきます。今回は記事用にダミーのサンプルファイルを作りました。それをページごとに読み込んで、PandasのDataFrameに１ページごと取り込んで、同じディレクトリにEXCELで出力します。

イメージはこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/823476/6d437245-85fa-40b1-df67-b5e56be95d43.png)

コードはこちら

```python
import os
import pandas as pd

in_pptx= 'サンプルPPTノート.pptx'

prs = pptx.Presentation(in_pptx)
pptx_name = os.path.basename(in_pptx)

df=pd.DataFrame()

for i, sld in enumerate(prs.slides):
    note=sld.notes_slide.notes_text_frame.text
    df=pd.concat([df, pd.DataFrame([[i, note]])])

excel_writer = pd.ExcelWriter('SlideNotes.xlsx')
df.columns=['page', 'note']
df.to_excel(excel_writer, 'original_notes', index=False)

excel_writer.close()
print ('fnished!')
```

このエクセルを自動翻訳などで・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/823476/70979535-c487-b78a-a1b5-4afc634579b5.png)

このように、書き換えたいシートを作ります。今回は、translatedというシート名にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/823476/afc0c115-3a0b-4531-497e-3cd571603388.png)

もちろん、自分で翻訳されてもいいし、自動翻訳を修正してもいいかと思います。

その後、今度はPPTのノートを書き換えます。
ここで、元のPPTファイルを書き換えるようにしてしまいましたが、名前を変えるように、コードを変更されてもいいと思います。

```python

import pptx
import pandas as pd

df=pd.read_excel('SlideNotes.xlsx', sheet_name='translated')

in_pptx= 'サンプルPPTノート.pptx'
prs = pptx.Presentation(in_pptx)

for i, sld in enumerate(prs.slides):

    if type (df.iloc[i, 0]) != int: #空の場合はエラーとなるので、処理を飛ばす
        prs.slides[i].notes_slide.notes_text_frame.text=df.iloc[i, 1]

prs.save(in_pptx)

print ('finished!')
```

そうすると、このようにPPTXのノートが書き換えられています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/823476/d4974b46-2b2f-4eef-57ef-cefcabb9b1dc.png)


このパワーポイントのノートはそこまで使わないかもしれませんが、この方式はタイトルや本文のテキストの抽出にも応用できるかと思いますので、ぜひトライしてみていただければと思います！
uuid生成からルーティングでuuidをidとして使用するまでの方法を解説

今回は実際のシステム開発の現場でuuidを使ったのでこれについてまとめました。

## uuidとは？
uuid（Universally Unique Identifier）は、128ビットの一意の識別子として用いられます。

わかりやすくいうと、uuidは8-4-4-4-12の形式で表される32文字の16進数と4つのハイフンから構成されるため、1兆個のuuidを生成しても重複する確率は低いです。

そのため、大規模なシステムや分散システムでも、重複しない識別子として利用できます。主にデータベースやネットワーク上で一意の識別子として使用されます。

またuuidは16バイトのバイナリ形式で保存するため、文字列形式の36バイトに比べて大幅にストレージを節約できます。合わせてインデックスが小さくなり、検索が高速化されます。

## uuidの設定

#### ・ステップ１
まず、userモデルを作成し、「t.binary :uuid, limit: 16」というカラムを設定し、「add_index :users, :uuid, unique: true」という設定を加えます。
```
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.binary "uuid", limit: 16, null: false # 16バイトのバイナリ形式でUUIDを保存

      t.string :name
      t.string :email

      t.timestamps
    end

    add_index :users, :uuid, unique: true
  end
end
```
その後、rails　db：migrateを行います。
ここでuuidをバイナリ形式で保存することで、インデックスのサイズが小さくなり、検索処理が高速になります。

インデックスのサイズが小さくなると、データベースがインデックスをメモリに保持できる可能性が高くなり、結果として検索クエリのパフォーマンスが向上します。また、バイナリ形式の比較は文字列形式よりも効率的に行えるため、検索処理自体も軽くなります。

#### ・ステップ２

dbにデータを登録する際に、uuidを作成するモジュールとして設定をします。
```
module UuidGeneratable
  extend ActiveSupport::Concern

  included do
    before_create :generate_unique_uuid

    def generate_unique_uuid
      loop do
        self.uuid = self.class.binary_uuid( SecureRandom.uuid )
        break unless self.class.exists?( uuid: self.uuid )
      end
    end

    def self.binary_uuid( uuid_string )
      [uuid_string.delete( '-' )].pack( 'H*' )
    end

    def uuid_string
      self.class.string_uuid( uuid )
    end

    def self.string_uuid( binary_uuid )
      binary_uuid.unpack1( 'H*' ).scan( /.{8}|.{4}|.{4}|.{4}|.{12}/ ).join( '-' )
    end

    def self.find_by_uuid( uuid )
      params_uuid = [uuid.delete('-')].pack('H*')
      self.find_by( uuid: params_uuid ) 
    end
  end
end
```
※「loop do」の処理はなくてもいいかもしれません。

#### ・ステップ３
modelファイルにモジュールをincludeする
```
class User < ApplicationRecord
  include UuidGeneratable
end
```

## ルーティングでUUIDをIDとして使用する手順
先ほどの処理でuuidは登録できるようになりました。
今度はuuidをurlに含めて使用できるように設定をします。

#### ・ステップ１
ルーティングを修正

```
  namespace :clients do
    root "dashboards#index"

    resources :companies, only: %i[ show ], param: :uuid # ここにURLでuuidをidにするよう設定
  end
```

#### ・ステップ２
viewファイルにあるパスでidを渡していたところにuuidを設定
またここではdbから取得したインスタンスのuuidを直接使用するはできません。

理由としては、データベースから取得したUUIDデータはバイナリ形式で保存されており、そのままでは使用できません。そこで、uuid_string メソッドを使用してバイナリデータを文字列形式に変換し、読みやすい形で利用できるようにします。

そのためパスに渡す引数でメソッドを設定することでバイナリデータを文字列形式に変換します。
```
= link_to clients_company_path( @company.uuid_string ) 
```

これにより適切にルーティングでuuidをidとして使用できるようになります。
これだけ抑えておけばOK！Xcodeショートカット集

# はじめに
Android側とiOS側の開発を行っていると、IDE（開発環境）のショートカットキーが異なるので脳がバグる時がある。

まずは、Xcodeの最低限抑えておくべきショートカット集を記載していく。
※Android Studioのショートカット集は別の記事にまとめる予定

# ショートカット集
## 編集系
・超基本
| ショートカットキー | 意味 |
|:-:|:-:|
| Cmd＋S   | 保存  |
| Cmd＋X   | カット  |
| Cmd＋C   | コピー  |
| Cmd＋V   | ペースト  |

・知っておくと便利
| ショートカットキー | 意味 |
|:-:|:-:|
| Cmd＋/   | 選択行のコメントアウト  |
| Docコメントをつけたいメソッドに移動し、Cmd + Opt + /  |　Docコメントの雛形生成  |
| Cmd + Z   | アンドゥ(元に戻す)  |
| Cmd＋Shift＋Z   | リドゥ(アンドゥの逆)  |
| Ctrl ＋ i  | 選択行のインデント整理  |

## 移動系
| ショートカットキー | 意味 |
|:-:|:-:|
| Cmd + Click   | 定義元へ移動  |
| Opt + Click   | 現在表示しているファイルから移動せずに定義元のリファレンスを表示してくれる  |
| Cmd + Shift + J   | 現在表示しているファイルを表示（ナビゲータエリアに移動）  |
| Cmd + Ctrl + ←   | ジャンプ前のファイルに移動  |
| Cmd + Ctrl + →| ジャンプしたことのある次のファイルに移動  |

※"Opt + Click"は以下のように表示される。
　コードを追っているときによく使うことになる
![スクリーンショット 2024-06-23 15.18.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/84e52ef5-121d-ecb0-0aaf-aa8e116f1bbb.png)



## ビルド系
| ショートカットキー | 意味 |
|:-:|:-:|
| Cmd + Shift + K   | クリーン  |
| Cmd + B   | ビルド  |
| Cmd + R   | 実行 |
| Cmd + .   | 停止  |

## 検索系
| ショートカットキー | 意味 |
|:-:|:-:|
| Cmd + F   | ファイル内検索  |
| Cmd + G   | ファイル内検索の次にフォーカスを移動  |
| Cmd + Shift + G   | ファイル内検索の前にフォーカスを移動 |
| Cmd + Shift + O (ZEROではなくアルファベットのオー)   | プロジェクト内のファイル検索（Android StudioでいうShift x 2と同じ）  |

# Tips：ワークスペースの名称
とりあえず５つの名称を覚えておけば良し！
・ツールバーエリア
・ナビゲーターエリア
・エディターエリア
・ユーティリティーエリア
・デバッグエリア

![スクリーンショット 2024-06-23 14.44.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/fe409747-73a1-150e-c367-fc2b23bc19e1.png)

# 参考資料
　https://heppokose.hatenablog.com/entry/20111129/1322530351
　https://zenn.dev/rockname/articles/77a2699b0123d5
　https://qiita.com/yutosa3/items/88e3ebedb74c02e324b2
2024年6月23日: Virtuoso、orient 変換を回転とX/Y両反転で表現

# 2024年6月23日: Virtuoso、アフィン変換を対称性のある表現で

Virtuoso の orient 変換は8つある。

* $\verb|R0|$
* $\verb|R90|$
* $\verb|R180|$
* $\verb|R270|$
* $\verb|MX|$
* $\verb|MXR90|$
* $\verb|MY|$
* $\verb|MYR90|$

このうち後半は座標軸に対しての反転の形をとっているが、座標軸に依らない完全反転 $\verb|F|$ と回転による表現を（わけあって）考えてみた。

$$\verb|F|=\left(\begin{array}\newline0&1\newline{}1&0\end{array}\right)$$

以下の通り。

<table>
<tr><th>Virutoso 表現<th>$\verb|F|$ と回転による表現
<tr><td>$\verb|MXR90|$<td>$=\verb|R0|\bullet\verb|F|$
<tr><td>$\verb|MY|$<td>$=\verb|R90|\bullet\verb|F|$
<tr><td>$\verb|MYR90|$<td>$=\verb|R180|\bullet\verb|F|$
<tr><td>$\verb|MX|$<td>$=\verb|R270|\bullet\verb|F|$
</table>
GithubにSSH Keyを設定する

# はじめに
Githubのリモートリポジトリからpushやpullなどをするためには、ユーザー名とアクセストークンを毎回入力するめんどくさい過程が必要です。
そのため、今回はSSH Keyを活用して、この過程を省略する方法を整理しようと思います。

# SSH (Secure Shell)
ネットワークに接続された機器を遠隔操作・管理するとき、セキュリティを維持するために使用する暗号化されたリモート接続プロトコルです。
SSH Keyは、秘密鍵と公開鍵をペアとして使います。

# SSH Keyを生成
LinuxやmacOSはターミナル、WindowsにGit bashやPowerShellなどで、以下のコマンドを実行し、キーファイルを生成します。
```console
$ ssh-keygen
```
:::note warn
コマンドを実行する前に、すでにキーが存在しないか確認してください。
:::
コマンドを実行すると、以下のように2つのファイルが生成されます。
```console
$ ls ~/.ssh/
id_rsa  id_rsa.pub
```
- `id_◯◯◯`は秘密鍵です。(例 : id_rsa、id_ed25519)

:::note alert
秘密鍵は、他人が見られないように注意する必要があります。
:::

- `id_◯◯◯.pub`は公開鍵です。(例 : id_rsa.pub、id_ed25519.pub)

:::note info
公開鍵は、GithubのSSH Key設定に使用します。
:::

# GithubにSSH Keyを設定
Githubにログインした後、右上のプロフィールアイコンをクリックするとメニューが表示されます。
メニューの中で「Settings」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/27078f39-e7fe-3ce0-b2ab-a3a4516dd063.png)

Settingsの画面が表示されたら、左のメニューで「SSH and GPG Keys」を探してクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/968e4be3-1298-ce7a-34e1-2928000d4bb8.png)

新たなSSH Keyを生成するため、「New SSH Key」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/1661a4a6-baec-5132-2052-bb512f529945.png)

「Title」は適切に入力、「Key」は`id_rsa.pub`（公開鍵）ファイルの内容をコピーして入れます。
その後、「Add SSH Key」ボタンをクリックして設定を完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/7bc1febc-52ee-d290-e215-48f4aebfd637.png)

# SSH接続を確認
以下のGithubのドキュメントに接続確認方法が作成されています。

https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection

接続確認方法を整理すると
まず、ターミナルで、以下のコマンドを入力して実行します。
```console
$ ssh -T git@github.com
```
以下のようなメッセージが表示される場合
```console
The authenticity of host 'github.com (IPアドレス)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```
表示されるメッセージのフィンガープリントが、GitHub の公開キー フィンガープリントと一致することを確認します。 

https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints

問題なければ、「yes」と入力します。
最後に以下のようなメッセージが出力されたら完了です。
```
Hi {ユーザー名}! You've successfully authenticated, but GitHub does not provide shell access.
```

# その他
SSHでリポジトリをクローンすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/a7ad5004-9e41-a801-2f4a-a706b01182f0.png)


# 参考
https://docs.github.com/ja/authentication/connecting-to-github-with-ssh
Excel VBA 自分が書いてきたクソコードのサンプル

# ITとかプログラミングとかの前提知識が全くない非エンジニアが殴り書きしてきたコード

Excelのことを何も知らないまま就職して、周りに詳しい先輩もいない中、日付が変わる前に退勤して過労死ラインを超えないためにずっと独学でやってきた、VBAのMyクソコードを紹介します。

## With や For Next を絶対に使わず気合と根性で何行も書く脳筋系

```vb
    Range("A1") = 別シート.Range("A1")
    Range("A2") = 別シート.Range("A2")
    Range("A3") = 別シート.Range("A3")
    Range("A4") = 別シート.Range("A4")

'こんな感じで何十行も頑張る
```

## 変数や関数の名前がカオス
これやってたときは自分以外にコードを読む人がいなかったため、やりたい放題
可読性とか知りません

```vb
    Dim wanwan as Long
    wanwan = Cells(Rows.Count, 1).End(xlUp).Row

'変数が飼ってる犬の名前
```

## インデントなし、すべての行を左詰めで書く

```vb
Sub Macro()
Dim i as Long
For i = 1 to 100
If Worksheets("Sheet1").Cells(i, 4) = True then
Worksheets("Sheet2").Range("B2") = Worksheets("Sheet1").Cells(i, 3)
Worksheets("Sheet2").PrintOut
End If
Next i
End Sub

'オブジェクト変数とか知らない
```
とにかく動かすことに必死でした。
今思えば、めちゃくちゃな書き方をしていた時が一番楽しかった気がします。
PUTとPATCHと冪等性


REST APIの設計に置いて更新系のリクエストはHTTPのPUTとPATCHが担う事になっている。

それらの違いが気になったので少し調べた

## 結論

PUTとPATCHの違いは冪等性にある。

PUTはリソースの完全な置き換えを行うため、同じリクエストを何度行っても同じ結果が返ってくる。

一方でPATCHはリソースの部分的な更新を行うため、同じリクエストを何度行っても同じ結果が返ってくるとは限らない。

## PUT

PUTはリソースの完全な置き換えを行うため、リクエストボディにはリソースの完全な情報を含める必要がある。

同じリクエストを何度実行しても、サーバー上のリソースの状態は最初の実行後と変わりません。（つまり冪等性を持つ）

またPUTはリソースが存在しない場合は新規作成を行う。

## PATCH

PATCHはリソースの部分的な更新を行うため、リクエストボディには更新したいリソースの一部の情報だけを含める。

同じリクエストを何度実行しても、サーバー上のリソースの状態は最初の実行後と異なる可能性があります。（つまり冪等性を持たない）

そのためPATCHはPUTと異なり、リソースの完全な情報を含める必要がないため、リクエストボディのサイズが小さくなる場合があります。


## まとめ

サービスの動きによって使い分けるのであれば

- PUT: オブジェクトストレージなどのリソースの完全な置き換えを行う場合
- PATCH: データベースなどのリソースの部分的な更新を行う場合

が適切かと思われる。

（がPUTを使ってよいのでは）
DDDでポケモンバトルを実装する(Step4：ポケモンのバトルのテストを実装する)

## はじめに
前回までの記事の続きです。今回はポケモンバトルのテストコードを実装していきます。

https://qiita.com/koji0705/items/80b59feda4afa60e0628

## 成果物

https://github.com/kouji0705/pokemon_ddd/pull/4

```ts:src/services/Battle.test.ts
import { Pokemon } from "@entities/Pokemon";
import { PokemonType } from "@enums/PokemonType";
import { Stats } from "@entities/Stats";
import { Move } from "@entities/Move";
import { Battle } from "@services/Battle";

describe("Battle", () => {
	let pikachu: Pokemon;
	let bulbasaur: Pokemon;
	let battle: Battle;

	beforeEach(() => {
		const pikachuStats: Stats = { hp: 100, attack: 55, defense: 40, speed: 90 };
		const bulbasaurStats: Stats = {
			hp: 100,
			attack: 49,
			defense: 49,
			speed: 45,
		};

		const thunderbolt: Move = {
			name: "Thunderbolt",
			type: PokemonType.Electric,
			power: 90,
		};
		const tackle: Move = {
			name: "Tackle",
			type: PokemonType.Normal,
			power: 40,
		};

		pikachu = new Pokemon(25, "Pikachu", [PokemonType.Electric], pikachuStats, [
			thunderbolt,
		]);
		bulbasaur = new Pokemon(
			1,
			"Bulbasaur",
			[PokemonType.Grass, PokemonType.Poison],
			bulbasaurStats,
			[tackle],
		);

		battle = new Battle(pikachu, bulbasaur);
	});

	test("バトルを1回実行", () => {
		battle.battleTurn();
		expect(bulbasaur.getStats().hp).toBeLessThanOrEqual(10); // Bulbasaur takes 90 damage
		expect(pikachu.getStats().hp).toBe(60); // Pikachu takes 40 damage
	});

	test("バトルを2回実行し、ピカチュウが勝利", () => {
		battle.battleTurn(); // First turn
		battle.battleTurn(); // Second turn
		expect(pikachu.getStats().hp).toBe(60); // Pikachu takes 40 damage
		expect(bulbasaur.getStats().hp).toBeLessThanOrEqual(0); // Bulbasaur is defeated
	});
});

```

:::note info
beforeEachでテストの準備をしています。ここでは対戦する2匹のポケモンを準備しています。
:::
GeometryNodesで平面シェイプを立体化する

平面の輪郭を描いたものを 3Dの立体にする処理は多くの人が望む手法です
Blenderのジオメトリノードでの方法を検証したので書き留めておきます

[BlenderConference 2023](https://conference.blender.org/2023/)の公演内の内容と  [Teddyアルゴリズム](https://www-ui.is.s.u-tokyo.ac.jp/~takeo/research/teddy/teddy.htm)の考えを元にしています

今回のものはBlender 3.3で作成しました
4.1でも同じ挙動なのを確認しましたが。もっと楽な方法があるかもしれません

## メッシュの三角分割
まずはBlenderConferenceで見かけた メッシュを細かい三角で分割する手法です
キャプチャの選択表示されている多角形ポリゴンのジオメトリを用意した状態からスタートします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/1cbea413-ae12-7477-679e-7cabe5b96f82.png)
「**カーブフィル**」のノードではカーブのシェイプ同士を最短で結んだ上で平面として塗りつぶす機能があるようです。
入力メッシュのアウトラインをカーブ化して
それとは別に「**面にポイント配置**」で適度な距離を保った座標を生成してカーブのスプラインを配置しています
ポイントにインスタンスで配置した状態だと実体をスプラインとしての実体を持たないので実体化を忘れずに。

::: note
今回の入力ジオメトリはNゴン状態でしたが　
外周にあたる部分をカーブに変換して　スプラインを平面上に配置さえできれば他にも色々手段はあります
:::  
  
::: note
カーブラインをインスタンス配置すると同位置２頂点になるのですが
フィル実行時に１頂点の扱いになるようです
:::


## 平面の立体化１
三角で充填した後に　元のメッシュの外周からの距離に応じて応じて移動させれば膨らませることが可能です。
![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/da7bf68d-aff7-187e-0498-60299edb7b69.png)
キャプチャでは 多角ポリゴン状態だったので
**ジオメトリ削除**で面だけを削除すると外周の辺が残り
**ジオメトリ近接**で　各頂点の辺からの距離が取得できます
単純に距離でを元に移動すると斜面は真直ぐになるので 
**Floatカーブ等**で曲面にしてもいいかもしれません
![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/f45cca1f-05f0-2ef8-66ae-eb532d6e64dc.png)


## 平面の立体化2
もう少しだけ高度な処理を試したいと思います
冒頭で少し触れたTeddyアルゴルズムでは

- 手描きストロークで囲まれた領域を三角分割
- 内部の辺を2分割した中点を立体の軸と仮定する
- 直交する平面上に中点と外周との距離を元に新しい頂点を作成して円筒状の立体を作る

![image-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/523a2960-9077-8559-c019-42ced0829591.png)

といった挙動のようですが、
膨らませる移動量の計算に 内部の辺の長さを利用する点を参考にしたいと思います

今回追加した主要な処理部分です
![image-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/f79c6668-e279-ca70-8b5a-b4374ae7f0af.png)
元のジオメトリを三角面化した後に
辺に接する面の数が１つしかない辺（=アウトライン）を削除することで内部に新しく作られた辺だけを抽出しています

「**属性転送**」を使って内部を三角分割する個々のポイントのから最も近い内部辺の長さを取得して
その長さを直径とします（利用したいのは半径なので0.5倍）
これを立体化するとこんな感じです

![24062301.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/e500798f-cece-10e1-48ed-1309de789a58.gif)

Teddyよりも簡易な部分での不具合がありますが　使える形になっているのではないでしょうか

::: note
Blender3.6以降で同じ動作をさせる場合には
属性転送のノードの部分は　最近接サンプルとインデックスサンプルの組み合わせになるようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/a1880061-3763-29ff-ce98-90a973c7da7e.png)

:::

## ノード全体
今回のノードの全体はこんな感じです

![image-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/11e48e76-a64a-5424-eb93-2842ae9d8fb7.png)

カーブフィルのおかげでシンプルな構成ですね
英語表示のキャプチャも置いておきます

![image-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/5a9ff28e-142b-566b-6734-205ca4892cd2.png)

まだまだ改良点はあるかと思います
何かの参考になれば幸いです
初サイト制作メモ6:  useStateとuseMemoを使ってフィルタ機能を実装

ラーメンのレビューを、条件で絞り込みたい。
![スクリーンショット 2024-06-23 14.26.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366676/c459a821-fcf0-0c3e-539c-700cbbf080e2.png)

useStateとuseMemoを使って実現した。

 - useState
     - フィルタ条件となる、店名、メニュー、評価の変数を管理する
     - 入力欄の内容が変わった時、それを検知して値を更新・保持するように実装する
 - useMemo
     - useStateで管理している値に変更があった時「のみ」、フィルタを再計算する。余計な計算が走らなくて済む
         - 再計算のトリガーとする値は、useMemoの記述の末尾に、[]内で指定

```index.tsx
const [nameFilter, setNameFilter] = useState("");
const [menuFilter, setMenuFilter] = useState("");
const [repeatFilter, setRepeatFilter] = useState<RepeatPreference | "">("");
const [modalIsOpen, setModalIsOpen] = useState(false);
const [selectedImage, setSelectedImage] = useState<string | null>(null);

const filteredRamen = useMemo(
() =>
  ramenList.filter((ramen) => {
    const matchesName = ramen.name
      .toLowerCase()
      .includes(nameFilter.toLowerCase());
    const matchesMenu = ramen.menu
      .toLowerCase()
      .includes(menuFilter.toLowerCase());
    const matchesRepeat = repeatFilter
      ? ramen.repeat === repeatFilter
      : true;
    return matchesName && matchesMenu && matchesRepeat;
  }),
[ramenList, nameFilter, menuFilter, repeatFilter]
);
```

フィルタ条件を入力するテキストボックス例は以下。
```index.tsx
<input
  type="text"
  value={nameFilter}
  onChange={(e) => setNameFilter(e.target.value)}
  className="block w-full p-1 border rounded shadow-sm focus:ring-2 focus:ring-blue-500"
  placeholder="店名"
/>
```


フィルタ条件に入力すると、リアルタイムにフィルタしてくれるようになった！![スクリーンショット 2024-06-23 14.34.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366676/6a8e3875-86f4-9f16-b046-5d790d5a39da.png)
ダークモードの実装方法

必要な部分のみ書いています。

```html:index.html
<head>
  <link rel="stylesheet" type="text/css" id="dark-mode-link" href="./css/dark-mode.css">
</head>

<body>
  <p>ダークモード！</p>

  <script>
    const darkModetoggleSwitch = document.querySelector("#darkModetoggleSwitch")
    const darkModeLink = document.querySelector('#dark-mode-link');

    darkModetoggleSwitch.addEventListener('click', toggleDarkMode);

    function toggleDarkMode() {
      if (darkModeLink.href.includes('dark-mode.css')) {
        darkModeLink.href = '';
      } else {
        darkModeLink.href = 'dark-mode.css';
      }
    }
  </script>
</body>
```

```css:dark-mode.css
body {
  background-color: #121212;
  color: #ffffff;
}
```
手動で切り替える方法。ボタンでの切り替え実装。参考サイトではローカルに保存して、最初の読み込み時に分けていたりしてます。


```css
@media (prefers-color-scheme: dark) {
  body {
    background-color: #121212;
    color: #ffffff;
  }
 }
```
OSの設定で切り替える方法です。mac、windows、ios、androidどれでもいけると思います。

#### 参考

https://qrz.co.jp/blog/dark_mode_webdesign/

https://seeds-create.co.jp/column/dark-mode/

https://qrz.co.jp/blog/dark_mode_webdesign/
【初心者向け】キーボード操作のみで使えるslackのショートカットキー

こんにちは！
1年目の小川です。

今回は、slackを使う上でよく使うショートカットキーをまとめていきたいと思います。
皆さんもぜひ使ってみてください!

# 使用環境
+ Mac

# こんな人に読んでほしい！
* slackを使い始めたばかりの方
* slackを使いこなせていない方

# slackのショートカットキー
それでは早速、よく使うショートカットキーをまとめていきたいと思います！

## 基本編
| コマンド | 操作内容  | 
| ---------- | ----------- |
| command+1 | ホームに移動 |
| command*2 | DM一覧に移動 |
| command+J | 最後の未読メッセージに移動 |
| ↑↓ボタン | メッセージの確認 |
| →ボタン | スレッドを開く |

## 入力編
| コマンド | 操作内容 |
| ---------- | ---------- |
| command+enter | メッセージを送信 |
| shift+option+command+C | コードブロックの挿入 |
| shift+command+C | 短いコードの挿入 |
| shift+command+8 | 箇条書きリストの挿入 |
| shift+command+9 | 引用する |

## リアクション
以下はリアクションしたいメッセージにいる状態で操作します。
| コマンド | 操作内容 |
| ---------- | ---------- |
| R | リアクション一覧を表示 |
| ↓ボタン | リアクション一覧から選択 |

# 最後に
今回はslackのショートカットキーについてまとめてきました。
今回は私自身が日常的によく使うショートカットキーを中心にまとめたので、今回ここに出てきていないショートカットキーも多く存在します。
もし興味がある方は以下の参考サイトをご覧ください！
ここまで読んでいただきありがとうございました！

# 参考サイト
https://slack.com/intl/ja-jp/help/articles/201374536-Slack-%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88
検索したいもののリストを逐次開くスクリプト（js）

注意
動作環境を確認したのはChromeのみです
あまりに数が多いと逐次実行の処理をしているため鬱陶しいかも

やりかた
①開発ツールのConsole開く
②allow pastingを入力して押下
③以下サンプルコードを参考にリストを変更して、入力して押下
※
行頭に'
行末に',
を入れる置換をすると一気に編集できますよ
サンプルコード
```
// 楽曲のリスト
const songs = [
    'ヴィヴァルディ - 四季 - ヴァイオリン協奏曲 ホ長調 春 Op. 8 No. 1 RV 269：I. アレグロ',
    'バッハ - チェロ組曲 第1番 ト長調 BWV 1007：I. プレリュード',
    'モーツァルト - G長調の弦楽のためのセレナーデ 第13番 – アイネ・クライネ・ナハトムジーク',
    'ベートーヴェン - 交響曲 第5番 ハ短調 Op. 67：I. アレグロ・コン・ブリオ',
    'チャイコフスキー - 白鳥の湖 Op. 20、第IV幕：No. 29、フィナーレ',
    'ブラームス - ハンガリー舞曲 第5番',
    'リスト - 愛の夢',
    'プッチーニ - 誰も寝てはならぬ / Nessun dorma',
    'ビゼー - オペラ カルメンより ハバネラ',
    'ドビュッシー - 月の光',
    'ラヴェル - 弦楽四重奏曲 ヘ長調 - 第2楽章: 十分に生き生きと - 非常にリズミカルに',
    'ラフマニノフ - ヴォカリーズ'
];

// 各楽曲を順次検索する関数
function openTabs(songs, index = 0) {
    if (index < songs.length) {
        const url = `https://www.google.com/search?q=${encodeURIComponent(songs[index])}`;
        const newWindow = window.open(url, '_blank');
        newWindow.onload = () => {
            openTabs(songs, index + 1);
        };
    }
}

// 最初のタブを開く
openTabs(songs);
```