OmniAICreator/Qiita-1.07M huggingface dataset:
自動Linterでルールに合わないソースをコミットさせない！

# 導入
よくプロジェクトで、結構開発中にLinterを実行せずにGitにプッシュされ、実はソースコードのインデントやルールがめちゃくちゃに...という経験のある方に必見です。

今回は、Next.jsのプロジェクトで`tsx`および`ts`ファイルを対象に、Gitコミット時にLinterを自動実行し、ルールに合致しない場合にコミットを防ぐ設定方法を紹介します。
使用するツールは、`husky`と`lint-staged`、および`ESLint`の3点です。

# 手順

## 前提

- **Node.js**と**npm**がインストールされていること
- **Git**がインストールされており、プロジェクトがGitで初期化されていること

## 1. `husky`と`lint-staged`のインストール

ターミナルを開き、以下のコマンドを実行して`husky`と`lint-staged`をインストールします。
これらはコードの品質を保つためにGitフックを使ってコミット時に自動でコードチェックやフォーマットを行うためのツールです。

<details><summary><font color="red">huskyについて</font></summary>

Gitフックを簡単に管理・設定できるツールです。
Gitフックには以下の種類があります。
- pre-commit: コミット前に実行
- pre-push: プッシュ前に実行
- commit-msg: コミットメッセージの検証

</details>
<details><summary><font color="red">lint-stagedについて</font></summary>

Gitのステージングエリアに追加されたファイルに対してのみLintやフォーマットを実行するツールです。
全体のファイルではなく、変更されたファイルのみに対して処理を行うため、効率的です。

</details>

これらのインストールは以下のコマンドで実行します。

```bash
npm install --save-dev husky lint-staged
```

## 2. `husky`の初期設定

以下のコマンドで`husky`のGitフックをセットアップします。

```bash
npx husky install
```

次に、Gitのコミット前に`lint-staged`を実行するように設定します。

```bash
npx husky add .husky/pre-commit "npx lint-staged"
```

`.husky/pre-commit`ファイルに以下の内容が追加されます。

```bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
```

## 3. `package.json`に`lint-staged`の設定を追加

`package.json`ファイルに以下の`lint-staged`の設定を追加します。
`tsx`および`ts`ファイルに対して`eslint`を実行する設定です。

```json:package.json
{
  "lint-staged": {
    "*.{ts,tsx}": [
      "eslint --fix"
    ]
  }
}
```

## 4. ESLintのインストールと設定

ESLintがインストールされていない場合は、以下のコマンドでインストールします。

```bash
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react
```

次に、以下のコマンドでESLintの初期設定を行います。

```bash
npx eslint --init
```

ESLintの設定を行い、`.eslintrc.json`ファイルを生成しておきます。

## 5. 動作確認

わざとLinterルールに合致しないソースコードを作成し、通常通り、Gitコミットを発行してみましょう。
Linterルールに違反している場合、エラーメッセージが表示され、コミットがブロックされます。

# 最後に

この手順に従えば、Next.jsプロジェクトで`tsx`および`ts`ファイルに対して、コミット時にLinterが自動的に実行され、ルールに合致しない場合にコミットをブロックすることができます。
これにより、コード品質を維持しやすくなります。
ぜひ試してみてください。
Salesforce数式項目でユーザレコードの部署を表示させる方法

今回はTodoレコードの作成者、Todoレコードの割り当て先の部署を表示する数式をそれぞれ作成します


## Todo作成者の部署を表示させる方法

数式は下記となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/b1120099-cd7b-16f9-a2a9-f05f30d2b182.png)

 CreatedBy.Department 


 ## Todo割当先ユーザーの部署を表示させる方法

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/57d32a66-747e-f7c3-3bd8-9b7558f2f39a.png)


 Owner:User.Department 

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/3028955d-f674-6710-e6b0-03dcd77ef3d2.png)


こうすればユーザの部署項目がTodoに表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/62fcefdb-0a70-8279-9a6c-4b64b64707da.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ee2f5f06-864c-fe35-fb3f-a9aad74cca1e.png)


なお、数式項目はユーザの部署項目の内容を更新したらリアルタイムで更新されるのでごちゅういくだｓ
array_reduceの使用例メモ

array_reduceはPHPの組み込み関数です。

・PHP公式はこちら
https://www.php.net/manual/en/function.array-reduce.php

関数の詳細説明は公式におまかせするとして、この記事ではこんな使用例があったというメモです。

例えば下記のようなコードを書いたとします。

```php
public function getAmountIncludingTax(array $postings)
{
  $totalPrice = 0;
  foreach ($postings as $postings) {
      $totalPrice += $postings->price;
  }
  return compact('totalPrice');
}
```

あるクラスの中にあるメソッドだけを切り取ってます。

`$totalPrice`を初期値で設定して`$positngs`をループで回して、priceカラムを足し合わせるといったものです。

これを下記のようにarray_reduceで書くことができます。

```php
public function getAmountIncludingTax(array $postings)
{
    $totalPrice = array_reduce($postings, function ($sum, $posting) {
        return $sum + $posting->price;
    }, 0);
    return compact('totalPrice');
}
```

第二引数（コールバック部分）で足し合わせをしていて、第三引数の`0`は`$totalPrice`の初期値の`0`になります。

どちらが直感的にわかりやすいかは人それぞれだと思いますが、array_reduceを使用すると少しすっきりしますね。

以上、誰かの参考になれれば幸いです。
ABC289Dを解いた

筆者は執筆時点レート600弱の茶色コーダ

最近の目標はDPとセグ木をマスターすることで、
DPの問題があったので解いていく

https://atcoder.jp/contests/abc289/tasks/abc289_d

# 実装コード

```python
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)

def main():
    N = rI()
    A = rLI()
    ma = max(A)
    M = rI()
    B = rLI()
    X = rI()
    
    steps = [0] * (X+ma+1)
    
    for b in B:
        steps[b] = -1
    
    steps[0] = 1
    
    for i in range(X):
        if steps[i] != 1: continue
        for a in A:
            if steps[i+a] != -1:
                steps[i+a] = 1
    ans = steps[X] == 1
    print("Yes" if ans else "No")
    
if __name__ == '__main__':
    main()

```

# 方針
部分和問題の派生として考えることができる。
普通の部分和では同じ数を複数回を使うことができないが、
この問題は何度も使い回すことができるので、それぞれの数を適応したかどうかの情報は不要で、単純にたどり着くかどうかの情報だけでいい。
よって1次元のリストで解ける。

```python
    # たどり着いたら1 でなければ0
    steps = [0] * (X+ma+1)
```

ただし、モチが設置されている数は多いので、一々配列の中身を確認するとTLEが出るでそこは気をつけよう。

```python
    for i in range(X):
        if steps[i] != 1: continue
        if i in B : continue # TLE
        for a in A:
            steps[i+a] = 1
```

無難に番兵を配置して対応した
```python
    # -1 はモチが配置されているとする
    for b in B:
        steps[b] = -1
```

モチの配置している段にたどり着けるかどうかが管理できていないが、
モチの配置している段が目的地になることはないので大丈夫なはず。

# まとめ

ABC289Dを解いた。

部分和問題の派生として考え、
モチ配置の考慮とかも行い、
各階段の到達可能性を計算した。
Terraformって何者？【AWS初心者】

## はじめに

