OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptで描画されたページをSplashとBeautifulSoupで取得する

BeautifulSoupではJavaScriptで描画される動的な要素を取得できません。
しかし、Splashサーバを経由することでJavaScript実行済みのレスポンスを取得できるようになります。


#### Splashのイメージ
```mermaid
sequenceDiagram
    クライアント ->> Splashサーバ: リクエスト
    Splashサーバ->>Webサイト: リクエスト
    Webサイト->> Splashサーバ:レスポンス
    Splashサーバ->> クライアント: JS適用後のHTMLやスクリーンショット

```

https://github.com/scrapinghub/splash


## BeautifulSoupを使った通常のパターン


```python:code1.py
import requests
from bs4 import BeautifulSoup

if __name__ == "__main__":
    # 取得元サイト
    url = "https://www.travel.co.jp/stay/city/kusatsu-100020271"
    # リクエスト送信
    res = requests.get(url)
    # HTML解析
    soup = BeautifulSoup(res.content, "html.parser")
    
    # 取得できた要素0件
    result_items = soup.select("div.result > div")
    print(f"{len(result_items) = }")

    for item in result_items:
        hotel_name = item.select_one("p.result_item_hotel_name a").text
        print(f"{hotel_name = }")

```
動的に描画される要素は取得できません。
```sh
$ python code1.py 
len(result_items) = 0
```

## Splashを使った場合
docker-composeでsplashを起動しておきます。
```yml:docker-compose.yml
splash:
  image: scrapinghub/splash
  ports:
    - 8050:8050
```

```zsh
$ docker-compose up -d    
Creating splash-bs4_splash_1 ... done
```


```python:code2.py
import requests
from bs4 import BeautifulSoup

if __name__ == "__main__":
    # 取得元URL
    url = "https://www.travel.co.jp/stay/city/kusatsu-100020271/"
    # Splashサーバーを経由してリクエストを送る
    res = requests.get("http://localhost:8050/render.html", {"url": url, "wait": 0.5})
    # JavaScirpt実行し描画済みのHTML解析
    soup = BeautifulSoup(res.content, "html.parser")

    # 10件取得できた
    result_items = soup.select("div.result > div")
    print(f"{len(result_items) = }")

    for item in result_items:
        hotel_name = item.select_one("p.result_item_hotel_name a").text
        print(f"{hotel_name = }")

```
JavaScript実行済みのHTMLをレスポンスで受け取ることで要素を取得できます。
```zsh
$ python code2.py 
len(result_items) = 10
hotel_name = '草津温泉\u3000望雲'
hotel_name = '草津ナウリゾートホテル'
hotel_name = '草津温泉\u3000ホテル櫻井'
hotel_name = 'ホテル一井'
hotel_name = '草津ホテル'
hotel_name = '草津温泉\u3000ペンションヴァンベール'
hotel_name = '草津温泉\u3000お豆の小宿\u3000花いんげん'
hotel_name = '草津温泉\u3000益成屋旅館'
hotel_name = '湯畑草菴'
hotel_name = '草津温泉\u3000薬師の湯\u3000湯元館'
```
rbenvを利用する下準備備忘録

Macでrbenvを利用しようと試みた所，予想外に時間を要したので備忘録として下準備の手順を残しておこうと思います．

# OpenSSLのインストール
Homebrewを用いてOpenSSLの最新バージョンをインストールします．

```bash
brew update
```

```bash
brew install openssl
```

2022/7現在の最新版はOpenSSL3.0.5がインストールされます．

# .bash_profileに各種環境情報を追加
.bash_profileに以下の情報を追加します．追加後，再読み込みを行います．

```bash
export PATH="/opt/homebrew/opt/openssl@3/bin:$PATH"
export LDFLAGS="-L/opt/homebrew/opt/openssl@3/lib $LDFLAGS"
export CPPFLAGS="-I/opt/homebrew/opt/openssl@3/include $CPPFLAGS"
export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@3/lib/pkgconfig $PKG_CONFIG_PATH"
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix)/opt/openssl"
```

```bash
source .bash_profile
```

この下準備を実施せずにrbenvを実行すると以下のようにエラーが発生します．

```bash
 $ rbenv install 3.1.2 
Downloading ruby-3.1.2.tar.gz...
-> https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.2.tar.gz
Installing ruby-3.1.2...
ruby-build: using readline from homebrew

BUILD FAILED (macOS 12.4 using ruby-build 20220426)
```

下準備実施後にrbenvを実行すると無事動作しました．昔はセキュリティソフトが有効だとエラー終了していましたが，現在のバージョンでは問題無く動作しました．

```bash
$ rbenv install 3.1.2 
Downloading ruby-3.1.2.tar.gz...
-> https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.2.tar.gz
Installing ruby-3.1.2...
ruby-build: using readline from homebrew
Installed ruby-3.1.2 to /Users/user/.rbenv/versions/3.1.2
```

# 実行後の確認作業

```bash
$ rbenv global 3.1.2
```

```bash
$ ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [arm64-darwin21]
```

# Reference

https://qiita.com/ksh-fthr/items/299684eec4e05cc607d7
【Unity】Udon イベント

UdonSharpBehaviourのトリガー関数
Interact()
VRC_Triggerでいうところの、OnInteract。 オブジェクトに対してアクションしたときに呼ばれる。

OnDrop()
Pickupオブジェクトを放したときに呼ばれる関数。

OnPickupUseDown()
Pickupオブジェクトを持った状態でUseするためにトリガーを押し込んだ瞬間１回だけ呼ばれる関数。

OnOwnershipTransferred()
OwnerShipを失う時に、失ったプレイヤーで実行される。 実行された段階でプレイヤーにはOwnerShipがないため、ここで同期変数を更新することはできない。

OnPickupUseUp()
Pickupオブジェクトを持った状態でトリガーの押し込みを解除した瞬間に1回だけ呼ばれる関数。

OnPlayerJoined(VRC.SDKBase.VRCPlayerApi player)
プレイヤーがインタンスに入った時に呼ばれる関数。引数のplayerにはそのプレイヤー情報が入る。

OnPlayerLeft(VRC.SDKBase.VRCPlayerApi player)
プレイヤーがインタンスから離れた時に呼ばれる関数。引数のplayerにはそのプレイヤー情報が入る。

OnSpawn()
公式ドキュメント

このオブジェクトがローカルプレイヤーのためにスポーンしたときに発生します。バッファリングされていないので、遅れて入場したプレイヤーはこのイベントを取得しません。ネットワークインスタンス化でオブジェクトがスポーンされた場合にのみ発生します。オブジェクトがベースシーンに存在する場合は発生しません。

現在(2020/04/10)、 ネットワークインスタンス化を行う方法がないため発動条件を満たせない？

OnStationEnterd()
UseAttachedStation()などで、VRC_Stationに座った時に実行される関数。
ただし、 現在(2020/04/10)は動作しない。

OnStationExited()
VRC_Stationから離れた時に実行される関数。
ただし、 現在(2020/04/10)は動作しない。

OnVideoEnd(),OnVideoPouse(),OnVideoPlay(),OnVideoState()
おそらくVRC_SyncVideoPlayer用のトリガー関数。現在(2020/04/10)はVRC_SyncVideoPlayerがSDK3に実装されていないため使用できない。Unity純正のVideoPlayerというコンポーネントがあるが、こちらはUdonに対応していない。

OnPreSerialization(),OnDeserialization()
同期変数を送受信したときに呼ばれる関数。同期変数の値が変更されたときに呼ばれそうだが、 変更されていなくても毎度実行されている。 （無駄では・・・？）
つまり同期変数は変更されていようがなかろうが常に通信されている？

OnPreSerialization()
ObjectOwnerが同期変数を送信するときにObjectOwner側で呼ばれる関数。

OnDesrialization()
ObjectOwnerから同期変数を受信した時にObjectOwner以外で呼ばれる関数。
python-pptxでパワポ作成自動化１

パワーポイントを自動的に作成するための初歩的な関数。
大まかなところは分かった。
あとはシェイプ同士を接続する線を入力する方法が分かれば自動でネットワーク図がかけそう。

```py
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.dml.color import RGBColor
from pptx.util import Pt

WHITE = RGBColor(255, 255, 255)
OLIVE = RGBColor(128, 128, 0)
YELLOW = RGBColor(255, 255, 0)
FUCHSIA = RGBColor(255, 0, 255)
SILVER = RGBColor(192, 192, 192)
AQUA = RGBColor(0, 255, 255)
LIME = RGBColor(0, 255, 0)
RED = RGBColor(255, 0, 0)
GRAY = RGBColor(128, 128, 128)
BLUE = RGBColor(0, 0, 255)
GREEN = RGBColor(0, 128, 0)
PURPLE = RGBColor(128, 0, 128)
BLACK = RGBColor(0, 0, 0)
NAVY = RGBColor(0, 0, 128)
TEAL = RGBColor(0, 128, 128)
MAROON = RGBColor(128, 0, 0)

DEFAULT_COLOR = BLUE
DEFAULT_SHAPE = MSO_SHAPE.RECTANGLE # https://qiita.com/fuji3195/items/5e1a2f5760e98ac7116b#%E4%BB%A5%E4%B8%8B%E4%B8%80%E8%A6%A7


def headline(sld, _title, _subtitle):
    # スライドタイトルとサブタイトルを入力する関数
    title = sld.shapes.title
    title.text = _title
    subtitle = sld.placeholders[1]
    p = subtitle.text_frame.add_paragraph()
    p.text = _subtitle


def shape(sld, _text, x, y, width, hight, shapetype=DEFAULT_SHAPE, fontsize=10, color=DEFAULT_COLOR):
    # オートシェイプを配置する関数
    rect = sld.shapes.add_shape(
        shapetype,   	      # 図形の種類を[丸角四角形]に指定
        Pt(x), Pt(y),         # 挿入位置の指定　左上の座標の指定
        Pt(width), Pt(hight))  # 挿入図形の幅と高さの指定

    # [B]図形の塗り潰しとテキストの設定
    rect.fill.solid()                                   # shapeオブジェクト➀を単色で塗り潰す
    rect.fill.fore_color.rgb = color  # RGB指定で色を指定

    pg = rect.text_frame.paragraphs[0]   # shapeオブジェクト➀のTextFrameの取得
    pg.text = _text         	         # TextFrameにテキストを設定
    pg.font.size = Pt(fontsize)          # テキストの文字サイズを10ポイントとする


if __name__ == "__main__":
    prs = Presentation()
    sld = prs.slides.add_slide(prs.slide_layouts[1])  # 空白のスライドを追加
    headline(sld, "これはタイトルです", "そしてサブタイトルです\nそして２行目です")
    shape(sld, "これは四角形ですね", 100, 300, 200, 100)
    prs.save('Blog_図形の挿入.pptx')


```
LPIC Lv1-101　共有ライブラリ付近&RPMについてまとめてみた

