OmniAICreator/Qiita-1.07M huggingface dataset:
結晶構造をjupyterlabでインタラクティブに可視化する

## はじめに
マテリアルズインフォマティクスの研究をしていると、jupyterlabで結晶構造を可視化したいことがよくあります。適当にグラフに原子をプロットすることも可能ですが、マウスでインタラクティブに動かしながら、様々な角度から見ることができれば便利です。
今回は結晶構造の可視化を簡単に行える、crystal-toolkitを紹介します。

## インストール
```shell
pip install crystal-toolkit
```
jupyterlabのバージョンは3以上にしてください。2だと追加でextensionをインストールする必要があります。

## 結晶構造を可視化してみる
jupyterlabで以下を実行することで、簡単に可視化可能です。
```python
from crystal_toolkit.renderables import StructureGraph
from pymatgen.analysis.local_env import MinimumDistanceNN
from pymatgen.core import Structure

struct = Structure.from_file("ZnO.cif")
env = MinimumDistanceNN()
graph = StructureGraph.with_local_env_strategy(struct, env)
graph
```
これを実行すると、出力部分に以下のような画像が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334977/41dbb8c3-de19-b7e6-3035-962c17d9a341.png" width=50%>

マウスで結晶を回転させることができ、原子にカーソルを合わせると座標が表示されます。

## コードの説明
```python
from crystal_toolkit.renderables import StructureGraph
```
この部分ではcrystal_toolkitの`StructureGraph`をインポートしているように見えますが、実はpymatgenの`StructureGraph`をインポートしています。その上で、`StructureGraph`に`get_scene()`というメソッドを追加して返しています。この`get_scene()`により、jupyterでインタラクティブなオブジェクトを表示することが可能になっています。

あとはこれをインスタンス化すればよく、`Structure`オブジェクトと、結合を判断するためのクラス`MinimumDistanceNN`を渡すだけです。結合判断のクラスは他のもの（`CrystalNN`など）でも問題ありません。

## 見た目を変える
結晶の見た目を変えることも可能です。上記のように、`get_scene()`をハックすれば良さそうです。ソースコードを見ると、
```python
StructureGraph.get_scene = get_structure_graph_scene
```
となっています。`get_structure_graph_scene`を変更してみましょう。
```python
from crystal_toolkit.core.legend import Legend
from crystal_toolkit.renderables.structuregraph import get_structure_graph_scene

StructureGraph.get_scene = lambda x: get_structure_graph_scene(
    x,
    bond_radius=0.2,
    legend=Legend(struct, color_scheme="VESTA")
)

graph = StructureGraph.with_local_env_strategy(struct, MinimumDistanceNN())
graph
```
`get_structure_graph_scene`の引数を変えてみました。bondを少し太くして、VESTAと同じ原子の色を用いて描画します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334977/8c673b42-2039-ae46-1931-fbd9108720fd.png" width=50%>
見た目を変えることができました。より細かい調整をする場合は`Scene`オブジェクトを自分で作る必要があります。

## まとめ
crystal-toolkitを使ってjupyterlabで簡単に結晶構造を可視化することができました。これの他にも分子や相図など、Materials Projectのページのような見た目で表示することが可能なようです。
これらも便利なものがあれば紹介したいと思います。
Githubのアカウントを削除して再登録してすぐに同じアカウント名を使う方法

Githubのアカウントを作ったんだけど、アカウント2つ作ってあったようだ

古い方のIDは書籍の勉強でいろいろ設定をしていたので、いらないかと思い削除

削除して、やっぱりIDは古い方のIDを使いたい

まあ変更すればいいかな？って思い残っている方のアカウントID変更しようと思ったらできない

というわけでサポートセンターに問い合わせ

対応は英語でした

どうやら削除後90日間はID履歴は残るらしい

サポートは今回は対応してくれた※ありがとう

※90日待てばデータは消えるみたいだからサポートが対応してくれなかったら待つしかない

削除したアカウントのIDを伝えて、削除した方のメールアドレスを使いたい方のアカウントに登録しておく

すると両方のアカウントの所有権を証明できるので、あとはサポートがIDを変更してくれた

自分みたいな人はそうそういないと思うけど、同じような人がいたとき用に覚え書きしときます
最新のトレンドを追うときにやっていること５選

## 1.テックブログを見る
こちらはみられている方多いと思いますが実際に現場で使用している技術を知ることができるのでおすすめです。
以下はおすすめのテックブログを書いている会社です。