最近「Terraform」というよくわからないコマンドを使う機会があったので概要を抑えつつ、使い方をまとめていきます。
Terraformのコマンドだけ知りたい方は[こちら](#コマンド紹介)まで読み飛ばしてください！

紹介するコマンドは以下のサイトを参考にしました。

https://developer.hashicorp.com/terraform/cli/commands

## IaCとは
Terraformの前に基本的な考え方であるIaCについて説明していきます。

IaCとはInfrastructure as Codeの略であり、サーバのインフラ(CPU、ストレージなど)構築を、コードを用いて自動的に行うことを示しています。

### IaCを利用するメリット

以下にIaCを利用するメリットを列挙します。

- 一貫性と標準化の役割
- 人為的なミスの軽減
- 作業時間の短縮
- バージョン管理が楽

ということでやはり人間が手作業を繰り返して構築していた作業を機械的に処理することが出来るので個人的には、時間効率とミス軽減の恩恵が大きいのかなと感じました。

逆にデメリットも調べましたが、使用者本人にかかる時間的な学習コストについての言及が大半で一部セキュリティや変更管理のプロセスについて言及されていましたが、技術的に大きな問題はないと考えます。

## Terraformとは

[Terraform][Terraform]は、HashiCorp社が提供するIaCツールとなっています。

Terraformではインフラの構成をコードで宣言します。構造化された構成ファイルでは、手動で操作することなくインフラ構成を自動で管理できます。

インフラの初期プロビジョニング、更新、破棄、いずれも記述したコードにより宣言し、実行します。

Terraformでは、構成ファイルで宣言した変更内容を宛先のプロバイダー（AWS, Azure, GCP, VMWareなどをサポートしている）にプッシュします。

AWSではGo言語で書かれたAWS SDKを介して、サーバーをクラウド上に直接構築することが出来ます。

## コマンド紹介

では早速基本的なコマンドについて紹介していきたいと思います！

### terraform init

__terraform init__ コマンドは、Terraform 構成ファイルを含む作業ディレクトリを初期化します。これは、新しい Terraform 構成を記述した後、またはバージョン管理から既存の構成を複製した後に実行する必要がある最初のコマンドです。このコマンドは複数回実行しても安全です。

### terraform plan

__terraform plan__ コマンドは実行プランを作成し、Terraform がインフラストラクチャに対して行う予定の変更をプレビューできるようにします。デフォルトでは、Terraform がプランを作成すると次の処理が行われます。

- 現在の状態が最新であることの確認


- 現在の構成と以前の構成を比較し、相違点がある場合記録する


- 適用するとリモート オブジェクトが構成と一致するようにする一連の変更アクションを提案します


> どのようなリソースが作成・更新・削除されるのかを事前に確認する

使い方
```
terraform plan [オプション]
```

ここで、オプション指定を行うと動作方法を変更することが出来ます。

これからいくつかのオプションを紹介していきます。

|オプション|内容|
|:--|:--|
|-refresh=false|構成の変更を確認する前に、Terraform の状態をリモート オブジェクトと同期するデフォルトの動作を無効化|
|-repleace=ADDRESS|指定されたアドレスのリソース インスタンスを置き換えるようにする|   
|-target=ADDRESS|指定されたアドレスに一致するリソース インスタンスまわりにのみに計画作業を集中するように指示| 
|-var 'NAME=VALUE'|構成のルート モジュールで宣言された 単一の入力変数の値を設定|
|-var 'file=FILENAME'|tfvarsファイルの定義を使用して、構成のルート モジュールで宣言されている 可能性のある多数の入力変数の値を設定|   

### terraform apply

__terraform apply__ コマンドは、Terraform プランで提案されたアクションを実行します。

使い方
```
terraform apply [オプション] [適用したいファイル名]
```

このapplyコマンドにもたくさんのオプションが存在するので紹介します。
|オプション|内容|
|:--|:--|
|-auto-approve|作成予定のリソース表示や実行確認を省略する|
|-backup=path|バックアップファイルのパスを指定する|   
|-compact-warnings|エラーを含まないの場合は、省略した形で表示する|              
|-lock=true|ファイルをロックする（またはしない）ように指定する|
|-lock-timeout=0s |ファイルのロックが失敗した場合のリトライまでの時間を指定する|   
|-input=true|未定義の変数がある場合に変数の入力を求めるかどうかを指定する| 
|-no-color|実行中のアウトプットを色なしで表示させる|  
|-parallelism=n|並列で実行するリソース数を指定する|  
|-refresh=true|実行前にファイルを更新するかどうかを指定する|   
|-state=path|ファイルのパスを指定する|    
|-state-out=path|更新するファイルを指定する　※ `-state` は読み込む＆更新するファイル|    
|-target=resource |どのリソースを実行するかを指定する|  
|-var 'foo=bar'   |変数をコマンド実行時に上書きする| 
|-var-file=foo    |変数を定義した `tfvars` ファイルを指定する|  

### terraform destroy

__terraform destroy__ コマンドは、特定の Terraform 構成によって管理されているすべてのリモート オブジェクトを破棄するのに便利な方法です。

使い方
```
terraform destroy [オプション]
```

また、削除する前に何が削除されるのか確認するためにも以下のコマンド実行をお勧めします。

```
terraform plan -destroy
```

> destroyコマンドにおけるオプション利用例を見つけられなかったことは内緒です。（知っている方いらっしゃいましたら是非教えてください。）

## さいごに

今回はTerraformの基本的なコマンドについて紹介しましたが、まだまだ紹介しきれていないコマンドやオプションがたくさんあると思います。情報が入り次第記事を更新しようと考えておりますが、使っていて便利なツールであることは確信していますので是非皆さん利用してみてください！

[Terraform]: https://developer.hashicorp.com/terraform
Javaで「文字列を作成する」の動作を確認してみた

# 概要

Javaで「文字列を作成する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/string/index2.html

# 実装

以下のファイルを作成しました。
```JSample2_1.java
class JSample2_1{
  public static void main(String[] args){
    String msg1 = "Hello";

    char[] c = {'B', 'y', 'e'};
    String msg2 = new String(c);

    String msg3 = new String(msg1);

    System.out.println(msg1);
    System.out.println(msg2);
    System.out.println(msg3);
  }
}
```
```JSample2_2.java
class JSample2_2{
  public static void main(String[] args){
    String msg1 = "Hello";
    String msg2 = msg1;

    System.out.println(msg1);
    System.out.println(msg2);

    System.out.println("----");

    msg2 = "Bye!";

    System.out.println(msg1);
    System.out.println(msg2);
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample2_1.java 
$ java JSample2_1 
Hello
Bye
Hello
```

```
$ javac JSample2_2.java 
$ java JSample2_2 
Hello
Hello
----
Hello
Bye!
```

# まとめ

何かの役に立てばと。
data-turbo=”false”とdata: { turbo_method: :post }を同時に使いたい場合

## はじめに
data-turbo="false"とdata: { turbo_method: :post }をどうしても一緒に使う必要があった時の話です。

※後述しますが、ajax化した場合ですと今回の書き方ではうまくいきません。予めご了承ください。

## 環境
ruby 3.2.2

rails 7.1.3.2

hotwire

Bootstrap5系

Google Map API

## 今回例示するアプリ画面についての説明

現在、「自分の好きな本屋を紹介し、また好きな本屋が増える事を支えるサービス」がテーマのポートフォリオを作成中です。

今回は開発途中で壁に当たった時の対処法としてここに記していきたいと思います。

## 今回のシチュエーション

ブックマークボタン（画像にある栞のマーク）を押すたびに、javascriptが読み込めなくなりGoogleMapが表示されなくなりました。

![turboメソッドの記事写真1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726578/e533d688-47a8-f35c-879e-c8556f7bff4b.png)

ブックマークを登録するためのビュー
```html
<!-- wanna_go_bookstoresはbookmarks、wanna_goはbookmarkと思ってください -->
<%= link_to wanna_go_bookstores_path(bookstore_id: bookstore.id), id: "wanna_go-button-for-bookstore-#{bookstore.id}", data: { turbo_method: :post } do %>
  <i class="bi bi-bookmark"></i>
<% end %>
```

turbo-railsが働いている影響か、このままだとブックマークボタン（栞のマーク）を押すと、Google Mapが読み込めなくなります。再読み込みすると元通りになりますが、これは改善したいです。

## data-turbo="false"を使う、しかし……
`<div data-turbo="false"></div>`で該当箇所を囲うも、このままだとエラーが出てしまいます。

どうやら**data_turbo=”false”とdata: { turbo_method: :post }は共存できないようです。**

ブックマークを登録するためのビュー
```html
<!-- data-turbo="false"とturbo_methodは共存できないようです -->
<div data-turbo="false">
<%= link_to wanna_go_bookstores_path(bookstore_id: bookstore.id), id: "wanna_go-button-for-bookstore-#{bookstore.id}", data: { turbo_method: :post } do %>
  <i class="bi bi-bookmark"></i>
<% end %>
</div>
```

## link_toではなくbutton_toを使う

ここで私はbutton_toの存在を知りました。

`button_to` はデフォルトでPOSTリクエストを送るもの。

これでPOSTリクエストを送りつつ、Turboの機能を活かしたままに出来ます。

ブックマークを登録するためのビュー
```html
　<div data-turbo="false">
<%= button_to wanna_go_bookstores_path(bookstore_id: bookstore.id), method: :post, id: "wanna_go-button-for-bookstore-#{bookstore.id}", class: "btn btn-link p-0 border-0" do %>
  <i class="bi bi-bookmark"></i>
<% end %>
</div>
```

※ `data: { turbo_method: :post}`ではなく、`method: :post`でないと動かない点に注意
※ また、デフォルトでbutton_toは**黒い枠**が現れるので、Bootstrapを使っている場合はclassで上記のように書けば枠を消すことが可能。

以上のように書けば、ブックマークボタンを押してもGoogleマップは消えず、ブックマークボタンも機能します。

deleteメソッドの場合はこちら

ブックマークを解除するためのビュー
```html
<!-- already_goはunbookmarkと思ってください -->
<div data-turbo="false">
<%= button_to wanna_go_bookstore_path(current_user.wanna_go_bookstores.find_by(bookstore_id: bookstore.id)), method: :delete, id: "already_go-button-for-bookstore-#{bookstore.id}", class: "btn btn-link p-0 border-0" do %>
  <i class="bi bi-bookmark-fill"></i>
<% end %>
</div>
```

## turbo-railsジェムを使ってajax化する場合は

button_toではうまくいきませんでした。
（ブックマークボタンを押すたびにリロードしないとエラーが出ます。）

**試しにlink_toに戻したところ、うまく実装できました。**

ブックマークを登録するためのビュー
```html
<%= link_to wanna_go_bookstores_path(bookstore_id: bookstore.id), id: "wanna_go-button-for-bookstore-#{bookstore.id}", data: { turbo_method: :post } do %>
  <i class="bi bi-bookmark"></i>
<% end %>
```

※今回turbo-railsでのajax化については省略いたします。こちらの方の記事が分かりやすいので共有いたします。

https://qiita.com/iijima-naoya-45b/items/e35bc3f4c38a7f093700

## まとめ
　便利な　data-turbo="false"が使えない場合の対処方法について今回記事を書いてみました。
 　初心者ゆえまだ理解が浅いので、今後も理解を深めていきたいです。
個人の.zshrc(.bashrc)紹介

#my own alias
alias -g @g='| grep'
alias -g @l='| less'

alias la='ls -alF'
alias ll='ls -lF'
alias rmf='rm -Rf'
alias cp='cp -Rf'
alias relogin='exec $SHELL -l'

# zsh aliases
alias vz="vim ~/.zshrc"
alias sz="source ~/.zshrc"

# alias for git
alias gc="git checkout"
alias gb="git branch -a"
alias gp='git pull origin $(git rev-parse --abbrev-ref HEAD)'
オプショナルチェーンとブラケット記法の組み合わせ

オプショナルチェーンとブラケット記法の組み合わせでちょっと詰まったので備忘
(めちゃくちゃ基礎的な内容です)

:::note info
### TL; DR
```typescript
const val = hogeObject.nullableParam?.["KEY"]
```
:::

---

あるオブジェクトがあり、そのうちの1つのプロパティは定義されていない可能性がある。
```typescript
const hogeObject = {
  nullableParam?: Record<string, string>,
  param: string,
  ...
}
```

このとき、以下のように書くと`ts(4111)`エラーが出る。
```typescript
const val = hogeObject.nullableParam?.KEY
// プロパティ 'KEY' はインデックス シグネチャに基づいているため、['KEY'] を使用してアクセスする必要があります。 ts(4111)
```

なのでブラケット記法に変えると、次は`ts(1005)`エラーが出る。
```typescript
const val = hogeObject.nullableParam?["KEY"]
// ':' が必要です。 ts(1005)
```

「`:`なんていらないだろ...？」と思っていましたが、どうやら三項演算子の記法と勘違いされているらしい
試しに以下で書き換えてみるとエラーは無くなった
```typescript
const val = hogeObject.nullableParam ? hogeObject.nullableParam["KEY"] : ""
```

---

ただ、同じ文字を2回も書いて冗長だし、何かいい感じに書ける方法ないかな...
と探していたところ、以下でいけることを知りました。
```typescript
const val = hogeObject.nullableParam?.["KEY"]
```

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining#%E6%A7%8B%E6%96%87

オプショナルチェーンとブラケット記法を組み合わせるときは間に`.`が要るんですね...
知らなかった orz

逆に、なんで今まで`.`つけてなかったんだろう？と思いましたが、
多分最初に習得した言語がPythonだったのでその影響はありそうな気がします。
(ブラケット記法の前に`.`をつけるという発想がなかった)
PageSpeed Insightsで（ほぼ）満点を取る《法令.app》

誰でも楽しく法律が読める[《法令.app》](https://jplaws.app)というWebアプリを作っています。

https://qiita.com/hibarisoft/items/423cd885435a911bc287

## :v:ずっと６０点台だったスコアが９７点に上がった！

ずっと低いままだった[モバイル版トップページ](https://jplaws.app)の "[PageSpeed Insights](https://pagespeed.web.dev/) " の Performanceスコアが急に上がったので、それについて書きます。


:point_down:デスクトップ表示のスコアはもともと高めでした。

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801207/876fcb4d-99cd-eb67-598d-3b7025f5f8a3.png">

しかし、モバイル表示では「６０台」が平均でした。トップページではほぼ全てのコンテンツを動的に生成しているので「ある程度仕方ないか」と諦めていました。（今は使えてない）バンドルツールで読み込み速度が上がれば、スコアを上げられるかもしれないけど、それも僅かだろうと考えていました。

今回、「レイアウトシフト対策」に絞って少し変更を加えると一気に30ポイントくらい上がりました。・・じつは満点じゃないんてすが・・「アクセシビリティ」については抜けているところを直せばもう少し上がりそうです。

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801207/a3e6e8d1-3a94-0e0f-6aa2-a2dd90d37542.png">

## :airplane: やったこと：「移動距離」を少なくした

そのままですね。もともと[トップページ](https://jplaws.app)の要素の９割くらいを動的に表示していました。しかし、古いスマホなどで表示されないことがあるため、よく使われる「法令リスト」を載せることにしました（ＳＥＯ的にも良いのでは？との素人判断もありました）

メインコンテンツは「おすすめ法令」をランダムに表示することでした。レイアウトシフトが発生するタイミングは３つありました

### :no_good: 改善前

1. 静的に表示された「よく使われる法令リスト」を押しのける形で「おすすめ法令」の「カード」が差し込まれる（１画面の高さの、派手なレイアウトシフト）
1. 数メガバイトの大きなデータファイルを読み込んだ後に、「おすすめ法令」のリストの中にランダムに「カード」が差し込まれる（FlexBoxが１つ分大きくズレる。画面がガタガタと動く）
1. LocalStorage の「履歴データ」読み込んで、同様に「カード」が差し込まれる。
1. データソースは３種類あり、揃うのを待っていると１秒ていど「白紙」になってしまうので段階的に差し込んでいる。


<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801207/afde7955-bb0a-fde6-c518-e8782a947b69.gif">

:point_up:改善前の[トップページ](https://jplaws.app)です。Ｆ５リロードを繰り返しています。このＧＩＦでは分かりにくいですが、一瞬見えた「リンク集」が押し出されて画面がガタガタすることがありました。

### :v: 改善後

1. 動的に書き出されるまで、画面に何も表示せず「白紙」にしました（ＣＳＳの `min-block-height`を使って何もない空間を確保した）。変わらず「押し出して」いますが、画面の下に隠れている部分なので影響は少ないようです。
1. 遅れて読み込まれる「ランダム法令」の「カード」は、Javascriptの `after()` で要素の間にねじ込んでいましたが、`replaceWith()` を使って「置換」することにしました。
1. 「置換前」の要素は、「画面外」のリストの末尾に `appendChild()` しました。

やってみると当たり前のことしかしていないのですが、「ユーザーの見えるところで動かさない」のが大事だと思いました。逆に言えば「スクリーン外で見えて無ければ要素をいじくってもいい」ということです。

「微動だに」させないためには、「カード」の高さを固定したり `grid`レイアウトで揃えることもできます。試しては見ましたが、整いすぎてトップページの「趣向」とは違うと思い戻しました。見知らぬ法律との「出会い」を作りたいので、少しランダムで不揃いな見た目が合うと考えています。

:point_down:現在のトップページ。Ｆ５連打です。違いがわかりにくいですが、時々要素が入れ替わります。

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801207/74b09a19-b21b-2cdf-97ee-fdf9ab35e020.gif">

今回の改善は、たまたま上手くいっただけかもしれません。[PageSpeed Insights](https://pagespeed.web.dev/) のスコア基準に詳しいわけではなく、指摘どおりに淡々と直しただけです。

次回は、元データを持っていて検証可能な、「本文から法令名をスキャンする」処理の改善プロジェクトについて書きます。（元がひどかったのもありますが・・）速度が10〜15倍ほどアップしました。

:bird:ひばりソフト（ひばり）
ファイル名の大文字小文字だけを変換した場合、Git に観測されないことがある

# はじめに
ファイル名の大文字小文字だけを返還した場合、Git に観測されないことがありました。。。
その解決方法の共有です！

# 問題

はじめに、で書いた通りですが、ローカルで git status しても検知してくれなかったり、ローカルの build 時にエラーにならないけど、CICD 上の build ジョブでエラーとなることなどがありました。

# 解決方法

以下の手順で git が再検知してくれます！

1. 該当ファイルを削除 
2. `git commit`（この時に大文字で書いたファイルと小文字で書いたファイル両方が Git 上で削除扱いで `commit` される）
3. 該当ファイルを復活させる
4. `git commit` 

# おわりに

結構無理やりな方法で直しましたが、もし他にいい方法を知っている方がいましたら是非コメントしてください！

## 参考

https://himenon.github.io/docs/javascript/case-sensitive-paths-error/
カプセル化と情報隠蔽の違いをちゃんと理解する

## はじめに
最近の輪読会で**カプセル化**と**情報隠蔽**について話があったのですが、まだ理解があやふやな部分が残っています。
そこで、もう一度これらの概念を整理し理解を深めたいと思います。

## カプセル化 (Encapsulation)
カプセル化は、オブジェクト指向プログラミングの基本概念の一つです。
データ（プロパティ）とそれに対する操作（メソッド）を一つの単位でまとめることを指します。
これにより、データの整合性が保たれ、オブジェクトの使用方法が明確になります。

### カプセル化の具体例
以下に、TypeScript でのカプセル化の例を示します。

```typescript
class Person {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public getName(): string {
    return this.name;
  }

  public getAge(): number {
    return this.age;
  }

  public setAge(age: number): void {
    if (age > 0) {
      this.age = age;
    } else {
      console.error("不正な年齢です");
    }
  }
}

const person = new Person("山田", 30);
console.log(person.getName()); // 山田
console.log(person.getAge());  // 30
person.setAge(35);
console.log(person.getAge());  // 35
```

この例では、`Person` クラスが `name` と `age` というデータを持ち、それらに対する操作をクラス内のメソッドで提供しています。これにより、データと操作が一体化されています。

## 情報隠蔽 (Information Hiding)
情報隠蔽は、オブジェクトの内部状態を外部から直接アクセスできないようにすることです。
これにより、オブジェクトの内部状態の不整合や不正な操作を防ぎます。
カプセル化の一部とも言えますが、特にデータの隠蔽に焦点を当てた概念です。

### 情報隠蔽の具体例
先ほどの例をさらに発展させて、情報隠蔽の重要性を強調します。

```typescript
class BankAccount {
  private balance: number;

  constructor(initialBalance: number) {
    this.balance = initialBalance;
  }

  public deposit(amount: number): void {
    if (amount > 0) {
      this.balance += amount;
    } else {
      console.error("不正な入金額です");
    }
  }

  public withdraw(amount: number): void {
    if (amount > 0 && amount <= this.balance) {
      this.balance -= amount;
    } else {
      console.error("不正な出金額または残高不足です");
    }
  }

  public getBalance(): number {
    return this.balance;
  }
}

const account = new BankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 1500
account.withdraw(200);
console.log(account.getBalance()); // 1300
```

ここでは `BankAccount` クラスの `balance` プロパティが外部から直接アクセスできないようになっています。これにより、`balance` を不正に変更されるリスクを回避しています。

## カプセル化と情報隠蔽の違い
カプセル化と情報隠蔽は密接に関連していますが、異なる概念です。以下の表でその違いをまとめます。

| 概念          | 定義                                                                           | 目的                               |
|---------------|----------------------------------------------------------------------------|----------------------------------|
| カプセル化     | データとそれに対する操作を一つの単位にまとめること                                      | データの整合性を保ち、使用方法を明確にする               |
| 情報隠蔽       | オブジェクトの内部状態を外部から直接アクセスできないようにすること                           | 内部状態の不整合や不正操作を防ぐ                   |

カプセル化はデータとメソッドを一つにまとめることに重点を置き、情報隠蔽はそのデータを外部から隠すことに重点を置いています。

## まとめ
普段意識せずカプセル化や情報隠蔽を使っていても、キーワードを出されると **???** となることがありますよね。
改めてこれらの概念を整理し、オブジェクト指向プログラミングの基本を理解することは、より良いコードを書くための第一歩だと感じました。
MisskeyのメールサーバーとしてGmailのSMTPサーバーを利用する

# なにするの？
MisskeyのメールサーバーとしてGmailを使う方法です。
制限こそありますが、小規模インスタンスであれば充分実用に耐えます。

# やり方
## アプリパスワードの発行
[ここ](https://myaccount.google.com/apppasswords)を開き、アプリパスワードを新規発行します。
https://myaccount.google.com/apppasswords

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/e030de91-fc72-b73b-1de7-5aebd0f89a16.png)

アプリ名は任意のもので構いませんが、分かりやすいものにしておきましょう。

生成されたアプリパスワードは後述の手順で必要となりますので、必ず控えておいてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/2e57cefa-8f6b-7a20-37fd-cf8dd1cd90ea.png)



## Gmailに独自ドメインを追加
Gmailから独自ドメインを利用してメールを送信するため、Gmailに独自ドメインを追加します。

:::note info 
この後の手順でメールアカウントの所有確認でメールを受信する必要があるため、Cloudflare Email Routing等で受信メールを確認できるようにしておいてください。
:::

準備が完了したら[Gmail](https://mail.google.com/)を開き、`設定 > すべての設定を表示 > アカウントとインポート > 他のメールアドレスを追加`を押下します。

![chrome-capture-2024-6-26.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/b6ac8085-cd1d-ec1f-6a7a-e447222801cf.gif)

出てきたポップアップウィンドウに任意の名前と利用したいメールアドレスを入力し、`次のステップ`を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/a8bf6cbf-426b-04b0-b142-d0aa2f698bb9.png)

次のページでは以下のように入力します。

|項目|設定値|
|--|--|
|ホスト|smtp.gmail.com|
|ポート|465|
|ユーザー名|アカウントのユーザー名部(@gmail.com以前の部分)|
|パスワード|上記手順で取得したアプリパスワード|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/d02328bf-d932-4b0f-4123-a25a91b6adcd.png)

すべての項目の入力が完了したら、`アカウントを追加`を押下してください。
しばらくすると、入力した独自ドメインのメールアドレス宛に認証メールが届くので、URLから認証を行ってください。


## Misskeyでの設定
`コントロールパネル > メールサーバー`を開き、`メール配信機能を有効化する（推奨）`を有効化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/be07eaba-8a57-28d4-722a-12a335137e43.png)




残りの項目は以下のように設定

|項目|設定値
|--|--|
|メールアドレス|使用する独自ドメインのメールアドレス|
|ホスト|smtp.gmail.com|
|ポート|587|
|ユーザー名|アプリパスワードを発行したアカウントのメールアドレス|
|パスワード|上記手順で発行したアプリパスワード|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/30a27939-e16e-3980-7057-a5d35f06cf21.png)

すべての入力が完了したら保存を**必ず**押下します。


# 確認
最後に正常送信ができているかの確認を行います。
Misskey上の設定ページにある`配信テスト`を押下し、メールが届くかを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/d79db0d8-e0e8-11b9-11a6-c22b81cd8dcf.png)

こんな感じのメールが届けばおっけーです！
お疲れ様でした👍🏻
大津の2値化について

初めまして
マルマウンテンと申します。
現在、製造業の新規事業部門でデータサイエンティストをしております。
業務で画像処理をよく行っており、大津の２値化について記載いたします。

まず画像処理で２値化を前処理で行い、その後に画像解析をすることが多いです。
その画像処理の２値化(白黒)を行うと、不要な情報を減らすことができるのと画像の容量を減らして解析のスピードを上げることができます。
ただし、2値化する際にどの画素値を閾値にして２値化するのかなど自分で判断することが大変なことも多いです。そこで、大津の2値化を行うことで閾値を自動的に算出して、その閾値を用いて２値化することができます。
その大津の２値化について原理を説明していきます。

# 大津の2値化（判別分析法）と原理
大津の手法は、分離度が最も大きくなるときの閾値を求めます。処理手順は次の通りです

1. 入力画像（1チャンネル）のヒストグラムを求めます。
2. ヒストグラムから、画素値の最大値 $I_{\text{max}}$、最小値$I_{\text{min}}$、平均値$\mu_0$を求めます。
3. 最大値 $I_{\text{max}}$と最小値$I_{\text{min}}$の範囲内で、ある閾値$t$を選びます。
4. 閾値でヒストグラムを2つのクラス（Class）に分けます。
5. クラス1の分散$\sigma_1^2$、平均値$\mu_1$、画素数$n_1$を求めます。
6. クラス2の分散$\sigma_2^2$、平均値$\mu_2$、画素数$n_2$を求めます。
7. クラス内分散とクラス間分散を以下の式から求めます：
クラス内分散： $\sigma_w^2(t) = \frac{n_1 \sigma_1^2 + n_2 \sigma_2^2}{n_1+n_2}$
クラス間分散： $\sigma_b^2(t) = \frac{n_1 (\mu_1 - \mu)^2 + n_2 (\mu_2 - \mu)^2}{n_1+n_2}$

9. 分離度（クラス内分散とクラス間分散の比）を求めます:
分離度 $D(t) = \frac{\sigma_b2(t)}{\sigma_w2(t)}$

手順3～8を繰り返し、分離度が最大になるときの閾値を二値化処理に用います。
このアルゴリズムにより、適切な閾値を自動的に決定して画像を二値化することができます。
[Linux] build するとき、とまっちゃう OOM のあれこれ

# はしがき

うちの会社はサービス向けのサーバー以外にも、サービスするためのテスト向けのサーバーも運用しています。

仕事をしながら、テスト向けのサーバーから build しましたが、終わるまで、時間がかなり長くかかりました。
終わったとしても、build は失敗でした。

上司にきいたら、OOM らしいでした。
「OOM」という言葉は初耳でしたが、このような現象は以前の CICD のことを実装するときも(　https://qiita.com/dkdidudtn/items/45f06b741bda7a14b838 )経験したことです。

swap を使って、解決した記憶がありますが、この時は自分の権限がないので、上司から swap もらいました。

# OOM ってなに？

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

```plaintext
Out of memory (OOM) is an often undesired state of computer operation where no additional memory can be allocated for use by programs or the operating system.
```

OS もしくは program に追加メモリーを与えられない状態です。
システムにメモリが足りなくなって、OS による program がシャットダウンされます。

```plaintext
Historically, the out-of-memory condition was more common than it is now, since early computers and operating systems were limited to small amounts of physical random-access memory (RAM) due to the inability of early processors to address large amounts of memory, as well as cost considerations. Since the advent of virtual memory opened the door for the usage of swap space, the condition is less frequent.
```

昔からは結構 OOM がありましたが、VM の発展による swap memory を使えるようになって、最近はどんどんなくなる状態ということです。

「どんどんなくなる」といっても、cloud computing service を使うことによって、サーバーを運用にある程度ピッタリする VM を使うので、場合によって、発生する可能性があります。

### swap space/memory

https://serverfault.com/questions/48486/what-is-swap-memory

https://phoenixnap.com/kb/swap-memory

物理 disk(SSD, hard disk)に RAM 機能を拡張することです。

# 解決方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582489/7b965a4f-5ff6-2f46-fd49-95eedbe25709.png)

aws の free tier の ec2 を使いました。

いかのコードで memory を確認できます。

```bash
$ free -h
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582489/22e30d85-7ee5-e94d-d4f7-dd4bcea732f8.png)

free tier なので、949MiB です。
この状態で、ある git repository から clone して、`npm install` したら、すぐ止まってしまいます。

ec2 の size を upscale する方法もあると予想しますが、今回は swap memory を追加する方法を使います。
swap memory を使うために disk の size を確認する必要があります。

```bash
$ df . -h
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582489/2cd7bc8c-884e-c00c-b656-2e613d744fe5.png)

使える部分が 6.5GB で、十分だと思います。

```bash
$ sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
```

これで、1GB　ぐらいの swap memory を追加しました。

```bash
free -m
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582489/c1275fd2-fc36-a6e8-76b4-0f94113f5e55.png)

ちゃんと追加されました。
これで小さい project ではmodule install できるはずです。

# 参考&関連 URL

https://serverfault.com/questions/48486/what-is-swap-memory

https://phoenixnap.com/kb/swap-memory

https://linuxize.com/post/create-a-linux-swap-file/

https://www.tecmint.com/create-a-linux-swap-file/

https://github.com/deliyami/AWS_frontend/blob/main/codedeploy.md
クロスサイト・スクリプティングについて調べる

# はじめに
現在携わっているシステムでセキュリティのチェックをするにあたり、
曖昧な知識しかないなと痛感したので、復習を兼ねて調べてみることにしました。
今回はクロスサイトスクリプティングについてです。

# クロスサイト・スクリプティングとは
ウェブページの出力処理に問題がある場合に、そのウェブページにスクリプト等を埋め込まれてしまうことを**クロスサイト・スクリプティングの脆弱性**といいます。

その脆弱性を悪用して、利用者のブラウザ上で不正なスクリプトを実行する攻撃を**クロスサイト・スクリプティング攻撃**といいます。

この攻撃を受けると、ウェブサイトを閲覧している利用者には以下のような影響を及ぼす可能性があります。

#### 本物のサイト上に偽のページが表示される
- 偽情報の流布による混乱
- フィッシング詐欺による重要情報の漏洩

例えば、ウェブサイト上に偽のログイン画面や個人情報入力画面が表示されることで、
入力したアカウント情報や個人情報が漏洩してしまう可能性があります。

#### ブラウザが保存しているCookieを取得される
- CookieにセッションIDが格納されている場合、利用者へのなりすましにつながる
- Cookieに個人情報等が格納されている場合、その情報が漏洩する

例えば、ログイン管理にセッションIDを利用しているサイトの場合、セッションIDが漏れることで、知らない間に別の人に自分のアカウントで取引や投稿などをされてしまう可能性があります。

#### 任意のCookieをブラウザに保存される
- セッションIDが利用者に送り込まれ、**セッションIDの固定化**攻撃に悪用されます。

##### セッションIDの固定化とは
悪意を持った人物が、あらかじめ用意したセッションIDを利用者に送り込み、そのセッションIDで利用者がログインすると発生する問題です。
このセッションIDの送り込みは、セッションID受け渡し時の不備が悪用されています。
この攻撃をされると、あらかじめ用意したセッションIDで本人になりすましてウェブサイトにアクセスすることができてしまいます。

# 注意の必要なサイト
- cookieを利用して、ログインセッション管理を行なっているサイト
- ログイン画面や個人情報入力画面をもつサイト　etc.

# 主な原因
~~1. **入力したスクリプトをそのまま実行できる状態になっている**~~
1.**ユーザーが入力した文字列をエスケープしないで画面に表示している**
- スクリプトを作成する際には、&や<、>、,、"などの特殊文字が利用されますが、
それらの文字があった場合文字列に置き換えるなどの処理を施していないと、
そのスクリプトが実行され、クロスサイト・スクリプティングが実行できてしまう可能性があります。

2.**入力値が制限されていない**
- 郵便番号や電話番号、計算値のような数字以外の情報を入力しない入力欄に対して
何も入力値の制限をしないこともクロスサイト・スクリプティング攻撃に繋がる可能性があります。

- また、文字数制限がないと、スクリプトが書きやすくなってしまう可能性があります。

# 対策
1.**入力したスクリプトをそのまま実行できる状態になっている場合の対策**
- 入力されたデータに対してエスケープ処理を実行するなどして、スクリプトを無害化する必要があります。
- 文字列に変換するなどして無害化しておけば、スクリプトが文字列として表示されるだけになり、攻撃者の意図するような攻撃を防止することができます。

具体例として、
```<div>何か処理</div>```

のような値が入ってきたときに、そのまま処理してしまうと、意図しない画面が表示されてしまうなどの危険性があります。
これに対して、
```<　　→　　&lt;```
```>　→　　&gt;```
に置き換えると

```&lt;div　&gt;何か処理&lt;/div&gt;```

のようになり、スクリプトではなく、文字列と認識されるようになります。
この置き換えの処理はライブラリを使うか、自分で置き換えのための関数を作って、それを使ってエスケープ処理を実施するといいでしょう。

2.**入力値が制限されていない場合の対策**
- 入力欄には意図した値以外は入力できないように制限を設けておくと、スクリプトを入力されるリスクを軽減できます。
- また、入力値の制限が難しい場合なども、文字数を制限しておくことでクロスサイト・スクリプティング攻撃を抑止することにつながります。

- また、入力値のチェックについては、ブラウザ側で制限を追加するだけでなく、サーバー上でも行うことが大切です。
なぜなら、ブラウザ上でのチェックはJavaScriptで行いますが、JavaScriptを無効にすることで、ブラウザ上でのチェックを免れてしまう可能性があるからです。
加えて、JavaScriptを無効にしなくてもクライアントサイドで書き換えができることもあるので、サーバー側でのチェックは欠かさないようにしましょう。

# 参照
https://www.ipa.go.jp/security/vuln/websecurity/about.html

https://www.fielding.co.jp/service/security/measures/column/column-9/#anc-03

https://cybersecurity-jp.com/column/33684
失敗が怖くて行動できないあなたへ

# はじめに

**主人公が挫折しないマンガは読んでいても面白くない**

あなたは**失敗すること**を怖がって行動できないという経験はないでしょうか？
私はよくアウトプットが大切という話をしていますが、**インプット中毒**になってしまうのはまさに失敗したくないという思いから来ています。

今回は「挫折したくない」「失敗したくない」と思ってしまいなかなか行動できない人に向けて**失敗が怖くなくなる考え方を紹介します**

私はこの考え方を身につけたことで失敗に対して怖いと思うことはなくなり、むしろ「失敗したからアウトプットしよう」そう考えるようになりました

以下は実際に私が失敗した経験です

https://qiita.com/Sicut_study/items/fee03dd7e20741a33bc5

https://qiita.com/Sicut_study/items/1723379221bd966b36aa

<font color="red">**大きな失敗や挫折であればより私としては羨ましいと思ってしまいます**</font>

ぜひともこの記事を通して、新しい考え方を身につけて挑戦できる人が増えたら嬉しいです。

# 少年ジャンプはなぜ面白いのか

**あなたは少年ジャンプの作品に熱中したことないでしょうか？**

私はアニメで「怪獣8号」をみてめっちゃ面白いなと最近感じました。
なぜ、ジャンプの作品はここまで人を長い間熱中させ続けているのでしょうか？

マンガにはかならず「起承転結」が存在します。
物語の中ではかならず何かしらの「問題」が起きて、うまくいっていた主人公がこの世の絶望と感じるほどに落ちます。つまり「失敗」や「挫折」です

強敵が現れたり、大事な仲間を失ったり、自信をなくしたり....

**しかし最後には絶対に立ち上がって成功を収めます**

この起承転結や「このあとどうなっちゃうの？」というハラハラ感が楽しさです。

# 挫折がないと面白くない

物語は挫折や失敗がないとまったく面白いものにはなりません

例えば、主人公が出会った敵をすべて簡単に倒して世界を平和にしたり、スポーツマンガで相手チームをボコボコにして日本一になっても読んでいる側は全く面白くないのです。

これはマンガだけではありません。

エンジニアの話で例えると、もしGoogleのエンジニアが「私が未経験のときは〜のように学習をしました」という話をしていても

その裏にはバックグラウンドとして「東京大学」「幼少期からプログラミングをしていた」など通常とは異なる生い立ちを送っていることもあるでしょう

<font color="red">**あなただから成功したんでしょ。私には参考にならない**</font>

そう誰しもが思ってしまうと思います。

# 自分のストーリーを発信する大切さ

私は「アウトプットが大切」ととにかくいっています。
**自分のストーリーを発信するのも大切なアウトプットなのです**

先程「Goolgeエンジニアの話」をたとえ話にしましたが、この話の中にも実際には色々な「挫折」「失敗」があるはずです

しかし、それらを語らずにいきなり「未経験のときにはこのように学習した」と話してしまうから物語として面白くならずに読んだ人を熱中させることができないのです。

もしここに「小学校の成績はクラスビリだった」「新卒の頃は100社以上落ちた」などのバックグラウンドを読者が知っていれば読者を熱中させて、読者に何かしらの「モチベーション」であったり「気づき」を与えることができるのです

<font color="red">**アウトプットでぜひ行ってほしいのは自分のストーリーを発信することです**</font>

ストーリーを発信するということは、自分がやってきた経験や体験、成功、失敗をその時時でしっかりと発信をすることです。

発信するのはQiitaでも良いですし、Twitterなどでも問題ありません。

**発信を続けているとあなたの投稿に応援してくれる人が増えていきます。**

読んでくれる人は「大きな失敗」「大きな挫折」からの立ち上がって頑張り、成功していく姿に大きく熱中していきます。

<font color="red">**失敗や挫折は何か挑戦をしているあなたにとっては「あなたの挑戦の話」を面白くする要素になるのです。**</font>

世の中では普通に成功した人はあまり日の目を浴びません
テレビに出るのは高卒から社長になるなどどん底から成功を収めた人が多いです。

**あなたの挑戦はかならずうまくいきます。大きな失敗があればそれを喜んで受け入れて、自分のストーリーが更に楽しくなったと考えられれば、更に挑戦することができるようになります。**

成功するまでやれば成功します。ぜひとも1度や2度の失敗でここまでの努力を無駄にしないでください。

# ストーリーはリアルに発信せよ

2人のエンジニアが転職をしたとします
2人の経歴や技術はほとんど同じで甲乙つけがたいとします

1人はエンジニアになってからずっと自分の経験を発信してきました
1人は面接でこれまでの経験を振り返って話しました

2人の経験は全く同じものだとします。
**自分の経験を発信している方が当たり前に信じることができます。**

つまり自分のストーリーを発信するときは、リアルタイムに発信することが大切なのです

ストーリーを発信し続けることは転職するときにもかなり有利になります。
採用担当はあなたのアウトプットをある程度チェックしています。

<font color="red">**あなたがこれまでの経験を発信していたら、それはあなたを採用することへの保証や核心へと変わるためより転職に有利に働くことになります**</font>

# おわりに

今回は私が失敗をしたても怖く感じない理由を紹介しました
何か大きな挑戦をしているときは、毎日のように辞めたくなるはずですが、この話を理解できていれば挑戦し続けて絶対に成功を掴むことができます

ぜひともあなたの挑戦を続けて、ネットで語られるくらいのストーリーを残していただけたらと思います

ここまで読んでいただけた方はいいねとストックよろしくお願いします。
@Sicut_study をフォローいただけるととてもうれしく思います。

また明日の記事でお会いしましょう！

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからライン登録お願いします👇

https://projisou.jp
【生成AI】Amazon Bedrockを使用してJupyterNotebookのコードを解説させてみた

どうもこんにちは。

今回は、Amazon BedrockのAPIを使用して、Jupyter Notebook（SageMakerノートブックインスタンス）のコードを解説させてみました。

# 使用したモデル

新しいClaude3を使用したかったのですが、東京リージョンでは7月から使えるようなので、今回は我慢します。
なので、Claude2.1を使用します。

AWSコンソールの`Amazon Bedrock > モデルアクセス`のページからアクセスをリクエストしておきましょう。

![スクリーンショット 2024-06-26 19.02.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/fe6fb47f-5e23-b03b-39e5-3d7e34dfc358.png)

# IAMポリシーについて

今回は、SageMakerノートブックインスタンスからBedrockへアクセスする必要があるので、ノートブックインスタンスに紐づいている`IAMロール > ポリシー`を変更する必要があります。

紐づいているポリシーにBedrockの`InvokeModel`アクションを許可すればOKです。

![スクリーンショット 2024-06-26 19.01.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/c5130ef4-68a7-9ae4-83f9-8805fc5e70c6.png)

# 手順

## 1. SageMakerノートブックインスタンス内で適当にコードを書く

本当に適当でいいです。自分は機械学習を行なっていたので、それを使用しました。
とりあえず、今回は以下のコードを読ませるとしましょう。

```python
print("test")
```

## 2. 必要なライブラリをインストール

ノートブックのコードを読ませるためのライブラリをインストールします。

```python
# ノートブックを読ませることができるライブラリ
!pip install nbformat
import nbformat

# Bedrockで使用するライブラリ
import boto3
import json
```

## 3. ノートブックを読ませるための関数を記述

```python
def get_notebook_code(notebook_path):
    with open(notebook_path, 'r', encoding='utf-8') as f:
        notebook = nbformat.read(f, as_version=4)
        
    code_cells = [cell['source'] for cell in notebook['cells'] if cell['cell_type'] == 'code']
    return '\n\n'.join(code_cells)
```

## 4. ノートブックを読ませて変数に保存

```python
notebook_path = 'test_notebook.ipynb'
code = get_notebook_code(notebook_path)
```

## 5. Bedrockクライアントを作成

```python
client = boto3.client('bedrock-runtime')
```

## 6. プロンプトを作成

```python
prompt_message = f'あなたはPythonコードのスペシャリストです。以下にpythonのコードを示しますので、何を行なっているコードなのか分かりやすく教えてください。\n\n{code}'

body = json.dumps({
    "prompt": f'\n\nHuman:{prompt_message}\n\nAssistant:',
    "max_tokens_to_sample": 300,
    "temperature": 0.1,
    "top_p": 0.9,
})
```

## 7. 必要な情報を定義して解説実行!

```python
modelId = 'anthropic.claude-v2:1'
accept = 'application/json'
contentType = 'application/json'

response = client.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)
response_body = json.loads(response.get('body').read())