# はじめに
LPIC Lv1-101　共有ライブラリ付近&RPMについてまとめてみた

# 最終更新日
2022年09月12日

# 環境の情報
OS
Ubuntu20.04

# 注意
最新の状態を確認して下さい。

# 公式さま
https://www.lpi.org/ja

# 参考さま
https://mondai.ping-t.com/
https://tech.pjin.jp/blog/2020/12/01/linux-shared-library-management


## 共有ライブラリ
# /etc
システム全体で使われる、
各パッケージ（アプリ・ソフト・デーモン）の
設定ファイルがある。

## ライブラリには2つある。

```
スタティックライブラリ 	lib●●.a
共有ライブラリ 	lib●●.so.●●
```

## ldd
プログラムがいる共有ライブラリを表示する。
依存性を確認する。

```
$ ldd /bin/cat
	linux-vdso.so.1 (XXXXXXXXXXXXXXXXXXXXXX)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6  (XXXXXXXXXXXXXXXXXXXXXX)
	/lib64/ld-linux-x86-64.so.2  (XXXXXXXXXXXXXXXXXXXXXX)
```


## ld.so.cache 
プログラムを実行した時に、共有ライブラリの場所を検索するために使われるファイル。

```
/etc$ ls
ld.so.cache 
```



## ldconfig
共有ライブラリのキャッシュファイル「/etc/ld.so.cache」を更新する。

```
$ ldconfig
```



## /usr/lib
一般的に使われる共有ライブラリを置くところ。

```
$ cd /usr/lib
/usr/lib$ ls
apache2                               linux
apt                                   linux-boot-probes
aspell                                linux-sound-base
```


## ld.so.conf
共有ライブラリの検索パスを書いておくファイル。

```
/etc$ ls
ld.so.conf
```




# LD_LIBRARY_PATH
環境変数。
共有ライブラリの検索パスを設定する。




## RPM





# zypper
パッケージ管理ツール。
aptコマンドやyumコマンドのようなもの。



# zypper repos
# zypper lr
zypperコマンドを使って、リポジトリの一覧を表示する。




# zypper list-updates
# zypper lu
zypperコマンドを使って、
アップデートが出来るパッケージを確認する。



# zypper info xxxx
zypperコマンドを使って、パッケージの詳細な情報を表示する。
JavaScript_よく使われるイベント（onclick,onchange,onmouseover,onmouseout,onkeydown,onload）

onclick:マウスがクリックされたとき
onchange:入力に合わせて動的に表示内容を変えたい場合
onmouseover:マウスのポインタ（カーソル）を要素の上に合わせた時のイベント。
onmouseout:当該要素内に入っていたカーソルが外れたとき
onkeydown:キーを押したとき
onload:ページを読み込みとき

例：
```
<body>
 <script>
　// onclickテスト
  function displayCurrentTime(){
   var p1 = document.getElementById("test1");
   p1.innerHTML= Date();
  }

  // onchangeイベントテスト
  function onchangeTest(){
   // letとvar
   let textForOnchange = document.getElementById("test2").value;
   document.getElementById("test3").innerHTML= textForOnchange.toUpperCase();
  }
 </script>

 <button onclick="displayCurrentTime()">click here</button>
 <p id="test1">時間表示</p>

 <input id="test2" type="text" size=6 onchange="onchangeTest()" value=""></input>
 <div id="test3"></div>
</body>

```
【プログラミング不要】オススメのノーコードAI開発ツール　ベスト３を紹介【最新版】

ノーコードやローコードのAI開発ツールが近年増えてきていますが、それぞれどのような特徴があるのでしょうか？
プログラミング無しで素早くAIを開発したい人のために、実際に私が試したことのあるノーコードAI開発ツールの中で、個人的なオススメを３つ厳選して紹介します！

