OmniAICreator/Qiita-1.07M huggingface dataset:
[GitHub Actions] 特定の文字列を含むブランチ名にエラーを叩きつける

## この記事が役立つかもしれない人
* 特定の文字列を含むブランチ名を使って欲しくない場合
  * ビルド時の都合でブランチ名に特定の文字列を含めず作成して欲しい！ 等
* Rulesets を使いたかったけど何らかの理由で使えないので代替手段が知りたい人

## 結論
ワークフローファイルとシェルスクリプトを作成し、push されたブランチ名が禁止リストにあるパターンを含んでいるかどうかをチェックします。
```bash:ディレクトリ構造
.
└── 📁 .github
    └── 📁 workflows
        ├── 📄 check-branch-name.yml
        └── 📁 scripts
            └── 📄 check-prohibited-branch-name.sh
```
```yaml:check-branch-name.yml
name: Check Branch Name
on: [push]
jobs:
  check-prohibited-branch-name:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        prohibition:
          - pattern: "{ここに禁止したい文字列を入力}"
    steps:
      - name: Check out the repository
        uses: actions/checkout@v4

      - name: Validate branch (not include "${{ matrix.prohibition.pattern }}")
        run: |
          chmod +x .github/workflows/scripts/check-prohibited-branch-name.sh
          .github/workflows/scripts/check-prohibited-branch-name.sh ${{ github.ref_name }} ${{ matrix.prohibition.pattern }}
```
```bash:check-prohibited-branch-name.sh
#!/bin/sh

# 引数で受け取ったブランチ名と禁止パターンを変数に格納
branch_name=$1
prohibited_name=$2

echo "Checking branch name: $branch_name"

# ブランチ名に禁止パターンが含まれているかチェック
if echo "$branch_name" | grep -qE "$prohibited_name"; then
  echo "Error: branch name cannot include '$prohibited_name'."
  exit 1
fi

echo "Branch name is valid."
```

### 実行結果
prohibition-word という文字列を禁止パターンとして設定した上で、prohibition-word というブランチを作成すると Actions にエラーが出力されます。

![prohibition-word という文字列を禁止パターンとして設定した上で prohibition-word というブランチを作成して push した様子](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2038389/f392e8c4-0f77-82f8-bda5-40d39067eab7.png)

なお判定は禁止パターンを含んでいるか？で行っているため、ブランチ名が `prohibition-word-hoge` の場合でも同様にエラーが出力されます。


## 解説
GitHub Actions お馴染みの yaml ファイルからシェルスクリプトを呼び出しています。

```yml
run: |
  # check-branch-name.sh が実行できるように権限を付与
  chmod +x .github/workflows/scripts/check-branch-name.sh
  # 実行
  .github/workflows/scripts/check-branch-name.sh ${{ github.ref_name }} ${{ matrix.prohibition.pattern }}
```

シェルスクリプトには `github.ref_name` と `matrix.prohibition.pattern` という値を渡しています。

それぞれ `github.ref_name` には push されたブランチ名、`matrix.prohibition.pattern` には `matrix` で指定した禁止したい文字列が入っています。

これらを用いて push されたブランチ名が禁止されたパターンを含むかどうか判定し、もし `github.ref_name` に `matrix.prohibition.pattern` が含まれていた場合はスクリプトを停止してエラーを返します。


### 複数の禁止名を設定する方法
複数の禁止名を設定したい場合は `matrix` で複数定義することが可能です。

```yml
matrix:
  prohibition:
    - pattern: "sample1"
    - pattern: "sample2"
    - pattern: "sample3"
```

これによりチェック対象のブランチ名が複数の禁止パターンのいずれかに一致した場合にエラーを返します。

---

GitHub Actions を使用して特定の文字列を含むブランチ名を禁止する方法を解説しました。
この記事が役に立ったら 🩷 を頂けると嬉しいです！
ChatGPT: Julia で、PostgreSQL のテーブルを Dataframe に読み込む方法