print(response_body.get('completion'))
```

ちょっと時間かかるので、気長に待っているとログ出力されます。

```text
はい、こちらのPythonコードは非常にシンプルな処理を行っています。

print("test")

この1行のコードは、「test」という文字列を出力するだけの処理です。

print関数は、括弧内のオブジェクトを標準出力(通常はコンソールやターミナル)に出力する組み込み関数です。ここでは「test」という文字列オブジェクトをprint関数に渡しているため、「test」と出力されます。

つまり、このコードはコンソールに「test」と表示するだけの簡単な処理を行うサンプル的なコードだと考えられます。

プログラミングを学習する際に、print関数を使って文字列などを出力し、処理の動作確認を行うことが多いです。そのような意味で、典型的な学習用のサンプルコードだと思います。
```

以上

# インターンシップ募集中！

弊社では、この夏、2種類のインターンシップを行います！

対象は、26,27,28卒の大学生の方です。

## 1day 機械学習体験インターンシップ

日程： 7/17（水）、7/31（水）、8/6（火） いずれか選択
時間： 13:00 ~ 17:30
 
## 5days Webアプリ開発体験インターンシップ

日程： 8/20（火）、21（水）、22（木）、26（月）、27（火）
時間： 10:00 ~ 18:00

参加をご希望の方は、`internship@pdc-ds.com`までご連絡ください！
ONTAPのイベントログをAthenaで見たかったけど出来なかった

ONTAPのイベントログをAthenaで見たかったけど出来なかった話（単純ではなかった）

Windowsのコマンドイベントログで.evtxファイルをCSVに簡単に変換できます。
以下のPowerShellスクリプトを参考にしてください。

```powershell
# 変換する.evtxファイルのパス
$evtxFile = "C:\Users\admin\Desktop\audit_log.evtx"