ちなみに、[前回投稿した記事](https://qiita.com/umapyoi/items/7c3e9b42388d576057b1)が「[Qiita Engineer Festa 2022](https://blog.qiita.com/qiitaengineerfesta-2022-presents/)」で「Qiita優秀賞」と「Top Contributor賞」の両方に選ばれました！この場を借りて感謝申し上げます。ありがとうございました！


# 1位　[ADFI](https://adfi.jp/ja/ai/)

URL: [https://adfi.jp/ja/ai/](https://adfi.jp/ja/ai/)

画像認識AIや異常検知AIの開発とテストをノーコードで行えるクラウドサービスです。AIモデルの開発とテストだけなら無料で利用できます！（かいはｔしたAIを商用利用する場合は有料ライセンスが必要。）
普段、私が仕事で最もよく使っている強力なノーコードAI開発ツールなので、自信を持ってオススメします！
使い方は、[以前の記事](https://qiita.com/umapyoi/items/9e3998a7001cc0ed5e67)で詳しく解説しているので、興味のある方はぜひご覧ください。

**ADFIの画面例**
![ADFI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535236/5d86a67b-ad03-5c89-1850-46ae5cbbcc01.jpeg)


### ADFIの想定される用途
画像データの識別タスク・異常検知タスクなど

具体例：
 - 画像検査・外観検査システム用のAI
 - 異物混入検知システム用のAI
 - 監視カメラ用のAI

### ADFIの特徴
 - AIの知識が全くなくても、簡単にAIモデルが作れる！（AIモデルのパラメータ調整が全自動のため不要です。）
 - 少ない学習データでも世界最高レベルの精度のAIモデルが作れる！（別記事でADFIと世界最先端手法を精度比較しています。↓
   - [PytorchのAIモデル(Pretrained + Fine-tuning)　VS　ノーコードAI開発ツール](https://qiita.com/umapyoi/items/f1a8ac86ef02abdf6b4f)
   - [最新論文の異常検知手法をMVTecデータセットの実験結果で比較してみた](https://qiita.com/umapyoi/items/ec64142dd3c70e90a9dc)）

### こんな人にオススメ
 - 仕事で画像AIを作る人
 - AIの知識はないけど、自分で開発したアプリにAIを組み込みたい人


# 2位　[DataRobot](https://www.datarobot.com/jp/)

URL: [https://www.datarobot.com/jp/](https://www.datarobot.com/jp/)

現在、世界で一番有名なノーコードAI開発ツールです。
元々、表形式データのみ対応していましたが、現在では画像データなどの他のデータ形式も取り扱えるようになっていて、どんどん新機能が追加されています！
AIの細かい設定を手動で調整できるだけでなく、AIの構造や出力などを視覚化することができます。
データサイエンティスト向けの高機能ツールになっており、AIの専門家でも満足できるレベルです。オススメです！

**DataRobotの画面例**
![DataRobot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535236/55ba19f0-f615-7f73-ce7d-143cec653d2f.jpeg)


### DataRobotの想定される用途
表データの分類タスク・回帰タスク、画像データの分類タスクなど

具体例：
 - 商品推薦システム用のAI
 - 売上予測システム用のAI
 - 商品仕分けシステム用のAI

### DataRobotの特徴
 - 多種多様なAIアルゴリズムを利用できる！（複数のAIアルゴリズムで精度を比較し、最も精度の良いAIモデルを選択できます。）
 - 様々な情報が視覚化されており、非常にAIの性能分析がしやすい！

### こんな人にオススメ
 - AIのアルゴリズムに詳しいデータサイエンティストの人
 - 表データを使ったAIを開発したい人


# 3位　[TeachableMachine](https://teachablemachine.withgoogle.com/)

URL: [https://teachablemachine.withgoogle.com)](https://teachablemachine.withgoogle.com/)

Google社が提供しているノーコードAI開発ツールです。無料で試せます！
非常に簡単な操作で分類タスクのAIを作成することができます！
ちょっと趣味でAIを作ってみたい時などに、さくっと気軽に作れるのでオススメです！

**TeachableMachineの画面例**
![TeachableMachine.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535236/c1154a0d-1b83-5ccf-d60f-e053bb4cc6a2.jpeg)


### TeachableMachineの想定される用途
画像データの分類タスク、画像データ（人間のポーズ）の分類タスク、音声データの分類タスク

具体例：
 - 商品仕分けシステム用のAI
 - 音声判定システム用のAI
 - ポーズ認識システム用のAI

### TeachableMachineの特徴
 - 音声データの分類や、人間のポーズの分類ができる！（音声や人間のポーズの分類タスクに対応しているノーコードAI開発ツールは珍しいです。）
 - 操作が非常に簡単！（画面上の指示に従って操作するだけでAIモデルを作成できます。）

### こんな人にオススメ
 - 音声データやポーズデータを分類したい人
 - AIもプログラミングも初心者だけど、AI作成を体験してみたい人

# まとめ

以上がオススメのノーコードAI開発ツールのベスト３でした！
それぞれのツールが対象としているタスクやユーザーが異なるため、使う人によってオススメできるツールも異なります。
ぜひノーコードAI開発ツールを選ぶ時の参考にしてみてください！
nuxtプロジェクト(SSR)をFirebaseでデプロイする。

Webサイト構築の勉強としてvue.jsとFirebaseを使ってみたので、その時の個人用メモ。


## 流れ
1. Firebaseアカウントを作成する。
1. Firebaseプロジェクトを作成する。
1. 作成したFirebaseプロジェクトにアプリを作成する。
1. nuxtプロジェクト(SSR)を作成する。
1. nuxt.config.jsを更新する。
1. nuxtプロジェクト上にfirebaseをインストールする。
1. デプロイする。

# 前提
・nuxtプロジェクトはSSR（サーバーサイドレンダリング）

# Firebaseアカウントを作成する。
[Firebase(公式)](https://console.firebase.google.com/)

# Firebaseプロジェクトを作成する。
手順①　Firebaseログイン後のトップ画面にある「プロジェクトを追加」ボタンをクリック。
手順②　表示される手順に従ってプロジェクトを作成。

# 作成したFirebaseプロジェクトにアプリを作成する。
手順①　作成したプロジェクトページを開き、「プロジェクトの概要」の歯車ボタンをクリックして、「プロジェクトの設定」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/0d8460f3-5b6f-377a-024d-3f6338e7ce9a.png)
手順②　「マイアプリ」フォームの「アプリの追加」ボタンをクリックし、「<<//>」マークボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/0ac97c01-a031-3a9e-2c50-79e528d1e47f.png)
手順③　表示される手順に従ってアプリを作成。

# nuxtプロジェクト(SSR)を作成する。
プロジェクト名や初期設定などは以下。
![プロジェクト作成時の設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/40a9ccd2-4417-247b-e13b-24d46e421c25.png)

# nuxt.config.jsを更新する
手順①　Firebaseの「マイアプリ」フォームの「SDK の設定と構成」のラジオボタンを「npm」にする。
手順②　「SDK の設定と構成」に以下の様な記載があることを確認する。
```vue:SDK の設定と構成(npm)_一部抜粋
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "xxxxx",
  authDomain: "xxxx.firebaseapp.com",
  projectId: "xxxx",
  storageBucket: "xxxx.appspot.com",
  messagingSenderId: "xxxxxxx",
  appId: "xxxxxxx",
  measurementId: "xxxxxxx"
};
```

手順③　「nuxt.config.js」の`modules`に`'@nuxtjs/firebase'`を追加する。
```diff_javascript:nuxt.config.js
  modules: [
+   '@nuxtjs/firebase',
  ],
```

手順④　「nuxt.config.js」に`firebase`を追加する。
　　※`config`には上で確認した`const firebaseConfig`の情報を記載。
　　※`services`は一旦適当にauthだけ記載。
```diff_javascript:nuxt.config.js
  modules: [
    '@nuxtjs/firebase',
  ],
+ firebase: {
+   config: {
+     apiKey: "xxxxx",
+     authDomain: "xxxx.firebaseapp.com",
+     projectId: "xxxx",
+     storageBucket: "xxxx.appspot.com",
+     messagingSenderId: "xxxxxxx",
+     appId: "xxxxxxx",
+     measurementId: "xxxxxxx"
+   },
+   services: {
+     auth: true // Just as example. Can be any other service.
+   }
+ },
```

手順⑤　「nuxt.config.js」に`generate`を追加し、`dir:(出力先フォルダ名)`を記載する。
　　※`npm run generate`：nuxtプロジェクトをNetlify / Vercel / Firebase などのホスティングサービスにデプロイするときに使うコマンド。nuxt.config.json上で`target:'static'`と設定されている時に`npm run generate`コマンドを実行すると、プロジェクト直下に<strong>distフォルダ（デフォルトの出力先)</strong>を作成する。Firebaseではデフォルトのデプロイフォルダが<strong>publicフォルダ</strong>なので、出力先を変更する。

```diff_javascript:nuxt.config.js
{
  ...,
  build: {},
+ generate: {
+   dir: 'public'
+ }
}
```

# nuxtプロジェクト上にfirebaseをインストールする。
手順①　FirebaseCLIをインストールしていなければ、`npm install -g firebase-tools`コマンドを実行する。
手順②　`firebase login`コマンドを実行して、Firebaseアカウントにログインする。
手順③　`firebase init`コマンドを実行。
手順④　`npm install @nuxtjs/firebase`コマンドを実行する。
手順⑤　「package.json」に`@nuxtjs/firebase`が追加されていたらOK。

# デプロイする。
手順①　`npm run generate`コマンドを実行する。
手順②　`firebase deploy`コマンドを実行する。
【Kotlin】sealed class(シールドクラス)

# はじめに
今回は『sealed class(シールドクラス)』について記事を残します
シールドクラスがどういったものか　や、使い方などを書いていきます

# Android公式　シールドクラス
https://kotlinlang.org/docs/sealed-classes.html

# sealed class(シールドクラス）とは
公式にもある通り、継承をより詳細に制御できる
つまり　クラス定義でsealedを付けると、「そのクラスを継承できるクラス」を限定することが出来る
というものです。


シールドクラスとは　直訳すると　「封印されたクラス」「密封されたクラス」といったようになると思いますが、
シールドクラスが宣言されたファイル内でしかそのシールドクラスは継承できないということになります。

# 使い方
クラスを定義するときに　classの前に　sealed　をつけるだけです。

# シールドクラスを使うメリット
・エラー発生時にエラー箇所を探す、確認する箇所が少なくできる
・独自のサブクラスを設定できる
・インスタンスの状態を後から変更することもできる
【Anki】プログラミング英語検定の単語帳を作ったので英語勉強しようぜ！

# 結論：これらを使ってプログラマーとして恥ずかしくない英語力を身につけよう！
[プログラミング英語検定](https://progeigo.org/)
単語帳サービス [Anki](https://apps.ankiweb.net/)
[AnkiのiOSアプリ](https://apps.apple.com/us/app/ankimobile-flashcards/id373493387)
[AnkiのAndroidアプリ](https://play.google.com/store/apps/details?id=com.ichi2.anki)
[プログラミング英語検定 Basic用単語帳](https://ankiweb.net/shared/info/1196723289)
[プログラミング英語検定 Advance用単語帳](https://ankiweb.net/shared/info/1619192694)

以上！

# 俺はっ‼‼(英語が)弱いっ‼‼
こんにちは。そんちょーと申します。
大学のアルバイト時代から数えてかれこれ5年以上エンジニアをやっております。
しかし未だに英語のドキュメントにビビるポンコツでございます。

Google翻訳の拡張機能を入れて英語のドキュメントを原文ママ読もうとします。
しかし30秒くらいで挫折して、Chromeさんに日本語に翻訳してもらう日々です。

このままでは世界のトレンドに置いて行かれてしまう...
ようやく英語を勉強するべく立ち上がりました次第です。

## プログラミング英語検定というものがあるらしい
別に英語ペラペラになりたいわけじゃないのです。TOEIC800点取りたいわけじゃないのです。
プログラマー向けのドキュメントをふつーに読めればいいのです。

最小限の努力でそれを達成しようとして見つけたのが[プログラミング英語検定](https://progeigo.org/)というもの。
どうやら「プログラミングで求められる英語力を測定」してくれる検定らしいです。
ここに「プログラミング必須英単語600+」というものを無料[^1]で公開してくれてたので、
とりあえずこの600個を覚えればいいんじゃね？と考えたわけです。

## 楽して覚えたい
はい。なるべく楽したいですね。
YouTubeでオススメの英単語アプリを探しました[^2]。
[Anki](https://apps.ankiweb.net/)というサービスが筆頭に上がってたのでそれを採用。

600個の単語を読み込ませるのも激しくめんどくさい。
プログラミング英語検定のサイトをスクレイピングしようかと思いました。
が、既にjsonにまとめてくれている神がいらっしゃったのでそれを使わせていただきました。
https://gist.github.com/ShinoharaTa/f967fab6a7fd6e0e289f5ce3d00f2060/revisions
ありがとうございます。

これをcsvに変換して、Ankiに読み込ませて単語帳にしました。
ついでにAwesomeTTSというアドオンを使ってGoogle翻訳さんの発音をくっつけました。

Ankiには単語帳のエクスポート機能、及びWeb上に公開、検索する機能があります。
せっかくなのでjson、csv、Ankiの単語帳データであるapkgをまとめてGitHubに載せました。
Ankiの公式サイトからもダウンロードできるようにしました。

ということでAnkiをインストールすれば、誰でもすぐにプログラミング英語検定の勉強ができます！

こうして世界は平和になった。

# 使い方
Ankiの細かい使い方は説明しません。
1. スマホなりPCなりでアプリをインストール
1. 使いたい単語帳をネット上からダウンロードしてインポート

で大体OKです。

自分が公開したものは、
[プログラミング英語検定 Basic用単語帳](https://ankiweb.net/shared/info/1196723289)
[プログラミング英語検定 Advance用単語帳](https://ankiweb.net/shared/info/1619192694)
[プログラミング英語検定_前提100](https://ankiweb.net/shared/info/602489398)
[プログラミング英語検定_略語70](https://ankiweb.net/shared/info/232021062)
[プログラミング英語検定_頭文字30](https://ankiweb.net/shared/info/438053075)
の5つです。

これらをインポートすれば、レッツスタディです。

GitHubに[リポジトリ](https://github.com/MatsumotoDesuyo/programming-english)を作ってjsonとcsv、apkgを残してあります。
俺は他の英単語アプリを使うぜっていう人はそれをうまいこと使って単語帳を作ってください。
プルリクエスト歓迎です。世界を良くしていきましょう。

以上です

[^1]:正確には「CC BY-NC-SA 4.0」ライセンスを守る限り無料で使用できます。
[^2]:プログラミング英語検定も単語帳アプリ的なのを出していますが、機能が少なくイマイチだったので選択肢から除外しました。
WebStormでDenoのFreshなデバッグ設定

## Denoで公開されたフルスタックフレームワークFresh
Freshなフレームワークが公開されたということで、早速触ってみることにしました。

とはいえ、JS/TSを扱うためになるべくデバッガーのブレークポイントで変数の中身をみたり、挙動を確認しながら作業をしたい。

そしてPHPでは強力なデバッガーXdebugに頼り切って開発しているため、正直デバッガーがないと開発できない体になってしまっています。

そんなわけで、まずはWebStormでデバッガーが動くようにしてみます。

## 準備
Denoのプラグインをインストールし、Denoの設定します。

https://plugins.jetbrains.com/plugin/14382-deno


## 設定方法
### Denoの素のコマンドを使う
Run/Debug Configurations → +ボタンから`Deno`を選択肢し、下記を設定します。
![](https://storage.googleapis.com/zenn-user-upload/a192b4b53ef9-20220714.png)
※スクショ用にファイルパスを省いていますが、ファイルパスはフルパスで設定

Command部分はこうなります。
```
run --allow-env --allow-read --allow-net --allow-run --allow-write
```
- デバッグボタンからデバッグを行う場合、`--inspect-brk`オプションが自動で付与される
- デバッグでは`--watch`オプションは使用できない。そのため`--watch`はここに記載できないので別途設定を用意する必要がある
- `File`にはbootstrapの役割っぽい`dev.ts`を指定

ここで設定するコマンドは、deno.jsonに`tasks`として登録してある設定を使用しています。


これでブレークポイント使用したデバッグができるようになります。

## 注意点
いざ、動作確認。

Freshの新プロジェクト作りたてであればカウンターモジュールが入っているので、このファイル`islands/Counter.tsx`にブレークポイントを仕掛けます。

さて、ここで残念なお知らせです。

`islands/`配下は、最初のページアクセス時はブレークポイントが動作します。Freshは要求発生時にレンダリングするJust-in-timeレンダリングため、この動作は理にかなっています。

（Just-in-timeレンダリングの詳細は理解できてないですが、おそらくサーバーサイドレンダリングのようなもの？）

しかし`islands`は実際のところサーバーサイドレンダリングを行わないプログラム、つまりユーザーのインタラクティブ動作のためのJavaScriptとして出力されています。そのため、このJSの挙動を確認するためのデバッグはこの手法ではできません。

`islands`のJSのデバッグを行うためには、ソースマップが必要なのですが出力方法が現状不明です。ソースマップの出力方法やその他デバッグ方法をご存じの方、ご連絡いただけると大変嬉しいです。


## 終わり
islandsで出力するJSのデバッグ方法は不明ですが、ひとまずサーバーサイドレンダリングが行われる箇所に関してはデバッグできるようになりました。

次回はFreshのプロジェクト作成時のサンプルコードを少し確認してみます。
AWS日記44 (Amazon EC2 - Rust)

# はじめに
今回は[Amazon EC2](https://aws.amazon.com/jp/ec2/)でのRustのビルドを試します。
EC2のARM64アーキテクチャで[aws-lambda-rust-runtime](https://github.com/awslabs/aws-lambda-rust-runtime)のexampleコードをビルドします。

# 準備
##### EC2インスタンスの準備
![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/3c13eb25-d31a-84af-8154-d88fc9ad51c5.jpeg)

 - 名前を設定します
![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/28a051f0-5599-c944-5cae-54bbd0e92306.jpeg)

 - Amazon マシンイメージを 「Amazon Linux 2 AMI」 に設定します
 - アーキテクチャを 「64ビット(Arm)」 に設定します
![03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/3f0c1465-2ef6-b318-fb33-899440ea7bf1.jpeg)

 - インスタンスタイプとキーペアを設定します
 - 作成したpemファイルは、SSH接続する際に指定します
![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/0857d75c-26f1-2cc6-dd5a-42ae39d03bbc.jpeg)

 - ネットワーク設定をします
 - SSH接続のため、自分のIPからの接続を許可します
![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/1847df96-0804-641c-9374-45df338d10ca.jpeg)

 - 「インスタンスを起動」 を選択します
![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/ea0417e2-c0c5-4e81-2fd9-29ef87c920f0.jpeg)


##### EC2インスタンスへ接続
 - [SSH を使用した Linux インスタンスへの接続](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html) を参考にインスタンスへ接続します


# [Rust](https://www.rust-lang.org/ja/tools/install)のインストール
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
```

# [cargo-lambda](https://github.com/cargo-lambda/cargo-lambda)のインストール
```bash
sudo yum install -y gcc
cargo install cargo-lambda
```

# [aws-lambda-rust-runtime](https://github.com/awslabs/aws-lambda-rust-runtime)の取得
```bash
sudo yum install git
git clone https://github.com/awslabs/aws-lambda-rust-runtime.git
```

# ビルド
```bash
cd aws-lambda-rust-runtime/examples/basic-lambda/
cargo lambda build --release
```

# ビルドアーティファクトの確認
```bash
ls -al target/lambda/basic-lambda/bootstrap
-rwxrwxr-x 2 ec2-user ec2-user 1738384  7月 31 06:55 target/lambda/basic-lambda/bootstrap
```

# 終わりに
EC2のARM64アーキテクチャでRustのビルドを試しました。
Lambdaランタイムの provided.al2 向けにビルドする際に利用していこうと思います。
【ActiveRecord】JOIN したテーブルに条件を指定するときは merge を使おう【Tips】


例として次のようなクラスがあると想定します。

```ruby
class User < ApplicationRecord
  has_many :comments
end

class Article < ApplicationRecord
  belongs_to :user
  has_many :comments
end

class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :article
end
```

`item_type` が `"Article"` の `Comment` を持つユーザーを取得したい場合、 `joins` と `where` を使うと以下のようになります。

```ruby
User.joins(:comments).where(comments: { item_type: "Article" })
```

これを `merge` を使って書き換えると次のようになります。

```ruby
User.joins(:comments).merge(Comment.where(item_type: "Article"))
```

試しに、出力されるSQLを確認してみると、同じSQLが実行されることがわかります。

```ruby
[17] (nobody)@development pry(main)> ::User.joins(:comments).where(comments: { item_type: "Article" }).to_sql
=> "SELECT `users`.* FROM `users` INNER JOIN `comments` ON `comments`.`user_id` = `users`.`id` WHERE `comments`.`item_type` = 'Article'"
[18] (nobody)@development pry(main)> ::User.joins(:comments).merge(::Comment.where(item_type: "Article")).to_sql
=> "SELECT `users`.* FROM `users` INNER JOIN `comments` ON `comments`.`user_id` = `users`.`id` WHERE `comments`.`item_type` = 'Article'"
```

上記の例ではあまりメリットが感じられませんが、以下のように複数 join する場合、 `merge` を使った書き方の方がわかりやすく短いコードで済むことが多いので、このテクニックを覚えておくことをオススメします！


```ruby
# merge を使わない場合
User.joins(comments: { article: :tags }).where(comments: { article: { tags: { name: "Haskell" }}})
# merge を使った場合
User.joins(comments: { article: :tags }).merge(Tag.where(name: "Haskell"))
```
我々は何のために振り返りをするのか

こんにちわ。

今日は振り返りの振り返りです。よく聞きますよね、このワード。
ただ、アジャイルされている皆さまがたまに実施するものとはちょっと異なりますし、振り返り手法を色々と紹介しそれらのメリデメなどをアレコレ評価するものではなく、
<font color="Red">「我々は何のために振り返りをするのか」を見つめ直したい</font> と思い、キーボードを叩いてます。

### 「振り返り」を紹介できるようにする
見つめ直したいと思った理由ですが、
まず、[前回の記事](https://qiita.com/text/items/7b7740d6843e8321b239 "私にとってのアジャイル
")で書いた通り、非システムの現場にもアジャイルを知ってもらいたいという野望があります。
>システムの現場だけでなく世の中全体がアジャイルというものを知って一人でも多くの人が仕事を楽しめるようになると良いなと。そのためには汎用性のあるアジャイルの要素を抽出、発信することで、それを受け取った各自が持ち帰り小さく一人でも実践し始めれる、再現性ある情報提供をしてみたい。といった感じです。

結論を先に書くと、
これを達成するための選択肢の一つとして「まず振り返りを薦めてみる」が浮かびました。そもそも単品で薦めるという選択肢がいままで浮かばなかったわけですが、その原因は私自身が「振り返り」というものをよりきちんと考えれてなかったのではないかなと。振り返りについて「どういうメリットがあるの？」と聞かれたときに説明できないようでは、非システムの現場に普及させるなんて到底無理な話だなと。商品の説明がきちんとできない営業担当と同じでごく当たり前の話です。

次に、
なぜ「振り返り」に着目したのかという理由ですが、アジャイルしているエンジニアチームとアジャイルしていない非エンジニアチームで、やってる事の「何が違うのか」を考えたんですね。その時にスッと出てきたのが「振り返り」というわけです。

これは私のイメージです。
| スクラムイベント | 昔からある似たやつ |
|:-:|:-:|
| デイリースクラム | 朝礼 |
| バックログリファインメント／計画会議 | 業務計画 |
| スプリントレビュー | 社内発表 |
| レトロスペクティブ／振り返り | アレ、よく考えたらこういうの<br>あんまりやってない気が… |

<font color="gray">※少し脱線しますが、こうやって並べてみると、業務の中で改善活動が端折られているとしたらものすごい違和感を覚えるとともに、改善活動およびこの振り返りこそがアジャイルの醍醐味だなと。</font>

さらに、
ではなぜ非システムの現場やアジャイルから遠い組織の現場で振り返り的な改善活動が基本ルーチンとして組み込まれていないかを考えてみました。原因はいくつかあると思いますが、そもそもとして「振り返り」というものが認知されていないことに尽きるかなと。

私の経験上システム開発でも非アジャイルだと振り返りなんてやった試しがなかったのと、関係する非システム部門で「振り返りしましょう！」というやりとりを殆ど見たことがなかったというのがあります。少し似た話だと思っていますがPDCAなんて言葉も世に出てきてからずいぶん久しい気もしますが、PDCAを上手く回せてる現場や事例を殆ど目にしたことがなかったというのもありますかね。

またトップダウンな社会活動の中では「業務フローは常に見直し（メンテナンス）するもの」という前提が持たれていないように見えます。考えてみれば個人レベルでは「主体性」とか「自分ごと」なんてボトムアップな言葉が飛び交っているのに、こういったチームレベルでの改善活動は自律性とかボトムアップを基本に据えたアジャイルの仕組みでこそ成立すると考えていた節があり、それを認知させるにパッケージ単位で落とすしかないと思っていましたが、それはそれで型が合わないために「非システム現場へアジャイルプロセスを適応できない」と。簡単に「スクラムやってみましょうよ」とは言えないわけです。

話を戻します。

イベント単位に目を向けると非システムの現場でもやれている事とやれていない事に分解できたので、やれていない事＝振り返りを単品で提供するということも可能かもしれないなと。

要するに
- 「振り返りだけでもやってみましょう」と言えない自分が居た
- 「振り返りだけでもやってみましょう」と言えると良いな
- それを実現しようとする人は見たことがない

という言った具合です。これが形にできると、先述したことへの達成に一歩近づくかもしれないなと思ったため、この記事に至ります。そして「振り返りだけでもやってみましょう」と言うためには、振り返りをよく解っていて、提案先にそのメリットとやり方を説明できる状態が求められます。

### 振り返りの目的とメリット
改めて、振り返りの目的ってなんでしょうか。それは目的達成をどれだけ有利に進めれるか、チームとして成長するためだと思っていますが「振り返り」という枠組みでなければその目的は達成できないのでしょうか。そのメリットはなんなんでしょうか。目的だけでなくメリットが言語化できれば振り返りの必要性も判断できますし他へ紹介も近づいてきます。

- 以下の向上が期待でき複合的に好循環を生む
    - チームパフォーマンス
    - 自律性
    - 主体性
    - 当事者意識
    - エンゲージメント
    - コミュニケーション効果
    - 心理的安全性
    - 透明性
    - モチベーション
    - ボトムアップ
    - 裁量性
    - リソース最適化
    - 役割の最適化
    - 客観性
   
ざっと思いつきで書いてみたのですが沢山ありますし、もっと時間を掛ければ他にもいろいろ出てきそうですね。こうやって眺めてみると「チーム力向上に加えメンバーのソフトスキル向上が見込める」という印象も持ちました。ここで言うソフトスキルも組織の中で語られるものですので属人的な言葉のように見えて、結局は所属する組織への影響力を指しています。

ということで、
「振り返りって何のためにやるんですか？」と聞かれたら、「日々の改善活動からチームだけでなくメンバーの成長をも促進し、プロダクトの目的達成に留まらず人材育成の観点でも非常に重要なプロセスである」としておきましょうか。

解り難いですかね。

では「業務上でのコミュニケーションという大切な仕事をメンバーに任せきりにするのではなくきちんとチームで対処していくための取り組み」と伝えましょうか。
良いですね。段々私の中で自信を持って「ちゃんと振り返りしてますか？」とアジャイルしていない非システム部門に対しても、さも当たり前のように伝えれる気がしてきました。
五島列島の船便を探すツールを作ってみた

# 作ったもの
五島の船の時刻表
https://goto-fune.herokuapp.com/

# 作ったきっかけ、問題提起
個人開発というタグをつけるのもどうかと思うくらい、技術的には簡単なものなので、控えめに発表いたします。

五島列島とは、九州の左上（言い方）の長崎県に所属する島々です。[ウィキペディア](https://ja.wikipedia.org/wiki/%E4%BA%94%E5%B3%B6%E5%88%97%E5%B3%B6)によると、152の島々からなるそうです。そんな島の国（言い方）に、今度旅行に行きます。２度目なんですけど。島ばかりなので、島と島を船で移動することが多々あるんですね。大きい島は大きいんですが、やっぱ島間を移動したくなる。

そこでググってみんながよく見るサイトがこちら。[五島交通ナビ](http://www.goto-koutsu.jp/pctime/timetable.php?kbn=ship)。（交通＝船の時刻表ということにちょっと驚き。）有名なのに見づらい見づらい。ほかのサイトも大体同じです。船はいつもこんな感じ。この**見づらいことが問題**です。

見づらい原因は、船の会社ごとに時刻表が並んでいて、複数の会社を跨いだ検索ができないためです。**渋谷駅から東京駅へ行くときに「最初に路線を選んでください。そしたら時刻表を出してあげます」と言われる感じ**です。つらい気持ちになる。

ということで、fromの港と、toの港を選べば、時刻表をもとに検索してくれるツールを作りました。

ソースはこちら（大したことないけど）

https://github.com/yo16/goto_fune

動くサイトはこちら（herokuのため最初だけ重い時があります）

https://goto-fune.herokuapp.com/

ちなみに五島のすべての港はこちら（25港！）

https://www.google.com/maps/d/edit?mid=1l0gnFvccRWHFEErs-4EIaQTQ9MfDi_4&usp=sharing

# 作った方法
まず、[五島交通ナビ](http://www.goto-koutsu.jp/pctime/timetable.php?kbn=ship)や五島最大手の[九州商船](https://kyusho.co.jp/publics/index/111/)のホームページを見て、すべての時刻表をJavaScriptに書き起こしました。

なにしろみんなフリーフォーマットなので、スクレイピングとかは絶対無理です。往路は左から右、復路は右から左に、tableになってたりとか。そういうのを目で確認しながらコツコツやりました。（おそらくミス＝バグもあるでしょう・・・）大体、５～６時間かかりました。

次に、JavaSciriptで配列をぐりぐり回して探す処理を入れました。大体３時間くらい。

最後に見た目を整えて完成。大体２時間くらい。


# テクニカルな話
あんまりないけどこのままだと日記になるので少しだけ。

## マスターテーブル（配列）から、IDを指定して取り出す

こんな感じで、マスタテーブルのような配列を作りました。

> let PORTS = [{'id':1, 'name':'福江港'}, {'id':2, 'name':'奈良尾港'}];

IDを指定して、この情報を取り出す方法。

> PORTS.find((mst_p) => mst_p.id==p["from"]);

うーん・・・しょぼいテクですみませんｗ
技術的にはそんなもんです。


# まとめ
技術的なレベルはさることながら、うれしい人は結構いると思うのです。次の朝ドラは五島みたいだし、リゾートホテルもオープンするようだし。
私自身の技術レベルも高くないので、ローテクだけどうれしい人がある程度いる、というところを、今後も攻めたいと思います。

あとこういうの、ちゃんと市とかまとめてる人たちが問題意識をもってやってほしい。（アドバイスしますよ！）

# 追記(2022/8/21)
2022年8月に福江島(下五島)、中通島(上五島)へ旅行へ行ってきました！このツールやっぱ使えますよ。五島へ行く人は是非！
- 五島の船の時刻表
  - https://goto-fune.herokuapp.com/

スマホ対応してなかったので、しておきました。
```
<meta name="viewport" content="width=device-width">
```
これを追記しただけですがｗ
東京都のオープンデータを使って、Googleデータポータルで遊ぼ！！

# これはなに？

Googleデータポータルで東京都のオープンデータを可視化したりなんだりして遊ぼうの記事です。

※「データポータルとは？」という方は、以下の記事をご参照ください。

https://qiita.com/chanmi-narita/items/96ba738fcdc50ccb067e

# きっかけ

完全にこれ ↓ です。
@e99h2121 さんの記事を見て「私もやりたいーーー！！！」と思った、それだけです、、、

https://qiita.com/e99h2121/items/1b53a6f5dca2cef6ac23

会社でデータ分析をする際は、専用の解析ツールを導入してたりなんだりして、
データポータルを触る機会がなかったりするじゃないですか。

とにかくデータポータルを触りたいだけなのです。


# いざ、実践。

## ①まずはデータを用意する

今回は東京都のオープンデータ一覧から、公衆無線LANアクセスポイント一覧データを使わせていただこうと思います。

▼TOKYO OPEN DATA

https://catalog.data.metro.tokyo.lg.jp/dataset


▼公衆無線LANアクセスポイント一覧データ

https://catalog.data.metro.tokyo.lg.jp/dataset/t000012d0000000016/resource/011260d9-6d76-4200-bd9a-643234e7ec4b

## ②分析用にデータを加工する

CSVで出力したものをスプレッドシートに移行しました。
今回、市区町村別のWi-Fiアクセスポイント数を可視化したかったのですが、なぜか市区町村のカラムがnullでしたので下記にて少し加工しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/0b6c2245-96dc-46c6-bca0-836ef0dfaebc.png)

加工手順はこちら。

https://qiita.com/chanmi-narita/items/40dbb397de603a726620

## ③データポータルの新規レポートを作成する

データソースは先ほど作ったスプレッドシートを選択します

![データポータル_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/9beab6a8-3481-7cc2-a29d-3c9a0ec74603.png)


## ④市区町村別のWi-Fiアクセスポイント数をグラフ化する

ディメンション：市区町村
指標：Record Count

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/8cec4ed7-7319-6070-996c-9f97fcbd9d33.png)

ほ～～～～、新宿か渋谷がぶっちぎりかと思ってたらそうでもなかった。
台東区や中央区は観光客が多いってのも関係あるのかな？

# まとめ

データポータルは楽しい:raised_hands_tone1:


# Reference

https://qiita.com/e99h2121/items/1b53a6f5dca2cef6ac23

きっかけをくださり誠に感謝です:pray_tone1:
【Excel関数】FIND関数を用いて住所から市区町村データを抜き出す

# これはなに

スプレッドシートでFIND関数を用いて、住所から市区町村データをカラムとして抜き出す方法をまとめます。

# 背景

下記、東京都のオープンデータを用いて、Googleデータポータルで遊びたい。

https://catalog.data.metro.tokyo.lg.jp/dataset/t000012d0000000016/resource/011260d9-6d76-4200-bd9a-643234e7ec4b

市区町村別の無料Wi-Fiのアクセススポット数を可視化したいが、
市区町村のカラムが空データのため、住所から市区町村をカラムとして抜き出したい。




# STEP①：まず、住所から`都道府県+市区町村` を抜き出す

LEFT関数 / FIND関数 / IFERROR関数を用います。

![スプレッドシート関数_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/ba95a1ec-bbc9-1cf0-0fe9-580d9a26e74f.png)



▼実際の数式

```=left(E2,IFERROR(FIND("市",E2),IFERROR(FIND("区",E2),IFERROR(FIND("町",E2),IFERROR(FIND("村",E2),0)))))```
※IFEROR関数じゃなくてIF関数を使ってもいいと思います。

> セルE2の中から「市」OR「区」OR「町」OR「村」という文字列を見つけたら、その左側の文字列を引っ張ってきてね

という指示文になっています。


# STEP②：STEP①で出したデータから`市区町村` を抜き出す

RIGHT関数 / FIND関数 / IFERROR関数を用います。

![スプレッドシート関数_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/2c2a4e84-acb8-8707-c7e5-2e6d6d5ea1b9.png)

▼実際の数式

```=RIGHT(K2,IFERROR(FIND("都",K2),0))```
※IFEROR関数じゃなくてIF関数を使ってもいいと思います。

> セルK2の中から「都」という文字列を見つけたら、その右側の文字列を引っ張ってきてね

という指示文になっています。

# 使用した関数一覧


|関数 | 関数書式 | 意味 | 
|:---:|:---:|:---:|
|LEFT関数|LEFT(文字列,文字数[任意]) | 指定した文字列の先頭から部分文字列を返します。|
|RIGHT関数|RIGHT(文字列,文字数[任意]) | 指定した文字列の末尾から部分文字列を返します。|
|FIND関数|FIND(検索文字列,検索対象のテキスト,開始位置[任意]) | 特定の文字列がテキスト内で最初に現れる位置を返します。文字列が見つからない場合は「#VALUE!」を返します。|
|IFERROR関数|IFERROR(値,エラー値[任意]) | エラー値でない場合は 1 番目の引数を返します。エラー値である場合は 2 番目の引数を返します（指定した場合）。2 番目の引数を指定していない場合は空白が返されます。|

引用元：Googleスプレッドシート

# まとめ

今回の方法は筆者がよくやる方法を書きましたが、2STEPに分かれるのでちょっと綺麗じゃない‥。
もっといい方法があれば教えていただけると幸いです:pray_tone1:


Excelの「区切り位置」、スプレッドシートの「テキストを列に分割」の条件を設定する際、
複数条件を設定できればよいのですがが、調べてもやり方が出てこなかった‥（出来ないのかなぁ？:thinking:）
「達人に学ぶSQL徹底指南書」の演習問題 4-3を解いてブラウザで動作確認してみた

## この記事の概要
- この記事は「達人に学ぶSQL徹底指南書/ミック著」の演習問題をブラウザのSQL実行環境([db-fiddle.com](https://www.db-fiddle.com/))で動かしてみたというものになります。
- 解説は書籍の方を参照してください。
- カラム名がアルファベット表記になっていることに注意してください

## [db-fiddle.com](https://www.db-fiddle.com/)の使い方
- テーブルの作成: Scheme SQLの欄にCREATE TABLEを書いてテーブルを作成
- データの挿入: Query SQLの欄にINSERT文を書いてデモデータを挿入する
- データの検索: Query SQLの欄にSELCT文を書く

## 問題文

「『関係除算でバスケット解析』(p73)では、条件を店舗だけを結果として選択しました。
しかし、要件によっては、品物を全て揃えていなかった店舗についても『どれぐらいの品物が不足していたのか』
を一覧表示したいこともあるでしょう。
　そこで、先の関係除算のクエリを、次のように全店舗について結果を一覧表示するよう変更してください。my_item_cntは店舗の現在在庫数、
diff_cntは、足りなかった商品の数を表しています。」

- 出典: p80, 達人に学ぶSQL徹底指南書, 第1版

## データセットの準備
- Schema SQL
```sql
CREATE TABLE Items(
  item varchar(255) NOT NULL 
);

CREATE TABLE ShopItems(
  shop varchar(255) NOT NULL, 
  item varchar(255) NOT NULL 
);
```

- Query SQL
```sql
INSERT INTO Items VALUES 
('beer'),
('omutu'),
('bicycle');

INSERT INTO ShopItems VALUES 
('sendai', 'beer'),
('sendai', 'omutu'),
('sendai', 'bicycle'),
('sendai', 'curtail'),
('tokyo', 'beer'),
('tokyo', 'omutu'),
('tokyo', 'bicycle'),
('osaka', 'TV'),
('osaka', 'omutu'),
('osaka', 'bicycle');
```

## 解答

詳しい解説は書籍を参照してください。

```sql

SELECT 
  SI.shop, 
  COUNT(*) AS my_item_cnt,
  (SELECT COUNT(item) FROM Items) - COUNT(SI.item) AS diff_cnt
FROM ShopItems SI, Items I
WHERE SI.item = I.item
GROUP BY SI.shop;

```
devise_token_authを用いたユーザ登録時の「Unpermitted parameter: :registration」の対処

# はじめに
vue.js + Ruby on Rails(apiモード)でユーザ登録機能を作成中に、以下のエラーが発生。
```ruby
Processing by DeviseTokenAuth::RegistrationsController#create as HTML
  Parameters: {"name"=>"dd", "email"=>"dd@dd.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "registration"=>{"name"=>"dd", "email"=>"dd@dd.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
Unpermitted parameter: :registration
Unpermitted parameter: :registration
Unpermitted parameter: :registration
```

ユーザ登録時には、emailとnameを受け付けたかったので、以下のようにしていた。

```ruby
class ApplicationController < ActionController::API
  include DeviseTokenAuth::Concerns::SetUserByToken
  before_action :configure_permitted_parameters, if: :devise_controller?

  private

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :name])
  end
end
```
:registrationが何者か？と思い、調べた結果を記載。
（似た情報では、params.require(:registration).permit(~~)みたいにして解決する情報がすぐにあったが、それ以外の情報が簡単に見つからなかったのでメモ）

# 結論
railsの(デフォルトの?)挙動で、parameterがwrapされるためのようでした。
https://github.com/lynndylanhurley/devise_token_auth/issues/1178 からの-> https://github.com/heartcombo/devise/issues/4825
で判明。
たしかに、以下のようになっていた。
```config/initializers/wrap_parameters.rb
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end
```
railsも作り立てで他への影響がないので、initializerで以下のように変更。
```config/initializers/wrap_parameters.rb
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: []
end
```
【Amazon S3静的ウェブサイト】なぜバケット名をドメイン名にしないといけないのか？

Amazon S3には、バケットにファイルをアップロードするだけでウェブサイトとして公開できる静的ウェブサイトホスティングという機能があります。Route 53を活用することで、自分で用意したドメインへのアクセスをS3バケットに転送することも可能です。これらは[公式チュートリアル](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html)に沿ってやればできるのですが、その中に気になる一文があります。

> バケット名はドメイン名と厳密に一致している必要があります

例えば`http://example.com`でウェブサイトを運用したい場合、バケット名も`example.com`にする必要があります。ただバケット名はリージョン内で一意でなければいけないので、すでに他の人がそのバケット名を使っていることだってあり得ます。なぜこんな制約があるのでしょうか？[^1]

# DNSの仕組み

そもそも`http://example.com`のようなアドレスからウェブサイトを見つけるには、まずドメイン`example.com`をIPアドレスに変換する必要があります。ドメイン名からIPアドレスへ変換することを名前解決といい、名前解決をしてくれるシステムがDNS (Domain Name System)です。DNSにはレコードと呼ばれる情報が格納されていて、それらを参照することで名前解決を行います。AWSでDNSを運用するためのサービスがRoute 53です。

## AレコードとCNAMEレコード

Aレコードは、ドメインとIPアドレスの対応づけを定義するためのレコードです。

| レコード名      | タイプ   | 値             |
| ------------- | ------- | -------------- |
| example.com   |  A      | x.x.x.x        |

上記の例で言えば、`example.com`のデータはIPアドレス`x.x.x.x`のサーバにあると定義するわけです。

ついでにCNAMEレコードというものもあって、これはあるドメインの別名を定義するものです。

| レコード名          | タイプ   | 値             |
| ----------------- | ------- | -------------- |
| sub.example.com   | CNAME   | example.com    |
| example.com       | A       | x.x.x.x        |

この例だと、`sub.example.com`は`example.com`の別名であり、`sub.example.com`のIPアドレスを知るためには`example.com`のAレコードを参照すれば良いことになります。


## エイリアスレコード

Aレコードには対応するIPアドレスを具体的に記入する必要があるのですが、AWSのように大規模でIPアドレスも固定されていない環境での運用は不便です。これを補うためにAレコードを拡張したのがエイリアスレコードで、Route 53固有の機能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065604/b92dded3-7f97-7488-3b15-dff88c6f1ff2.png)

Route 53でAレコードを作成する際にエイリアスをオンにすると、対応しているAWSのサービス一覧が表示されので、IPアドレスの代わりに目的のリソースを選ぶことができます。エイリアスレコードの実態はあくまでもAレコードなので、名前解決の問い合わせに対しては、Amazonが自動的にリソースに対応するIPアドレスを応答してくれます。

## 独自ドメインとS3の静的ウェブサイトホスティング

自分で用意したドメインでウェブサイトを運用したい場合、DNSへのAレコードやエイリアスレコードの登録が必要なのはわかりました。しかしS3で静的ウェブサイトホスティングをしたい場合、どのIPアドレスをレコードに記入すれば良いのでしょうか？

仮に世界中の個々のS3バケットにIPアドレスが割り振られているとしたら話は簡単で、レコードにそのアドレスを記入すれば良いでしょう。しかしIPv4で扱えるアドレスは限られているので（[というか大体の地域で枯渇してる](https://www.nic.ad.jp/ja/ip/ipv4pool/)）、Amazonが静的ウェブサイトホスティング機能を使用する全てのバケットのためにIPアドレスを用意するのは現実的に無理でしょう。

従って窓口となるIPアドレスを用意し、HTTPリクエストの情報をもとにバケット名を推測して、目的のバケットへと転送せざるを得ません。そこでAmazonはHTTPリクエストに書かれているドメイン名を使うことにしたのだと思います（HTTP/1.1でいうならば[Hostリクエストヘッダ](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Host)の値[^2]）。

# 結論

ネットでも断片的にしか情報が見つからなかったので、自分なりに考察を加えて出した結論は以下です。

- 独自ドメインとバケットのIPアドレスの紐づけが必要（名前解決）
- IPv4を使用する限り、個々のバケットにIPアドレスを割り振るには数が足りない
- 窓口となるIPアドレスを用意して、HTTPリクエストに書かれているドメイン名をもとに目的のバケットを探すことにした

IPv6に完全に移行できたら、こんな制約は不要になるんじゃないかなと思います。

[^1]: あくまでもドメインへのアクセスを直接バケットに転送したい場合です。CloudFrontなどのサービスを間に挟む場合は、ドメイン名とバケット名を一致させる必要はないです。

[^2]: HTTP/2では:authorityヘッダが相当するらしいです。
【Ruby on Rails】ransackの関連を調べる方法

## やり方
rails consoleを開く。
```ruby
[8] pry(main)> Gorira.ransackable_associations
=> ["corporation", "user", "articles", "schools", "shool_goriras"]
```
こんな感じで``.ransackable_association``というものを使用すると関連を確かめることができる。
【GCE】アクセススコープは、意識しなくても良くすることがベストプラクティス

Google Compute Engine (GCE)において、VMインスタンスから他のサービスのAPIを叩けるようにするには、
**サービスアカウント**と**アクセススコープ**の両方でアクセス権限を付与する必要があります

片方でしか許可してないと、アクセスは拒否されます

そこで、以下の疑問が浮かびました
- 何故サービスアカウントとアクセススコープの両方で許可をしないといけないのか
- 結局アクセススコープはどのように扱うのがベストプラクティスなのか

## 調べた結果たどり着いた結論
### 何故サービスアカウントとアクセススコープの両方で許可をしないといけないのか
アクセススコープは[レガシーな方法](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam)であり、本当はサービスアカウントで権限管理をしたほうが良い
だけどアクセススコープベースでの権限管理を続けたい人のために、今の形になっている

基本的に「権限管理に使わない方では全部のAPIを許可する」
- アクセススコープで権限管理するなら、サービスアカウントはGCE用のデフォルトのものを使用する（編集者ロールが付与されている）
- サービスアカウントで権限管理するなら、アクセススコープは全てのAPIを許可する

### 結局アクセススコープはどのように扱うのがベストプラクティスなのか
[公式ドキュメント](https://cloud.google.com/compute/docs/access/service-accounts#scopes_best_practice)に書いてあるとおり、**サービスアカウントベースの権限管理をするのがベストプラクティス**
- デフォルトのGCE用サービスアカウントは使わない
    - 各VMインスタンス用の自作のサービスアカウントを用意
- アクセススコープは全部のAPIを許可

## もう少し詳しく
GCEにおいては、具体的には次の2パターンの方法で権限管理ができます

### アクセススコープベースでの権限管理
こちらの場合、サービスアカウントはGCE用にデフォルトで用意されているものを使用します
GCE用にデフォルトで用意されているサービスアカウントは編集者ロールが付いているため、ほぼ全てのAPIが許可されています

そのうえで、アクセススコープを用いて権限管理を行います

コンソール画面はこうなります
![sa_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697194/7da0e03b-29ea-4f12-1694-88209f48a30b.png)

### サービスアカウントベースでの権限管理
**こちらがベストプラクティスとなります**

こちらの場合、サービスアカウントはVMインスタンス毎に自作のものを用意します

そのうえで、アクセススコープは全部のAPIを許可するように設定します

これによって、**権限管理においてアクセススコープを意識する必要がなくなります**

コンソールにおいては、自作のサービスアカウントを設定すると、アクセススコープは設定変更することすらできなくなります
※ 「my-sa-vm」が事前に自作したサービスアカウント
![sa_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697194/721cdc24-23be-5bf2-c91c-3009cc426317.png)

#### （おまけ）cloud-platform
アクセススコープのベストプラクティスについて、[公式ドキュメント](https://cloud.google.com/compute/docs/access/service-accounts#scopes_best_practice)は以下のように記載されています

> 使用可能なアクセス スコープは多数ありますが、ベスト プラクティスは `cloud-platform` アクセス スコープを設定することです。これは、ほとんどの Google Cloud の OAuth スコープです。サービス アカウントに IAM ロールを付与し、サービス アカウントのアクセス権を制御できます。

「`cloud-platform` アクセス スコープ」というワードが出てきますが、
直下の[スコープの例](https://cloud.google.com/compute/docs/access/service-accounts#scopes_examples)に記載されている通り、
「`cloud-platform` アクセス スコープを設定する」=「全てのAPIを許可する」
です

TerraformでVMインスタンスを作成する際に、このことを意識する必要があります
Terrafromにおいては、自前のサービスアカウントを指定していたとしてもアクセススコープの指定をする必要があります
そこで、以下のように`service_account.scopes`に`"cloud-platform"`を指定することで、ベストプラクティスに則ることができるのです
```
resource "google_compute_instance" "my_vm" {
  ...

  service_account {
    email = google_service_account.my_vm.email
    scopes = [ "cloud-platform" ]
  }

  ...
}
```

## 参考
- [サービス アカウント](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam)
UE4 初心者・集中トライ・照明制御まで　

## UE4 ブループリント整理は頭の整理ですね！　”好きになってきました”
![2022-08-02 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/427535ec-28ab-bd6f-2844-e6876e4d20ee.png)
## UE4 Eyetrack  ブループリントを中心に録画してみました。
https://youtu.be/oCyvl_-ZYNw
## UE4　開発関係映像紹介
![youtube tkurume UnrealEngine-Eyetrac-2022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/d68b71aa-d9db-01bb-161b-68b8781fd544.png)
＜　youtube UnrealEngine-Eyetrack Demo&Test ＞
2021/6/09 
・UE5-Eyetrack Editor Newly developed environment Test
https://youtu.be/rs1Pv4yDp38 
2021/5/21
 ・UE4 Newly developed environment CPU-i7-10700 GPU-RTX2070super
 https://youtu.be/Sw_uTYa6LCE
2021/5/06
・UE4-Eyetrack Editor Utility Widget Blueprint test for distribution package
https://youtu.be/5R3qAJbK6oU
2021/5/03
・UE4-Eyetrack Demonstration recording software test for distribution package
https://youtu.be/EJNyHhOVJSA
2021/4/26
・UE4-Eyetrack lighting water-surface testing Demo
https://youtu.be/zLbwOX_psyU
2021/4/23
・UE4-Eyetrack AI-tracking camera-zoom-view
https://youtu.be/VFrGF7BBAyg
2021/4/22
・UE4-Eyetrack AI-tracking Test
https://youtu.be/0rA4du2zUpk
2021/4/20
・Multi-control & camera-view
https://youtu.be/uYu3JfWIo6c
2021/4/19
・Eyetrack  Unreal Edito Dmx-Output
https://youtu.be/qsb2r3Y2vQA
2021/4/16
・Automatic tracking lighting camera demo
https://youtu.be/5aCgFMl6OrM
2021/4/16
・Game-pad PTZ camera EyetrackT 
https://youtu.be/wKWXK1CBTUM
2021/4/15
・Tracking lighting PTZ camera
https://youtu.be/OB3zk2mZByo
2021/4/15 
・Automatic tracking lighting  web camera
https://youtu.be/Jtrx4bdbzM8
2021/4/14
・Automatic tracking lighting camera
https://youtu.be/7W8tie6wlPs
2021/4/13
・Successful automatic tracking lighting !!
 https://youtu.be/0twSVEAzaFQ
2021/3/29
・Unreal Engine DMX Art-net Input Game-pad Rasperry-Py
https://youtu.be/N5WdJM_tKfg
2021/3/29
・UE4 Moving-light control game-pad
https://youtu.be/8ZrASYwUaL8
2021/3/23
・UE4 Dmx Art-net Input Wifi stick
https://youtu.be/BDmcKNjoYQ4
2021/3/09
・Panasonic Network camera new Eyetrack system import confirmation
https://youtu.be/hpL0RD2in5o
2021/3/09 
・Panasonic Time stamp, camera position, center mark display on network camera image
https://youtu.be/hvtNowpzhoQ
laravelで画像投稿処理を実装する


# 前書き
現在独学でlaravelを使ったポートフォリオの作成に取り組んでいます。
今回は画像登録・表示処理で詰まったところを備忘録として投稿します。

# 環境

https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4

上記記事に準じて環境構築を行っています。

# 実現したいこと
・作成済みのユーザーページを編集する際に、名前、年齢の他にアイコンとして画像を登録できるようにする。
・登録した画像を表示する。


# 対応方法
①編集フォームにinputタグを設置し、ファイルを送信できるようにする。
```php:edit.blade.php
<form method="post" action=" {{route('users.update',['user'=>$user])}}" enctype="multipart/form-data">
<input type="file" name="image">
~~~
<button tyoe="submit"></button>
</form>

```
＊formにtype="multipart/form-data"を入れないとファイルデータが送信できない。
*accept="~~"で登録可能な画像の拡張子を限定できます。


②コントローラーに処理を記載
```php:UserController
public function update(UserRequest $request, User $user)
{
$image = $request->file('image');
if ($image !== null) {
    $filename = $image->getClientOriginalName();
    Storage::disk('public')->delete(($user->image));
    InterVentionImage::make($image)->resize(
        100,
        100,
    )->save(storage_path('app/public/' . $filename));
    $user->update([
        'name' => $request->name,
        'age' => $request->age,
        'image' => $filename,
    ]);
} else {
    $user->fill($request->all())->save();
};
return redirect()->route('users.show', ['user' => $user->id]);
}

```
laravelの画像の保存先は、下記の２つがあります、
・storage>app>public 外部公開用
・public>storage 


```
docker compose exec app php artisan storage:link
```
を実行し、シンボリックリンクの作成を忘れずに実施しておきましょう。

ファイルの保存先を指定します。
（この場合はapp>publicディレクトリ内に保存されます。）
>->save(storage_path('app/public/' . $filename));

今回は画像サイズを編集したかったので、InterVention/Imageを使用しています。
インストールしてconfig>app.phpの編集後エラーが出ましたが、下記記事を見てDockerfileを編集して再度buildすることで対応しています。

https://qiita.com/Soh1121/items/17dcdc815a1d22f31788


ファイルの保存にあたっては、今回はInterVentionImageを使用しているため、saveメソッドでのファイル保存となっています。
通常はstore(storeAs)メソッドでの登録となるようです。


また、今回はユーザーごとのアイコンをDB上にも保存させたいので、
userモデルには画像ファイルのパスを渡します、

ファイルが選択されている場合とされていない場合で処理を分岐させています。

```php:UserController
Storage::disk('public')->delete(($user->image));
~~~
$user->update([
    'name' => $request->name,
    'age' => $request->age,
    'image' => $filename,
]);
```
選択ありの場合、既存の画像ファイルを削除した上で、新しい画像ファイル(のパス)を登録しています、

選択されていない場合、image以外の項目のみ更新されるようにしています、

③view表示

```php:User.blade.php
  @if($user->image !== null)
#userモデルのイメージカラムに値があるかどうかで条件分岐
        <img class="rounded-circle" src="{{asset('storage/' . $user->image)}}">
        @else
        <i class="fa-solid fa-circle-user"></i>
#falseの場合デフォルトアイコンを表示するよう設定
        @endif
```


# 結果
アイコンが表示されるようになりました。
新しい画像を追加すると、元の画像は削除され、新しい画像が反映されます。
画像が登録されていない人はデフォルトアイコンが表示されます。

# 最後に
より良いコードの記述方法や投稿内に誤りがありましたら、ご指摘いただけると助かります。

今後も定期的に詰まったところを備忘録として記載していきたいと思います。
駄文にはなりますが、最後までご覧いただきありがとうございました。
RPAでビジネスはどう変わるか？

# はじめに
IT×ビジネスという視点で週1本記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiita.com/7_inai_)
# RPAとは
RPAとは、Robotic Process Automationの略で、__PC上で行う業務をロボットで自動化__ することを指します。
データの入力や転記、ファイルの複製といった単純作業の自動化をしてくれるので、業務改善や働き方改革に繋がります。

# RPAのできること。できないこと。
RPAがあれば人の仕事がなくなってしまうのでは？と思う方もいるかもしれませんが、その心配はありません。RPAには得意分野と苦手分野があり、人の手が必要な業務もまだまだ存在します。具体的には以下の通りです。

### ■できること
- 手順が決められている作業
→「どのデータを抜き出すか」「どう集計するか」「どこに登録するか」といった条件が同じであればRPAツールで自動実行可能
- 情報収集
→RPAツールにはWebブラウザを自動操作できるものもあります。そのため人が操作するよりも格段に速いスピードでウェブサイトを巡回し、最新の動向をチェックすることができます。
- 電話やメールの自動応答

### ■できないこと
- ルールが複雑であったり都度変わる作業
- 臨機応変さが求められる作業
- 物理的な操作が必要
- RPA自体の設計・開発



# 終わりに
RPAを使用すると今まで人がしていた作業をロボットに任せることができます。前述しましたが、それにより仕事の内容が変わることはあっても人の仕事がなくなることはないでしょう。例えば、車が世間一般に広まったことで、現在では馬車を見かけることはめったにありません。それにより御者(馬車を運転する人）のような馬に関わる仕事は減りましたが、その代わり自動車開発やタクシーの運転手のような新しい仕事が生まれました。RPAで言えば、今度はRPAを設計するというような新しい仕事が生まれるのです。


最後までお付き合いくださりありがとうございました。
「取り返しのつかないことをしない」

> 「取り返しのつかないことをしない」

昔、同僚と議論していて口走った言葉です。実はプログラマーとしてわりと重要な考えなのではないかと思います。

# 例: EC2のパブリックIPをスマホアプリに直書きする

スマホアプリ向けの静的ファイルやバックエンドAPIをAWSに実装した際、最初はスモールスタートだと言うことでEC2インスタンス1台の構成にしたところまではいいが、インスタンスに自動で割り当てられるIPアドレスをスマホ側で直接参照する実装にしてしまった。

こうなると、AWS側はアーキテクチャを変えるどころか、EC2インスタンスを再起動することすらできません（再起動するとIPアドレスが解放されてしまう）。スマホアプリをアップデートして、IPアドレスを直接参照するのを止められればいいのですが、一度公開したアプリを100％アップデートするのは事実上不可能です。

最初にRoute53でホスト名を解決するか、せめてEIPを使ってIPアドレスを再利用できるようにしていれば…

# 例: 大量のBashスクリプト

顧客向けの請求レポートを日次で作ることになりました。簡単な集計をしてメールを送るだけなので、sqlplusコマンドでSQLを実行し、sendmailコマンドを実行する、Bashスクリプトを書きました。顧客はせいぜい数社なので、受注するたびスクリプトをコピペで増やしていました。

数年後……そこには、千個を超えるバッチ処理スクリプトの群れが！しかも、顧客ごとに微妙にカスタマイズされており、1つとして同じものはありません（より正確には、同じものがあるのかどうかも分かりません）。

ところで、DBをオンプレのOracleから Amazon RDS for PostgreSQLに移すことになったのですが、一体どうすればいいのでしょう。

# 例: グローバル変数を使う

古典的＆マイクロな話題としては、グローバル変数を使わない「取り返しのつかないことをしない」ためです。

一度使われたグローバル変数を廃止するのは、大抵コード全体の構造を変える必要が出てきて、困難な作業になります。

# 例: テストを書かない

テストが無いコードはレガシーコードだ！

テストがあれば、本体のコードが汚くても、比較的容易にリファクタリングすることができ、リグレッションの恐れもありません。逆にテストが無いと…。

また、実際のところ、最初からテストを書いて品質の良いコードを書いた方が最終的な開発効率は上がります。それどころか、テスト自動化の損益分岐点は**４回**であり、月１リリースでも半年で「初めからテストを書いた方が安上がりだった」状態に達することになります。

https://speakerdeck.com/twada/quality-and-speed

# その他「取り返しがつかないこと」

- Pythonの依存パッケージを管理していない。pipenv? pip? そんなの知らないよ、僕初心者だもん。
- １人プロジェクトだからとScalaでコードを書いたら、社内にScalaを書ける人がおらず、プロジェクトに縛り付けられた
- バグを放置していたら、ユーザーが「バグを前提にした利用」をし始め、バグを直せなくなった
- 小規模だからと IoC化せずAWSコンソール画面からリソースを作っていたら、全体像が分からなくなった。

# 「取り返しのつかないことをしない」とは

上で挙げた「取り返しのつかないこと」の例は、**ちょっと時間を掛けて予習したり相談したりすれば、避けられた問題**が多いようです。

なので、「取り返しのつかないことをしない」とは言い換えれば **「目先のコストを厭ったり、目先の利益を追ったりして、長期的な負債を抱えるなかれ」** ということなのかもしれません。

そして、「取り返しのつかないこと」を避けるのは、大抵、難しいことではなさそうです。

# なんでこんな記事を書いたの？

お風呂に入ってボーッと今までの仕事のことを考えていたら、突然、この台詞を思い出しました。今となっては、どんなシチュエーションで誰に言ったのかも曖昧です。