OmniAICreator/Qiita-1.07M huggingface dataset:
【React】コンポーネント分割（Atomic Design）


# この記事の目的
- Reactの理解とアウトプット、振り返り用
- Reactでよく使われている基本的な技術を言語化できるようする

# Atomic Designとは
Atomic DesignとはUI設計の考え方で、「小さなUIコンポーネントを組み合わせて1つのページを作っていこう」というものになります。
- 画面要素を5段階に分け、組み合わせることでUIを実現
- コンポーネント化された要素が画面を構成しているという考え方
- React用ではなく、もともとはデザインの考え方
- モダンjavascript（コンポーネント）と相性が良い


### 5段階のコンポーネント
Atoms(原子)・Molecules(分子)・Organisms(生体)・Templates(テンプレート)・Pages(ページ)という単位に分かれています。
![Atomic_Design.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/01ca0e39-816f-e1ca-be02-03507d67f403.png)
|    名称   |   役割      |
|:----------:|:---------------:|
| Atoms(原子)  | 最小でそれ以上分解できない要素 <br> 例：ボタン/入力テキストボックス/アイコン 等 |
| Molecules(分子) |	Atomの組み合わせで意味を持つデザインパーツ <br> 例：アイコン+メニュー名/プロフィール画像+テキストボックス/アイコンセット 等|
| Organisms(生体)  | 	AtomやMoleculeの組み合わせで構成される、単体である程度の意味を持つ要素群 <br> 例：入力エリア/サイドメニュー 等|
| Templates(テンプレート) | 	ページのレイアウトのみを表現する要素（実際のデータは持たない） <br> 例：ヘッダー、サイドメニュー、コンテンツエリア等のレイアウト情報　等 |
| Pages(ページ) | 最終的に表示される1画面 <br> 例：ページ遷移毎に表示される各画面 |

# メリット
- 細分化しているため、小さな単位で問題を捉えられる
- コンポーネントを使い回すことにより全体のデザインに一貫性が出て再利用性も高い
- このコンポーネントが何をするものなのか分かり易い

# Atomic Designまとめ
- 小さな単位で問題を捉えられる
-デザインに一貫性が出て再利用性も高い
- わかりやすくメリットはあるが、無理して取り入れて分けるのではなく、まずは書いて定期的にコンポーネント分割したほうがよさそうと感じました。
初心者「Vimとかnvimってなんですか？」