# CSV出力先のパス
$csvFile = "C:\Users\admin\Desktop\audit_log.csv"

# イベントログを取得してCSVに変換
Get-WinEvent -Path $evtxFile | Export-Csv -Path $csvFile -NoTypeInformation
```
この方法でCSVに変換することは可能ですが、単純にCSVに変換しただけでは欲しい情報を抽出するのが難しく、Athenaを利用しても十分な分析ができませんでした。

以下の記事にあるように、Pythonを利用して必要な情報を定義し、目的に合ったCSVへ変換する必要があるようです。

https://qiita.com/turupon/items/1956600a14571b9f0b6e
`??` で nullish な値を判定する

## TL;DR
JS/TS において、 [falsey](https://developer.mozilla.org/ja/docs/Glossary/Falsy) な値には色々とあるが、参照してランタイムエラーになってしまうのは `null` と `undefined` の2つである。
この `null` と `undefined` を合わせて [nullish](https://developer.mozilla.org/ja/docs/Glossary/Nullish) な値という。
falsey な値は `||` で判定・置き換えが可能だが、例えば `''` はそのまま通したい、という場合もある。
JS/TS には nullish な値を簡潔に判定することができる `??` という演算子が用意されている。

## Null 合体演算子 `??`
左辺が `null` または `undefined` の場合左辺の値を返す。
それ以外は左辺の値を返す。
[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing)には「論理OR演算子`||`の特殊形と見なせる」と書いてある。

### コード例
```ts
null ?? 'foo' // 'foo'
undefined ?? 'foo' // 'foo'