[LINE株式会社](https://engineering.linecorp.com/ja/blog)
[メルカリ](https://engineering.mercari.com/)
[Google](https://developers-jp.googleblog.com/)

## 2.ポッドキャストを聞く
こちらはラジオ形式で企業の技術情報を得られるサービスになっています。
通勤時間や隙間時間に聞くことができるので時間が取れない方にもおすすめです。
私は最近フロントエンドの勉強をしているのでLINEのポッドキャストを聴いています。

https://uit-inside.linecorp.com/

## 3.Zenn
https://zenn.dev/
こちらはQiitaと同じように記事の投稿ができるサービスです。
Qiitaと違うところは書籍を販売することができるところです。
質の高い情報なども無料で見れたりするのでかなりおすすめです！
![スクリーンショット 2022-09-24 20.44.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577311/112babfd-f615-f3ba-97c1-779b1324e451.png)

## 4.Qiitaのトレンドを見る
これはタイトルの通りですがQiitaのトレンドを見るといった方法で最近話題になっている情報や注目されている記事を見ておくと新たな知識を得られるはずです。

## 5.執筆している人のTwitterを見る
こちらは私の持論なんですが執筆などをされている方はすでに発信能力や技術力に長けている方が多いのでその方のTwitterなどを定期的にチェックしておくと最新のトレンド情報や質の高い情報を得られると思います。

## 最後に
最後まで見ていただきありがとうございます！
他にもやっている情報収集のやり方などがありましたコメントお願いします！
【Git】文字コードがUTF-8以外のファイルを扱う

## 問題

文字コードがUTF-8以外のファイルをGitリポジトリにコミットすると、そのファイルが文字化けしてしまう。
（厳密にはファイル自体は文字化けしておらず、差分表示などの際にUTF-8でデコードされるために文字化けする）

## 解決策

リポジトリ直下に `.gitattributes` ファイルを作成し、対象のファイルに `working-tree-encoding` 属性で正しいエンコーディングを指定する。

例えば、WindowsでShift_JIS（cp932）の.txtファイルを扱いたい場合は以下のようにする。
```.gitattributes
*.txt working-tree-encoding=cp932
```

なお、内部的には指定されたエンコーディングとUTF-8とが相互変換されているだけで、実際のGitリポジトリにはUTF-8で上がるので注意。

詳細は公式ドキュメントを参照。
[Git - gitattributes Documentation](https://git-scm.com/docs/gitattributes#_working_tree_encoding)
Bluetoothスピーカー実験ボードをPlatformIOで動かす

BitTradeOneさんより、
[音と光の実験ボード「 Connected Doll」](https://bit-trade-one.co.jp/blog/20220923/)
が発売になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/0d7ad263-88ab-ba14-b3f9-4b21fb46499f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/453dae1f-5d22-2556-694e-1b7e682a11e4.png)

今回はこれの[サンプルプログラム](https://github.com/bit-trade-one/ADE32CD-Connected-Doll/)をWin/PlatformIOから動かしてみたいと思います。

まずはこちらからサンプルをダウンロードします。
https://github.com/bit-trade-one/ADE32CD-Connected-Doll/
今回はBluetoothスピーカーのチェック用サンプルを動かすだけなので、Git UrlからCloneしてもDownloadZIPでダウンロードしても大丈夫です。

![2022-09-24_200854.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/1b53e340-352c-1520-b0ce-abef2a64f5c6.png)

次に空のプロジェクトを作成します。BoardはEspressif ESP32 Dev Moduleを選択します。
![2022-09-24_194619.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/544f768b-2444-606a-d430-f9707fa39590.png)

プロジェクトを作成したら、```main.cpp```を削除し、先ほどBitTradeOneのGitHubよりダウンロードしたフォルダから
```bt_speaker_demo.ino```をsrcフォルダに入れます。
![2022-09-24_194826.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/4ecf85c3-fe5a-dffe-d784-902d037c197b.png)
この状態だとライブラリが不足しており、
```
#include "BluetoothA2DPSink.h"
#include <FastLED.h>
```
のところに波線が入っていると思いますので、これを解決します。

![2022-09-24_195550.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/9f8ce891-2acf-0eb7-4bc3-e737d35c87f5.png)

https://github.com/pschatzmann/ESP32-A2DP

からライブラリをダウンロードし、libの下にドラッグ＆ドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/eabd467a-0a12-bca1-fd58-7b89f911baef.png)

次にFastLEDですが、こちらはPlaiformIOのライブラリにあるのでそちらを使用します。
Librariesタブを選択し、検索窓にFastLEDと入力するとライブラリが出てくるので選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/1f7f08eb-916c-67ce-132d-c7ab8730c63b.png)

選択したら現在のプロジェクトを選択しインストールします。
![2022-09-24_200107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/9167d41f-526a-336a-daaa-c34e6f9915c0.png)

これで波線が消えたと思います。
![2022-09-24_200145.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/1850b93f-7cd6-fec1-ee43-000902fbb8ce.png)

ビルドの準備が終わったので、実験ボードを接続してビルドをします。エラーが出なければ成功です。
成功するとPCからBT_Musicという名前でBluetoothデバイスを見つけることができるようになるので、これを追加します。

![2022-09-24_200437.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/13f12b10-dafe-68b4-c4a2-28349ec906df.png)

BTO_Musicを選択し、youtubeなどを再生し、音が出ることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5f2a94c5-2da2-871e-e937-f7429c918f02.png)

おつかれさまでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/937f920d-8cf1-ed11-7c3c-07288fd8c649.png)
40代腰痛 在宅になって思ったアーロンチェアよりゲーミングチェアよりベッドテーブル

在宅ワークになる前は、会社でアーロンチェアを使ってました

在宅になって、腰痛いたい

FPS好きでゲーミングチェアはいいぞ！って聞くので買いました

5万ぐらいのやつ

徹夜でFPSやってると1時間おきにこしいてぇ・・・ってなってたけど

余裕で徹夜できるようになりました

アーロンチェアよりも全然腰痛くならない。てか、背もたれ後ろに90度倒せるからそのまま寝れるやばい最高

いまコロナで中古のアーロンチェア安く買えるからゲーミングとどっち買おうって思ってたけどゲーミング買ってよかった

でもやっぱ椅子は猫背になるからつかれるんだよなぁ・・・目も画面に近くなるし

そして色々アマゾンで探してみて

入院ベッドのときにご飯を配膳する台みたいなのないかなって思ってみつけた

買ったとても快適だった

足伸ばしてほぼ仰向け状態になってのPC作業楽ちんなのよね

背中にヨギボーとか人間をだめにするクッション的なやつを入れるか、IKEAのサメを買うか好きな方を選んでください
【EC-CUBE4系】MAMPで新規カラム追加しようとしたところ、エラー発生（An exception occurred in driver: SQLSTATE[HY000] [2002] No such file or directory）


下記リンクを参考に、EC-CUBE4.1系でテーブルのカラムを拡張しようとした。
https://doc4.ec-cube.net/customize_entity

▼エラー

エラーが発生したコマンド
$ bin/console doctrine:schema:update --dump-sql

エラー内容
An exception occurred in driver: SQLSTATE[HY000] [2002] No such file or directory

データベースのテーブルは、あるのに。
SQLは、起動しているのに。
なぜだ。。。

▼解決策

PHPのパスを確認してみたところ、ローカルのパスが通っていた。
MAMPを使う場合は、MAMPで使用しているPHPのパスを通しておく必要があった。

$ where php
→実行結果は、ローカルで使用しているPHPのパスのみ存在
　/opt/homebrew/bin/php

↓

$ vi ~/.zshrc
下記をviにて記述
export PATH=/Applications/MAMP/bin/php/php7.4.21/bin:$PATH

$ source ~/.zshrc

↓

$ where php
→実行結果は、/Applications/MAMP/bin/php/php7.4.21/bin/php

上記を確認して、ターミナルを再起動。
下記を実行したら、テーブルにカラムを新規作成できました。
$ bin/console doctrine:schema:update --dump-sql
$ bin/console doctrine:schema:update --dump-sql --force
Rasberry Pi 4 Model B（Ubnutu20.04）上でのMiniconda実装【備忘録】

# はじめに
RasPiを使ってドンキーカーを実装しようとしていたのですが、環境作成中、Anacondaの実装に苦戦したため備忘録代わりに投稿します。
# 環境
使用機器：Rasberry Pi 4 Model B（4GB）
OS：Ubuntu 20.04.5 LTS

# コマンド
Minicondaの.shファイルの取得
```
$ wget http://repo.continuum.io/miniconda/Miniconda3-py37_4.9.2-Linux-aarch64.sh
```
bashで実行
```
$ bash Miniconda3-py37_4.9.2-Linux-aarch64.sh
```
以降は画面の指示に従って進めていく。
なお、yesかnoの打ち込みを要求されたらyesと打っておく

その後、.bashrcの更新を行う。
```
$ source ~/.bashrc
```
以下のようにコマンド上の名前の最初に(base)が表示されえばOK
また下記コマンドでバージョンの確認をする。
```
(base) name@host:~$ conda -V
conda 4.9.2
```
あとは適当に環境作成～～

```
例：conda create -n donkey python=3.7
Collecting package metadata (current_repodata.json): done
Solving environment: done

～～～～～

# To activate this environment, use
#
#     $ conda activate donkey
#
# To deactivate an active environment, use
#
#     $ conda deactivate
```
お疲れさまでした!

# 追記
お気づきの方もいるかもしれませんが、実はこのMinicondaのバージョンわざと下げてます。
理由としては、最新版だとインストール時にCore dumpが起きてインストールができなってしまうからです。

以下記事が今回参考にしたGithubのissueです。

https://github.com/conda/conda/issues/11339
Qiita 書き方

# はじめに
競技プログラミング、大学やネットで学んだことを、あまりにもメモしなさ過ぎたので、備忘録として書き始めることにした

## 1. Qiitaの書き方
### マークダウン方式
- 編集欄の？マークからヘルプへ飛んだり、検索で調べてみる
   見出し：#見出し　だったので、エディタに書き込んで、プレビューで見てみる。
    ー＞＃がそのまま出てくる．．．書き方が間違っているのか？

    動画を見て気づいた　**#のあとは空白。**
    ひとつのことに、時間をかけすぎないでください。（自重）
~~前に書き始めようと思った時も、これに気づけなかったせいで後回しにしていました。~~

### インデント
　Tabキー
### 強調
　** word **, * word *
### 打消し線
　~~で囲む
### 表 
｜その1｜その２｜その３｜　のように書く、|--:|のようにハイフンとダブルコロンの配置で、文字配置を変えられる

### ソースコード

バッククォート３つ。```１行ずつ書いて、囲まれている行を表示する

```
#例
print("Hello world")
```
 
## 最後に
構造についてある程度分かったので、あとは時間をかけずに書けるようにしたい。


この記事を書いた2日後、投稿したと思いこみ、投稿欄を見たら、もちろん記録はなく、あせって、また下書きを書いていたところ、見つけられました。
ホームのマークから、「マイページ」ではなく、「下書き記事」より発見。気を付けてください（自重）

さらに、ミスしたため追加。投稿できたと思い込んでいると、またできていない。投稿ボタンを押した後、よくよく見ると、左画面に「タグを一つ以上指定してください」とのこと。忘れないように。

## 参照
[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
[Qiita Markdown 書き方　まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)
[Qiitaの記事の書き方〖研究生活ハック〗](https://youtu.be/pHfIs-5AJ5E)
データ分析にはLUXが便利？

# 初めに

LUXご存じでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/d2d7ea7e-4e65-ce50-fc35-86795e32e5de.png)

私はいつも視覚的・定性的にデータをさらっと見る時は
seabornのpairplotで多変量連関図を描いて
確認することが多いのですが、最近はLUXです。

Jupyterユーザーの方でデータの可視化の時に
[lux-API](https://lux-api.readthedocs.io/en/latest/source/getting_started/overview.html)を使ってますでしょうか？それともご存じないでしょうか？

https://lux-api.readthedocs.io/en/latest/source/getting_started/overview.html

# LUXのインストール

Anaconda promtを起動し、下記を実行します。

~~~python
# LUX-APIインストール
conda install -c conda-forge lux-api
# Jupyter notebookに機能を追加
jupyter nbextension install --py luxwidget
jupyter nbextension enable --py luxwidget
~~~

pipでインストールする場合は、下記とのこと。
私の環境下ではうまくいきませんでしたが・・・ご参考

~~~python
pip install lux-api
~~~

# LUX-API実行

~~~python
# ライブラリのインポート
import lux
import pandas as pd

# データインポート
data_train = pd.read_csv('train.csv')

# LUX-API実行
data_train
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/085078c7-6188-6477-151f-1748dc632c5a.png)

`Toggle Pandas/Lux`をクリックするだけで
簡単にデータが可視化できる。

# Correlation Plot
まずは`Correlation Plot`である
水平方向のスライダーを移動させることで
すべての因子の組み合わせの散布図を確認することが出来る
これにより2因子間の相関の有無を視覚的に確認することができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/a7b324b9-23b4-14a3-2a84-1f4b0ffd7841.png)

# Distribution
続いて、頻度分布（ヒストグラム）も確認することができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/dec25f18-6536-54e5-88d0-ca171539635c.png)

# 特定の1因子の詳細を確認する
~~~python
data_train.intent=["MedInc"]
data_train
~~~
今回の例では特定の1因子をMedIncとしたときの実行例を示す
横軸にユーザーが指定した任意の因子が固定され詳細を確認することが出来る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/ea871fd4-d9b2-d82a-e8ad-11fe011172c5.png)

# 特定の2因子の詳細を確認する
~~~python
data_train.intent=["MedInc","HouseAge"]
data_train
~~~
この場合、縦横はユーザーが指定した2因子となり、カラースケールがその他の因子でプロットされる3次元プロットとなる。これも視覚的にデータ分析する際に有効だろう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/cce21514-f99c-186b-60dc-0132730f8888.png)

# htmlで保存する
分析結果もhtml形式で保存できるので重宝すると思います

~~~python
data_train.save_as_html("sample.html")
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/039d6312-1a51-438f-083b-d7efa64df1fe.png)

# 最後に
いろいろなAPIがあると思います。
皆さんのおススメ等あれば教えてください
以上　最後までお読みいただきありがとうございました
【Unity】通信量削減に役立つビットパッキングクラス集

# 概要
Unity で Photon を使ったゲームを作る際、Vector3 や Quaternion を手間なくビットパッキングできるクラスが欲しくなったので作りました。
不具合や改善点がありましたら、コメントしていただけると幸いです。

# コード

https://github.com/yamara-mh/CodeStorage/blob/main/Codes/BitPacking.cs

# クラス紹介
## BitPacking.Vec3ToLong

Vec3ToLong はVector3をlongに非可逆圧縮・展開できるクラスです。他に Vec3ToInt, Vec2ToInt, Vec2ToShort を用意しています。

``` 使用例.cs
// 最小単位, 中央座標, ループ, X座標に使うビット数, Y座標に使うビット数、Z座標に使うビット数を指定できる
// （符号付きの値を利用する際は、値をマイナスにする）
var posPacker = new BitPacking.Vec3ToLong(0.01f, Vector3.zero, false, -22, -20, -22);
// 圧縮
long data = posPacker.Build(transform.position);
// 展開
transform.position = posPacker.Expand(data);
```

ループを無効にした場合、オーバーフローを抑制します（マップの端より先に移動できなくなります）。
ループを有効にした場合、オーバーフローを許容します（マップの右端まで行くとマップの左端にワープする挙動になります）。

## BitPackingQuaternion

BitPackingQuaternion は、QuaternionのEulerAnglesをintやlongに非可逆圧縮・展開できる拡張メソッド等を定義したクラスです。
方向の情報のみを圧縮・展開できる拡張メソッドも用意しています。

``` 使用例.cs
//EulerAnglesをlongに圧縮する拡張メソッド。角度は 0.0005f 刻みになる
long data1 = transform.rotation.PackingToLong();
transform.rotation = data1.ExpandToQuaternion();
//EulerAnglesをintに圧縮する拡張メソッド。角度は 0.5f 刻みになる
int data2 = transform.rotation.PackingToInt();
transform.rotation = data2.ExpandToQuaternion();

// EulerAnglesの一つをshortに圧縮する拡張メソッド。角度は 0.01f 刻みになる
short data3 = transform.rotation.eulerAngles.y.AnglePackingToShort();
transform.rotation = data3.ExpandToQuaternion(Vector3.up);

/* 方向の情報のみを圧縮・展開できる拡張メソッド */
//EulerAnglesのX,Yをintに圧縮する拡張メソッド。角度は 0.01f 刻みになる
int data4 = transform.forward.DirectionPackingToInt();
transform.forward = data4.ExpandToDirection();
//EulerAnglesのX,Yをlongに圧縮する拡張メソッド。変換で僅かな誤差が生まれるものの高精度
long data5 = transform.forward.DirectionPackingToLong();
transform.forward = data5.ExpandToDirection();
```

## BitPackingJoyStick

BitPackingJoyStick は、JoyStick等で扱われるVector2をushortにビットパッキングできる拡張メソッドを定義したクラスです。

``` 使用例.cs
ushort data = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).JoyStickPackingToUshort();
Debug.Log(data.ExpandToJoyStick());
```

## BitPackingColor

BitPackingColor は、Color, Color32をintにビットパッキングできる拡張メソッドを定義したクラスです。

``` 使用例.cs
int data = Color.yellow.PackingToInt();
Debug.Log(data.ExpandToColor());
```
## BitPacking
BitPacking クラスには、long, int, short, byte に複数の値を組み込める関数を用意しています。

``` 使用例.cs
// 各値をパッキングする際、必要になるビット数を指定する配列を用意する
// （符号付きの値を利用する際は、値をマイナスにする）
private static readonly int[] PlayerInfoBits = { 2, 20, -10 };