# Vimとは
最近、プログラミングを始めた方はもっぱらvscodeというテキストエディタを使用していると思います。
実はこのVimもテキストエディタの一種になります。
> Vim（ヴィム。「ヴィアイエム」という読み方は誤り）は、vi から派生し、発展した高機能なテキストエディタである。(脚：https://ja.wikipedia.org/wiki/Vim）

ただし、vimはその他のテキストエディタとは違います。
vscodeはマウスを用いてカーソル移動などを行うGUIに対し、vimマウスを用いないターミナル操作（CLI）です。そうです、マウスで操作が出来ないのです！！！

![computer_programming_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610783/5e50db38-88e2-5389-aa3c-714a126daeff.png)


## 初心者「めちゃくちゃ使いづらそうだしvscodeでいいやん笑」
まずはこう思うはずです。**ターミナル操作？難しそうだし、いままでのテキストエディタでいいやん・・・** と。

とりあえずvimのメリットを見てみましょう。

:::note 
メリット
・コマンドによる操作のため、キーボードから手を動かさず作業効率アップ！  
・サーバー操作ができる！  
・恐るべき拡張性
:::
これ見て気になった方はもれなく

     $ apt-get install vim

でインストールできます！おめでとうございます！！！


次は少しメリットを深堀りしていきます！
> サーバー操作の説明は私が疎いため今回は割愛させていただきます
## メリットその１- 全てコマンド操作
**初心者「ﾊｧﾊｧ・・全てコマンド操作がｯ・・・メリット・・・？？」**
めでたいことにvimは全てコマンド操作です。ターミナルをろくに触っていない初心者にとってはあの真っ黒い画面と”コマンド”という響きは恐怖でしかないです。

安心してください、vimは複雑なコマンドは用いません。

以下に簡単に紹介します。


| コマンド（カーソル移動） | 内容 |
|:-:|:-:|
|  h | カーソルを左に移動  |
|  j |  カーソルを下に移動 |
|  k |  カーソルを上に移動 |
|  l | カーソルを右に移動  |
| w  |  単語の先頭に進む |
|  b |   単語の先頭に戻る|
|  O | 先頭に移動  |
|  ^|  インデントの先頭に移動 |
|  ＄ |  行末に移動 |
|  :set number / :任意のnum |行番号を表示 / 任意のnumに移動   |

慣れには時間がかかりますが、カーソルは`HJKL`で行います。

以下ファイル関係です

| コマンド（ファイル関係） | 内容 |
|:-:|:-:|
|  i |  編集モード |
|  a |  次の文字から編集モード |
|  esc |  編集モード終了 |
|  :w |  上書き保存 |
|  :q |  ファイルを閉じる |
|  :wq |  保存して閉じる |
|  :q! |  保存せず閉じる |

基本的に`i`や`a`で編集モードに移行し、コードをイジイジしていきます。
編集モードに入らないと基本コードは触れません。
終わったら`esc`で編集モードを終了します。



| コマンド（編集関係） | 内容 |
|:-:|:-:|
|  x |  一文字消す |
|  dd |  一行消す |
|  dw |  一単語消す |
|  * dd |  *行消す |
| y  |  一文字コピー |
| yy  |  一行コピー |
| * yy  |  *行コピー |
|  p(小文字） |  カーソルの下行にペースト |
|  P(大文字） |  カーソルの現在行にペースト |
|  . |  リピート |
|  u |  一つ前の状態に戻る(undo) |
|  ctrl + r |  undoの取り消し |

編集モードでも文字は消せますが、コピペなどはノーマルモードでコマンドを叩いたほうが簡単です。
今までマウスで行選択して消していたところがvimだと`dd`で終わるので効率化は目に見えると思います。

他にもファイル内でのコマンド実行や置換などもありますが、全ては紹介しきれないため、[日本語ドキュメント](https://vim-jp.org/vimdoc-ja/cmdline.html)や[チートシート](https://vim.rtorr.com/)などがありますので参考にしてください！

> 実はvimには
・ノーマルモード
・ビジュアルモード
・インサートモード（編集モード）
・コマンドモード
と４つモードがありますが混乱を招くため細かく分類化せず、詳細は割愛しました。

https://vim-jp.org/vimdoc-ja/cmdline.html

https://vim.rtorr.com/




## メリットその２- 恐るべき拡張性

しばらくvimを触っているとふと
「あの機能他のエディタにはあるけどvimにはないな〜」
と思うことがあるはずです。例えばvscodeですと横にディレクトリ構造が見れるタブがありますよね。
欲しくないですか？あれ
### vimにもあります
vimは良くも悪くも最低限の機能しかないため、つよつよの先人たちがプラグインを作ってくれてあります。
大体のプラグインが[Vim Plug]( https://github.com/junegunn/vim-plug)というプラグインを導入するためのプラグインがあるので入れておきます。

 https://github.com/junegunn/vim-plug

例えばですが先程の話のプラグインは[NERDTree]( https://github.com/preservim/nerdtree)というプラグインで再現可能です！
<details><summary>こんな感じになります。</summary>


![スクリーンショット 0005-02-17 22.32.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610783/8de0a463-a53d-ae51-e831-f12a9535b197.png)

</details>

 https://github.com/preservim/nerdtree

大抵欲しいと思った機能はプラグインで公開されています。
vimという骨組みに欲しい機能を継ぎ足していって自分専用のエディタを作り上げることができるのです。

# 最後にnVimとは
nVimとはNeoVimの略称で、機能はほとんど変わりません。
ですが、API実装や非同期処理など細かいところがvimよりnVimより優れているらしいので、今から始める方はnVimでいいと思います。
詳しくは公式docとかでお願いします（他力本願）

https://vim.blue/what-is-neovim/


https://neovim.io/
OpenSSLの暗号化・復号化でハマった話

OpenSSLを使って暗号化した情報を復号化しようとしたところ、こんなエラーに遭遇しました。
ネットで探してもなかなか解決策が見つからず、苦労したので理解できたことをメモとして残しておこうと思います。

```
# openssl aes-256-cbc -d -in hoge -pass pass:foo > piyo
bad decrypt
40D74304EF7F0000:error:1C800064:Provider routines:ossl_cipher_unpadblock:bad decrypt:../providers/implementations/ciphers/ciphercommon_block.c:124:
```

## エラーが発生した状況
- 自身のMac(macOS: 12.6.3)でとあるデータを暗号化した
- git push時にgithub actionsで実行しているubuntu上で復号化を実行した

## どうやって解決したか
暗号化するときと復号化するときの両方で、同じメッセージダイジェスト方式を指定する(`-md md5`などのオプションをつける)。

```sh
# 暗号化する時
openssl enc -aes-256-cbc -e -in foo -pass pass:bar > hoge -md md5

# 復号化するとき
openssl enc -aes-256-cbc -d -in hoge -pass pass:bar > piyo -md md5
```

※ 上記の例は以下の環境(OpenSSL3でもLibreSSL)でも動くことを確認しています。

### 動作環境
- macOS: 12.6.3
  - LibreSSL 2.8.3 ← デフォルトでインストールされているOpenSSL
  - OpenSSL: 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023) ← homebrewで入れたやつ
- ubuntu: 22.04.1
  - OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)

## 分かったこと
調べていると、MacとUbuntuで実行しているOpenSSLのバージョンが違うことに気づきました。

さらに調べていくとMacにインストールされているデフォルトのOpenSSLは
実際には**LibreSSL**というOpenSSL 1.0.1からフォークした別のライブラリなのだそうです。
(フォークした背景にはいろいろ根深いものがありそうです)

- https://www.ossnews.jp/compare/OpenSSL/LibreSSL
- https://www.libressl.org

そして、OpenSSL3とLibreSSL（OpenSSL2)では `-md` を指定しなかったときの
デフォルトのメッセージダイジェストの方式が異なるそうです。

> OpenSSL は 1.1.0 を境にダイジェストアルゴリズムのデフォルト値が md5 から sha256 に変更されています。

https://qiita.com/cmpk/items/6a9aec0b0909c5970e18

確かにOpenSSL3だと`-md`のデフォルト値は`sha-256`となっています。

```
-md digest
Use the specified digest to create the key from the passphrase. The default algorithm is sha-256.
```
[OpenSSL公式ドキュメント](https://www.openssl.org/docs/man3.0/man1/openssl-enc.html)

一方、LibreSSLのマニュアルには明確にどっちということは書いてありませんでした(むしろsha-1とか書いてある)。
```
# man openssl
ENC
     openssl enc -ciphername [-AadePp] [-base64] [-bufsize number] [-debug] [-in file] [-iv IV] [-K key] [-k password] [-kfile file] [-md digest] [-none] [-nopad] [-nosalt] [-out file]
                 [-pass arg] [-S salt] [-salt]
     -md digest
             Use digest to create a key from a pass phrase.  digest may be one of md5 or sha1.
```

解決策としては[こちらの記事](https://qiita.com/cmpk/items/6a9aec0b0909c5970e18)にも書いてあったとおり
`-md`を明示的に指定しするということで解決できました。

ググってもなかなか探し当てられずハマってしまったので、この記事が誰かのお役に立てられたら幸いです。(ちなみに最初にヒントを得ることができたのは[技術評論社さんから出版されている書籍の補足のページ](https://gihyo.jp/book/2018/978-4-7741-9596-4/support)でした)

## 補足

なおOpenSSL3では`-pbkdf2`(か`-iter`)オプションをつけないと、以下のようなWarningが表示されます。

```
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
```

問題なく暗号化・復号化できますが、OpenSSL3以降の環境だけで使うことが明らかな場合は、このオプションをつけておいたほうが良さそうです。(bruteforceのような総当り攻撃に対する試行回数の制限や、その類の脆弱性に対するオプションのようです)
https://ja.wikipedia.org/wiki/PBKDF2

## 最後に
なお、本記事で取り扱っている内容はセキュリティに関する情報であり、誤解や誤用によってリスクが発生するものでもあります。鵜呑みにせず、あくまで参考程度にしていただき、各自一次リソースや専門家や経験者による確認や相談もしていただければと思います。

また本記事で間違っているところがあったら指摘していただけますと幸いです。
PHP：浮動小数点同士の比較には気を付ける。単純にトリプルイコールでは誤判断する

# 浮動小数点同士の比較をトリプルイコールで行うと、誤判断する

```php
if ((0.2 + 0.3) === 0.5) echo '同じ数値';
else echo '異なる数値';
// どの小数点でも誤判定するわけではないが、この場合はelseが表示されてしまう。
```




# 正確性を求めるなら BC Math関数が良いが、消費税ならば工夫でできそう

## 消費税
1.1に100をかけて計算し、最後に100で割れば良いかも。


## BC Math関数
ただ、そのままでは使用できない。
BC Mathは拡張機能のため、あらかじめ環境にインストール及び有効化されている必要あり。

（例）Docker環境の場合

（Dockerfile）
```docker
FROM php:8.0.21-apache
RUN docker-php-ext-install bcmath
```

BC Mathの有効化はphpinfoより確認することができる。
（BCMath support enabled になっていればOK）

公式ドキュメント
https://www.php.net/manual/ja/ref.bc.php

## 加算：bcadd
```php
$result1 = 0.7 + 0.1;
$result2 = bcadd('0.7', '0.1', 3);

var_dump($result1, $result2);
```

出力結果
```php
float(0.7999999999999999)
string(5) "0.800"
```


## 減算
減算の場合はbcsubを使用します。

```php
$result1 = 0.7 - 0.1;
$result2 = bcsub('0.7', '0.1', 3);

var_dump($result1, $result2);
```

出力結果
```php
float(0.6) 
string(5) "0.600"
```

## 乗算

乗算の場合はbcmulを使用します。

```php
$result1 = 0.7 * 0.1;
$result2 = bcmul('0.7', '0.1', 3);

var_dump($result1, $result2);
```

出力結果

```php
float(0.06999999999999999) 
string(5) "0.070"
```


## 除算
除算の場合はbcdivを使用します。

```php
$result1 = 0.7 / 0.1;
$result2 = bcdiv('0.7', '0.1', 3);

var_dump($result1, $result2);
```

出力結果
```php
float(6.999999999999999) 
string(5) "7.000"
```


## 冪乗
冪乗する場合はbcpowを使用します。
「0.7の3乗」

```php
$result1 = 0.7 ** 3;
$result2 = bcpow('0.7', 3, 5);

var_dump($result1, $result2);
```

出力結果

```php
float(0.3429999999999999) 
string(7) "0.34300"
```
gen_z_web開発部

こんにちはgen_Z_webリーダーのibukiです
# gen_z_webとは
gen_z_webとはz世代から見た世間のニュースなどを作るウェブマガジン作成グループです
↓求人募集
```diff
+募集一覧
+webデザイナー
+人事管理
+記事作成
+記事等の誤字チェック
-↓↓重要↓↓
+SNS等の宣伝
+web管理人
```
https://discord.gg/EUyHu5TzGq


# サイトの作り方
まず記事を作るにはhtmlでページを作りましょう
https://gen-z-webmagazine.netlify.app/
このような感じです
では記事を書いていきましょう
上のリンクはindexpage(目次のページ)なので記事ではありません
https://gen-z-webmagazine.netlify.app/magazine/page1.html
このようにpage.1htmlを作ります
自分の場合はサイドメニューがありますがのその作り方も教えます
このように改行して文章を書くだけです
例えば

sample



sample
としたい場合は
```html
<p>sample</p>
<br>
<br>
<br>
<p>sample</p>
```
とするといいですよ
# サイト公開の仕方
作っただけではみんなに見てもらえません
ではどうするかというと
**レンタルサーバー**です
レンタルサーバーとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2863637/a96f4b01-c99b-25e5-7433-6f9ce831a853.png)
このように**作成者**(developer)と**web閲覧者をつなぐ役目**をしています
ではレンタルサーバーとはどんなもんか説明します
Xfree
無料
ドメインは有料
容量は
html → 1GB
php等　→ 1GB
Wordpress → 2GB
https://www.xfree.ne.jp/

netlify
ドメイン無償
ただし後ろに.netlify.appがつく
gen_Z_webはこれを使っています
容量100GBくらい
有料プランもあり
無料プランで十分
https://app.netlify.com/


ご閲覧ありがとうございました!!!!!
https://gen-z-webmagazine.netlify.app/
https://gen-z-webmagazine.netlify.app/magazine/page1.html
【chatGPTを使って3分で書いた】Python:Fakerについて

◉指示
PythonのFakerについて、HTMLを使って書いて。文章がHTML内に収まるように。
以下、出力の貼り付け。
<!DOCTYPE html>
<html>
<body>
	<h1>Fakerとは？</h1>
	<p>Fakerは、Pythonで架空のデータを生成するためのライブラリです。開発やテストなどで実際のデータを使用する場合に役立ちます。Fakerを使用することで、偽の氏名、住所、メールアドレス、電話番号、クレジットカード番号など、様々な種類のデータを生成することができます。</p>
	<h2>Fakerの使い方</h2>
	<p>Fakerを使用するには、まずFakerライブラリをインストールする必要があります。以下のように、pipを使用してインストールすることができます。</p>
	<pre><code>pip install faker</code></pre>
	<p>Fakerをインストールしたら、Pythonスクリプトで使用することができます。以下は、ランダムな氏名、住所、メールアドレス、電話番号、クレジットカード番号を生成する例です。</p>
	<pre><code>from faker import Faker

# フェイカーのオブジェクトを作成
fake = Faker()

# ランダムな氏名を生成
name = fake.name()

# ランダムな住所を生成
address = fake.address()

# ランダムなメールアドレスを生成
email = fake.email()

# ランダムな電話番号を生成
phone_number = fake.phone_number()

# ランダムなクレジットカード番号を生成
credit_card_number = fake.credit_card_number()

print(name, address, email, phone_number, credit_card_number)</code></pre>
	<p>このスクリプトでは、FakerライブラリからFakerオブジェクトをインスタンス化し、ランダムな氏名、住所、メールアドレス、電話番号、クレジットカード番号を生成し、それらを出力しています。</p>
	<h2>まとめ</h2>
	<p>Fakerは、Pythonで架空のデータを生成するための便利なライブラリです。開発やテストなどで実際のデータを使用する場合に役立ちます。Fakerを使用することで、偽の氏名、住所、メールアドレス、電話番号、クレジットカード番号など、様々な種類のデータを簡単に生成することができます。</p>
</body>
</html>
市場調査と資料作成を経営コンサルが代行する新たなサービス開始


showa Research Consulting（東京江東区）が展開する「市場調査＆資料作成.com」は2022年9月から、忙しいビジネスマン向けに特化し、現役の経営コンサルタントが市場調査や事業計画書、パワーポイント資料等の資料作成を代行するサービス提供を開始しました。

新型コロナ発生を契機にますます働き方が大きく変わる中、企業や事業者が市場調査、資料作成の業務を外部にアウトソーシングする事例が増えてきました。

従来は依頼主から原稿や情報を受け取ってデザイン会社が資料作成を代行する形式が主流でしたが、最近ではフリーや兼業で活動する経営コンサルタントが自ら主体的に市場調査や分析を行い、ビジネススキルを要する事業計画書や市場調査レポート、プレゼンテーションといった資料作成の代行サービスが拡大しつつあります。

日本最大級のクラウドソーシング仕事依頼サイトを運営する「ランサーズ株式会社」の『新・フリーランス実態調査 2021-2022年版』によれば、日本国内のフリーランス人口は1,577万人、経済規模は23.8兆円であることが公表されています。
このことから、ますます市場調査や資料作成をフリーで活動する経営コンサルタントに依頼できる環境が整いつつあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113800/085ffd7c-bbdb-8fb1-2fea-0fb8bdfc37af.png)
従来の市場調査・資料作成の代行サービスと何が違うのか
「市場調査＆資料作成.com」では、ビジネススキルを必要とするため、作成の難易度が高い市場調査レポートや事業計画書、プレゼン資料といった資料作成の代行に特化しています。
実際のところ、外部にアウトソーシングできるビジネス資料の種類は多岐にわたります。
例えば、プレゼンテーション資料、事業計画書、企画書、M&Aに関する資料、会社紹介資料、営業資料、ピッチ資料、ホワイトペーパー、市場調査レポート、セミナー・講演資料、等です。

ビジネスの現場では多種多様な資料が日々使用されますが、従来の代行サービスでは、依頼主が資料の材料となるデータや原稿を代行会社に提供し、デザインを整えて資料化する形式が殆どでした。

「市場調査＆資料作成.com」が提供する代行サービスでは、「作成のためにビジネススキルが必要になる資料」に特化し、経営コンサルタントがマーケテイングリサーチ、市場調査を主体的に行い、依頼主が必要とする情報の設計、情報収集、分析、資料化（パワーポイント等）までワンストップ型資料作成のサービスを提供しています。

 

従来、外注することが難しい資料作成は後者の「ビジネススキルが必要になる資料」でした。「ビジネススキルが必要でない資料」の場合、依頼主が代行会社に対して、資料作成に必要なデータや原稿を提供すれば、代行会社は作業に着手できます。
一方で、「ビジネススキルが必要になる資料」の場合、市場調査スキルを持ち、経営環境を分析できる経営コンサルタントでなければ作成はそもそも難しいことが現状です。

資料作成をアウトソーシングするメリット
面倒で時間のかかる資料作成はプロの経営コンサルタントに依頼することで時間を節約し、より本業に注力することができます。主には以下のようなメリットをあげることができます。

	時間削減ができる
	相手に伝わる資料の作成をプロに任せられる。
	ビジネススキルが必要な作成の難易度が高い資料もアウトソーシングできる。
	資料作成に時間をとられず、より本業に集中できる。
	代行会社に依頼するよりも安価である。
 

市場規模・資料作成の代行サービスの市場動向
ビジネス用途の市場調査や資料作成の代行依頼の相場費用は2〜10万円程度です。
ランサーズ株式会社が公表するパワーポイント作成やコンサルティングサービスの依頼価格の相場は以下の通りになっています。
	経営・戦略コンサルティング：150,000〜300,000円
	パワーポイント作成：30,000〜100,000円（10枚）
	エクセル作成：20,000〜30,000円
日本国内のクラウドソーシング、スキルシェア大手サービスと言えば、ランサーズのほか、クラウドワークス、ココナラを挙げることができます。
独自の試算から、日本国内におけるビジネススキルを要する市場調査・資料作成の代行依頼サービスの市場規模は20〜30億円程度と予測されます。

【事業概要】
	屋号：Showa Research Consulting（ショーワリサーチコンサルティング）
	所在地：東京都
	事業内容:市場調査、ビジネス文書作成、リサーチ、ビジネスパーソン向け資料作成
	自社サイトURL https://sirabemono.com/
	自社メディアサイト　「市場調査＆資料作成.com」URL https://osirabe.com/
	問い合わせ先
【CSS】「ファイルを選択」ボタン(input[type="file"]) のスタイル変更は疑似要素でできます！！


# はじめに

ウェブページのフォームを作成していると、コヤツ👇のスタイル変更に困ることありますよね。
![スクリーンショット 2023-02-17 21.48.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231104/85d632f1-140a-fc62-4c21-fc84edda55de.png)

この「ファイルを選択」ボタンのスタイルは簡単に変えることができないため、ネット検索で検索すると`input`タグを非表示にし`label`タグや`button`タグを使って代わりのボタンUIを作成する方法が山のように出てきます。
しかし実はそんな回りくどいことをしなくても、ある程度のスタイル変更であれば`input`タグとCSSだけで完結させる方法がちゃんと用意されています。

# 解決方法

CSSの疑似要素`::file-selector-button`または`::-webkit-file-upload-button`（古いWebKit/Blink互換のブラウザ用）を使用することで「ファイルを選択」ボタンにスタイルを当てることができます。

# 実装例

例えば、以下のようなスタイル変更が可能です。

```css
input[type='file'] {
  color: rgb(31, 41, 55);
  cursor: pointer;
  border: 1px solid rgb(191, 194, 199);
  border-radius: 0.375rem;
  padding-right: 0.5rem;
  width: 24rem;
}

::file-selector-button,
::-webkit-file-upload-button {
  background-color: rgb(209, 213, 219);
  color: rgb(31, 41, 55);
  border: none;
  cursor: pointer;
  border-right: 1px solid rgb(191, 194, 199);
  padding: 0.25rem 1rem;
  margin-right: 1rem;
}
```

↓
![styled_button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231104/3c4e09a8-537c-90d5-ff69-451600a0c466.png)


# Tailwind CSS の場合

Tailwind CSSを使用している場合は `file` modifier を使用することでより簡単にスタイル変更できます。

https://tailwindcss.com/docs/hover-focus-and-other-states#file-input-buttons


# 参考

https://developer.mozilla.org/en-US/docs/Web/CSS/::file-selector-button
PHP：重要：変数の運用の仕方（狭小、隣接、短命、単一目的、良名）

# 【狭小】スコープは最小限の範囲で

コードを把握する時間がかかる。
当然バグを生みやすくなる。

# スコープ狭小のために

## 【隣接】変数を使う場所の近くで宣言する

## 【隣接】変数の参照も近くにまとめる

## 【短命】変数を使用する行数（使用期間）をできるだけ短くする

# 【単一目的】同じ変数名を異なる目的で複数回使用しない

# 【良名】良い変数名を命名する
Curl で install した Docker の削除方法

# 背景

以下の記事を試していた。

https://dev.to/azure/building-jetson-containers-for-nvidia-devices-on-windows-10-with-vs-code-and-wsl-v2-1ao

その際に、Docker を利用する箇所があったが、記事のままに進めたところ、apt ではなく、curl で install をした結果、削除方法がよくわからず困ったので記録まで。

といっても、BingAI 君に聞いたらあっという間だったので・・もうこういう備忘録すら要らないんじゃね？とも思うけれど、有償化される可能性もなくはない、ということで

# Bing AI さんの回答

> curl でinstall した docker on wsl2 を削除したいということですね。その場合、以下の手順を試してみてください。
WSL2 の Ubuntu で **sudo apt-get remove docker-ce** を実行して、Docker Engine をアンインストールします1。
WSL2 の Ubuntu で **sudo rm -rf /var/lib/docker** を実行して、Docker のデータを削除します2。
Windows の PowerShell で wsl --unregister <DistroName> を実行して、WSL2 のディストリビューションを削除します3。
これで curl でinstall した docker on wsl2 を削除することができます。ご参考になれば幸いです。
</code>

で、改めて apt install するなら、以下から

https://docs.docker.com/engine/install/ubuntu/

以上
zorin linux を仕事で使ってみる

ubuntuに飽きてしまったので、zorin linux とやらを使ってみます。
いまはまだInstallしたばっかりの状態。使いづらくてしょうがない。

これからいろいろカスタマイズします。

とりあえず日本語が　WINキー＋Spaceなのが驚き。

# Openconnect-ssoをいれる

sudo apt install python3-pip
ちなみに ~/.local/binにInstallされます。
pip install PyQt5
sudo apt install python3-testresources
sudo apt-get install python3-pyqt5
pipx install "openconnect-sso"
sudo apt install python3.8-venv
pipx install "openconnect-sso"
apt-get install python3-pyqt5.qtwebengine



# VMware Horizon Client
ビミョーにCONFIGができないのでVMware-Horizon-Client-5.5.4をインストール。
その後、ライブラリがなんかなさそうなので以下を入れました。

apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio
Rust研究：HTTPクライアント

Rust初心者です。
Rust を使い始めて一か月くらいたちました。
簡単な HTTP クライアントの書き方を勉強しました。
とりあえずコンパイルが通るところまできましたのでメモしておきます。

# お題

* 指定したURLに接続した結果をファイルに保存し、そのときのステータスコードを標準出力に表示するツールを作りたい。
* 使い方はこんな感じで。

```
// 使い方
C:\work>study0217.exe
[USAGE] study0217.exe url out_file

// Rust ロゴのダウンロード
C:\work>study0217.exe https://docs.rs/-/rustdoc.static/rust-logo-151179464ae7ed46.svg rust.svg
status code = 200
```

# ソースコード

Cargo.toml

```
[package]
name = "study0217"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bytes = "1.4.0"
reqwest = "0.11.14"
tokio = {version = "1.25.0", features = ["full"] }
```

```rust
// main.rs
use std::io;
use std::env;
use std::fs::File;
use bytes::Buf;
use reqwest;

#[tokio::main]
async fn main() {

    // 引数をチェック
    let args:Vec<String> = env::args().collect();
    if args.len() < 3 {
        eprintln!("[USAGE] study0217.exe url out_file");
        return
    }

    // 引数から接続先URLと出力先ファイル名を取得
    let url = args[1].as_str();
    let out_file = args[2].as_str();

    match run(&url, &out_file).await {
        Ok(status_code) => println!("status code = {}", status_code),
        Err(e) => eprintln!("[ERROR] {:?}", e)
    }
}

async fn run(url:&str, out_file:&str) -> Result<u16, Box<dyn std::error::Error>> {

    // URL に対して GET メソッドでアクセス
    let res = reqwest::get(url)
        .await?;
    
    // ステータスコードを取得
    let status_code = res.status().as_u16();

    // レスポンスボディーの Read ストリームを取得
    let mut r = res.bytes()
        .await?
        .reader();

    // 出力先ファイルオープン
    let mut w = File::create(out_file)?;

    // レスポンスボディーを出力先ファイルにコピー
    io::copy(&mut r, &mut w)?;

    // ステータスコードをリターン
    Ok(status_code)
}
```

ここまでの感想。

* ついに Rust の非同期コードに触れてしまいました。まったく非同期ではありませんが。
* とりあえずの reqwest ライブラリを使用。ググって調べたところ、見つかったサンプルではどれも Response から text() メソッドでテキストデータを取り出す作例ばかりでした。
* テキストじゃないコンテンツも想定して bytes() メソッドでバイト列を取り出し、reader() メソッドでストリーム化してみました。あとは io::copy で出力先ファイルにコピーするという。
* 今回ちょっとした発見がありました。run 関数の返り値のように dyn std::error::Error のインスタンスを Result で包んで返すようにしておけば、複数種類の Error を一元的に返せることがわかりました。この例では run 関数の中で reqwest::Error と std:: io::Error を ? で返す箇所が混在しているのですが、これならどちらも受け取れます。おかげで今後のエラー処理のスタイルが確立できそうな気がしています。
* 入門書もまともに読まずに見様見真似で一か月やってきました。順番が少しおかしいのですが、そろそろ Rust 本を一冊読むだけの下準備ができたような気がしています。
【PowerShell】ファイルのハッシュ値を求める

# はじめに

仕事で作ったファイルのMD5ハッシュ値を求める機会があったので、以前に調べたcertutil関数をあえて使わずに、PowerShellでハッシュ値を求める方法を調べてみました。

* [certutilコマンドの出力結果の違い（Win8.1～/ Win11））](https://qiita.com/nkojima/items/1dc5f021c9f34fefaf77)
* [【ExcelVBA】ハッシュ値を取得する関数を自作してみた](https://qiita.com/nkojima/items/89d2c53d34631b33d51e)

# コード

* `Get-FileHash`という関数を使うことで、簡単にMD5ハッシュ値を求めることができました。
  * `-Algorithm`パラメーターでハッシュ化する際のアルゴリズムを指定しない場合、デフォルトのSHA256が使われます。

```powershell:基本構文
Get-FileHash C:\Users\NKOJIMA\Downloads\img.png -Algorithm md5
```
```text:実行結果
Algorithm       Hash                                                                   Path
---------       ----                                                                   ----
MD5             C21F968AF02E47D3EA693DF25D05A74E                                       C:\Users\NKOJIMA\Downloads\img.png
```

* 以下のように`(得られた結果).hash`と書けば、ハッシュ値だけを求めることもできます。

```powershell:ハッシュ値だけを求めるコード
(Get-FileHash C:\Users\NKOJIMA\Downloads\img.png -Algorithm md5).hash
```
```text:実行結果
C21F968AF02E47D3EA693DF25D05A74E
```

* 以下のようなコードを使えば、指定したフォルダ内のハッシュ値を一度に取得することが出来ます。

```powershell:指定したフォルダ内のファイルのハッシュ値を求めるコード
$targetDir = "D:\ISO"
$files = Get-ChildItem $targetDir -File

foreach ($file in $files){
    Write-Host "$($file): $((Get-FileHash $file.FullName -Algorithm md5).Hash.toLower())"
}
```

```text:実行結果
AlmaLinux-8.3-beta-1-x86_64-minimal.iso: 3712e5250b92593169f18be198207176
AlmaLinux-8.3-x86_64-dvd.iso: 2734fcd999fbe9d7e81d4dae18db6b7b
AlmaLinux-8.3-x86_64-minimal.iso: 627d7a490adc409a1d3024181d3206f8
CentOS-6.10-x86_64-bin-DVD1.iso: 8ffcc065c3110e6fa0144cb85e4bb4bc
CentOS-6.10-x86_64-bin-DVD2.iso: 8ff3b03bbac2224c56943e8936348a9d
CentOS-7-x86_64-DVD-1908.iso: dc5932260da8f26bcdce0c7ebf0f59ca
CentOS-8.2.2004-x86_64-dvd1.iso: 47dc26d76e566280cc47437fd2466134
ClearOS-DVD-x86_64.iso: 64aa911ac344407b29c94d4855c5cc08
Oracle Linux 7.9.0.0.0_V1003434-01.iso: 41d1e84688c115215b445b7cfcc51d82
Oracle Linux 8.0_V983280-01.iso: 80255acf17ce75725e6322e0eed8197e
Rocky-8.3-x86_64-minimal.iso: f9c635416aa10020b1eb212498ed6e25
```

# 参考URL

* [PowerShellでファイルのハッシュ値を確認する方法](https://win.just4fun.biz/?PowerShell/PowerShell%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E5%80%A4%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%83%BBGet-FileHash)
* [about_Foreach](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_foreach?view=powershell-7.3)
* [PowerShell: ファイル一覧を取得（フルパス・ファイル名のみ）](https://step-learn.com/article/powershell/101-file-list.html)
* [certutilコマンドの出力結果の違い（Win8.1 / Win10）](https://qiita.com/nkojima/items/1dc5f021c9f34fefaf77)
ExcelVBAとSeleniumBasicでChromeを操作する際、ブラウザ上でメッセージボックスを表示する

# やりたいこと
ExcelVBAでSeleniumBasicを使ってChromeを自動操作するとき、
ユーザーにメッセージを伝えたいことがあります。

その場合、VBAの```msgbox```を使っても良いですが、
一旦画面をExcelに戻さないといけないので、不便です。

そこで、Seleniumで操作しているブラウザ上でそのままメッセージを表示できると便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/828c9330-b4f6-6e1c-5951-0dd25ed031f8.png)

# コード
コードは以下の通りです。
前提として、SeleniumBasic、ChromeDriverはインストール済み、参照設定でSelenium Type Libraryを設定済みとします。

```vb
'プロシージャの外で宣言すると、プロシージャが終わってもブラウザが消えない
Private Chrome As New selenium.ChromeDriver
  
Sub msgbox_on_chrome()
  '適当なサイトにアクセス
  Chrome.Get "https://www.google.com/"
  
  'サイト上でメッセージを表示
  text = "これはVBAからのメッセージです。何か検索してください。"
  Chrome.ExecuteScript ("alert('" & text & "');")
End Sub

```

コードの一行目でselenium.ChromeDriverを宣言しているのは、
プロシージャの外でドライバの宣言をすると、プロシージャの実行が終わってもブラウザが消えなくなるためです。
詳しくはこちら
https://qiita.com/shibahead/items/0a17efaa70995756261c

# おわり
以上です。お疲れ様でした。
【VBA Selenium】Chromeを閉じずにVBAコードを終わる

# やりたいこと
VBAでSeleniumを使ってChromeを操作するとき、
VBAのコード実行が完了すると、Chromeが勝手に閉じてしまう。
これを閉じずにVBAコードを終わりたい。
そうすれば、下図のように別の作業を手作業で挟むことができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/ffde3126-1965-c80c-0af1-7827ee6aad4a.png)

# サンプルコード
以下サンプルです。
前提として、SeleniumBasic、ChromeDriverはインストール済み、参照設定でSelenium Type Libraryを設定済みとします。

ここで重要なのが、１行目でSubの外でDriverを宣言している点です。
こうすることで、Subが終了してもブラウザが消えません。
ただし、いつまでもDriverが残ることになるため、本当に処理を終了するときには
Driver.Quitを入れないと、次回実行時にエラーがでます。
```vb
Private Driver As New Selenium.ChromeDriver
  
'最初に実行するVBA
Sub Macro1()
    
    '古いDriverが残っているとエラーになるのできれいにする
    If Not Driver Is Nothing Then
      Driver.Quit
      Set Driver = Nothing
    End If
    
    'Driverでどこかにアクセスして、何か作業があれば作業させる。
    Driver.Get "https://google.com"

    '一旦VBA１はおわり。
    'ブラウザは開いたままなので、このあと人間の手作業をはさむ。
End Sub

'ここで、人間が手作業する。(例えば何か検索してください)
'手作業が終わったら、次のMacro2を実行することもできる。

Sub Macro2()
    
    'Driverを引き継いで、別の作業をさせる（例：検索結果の１番上のテキストをプリント）
    Debug.Print Driver.FindElementsByClass("MjjYud")(1).Text
    
    'ブラウザ終了
    Driver.Quit

End Sub

```

# おわり
以上です。お疲れ様でした。
FetchError: request to https://registry.npmjs.org/ failed, reason: connect ECONNREFUSED 2606:4700::6810:1623:443


えとせホストに追加することで`npm install`できます

```bash
echo 104.16.20.35 registry.npmjs.org | sudo tee -a /etc/hosts
```

https://qiita.com/raiga0310/items/ba198156cfb5a5f8462b
PHP：配列の並び替えも注意点ある。キーが消え去るケースもあるので要注意（sort、rsort、asort、arsort、ksort、krsort）

# sort関数：配列の要素を昇順に並び替える
※降順　rsort

注意点！！　キーが消え去り、キーは0から順番に割り振られてしまう。
これがマッチする用途もあるのだろうが知らないと怖い。

```php
$arr1 = [3, 1, 2];
sort($arr1);
var_dump($arr1); // [0] => int(1) [1] => int(2) [2] => int(3)
```

```php
$arr2 = ['a' => 3, 'b' => 1, 'c' => 2];
sort($arr2);
var_dump($arr2); // [0] => int(1) [1] => int(2) [2] => int(3)
```


# asort関数：キーと値のペアを維持しつつ配列の要素を昇順に並び替え
※降順 arsort

```php
$arr3 = ['a' => 3, 'b' => 1, 'c' => 2];
sort($arr3);
var_dump($arr3); // ['b'] => int(1) ['c'] => int(2) ['a'] => int(3)
```


# ksort：配列のキーを昇順に並び替え
※降順　krsort

```php
$a = array('K'=>32,'D'=>77,'A'=>8,'B'=>9);
print_r($a);

var_dump(ksort($a)); // 第2引数を指定していないので、SORT_REGULARでソート
print_r($a);
```

実行結果
```php
Array
(
    [K] => 32
    [D] => 77
    [A] => 8
    [B] => 9
)
bool(true)
Array
(
    [A] => 8
    [B] => 9
    [D] => 77
    [K] => 32
)
```


# 結論：ケースに合わせて使い分ける
SASを生成してBlobからファイルをダウンロードする（Python）

# はじめに
Azure Blob StorageをPythonから操作します。
今回はAutoMLでトレーニングされた一番精度の良いモデルの「outputs」フォルダのSAS生成をPythonから行い、SAS URIを使ってローカルファイルにダウンロードしてみます。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2976188/7128ce46-2d54-6e8e-9981-8aaad31ea6ca.png)
# 環境
+ OS Windows 10(NVIDIA GTX 1650Ti,16GB RAM, i5-10300H CPU)
+ Visual Studio Code 1.73.1
+ Python 3.8

# BLOBのSAS生成
それではPythonからSAS生成をします。

以下のコードでは、コンテナーにある特定のフォルダのSASを生成し、このSASトークンを使ってローカルファイルにダウンロードします。
```sas.py
import os
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient, BlobSasPermissions,  generate_blob_sas
import datetime
import requests

try:
    account_url = "https://<ストレージアカウント>.blob.core.windows.net"
    credential = DefaultAzureCredential()
    blob_service_client = BlobServiceClient(account_url, credential=credential)
    container_name = "<コンテナー名>"
    container_client = blob_service_client.get_container_client(container=container_name)

    outputs_path = "<BLOB名>"
    blob_list = container_client.list_blobs(name_starts_with=outputs_path)

    outputs_folder = "<ローカル先のフォルダ名>"
    if not os.path.exists(outputs_folder):
        os.makedirs(outputs_folder)

    for blob in blob_list:
        sas_token=generate_blob_sas(
        blob_service_client.account_name,
        account_key="<アカウントキー>",
        container_name=container_name,
        blob_name=blob.name,
        permission=BlobSasPermissions(read=True),
        expiry=datetime.datetime.utcnow() + datetime.timedelta(hours=1)
    )

        sas_url=f"{account_url}/{container_name}/{blob.name}?{sas_token}"
        response = requests.get(sas_url)
        print(sas_url)
        if response.status_code==200:
            file_path=os.path.join(outputs_folder,(blob.name.split("/")[-1]))
            with open(file_path, mode="wb") as download_file:
                download_file.write(response.content)
        else:
            print("Failed to download the file")

except Exception as ex:
    print("Exception:")
    print(ex)

```
`account_url`にはストレージアカウント名を入れます。ポータルサイトから確認できます。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2976188/440d8a00-5db3-cae8-69d9-98534b57f382.png)

`container_name`にはSAS生成をするBLOBが入っているコンテナー名を入れます。
今回SAS生成する「outputs」フォルダは「azureml」というコンテナーにあるので、次のように入力します。
```
container_name = "azureml"
```
続いて`outputs_path`には「outputs」フォルダが入っているパスを入力します。
```
outputs_path = "ExperimentRun/dcid.sleepy_spider_ryfkltxvgt_2/outputs/"
```
`outputs_folder`はダウンロード先のローカルのフォルダの名前を入れます。
今回は`outputs`という名前のフォルダにすべてダウンロードするようにします。
```
outputs_folder = "outputs"
```
後の流れとしては、`generate_blob_sas()`でSASトークンを作成し、その後ストレージリソースURIとSASトークンを「？」でつなげてSAS URIを作ればダウンロードできます。

`expiry`には1時間の有効期限をつけています。

実行後、ローカルの「outputs」フォルダにダウンロードされたファイルが入っているのを確認できます。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2976188/9ab5fad6-7d49-025e-7bf0-1110e2faf613.png)
スプレッドシートでシート切替時に勝手に範囲選択される問題（交互の背景色）

こんにちは。備忘録も兼ねて書かせて頂きます。

## 問題

スプレッドシートでシートを切り替えるたびに、なぜか全範囲が選択状態になります。原因は交互の背景色で、それを設定しているとその範囲が勝手に選択されてしまうようです。どうも見にくい上に操作ミスで全部消してしまいそうな焦燥感に駆られてしまいますので、どうにかすべくchatGPTに聞いてみました。

## 解決法とそのメリット

chatGPTに教えてもらった解決方法は以下のものでした。

「条件付き書式でこう書け。=mod(row(),2)」

なるほど、さすがchatGPTはかしこいです。早速やってみました。ちゃんと交互の背景色になる上に、シートを切り替えても勝手に範囲選択されたりしません。素晴らしい。

ですが以下の問題が。

## 解決法のデメリット

条件付き書式は重い重いと言われますが、本当にその通りで上記の書式を入れたところやはり重たいです。行を追加したりする度に処理が走り、右上のプログレスバーがえっちらおっちら動き出します。これはいかん。重い。

というわけで、泣く泣く元の交互の書式設定に戻しました。

## 分かったこと

今回分かったことは、以下の通りです。

1. やっぱり条件付き書式は重い
1. 交互の背景色は内部で最適化されているらしく軽い。でもシートを切り替える度に範囲選択されてしまう。

何か良い方法をご存知の方おられましたら、教えていただけますと幸いです。

なお蛇足ですが、chatGPTはこの回答意外にも設定をいじる方法も教えてくれました。Googleスプレッドシートには、シートを切り替えるごとに範囲を選択すると言う設定があるそうです。もちろんそのような設定は実際にはないのですが、さも実在するが如くスラスラと語るchatGPTくんは今後に期待したいところです。

以上です。ご精読ありがとうございました。
Ansible初心者

:writing_hand:SREエンジニアを目指してAnsibleで簡単に自分が勉強したことをまとめます。

# 目次
1.Ansibleとは
2.YAMLについて（特徴）]
3.Playbookの文法
　・配列

## 1.Ansibleとは
   　-Pythonで書かれる構成管理のツール
    　　-管理対象のサーバにわざわざインストールする必要なし　＊他の構成管理ツールは必要
    　　-設定ファイルはYAMLで記載
    　　-モジュールたくさん
    　　-冪等性が担保されている。
　　　＊冪等性（べきとうせい)：何回実行しても実行結果が同じ状態になること

## 2.YAMLについて(特徴)
　　　-インシデントと改行は構造的な意味を持っている。
　　　-文章内でTabは含まれない。（使えない）
　　　-コメントアウト使える。（先頭に＃つける）
### 3.Playbookの文法
#### 配列
・先頭に - をつけると配列になる。
```書き方
　　　　         - 要素1
　　　　         - 要素2
　　　　         - 要素3
```
・入れ子構造の表し方
```書き方
　　　　         - 要素1
           -
             - 入れ子要素1
             - 入れ子要素2
             - 入れ子要素3
　　　　         - 要素2
　　　　         - 要素3
```
※入れ子構造
|　　　　　　　　  　　　　　　　　   　　　　　　　　　　　　　　　　　　　　　　　　　|
|:-:|
![Ansible.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3172936/0109c037-0be9-e7ef-d7b8-23bfc63ab063.png)
sudoは必要なときに使う

ターミナルで入力するコマンドでたまに出てくる`sudo`だが、これのせいで私は半日程度苦しんだのでここに残しておく。

Ruby on Rails チュートリアルをやっていたときに途中で自分のコードがおかしくなり、仕方なく筆者の方のgithubからクローンしてやり直すことになった。

その際master.keyファイルが無かったため、
[master.keyが見つからない問題 [初見殺し] - はじめてのデプロイで嵌るポイント](https://qiita.com/naokit-dev/items/5e09b2fb4b64a29712e4)
の記事などを参考にしてcredentialsyml.encも消してから自分で新しく二つとも作り直そうとして、ターミナルで
```
sudo EDITOR="vi" rails credentials:edit
```
を実行した。

「管理者権限が必要なんやなー」くらいのノリで実行したが、
結論から言えばこの`sudo`が悪さをしており、`sudo`無しで
```
EDITOR="vi" rails credentials:edit
```
と実行すれば正解であった。

上記で`sudo`を使用した弊害として、`rails  s` `rails routes`などのコマンドを打つと
```
/Users/ユーザー名/.rbenv/(略)/encrypted_file.rb:118:in `binread':　Permission denied @ rb_sysopen - /Users/ユーザー名/environment/sample_app/config/master.key (Errno::EACCES)
```
というエラーが出た。

どうやらファイルへの権限から来るエラーのようだったが、
前後どっちのファイルの権限を直せば良いのかわからなかった。

`.rbenv`の方の権限を直そうとしたがうまくいかず、
`master.key`の方も何回も作り直したがうまくいかなかった。
しかし`master.key`を作り直すというのは実は合っていたようだ。

`sudo`は管理者権限で何でもできる便利なコマンドだなーと思っていたら、
どうやら`sudo`を使ってターミナルで実行すると生成されたファイルとかも管理者じゃないとアクセスとかがダメになってしまうらしいという記事
[Ruby gem install bundler で Permission denied エラーになった](https://chaika.hatenablog.com/entry/2019/06/06/190000)
等を見つけたので、試しに`sudo`を外して
```
EDITOR="vi" rails credentials:edit
```
で`master.key`を作ったら一発だった。

当然`sudo`が便利なときや必要な時はあるのだろうが、こういったトラブルの元になることもあるため慎重に使っていきたい。
PHP：二つの配列を結合する方法大きく二つ。基本はarray_merge使用だがいくつか注意点ある

# + の場合：左辺の要素数よりも右辺の要素数が多ければ、その多い要素だけを左辺の要素の後ろに結合

```php
$arrA1 = ['a', 'b'];
$arrA2 = ['c', 'd', 'e'];
$arrA = $arrA1 + $arrA2;
var_export($arrA);
echo PHP_EOL;
// $arrA は　　['a', 'b', 'c', 'e'] が入っている。
```




# array_merge の場合：「文字列ならば」想像通り順序よく結合してくれる

```php
$arrB1 = ['a', 'b', 'c'];
$arrB2 = ['d', 'e'];
$arrB = array_merge($arrB1, $arrB2);
echo PHP_EOL;
var_export($arrB);
// $arrB　は ['a', 'b', 'c', 'd', 'e'] が入っている。
```

# しかし、array_merge はキーが数字の場合、キーが破棄される

```php
# array_mergeの注意点
$arrC1 = ['1' => 'a'];
$arrC2 = ['10' => 'b'];
$arrC = $arrC1 + $arrC2;
var_dump($arrC); // キーが数字でもキーとして保持して正常に動作する

$arrD1 = ['1' => 'a'];
$arrD2 = ['10' => 'b'];
$arrD = array_merge($arrD1, $arrD2);
var_dump($arrD); // array_mergeの場合、キーが数字だと破棄されてキーが0から割り振られてしまう。
```
ChatGPTに日本語の分かち書きをやらせてみる

# ChatGPTに日本語の分かち書きをやらせてみる
やる意味あるかは置いておき、ちょっと興味があったのでChatGPTに日本語の分かち書きをさせてみました
## 分かち書きについて
昔から、や、今でもNLPのためにMeCabなどで形態素解析させていたり、最近では分かち書きせずにMLの入力を処理する **[CANINE](https://arxiv.org/abs/2103.06874)** なんてのもあるようですが、とにかく日本語を機械に処理させるには一工夫が必要のようです
## 早速試してみる
咄嗟に日本語の文を考えろと言われてもちょっと困るので、今朝(2023/02/17)のニュースの一部をちょっとやってもらった。
(ChatGPTなら生成してくれるか？)
![chatGPT_worked_001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145338/0ae7d11e-3536-dca9-b88d-6608cde69c65.png)
形態素解析ではなく、文節に区切った方が個人的に使い勝手がよいのでそうしましたが、如何様にもできそうです。 
## 感想
ChatGPTがどのような入力処理をしているのかは伺い知れませんが、仮名への変換精度といい、もうこの用途でのMeCabの出番はなくなりそうです。そもそもNLPでの入力処理ならもうMeCabは使わなくなってるのかもしれませんが、もうちょいローテクな用途(内緒)ではまだ分かち書きしたいところがあるもんで
## 最後に
面白いおもちゃ(ChatGPT)をありがとう
【最新版対応】bootstrap5.3の最初のテンプレート

```html
<!doctype html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
	<title>タイトル!</title>
</head>
<body>
	<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.min.js" integrity="sha384-Rx+T1VzGupg4BHQYs2gCW9It+akI2MM/mndMCy36UVfodzcJcF0GGLxZIzObiEfa" crossorigin="anonymous"></script>
</body>
</html>
```
忘れるgit備忘録

# 忘れるgitの備忘録
自分用です。
# git clone
```sh
git clone https:xxx.xxx
```
# sshでcloneするとき
```sh
git clone [ssh configの接続名]:xxx/xxx
#branch　指定
git clone -b [ブランチ名][リポジトリのアドレス]
```
# 接続
```sh
# remoteリポジトリの確認
git remote　-v

# remoteリポジトリ削除
git remote rm origin http://xxxxxx.xxx/xxxx

#remoteリポジトリの追加
git remote add origin http://xxxxxx.xxx/xxxx
```

# branch系
```sh
# branchの作成
git branch [branch名]
# branchの移動
git checkout [branch名]
#　 branchの削除
git branch -d [branch名]

```

# add commit push
```sh
# ステージング
git add .
# commit
git commit -m "コメント"

# push
git push 
```
paizaラーニング レベルアップ問題集 新・Bランクレベルアップメニュー JavaScript 【条件判定 2】視力検査

【条件判定 2】視力検査 (paizaランク C 相当)

https://paiza.jp/works/mondai/b_rank_new_level_up_problems/b_rank_new_level_up_problems__vision_test

# 解答例
コードが少し長くなったので、細かなところのミスに気をつけました。

>2 回失敗する前に 2 回成功した場合、その段階について「合格」、それ以外の場合を「不合格」

なので、先に2回失敗したら、その後2回以上成功しても不合格判定なので、eye配列で、未判定、失敗、成功を保持するようにしました。eye配列のインデックスが小さい順にA,B,C,Dと対応しています。

```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N] = lines[0].split(" ").map(Number);

const eye = Array(4).fill(-1);//視力、未判定-1、失敗0、成功1
const success = Array(4).fill(0);//テスト成功数
const failure = Array(4).fill(0);//テスト失敗数
//視力テスト
for (let i = 1; i <= N; i++) {
  const [T, J] = lines[i].split(" ");
  if (T === "TA") {
    if (J === "ok") {
      success[0] += 1;
    } else {
      failure[0] += 1;
    }
  } else if (T === "TB") {
    if (J === "ok") {
      success[1] += 1;
    } else {
      failure[1] += 1;
    }
  } else if (T === "TC") {
    if (J === "ok") {
      success[2] += 1;
    } else {
      failure[2] += 1;
    }
  } else if (T === "TD") {
    if (J === "ok") {
      success[3] += 1;
    } else {
      failure[3] += 1;
    }
  }

  //合格判定
  for (let j = 0; j < 4; j++) {
    if (success[j] === 2 && failure[j] < 2 && eye[j] === -1) {
      eye[j] = 1;//成功
    } else if (failure[j] === 2 && success[j] < 2 && eye[j] === -1) {
      eye[j] = 0;//失敗
    }
  }

}

//視力結果
const result = eye.indexOf(1);

if (result === 0) {
  console.log("A");
} else if (result === 1) {
  console.log("B");
} else if (result === 2) {
  console.log("C");
} else if (result === 3) {
  console.log("D"); 
} else {
  console.log("E");
}
```
# 解答例(C++の場合参考)
視力テストをするところを関数にした。
視力レベルを表すインデックスを活用した。(A=0,B=1,C=2,D=3,E=4)
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

let tester_level = 4;//視力を表すインデックス、初期値4はE相当

const ok = Array(4).fill(0);//テスト成功数
const ng = Array(4).fill(0);//テスト失敗数
//ok,ngのインデックスが視力に対応

//視力テストの関数定義
const tests = (level, result) => { //level：視力レベルを表すインデックス、result：okまたはng
  if (result === "ok") {
    ok[level]++;
  } else {
    ng[level]++;
  }
  if (ok[level] === 2 && ng[level] < 2) { //ok2回、ng2回より前に。ng2回以上ならok2回以上でも不合格
    tester_level = Math.min(tester_level, level);//合格した段階のうち、最も良い段階優先
  }
};

//メイン
const [n] = lines[0].split(" ").map(Number);

//test_nameとlevel_nameのインデックスを視力レベルに対応させる
const test_name = ["TA", "TB", "TC", "TD"];
const level_name = ["A", "B", "C", "D", "E"];

for (let i = 1; i <= n; i++) {
  const [test, result] = lines[i].split(" ");
  //合格判定
  for (let j = 0; j < 4; j++) {　//インデックスjが視力レベルに相当
    if (test === test_name[j]) {
     tests(j, result);//視力テスト
    }
  }
}

//視力結果
console.log(level_name[tester_level]);
```
Dockerコンテナでyumもapt-getも使えないとき

# 概要
Dockerで`Alpine`イメージを使っているとき、`yum`も`apt-get`も使えないので`apk`を使う必要があります。
Linuxディストリビューションごとのパッケージ管理ツールは下記のようになっています。
- Ubuntu なら apt-get
- Centos なら yum
- Apline では apk

https://qiita.com/YumaInaura/items/57ebe9bc572af4da799a


Linuxディストリビューションの判別は`/etc/[ディストリビューション名]-release`を見ればわかるようです。

https://qiita.com/koara-local/items/1377ddb06796ec8c628a
ECS exec でログを有効化する

# はじめに
ECS execでログを有効化した際のメモです。

# 手順
## 1. ECSクラスターでロギングを有効化
```ecs_cluster.ts
import { Construct } from 'constructs';
import * as logs from 'aws-cdk-lib/aws-logs';
import * as ecs from 'aws-cdk-lib/aws-ecs';

export class EcsCluster {
  private scope: Construct;
  public readonly cluster: ecs.CfnCluster;

  constructor(_scope: Construct, clusterName: string) {
    this.scope = _scope;
    const env = this.scope.node.tryGetContext('env');

    // ロググループを作成
    const ecsExecLogGroupName = `/ecs/ecs-exec/logs/${env}-log-group`;
    const ecsExecLogGroup = new logs.CfnLogGroup(this.scope, 'EcsExecLog', {
      logGroupName: ecsExecLogGroupName,
      retentionInDays: 30
    });

    // クラスターでログを有効化
    this.cluster = new ecs.CfnCluster(this.scope, `Cluster`, {
      clusterName,
      configuration: {
        executeCommandConfiguration: {
          logging: ecs.ExecuteCommandLogging.OVERRIDE,
          logConfiguration: { cloudWatchLogGroupName: ecsExecLogGroupName }
        }
      }
    });
    this.cluster.addDependency(ecsExecLogGroup);
  }
}
```
## 2. ECSタスクロールを追加
```task-role.ts
...
    const ecsTaskRole = new iam.CfnRole(
      this.scope,
      'EcsTaskRole',
      {
        assumeRolePolicyDocument: new iam.PolicyDocument({
          statements: [
            new iam.PolicyStatement({
              effect: iam.Effect.ALLOW,
              principals: [new iam.ServicePrincipal('ecs-tasks.amazonaws.com')],
              actions: ['sts:AssumeRole']
            })
          ]
        }),
        policies: [
          {
            policyDocument: new iam.PolicyDocument({
              statements: [
                new iam.PolicyStatement({
                  effect: iam.Effect.ALLOW,
                  actions: [
                    'ssmmessages:CreateControlChannel',
                    'ssmmessages:CreateDataChannel',
                    'ssmmessages:OpenControlChannel',
                    'ssmmessages:OpenDataChannel',
                    'ssm:UpdateInstanceInformation',
                    'logs:DescribeLogGroups',
                    'logs:CreateLogStream',
                    'logs:DescribeLogStreams',
                    'logs:PutLogEvents'
                  ],
                  resources: ['*']
                })
              ]
            }),
            policyName: `EcsTaskRolePolicy`
          }
        ],
        roleName: `${env}-ecs-task-role`
      }
    );
...
```

# 参考
https://dev.classmethod.jp/articles/ecs-exec-logging/

https://dev.classmethod.jp/articles/ecs-exec-use-task-role-for-logging/

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html#ecs-exec-logging

https://aws.amazon.com/jp/blogs/news/new-using-amazon-ecs-exec-access-your-containers-fargate-ec2/
Paraviewで3Dデータを「綺麗に」可視化する

## はじめに
Qiitaには少し古いですがこんな記事があります。

[UE4で科学可視化やってみよう](https://qiita.com/menonon/items/e8c5be640042c8bdf7e3)

この記事では，元データをparaviewで一度可視化して3Dデータとして保存した後に，その3Dデータをblenderで変換して，変換したデータをさらにUE4で編集することで綺麗な可視化を行っています。
が，個人的にはいくつか課題も感じました。
① 記事で使用されているBlenderのバージョンがもはや古くなっているためか，記事の通りやっても手元で再現できなかった
② UE4をEPIC Games経由でダウンロードすることが，職場の環境的に厳しい。
③ 手順が多くて正直面倒

上記記事ほどクオリティが高くなくてもいいので，paraview単体でもっと簡単に綺麗な3D可視化ができないか？というのが今回の主題です。

## 結論
**超簡単にできる。**

## やり方
今回使ったparaviewのバージョンはwindows版の5.10.0です。
サンプルデータとして，下図のような球を用意しました。

![スクリーンショット 2023-02-17 192918.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348972/c4d10f18-30f7-3247-0e79-d8b07b0501d0.png)


これを「綺麗に」してみます。
この時重要なのが，3D物体の表面が描画されていることです。
描画方法はContourでもClipでもIso Volumeでも構いません。
Pipeline Browserで表面を描画しているアイテムを選択し，画面左下のPropertiesで次のように操作します。
① Searchボックス右の歯車を押し，詳細設定を行えるようにする
② Ray TracingのScale ModeをAll Approximateにする
③ 同じくMaterialを，好きなものに設定する (下画像ではMetal_Gold_brushed)

![スクリーンショット 2023-02-17 190745.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348972/d4d9dbf7-8768-6986-e948-0cd8d08edab0.png)

これだけだとまだ変化はありません。
次に，Propertiesの一番下まで行き，Ray Traced RenderingのEnable Ray Tracingにチェックを入れます。
その後，
① Back EndをOSPRay pathtracerにする
② Samples Per Pixelを5にする
③ Denoiseにチェックを入れる
④ 必要であれば背景色を適宜変える

ここまで操作すれば，下図のような可視化ができていると思います。

![スクリーンショット 2023-02-17 191900.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348972/61cbca98-51be-de96-8a59-b4f9154d389a.png)

あとは，見た目がいい感じになるように調整していきます。以下は一例。

![スクリーンショット 2023-02-17 192248.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348972/35c01d0d-96b3-b9d7-54b7-6a5932a6a879.png)

操作は以上で，paraviewだけでとても簡単に「綺麗な」可視化を行うことができました。

## さいごに
今回の記事は[こちらのページ](https://www.rccm.co.jp/icem/pukiwiki/index.php?SPH%E3%81%AE%E3%83%AC%E3%82%A4%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%B3%E3%82%B0%E5%8F%AF%E8%A6%96%E5%8C%96)を参考にしました。
正直に言えばこの記事よりも詳細に説明されているので，参考にしてください。
【VBA】CLngで文字列をLong型に変換！！

CLngは、VBAのデータ型変換関数の一つで、Long型に変換するために使用されます。CLng関数を使用すると、文字列や数値など、異なるデータ型の値をLong型に変換することができます。

例えば、以下のようなコードを実行することができます。

```
Dim str As String
Dim num As Integer
Dim lngNum As Long

str = "1234"
num = 1234

lngNum = CLng(str) ' 文字列をLong型に変換
Debug.Print lngNum ' 結果：1234

lngNum = CLng(num) ' IntegerをLong型に変換
Debug.Print lngNum ' 結果：1234
```
上記の例では、CLng関数を使用して、文字列 "1234" と整数値 1234 をLong型に変換しています。Long型は、整数値を格納するために使用されるデータ型で、数値の範囲は-2,147,483,648から2,147,483,647までです。

VBAには、他にも多くのデータ型変換関数があります。例えば、CInt関数は整数型、CDbl関数は倍精度浮動小数点型、CStr関数は文字列型に変換するために使用されます。
python maya Minimize Rotation Curve

```python
def minimizeRotationCurves(obj):
    rotateCurves = mc.keyframe(obj, attribute=('rotateX','rotateY', 'rotateZ'), query=True, name=True)

    if not rotateCurves or len(rotateCurves) < 3: return
    keyTimes = mc.keyframe(rotateCurves, query=True, timeChange=True)
    tempFrame = sorted(keyTimes)[0] - 1
    mc.setKeyframe(rotateCurves, time=(tempFrame,), value=0)
    mc.filterCurve(rotateCurves)
    mc.cutKey(rotateCurves, time=(tempFrame,))

curve_transforms = [cmds.listRelatives(i, p=1, type='transform')[0] for i in cmds.ls(type='nurbsCurve', o=1, r=1, ni=1)]
for curve in curve_transforms:
    minimizeRotationCurves(curve)
```
Amazon Connect で音声データをアップロードしたらなぜか聞き取り難くなった？

# 概要

この記事はAmazon Connectを利用中の方に向けた記事です。（かつ、macユーザー向けです）

Amazon Connectにはアップロードした音声データを再生する機能があります。macで音声データを再生した時はキレイに聞こえるのにアップロードした音声を聞くと摩擦音（サ行などの発音）の所がノイズ混じりに聞こえるという現象に遭遇しました。この問題を回避する方法を紹介したいと思います。

# Amazon Connect って何？

Amazon Web Service のアカウントとパソコンがあれば、コールセンターを開設できるAmazonのサービスです。

Amazon Connectについて書いた記事があるのでご興味があればリンク先をご覧ください。
[Amazon Connect できること](https://qiita.com/tatsumi_t2/items/4c0046df2e2b62b72890)

# プロンプトの仕様について

Amazon Connect にはプロンプトと呼ばれる音声ガイダンスを再生する機能があります。

音声ガイダンスはアップロードした音声データを再生することができます。これ以外にもテキストを入力するとそのテキストを音声に変換して出力する機能もあります（ボカロみたいな感じ。歌は唄はないけれど）

このプロンプトは、アップロードできる音声データの仕様が決まっています。

**wav形式でサンプリングレートが8kHzです。**

普通に音声データを作ると大抵は44.1kHzなのでかなり低い数値です。
詳しい仕様はリンク先を参照してください。
[https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/prompts.html](https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/prompts.html)

プロンプトに44.1kHzのwav形式の音声データもアップロードすることができます。
しかし、高サンプリングレートの音声データを再生すると冒頭で説明したように聞き取り難い音になってしまうようです。

# 回避策

音声データのサンプリングレートを低レートに変換することで問題を回避することができます。
44.1kHz　→ 8kHz

macには標準で「afconvert」という音声データを変換するコマンドがありますので、ターミナルでコマンドを実行してください。

8kHzに変換する例は次の通りです。

```
afconvert -d UI8@8000 元データファイル名.wav 変換後ファイル名.wav
```

変換後のファイルをプロンプトに登録すれば問題を回避することができるハズです。
ガントチャート（JSライブラリ： jquery.ganttView）をカスタマイズしてみた（１行に複数タスク）

# はじめに

今となっては古のJSライブラリ

https://github.com/thegrubbsian/jquery.ganttView

上記ライブラリのスケジュール管理オブジェクトを１行内に複数配置するカスタマイズをしてみたので、勘所をメモ書きしておきます。

ニッチな内容だけど、誰かの参考になれば幸いです。

# スタイルシートの追加

標準の管理オブジェクト（チャート部に置くスケジュール線）

```css
div.ganttview-block {
	position: relative;
	height: 25px;
	background-color: #E5ECF9;
	border: 1px solid #c0c0c0;
	border-radius: 3px;
	-moz-border-radius: 3px;
	-webkit-border-radius: 3px;
}
```

を基にして、1行内に複数配置できるスタイルシートを追加します。

```css
div.ganttview-block-cells {
	position: relative;
	height: 25px;
}

div.ganttview-block-cell {
	position: absolute;
	height: 25px;
	background-color: #E5ECF9;
	border: 1px solid #c0c0c0;
	border-radius: 3px;
	-moz-border-radius: 3px;
	-webkit-border-radius: 3px;
}
```

ganttview-block-cellsがコンテナとなる階層で、配下に複数タスク（ganttview-block-cell）が格納されるイメージになります。

# スクリプト側の改修前イメージ

```javascript
function addBlocks(div, data, cellWidth, start) {
    //  ～省略
    // 入力データのループ
    for (var i = 0; i < data.length; i++) {
        for (var j = 0; j < data[i].series.length; j++) {
            // タスクのオブジェクト生成
            block = jQuery("<div>", {"class": "ganttview-block","～",""});

            // １行データ登録
            addBlockData(block, data[i], series);
            // ～後処理省略

            jQuery(rows[rowIdx]).append(block);
            // ～後処理省略
        }
    }
}
```


# スクリプト側の改修後イメージ

```javascript
function addBlocks(div, data, cellWidth, start) {
    //  ～省略
    // 入力データのループ
    for (var i = 0; i < data.length; i++) {
        for (var j = 0; j < data[i].series.length; j++) {
            var series = data[i].series[j];
            
            if("複数オブジェクトのキー" in series && series."複数オブジェクトのキー".length > 0){
                /// 新規追加したスタイルで箱を生成
                var 複数オブジェクト群格納用 = jQuery("<div>", {
                      "class": "ganttview-block-cells"
                });
                for (var k = 0; k < series."複数オブジェクトのキー".length; k++) {

                    // ～省略

                    // 新規追加したスタイルでタスクのオブジェクト生成
                    var block = jQuery("<div>", {"class": "ganttview-block-cell","～",""});
                    // ループの中では格納用に追加
                    複数オブジェクト群格納用.append(block);
                }
                // 全部の複数タスクを可能し終えたら
                jQuery(rows[rowIdx]).append(複数オブジェクト群格納用);
                // ～後処理省略
            }else{
            
                // タスクのオブジェクト生成
                block = jQuery("<div>", {"class": "ganttview-block","～",""});

                // １行データ登録
                addBlockData(block, data[i], series);
                // ～後処理省略
                jQuery(rows[rowIdx]).append(block);
                // ～後処理省略
            }
        }
    }
}
```

# 画面イメージ

+ 改修前

![改修前.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/271ad9b9-ed29-0ff6-9677-66d17aefda7c.jpeg)

+ 改修後

![改修後.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/18508929-cd0d-81fd-ecd9-8b9b3e63af59.jpeg)

無事に、複数タスクを表示できました。