false ?? 'foo' // false
0 ?? 'foo' // 0
-0 ?? 'foo' // -0
0n ?? 'foo' // 0n
NaN ?? 'foo' // NaN
'' ?? 'foo' // ''
document.all ?? 'foo' // HTMLAllCollection(...
```
なお `??` ではなく `||` で比較した場合、すべて `'foo'` が返ってくる。

## Null 合体代入 `??=`
例えば`x ??= y;` は `x = x ?? y;` とほぼ同じ。
JS/TSの論理演算は短絡評価なので、 `x` が nullish でない場合、**前者は代入自体が行われない**。
後者は `x` が nullish であってもなくても代入が行われる。(短絡評価ではある)

### コード例
```ts
let x;

x = null;
x ??= 'piyo'; // 'piyo'

x = undefined;
x ??= 'piyo'; // 'piyo'

x = false;
x ??= 'piyo'; // false

x = 0;
x ??= 'piyo'; // 0

x = -0;
x ??= 'piyo'; // -0

x = 0n;
x ??= 'piyo'; // 0n

x = NaN;
x ??= 'piyo'; // NaN

x = '';
x ??= 'piyo'; // ''

x = document.all;
x ??= 'piyo'; // HTMLALLCollection(...
```
なお `??=` ではなく `||=` を使った場合、 `x` にはすべて `'piyo'` が代入される。
Python for 鬼の100本ノック in range(93, 98)

https://www.youtube.com/watch?v=Gh0qRBHbnVs&t=1420s

93から99を2周目
サクサク解説してくれます。


https://www.youtube.com/watch?v=U-_43dmdV_I&t=25s

あとこの動画の1問目だけ（1週目）
鬼の100本よりはじっくり丁寧な解説です。

両方で写経するとよさそう
腱鞘炎悪化した
Git リポジトリから機密情報を削除するための BFG Repo-Cleaner の使用方法

## 概要

Git リポジトリに機密情報（例えば、API キーやパスワード）を誤ってコミットしてしまった場合、その履歴を完全に削除することが重要です。BFG Repo-Cleaner は、Git リポジトリの履歴から不要なファイルや機密情報を効率的に削除するためのツールです。本記事では、BFG Repo-Cleaner のインストールから使用方法までを詳しく説明します。

## BFG Repo-Cleaner のインストール

まず、BFG Repo-Cleaner をインストールします。以下のコマンドを使用して、公式の Maven リポジトリから JAR ファイルをダウンロードします。

```bash
curl -LO https://repo1.maven.org/maven2/com/madgag/bfg-repo-cleaner/1.13.0/bfg-repo-cleaner-1.13.0.jar
```

## Java のインストール

BFG Repo-Cleaner を実行するには Java が必要です。Homebrew を使用して Java をインストールします

```bash
brew install openjdk
```

Java をインストールした後、PATH 環境変数に追加します。

```bash
echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