// int data に3つの値をパッキング
int data = BitPacking.BuildInt(PlayerInfoBits, 3, 65535, -512);
// パッキングした値を array に展開
int[] array = BitPacking.Expand(PlayerInfoBits, data);
```

32ビット以上の値をパッキングする際は```BuildLong(int[] bits, params long[] values)```と```ExpandToLongs(int[] bits, long packedData)```関数を利用してください。
必要になるバイト数は```2^n```で求まりますが、```BitPacking.MinValue(int bit)```と```BitPacking.MaxValue(int bit)```関数で求める事もできます。またオーバーフローさせたくない場合は```BitPacking.Clamp(long value, int bit)```関数で抑制できます。
【Linux】絶対パスやファイル名のみを取得する方法

## 絶対パスを取得する
絶対パスを取得するには以下のコマンドを実行します。

```zsh
ls ~/path/to/dir/*
```

```zsh
$ ls /home/user/sample/*
/home/user/sample/example.txt
/home/user/sample/sample.txt

/home/user/sample/example:

/home/user/sample/sample/sample:
```

## ファイル名のみを取得する
ファイル名のみを取得するには以下のコマンドを実行します。
```zsh
basename /path/to/file
```

```zsh
$ basename /home/user/sample/sample.txt
sample.txt
```

また以下のように実行すると拡張子を除いた部分を取得できます。

```zsh
$ basename /home/user/sample/sample.txt .txt
sample
```
【GCP】Cloud RunとApp Engineの比較

# 背景
これまでクラウドの経験はAWSだけでしたが、GCPにも関わるようになりました。
最近とあるシステムのインフラを検討することがあり、GCPのサーバーレスサービスを調べる中で`CloudRun`が最近アツいということを知りました。
そこでAppEngineを比較対象としてメリデメを自分なりにまとめてみました！

# AppEngineとの比較

## メリット
- **コスト面**
    - `GAE`は最後のリクエスト処理してから15分後にインスタンス終了するため、その間リクエストはないのに課金される。
    - `CloudRun`はリクエスト時間で純粋に従量課金。
    - そのためリクエスト頻度が少ないケースではCloudRunの方が安くなる可能性が高い。
    - ※ コールドスタート（後述）には注意。
 
- **スケールの速度**
    - `CloudRun`はコンテナベースで高速スケーリングする。
    - `GAE`はVM上でビルドされるため、デプロイ及びバースト時のスケーリングが遅い。
    - よって、スパイクが発生するようなシステムでは`CloudRun`の方がHTTP503など起きづらくて安心。

- **ランタイム依存**
    - `GAEスタンダード環境`では提供ランタイムに制限あるため、GCP側の提供ランタイム変更に影響を受ける恐れあり。
        - [ドキュメント](https://cloud.google.com/appengine/docs/standard?hl=ja)
    - `CloudRun`はDockerfileによりコンテナビルドできる限りランタイム制約無いため、影響なし。
    - よって言語やバージョンをGCP側に制約されない`CloudRun`がグッド。

- **ローカル開発効率**
    - `GAEスタンダード環境`ではdev_appserver.py（ローカル開発用サーバー）を実行する。（Python使用時のみ？）
    - `Cloud Run`ではDockerfileを実行し、cloud_sql_proxyを使用してCloudSQLに接続。
    - よって`Cloud Run`によるコンテナベースでの開発の方が、なじみがあるエンジニアが多く開発効率高いと思われる。

- その他運用面
    - **移行時の柔軟性**
    CloudRunは[Knative](https://cloud.google.com/knative?hl=ja)がベースとなっており、仮に他インフラ（GKEなど）へのアプリケーションの移行が発生してもスムーズに対応可能。
    - **サービス自体の勢い**
    CloudRun自体に勢いがあり機能拡張されており、またコンテナイメージからのデプロイ用に周辺ツールが整備されているため、今後エコシステムの恩恵を受けやすそう。

## 懸念点（デメリット）
- **実行タイムアウト**
    - `CloudRun`はタイムアウトはデフォルト５分だが、[最大60分](https://cloud.google.com/run/docs/configuring/request-timeout?hl=ja)まで延長可能。
    → 相当重いワークロードでは無い限り、タイムアウトが制約となる場合はほぼなさそう。制約大きく解消しつつある。

- **ファイルの永続化**
    - `CloudRun`ではメモリ上でファイル操作するため、ファイルの永続化不可。
    - `GAE`では`Cloud Storage`など利用可能。

- **コールドスタート（回避可能）**
    - `CloudRun`では一定時間アクセスがないと自動的にコンテナが終了し0になり、再アクセス時にコールドスタートするためレスポンスが遅延する。（言語やアプリケーションによるが数秒程度？）
    - [参考：遅延時間について](https://medium.com/google-cloud-jp/cloud-run%E3%82%92%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%89%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%81%8B%E3%82%89%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%A0%E3%81%8C%E5%AE%89%E5%AE%9A%E5%8C%96%E3%81%95%E3%82%8C%E3%82%8B%E3%81%BE%E3%81%A7%E3%81%A9%E3%81%AE%E3%81%90%E3%82%89%E3%81%84%E3%81%8B%E3%81%8B%E3%82%8B%E3%81%8B-abdb9bbc84bf)
    - ただ、[最小インスタンス数を1以上にしてコールドスタート対策も可能](https://cloud.google.com/blog/ja/products/serverless/cloud-run-adds-min-instances-feature-for-latency-sensitive-apps)。（※ 常時起動するためコストは上がる。）
    - （コンテナでなくVMで起動するAppEngineの方がコールドスタート遅いかと思いきや、[公式ブログ](https://cloud.google.com/blog/ja/products/gcp/best-practices-for-app-engine-startup-time-google-cloud-performance-atlas)見た限りはかなり早そう。。このあたり詳しい方いれば教えてほしいです。）

- **レスポンス後の処理（回避可能）**
    - `CloudRun`ではレスポンス後にCPU割り当てが解放されるため、非同期処理等ができないという点がつらみとしてあった。しかし**Always on CPU**機能が実装されたため、この点は解消された。
    - [参考：サーバーレス コンテナ Cloud Run に待望の新機能 Always on CPU が登場しました](https://medium.com/google-cloud-jp/%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AC%E3%82%B9-%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A-cloud-run-%E3%81%AB%E6%96%B0%E6%A9%9F%E8%83%BD-always-on-cpu-%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-c88cd1114c60)


# まとめ
- 2019年に発表されて以来、日が浅いうちはつらみも多かったようですがアップデートを重ねてかなり使いやすいサービスとなりました。
- GCP的にも`CloudRun`を推しているようで、機能拡張はもちろん他サービスとの統合もどんどん進められており多彩なアーキテクチャを組めるようになっています。
- 今後インフラを検討する上で`CloudRun`は有力な選択肢となってきそうです。
IAMユーザにIAMロールをアタッチする話

### 記事を書くきっかけ
自分「IAMユーザにIAMロールをアタッチして、権限制御することを考えていて〜」
同僚「IAMロールはAWSリソースにつけるもので、IAMユーザにはアタッチできないよ」
自分「確かに書いてあるな。だけど、以前の現場でマネコンにアクセスする際、環境ごとにリンクを踏んでスイッチロールした記憶があるぞ？？？」
ということで調べてみました。

https://qiita.com/montama/items/90bb8a3973d101be4690

### 検索してみた　　　　
- どうやら、あるアカウント内にあるIAMユーザについて、他のアカウントでのロールを引き受けることはできるよう。
- 例えば、ユーザ管理用アカウントを作っておき、別に○○システム動作用のアカウントを作るとすると、以下のような設定が必要です。
    - ○○システム動作用のアカウント内で、以下のポリシー・ロールを作成する。
        - ユーザ管理用アカウントのIAMユーザを信頼するポリシー
        - 動作用アカウント内で必要な動作を許可するポリシー
        - 上記のポリシーを付与したロール
    - ユーザ管理用アカウント内では、以下のポリシーを作成する。
        - ○○システム動作用アカウントのIAMロールを引き受けることを許可するポリシー
-  これで、ユーザ管理用アカウント内のユーザで○○システム動作用アカウント内での作業が可能になります。

https://blog.serverworks.co.jp/switch-role

### 仕様が想定されるシチュエーション
- 私の経験上、本番環境・検証環境・開発環境など、環境ごとにアカウントを分割する例は多いです。
- そうなると、各アカウント内で個別にユーザを持つと管理が煩雑になるので、一つのアカウント内でユーザを一元管理できるというメリットがあります。
- 私の過去の現場では、URLでスイッチロール先のアカウント等の情報を持たせて、それを踏ませて権限制御していたようです。

なので、原則論（単一アカウント）としてはロールはリソースに付与されますが、アカウントをまたぐとそうでもない、ということかと理解しました。
Python 例外処理の解説

# 例外とは
構文エラー(SyntaxError)以外のエラーを例外エラーとする。

# エラーの種類
## [ZeroDivisionError]
「/」や[//]、「%」で計算する時に割る数が0だった時に起きる。
割る数が0でないか確認する。
## [NameError]
スペルミス、変数名ミスなどで名前が見つからなかった時に起きる。
スペルミスや変数名を間違えていないか確認する。
## [TypeError]
異なるデータ型同士での演算や関数での処理が行われた時に起きる。
データ型が間違っていないか確認する。
## [ValueError] 
数値が適切でないときに起きる。（型は合っている）
数値を確認する。（引数とか）
# 書き方
* try →例外が発生するかもしれない処理
* except →例外が発生した後の対応方法
```
try:
    例外が発生するかもしれない処理
except 想定されるエラー名:
    検証したい処理で、想定されるエラーが起きた時の処理
```
## 例
```
while True:
    try:
        x = int(input('数字列入力欄'))
    except ValueError:
        print('有効な数字列を入力してね')
    else:
        break        
```

# raise文
## raise文とは
強制的に例外を発生させる文
## 書き方例
```raise エラー名(引数)```と書く。
引数にエラー内容を与えると便利。

```
>>> raise ZeroDivisionError("割る数が0です")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: 割る数が0です
```
# クリーンアップ動作
* tryから抜け出す時に実行される処理。
* finally　を使って実行する。
* finallyは必ず実行される処理。
GoでメールのFrom/Toをエンコードする一番簡単な方法

Amazon SESを使ってメールを送信する際に、aws-sdk-goではFromに日本語名を使うと文字化けしてしまったので。

```go
func main() {
	addr := mail.Address{
		Name:    "太田豊太郎",
		Address: "mail@example.com",
	}
	fmt.Println(addr.String()) // =?utf-8?q?=E5=A4=AA=E7=94=B0=E8=B1=8A=E5=A4=AA=E9=83=8E?= <mail@example.com>
}
```
TypeORMの0.3系でType 'string' has no properties in common with type 'FindOneOptions<T>'と怒られた

# エラー時の状況

TypeORMの0.3系で`findOne`メソッドの使い方ではまったので備忘録。
エラーは以下の通り

```
src/todo/todo.service.ts:20:46 - error TS2559: Type 'string' has no properties in common with type 'FindOneOptions<Todo>'.

20     return await this.todoRepository.findOne(id);
                                                ~~
```

問題のコード。

```ts: todo.service.ts
@Injectable()
export class TodoService {
  constructor(
    @InjectRepository(Todo)
    private readonly todoRepository: Repository<Todo>,
  ) {}

  async findOne(id: string): Promise<Todo> {
    return await this.todoRepository.findOne(id);
  }
}
```

## 環境

```json: package.json
{
  // ...
  "dependencies": {
    "@nestjs/common": "^8.0.0",
    "@nestjs/config": "^2.2.0",
    "@nestjs/core": "^8.0.0",
    "@nestjs/mapped-types": "*",
    "@nestjs/platform-express": "^8.0.0",
    "@nestjs/typeorm": "^9.0.1",
    "class-transformer": "^0.5.1",
    "class-validator": "^0.13.2",
    "pg": "^8.8.0",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0",
    "typeorm": "^0.3.9"
  },
  "devDependencies": {
    "@nestjs/cli": "^8.0.0",
    "@nestjs/schematics": "^8.0.0",
    "@nestjs/testing": "^8.0.0",
    "@types/express": "^4.17.13",
    "@types/jest": "27.5.0",
    "@types/node": "^16.0.0",
    "@types/supertest": "^2.0.11",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "eslint": "^8.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "jest": "28.0.3",
    "prettier": "^2.3.2",
    "source-map-support": "^0.5.20",
    "supertest": "^6.1.3",
    "ts-jest": "28.0.1",
    "ts-loader": "^9.2.3",
    "ts-node": "^10.0.0",
    "tsconfig-paths": "4.0.0",
    "typescript": "^4.3.5"
  },
  // ...
}

```

# エラーの原因の仮説

パラメータの渡し方もしくは、型になにかしら問題がありそう。

- TypeORMの`findOne`メソッドの引数に渡すパラメーターが間違っている?
- 型定義が間違っている?

## 仮説を検証してみる

エラーにも書いてあるように、パラメーターの渡し方が悪そうなので、一旦`FindOneOptions<T>`を見てみる。  
`FindOneOptions<T>`には`id`は渡せなさそう…

TypeORMの公式ドキュメントで`findOne`メソッドについて調べている。
すると…

> findOne(id) signature was dropped. Use following syntax instead:
> ```js
> const user = await userRepository.findOneBy({
>   id: id // where id is your column name
> })
> ```
> https://orkhan.gitbook.io/typeorm/

「`findOne(id)`は使えなくなったよ。代わりに`findOneBy`を使ってね。」的な事が書いてありました。  

## 公式ドキュメントの通りコードを修正する

以下のようにコードを修正すると…  
エラーが解消されました!  
修正したAPIにリクエストを送ると、問題なく動作しました!


```diff_typescript: todo.service.ts
@Injectable()
export class TodoService {
  constructor(
    @InjectRepository(Todo)
    private readonly todoRepository: Repository<Todo>,
  ) {}

  async findOne(id: string): Promise<Todo> {
-    return await this.todoRepository.findOne(id);
+    return await this.todoRepository.findOneBy({ id });
  }
}
```

🎉🎉🎉

# 原因

このエラーの原因は以下の通りです。

- `findOne`メソッドに渡すパラメータのかたちが間違っていた
- そもそも、TypeORM`0.3.0`以降から、`findOne`メソッドが廃止されていた
  - NestJS`8.0.0`で[CRUD generator](https://docs.nestjs.com/recipes/crud-generator)`nest g resource <resource-name>`を使うと、自動的に`findOne`メソッドを使うようになっている

# Source and Thanks

https://orkhan.gitbook.io/typeorm/
STM32G071で有機エレクトロルミネッセンス温度計。(STTS751)(Adafruit SSD1306,Adafruit GFX)


x ライブラリのインストール方法は、めんどいので省略
x サイズは、約34KB

x NUCLEO-G071RB
x OLED096UNO-Aです。


x 昔、秋月で売っていた温度センサーSTTS751
代用品は、S-5851A。(おもにアドレスの違い)


x 非営利、研究調査目的で引用する。



目的
OLEDで遊ぶ
適当にあつたI2C温度センサーを使用


![o_con796.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/84f8fdab-c59d-b7f2-cd3e-e95238b2f12b.jpeg)



参考


https://qiita.com/jakalada/items/793a6cf5ff2796db4e86




```c++



#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>



#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



// コンパイル時にヘッダーファイルが適切に編集されていない場合に
// "Height incorrect, please fix Adafruit_SSD1306.h!"
// というエラーを表示するための記述
//#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
//#endif

// RSTピンがない互換品を使用するので-1を指定
//Adafruit_SSD1306 display(-1);

void setup() {
  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
}

#define STTS751 0x39

int tempval;

void loop() {
  // 画面表示をクリア
  display.clearDisplay();

  // テキストサイズを設定
  display.setTextSize(3);
  // テキスト色を設定
  display.setTextColor(WHITE);
  // テキストの開始位置を設定
  display.setCursor(0, 10);


  //0番目のレジスター
  Wire.beginTransmission(STTS751);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);

  //温度の読み込み
  tempval = 99;
  Wire.requestFrom(STTS751, 1);
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    tempval = (int)Wire.read(); // 1バイトを受信
  }//while
  delay(1);

  //表示変換する
  char str1[3];
  str1[0] = '0' + (tempval/10);
  str1[1] = '0' + (tempval%10);
  str1[2] = 0;

  // 1行目に"Hello"を表示
  display.println(str1);
  // 2行目に"World!"を表示
  //display.println("World!");

  // 描画バッファの内容を画面に表示
  display.display();

  delay(1000);
}


```
コンサート検索アプリを開発したくなった話

# 開発している Web アプリ
趣味でコンサートホールで開催されるコンサートの検索アプリを個人開発をしています。

[Concert Map](https://concertmap.page "Concert Map")

# クラシック音楽業界の抱える課題
趣味でクラシックのコンサートをよく聞きに行っているのですが、コンサートを探すときに毎回不満を感じています。
知りたい情報が手に入らなかったり、探すのに手間がかかっています。

## コンサート探しの不便さ
### 本を探すなら Amazon がある

突然ですが、本を探すときどうやって探していますか？
僕の場合はとりあえず Amazon を見ます。
漫画を探すときも技術書を探すときも、とりあえず Amazon さえ見えおけばほとんどあらゆる本が掲載されています。
最新の本や中古の本はもちろん、海外の本や個人の出版する本すら Amazon なら載っています。
しかも詳細検索がこれまた便利で、ジャンルや著者を指定することができます。
参考までに Amazon の本・コミック・雑誌の詳細検索の画面のキャプチャはこちらになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/32d283d2-2d8c-21b5-793b-507fe11e0124.png)
Amazon がない時代の本探しをどうやっていたのか、想像するのが難しいほどに現代の本探しは楽です。

### Amazon の無い世界

もしも Amazon から本が一切なくなったらどうなるでしょうか（ついでに Rakuten books などのサイトからも）。
おそらく次のような形で本を探すことになるのではないでしょうか。
- 本屋に足を運んで探す
- 本屋のホームページから探す
- 出版社のホームページから探す
- 本を出版している人から直接知る

これはだいぶめんどくさそうです。
ホームページをいろいろと渡りあるく場合はホームページごとの UI を使いこなさなければならず、いちいち慣れるのにストレスがかかります。中には使いにくい UI も存在することでしょう。
また個人が出版している本はごく一部の知り合いの本しか知ることができません。

### クラシック音楽業界の Amazon は存在しない
クラシック音楽業界でコンサートを探そうとすると、Amazon が存在しない世界で本を探すのと似た感じになります。
- コンサート会場に足を運んでチラシをもらう
- 演奏者（個人 or オーケストラなどの団体も含む）のホームページから探す
- コンサート会場のホームページから探す
- 演奏家と SNS 等で通じてコンサートを知る

もちろん大手チケットサイトでは有名なコンサートは掲載されていますし、コンサートを登録・検索できるサイトは世の中に存在しています。
しかしどれも網羅性が低く、検索性能もかゆいところに手が届かない印象です。
主観が入っていますが、ざっくりまとめるなら次の図のような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/868c3b7b-3fb3-b347-6506-58c7b275354c.png)

いちクラシック音楽ファンとしてはコンサートの網羅性と検索機能でそれぞれ次のようなものが理想的です。
- コンサートの網羅性
    - 有名なコンサートからサロンや小ホールで開催されるようなコンサートまで掲載されている
    - オンラインでのコンサートも掲載されている
- 検索機能
    - リスト表示と地図が切り替えられる
    - 演奏者、プログラム、日付で詳細検索できる
## 課題の解決策
上記のような検索のしにくさは、いち業界として大きな問題だと思っています。
ショパン国際ピアノコンクールで2位に入賞した反田恭平さんや、ピアニストかつ YOUTUBER として活躍されている角野隼人さんなど、活躍する若い人がたくさん出てきている一方で、業界としてのプラットフォームが貧弱ではコンサートを聞きに来てくれる人も増えないのではないかと考えています。
クラシック音楽業界そのものが好きな人間としてはこのまま廃れていってしまう可能性があるのを見過ごすわけにも行きません。
### ないなら自分で作ればいい
前置きが長くなりましたが、それなら自分でコンサートの検索サイトを作ればいいということで開発をはじめました。
冒頭にも貼りましたがコンサートマップという Web アプリです。

https://concertmap.page

まだまだバグが多く、掲載されている件数も全然すくないのですが、まずは自分自身が使う上で理想的な検索サイトを目指して開発していこうと思います。
Qiita ではこのアプリの開発記事をゆるく投稿して開発ブログのようにしていこうと思います。

# 2022年9月現在搭載されている機能
このアプリは GCP を使って実装されています。GCP は細かい設定をしなくても Google がよしなにしてくれるところが好きです。ときどき知らないうちにリソースが作られて料金が発生しているとなんともいえない気持ちになりますが。

現在使っている GCP のサービスは次のとおりです。
- App engine
- Cloud SQL
- Cloud Storage
- Cloud Scheduler
- Cloud Pub/Sub
- Cloud Functions
- Cloud Logging
- Natural Language
- Monitoring
- Cloud Build

アーキテクチャ図もそのうち書きたいです。

## フロントエンド
### 検索結果の表示
- リスト表示
- マップ表示
## バックエンド
### スクレイピング
有名なコンサートを各オーケストラの Web サイトやコンサートホールの Web サイトから取得してくる機能
GCP の Functions を使ってスクレイピングする機能を実装する話を執筆予定
[Natural Language を用いたスクレイピングの改善 準備編](https://qiita.com/ogatango/items/7a9e70e9c6551152fca3)

# 開発予定
- 登録ユーザーがコンサートを登録する機能
Reactにbootstrapを適用する方法

Reactでbootstrapをいじるには？

react bootstrapで検索

https://react-bootstrap.github.io

getstarted
```
npm install react-bootstrap bootstrap
```
cssをindex.js（すべてのコンポーネントを含むjavascript）に張り付ける
```
import 'bootstrap/dist/css/bootstrap.min.css';
```

start bootstrapでレスポンシブデザインができた簡単なひな形は取れる
AWSでIAMユーザーを作る

## IAMユーザーとは

AWSアカウントを作成するとrootユーザーが自動的に作成されますが、なんでもできるrootユーザーは使わずに、適切に権限を付与して作ったIAMユーザーを使うことを、AWSは強く推奨しています。

- 使用料無料
- アクセス権限
各IAMユーザーが利用できるサービスに制限をかけれます
- 多要素認証(MFA)
個々のアカウントに付与することできて、セキュリティ強化につながる
- etc

## 1. IAMユーザーでも請求金額を見れるように設定

- 画面右上のアカウントを押下して、開いたメニューの中から "アカウント" を選択
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/bd84e4fd-dece-624b-0203-f7f0e3581bb7.png)

- " 編集" 押下
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/d73fc6d8-ab64-729b-af49-10cb283a0d00.png)

- "IAMアクセスのアクティブ化" にチェックを入れて更新押下
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/4c1bebd4-68c2-533e-a017-b0794ed161e2.png)

## 2. IAMユーザーの作成

### 2.1. ユーザー追加画面へ移動
- 検索ボックスに `IAM` と入力し、IAMサービスを選択
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/bc944bde-2289-f510-fefc-6b00d266efc0.png)

- 画面左のメニューから "ユーザー" を選択
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/4f103651-91a8-487e-fa8e-1706e67efe4e.png)

- "ユーザーを追加" を押下
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/1da2b3a6-b749-c247-dcb2-d918c6091295.png)

### 2.2. ユーザーの詳細設定
- ここは任意のものを選択すればOKですが、私は当面はマネジメントコンソールだけでOKなので、ここにだけチェックを入れています。
- 他人のパスワードを作るときは、 "パスワードのリセットが必要" にチェックをつけた方がよいです
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/94b27064-a6cd-9fcf-5025-0c26b03ba19f.png)

### 2.3. アクセス許可の設定
- 今回はAWSが用意してくれているポリシーを利用するので、 "既存のポリシーを直接アタッチ" を選択し、任意のポリシーにチェックをつけて進みます
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/2451b9e8-5eaf-fc5f-d072-7005c0e9f4c8.png)

### 2.4. タグの追加(オプション)
- ユーザーの情報を付与するもの。不要なので次へ進みます
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/59e85fd9-50f5-2495-e233-720837b8ac68.png)

### 2.5. 確認
- 追加するユーザーの内容を確認して、問題なければ作成します
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/38efdf61-7926-4a82-f558-48990c670ff2.png)

### 2.6. 成功
- ログインするURLが発行されます。忘れないように "Eメールの送信" を押下します
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/fb99840e-1a64-dbe4-ac7e-a0a5d02484aa.png)

- メーラが起動するので送信しておきます
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/d3e6dc07-fa50-fe24-ff3d-89b79a3fddff.png)

### 3. IAMユーザーでログイン
- 送信済みメールに載ってあるURLへアクセスすると、以下のような画面になるので、サインインします
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/de440fc8-d0f5-1931-8de7-d643ced353e8.png)
【備忘録】apt-get updateって何やってるの？

# 結論
端的に言うと、`パッケージリストの更新`をするためのコマンドです。

### 具体的にどういうこと？
一般的に、ソフトウェアを配布する際には、実行ファイル1つだけでなく、設定ファイルやマニュアルなどの関連ファイルをまとめて`パッケージ`という形で配布します。
ubuntuでは、パッケージを`apt(Advanced Packaging Tool)`というシステムを使って管理しています。
（この辺の知識については後日改めて学習します・・・）

ubuntuでパッケージをインストールしたい時、以下のコマンドを使ってインストールします。

```
$ apt-get install [パッケージ名]
```

上記のコマンドを実行すると、`/var/lib/apt/lists`にあるパッケージインデックスファイルというものを参照し、そのファイルに含まれるパッケージをインストールします。そのため、このディレクトリ内にパッケージインデックスファイルがないパッケージについては、上記のコマンドを実行してもインストールすることができません。

### apt-get updateの役割
`apt-get update`を実行すると、`/etc/apt/sources.list`に指定されているリストに基づいて、パッケージインデックスファイルをダウンロードします。つまり、インストールすることができる`パッケージ一覧のリスト`を更新します。ただし、あくまでも一覧のリストを更新するだけであって、実際のパッケージの更新やインストールは別のコマンド(`apt-get upgrade`や`apt-get install`)で行います。

### 参考
[https://qiita.com/YumaInaura/items/dd50ba59c245a0a5f3f1](https://qiita.com/YumaInaura/items/dd50ba59c245a0a5f3f1)
リーダブルコードまとめ(第10章:無関係の下位問題を抽出する)

# 第10章:無関係の下位問題を抽出する
## 概要
本章では、「無関係の下位問題を積極的に見つけて抽出すること」が大事であると主張している。そのために「関数やコードブロックを見て『このコードの高レベルの目標は何か？』と自問する」「コードの各行に対して『高レベルの目標に直接的に効果があるのか？』と自問する」「無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して別の関数にする」ということが大事であると説明している。

### まとめ
プロジェクト固有のコードから汎用コードを分離することが大事ということ。ライブラリやヘルパー関数を作っておけば、プロジェクト固有の小さなコードのみを残すことができる。

### 学んだ点
・汎用コードをたくさん作る。そうすることで、プロジェクトから完全に切り離されたコードを活用できるからであり、コード自体も結果的にはコードを小さくできる。
・積極的に無関係な下位問題を見つけて抽出する必要があるが、やりすぎないようにする。

### 感想と振り返り
本章は、JavaScript等の特有の関数を説明しており、直接的に学べる部分は少なかったが、以後Swiftの習熟度が上がれば再度読み込んで抽象化していきたいと思います。
何はともあれ、ライブラリ等で既にインポートされているもの等をうまく活用することを念頭に開発するべきですね！
Sphinxで電子書籍用のCSSを読み込ませ、書籍の体裁を整える

## 概要

電子かそうでないかに関わらず、書籍として文章を書くのであれば、見出し（章・節・項あたりまで）と見出しの次に続く段落やリストなどを意識して記述する必要があります。「必要があります」としましたが、Sphinxで文章を書くのであれば、見出しや段落などは自然と意識していることかと思われます。

Sphinxでは、各ビルドごとにテーマが用意されていて、特にHTMLについては任意のテーマを選択しやすくなっています。テーマはEPUBでも使用されていて、EPUB用のテーマを自分で選択することも可能ですが、EPUB用のデフォルトのテーマはよくできているようで、そのまま使ったとしても、問題ないレベルだと感じました。

ただ、それでも手を加えたいところはありました。それは以下のとおりです。

* 段落の始まりは字下げを行う

書籍であれば、段落の先頭は字下げを行うことが通例となっています。いわゆる出版社が出版する書籍であれば、ほぼ間違いなく行われています（逆に個人で出版していると思われる書籍は、この点がまちまち。字下げの有り無しが混在している書籍もある）。

HTMLで文章を表示する際の字下げについては、有名なメディアであっても字下げの有り無しは、各メディアによってまちまちなようですが（それでも、名の知れたメディアであれば、字下げの有無が混在していることはないようです）、書籍については先にも述べたとおり、出版社が出版する書籍であれば段落の字下げは行っているようです。

本記事では段落の件を例にして、EPUB用のテーマを作るほどではないが、EPUBのCSSに手を加えるための方法を紹介します。

## EPUBのみ、任意のCSSを読み込ませる

Sphinxでは、EPUBのみで使用するCSSを指定することが可能です。EPUBだけCSSを明示的に使うことで、HTMLのビルドとは別にEPUBのビルドでは見栄えを変えるということが可能です。

### CSSファイルを用意する

CSSファイルは、`_static`フォルダに置きます。本記事では`_static`フォルダの直下に`epub_custom.css`を置くものとします。

### conf.pyに追記

`conf.py`に以下を設定します。

    epub_css_files = ['epub_custom.css']

## CSSの設定例

### 段落の字下げ

:::note info
前提として、段落の字下げを「全角もしくは半角のスペース文字を使って行っていない」ものとします。
:::

段落はpタグで構成されていますので、CSSで`text-indent`を指定します。

```CSS
p {
  text-indent: 1em;
}
```

### リスト内のpタグは字下げしない

Sphinxで以下のようなリストを記述したとします。

```
* リスト1
* リスト2
```

EPUBのソースでは、以下のHTMLで構成されます。

```
<ul class="simple">
<li><p>リスト1</p></li>
<li><p>リスト2</p></li>
<ul>
```

liタグ内でもpタグが使われていますので、「段落の字下げ」で設定した字下げはここでも機能してしまいます。

よって、以下のCSSを追加して、liタグ内のpタグは字下げをしないようにしておきます。

```css
li > p {
  text-indent: 0;
}
```

## 参考

### EPUBのテーマの配置先について

Windows版での確認内容ですが、EPUBのテーマは以下のフォルダにありました。`Python310`のフォルダは、Python 3.10系をインストールしていることに起因しているようです。

    C:\Users\%username%\AppData\Local\Programs\Python\Python310\Lib\site-packages\sphinx\themes\epub

## まとめ

Sphinxでは、EPUBだけに働くCSSを設定することが簡単にできます。テーマを作り直すほどではないが、HTMLの装飾を変更したい場合には有効な方法です。段落に関する字下げを設定するだけでも、書籍としての見栄えが整い、より書籍らしく見えるようになります。
この文法何？？ ~ パート1（T extends HTMLElement = HTMLDivElement）~

## 前置き

OSS のコードを読んでいると、私はよく知らない文法を目にします。
この記事は、私がコードを読んでいてナンダコレとなった文法について書いています。

以下、注意点。
※ ナンダコレとなっているのは私が文法を知らないだけです。普段からリリースノートをこまめにキャッチアップしていれば、ナンダコレは起きません。
※ いつものごとく保険をはりますが、正しい記載は公式ドキュメント参照です。この記事で書いていることが正しい可能性は低いです。


## ナンダコレとなった文法

`HTMLElement` に `HTMLDivElement` を代入している文法を見て、ナンダコレとなりました。

```typescript
declare function create<T extends HTMLElement = HTMLDivElement, U = T[]>(
  element?: T,
  children?: U
): Container<T, U>;
```

ジェネリクスの型 `T` に対して `extends` で型を指定するまではよく使う & 見ますが。

```typescript
declare function create<T extends HTMLElement>
```

ジェネリクスの型 `T` に対して `extends` で型を指定して、さらに、その指定した型に対して、異なる型を代入しています。

```typescript
declare function create<T extends HTMLElement = HTMLDivElement>
```


## 文法の説明

この文法については、TypeScript 2.3 のリリースノートに記載されています。

https://github.com/microsoft/TypeScript-Website/blob/v2/packages/documentation/copy/en/release-notes/TypeScript%202.3.md

この文法は、`extends` に指定した型に対してデフォルトの型を指定しています。
以下の例だと、`T` のデフォルトの型は、`Player` 型になります。

```typescript
// デフォルトの型を指定
function hello<T extends string = Player>(arg: T): T
```


デフォルトの型を指定する記法は、上記の文法が使えるようになる以前は以下のように書いて、同じことを実現していました。

```typescript
// 以前の記法
function hello<T extends Player>(arg: T): T
function hello<T extends string>(arg: T): T
```

上記を例にすると、`T` は `string` 型、あるいは、`Player` 型である必要があり、デフォルトの型を指定する記法と同じことが実現できています。これまでは関数シグネチャを2つ書いていましたが、これを省略して書けるということで嬉しい & 楽しい、ということみたいです。


## サンプル

この記法を使う場面としては、`hello` 関数は基本的には引数に `Player` 型を受け取るけど（= デフォルトの型）、たまに、それ以外の型の引数(= `string` 型)も受け取ることがある、みたいな場面で使えるかと思います。

```typescript
type Player =
    | "Bradley"
    | "Kyle"

function hello<T extends string = Player>(arg: T): T
function hello<T>(arg: T) {
    return arg
}

// Player 型の引数を指定する場合（デフォルトの型）
hello("Bradley")

// string 型の引数を指定する場合（デフォルト以外の型）
hello("Daniel")
```

## まとめ

この件はあまり自信がない...間違っていれば優しく指摘してください。以上、終わり！
blastengineのRuby SDKを使ってテキストメールを一括配信する

[blastengine](https://blastengine.jp/)はエンジニアフレンドリーなメール配信サービスです。APIとSMTPリレーの両方をサポートしており、手軽に素早くメール配信ができるようになっています。

今回はRubyでblastengineのAPIを簡単に使えるSDKを開発しましたので、使い方を紹介します。現在はトランザクションメール（即時発信メール）とバルクメール（一括配信）をサポートしています。この記事ではバルクメールの使い方を紹介します。

## インストール

インストールはgemコマンドやbundlerで行ってください。

```
# Gemfile
gem 'blastengine'
```

または

```
gem install blastengine
```

## インポート

SDKをインポートします。

```ruby
require "blastengine"
```

## 初期化

Blastengineを初期化します。ユーザ名とAPIキーを使います。

```ruby
# 初期化
Blastengine.initialize api_key: "API_KEY", user_name: "USER_NAME"
```

## メールオブジェクトの用意

バルクメールは `Bulk` を使います。件名やテキスト本文、宛先などを指定します。 `__xx__` というのは送信先ごとに置き換わる文字列になります。キーワードの指定方法は後述します。

```ruby
bulk = Blastengine::Bulk.new
# nameはオプションです
bulk.from email: "info@example.com", name: "Administrator"
bulk.subject = "テストの件名"
bulk.text_part = "__name__ さん\nメール本文です。\n金額は__price__円です"
# オプション
bulk.html_part = "<p>__name__ さん<br />メール本文です。<br />金額は__price__円です</p>"
```

## 添付ファイルの追加

添付ファイルは `attachments` プロパティに、ファイルのパスを指定してください。

```ruby
# 添付ファイルがある場合
bulk.attachments << './test.rb'
bulk.attachments << './image.png'
```

## バルクメールの登録

まず宛先を指定しない状態でバルクメールを登録します。登録は `register` メソッドになります。

```ruby
bulk.register
```

## 宛先の登録

次に宛先を登録します。この時、置換する文字列も登録します。 `name` というキーワードであれば、メール本文に `__name__` と書くことで、そこで指定した文字列と置き換わります。

```ruby
bulk.add "user+1@example.jp", {name: "User 1", price: 1000}
bulk.add "user+2@example.jp", {name: "User 2", price: 1500}
```

送信先を登録したら、 `update` で反映します。

```ruby
bulk.update
```

## 送信

送信は `send` メソッドになります。返値はデリバリーIDになります。このデリバリーIDで、メールの送信状況確認や配信停止などを行います。

```ruby
begin
	# 送信
	delivery_id = bulk.send
rescue => e
	# APIエラー
	puts e
end
```

## 削除

バルクメールを削除する場合は、 `delete` メソッドを実行します。登録したままの状態（送信やキャンセルしていない状態）では10件までしか登録できないので注意してください。

```ruby
bulk.delete
```

## まとめ

Ruby SDKを使えばRuby on RailsやSinatraなどのWebアプリケーションはもちろん、コマンドラインを使った自動化ツールでもblastengineを活用してもらえます。

ぜひblastengineのRuby SDKを活用ください！

[blastengine | RubyGems.org | コミュニティのGemホスティングサービス](https://rubygems.org/gems/blastengine)
google artsの画像をダウンロードしたい続編(RPA)

ダウンロードする数が少ない場合は、以前紹介した方法で対応できますが、多くなってくると辛くなってきます。
なので、「Power Automate for desktop」で自動化しようと思います。
(製品名長い...)

https://qiita.com/tera11/items/efcfa6aa410ec1661faf

## 方法

![test01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280639/4d96a697-eb46-10f9-5da2-ca3180b0584f.jpeg)

↑見てもらったら分かりますが、csvをループさせて毎回 dezoomify-rsのソフトを起動させています。

初回のみ起動では無いかというと、画像のサイズを指定する処理が「dezoomify-rs」にはあるのですが、画像毎にサイズが違い、2回目以降の判定ができません、なので毎回閉じて起動させています。
(ウィンドウが次を含むという処理なのですが、範囲指定して取得ができないため)

```ダウンロード.csv
画像url
https://artsandculture.google.com/asset/woman-from-prizren-gypsy-art-gallery-nade%C5%BEda-petrovi%C4%87/fQFEB1L3PpIW9A
https://artsandculture.google.com/asset/woman-with-orange-background-from-a-b-davies-book-edition-25-50-arthur-b-davies/UgF-0XksPQu1eA
```

## 注意点

### 注意点1
Power Automateは従来のX、Y位置を指定して処理を実行しているわけではなく起動する要素自体を解析して処理を実行しています。
webで言ったらjsでidとかを指定している処理をしている感覚に近いです。
これがUI オートメーションと呼ばれています。

ただ、デフォルトだと追加したときの要素しか判定されないです。
(同じソフトで合っても閉じると、処理されないという厳格なチェックが行われる？ようになっているので、チェックを外します。)
これでテキストエリアをフォーカスしたりソフトを閉じることができるようになります。
![test02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280639/5f8ed27f-00b4-1fd9-7988-eb462761744e.jpeg)



### 注意点2
アプリケーション実行時のオプションで作業フォルダを指定します。
これがないと画像がダウンロードされる先がPower Automateのソフト直下にダウンロードされるようになってしまうので
![test03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280639/136879e6-2999-a877-a789-2ba0d647c450.jpeg)

## 感想
Power Automate以前使った際にも思いましたが、プログラマーでなくても定期的な作業を簡単に自動化できるの凄いですしもっと広まれば生産性上がるのではと思います。
(コーディングとかで使う機械は無いですが...)
blastengineのRuby SDKを使ってテキストメールを即時配信する

[blastengine](https://blastengine.jp/)はエンジニアフレンドリーなメール配信サービスです。APIとSMTPリレーの両方をサポートしており、手軽に素早くメール配信ができるようになっています。

今回はRubyでblastengineのAPIを簡単に使えるSDKを開発しましたので、使い方を紹介します。現在はトランザクションメール（即時発信メール）のみサポートしています。

## インストール

インストールはgemコマンドやbundlerで行ってください。

```
# Gemfile
gem 'blastengine'
```

または

```
gem install blastengine
```

## インポート

SDKをインポートします。

```ruby
require "blastengine"
```

## 初期化

Blastengineを初期化します。ユーザ名とAPIキーを使います。

```ruby
# 初期化
Blastengine.initialize api_key: "API_KEY", user_name: "USER_NAME"
```

## メールオブジェクトの用意

トランザクションメールは `Transaction` を使います。件名やテキスト本文、宛先などを指定します。

```ruby
transaction = Blastengine::Transaction.new
# nameはオプションです
transaction.from email: "info@example.com", name: "Administrator"
transaction.to << "user@example.jp"
transaction.subject = "テストの件名"
transaction.text_part = "メール本文です"
# オプション
transaction.html_part = "<h1>メール本文です</h1>"
```

## 添付ファイルの追加

添付ファイルは `attachments` プロパティに、ファイルのパスを指定してください。

```ruby
# 添付ファイルがある場合
transaction.attachments << './test.rb'
transaction.attachments << './image.png'
```

## 送信

送信は `send` メソッドになります。返値はデリバリーIDになります。このデリバリーIDで、メールの送信状況や配信停止などを行います（トランザクションメールは即時配信されるので停止できません）。

```ruby
begin
	# 送信
	delivery_id = transaction.send
	puts delivery_id
rescue => e
	# APIエラー
	puts e
end
```

## まとめ

Ruby SDKを使えばRuby on RailsやSinatraなどのWebアプリケーションはもちろん、コマンドラインを使った自動化ツールでもblastengineを活用してもらえます。

ぜひblastengineのRuby SDKを活用ください！

[blastengine | RubyGems.org | コミュニティのGemホスティングサービス](https://rubygems.org/gems/blastengine)
Google UXデザイン：デザインアプローチ

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

# 3つのデザインアプローチ

今回は、ユーザを第一に考えた３つのデザインアプローチについて紹介します。

1. Universal design: ユニバーサル・デザイン
1. Inclusive design: インクルーシブ・デザイン
1. Equity-focused design:　公平性に重点を置いたデザイン

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/595abb72-475a-10df-014d-cda4e91432e6.jpeg">

### ユニバーサル・デザイン

ユニバーサルデザインとは、最も幅広い能力を持ち、最も幅広い状況にあるユーザーのために一つの製品を作る手法です。

デザイナーは、すべての人に一つの解決策を提案します。問題は、万人に一つの解決策を作ることに注力すると、デザインが効果を失ってしまうことです。

例えば、1サイズしかない帽子を売っている店に行くと、ラベルには「One-size-fits-all」と書かれているかもしれませんが、その帽子は多くの人にフィットしないものです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/55017151-604b-28ed-e240-dbf4931644fc.jpeg" width="450">

つまり、「フリーサイズ」は優れた解決策ではないのです。


# インクルーシブ・デザイン

インクルーシブデザインとは、能力、人種、経済状況、言語、年齢、性別などの個人を特定する要素を考慮してデザインを選択します。

インクルーシブデザインは<font color="DodgerBlue">「一人のために解決し、多くの人に広げる」</font>と表現することができます。

例えば、私たちはデザインをする際、視覚や聴覚に障害のある人たちのニーズに焦点を当てます。そして、製品のバージョンを重ねるにつれ、身体障害者や認知障害者など、さらに排除されたグループのためにデザインするようになります。

障害のある人々のために製品、機器、サービス、あるいは環境を設計することは、<font color="DeepPink">***アクセシビリティ***</font>と呼ばれています。アクセシビリティは、インクルーシブ・デザインの1つの側面に過ぎません。

「一人のために解決し、多くの人に広げる」という考え方は、デザインが作成されたグループと既存のユーザーにしか利益を与えません。多くのグループはまだ取り残されています。

###  ユニバーサルデザインとインクルーシブデザインの違い

- ***ユニバーサルデザイン***: 多くの人が「使える」ものを作ることで社会から排除される人々をなくそうとする。公共性が高い場所など多くの人が使えるようにしなければならない状況で利用される。

- ***インクルーシブデザイン***: 排除されつつある個人のニーズや価値観を深く理解したうえで、「使いたい」と思わせるものを作ることで社会に取り込もうとする。特定の問題や状況の改善を起点とし、より大きな問題を解決しようとする状況で利用される。

# 公平性に重点を置いたデザイン

公平性に重点を置いたデザインは、インクルーシブデザインの考え方をさらに一歩進めたものです。

それは、<font color="DodgerBlue">製品を作る際に歴史的に十分に代表されなかったり、無視されてきたグループ</font>のために設計することに焦点を当てるようデザイナーに求めるものです。

公平性を目標にデザインするためには、まず、平等と公平の違いを知る必要があります。

- ***Equality（平等）***:　社会のあらゆる層に対して、同じだけの機会と支援を提供することです。言い換えれば、誰もが同じものを手に入れることができるということです。
- ***Eaity（公平)***:　一人ひとりに異なるレベルの機会や支援を提供することです

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/f28afcdf-d351-08f8-decd-0b94e3449224.png" width="600">

- ***Equality（平等）***:　すべての人が同じ箱の上に立つことができますが、背の高い人だけが見やすいようになっています。
- ***Eaity（公平)***:　一番背の低い人が、一番高い箱の束の上に立つことができるようになっています。


###  インクルーシブデザインと公平性に重点を置いたデザインの違い

- ***インクルーシブデザイン*** : 現在排除されている人々のグループのために製品を作る。

- ***公平性に重点を置いたデザイン*** : 過去に排除されてきたグループの特定の個人のニーズを満たす製品を作る。


### 実際の現場でやるべきこと

1. 作りたい製品を特定する。
1. これまでそのような製品が提供されてこなかったグループについて考える。
1. そのような人たちを中心に据えて、設計を進めていく。

# まとめ

インクルーシブデザインやユニバーサルデザインがすべての問題を解決するわけではないのと同様に、公平性に焦点を当てたデザインがすべての問題を解決するわけではありません。

しかし、すべてのデザイナーがアクセシビリティの基本を知るべきであり、なぜ、十分に代表されず排除されている人々のために製品を作ることが必須であると認識しましょう。
bundlerのインストール

```
ys@mbp ~ % gem install bundler
Fetching bundler-2.3.22.gem
Successfully installed bundler-2.3.22
1 gem installed
ys@mbp ~ % bundle -v
Bundler version 2.3.22
ys@mbp ~ % 
```

参考サイト
【Ruby入門】今更聞けない！Ruby bundlerとは | 侍エンジニアブログ
https://www.sejuku.net/blog/19426

>インストールしたあとは、rbenvを使っている場合、以下のコマンドを実行します。
$ rbenv rehash
rehashが何をやっているかというと、新規にインストールされたbundlerの実行ファイルへの実行フォルダをrubyが気にすることのないようにしています。
ざっくりと説明すると、rubyの実行フォルダに、bundl;erの実行ファイルのシンボリックリンク（実行ファイルへのリンク）を貼り直し（rehash）しています。

これはRailsチュートリアルには記載されていないので、実行していない
Scalaでネイティブアプリを作ろう

「え、ScalaってJVM言語でしょ？ネイティブアプリは作れないよね？」と思ったそこのあなた！そう、あなたですよ！

確かにScalaはJVM言語です。ですが、JVM言語をネイティブ化する魔法のビルドツール、GraalVMを使うと、あら不思議！ついにScalaはJavaのランタイムがなくても実行できるようになります！

この記事ではScalaプロダクトをGraalVMでビルドする方法と、実際にビルドしたCLIを見ていくことにします。

# ScalaをGraalVMでビルドする

幸いなことに sbt-native-image という sbt plugin を使うことで、あなたは GraalVM の環境構築をすることなしに、GraalVM でビルドできてしまいます。便利ですね。

```project/plugins.sbt
addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.2")
```

簡単なアプリなら、あとは `build.sbt` にこんな設定でいけます。

```build.sbt
lazy val root = (project in file("."))
  .settings(
    name := "sample",
    scalaVersion := "2.13.8", // 3系には対応していない。残念...
  )
  .enablePlugins(NativeImagePlugin)
  .settings(
    nativeImageVersion := "21.3.0", // 最新のバージョンを使う
    nativeImageOptions ++= Seq(
      "-H:+AllowIncompleteClasspath"
    )
  )
```

入門ということで HelloWorld を用意しておきましょう。

```src/main/scala/Main.scala
object Main extends App {
  println("Hello world");
}
```

これをビルド&実行してみましょう。

```shell
sbt nativeImage
target/native-image/sample
```

思ったより簡単でしょ？

## 例：LINE notify

では、これを用いて1つ例をみてみましょう。

https://github.com/kijuky/line-notify

このCLIツールは LINE notify を行います。

```
line-notify "hello world"
```

これくらいなら curl をそのまま叩けば良いかもしれませんが... Webリソースと連携して何かするCLIアプリなら難なくネイティブ化できます。 [Preference](https://docs.oracle.com/en/java/javase/19/core/preferences-api1.html), [Scopt](https://github.com/scopt/scopt), [sttp](https://github.com/softwaremill/sttp) などのライブラリも追加しても問題ありませんでした（ただし、Preferencesを有効にするためにGraalVMのバージョンを新しいものに指定しています）。

## 例：Slack notify

2つめ。似たようなことを Slack でもやってみましょう。[Slack は API が存在する](https://slack.dev/java-slack-sdk/guides/ja/)のでそれを利用してみます。

https://github.com/kijuky/slack-incoming-webhook

Slack API は内部で [Gson](https://github.com/google/gson) をつかうため、[リフレクションの設定が必要](https://docs.oracle.com/cd/F44923_01/enterprise/21/docs/reference-manual/native-image/Reflection/)になります。reflect-config.json を取得するために次のコードを実行します。

```shell
sbt
nativeImageRunAgent " hello world"
```

これで [`target/native-image-config/*.json` に、ビルドに必要なコンフィグファイル](https://github.com/kijuky/slack-incoming-webhook/tree/develop/target/native-image-configs)が出力されます。

# まとめ

簡単なScalaアプリなら、GraalVMを使ってネイティブアプリ化できました。実行時にJVMは不要ですし、実行速度も良好です。GraalVMはリフレクションが苦手ですが、コンパイルタイムで解決するScalaとは相性が良いです。皆さんもぜひScalaでネイティブアプリを試してみてください！