[ChatGPT](https://chatgpt.com/)に次の問を出しました。

```text
Julia で、PostgreSQL のテーブルを Dataframe に読み込む方法
```

この質問だけで、サンプルのコードが出てきました。

## 結果を修正したプログラム

```jl:chatgpt.jl
#! /snap/bin/julia

using DataFrames, LibPQ

# PostgreSQLへの接続情報を設定
# conn = LibPQ.Connection("dbname=city user=scott password=tiger123")
conn = LibPQ.Connection("postgresql://scott:tiger123@localhost/city")

# クエリの作成
query = "SELECT * FROM cities"

# クエリを実行して結果を取得
result = LibPQ.execute(conn, query)

# 結果をDataframeに変換
df = DataFrame(result)
println(df)

# PostgreSQLとの接続を閉じる
# LibPQ.finish(conn)
close(conn)

# 最初の数行を表示してみる
println(first(df, 5))
```

## 実行結果

```text
$ ./chatgpt.jl 
9×4 DataFrame
 Row │ id       name     population  date_mod   
     │ String?  String?  Int32?      Date       
─────┼──────────────────────────────────────────
   1 │ t3461    広島          25176  2003-09-24
   2 │ t3462    福山          47935  2003-05-15
   3 │ t3463    東広島        28654  2003-02-08
   4 │ t3464    呉            83152  2003-10-09
   5 │ t3465    尾道          42791  2003-08-04
   6 │ t3466    竹原          35687  2003-01-21
   7 │ t3467    三次          81296  2003-07-23
   8 │ t3468    大竹          21764  2003-10-26
   9 │ t3469    府中          75423  2003-12-15
5×4 DataFrame
 Row │ id       name     population  date_mod   
     │ String?  String?  Int32?      Date       
─────┼──────────────────────────────────────────
   1 │ t3461    広島          25176  2003-09-24
   2 │ t3462    福山          47935  2003-05-15
   3 │ t3463    東広島        28654  2003-02-08
   4 │ t3464    呉            83152  2003-10-09
   5 │ t3465    尾道          42791  2003-08-04
```
【第２回】Raspberry Pi Imagerにssh接続を接続を試みたときに、出会ったエラーやヒントの共有

# 前回記事
https://qiita.com/nami_fumi/items/b51d515a0866f2b44002

# 目次
- 小技
    - microSDを空にするときの注意
    - ※※ 64bitなのか、32bitなのかで違います！！
- エラー2
    - UserNameを変えたときに出くわしたエラーについて

# 小技　microSDを空にするときの注意

ssh接続を間違えたり、ラズパイをリセットしたいときはmicroSDの中身を空にしたくなりますよね？

このとき、適切なフォーマットを選択して空にする必要があります。
適切なフォーマットは以下の通りです。

* **32GB以下のSDカードの場合:** 「MS-DOS(FAT)」を選択
* **64GB以上のSDカードの場合:** 「exFAT」を選択

間違ったフォーマットを選択すると、SDカードが正常に使用できなくなる可能性があります。

詳しくは、参考資料１つ目を参照してください！
microCDを削除するのにおすすめの記事です！

# エラー　UserNameを変えたときに出くわしたエラー

ラズパイにSSH接続しようとしたら「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」と表示されて接続できない・・・

![スクリーンショット 2024-06-16 21.59.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3769985/3c3c22a4-ddb5-5c54-2a1f-388e58b01fa4.png)

## このエラーが発生する事象
リモートホスト（接続先のラズパイ）の公開鍵が変更されたときに発生します。
私の場合では、プライベートIPアドレスは同じなのに、ユーザー名を変更したときに発生しました！

## 解決策
原因としては、OSの再インストールや、SSHサーバの設定変更などが挙げられます。
セキュリティ上、以前の接続時に保存された公開鍵と異なる場合は接続が拒否されます。
そのため、**known_hostsファイルから、該当するリモートホストの情報を削除** する必要があります。


 -  以下の手順でknown_hostsファイルを編集

```terminal
ssh-keygen -R  {自分のラズパイのプライベートIPアドレス}
```

```
ssh {新しいユーザー名}@192.168.〜
```

 -  「Are you sure you want to continue connecting (yes/no/[fingerprint])?」と表示されたら、「yes」と入力します。

 - いつも通りのパスワードを入力して接続


# 次回
VNCをつかって、ラズパイデスクトップに接続する方法を共有します！

# 参考資料

* [SDカードがMacに認識されない問題の解決策](https://4ddig.tenorshare.com/jp/mac-problems/solution-for-sd-card-not-recognized-by-mac.html#part1)
* [Mac上におけるSDカードの場所](https://qiita.com/WaterMelonEel/items/92de0c641571370074c8)
* [「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」と出たときの対処法](https://www.niandc.co.jp/tech/20150729_2464/)
統計学において推定量の良し悪しって何だろうをわかりやすくまとめてみた

## キーワード
- 一様最小分散推定量
- 有効推定量
- 不偏性
- 一致性
- 漸近有効性
- フィッシャー情報量
- クラーメル・ラオの不等式

# はじめに
統計学を学んでいると序盤の方に出てくる点推定量周りの用語をまとめた。

# 目的
この記事では以下の言葉を自分の言葉で説明できることを目的としている。
・一様最小分散推定量
・有効推定量
・一致性
・漸近有効性

# 不偏推定量
まず、不偏推定量が何かを説明する。（理解している人は飛ばして問題ない）
不偏推定量とは推定量の期待値が母数と一致する（この性質を不偏性という）推定量のことである。つまり、$\hat{\theta}$が不偏推定量であるとは次式が成り立つことということである。
``` math
\mathrm{E}[\hat{\theta}]=\theta
```
例えば、母集団からn個をランダムサンプリングして、その標本平均$\bar{x}$で母集団の平均（母平均）$\mu$を推定する場合を考える。
``` math
\bar{x} = \frac{1}{n} \sum_{i=1}^{n}x_i
```
推定量$\bar{x}$の期待値を求める。
``` math
\begin{align}
\mathrm{E}[\bar{x}] &= \mathrm{E}[\,\frac{1}{n} \sum_{i=1}^{n}x_i\,]\\
&= \frac{1}{n}\sum_{i=1}^{n}\mathrm{E}[\,x_i\,]\\
&=\frac{1}{n}\sum_{i=1}^{n}\mu \\
&=\mu
\end{align}
```
よって、標本平均の期待値は母平均と一致するので、$\bar{x}$は不偏推定量である。
一方で標本分散$v$は期待値が母分散$\sigma$に一致しない。$\mathrm{E}[v]$を計算すると
``` math
\mathrm{E}[v] = \frac{n-1}{n}\sigma
```
となる。点推定では不偏性を持った推定量として下の不偏分散を標準分散の代わりに利用することが多い。
``` math
\hat{\sigma} = \frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar{x})^2
```
また、不偏分散と標準分散を区別するために、不偏分散を$\hat{\sigma}$で標本分散を$s^2$で表す。

# 推定量の期待値と分散の気持ち
推定量の期待値や分散と急に言われてもその意味が捉えにくいかもしれない。
同じ母集団に対してn回サンプリングを行いそれぞれの標本データを用いて推定を行うとn個の推定量を得られる。このn個の推定量の期待値や分散のことを推定量の期待値や分散という。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798972/1e53a2f6-722d-5244-f0d9-6114f52f6f92.png)
したがって、推定量の分散は小さい方が好ましい。標本によって得られる推定量がバラバラでは、うまく母数を推定できているとは言えないからだ。

# 一様最小分散不偏推定量
推定の方法はさまざまであり、不偏推定量も複数考えることができる。つまり、ある母数の不偏推定量と言われても解が複数考えられるのだ。一様最小分散不偏推定量はそんな不偏推定量の中で分散が最小になるものを指す。

# 有効推定量
では、分散が最小化どうかの確認はどのようにすればいいのか。その疑問に答えるのがクラーメル・ラオの不等式だ。
``` math
\mathrm{V_\theta}[\hat{\theta}] \ge J_n(\theta)^{-1}
```
これは$\theta$の不偏推定量$\hat{\theta}$をどのように選んでも$J_n(\theta)$の逆数より小さくはならないということを意味している。$J_n(\theta)$はフィッシャー情報量と呼ばる。(クラーメル・ラオの不等式とフィッシャー情報量の詳細については割愛する。)
また、クラーメル・ラオの不等式の等式を満たす不偏推定量を有効推定量という。つまり、有効推定量であれば一様最小分散不偏推定量である。ただし、等式を満たす不偏推定量が存在しないような確率分布では有効推定量は存在しないので、一様最小分散不偏推定量なら有効推定量であるとは言えない。

# 一致性
直感的に標本のサイズが大きくなればなるほど、推定量が母数に近づく気がする。例えば、5人の日本人男性の平均身長よりも1000人の平均身長を日本人男性全体の平均身長と考える（つまり、推定する）方が適切であろう。この直感が成り立つことを一致性を持つという。これは推定値$\hat{\theta}$が真のパラメータ値$\theta$に確率収束すると言える。したがって、任意の$\varepsilon$を用いて次式で表せる。
``` math
\lim_{n \to \infty}	P(|\hat{\theta}-\theta|\lt\varepsilon) = 1
```

# 漸近有効性
フィッシャー情報量は標本が独立同一である場合$J_n(\theta)=nJ_1(\theta)$となる。この時、クラーメル・ラオの不等式は次式のように書き換えられる。
``` math
V_\theta[\hat{\theta}] \ge \{n J_1(\theta)\}^{-1}
```
一致推定量の分散が漸近的にクラーメル・ラオの不等式の下限に近づくとき、つまり、
``` math
\lim_{n\to\infty}V_\theta[\hat{\theta}] = J_n(\theta)^{-1} =\frac{1}{nJ_1(\theta)}
```
を満たすような一致推定量$\hat{\theta}$を漸近有効性を持つという。

# まとめ
今回は推定量に関する用語の意味の説明を通して、優れた推定量とは何かについてまとめた。押さえておきたいポイントを以下に示す。
- 不偏性・不偏推定量
推定量が不偏性を持つとは、推定量の期待値が母数と一致するということ。この時、この推定量は不偏推定量であるという。
- 優れた推定量
優れた推定量はその分散が小さいもの。
- 一様最小分散不偏推定量
分散を最小化する不偏推定量
- 有効推定量
クラーメル・ラオの不等式の等式を満たす不偏推定量。有効推定量ならば一様最小分散不偏推定量である。
- 一致性
標本サイズを大きくしていった時に、母数に収束する性質
- 漸近有効性
標本サイズを大きくしていった時に推定量の分散がクラーメル・ラオの不等式の下限に漸近的に近づくこと。

# 最後に
用語が多く出てきて、はじめは混乱するかもしれない。敢えて難しい部分は省略したので概要を押さえる気持ちで読んでもらえるとありがたい。（そのため、クラーメル・ラオの不等式などでは厳密性にかける箇所があるので、追加で調べてもらえると良いと思う。）

# 参考文献
統計学実践ワークブック（準一級）　日本統計学会　編
wrtn: Julia で、PostgreSQL のテーブルを Dataframe に読み込む方法

[リートン](https://wrtn.jp/)に次の問を出しました。

```text
Julia で、PostgreSQL のテーブルを Dataframe に読み込む方法
```

続けて次の依頼をしました。

```text
サンプルのプログラムを示して下さい。
```

## 結果を修正したプログラム

```jl:wrtn.jl
#! /snap/bin/julia

using DataFrames, LibPQ, CSV

println("*** start ***")
# PostgreSQLに接続
#conn = LibPQ.Connection("host=localhost port=5432 user=scott password=tiger123 dbname=city")
conn = LibPQ.Connection("postgresql://scott:tiger123@localhost/city")

# テーブル"mytable"のデータをDataFrameに読み込む
# df = DataFrame(conn, "SELECT * FROM cities")
df = DataFrame(execute(conn, "SELECT * FROM cities"))

# DataFrameの内容を確認
println(df)

# DataFrameの列名を表示
println(names(df))

# DataFrameの行数と列数を表示
println("Rows: $(size(df, 1)), Columns: $(size(df, 2))")

# DataFrameの特定の列を抽出
col1_data = df[:, 1]
col2_data = df[:, "name"]

# DataFrameの特定の行と列を抽出
row1_col1 = df[1, 1]
println(row1_col1)
row2_col2 = df[2, "name"]
println(row2_col2)

# DataFrameの加工
#df[!, "new_col"] = df[:, "id"] .+ df[:, "name"]
df = df[df[:, "population"] .> 50000, :]
println(df)

# DataFrameのデータをCSVファイルに書き出す
CSV.write("output.csv", df)
```

## 実行結果

```text
$ ./wrtn.jl 
*** start ***
9×4 DataFrame
 Row │ id       name     population  date_mod   
     │ String?  String?  Int32?      Date       
─────┼──────────────────────────────────────────
   1 │ t3461    広島          25176  2003-09-24
   2 │ t3462    福山          47935  2003-05-15
   3 │ t3463    東広島        28654  2003-02-08
   4 │ t3464    呉            83152  2003-10-09
   5 │ t3465    尾道          42791  2003-08-04
   6 │ t3466    竹原          35687  2003-01-21
   7 │ t3467    三次          81296  2003-07-23
   8 │ t3468    大竹          21764  2003-10-26
   9 │ t3469    府中          75423  2003-12-15
["id", "name", "population", "date_mod"]
Rows: 9, Columns: 4
t3461
福山
3×4 DataFrame
 Row │ id       name     population  date_mod   
     │ String?  String?  Int32?      Date       
─────┼──────────────────────────────────────────
   1 │ t3464    呉            83152  2003-10-09
   2 │ t3467    三次          81296  2003-07-23
   3 │ t3469    府中          75423  2003-12-15
```

出力された　csv

```text:output.csv
id,name,population,date_mod
t3464,呉,83152,2003-10-09
t3467,三次,81296,2003-07-23
t3469,府中,75423,2003-12-15
```
GPTs用ガイド生成プロンプト

ChatGPTのカスタマイズ機能で作られたGPTs（カスタムGPT）の使い方が分かりづらいというご意見を頂きまして、ユーザビリティ改善のために「AI本人に自分の使用方法をガイダンスさせるプロンプト」を考えてみました。

GPTsとは、システムプロンプト、知識、アクションによってChatGPTをカスタマイズし、オリジナルのAIアプリを作成・公開できる機能です。便利だったり面白かったり専門的だったりと、スマホアプリのように多種多様なAIアプリを無料で利用できます。

ただ、それぞれのカスタムGPTがどんな特徴を持っていて、どう使えばいいのか分かりづらいことがネックでした。それを解決するためのプロンプトです。

こちらのプロンプトを各種カスタムGPTに送ると、丁寧な利用ガイドを提供してくれます。

```java
こんにちは。あなたの使用方法を日本語で詳しく教えてください。具体的な指示の出し方や、どのような指示や情報を提供すれば良いか、ステップバイステップで説明してください。また、どのような利用方法が効果的か例も挙げてください。
```

ChatGPTの「GPT Store」で公開されている多くのAIアプリで有効だと思います。ぜひお試しください。

本家GPT Storeは探しづらいので、GMOが運営する「教えてAI」をおすすめします。

https://oshiete.ai/

OpenAI公式のGPT Storeはこちら

https://chatgpt.com/gpts

疑似人格プロンプトの名手、Sharaku Satoh作のカスタムGPTはこちら

https://oshiete.ai/profiles/F5smI1a55WeeZ0aKHaa9n24
Command-R+: Julia で、PostgreSQL のテーブルを Dataframe に読み込む方法

[Command R+](https://huggingface.co/spaces/CohereForAI/c4ai-command-r-plus) に次の問を出しました。

```text
Julia で、PostgreSQL のテーブルを Dataframe に読み込む方法
```

続けて次の依頼をしました。

```text
サンプルのプログラムを示して下さい。
```

## 結果を修正したプログラム

```jl:commandr.jl
#! /snap/bin/julia

# using Pkg
# Pkg.add("LibPQ")
# Pkg.add("DataFrames")

using LibPQ
using DataFrames

# データベースへの接続情報
db_url = "postgresql://scott:tiger123@localhost/city"

# データベースに接続
conn = LibPQ.Connection(db_url)

# テーブル名を指定
table_name = "cities"

# テーブルを Dataframe に読み込む
df = DataFrame(execute(conn, "SELECT * FROM $table_name"))

# Dataframe の先頭 6 行を表示
println("先頭 6 行のデータ:")
println(first(df, 6))
println()

# Dataframe の列名を表示
println("列名:")
println(names(df))
println()

# Dataframe の行数と列数を表示
println("データのサイズ: $(size(df))")
println()

#
num_high_population = count(row -> row[:population] >= 50000, eachrow(df))
println("人口が 50000 以上の都市の数: $num_high_population")
println()

# データベースとの接続を閉じる
close(conn)
```

## 実行結果

```text
$ ./commandr.jl 
先頭 6 行のデータ:
6×4 DataFrame
 Row │ id       name     population  date_mod   
     │ String?  String?  Int32?      Date       
─────┼──────────────────────────────────────────
   1 │ t3461    広島          25176  2003-09-24
   2 │ t3462    福山          47935  2003-05-15
   3 │ t3463    東広島        28654  2003-02-08
   4 │ t3464    呉            83152  2003-10-09
   5 │ t3465    尾道          42791  2003-08-04
   6 │ t3466    竹原          35687  2003-01-21

列名:
["id", "name", "population", "date_mod"]

データのサイズ: (9, 4)

人口が 50000 以上の都市の数: 3
```
Koka で Welcome to AtCoder を解いてみた

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)
において、約1ヶ月で38記事という大量の記事の投稿を要求されることがわかった。
そこで、あまりコストをかけずに記事数を稼ぐ方法を考えた結果、「Welcome to AtCoder を様々な言語で解く」ことを思いついた。
単に解くだけでなく、使用する言語仕様の解説を入れれば、記事として一応成立するだろう。

# Welcome to AtCoder

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

Welcome to AtCoder では、以下の形式で整数 $a$, $b$, $c$ および文字列 $s$ が入力として与えられる。

```text
a
b c
s
```

この入力をもとに、与えられた整数の和 $sum = a + b + c$ および文字列 $s$ を、以下の形式で出力することが求められる。

```text
sum s
```

# 今回用いた Koka の機能

## エントリポイント

[3.1.1. Hello world](https://koka-lang.github.io/koka/doc/book.html#sec-hello-world)

以下のように `main` 関数を作ることで、これを呼び出してコードを実行してもらえる。

```
fun main()
  // 処理内容
```

## 変数宣言

関数内で

```
val 変数名 = 値
```

と書くことで、「変数名」に「値」を割り当てることができる。

## 標準出力

[std/core/console documentation](https://koka-lang.github.io/koka/doc/std_core_console.html)

```
println(値)
```

と書くことで、「値」を標準出力に出力し、さらに改行を出力できる。

## 標準入力

[std/os/readline documentation](https://koka-lang.github.io/koka/doc/std_os_readline.html)

```
readline()
```

により、標準入力から1行 (1023文字まで) 読み込み、文字列として得ることができる。
得られる文字列に改行文字は含まれない。

これを用いる場合は、プログラムの先頭に

```
import std/os/readline
```

と書くべきようである。
これを書かないと、

> error: identifier readline cannot be found

というエラーになってしまった。

## リストの処理

[std/core/list documentation](https://koka-lang.github.io/koka/doc/std_core_list.html#_null_)

```
head(リスト)
```

により、「リスト」の最初の要素を得られる。
返り値の型は、「リスト」の要素の型が `a` だとすると、`maybe<a>` となる。

```
tail(リスト)
```

により、「リスト」から最初の要素を取り除いたリストを得られるようである。

## 整数の処理

`a + b` により、`a` と `b` の和を求めることができる。

[std/core/int documentation](https://koka-lang.github.io/koka/doc/std_core_int.html#_null_)

```
parse-int(文字列)
```

により、「文字列」をそれが表す整数に変換できる。
結果は `maybe<int>` 型で返る。

```
mbint(値)
```

により、`maybe<int>` 型の「値」を `int` 型に変換できる。

```
show(値)
```

により、「値」を文字列に変換できる。

## 文字列の処理

`""` で囲むことで、文字列を表現できる。

[std/core/string documentation](https://koka-lang.github.io/koka/doc/std_core_string.html#_null_)

```
string(値)
```

で、`maybe<string>` 型の「値」を `string` 型に変換できる。

```
split(対象, 区切り)
```

で、「対象」の文字列を「区切り」の文字列で区切った文字列のリストを得ることができる。

```
join(リスト)
```

で、文字列の「リスト」に格納された文字列を結合した文字列を得ることができる。

# 提出コード

```
import std/os/readline

fun main()
  var astr := readline()
  var bcstr := readline()
  var s := readline()
  var a := mbint(parse-int(astr))
  var bclist := split(bcstr, " ")
  var b := mbint(parse-int(string(head(bclist))))
  var c := mbint(parse-int(string(head(tail(bclist)))))
  println(join([show(a + b + c), " ", s]))
```

[提出 #55001709 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/55001709)
The above error occurred in the <componentName> componentエラーが発生した

## The above error occurred in the InputForm(コンポーネント名 component　エラー解決について

# エラーの意味
上記のエラーはInputForm（コンポーネント名）で発生しました。

# 問題の原因
propsを受け取る際の定義の仕方でオブジェクトの分割代入ができていなかった。
⇒プロパティを取り出すところで配列の書き方をしていた。

# エラーが発生する原因になっている箇所
```InputForm.jsx
 const [studyContentForm, studyTimeForm]=props;
```
# 画面を表示しているファイル
```App.jsx
const [studyContent, setStudyContent] = useState("");
const [studyTime, setStudyTime] = useState("");
return (
    <>
    <InputForm studyContentForm={studyContent}/>
    <InputForm studyTimeForm={studyTime}  />
    </>
  );

```
# エラー解決策
* コンポーネントをpropsで受け取り時にオブジェクトの分割代入をするときには｛｝の中にpropsのプロパティを入れる必要がある。
```InputForm.jsx
const {studyContentForm, studyTimeForm}=props;
```
Appファイルは上記のファイルと同じため省略します。

## さいごに
今回は正しくオブジェクトを分割代入できていなかったことによりエラーが発生したので
エラー発生時にはまず始めに正しい書き方ができているかを確認した方がよいと感じた。
【読書記録】「良いコード/悪いコードで学ぶ設計入門」を読んで

## 読んだ本
「良いコード/悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方」

https://amzn.asia/d/0e5N8bUZ

## 本の感想

「保守性の高いコードとは？どのような状態を保守性が高いと言えるか？」を明確にしてくれる本でした。

15章の「理想形を知って初めて課題を知覚できる」の言葉の通り、まずは理想形をしっかりと学ぶ必要があると痛感しました。

## 特に印象に残ったこと

### クラス

- クラスが単体で正常動作するよう設計する
- クラスが果たす目的は、たったひとつに限定すべき（単一責任=単一目的）
- 良いクラスの構成要素は「インスタンス変数」「インタンス変数を不正状態から防御し、正常に操作するメソッド」
- 自分の身は自分で守らせる。自己防衛責務を全てのクラスが備える
⇒ 不正値の混入を防止するためのバリデーションをコンストラクタ内に定義する
- 継承は注意して扱う
    - 継承関係にあるクラス同士では、サブクラスはスーパークラスの構造に酷く依存するため
    継承より委譲が推奨される。委譲とは、コンポジション構造にすること。


### 関数

- 関数が影響を受ける・与える範囲を限定する。関数が以下項目を満たすことを前提に設計する
    - データ、つまり状態を引数で受け取る
    - 状態を変更しない
    - 値は関数の戻り値として返す
- staticメソッドはデータとデータを操作するロジックをバラバラに定義可能な構造であり、低凝集に陥りがち
    - staticメソッドの使いどき: 凝集度に影響がない場合。例えばログ出力用メソッドやフォーマット変換用メソッドなど
- 共通処理クラス（Common・utilなど）を安易に作らないようにする
横断的関心ごとならまとめてOK（ログ出力・エラー検出・デバッグ・例外処理など）
- アンチパターン
    - 良くない1: 多すぎる引数
    引数の量が多いということは、すなわちそれだけ処理させたい内瑤が膨らむため。
    概念的に意味のある単位ごとにクラス化する
    - 良くない2: メソッドチェイン
    ドットで数珠つなぎにして戻り値の要素に次々にアクセスする書き方により多くの要素にあらゆる箇所からアクセス可能で、影響範囲がいたずらに拡大可能な構造のため
- ポリシークラスにルールを集約する
- 引数
    - フラグ引数は使わない（機能ごとにメソッドを分離する）
    - nullを渡さない
    - 引数は可能な限り少なく
- エラーは戻り値で返さない、例外をスローすること

### 共通

- nullが入り込む前提でロジックを組むと、至る所でnullチェックをしなければいけなくなる。nullの代わりに`empty`を使う
- 疎結合高凝集にする
    - 密結合を解消し、疎結合高凝集にするためには関心の分離「関心事、つまりユースケースや目的、役割ごとに分離する」が重要
- 可能な限り具体的で意味範囲が狭い、目的に特化した名前を選ぶ

## 覚えておきたいワード

### 凝集度

モジュール（クラス、パッケージ、レイヤーなど）内における、データとロジックの関係性の強さを表す指標

密接に関係し合うロジックが１箇所にぎゅっと集まっている高凝集な構造が良い

### 結合度

モジュール（クラス等）間の依存の度合いを表す指標
疎結合な設計が良い

### 完全コンストラクタ

不正状態から防護するための設計パターン
生成された段階で正常な値だけを持つ完全なコンストラクタを生成する

### 値オブジェクト Value Object

値の概念そのものをクラス（型）として表現する。
値オブジェクトと完全コンストラクタは得たい効果が近いためほぼセットで用いられる。

### デメテルの法則

利用するオブジェクトの内部を知るべきではない。「知らない人に話しかけるな」
格言：尋ねるな、命じろ（Tell, Don't Ask）
他のオブジェクトの内部状態（変数）を訪ねたり、その状態に応じて呼び出し側が判断したりするのではなく、呼び出し側はただメソッドで命ずるだけで、命令された側で適切な判断や制御をするよう設計する。
詳細なロジックは呼ぶ側ではなく、呼ばれる側に実装する。

### YAGNI原則

You aren’t going to need it. 実際に必要になったときにのみ実装せよ、という方針

### 目的駆動名前設計

ソフトウェアで達成したい目的をベースに名前を設計（命名）する。名前から目的や意図が読み取れることを特徴とする。

### クラスベース

データとそのデータを操作するロジックをクラスにひとまとめにし、プログラムの構造を定義していく手法。クラスが構造の基本単位となる。

### コンポジション
https://qiita.com/turanukimaru/items/0b1396393908b7e22618

## 学ぶ必要があると感じたこと

本を読んで理解が浅いと感じたことを、次の勉強のためにメモします。

- 値オブジェクト・データクラスについて
エンジニア向けおすすめ Podcast

# はじめに
この記事では、自分が思うエンジニア向けおすすめ Podcast を紹介します。

# Qiita FM

https://open.spotify.com/show/4E7yCLeCLeQUsNqM4HXFXA

よいしょしている訳ではないです。毎回色々なエンジニアをゲストに招いて、技術やキャリアについて話しています。

# fukabori.fm
https://fukabori.fm/

こちらも毎回ゲストを招いて、技術・組織・マネジメントなどについて話しています。ラジオパーソナリティの iwashi さんの深掘力がすごく、聴いていて気になった点はだいたい深堀って質問してくれています。

# EM.FM

https://open.spotify.com/show/0lpI8cSWxiDH4Eza1A8SSk

エンジニアマネージャーをしている3人の方々がエンジニアマネージャーに関するトピックを話しています。

# ふりかえりam

https://open.spotify.com/show/1MvWCMmcH3zy0LJ6vERTi9

最近更新されていないですが。様々なふりかえり手法を試しているので、ふりかえりカイゼンの参考にしています。

# zenncast

https://zenncast-web.vercel.app/

ここに載せてよいかわからないです。

# ゆるコンピュータ科学ラジオ

https://open.spotify.com/show/32qgIhAHYnseWxiGyrFzSt

ゆるく楽しくコンピューター科学を学べます。脱線多めです（笑）

# おまけ
エンジニアと直接関係ないですが、自分がよく聴いている Podcast も紹介します。

## COTEN RADIO

https://coten.co.jp/services/cotenradio/

メタ認知 ホモサピエンス ライジング

## ゆる言語学ラジオ

https://yurugengo.com/

ケレスとバッカスがいないとヴィーナスは凍えてしまうよね

# 最後に
Podcast はながらでインプットできるので、おすすめです！自分は家事やランニング、散歩、ドライブ中に聴いています。
面白い Podcast 見つけたら随時追加していきます。
「curl: (3) bad range in URL」エラーの解決方法

curlの実行で「curl: (3) bad range in URL」というエラーが出て困った時の対処方法です。

## 現象

以下のようなcurlコマンドを実行すると `curl: (3) bad range in URL position 55:` というエラーが発生しました。

```bash
$ curl -X GET "http://localhost:3000/hogeapi/search?sort[column]=code&sort[direction]=asc" -H "accept: application/json"
curl: (3) bad range in URL position 55:
http://localhost:3000/hogeapi/search?sort[column]=code&sort[direction]=asc
                                         ^
```

## 解決策

`--globoff` オプションを追加する。

```bash
curl --globoff -X GET "http://localhost:3000/hogeapi/search?sort[column]=code&sort[direction]=asc" -H "accept: application/json" -H "X-Request-ID: 99c15ac0-2fd8-4d16-bfe4-6b65b08e3077" -H "Accept-Language: ja-JP" -H "USER-ID: 1" -H "AUTHORITIES: \"[\"sys_admin\"]\""
```

## 原因

URLの `sort[column]` あたりでエラーになっているようでした。

クエリパラメータに特殊文字（`[` と `]` ）が入っており、 `curl` が自動的にエスケープ処理を行っていました。

 `-globoff` オプションを使うと、このエスケープ処理が無効化され、URL に含まれる特殊文字をそのまま使えます。

`curl` が特殊文字をファイルパスのワイルドカードとして解釈するのを防ぎます。
REACT  Memo

React.memo は、関数コンポーネントのメモ化を提供する高階コンポーネント（HOC）です。コンポーネントが同じプロパティ（props）で再レンダリングされるのを防ぐために使用します。これにより、パフォーマンスの向上を図ることができます。

#### React.memo の使用方法
以下は、React.memo の基本的な使用例です。

```
import React from 'react';

const MyComponent = ({ name }) => {
  console.log('Rendering MyComponent');
  return <div>Hello, {name}</div>;
};

// MyComponent をメモ化
const MemoizedComponent = React.memo(MyComponent);

const App = () => {
  return (
    <div>
      <MemoizedComponent name="John" />
      <MemoizedComponent name="John" />
    </div>
  );
};

export default App;

```
上記の例では、MyComponent が同じ name プロパティで2回レンダリングされますが、React.memo によって2回目のレンダリングはスキップされます。コンソールには「Rendering MyComponent」が一度だけ表示されます。

#### React.memo のカスタム比較関数
デフォルトでは、React.memo は浅い比較（shallow comparison）を行います。カスタム比較関数を提供することで、より複雑な条件で再レンダリングを制御することができます。

```
import React from 'react';

const MyComponent = ({ name, age }) => {
  console.log('Rendering MyComponent');
  return <div>Hello, {name}. You are {age} years old.</div>;
};

// カスタム比較関数
const areEqual = (prevProps, nextProps) => {
  return prevProps.name === nextProps.name;
};

// MyComponent をメモ化
const MemoizedComponent = React.memo(MyComponent, areEqual);

const App = () => {
  return (
    <div>
      <MemoizedComponent name="John" age={30} />
      <MemoizedComponent name="John" age={40} />
    </div>
  );
};

export default App;

```

この例では、カスタム比較関数 areEqual を使用して name プロパティのみを比較しています。age プロパティが異なる場合でも、name が同じであれば再レンダリングは行われません。コンソールには「Rendering MyComponent」が一度だけ表示されます。

>利点
不必要な再レンダリングを防ぎ、パフォーマンスを向上させる。
特にプロパティが頻繁に変更されないコンポーネントで有効。
>注意点
メモ化自体にコストがかかるため、すべてのコンポーネントに適用するのは逆効果。
状態やプロパティの変化が頻繁にある場合、効果が薄れることがある。
Praat scriptで空のvectorを作成する

Praat scriptの小ネタです。

空のvectorを作成しようとした場合、通常のリテラルの記法で書くとシンタックスエラーになってしまいます。

```praat
# 以下はエラーになる（symbol misplaced）
v# = {}
```

代わりに、ゼロ埋めされたvectorを生成する関数 `zero#` を使用することで作成できました。

```praat
# zero#: 全要素0のvectorを生成
# 引数に長さを指定可能なため、以下で長さ0 = 空のvectorが返ってくる
v# = zero#(0)

appendInfoLine(size(v#)) ; 0
```


(※ちなみに、`zero#` の本来の使い方は以下のように0埋めされたvectorの生成です)

```praat
# 長さ3のvector
appendInfoLine(zero#(3))
```

```
0 0 0
```
classic環境のまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)



+ [久しぶりにclassic環境にしてみたら...](https://qiita.com/Keiji_otsubo/items/a1e71bb8be0df694e56b)
+ [ログイン時のデフォルト画面が設定とは違って別画面にリダイレクトされる【未解決】](https://qiita.com/Keiji_otsubo/items/5bdb45b5200381184546)


# 既知の問題

+ [取引先の住所（請求先）にて郵便番号を入れての自動反映を行ったところ、都道府県部分だけが自動で取得ができないようになってしまいました。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000HDjUd)

:::note
ちょっと古い投稿ですが同じようなことが質問されています。
どちらもクラッシックなら機能してLightningでは機能しない点ではバグと言っています。
以下の投稿も示してサポートに確認した方がいいかもしれません。

Billing State/Province Code Is Not Carrying Forward On Lead Conversion
https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000A8bbESAR
:::

# ロールの新規追加ができない。

+ [ロールの新規追加ができない](https://qiita.com/Keiji_otsubo/items/3f6d6381cb4683e5c36f)

+ [issue with adding roles](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000HEM5aSAH)

画面もクラッシックに勝手に切り替わるらしい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b7b59b56-2aa3-52cb-61f9-e235e8cf2845.png)

# Conga Composer Button



以下は、クラッシックのみの対応。

+ [Conga Composer URL Examples](https://documentation.conga.com/composer/latest/conga-composer-url-examples-143198509.html)
+ [Anatomy of a Conga Composer Button](https://documentation.conga.com/composer/latest/anatomy-of-a-conga-composer-button-143198461.html)

# 切替の問題

+ [ライセンス変更に伴う画面変更について](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Tj19Q)

:::note
切り替えボタンについては、以下の制限があるみたいです。確かに弊社の環境を見ると2018年11月にUnlimited Editionで作成していますが、管理者以外はclassicに切り替えるリンクは表示されないですね。 

>2018 年 6 月 11 日以降、Sales Professional Edition および Services Essentials エディション用に作成されたすべての新しい組織は、デフォルトで Lightning に設定されます。

サポートで権限を変更してもらえば可能みたいなので、サポートに確認してみるのがいいかもしれません。 

>Salesforce でサポート ケースを開いて、組織の「ユーザーは Lightning のみ」権限を無効にすることができます。
 

https://salesforce.stackexchange.com/questions/346296/non-admin-user-cannot-switch-back-to-classic
:::
REACT Context (HOOK全記録の章既に紹介した)

# REACT Context
React Context は、React アプリケーションでグローバルにデータを共有するための方法です。これにより、プロパティを一つ一つ手動で渡すことなく、コンポーネントツリーの深くまでデータを渡すことができます。

以下に、React Context を使用する基本的な方法を説明します。

#### React Context の作成
まず、Context を作成します。以下の例では、UserContext を作成し、ユーザー情報をグローバルに共有します。

```
import React, { createContext, useState } from 'react';

// Context の作成
export const UserContext = createContext();

// Provider コンポーネント
export const UserProvider = ({ children }) => {
  const [user, setUser] = useState({ name: 'John Doe', age: 30 });

  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
};

```

#### Context Provider の使用
次に、Context Provider を使用して、アプリケーション全体または特定の部分にデータを提供します。

```
import React from 'react';
import { UserProvider } from './UserContext';
import UserProfile from './UserProfile';
import UserSettings from './UserSettings';

function App() {
  return (
    <UserProvider>
      <div>
        <h1>React Context Example</h1>
        <UserProfile />
        <UserSettings />
      </div>
    </UserProvider>
  );
}

export default App;

```

#### Context の使用
最後に、Context を使用してデータを取得します。useContext フックを使用して、Context にアクセスします。

```: UserProfile
import React, { useContext } from 'react';
import { UserContext } from './UserContext';

const UserProfile = () => {
  const { user } = useContext(UserContext);

  return (
    <div>
      <h2>User Profile</h2>
      <p>Name: {user.name}</p>
      <p>Age: {user.age}</p>
    </div>
  );
};

export default UserProfile;

```

```:UserSettings
import React, { useContext } from 'react';
import { UserContext } from './UserContext';

const UserSettings = () => {
  const { user, setUser } = useContext(UserContext);

  const handleNameChange = (e) => {
    setUser({ ...user, name: e.target.value });
  };

  return (
    <div>
      <h2>User Settings</h2>
      <input
        type="text"
        value={user.name}
        onChange={handleNameChange}
      />
    </div>
  );
};

export default UserSettings;

```

React Context は、プロパティドリリング（props drilling）を回避し、コンポーネント間でデータを効率的に共有するのに非常に便利です。Context を使用することで、グローバルな状態管理が簡単になり、コードの可読性とメンテナンス性が向上します。
【HTML / CSS】マージンとパディングの違いについて

## はじめに
学習したことを自分用の参考書のようにまとめていきます。

## マージン(margin)とパディング(padding)とは

どちらも要素のまわりの余白を指定するためのプロパティです。

下記のような違いがあります
- margin : 要素の**外側**の余白
- padding : 要素の**内側**の余白


https://developer.mozilla.org/ja/docs/Web/CSS/margin

https://developer.mozilla.org/ja/docs/Web/CSS/padding

## margin

marginを指定して要素の外側に余白を設定してみましょう！

下記画像はh1タグに幅・高さ・背景色だけを指定したものです。
※少し余白がありますが、リセットCSSを読み込んでいないのでデフォルトで設定されている分です。

![スクリーンショット 2024-06-29 7.53.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459296/15e1ebca-3575-3771-e9ba-670ca2059758.png)

h1タグに" margin: 50px; "を追加してみましょう！

すると、下記のように要素の外側に余白ができるはずです。

![スクリーンショット 2024-06-29 7.54.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459296/6471e222-81c2-1ea0-24c7-aa9f468a46f7.png)




## padding

次にpaddingを指定して要素の内側に余白を設定してみましょう！

先程h1タグに" margin: 50px; "と指定していたところを " padding: 50px "に変更すると下の画像のように外側の余白がなくなり、内側に余白ができます。

![スクリーンショット 2024-06-29 8.08.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459296/6217a47a-cce5-4f6a-e1c4-233232055d4a.png)


## さいごに
いかがだったでしょうか。

他にもいろいろな記事を書いているのでぜひ読んでいただけたら嬉しいです。
React前に押さえておくべきJavaScript知識

## アロー関数でオブジェクトを返す時
丸括弧の中にオブジェクトリテラルを書く

```js
const fn = num => ({ result: num });
```

## mapメソッドのコールバック関数の引数について
map() は Array インスタンスのメソッドで、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。

```js
const arry = [10, 20, 30, 40];
const newArry = arry.map((val, i, arry) => val * 2);
// val: 配列内で現在処理中の要素
// i: 現在処理中の要素の配列内における添字
// arry: map() が呼び出された配列                    
```

## 分割代入
オブジェクトの場合はプロパティで管理されるため、順番通りである必要ない

```js
const { z, x } = { x: "obj1", y: "obj2", z: "obj3" };
console.log(x); // => "obj1"
console.log(z); // => "obj3"              
```

## スプレット演算子
別の新しい配列を作成することができる

```js
let arr1 = [1, 2, 3];
let arr2 = arr1;
// 参照先が同じなので
console.log(arr2 === arr1); // => true
let arr3 = [...arr1];
console.log(arr3 === arr1); // => false
```

## 残余引数
関数が不定数の引数を配列として受け入れることができる

```js
const restA = (...argA) => console.log(argA);
restA(1, 2, 3)
 // => [1, 2, 3]

const restB = (n, ...argB) => console.log(argB);
restA(1, 2, 3)
// => [2, 3]
```

## 非同期処理(await/async)
async function 宣言は非同期関数を宣言し、その中で await キーワードを使うことができる。すると、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができる。
```js
let num = 0;

init(); // => 1

// awaitをつけることで resolve が呼ばれるまでまってくれる
async function init() {
  const result = await new Promise((resolve, reject) => {
    setTimeout(() => {
      num = 1;
      resolve(num) // numがresultに入る
     }, 2000);
  })
  console.log(result);
}
```
robloxでassistant その119

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
スクリプトだけで、地形を作れ。

# 手順
- ServerScriptServiceに、Scriptを追加。
- スクリプトを書く。
```
local len = 65
local size = 2
local zoom = 50
local amp = 30
local lin = -2
for x = -len, len do
	for z = -len, len do
		local y = math.noise(x / zoom, z / zoom) * amp
		if y < lin then
			game.Workspace.Terrain:FillBlock(CFrame.new(x * size, 2, z * size), Vector3.new(size, size * 2, size), Enum.Material.Water)
		else
			game.Workspace.Terrain:FillBlock(CFrame.new(x * size, y, z * size), Vector3.new(size, size * 2, size), Enum.Material.Rock)
		end
	end
end
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8943a0fb-0d9b-bfce-a4be-3fb306bb3f18.png)


以上。
robloxでassistant その118

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
スクリプトだけで、地形を作れ。

# 手順
- ServerScriptServiceに、Scriptを追加。
- スクリプトを書く。
```

local len = 65
local size = 2
local zoom = 50
local amp = 30
local lin = -2
for x = -len, len do
	for z = -len, len do
		local y = math.noise(x / zoom, z / zoom) * amp
		if y < lin then
			game.Workspace.Terrain:FillBlock(CFrame.new(x * size, 2, z * size), Vector3.new(size, size * 2, size), Enum.Material.Water)
		else
			game.Workspace.Terrain:FillBlock(CFrame.new(x * size, y, z * size), Vector3.new(size, size * 2, size), Enum.Material.Grass)
		end
	end
end

```


# 写真


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/599dd535-5a1b-4359-dee8-2ef0cb0ff1ce.png)

以上。
robloxでassistant その117

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
スクリプトだけで、地形を作れ。

# 手順
- ServerScriptServiceに、Scriptを追加。
- スクリプトを書く。
```

local X, Y, Z = 3, 3, 3
local Amount = 5
for i = 1, Amount do
	game.Workspace.Terrain:FillBlock(CFrame.new(X, Y, Z), Vector3.new(Amount * Amount - (i * 10), Y * (i * 2), Amount * Amount - (i * 10)), Enum.Material.Rock)
end



```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c0da18ca-15ae-c30d-eb09-5bed4161eb1c.png)


以上。
【2024マラソン11】モバイルバッテリーと100均アイテムでメガネユーザのquestピントズレを解消する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/8fea35be-d265-7ee1-7ff1-da2d759a1a4b.jpeg" width=300>

# 何これ？
見た目は兎も角、私の快適スタイルです。

# 何の記事？
quest2を純正ストラップで使うメガネユーザ向けの、物理的なピントズレ解消方法について書きました。

# 誰向け？
- questの純正ストラップのピントズレが気になる人
- メガネをつけてquestを使用していて、ピントズレが気になる人
- 装着直後は気にならなくても体を動かすとピントがズレてくる人
- メガネユーザ向けの度入りレンズにはしたくない人

# あらすじ
quest2を初めて使った時から、ピントズレは気になっていました。
ビートセイバーなどのゴーグルと体を激しく動かすゲームをすると、動くたびにピントのズレが激しくなり、曲が最後まで続けられない状態でした。
ゲームを楽しくプレイできるようにするために、ずれない方法を探した記録をここに残します。

# 具体的に何を使ったか
#### 曇り止めシート
動いているうちに、ゴーグルと顔の間に汗をかいたり、熱がこもったりすることで、レンズがぼやけて見えることがあったため、プレイ前には拭くようにしました。

#### メガネ止めクリップ（seria）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/a8cb1014-f4c7-ed69-234c-e46396297d9b.jpeg" width=300>

そもそも、メガネが普段から歪んでおり、questをつけていなくてもずれてしまうと言うことがありました。
なので、questだけではなくメガネの固定自体にも問題があると考え、なるべく動いてもメガネがずれないようにずれ防止のクリップを導入しました。

百均で買ったものではありますが、普段遣いでも重宝しています。
マスクをつけるときにも付け方を工夫すれば、耳が痛くなると言う事もありません。

#### モバイルバッテリー
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/1b09a336-ced1-4052-c0d9-8bcdec1d6302.jpeg" width=300>

今回の肝になるアイテムです。
このモバイルバッテリーの重さによって、ヘッドセットの重心が前によるのを防ぎ、後ろにずらすことで、ピントズレを防いでいます。

バッテリー自体は何でも構いません。
ある程度充電ができるものだと、questの充電不足を補うことができるでしょう。
超小型だとつける意味がないため、それなりの重量があるものをお勧めします。

このあたりは試しながら、自分にちょうどいい重さを探してみてください。


#### バッテリー固定用バンド（seria）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964152/32bee7e0-f223-34f2-01d3-628af345b73a.jpeg" width=300>
バッテリーの大きさなどによって巻き具合を微調整できるバンドです。
これも百均のもので十分固定できます。
マジックテープで任意の長さに固定できるものを購入すると良いです。

バンド2つでしっかり固定すれば、バッテリーが飛んでいくということもありませんでした。

#### 短めの充電用ケーブル
固定したバッテリーからquestを充電するのに使います。
バッテリーからquestへ、短い距離がつなげるものであれば何でも大丈夫です。

ただ、あまり長すぎると体を動かすゲームをやった際にケーブルが引っかかります。
なるべくジャストサイズのケーブルを使うと良いかと思います。

なお、バッテリーを使わない、短時間の使用であれば、ケーブルは使わなくても問題ありません。

# 何をやったか
#### 1.メガネにメガネ留めクリップをつける
#### 2.quest装着前にメガネをしっかり装着・固定する
#### 3.questの後ろにモバイルバッテリーを固定する
#### 4.バッテリーからquestにケーブルをつなぐ
#### 5.メガネがずれないようにゴーグルをまっすぐ装着する
- ゴーグルを装着した後、グルがずれてしまうようであれば、締め付け具合を調整する

# 結果
#### 見違える位映像がきれいに見えるようになった
今まではピントが合ってないがために少し画質の悪い映像を見ていたようです。


#### 目があまり疲れなくなった
最初にクエストを装着した時は目がとても疲れてしまって毎日は使えないなぁ……と思いました。
ですが、この方法で調整したところ、目が疲れてきたのでやめる……と考えることがなくなりました。
何時間でも気にせず使えるようになったのは嬉しいです。

#### ビートセイバーを終わりまでプレイできるようになった
いつもは曲が終わる前にquestズレてしまい、中断したり、なんとか最後までプレイしていましたが、
曲が終わるまでハッキリノーツが見えるようになりました。
ようやく音楽ゲームが楽しめるようになりました。

#### quest2を1時間以上使えるように
バッテリーと繋いだことで、quest2の充電が短い問題も解消されました。
普通に使っていると大体1時間弱位しかもたない印象でしたが、モバイルバッテリーをつなぐことによって時間を気にせずにプレイできるようになりました。

#### ヘッドセットと顔の接着面が痛くなくなった
当初、初期のスポンジだと顔が痛くなるため、付属のシリコンのパットにしていたのですが、それでも長期間つけていると顔のあたりが痛いなぁと感じていました。
こんなものなのかなと半ばあきらめていたのですが、今回重心が後ろにずれたことによって、顔のあたりがソフトになったので、何時間装着していても顔が痛いと感じることがなくなりました。
Create a Product Pipeline Dashboard with CRM Analytics Charts


https://trailhead.salesforce.com/content/learn/projects/wave_charts_prod_pipeline

# Add a Pyramid Chart

+ [The error message says that there is no pyramid chart with the title "Products..."](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmFU0)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/937decbe-7de1-13ea-2977-4b8587cf66f8.png)

:::note
"Click Count of Rows options menu (⌄), then select Sort ascending to sort the bars in ascending order."

I selected the "Sum of pipeline..." to sort ascending 
:::
Javaで「文字列と文字列を比較する(String.equals)」の動作を確認してみた

# 概要

Javaで「文字列と文字列を比較する(String.equals)」の動作を確認してみました。
以下のページを参考にしました。

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

# 実装

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

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

以下のコマンドを実行しました。
```
$ javac JSample4_1.java 
$ java JSample4_1 
false
true
```

# まとめ

何かの役に立てばと。
今でも使えるBASIC

# 今でも使えるBASICマシン
今でも使えるBASICマシンがあります。
それがIchigojamです。
子供向けのマシンですがGPIOも使えます。
https://ichigojam.net/

# WebでもIchigojamが使えます。
実はこのIchogojamBASICはブラウザから使えるようにサイトが用意されています。
https://fukuno.jig.jp/app/IchigoJam/

# じゃ使ってみよう！！
上記のサイトに行って黒い画面でプログラムを書いていきます。
BASICでプログラムを作るときは、行番号という数字の後ろに命令を入力しENTERキーで記録されます。
では以下のコードを入力してみます。
```
100 INPUT "A=",A
110 INPUT "B=",B
120 PRINT "A+B=";A+B
```
ちゃんと入っているかは
LIST
で入力したプログラムが表示されれば大丈夫です。

# 動かしてみよう
RUN
という命令で実行できます。
【黒魔術】GitHub Educationの審査通るためにやったこと

GitHub Educationって審査が通らないことで有名ですよね(((圧

私はGitHub Educationに4回申請してようやく審査が通りました。3回リジェクトされたときに、様々試してみたことをまとめます。

https://education.github.com

:::note warn
警告
説明は省きに省いているので、ネットにある他の記事も併用して登録するのが一番です。
:::

# メリット
個人的にGitHub Educationのメリットを上げます。下に書いているのは一部GitHub Student Developer Packの内容です。

- GitHub Copilot
- GitHub Pro
- Azure for Students
- Tech Domains
- JetBrains
- GitLens
- BrowserStack
- Doppler

※フロントエンド系の思想が入っています
# 位置情報
登録するときに位置情報を求められる場合があります。ただ学校にいる間に登録をするのは面倒だったので、(わざわざ学校に出向いて、登録作業はちょっと、、、)Chrome側で位置情報を学校に書き換えました。

果たしてこれが効果があったのか、それ以前に正しくGitHub側に送信されたのかよく分かっていませんが、書き記します。

まず[国土地理院地図](https://maps.gsi.go.jp)やらなんやらで緯度と経度を取得してきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/2fd2fe95-813e-304c-80fc-53c73cd50a77.png)

次にGitHub Educationの登録画面に進みます。デベロッパーツールを開き右上のメニューから、「More tools＞Senseors」を開くとLocationを設定できるようになるので、先ほどコピーした緯度経度を貼り付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/f82b757c-89e4-2049-680f-fd5ba78a8b99.png)

Continueを押して、サイト側から位置情報が求められたら許可します。

# 英語訳
学生証の英語訳があるといいという話を聞き、ボールペンで手書きした英語訳を横に置いて画像を送信してみましたが、ダメだったので、[OBS Studio](https://obsproject.com/ja)を用いて「学生証の画像＋英訳したテキストを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/38456260-ae81-fed7-9440-1eabc421668c.png)

このように「名前、学校、有効期限」がそれぞれ英語表記で書いてあれば通るように思えます。準備ができたら、「仮想カメラ開始」を押して、OBSをカメラとしてGitHubで写真を撮りましょう。

# 補足
学校のメールアドレスを使うと審査が通りやすいようですが、私の学校ではメールの使用が制限されていたため、申請に使用できませんでした。裏を返せば、別に学校のメールアドレスがなくても問題なく審査自体は通ります。

# 参考文献

https://zenn.dev/waki285/articles/2fcfc6b1e8ba8f

https://qiita.com/Hyouhyan/items/5871be559d2c28e0fef9
【Rails】「アセットパイプライン」とは

# はじめに

改めてアセットパイプラインについてまとめてみました

# 目次

[1.アセットパイプラインについて](#1-アセットパイプラインについて)
[2.主な機能](#2-主な機能)


# 1. アセットパイプラインについて

アセットパイプラインは、Ruby on Railsアプリケーションで使われる便利な仕組みです。これは、ウェブサイトやウェブアプリで使うJavaScriptやCSSなどのファイルを、効率よく扱えるようにしてれくます。

例えば、アセットパイプラインを使うと、複数のJavaScriptやCSSファイルを1つにまとめて、ブラウザが1回のリクエストで取得できるようにできます。それに加えて、ファイルのサイズを小さくするための工夫もしてくれます。つまり、使っているJavaScriptやCSSが少ないリクエストで、早くページが表示されるようになるんです。

# 2. 主な機能
具体例を交えて４つ紹介します。

## SHA256フィンガープリントを挿入する機能：
この機能は、ファイル名にSHA256フィンガープリントを含めることで、ブラウザとCDNによってファイルがキャッシュされるようにします。例えば、application.cssというファイルがある場合、アセットパイプラインはそれをapplication-1a2b3c4d5e.cssのように変更します。ファイルの内容が変更されると、フィンガープリントも変わり、ブラウザが古いバージョンのファイルをキャッシュしないようになります。

## import mapsを使う機能：
この機能は、JavaScriptファイルの配信にimport mapsを使用します。これにより、ESモジュールを利用するアプリケーションを簡単に構築できます。例えば、application.jsに以下のように記述します。

```js:application.js
import { myFunction } from './myModule.js';
```
アセットパイプラインは、これを適切な形式に変換してブラウザに提供します。

## CSSファイルの連結と最小化または圧縮する機能：
この機能は、すべてのCSSファイルを1つのファイルに連結し、最小化または圧縮します。例えば、application.cssやstyle.cssなどの複数のCSSファイルがある場合、アセットパイプラインはこれらを1つのファイルにまとめて最適化します。

```css:css
/* application.css */
body {
    background-color: #fff;
}

/* style.css */
.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
}
```
これらのCSSファイルは、1つのapplication.cssにまとめられ、不要な空白やコメントが削除されます。


## CSSの上位言語によるアセットコーディングを可能にする機能：
アセットパイプラインは、SassやSCSSなどのCSSの上位言語を使用することも可能です。これにより、より効率的にスタイルシートを管理できます。例えば、application.scssに以下のように記述します。

```scss:application.scss
/* application.scss */
$primary-color: #007bff;

.button {
    background-color: $primary-color;
    color: #fff;
    padding: 10px 20px;
    border: none;
}
```

このように、変数やネストなどを使用してスタイルを定義できます。

これらの機能によって、開発者は効率的にアプリケーションの静的ファイルを管理し、最適化することができます。
Accounts with Contact Roles report　という標準のカスタムレポート

[レポートのまとめに戻る](https://qiita.com/Keiji_otsubo/items/9c883d1e4bf0df549a2a)


-----------
+ [all contacts related to accounts that have at least one closed/won opportunity](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmD1m)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ec38087e-c486-f7a3-75a2-d76dfa462194.png)

:::note
I also checked, and if I deleted the contact item, the account was displayed.

We have the same question below.

accounts with contact roles report

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A907WSAR

It looks like the contact role the account has been discontinued.

This may be the cause.

I created a report in Classic as well, but it could not be displayed.

Contact Role not showing up in Lightning for Account
https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A7i6oSAB

Account Contact Roles in Lightning Experience
https://ideas.salesforce.com/s/idea/a0B8W00000GdguEUAR/account-contact-roles-in-lightning-experience
:::

古くから存在するレポートタイプみたいです。取引先の取引先責任者の役割という機能は廃止されたみたいなので、機能しなくなったのかもしれませんね。

調べてもよく分かりません。
間違ってgit pushで重たいファイルをgithubに上げた時の対処

githubに重たいファイルを挙げてしまって、`git push`の途中で、どうしたらいいか分からなくなった時の対処方法です。

結論から言うと以下二つのコマンドを実行して、.gitignoreに重たくてアップできなかったファイルを記載して、ignoreする設定にすれば大丈夫です。

```
git reset --soft HEAD^ 　# commitの取り消し
git reset --mixed HEAD 　# addの取り消し
```
:::note warn
このページを見ている皆さんは、おそらくこの記事以外のサイトなども参考に色々コマンドを調べると思います。
ただコマンドの中には、編集したファイルが編集前に戻す(編集箇所が消えた)ことがあったので、一度編集したファイルをダウンロードしたり、バックアップを取ることをお勧めします！
:::

これで、.gitignoreを編集し重たいファイルを無視するようにすれば再度git pushすれば完了！
【参加日記#03】Gemini API デベロッパー コンペティション

～[前回](https://qiita.com/arc-lab-jp/items/e195361b5181b21819be)までのあらすじ～
入門チュートリアルを進めてみることにする。やったこともないDartで開発することにして文章を読み進めることにしたのだが・・・

# 1.スケジュール的にほんとに間に合う？
残り45日・・・アプリと動画を作る必要があるんだよなぁ。

- [x] a.参加登録
- [ ] **b.製作するアプリの決定** [2d]
- [ ] c.開発環境作成　[.5d]
- [ ] **d.プログラミング＆ブラッシュアップ** [15d]
- [ ] **e.アプリ紹介の動画作成** [5d]
- [ ] f.最終テスト・調整 [3d]
- [ ] g.投稿(〆8月12日)
※d=日

動画作成(30秒～3分)、全くの素人なんですが😢
何よりもこれが不安でしょうがないです。

どなたか動画作成に詳しい方、無料のおすすめアプリとか
素人でもそれっぽく見える編集とか教えてください m(__)m

# 2.開発スケジュール

+ b：6月30日迄
+ d：7月15日迄
+ e：7月20日迄

平日はあまり時間が取れないので、プログラミングの段階で時間が足りなくなりそうだが、まずはこれを目標に進めよう。

これで時間が余れば、アプリの改善していけるね。

# 3.製作するアプリの決定
今頭の中にある構想は、まだフワフワして「これだ！」というインスピレーションが沸いていない。
今回はGeminiAPIのコンペということなので、どうせなら他のAIたちにも手伝ってもらう事にするのはどうだろう？
ChatGPT とか Claude君たちとお話ししてみよう！


というわけで、また[次回](https://qiita.com/arc-lab-jp/items/ac3c6c508ee0fea8d259)
pythonでDecimal型をintとfloatに変換する

# はじめに
DynamoDBに登録したデータをLambdaで取得して返却しようとしたときに
"Object of type 'Decimal' is not JSON serializable"とエラーが出てしまいました。
Dynamo側から取得したデータを見ると数値がDecimal型になっており、Decimal型はjson.dumpsできないみたいです。
今回は整数で表現できるものは整数、実数値は実数値に変換したかったのでそのように処理を追加しました。

# 本題
下記が対象のコードです。
対象のデータを一度整数に変換して変換前のデータと比較して一致した場合、つまり小数点以下が0の場合はint、違う場合はfloatに変換して返却するようにしました。

```python:main.py
import json
import boto3
from decimal import Decimal

def lambda_handler(event, context):
    try:
        def decimal_transform(obj):
            if isinstance(obj, Decimal):
                return int(obj) if int(obj) == obj else float(obj)
                
            
        dynamodb = boto3.resource("dynamodb", region_name='ap-northeast-1')
        table = dynamodb.Table("table_name")
        response = table.get_item(
            Key={
              'key': 'key_name'
            }
        )
        
        return {
            'statusCode':200,
            'body': json.dumps(response, default=decimal_transform),
        }
      
    except Exception as e:
        print(e)
        return {
            'statusCode':500,
            'body': json.dumps('server faild'),
        }
```

# おわりに
DynamoからDecimalが返ってくることも、Decimalにjson.dumpsが使えないことも知らなかったので意外なところで時間を使ってしまいました。
同じ問題が発生した人に助けになれば幸いです。
MakeYourCommand


# Architecture
```
[notification_slack.py] <--[comment]-- [run_and_notify.sh]
```
# Prepare
- Python Environment
- Slack API Setting

# Notification wih Python
## notification_slack.py
```python
import slack
import argparse


OAUTH_TOKEN = 'YOUR_SLACK_OAUTH_TOKEN'
CHANNEL_NAME = 'CHANNEL_NAME'
client = slack.WebClient(token=OAUTH_TOKEN)

parser = argparse.ArgumentParser(
    prog='SlackMessenger',
    description='A script to post a comment to a Slack channel',
    epilog=f'This message will send to {CHANNEL_NAME}'
)
parser.add_argument('-c', '--comment', required=True, help='Comment to be posted')

args = parser.parse_args()
text_base = f'{args.comment}'

response = client.chat_postMessage(
    channel=CHANNEL_NAME,
    text=text_base
)
```
## Run this command
```
sudo mv notification_slack.py /usr/bin/
sudo chmod +x /usr/bin/notification_slack.py
sudo bash -c "echo \"alias notify_slack='python3 /usr/bin/notification_slack.py'\" >> /etc/bash.bashrc"
/usr/bin/python3 -m pip install slack slackclient==2.9.4
source /etc/bash.bashrc
```
## Usage
```shell
notify_slack -c 'Hello World!'
```

# Shell script
## run_and_notify.sh
```shell
#!/bin/sh
python3 /usr/bin/notification_slack.py -c "$1 will run!"

nohup $1 &
PID=$!
wait $PID
python3 /usr/bin/notification_slack.py -c "$1 was successful!"
```

## Run this command
```
sudo mv run_and_notify.sh /usr/bin/
sudo chmod +x /usr/bin/run_and_notify.sh
sudo bash -c "echo \"alias run_notify='sh run_and_notify.sh'\" >> /etc/bash.bashrc"
source /etc/bash.bashrc
```

## Usage
```shell
run_notify 'echo ThisIsTest'
```
Windows環境でZedをビルドして使う


## はじめに

最近話題にあがるようになった軽量エディターであるZedは、現在Mac版のみの提供である。
しかし公式には提供されていないもののオープンソースかつクロスプラットフォーム対応なので自分でビルドすればWindowsやLinuxでも使うことができる。

公式にWindows向けのビルド方法が書いてあるのでそれを見ながらやっていく。
<https://github.com/zed-industries/zed/blob/main/docs/src/development/windows.md>

今回はインストーラーを作成する形式ではなくexeを直接生成するやり方である。
また、この流れで発生するいかなる事象について、私は一切の責任を負えないことを了承のうえで実行してほしい。

## 環境

- OS: Windows11 x64
- Rust: 1.79.0
- Visual Studio 2022 Community Edition

## セットアップ

### Rustのインストール（アップデート）

ZedはRustで記述されているため、まずはRustのインストールを行う。
今回はWindows向けのビルドなのでWSL環境やDevContainer環境でのRustが使えないことは注意が必要だ。

公式からダウンロード＆インストールしよう。
<https://www.rust-lang.org/ja/tools/install>

パッケージ管理ツールを使っている方はそちらからインストールでも良い。
たとえばwingetを使っているなら以下のコマンドを打つ。

```ps1
winget install Rustlang.Rustup
```

アップデートの場合は下記コマンドを実行するだけで良い。

```ps1
rustup update
```

### MSVCのインストール

次にWindows向けビルドをするためにMSVCが必要になる。
主に2つのやり方があるのでどちらも紹介する。

#### Visual Studioを使う場合

Visual Studio Installerの画面で追加コンポーネントを選ぶことができる。
このうち必要になるのは「C++によるデスクトップ開発」の項目だ。
「MSVC」が必要になるのでそれを選んでインストールしよう。
![Visual Studio Installer](https://raw.githubusercontent.com/varubogu/zetabook/main/images/zed-windows-build/image.png)

#### Build Tools for Visual Studioを使う場合

Visual Studioを入れる余裕がない人の選択肢がこちら。

下記からインストールできる
<https://visualstudio.microsoft.com/ja/visual-cpp-build-tools/>

一応winget版も書いておく。

```ps1
winget install Microsoft.VisualStudio.2022.BuildTools
```

### wasmツールチェインのインストール

下記のコマンドでインストールしよう。

```ps1
rustup target add wasm32-wasi
```

### リポジトリをCloneする

```ps1
git clone https://github.com/zed-industries/zed.git
```

### rust-toolchain.tomlにツールチェインを記載

リポジトリのルートにあるファイルを編集して下記のように書き換える。
targetsの中身をMSVCのものに変えれば良い。

```Cargo.toml
[toolchain]
channel = "1.79"
profile = "minimal"
components = [ "rustfmt", "clippy" ]
targets = [ "stable-x86_64-pc-windows-msvc" ]
```

### Cargoでビルドする

以下のコマンドでビルドを行う。
長時間かかるしメモリ使用率・CPU使用率も跳ね上がるので事前に他のアプリは終了させておこう。
~~自分はというとRustRover内のコンソールでビルドしてしまってえらいことになった。デバッグビルドはともかくリリースビルドする時は落としておきたい~~

```ps1
cargo build --release
```

ビルド終了後、リポジトリのある位置から `target/release/` といけば本体のzed.exeファイルがある。
これを好きな位置に配置して実行しよう。

![zed.exe](https://raw.githubusercontent.com/varubogu/zetabook/main/images/zed-windows-build/image-1.png)

これで完了。

## Zedの感想

まずビルドしての感想。
Windowsビルドの難易度は全然高くないと思った。
英語を読む力（翻訳系アプリを使っても良い）がある程度あってWindowsアプリを何かしら作ったことがある人であれば問題なくできるだろう。
ドキュメントが簡潔にまとまってるのでかなり良いなという印象。

次にZed自体の感想。
起動時間がマジで早い。
サクラエディターより若干遅いが1秒かからず起動。
VS Codeより起動が早いのでササッとコード確認したいときには便利。

## 余談：サクラエディターとメモリ使用量を比較してみた

Zed 174.1MB
<https://x.com/varubogu_tysk/status/1806462060324425980>

サクラエディター 3.4MB
<https://x.com/varubogu_tysk/status/1806435538326749320>

あれ、もしかしてサクラエディターすごい・・・？