## 機密情報の削除

### 1. 削除したいファイルを指定

以下のコマンドを実行して、`.env.development` ファイルをリポジトリの履歴から削除します。

```bash
java -jar bfg-repo-cleaner-1.13.0.jar --delete-files .env.development
```

### 2. リポジトリのクリーンアップ

BFG Repo-Cleaner の実行後、Git リポジトリをクリーンアップするために以下のコマンドを実行します。

```bash
git push origin --force --all
git push origin --force --tags
```


## 注意点

- BFG Repo-Cleaner を使用する前に、リポジトリのバックアップを取っておくことをお勧めします。
- `--force` オプションを使用するため、リモートリポジトリの履歴が書き換えられます。チームメンバーと協力して作業を行い、必要に応じてリモートリポジトリの再クローンを行うように伝えましょう。

## まとめ

BFG Repo-Cleaner は、Git リポジトリから機密情報を効率的に削除するための強力なツールです。適切に使用することで、セキュリティリスクを低減し、クリーンなリポジトリを維持することができます。

---

この記事が役に立ったと思われたら、いいねやコメントをお待ちしております。さらに質問がある場合はお気軽にどうぞ！
Unity学習記録 #004 条件分岐（switch文）

# 条件分岐に使用される制御構文
条件分岐で使用される構文は2つです。
・if文（条件を満たす場合に実行する処理を記述）
・switch文（変数の値によって処理を分岐）

前回はif文の学習をしました。今回はswitch文を見ていこうと思います。

## switch文
まずはシンプルなswitch文を記述します。
switch文の構造が理解しやすいように行間を作っていますが、慣れてきたら行間は空けなくても問題なく処理は実行されます。
```csharp
string lamp = "青";

switch (lamp)
{
    case "青":
        Debug.Log("信号の色は青色です");
        break;

    case "黄":
        Debug.Log("信号の色は黄色です");
        break;

    case "赤":
        Debug.Log("信号の色は赤色です");
        break;

    default:
        Debug.Log("指定された色ではありません");
        break;
}
```
<br>

switch文の中身を見ていきます。
まずは判定する値を小括弧の中に設定します。ここではlampという変数を記述しました。このlampという変数の中にある値によって処理内容を分岐させて目的の処理を実行します。
```csharp
switch (lamp)  //　判定したい値をここに記述する
```
<br>

続いて中括弧の中身を見ていきます。サンプルコードでは3つのcase文を記述してそれぞれに条件を設定しています。判定した値が "青" だった場合、"黄" だった場合、"赤" だった場合にそれぞれ実行したい処理を記述しています。今回は処理する内容は1行しか記述していませんが、case文の中の処理したい内容は何行になっても大丈夫です。

それぞれの条件処理の最後には "break;" を記述してswitch文の処理を終了させなければなりません。
```csharp
case "値":
    //実行したい処理をここに記述
    break;
```
case文で気を付けるポイントは、caseを記述した行の末尾にはコロン「:」、breakの末尾はセミコロン「;」を使用します。それぞれ使用する文字を間違えるとエラーになってしまいますので注意しましょう。
<br>

最後にdefault文がありますが、これはどの条件にも当てはまらなかった場合に処理する内容をここに記述します。記述しなくてもエラーが出ることはありませんが、どの条件にも当てはまらなかったときに何かしらの応答があった方がいい場合は記述します。
```csharp
default:
    //どの条件にも当てはまらなかった場合の処理をここに記述
    break;
```
<br>

異なる値でも処理する内容が同じであれば、case文をまとめた記述ができます。
```csharp
string lamp = "赤";

switch (lamp)
{
    case "青":
        Debug.Log("進行可");
        break;

    case "黄":
    case "赤":
        Debug.Log("止まれ");
        break;
}
```
このような表記方法も覚えておくといいかと思います。
<br><br>

## おまけ情報
学習メモを残してく中で「小括弧」や「中括弧」という単語を使っています。
( )：小括弧（丸括弧）
{ }：中括弧（波括弧）
[ ]：大括弧（角括弧）

読み方が複数ある記号などは、なるべく統一した単語を使うようにしようと思います。
初心者こそコードレビューするべき理由

# はじめに
みなさん、コードレビューに対してどのような考えをお持ちですか？
特にチーム開発経験が浅い方は、「自分の指摘なんて:worried: 」「偉そうだと思われるかも:cry: 」と思いがちかもしれません。かくいう私もその一人でした。

今年から新卒で働き始め、チームでの開発経験も乏しい私が「初心者こそコードレビューすべき！」と感じた理由をいくつか紹介します。

これを機に、一歩前進してみましょう！！！

# 質問が気軽に行える
<!--
レビューちゃうやんと思ったそこのあなた、それでもいいんですよ
はじめからレビューはむずいのでこれくらいハードル引くいものからにしましょ的な
-->
他人が書いたコードを読んでいて気になる部分、疑問に思う部分というのは必ずでてくると思います。
「気にはなるけど、今の自分がやっているタスクとは関係ないから相手の時間を割いてまで質問するほどでもないな :thinking: 」という部分を聞けるのがコードレビューの場です。

なぜなら、質問内容は**相手のタスク**とは関係しており、**いつ回答するかは相手次第**なので、質問のハードルが低くなるからです。チャンスがあれば簡単な内容でもぜひ聞きましょう！

以下は自分の例です。以前から自分の理解が合っているか気になっていた部分がちょうど差分に入ったのでこの際聞いてしまおうという感じで質問しました。
![質問はいいぞ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698077/f375a17d-fbfe-4681-7d2e-f2de114145f0.png)

# 担当外の仕様理解度が上がる
レビューでは、「想定通り動作するか」も確認対象なので、自分が担当していない部分の仕様の理解が求められます。

**担当領域外まで知ろうとする行為にマイナスはない**です。もし主担当者がいない場合でも、その経緯を把握している人がいるだけで話が進みやすくなるはずです。

以下は自分の例です。（[ラベル](https://shields.io/)を最近使い始めました :thumbsup: ）
![仕様確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698077/9f4343ac-f071-0845-cef2-193c2c7d8c03.png)


# チーム全体のコードの質が上がる
どんなに技術力がある方も人間なので、どこかで考慮漏れ等のミスが起きることもありえます。前提知識の乏しい純粋な気づきにこそ、バイアスなしの新視点の可能性があります。

少しでも「良くなるかも？」と思ったら積極的に伝えてみましょう！考慮済みであれば採用されないだけなので、**良くなることはあっても悪くなることは基本ない**です。

以下は、たまたま気になった部分を伝えて、採用されたラッキーなケースです！（ポジティブなフィードバックも添えてくださっています:smile:）
![たまには役立つかも.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698077/584e9e47-74c6-b343-b683-3d25d489eea3.png)

# レビューを受けるチャンスが増える
これは意外な観点ですが、レビューする側もレビューを受けるチャンスです。なぜなら、自分の指摘が微妙だった場合には必ず反論があるからです。むしろコードや説明を書く手間を省ける分、効率的にレビューを受けることができるとポジティブに捉えることもできます。

特に、**自分ならこうするかも**という意見を伝えることで、**質問相手の思考を追体験できる**のがよいと感じています。

以下は自分の例です。（反論ではないですが、このような対処をした理由を添えてくださっています）

![レビューを受けることができる.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698077/bb30ef54-fae7-e51b-9aca-2f139d036d9d.png)

# 引き出しの質が向上する
どうしても自分のコードだけを書いていると引き出しが自分に閉じがちです。もちろん他の人が書いた部分を参考にすることもありますが、**自分なりの解釈をしてしまうので相手の意図をきちんと汲み取れているかは定かではない**です。

そこで、レビュー時に直接コメントして、良いかもと思った書き方についてその意図を訪ねたり、いいと思った理由とともにフィードバックして取り入れるのがよいと感じています。

以下は、自分の例です。

![コーディング力アップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698077/fde11fc2-1c3e-1400-28d3-c7b473f258b1.png)

![ポジティブなコメント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698077/66b80d17-2b5f-c998-9d8d-521501713030.png)

# チーム全体の開発者体験向上に寄与する
レビューを通して、読みやすい PR の粒度、あるべき説明とその分量を身を持って知ることができます。したがって、**必要十分な情報をわかりやすく伝えること**を意識するようになります。これを意識することでレビューコストが大きく減り、チーム全体として時間が節約できます。

自分の場合は、以下のことを意識することが多いです。
- この PR で変更の対象としてる変更内容をトピックごとに記述する
- 視覚的に差分がわかるところは画像としてエビデンスを出す
- 複数の方針に悩んだ場合、他の選択肢とその方針にきめた理由を記述する

# おわりに
弊社 CTO は新卒時代、先輩が書いたコードは必ず目を通すようにしていたという話を聞いたことがあります。多くの人の考えに直接触れていくことが成長速度を底上げした一因になっているのではないかなと思っていたりします。
もちろん、自分のタスクがボトルネックになっているときに他人のレビューに時間を掛けていては本末転倒になることもあるので、バランスを意識してともに良い成長をしましょう！


積極的にエンジニア採用をしているので、興味持たれた方はぜひ！

https://www.hrbrain.co.jp/recruit
tinySA ULTRA 教養としてのスペクトラムアナライザ

# 概要 
モバイルは目に見えないからなんもわからん。
なので、見えない電波を見るために`tinySA ULTAR`を買って電波を可視化してみました。

# 参考文献
- [1] https://www.tinysa.org/wiki/
- [2] 


# 詳細

## 1. 購入
公式Wikiに記載の信頼できるところから買うのが良さそうです。
　https://tinysa.org/wiki/pmwiki.php?n=Main.Buying

日本だとスイッチサイエンスさんから買えました。
　https://www.switch-science.com/products/9482?_pos=2&_sid=c7cd1c7c0&_ss=r

## 2. 最初に使う
### Updating the unit’s firmware (optional).
https://tinysa.org/wiki/pmwiki.php?n=Main.UpdatingTheFirmware
- [x]  firmwareのアップデート
    - [x]  ファーム `tinySA4_v1.4-156-g4eb315d.bin` をダウンロード
    - [x]  ジョグボタンを押しながら`Tiny SA ULTRA`のスイッチオン
    - [x]  ファームアップデート
        - [ココ](https://www.jh4vaj.com/archives/39971) の方法でcmdから.batを叩いたらインストールできた 
:::note warn
2024年3月30日　の時点では
[Tiny SA公式](https://tinysa.org/wiki/pmwiki.php?n=Main.UpdatingTheFirmware) のSTM32CubeProgrammer(Windows)を使う方法だとFirmUpに失敗するっぽい。
詳細は[groups.io/g/tinysaのスレ](https://groups.io/g/tinysa/topic/firmware_update/105195227?p=,,,20,0,0,0::recentpostdate/sticky,,,20,0,0,105195227,previd%3D0,nextid%3D1711656927719422839&previd=0&nextid=1711656927719422839)参照
:::
- [x] self test　本体タッチ　CONFIG > SELF TEST
- [x] Calibration  保体タッチ　CONFIG > LEVEL CAL

## ultra mode on
5GHzまで測定できるようになる。
Config > More > Enable Ultra > 4321を押して Enter

### Tyni SA App Windowsのツール
https://www-jh4vaj-com.translate.goog/archives/26473?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=ja
How to install ruby(rbenv) and npm on WSL2 as Ubuntu

apt でインストールしたらやたら古かったのでメモ

# 環境
- Windows 11 Pro
- wsl 2.2.4.0
- Ubuntu 22.04.4 LTS

# TODO
```shell
# rbenv and ruby

sudo apt-get install -y libssl-dev zlib1g-dev libyaml-dev
git clone --depth 1 https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'eval "$(~/.rbenv/bin/rbenv init - bash)"' >> ~/.bashrc
. ~/.bashrc

git clone --depth 1 \
  https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build 

rbenv install 3.3.1
rbenv global 3.3.1
gem update --system
gem update
gem cleanup

# npm and nodejs

curl -fsSL https://deb.nodesource.com/setup_20.x | \
  sudo -E bash - && sudo apt-get install -y nodejs
```

# 参考にしたサイト
[Ubuntu 22.04LTSへのNode.js 20のインストール - Jaybanuan's Blog](https://redj.hatenablog.com/entry/2024/02/20/011007)
Github Issueを立ててみる

GithubでIssueを立てる方法をおさらいします。

# 前提

自分で開発しているプライベートリポジトリに立てるIssueで、身内向けのもの。
（OSSというわけでもなく、ある程度気軽に書き込んで構わない。）

# GithubのIssueとは

>GitHub Issues は、作業を計画、議論、追跡するためにリポジトリで作成できる項目です。
issue は簡単に作成でき、さまざまなシナリオに合わせて柔軟に対応できます。 issue を使用して、作業の追跡、フィードバックの送受信、アイデアやタスクに関する共同作業、他のユーザーとの効率的なコミュニケーションを行うことができます。

https://docs.github.com/ja/issues/tracking-your-work-with-issues/about-issues

わかったような、わからないような……。

Issueとは、英語で

>〔議論すべき〕重要な話題［問題］、問題点、論点、争点

といった意味らしいです（参考：[英辞郎 on the web](https://eow.alc.co.jp/search?q=issue)）。

具体的には、リポジトリで、「ファイルの読み込みが極めて遅い」みたいな問題提起がされて、誰かがコードを変更してそれを解決したり、「いや、それはまだ対応しないんだ」ということでほっとかれたり、という感じに使われていると思います。

たとえば、misskey（オープンソースの分散型SNS）で立っているIssueがこんな感じです。

https://github.com/misskey-dev/misskey/issues

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/3b85f19e-94a5-a969-312f-c4d99f185c0d.png)

バグのほか、「こういう機能を足してほしい」みたいな要望なんかもあげられています。
（覗いてみるのは、ちょっと楽しい。）

# 自分のリポジトリにIssueを立ててみる

Githubのリポジトリの右上あたり、New issueからIssueを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/525e0444-dd2e-5028-7ddf-c032bbf883ac.png)

タイトルと内容を書きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/7710ad87-9ef0-3d6e-92b8-7dc545da161c.png)

マークダウンが使えます。
ほか、Issueのテンプレートを使用することもできるらしいのですが、今回は身内だしそんなにかっちりしたものでなくてよいので使用しません。

とはいえ、ラベルくらいははっておくことにしましょうか。
とりあえず、機能ではないので、「enhancement」でしょうか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/3b370164-8944-8300-8234-bc394498f9ec.png)

これでOK。
＃で、通し番号が付与されます。

Open＝未対応のIssueということです。
コードを改造して対応したら、右下のClose IssueでIssueを閉じます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/df0fa975-6c9e-2474-b6cd-3679c943abaf.png)

## 発展：コミットメッセージによるIssueの自動クローズ

Issueを解決するコードをコミットする際に、コミットメッセージに「fixes #番号」と記述すると、勝手にCloseしてくれます。

例えば、Issue番号が123の場合、コミットメッセージは以下のようになります。

```
git commit -m "fixes #123 Added caching to improve loading speed"
```

コミットがマスターブランチやメインブランチにマージされると、コミットメッセージに記述されたIssueが自動的に閉じられます。

- close
- closes
- closed
- fix
- fixes
- fixed
- resolve
- resolves
- resolved

英単語なので、これのために、私は
`〇〇に対応しました。 fix #123`
みたいなコミットメッセージにしています。

楽なやり方を模索中です。

https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#closing-an-issue-using-keywords

## Issueの削除

Issueは立てるのは簡単ですが削除には権限が必要で、権限がないとたとえ自分の作ったリポジトリのものでも削除できません（組織アカウントのポリシーによる）。
その場合、それとわかるコメントをつけて、Closeしてみなかったことにするしかないようです。