OmniAICreator/Qiita-1.07M huggingface dataset:
PostgreSQLでテーブルとカラムのコメント抽出

備忘録。

テーブルやカラムにつけたコメントをまとめて表示する。
WHEREにて、テーブル指定やコメント文字列指定、NULL指定ができる。

コンセプトは、把握できていないDBについて、コメントを横断検索して、調査の手がかりにすること。

ビューに対応させる気がなかったので、
必要な人はpg_stat_user_tablesをpg_classに変えること。
ユーザテーブルに絞り込まれているので便利。

確認：PostgreSQL12

```sql:PostgreSQL
SELECT
    pg_stat_user_tables.schemaname,
    (SELECT pg_description.description
    FROM pg_description
    WHERE pg_stat_user_tables.schemaname::regnamespace = pg_description.objoid
    ) AS schemacomment,
    pg_stat_user_tables.relname,
    (SELECT pg_description.description
    FROM pg_description
    WHERE pg_stat_user_tables.relid = pg_description.objoid
    AND pg_description.objsubid = 0
    ) AS relcomment,
    information_schema.columns.column_name,
    pg_description.description AS colcomment,
    information_schema.columns.data_type,
    information_schema.columns.character_octet_length,
    information_schema.columns.numeric_precision || ',' ||
      information_schema.columns.numeric_scale AS numeric_length
FROM pg_stat_user_tables
LEFT JOIN information_schema.columns
    ON pg_stat_user_tables.schemaname = information_schema.columns.table_schema
    AND pg_stat_user_tables.relname = information_schema.columns.table_name
LEFT JOIN pg_description
    ON pg_description.objoid = pg_stat_user_tables.relid
    AND pg_description.objsubid = information_schema.columns.ordinal_position
WHERE 1 = 1
/*    AND pg_description.objsubid = 1 */
/*    AND pg_stat_user_tables.schemaname = 'schema' */
/*    AND pg_stat_user_tables.relname = 'table' */
/*    AND EXISTS
    (SELECT 1 FROM pg_description
    WHERE pg_stat_user_tables.relid = pg_description.objoid
    AND pg_description.objsubid = 0
    AND pg_description.description = 'relcomment'
    ) */
/*    AND information_schema.columns.column_name = 'column' */
/*    AND pg_description.description = 'colcomment' */
ORDER BY pg_stat_user_tables.schemaname,
    pg_stat_user_tables.relname,
    information_schema.columns.ordinal_position;
```

参考：https://ufirst.jp/memo/2014/11/30/postgresでテーブルのカラム一覧をコメント付きで取得/
获取 youtube 封面

http://i.ytimg.com/vi/A5qVLy8tHyI/default.jpg

http://i.ytimg.com/vi/A5qVLy8tHyI/mqdefault.jpg 普清

http://i.ytimg.com/vi/A5qVLy8tHyI/hqdefault.jpg  标清

http://i.ytimg.com/vi/A5qVLy8tHyI/sddefault.jpg  高清

http://i.ytimg.com/vi/A5qVLy8tHyI/maxresdefault.jpg  超清 不一定存在

https://img.youtube.com/vi/kGkd48vo6UI/sd1.jpg

https://img.youtube.com/vi/kGkd48vo6UI/sd2.jpg

https://img.youtube.com/vi/kGkd48vo6UI/sd3.jpg

---

参考：

https://stackoverflow.com/questions/2068344/how-do-i-get-a-youtube-video-thumbnail-from-the-youtube-api

https://www.strerr.com/t.html
イニシャライザーってなんだ。

# はじめに
野良でコードをまねていたりすると、たまに構造体の中に出てくるinit( ) 。
調べてみるとどうやらイニシャライザーというものらしい。
使い方が全く分からない。てかいらなくない？と思ってしまった。
しかし、イニシャライザーを理解できていない = しっかり基礎が身についていないということに気づいてしまいました。。。
そこで今回は、イニシャライザーについて備忘録的にまとめていくことにします。

Swiftは勉強中ですので、間違えていましたら指摘いただけると幸いです。

# 目次
| 項番 | ページ内リンク |
|:----:|:-------------|
| 1 | [イニシャライザーとは](#-1-イニシャライザーとは) |
| 2 | [どのような時に必要なのか](#-2-どのような時に必要なのか) |
| 3 | [selfとは](#-3-selfとは) |
| 4 | [まとめ](#-4-まとめ) |


# 1.イニシャライザーとは
結論から言うとイニシャライザーとは、 **「構造体の初期設定を実行するメソッド」** です。

・・・？？？
わけわかんねぇよ。お腹すいたよ。
まずは落ち着いておにぎりを食べてください。
順番に説明していきます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
※ここまでで構造体、プロパティ、メソッド、インスタンスをはっきり理解できていない人は、まずはこの基礎を理解しましょう。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

# 2.どのような時に必要なのか
説明する前に以下のコードを理解してください。

```swift
    struct ProfileSetting {
        var name = "田中"
        var hairColor = "黒"
        func sayProfile() {
            print("あなたのユーザ名は\(name)、髪の色は\(hairColor)です")    
        }
    }
```

ゲームで初めにプロフィールを設定する場面を想像してください。
あなたの名前、髪の色など、様々な初期設定を冒険の前に設定しますよね？
この時、ゲーム制作者はゲームをするユーザの名前、髪の毛の色は分かりますでしょうか？

上記の場合、構造体ProfileSettingのプロパティnameには、"田中"が初めから格納されています。
ただ、ここは田中である必要はありません。
しかし、絶対に必要であるにもかかわらずユーザごとに設定が違うのでゲーム制作者は事前に設定することができません。

つまり以下のように書き替えることが可能です。

```swift
    struct ProfileSetting {
        var name: String
        var hairColor: String
        init(name: String, hairColor: String) {
            self.name = name
            self.hairColor = hairColor
        }
        func sayProfile() {
            print("あなたのユーザ名は\(name)、髪の色は\(hairColor)です")    
        }
    }
```

はい、出てきた init !
上記ではname, hairColorにはぞれぞれ何も代入されていません。
そのため初期設定としてメソッドのinitを使用し、それぞれにname, hairColorを代入しておくのです。

こうすることで、名前がまだない、いつでもなんでも代入できるname, hairColorが完成します。

通常、構造体を実体として呼び出すときにはインスタンスを使用すると思います。
今回の構造体ProfileSettingの場合は以下です。

```swift
    var profileSetting = ProfileSetting(name: "田中", hairColor: "黒")
```

実はなんとなく、ProfileSettingをProfileSetting()と記載していますが、
ProfileSetting()というのは、イニシャライザーを呼び出しているんです。
イニシャライザーを指定しておかないと、上記のように自由に値を入れることはできず、いちいちプロパティを変えたいときにはインスタンス名.name = ""や.hairColor = ""を記載していかなければいけません。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
※イニシャライズの宣言
ちなみにイニシャライズの宣言方法は以下です。

```swift
    init(ラベル1 引数名1: 型, ラベル2 引数名2: 型) {
        文
    }
````
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー


# 3.selfとは
さて、ここまで解説してきましたが、
なんかselfとかいうのいましたね。何だこいつ。

プロパティに値を指定するときに、selfを使っていますが。
 **これはインスタンス自身を表す識別子です。**

今回の場合、ProfileSetting構造体を宣言する{}の中でを指定すると、そのselfはProfileSetting構造体から作成されたインスタンスのことを指します。

別に構造体の中でname = nameって書いてあるんだからいちいちselfつけなくてもわかるっしょ。って思いますが、Xcodeは構造体ProfileSettingのプロパティのnameなのか、イニシャライザの第一引数のnameなのか区別できないんです。
人間じゃないから、なんとなくこれでしょは通じないんです。。。。

```swift
    struct ProfileSetting {
        var name: String
        var hairColor: String
        init(name: String, hairColor: String) {
            self.name = name
            self.hairColor = hairColor
        }
        func sayProfile() {
            print("あなたのユーザ名は\(name)、髪の色は\(hairColor)です")    
        }
    }
```

※ただし、selfをつけなくてもSwiftが区別できる場合はつけなくてOKです。

# 4.まとめ
イニシャライザーとは、 **「構造体の初期設定を実行するメソッド」** です。
自分で構造体を作成する際、ここは自分じゃプロパティを指定できないと思った際は使用することになると思います。
基礎力が必要といった意味は、構造体ってなんだっけ？アプリ作成した時見た目としてどんな役割だっけ、そのようなところが抜けていると（想像できないと） **文章だけではわけわからないと思います。**

土台は大事ですね。。。日々精進。
ではまた。
Mac 安装允许任何来源的应用

>![](https://upload-images.jianshu.io/upload_images/47789-a8ebe2489f0510b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

macOS 因为增强了安全性，所以 “允许任何来源的应用” 选项被隐藏，目的在于避免除Mac AppStore和正规签名外的未知或未签名App在系统内被任意执行，从而威胁用户隐私和系统安全。但这也造成了很多不便。

## 关闭方法

在终端中输入命令`sudo spctl --master-enable`，即可。
`sudo spctl --master-enable`

---
 
参考：

https://www.jianshu.com/p/319d3ed5d979
SQLiteのソースコードを読んでみる（１）～準備その２～

# 前回のおさらい

[前回の記事](https://qiita.com/Aburaiwashi/items/c248f47ca869f2384d1f)では SQLite のソースコードを入手するところまで終わった。
私はまだソースコードの海原に帆を立てていない。というか船を浮かべてすらいない。そもそも旅の計画を立てていない。私は夢見る少女じゃイラレない。このままでは遠足の 1 週間前に「バナナはおやつに入りますか？」と質問する小学生の方が今後の見通しが立っているではないか。

とはいえ、前回の記事を投稿してから何もしていなかった訳ではない。あれから私は焼き鳥を 40 本買い、駅の非自動ドアに顔から衝突し、歯医者から歯をゴリゴリされ、SQLite のソースコードをざっと眺めたりなどしていた。

# ところで "SQLite" でいいの？

ところで、表記は"SQLite"でいいのだろうか。今更不安になってきた。
[公式サイト](https://www.sqlite.org/index.html) のロゴには"SQLite"と書いてある。ハイデガーも「確認はメンタルの安定に一躍買う」って言ってますからね、確認してよかった（きっとハイデガーはそんなこと言ってない）。

# ソースコード多くないか？

緩和救済、もしくは閑話休題。
ソースファイルをざっと見た感じ、「SQLite のソースコードを全部読む」って池の水を抜くのと同じくらい大変そう。それでも全部読めないことはない……気がする。SQLite を開発する人たちって、この絶妙なラインを意図的に維持してるのだろうか。
きっとSQLite の開発規約に

```
3.4.16 ソースコードの分量
ソースコード全体の分量は以下の基準を維持すること。
* 一人で全部読むために３ヶ月以上かからない。
* ソースコードを入手した人の1/3は読む気にならない
```

みたいな一文が書いてあるんだろうな。
そんでこの基準を「３の法則」とか呼んでるんだろうな。きっと。

とりあえずコマンドプロンプトで以下のコマンドを実行

```
cd (SQLiteのソースコードを展開したフォルダ)
tree >file.txt
tree /F >dir.txt
```

**ファイル数、2000 個くらいあるジャマイカ。。。**

思ってたより多いな。ソースコードをアルファベット順に読んでいくのは非効率な気がするぞ。
まあ、ファイル名やフォルダ名を一通り読んでみて、どの順番でソースコードを読むか決めてみよう。

# 今後の読み進め方(2022-03-07 現在)

次回から以下の順番でソースコードを読み進めていこうと思う。順番はファイル名とか`README`を読みながら今日のノリで決めた。ので、十中八九この順番にはならないと思うよ！

- `src/`
  SQL の処理とかメインの処理をいろいろやってるみたい。
- `tool/`
  `src/` 内のファイルを一通り読んだらこっちも読む。メイン処理を補助する系のソースコードが置いてあるみたいなので、必要に迫られたときにも読んでいく予定。
- `ext/`
  機能を拡張するためのソースコードが入ってるみたい。読むのは後回しにする。ちなみに`ext/fts1/`みたいなフォルダがあるけれど、これがあると全文検索ができるんだって。ちょっと気になる。(多分"Full Text Search"の略)

ファイル名を見ながら思ったんだけど、拡張子が`.test`のファイルが異常に多い。
test ファイルが何者なのかよくわかっていないので、次回以降に調べます。
test ファイルさん、君のことはそのうち真面目に読みたくなるかもしれないけれど、当面は補助教材扱いにするね。（自由律俳句）

# 次回予告

やっと旅に出かける準備ができた。ハリボテでもいいのさ。仕事じゃないからね。
次回からソースコードを読んでいこうと思う。
Jenkinsでdockerコマンドが使用できるかを簡単に確認する方法

# はじめに
近年、JenkinsサーバにJDKなどのツールを導入してビルドするのではなく、Dockerコンテナを活用してビルド処理を実行するケースが多いと思います。ここでは、自分が使用しているJenkins環境でdockerコマンドを使用できるかを簡単に確認する方法をご紹介します。

# 前提環境
- マシン：MacBook Pro （14インチ, 2021）（M1 Max, メモリ64GBモデル）
- OS：macOS Monterey 12.0.1
- Jenkins 2.334（Homebrewで導入）

# 確認方法
Jenkinsのダッシュボードで「新規ジョブ作成」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/96dcb5a9-7533-93d7-c6bc-39d8a73376dc.png)

「フリースタイル・プロジェクトのビルド」を選択し、ジョブ名を適当に入力して「OK」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/b98c126f-b12a-f036-90d6-bf5d11579c5c.png)


ビルドの項の「ビルド手順の追加」→「シェルの実行」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/61dc1849-c327-a321-f14c-7a97c5c11934.png)

展開された「シェルスクリプト」欄に以下を入力し、画面下部の「保存」ボタンをクリックします。

```bash
docker run hello-world
```

作成したジョブのメニューの「ビルド実行」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/9e76c281-5055-770a-174e-74f8ecb22280.png)

実行されたジョブのログを確認し、``Hello from Docker!`` のメッセージが出力されていれば、dockerコマンドが正常に使用できています。
Matlab/Simulinkの備忘録

### タイトル
#### 新規モデルのテンプレート
[Simulinkを起動]-[新規]-[Simulink Real-Time]を選択
#### モデルの製作
[シミュレーション]-[ライブラリブラウザ]
#### モデル全体のインターバルトリガー
[REAL-TIMEタブ]-[ハードウェア設定]-[ソルバー]
タイプ「固定ステップ」、ソルバー「離散(連続状態なし)」、固定ステップサイズ「0.001」
#### IPアドレスの設定
HostLinkの設定はMATLABのコマンドウィンドウで以下を実行
HostPC「192.168.7.2」SpeedGoat/HostLink「192.168.7.5」がスタートアップガイドの記載
```
>> slrtExplorer
```
ETH1の設定はMATLABのコマンドウィンドウで以下を実行
```
>> sg_EthernetConfigurationTool
```
【パブリッシャー】2つのレポートを並列に配置してみる

この記事では、**[Sharperlight](https://sharperlight.jp/)パブリッシャー**で、2つのレポートを作成しブラウザに並列に配置してみます。
## レポートの作成
[Sharperlight](https://sharperlight.jp/)アップリケーションメニューからパブリッシャーを開きます。
![2022-03-08 Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/05c19efe-6802-aa12-b383-c8bdab3f8b18.png)
[パブリッシャー]ダイアログが開いたら、[新規]ボタンでレポートを作成します。[クエリを編集]ボタンでクエリの作成を行います。
このような2種類のレポートを作成しました。
ひとつは通常のテーブルを表示、もうひとつは折れ線グラフを表示します。
![2022-03-08 Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0b478f14-ba03-4c68-b406-0ecc1b6e50cb.png)
通常のテーブルを表示する方のレポート定義[オプション]タブで配置オプションを有効にします。
![2022-03-08 Figure 03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1b0c2fb0-b015-7a53-1f84-579617b90d96.png)
[編集]ボタンで編集用ダイアログを表示、[新規]アイコンで配置の作成を開始します。
![2022-03-08 Figure 04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a20448a5-ef6a-68f1-cbd8-19805e4c2e8f.png)
![2022-03-08 Figure 05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3bbf53c5-d357-2903-d7e0-a6988798da89.png)
もう一度、[新規]アイコンをクリックし、今度は作成済みの折れ線グラフを表示するレポートを設定します。
![2022-03-08 Figure 06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9b997587-e99c-f5fd-863a-8fc500b4f30b.png)
初期設定では、この２つのレポートは上下に表示されるので、[列]属性を２に設定して、更に[列をスパンします]属性を無効にします。
![2022-03-08 Figure 07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a1c8e144-a2e2-704d-6d37-ea7c26ee6247.png)
その他の属性はそのままにして、[OK]ボタンを押してこの配置を保存します。レポートも保存します。
 **Sharperlightサービス**を起動し、早速レポートを表示します。
![2022-03-08 Figure 08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/dbd7d47c-8b98-6cb5-668b-3e2f9a9263c7.png)
[配置]編集ダイアログのサイズ属性等を利用して、見映えをよくすることができます。
:postbox:[Sharperlight](https://sharperlight.jp/)
【GAS】設定ファイルをスプレッドシートにしている場合の速度改善

## はじめに
Google Apps Scriptを用いたサービスを作る場合、メンバーリスト等の設定ファイルはGoogle SpreadSheet上に記載し、そこから都度読み込むという作りになることが多いと思います。
とはいえSpreadSheetの読み込みはそこそこ時間を使うので、更新頻度が低いものは別の形で保存し、そこから早く読み出す形を考えます。

## スクリプトプロパティの場合
[Propertiesリファレンス](https://developers.google.com/apps-script/reference/properties/properties)
各種APIを利用する場合、トークンをスクリプトプロパティに保存するということが多いです。
スクリプトプロパティは永続的に保存される代わりに、読み込み回数と容量に制限があります。
[Quotas for Google Services ](https://developers.google.com/apps-script/guides/services/quotas)
上記を確認すると、読み出し制限は無料で50,000/日、Workspaceアカウントの場合は500,000/日となっています。
Workspaceアカウントの場合、社内向けのシステムなら気にするほどではないかと思いますが、容量上限においては1値あたり9KBとなっているため、データ量の多いものだと使い勝手に難が出ることがありそうです。

## スクリプトキャッシュの場合
[Cache Serviceリファレンス](https://developers.google.com/apps-script/reference/cache)
キャッシュを利用する場合、容量上限は100KBで読み込み回数制限はありません。ただキャッシュなので、最大6時間という保持制限があります。
とはいえ1回読み込めば6時間は速く読み込み可能なので、うまく使えばこちらが便利ということもありそうです。
場合によっては一定時間ごとのトリガーを仕込んでキャッシュを上書きしていくなどもいいかもしれません（試したことないですけど）。
今回はこちらのキャッシュを利用する方法をとることにしました。

## コード
キャッシュを利用する前に、SpreadSheetのオブジェクトも1回の処理内で使いまわしたいと思います。
重複で読み込んでもいいように、下記のようにスプレッドシートとワークシートを保存し、あればそちらを読み込むようにします。

```JavaScript
//======================================================================================================
// 毎回スプレッドシートを開かなくていいように使いまわす
//======================================================================================================
var _spreadSheetSettings = {};

function getSheet(ssId,wsName){

  if(ssId in _spreadSheetSettings){
    if(!(wsName in _spreadSheetSettings[ssId]["ws"])){
      _spreadSheetSettings[ssId]["ws"][wsName] = _spreadSheetSettings[ssId]["ss"].getSheetByName(wsName);      
    }
  }else{
    _spreadSheetSettings[ssId] = {"ss":SpreadsheetApp.openById(ssId),"ws":{}}
    _spreadSheetSettings[ssId]["ws"][wsName] = _spreadSheetSettings[ssId]["ss"].getSheetByName(wsName);
  }

  return _spreadSheetSettings[ssId]["ws"][wsName];
}
```
その上で、
* キャッシュがあればキャッシュから読み込み
* なければスプレッドシートから読み込み、キャッシュに保存

という形にしようと思います。以下です。
MEMBER_SHHET_IDとMEMBER_SHEET_NAMEにはそれぞれSpreadSheetのIDとシート名が入っています。
Cacheには文字列形式での保存になるので、JSON形式にして保存、読み出しを行うのが簡単です。
キャッシュはdevとデプロイ環境で共通なので、デプロイ環境でのキャッシュを壊さないように別名で管理するのがおすすめです。
今回は「指定文字列+バージョン番号(CACHE_VER)」で保存・呼び出しするようにしています。
デプロイ後、このCACHE_VERを別の番号にするとデータを壊さなくて済みます。
```JavaScript
var CACHE_VER = "20220314";

//======================================================================================================
// メンバーリストを取得
// データの更新頻度が低いので、Cacheを利用する
//======================================================================================================
function getMemberList(){

  var cache = CacheService.getScriptCache();
  var val = cache.get('member_' + CACHE_VER);
  if(val){
    var values = JSON.parse(val);
    return values;
  }else{
    var ws = getSheet(MEMBER_SHEET_ID,MEMBER_SHEET_NAME);
    var values = ws.getRange(1,1,ws.getLastRow(),ws.getLastColumn()).getValues();
    //キャッシュの保持は最大の6時間
    cache.put("member_" + CACHE_VER,JSON.stringify(values),21600);
    return values;
  }
}
```

スプレッドシートの読み込みは計測した結果データが少なくても0.5～1.0秒ほどかかるので、これで読み込み速度の改善が図れると思います。
【設計】Web３階層構造とは

> WebAPサーバー
Backends for Frontends(BFF)
データベース

で構築されるWebアプリケーションのこと



# なぜ興味持ったの？？
近年Web３階層構造が注目され主流になりつつあるためです。

従来のWebアプリケーションは
Webサーバーとデータベースの２つを用いた構造が主流でした。


# なぜWeb３階層構造が主流に？？？

増え続ける端末の全てに対応するようにバックエンドを変更していくのは限界があり,
特に複数のUIに対応するようすべてのAPIを変更するのは非効率的であったため、UI処理を専用で行うWebサーバを用いる構造に変化しました。
この時Webサーバはバックエンドとフロントエンドをつなぐという意味でBFF（Backends For Frontends）と呼ばれるようになります。



# メリット
## 処理の負荷分散が容易
処理の負荷分散は文字通り、従来の構造よりも細かくモジュールが分かれているためどれか一つのリソースに大きな負荷がかかるということが少なくなりました。また、もし仮に大きな負荷がかかる場所があるとしてその特定が簡単なため、リソース配分を考えるうえでも利点となります。
## 保守性が高い
各機能ごとにモジュール単位で稼働しているため障害が発生した場合の原因の特定が容易になる。

また、何か障害が発生した際にその部分を切り離すなどして全体の機能を止めずに機能や性能を落として運用を続けられます


## フロントエンドとバックエンドの実装を別々に行える
FEとBEはこのような構成だと明確に分かれます。

BFFとバックエンド間のAPIが定まれば
BFFをフロントエンドエンジニアが、バックエンドやデータベースをバックエンドエンジニアがと分担を明確にすることが可能となり、同時並行で互いの領分や仕事内容を邪魔することなく開発がすすめられます。

# デメリット

## 管理資産が増える
各機能ごとにサーバが必要なため管理資産が増えるというデメリットがあります。

しかし、クラウドやコンテナによる開発が主流となってきた今日これらのデメリットはなくなりつつあります。


# 注意点
## BFFとバックエンドの処理内容を明確にする
BFFとバックエンドが互いにどこまでの処理を行うか、どこまでの責任をどちらが持つかを明確にしておかないと、本来必要だった処理が双方から漏れてしまう可能性があります。

これを防ぐためにも設計段階からBFFとバックエンドのすり合わせを何度も行い、責任範囲を明確にしておく必要があります。

## BFFに機能を載せすぎない
BFFはバックエンドの処理の一部を移譲させる形でバックエンドの処理を減らしました。しかし、処理を移譲させすぎるとBFFの負荷が高まり結果として全体の性能が悪化することが考えられます。

BFFはあくまでUIのためのサーバであることを共通認識として持ち、BFFの処理が増えていると思った場合はバックエンドのAPIの仕様を見直すのも一つの手。
AWS Artifact、準拠法を日本法に変更ができない！2022-03-08

# 概要

検索するといくつか見つかる「AWSアカウントを作ったら最初やること！」のようなタイトルの記事を参考に作業中だった、2022/03/08。

概ね問題なく設定できたが、 `AWS Artifact` で準拠法を日本法に変更しようとしたところ、「契約」の一覧に表示されない!
変更できない、困った！

# 結論

「`AWS Artifact` で準拠法を日本法に変更」は不要になったっぽい

* https://aws.amazon.com/jp/agreement/
    * https://d1.awsstatic.com/legal/aws-customer-agreement/AWS_Customer_Agreement_Japanese_Translation.pdf

2022/03/08 にPDFから該当箇所をキャプチャ
![スクリーンショット 2022-03-08 11.17.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3800/6546f772-d7b4-f37b-f00b-921b6487da01.png)

「アマゾン ウェブ サービス ジャパン合同会社」との契約になったので不要になったっぽい。

# 参考

https://aws.amazon.com/jp/legal/awsjp/
enabledが効かないとき

# 状況
Unityでenabledをfalseにしても操作が出来てしまう
# 解決策
UnityのenabledでOnMouseDrag()のようなOn---な関数の呼び出しは止めることができません。
それら関数の中にif(this.enabled==false)return;を置いて対処しましょう。
Docker のコンテナが停止できなくなった場合

## 問題
docker-compose down などをしても以下のように正常に終了できない。
```
[+] Running 0/1
 ⠿ Container webdev-pgsql-1  Error while Stopping       879.0s
```

```
[+] Running 0/1
 ⠿ Container app-1  Error while Stopping                                                                     24.0s
Error response from daemon: cannot stop container: d76d6e2a5f8aed35a4462b11c591c210fe18dc11e38063305cbf636de85fa91e: tried to kill container, but did not receive an exit event
```

## 解決策
### mac の場合
Docker for Desktop をUIで再起動すれば良いはず。

それでも直らない事象にあったので、その場合は以下コマンドで直った。
```
killall Docker && open /Applications/Docker.app
```

その後各コンテナが削除できるはず。

https://forums.docker.com/t/restart-docker-from-command-line/9420/6

### liunx　の場合
```
sudo service docker restart
```

https://qiita.com/musatarosu/items/31d6293a93e75ca6073e#%E8%BF%BD%E8%A8%98
githubのデプロイキーの指定の仕方

# 失敗したやり方
同じサーバ内で複数のリポジトリを扱っていたので`~/.ssh/config`に以下のような設定を書いて
```shell:~/.ssh/config
Host repo-A
    HostName github.com
    User git
    IdentityFile ~/.ssh/repoAkey
Host repo-B
    HostName github.com
    User git
    IdentityFile ~/.ssh/repoBkey
```
gitリポジトリの`origin`をそれぞれ`repo-A:<github_user_name>/repoA.git`、`repo-B:<github_user_name>/repoB.git`としていた
これでうまくいっていたのだが、デプロイキーを入れ替えたら全く機能しなくなってしまってハマった
# 原因
原因は`config`の設定に`IdentityFile`を指定しても必ずしもそれが使われるわけではないことだった
sshは使える鍵をいろいろ試してみて適合したらログインするという方法をとっているがその試してみる順番が必ずしも`IdentityFile`が一番ではない（！）ので、repoAにアクセスしようとしているときにrepoBkeyを先に試されるとrepoBkeyを使ってgithub.comに接続してしまい（repoBkeyもgithubのリポジトリに登録されているのでgithub.comとのアクセスに使えてしまう!）repoAをいじる権限がないよ！と怒られてしまうのだ
指定した鍵より先にssh-agentに登録されている鍵が使われてしまうようだ
ssh-agentにどの鍵が登録されているかは`ssh-add -L`で確認できる
`ssh -T repo-A`してみると
```
Hi xxxxx/xxxxx! You've successfully authenticated, but GitHub does not provide shell access.
```
というメッセージが出るが、このxxxxの部分がrepoAならrepoAkeyが正しく使われていて、repoBならrepoBkeyが使われてしまっているということがわかる
# 対策
なので、正しくは
```shell:~/.ssh/config
Host repo-A
    HostName github.com
    User git
    IdentityFile ~/.ssh/repoAkey
    IdentitiesOnly yes
Host repo-B
    HostName github.com
    User git
    IdentityFile ~/.ssh/repoBkey
    IdentitiesOnly yes
```
と、`IdentitiesOnly`をつけてあげると良い
そうするとそこに指定された鍵しかトライしないので想定した動作が得られる

ただしこれはそのサーバに鍵が実在するときのパターンで、鍵をAgentForwardで持ってきてる場合は鍵を使う順番を明示的に指定する方法がない（？）ため、事前に`ssh-add`コマンドを使ってForwardする鍵を絞っておくくらいしか方法がなさそう
リポジトリごとのデプロイキーを使わないでユーザーに紐付けた鍵を使えばこのような問題は起きないのでAgentForwardで使うならそうした方がいいかもしれない
rbenv installコマンドが終わらな過ぎて困った話

# はじめに
１月〜プログラミングスクールで学習しています。
これから平日は~3/25まで毎日何かしらアウトプットのため投稿を続ける予定です。
今回はrbenv installコマンドを用いてRubyのバージョンを指定してインストールしようとした際に、コマンドが終わらなくて困った時のことを書きます。

# 経緯
オリジナルアプリをAWS上にアップするためにEC2（Linux）にSSH接続し、下記インストールコマンドを実行していました。
- rbenv install 2.6.5
ところが数分待っても動きが無く、control＋Cで抜けたところよく見るとインストールに少し時間がかかると書いてあったため、再度実行し少し待つことに。。。
そこから15分、２０分、、、３０分、、、待てども待てども終わりません。。。

```:ターミナル
[ec2-user@ip-172-31-1-171 ~]$ rbenv install 2.6.5
Downloading ruby-2.6.5.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.5.tar.bz2
Installing ruby-2.6.5...
```

しまいにはタイムアウトでssh切断されてるし:dizzy_face:
```
client_loop: send disconnect: Broken pipe
```

# 解決
ところが再度ssh接続し、確認してみると、なんだインストール出来てるじゃん:hatching_chick:
```:ターミナル
[ec2-user@ip-172-31-1-171 ~]$ rbenv versions
  2.6.5
```
その後、続けて下記コマンドを実行し、無事インストールが完了しました！
```:ターミナル
ec2-user@ip-172-31-1-171 ~]$ rbenv global 2.6.5
[ec2-user@ip-172-31-1-171 ~]$ 
[ec2-user@ip-172-31-1-171 ~]$ rbenv rehash
[ec2-user@ip-172-31-1-171 ~]$ 
[ec2-user@ip-172-31-1-171 ~]$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
```
謎の挙動でしたが、コマンド自体はちゃんと動いていたようで良かったです。
当たり前ですが確認コマンド大事ですよね。。。
ではまた~:rocket:
セキュリティの勉強

# セキュリティを学ぶ

悪いことされると困るから
アングラの勉強もしとかないとね。

# 匿名サーバーって借りられるの？

防弾ホスティングってなんぞ？

仮想通貨で支払いが可能。
防弾ホスティングは極めて高い匿名性を謳っており、仮に捜査機関からの協力要請があったとしても情報を開示したりサービスを停止したりすることはありません
「WikiLeaks」や人権保護団体のサイトなどは、権力者からの不正な圧力から守るために匿名性の高い防弾ホスティングが使用されている事例


オランダは著作権に関連する法律が他国に比べて緩いため、防弾ホスティングサーバーが数多く設置されています。世界の国の中でも通信回線が極めて高速で安定しており、コストパフォーマンスの高いサービスが提供できることから人気の高い国


# 匿名のメールアドレスってどうやって取るの？
ProtonMailを使うといい

https://note.com/orejanai/n/nc00f78af0b02


# 匿名の電話番号が欲しいんだけど
https://note.com/orejanai/n/n986be0912bbe
5sim.net
で買える。
vプリカを使うとよいみたい。
Rubyのevalを使ってみた

## 環境
Ruby 2.6.6

## 発端
開発中に既存コードでこのような感じのCASE文に出会った。

```ruby
＃　定数（商品タイプ）
FOOD = 'FOOD'
DRINK = 'DRINK'
OTHER = 'OTHER'

＃　定数（商品タイプラベル）
FOOD_LABEL = '食べ物'
DRINK_LABEL = '飲み物'
OTHER_LABEL = 'その他'

def get_label(shouhin_type)
	case shouhin_type
	when FOOD
	  FOOD_LABEL
	when DRINK
	  DRINK_LABEL
	when OTHER
	  OTHER_LABEL
	else
	  raise
	end
end
```

要はそれぞれの商品タイプに対応したラベルを取得するために、「商品タイプ名」＋「_LABEL」という名前の定数を返したいというメソッド。この状態だと、商品タイプが増えるたびにCASEの分岐をメンテしなければならないし、ただ「_LABEL」をつけるだけなのに何とも回りくどさを感じた。そこでRubyには動的にコードを生成して実行する機能があったなと思い検索。

[Ruby 3.1 リファレンスマニュアル module function Kernel.#eval](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/eval.html) を発見

## eval

```ruby
a = nil
b = "ああああ"
eval("a = '#{b}'")
# 実行される → a = ああああ
p a #=> "ああああ"
```

・引数で渡された文字列をRubyとして実行

・文字列なので変数展開できる

これを使えばできそうなので早速書き換えてみる。

```ruby
def hoge(shouhin_type)
	eval("label = #{shouhin_type}_LABEL")
  p label
end

hoge('FOOD')
```

```ruby
undefined local variable or method `label' for main:Object (NameError)
```

あれ、labelなんて変数名はない…？

どうやらeval内で定義した変数は、スコープの関係で外からは呼び出せないみたい。

```ruby
def hoge(shouhin_type)
	label = nil
	eval("label = #{shouhin_type}_LABEL")
	p label
end

hoge('FOOD')
#=> '食べ物'
```

修正して無事に動作するようになった。


## 結果
```ruby
# CASE文の場合
def get_label(shouhin_type)
	case shouhin_type
	when FOOD
	  FOOD_LABEL
	when DRINK
	  DRINK_LABEL
	when OTHER
	  OTHER_LABEL
	else
	  raise
	end
end

# evalの場合
def get_label(shouhin_type)
	label = nil
	eval("label = #{shouhin_type}_LABEL")
	label
end
```

結果、CASE文なら12＋α行だったところをevalを使うことで4行にでき、

今後、商品タイプが変更されてもメンテ不要にすることができた。
Amazon Connect 主要概念の関係性について

# はじめに

Amazon Connect は、AWSのアカウントとパソコンがあれば、コールセンターを開設できるAmazonのサービスです。
Amazon Connectは、設定を柔軟に組み合わせることで、色んなニーズに応えることができるようになっています。
主要な概念について、汎用性が高くて関係性を理解するのが難しかったので、それらについて簡単にまとめてみました。


# 電話番号、問い合わせフロー、キューの関係
![スクリーンショット 2022-03-08 10.18.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261675/cb94548f-a6c0-9aad-b69a-a87ce1a77f0f.png)

- １つの電話番号は１つの問い合わせフローに接続されます。
- 問い合わせフローは複数の電話番号から接続することができます。
- 複数の電話番号に掛かってきた処理を、全く同じ処理にすることもできます。
- 問い合わせフローの中で最終的にどのキューへ接続するかを指定することができます。

電話番号の管理画面の中に問い合わせフローの設定項目があります。


## 電話番号

Amazon Connect内で取得することができる050や0120などの電話番号。携帯電話や固定電話などから、この番号へ電話をかけることができます。

## 問い合わせフロー

掛かってきた電話をどのように処理するか、手順を記述する場所です。
掛かってきた電話は受電オペレータにつなぐ前に、この問い合わせフローを通ります。

この問い合わせフローの中で、IVR（Interactive Voice Response：自動音声応答システム）の選択肢を提示したり、選択された結果で処理を振り分けたりできます。

問い合わせフローは、最終的にかかってきた電話をキューへ渡す。あるいは通話を切断して終了することもできます。
問い合わせフローの例として、「商品について」の問い合わせフローと「採用応募」の問い合わせフローを分けることなどが考えられます。

## IVR

「○○に関するお問い合わせの場合は１番を押してください」といったアナウンスを流して、選択された内容によって処理を行う（電話オペレータへの振り分けたり）システムのこと。

## キュー

受電オペレータが掛かってきた電話に出るまでの間、電話を掛けてきた人が待たされるところです。電話を掛けた人は待ってる状態（音楽を流したりすることもできる）になります。

受電オペレータはあらかじめ決められたキューの電話にしか出ることはできません。

キューの例として、商品説明を希望している人のキューとか、解約を希望している人のキューといった設定が考えられます。


# ユーザー、ルーティングプロファイル、キューの関係

![スクリーンショット 2022-03-08 10.30.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261675/819e86df-a740-2ba4-85ef-b3cd2a38c870.png)

- ユーザーは１つのユーザープロファイルを指定することができる
- ルーティングプロファイルは複数のキューを処理対象とすることができる



## ユーザー

ユーザーの大半は受電オペレータですが、管理や分析を行うような人もユーザーです。
電話を掛けてくる顧客のことではありません。
ユーザーは、どのルーティングプロファイルに属するかを複数指定することができます。

## ルーティングプロファイル

どのキューに入ってきた電話を取り扱えるかを設定します。
ユーザーとキューを直接つなぐのではなく、ルーティングプロファイルが間に入ります。
１つのキューを指定できます。複数のキューも指定することができます。その場合、優先度を設定することが可能です。

例えば、ベテランスタッフ用ルーティングプロファイルや、商品知識が豊富なスタッフのルーティングプロファイル、新人スタッフ用のルーティングプロファイルなど用意することができるので、対応するキューやその優先度を管理することができるようになります。


# 全体的な関係

![スクリーンショット 2022-03-08 10.19.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261675/a8fd0826-32c2-82dd-d811-bcb4e1d17277.png)
Google Sheets APIで誰でも編集できるスプレッドシートを作成する（Node.js / TypeScript）

## 結論

Google Sheets API だけじゃなくて、Google Drive API も使う

```typescript
const sheets = google.sheets({ version: "v4", auth: oAuth2Client });
const drive = google.drive({ version: "v3", auth: oAuth2Client });

// スプレッドシートを作成する
const createdSheet = await sheets.spreadsheets.create();

// Google Drive APIでスプレッドシートの権限を作成する
await drive.permissions.create({
  fileId: createdSheet.data.spreadsheetId,
  requestBody: {
    type: "anyone",
    role: "writer",
  },
});

// 誰でも編集できるスプレッドシートのURL
console.log(createdSheet.data.spreadsheetUrl);
```

## 動くサンプル

`credential.json`と`token.json`はあらかじめ作成してある前提です。
トークンの生成がまだの方はこちらのドキュメントを参考に、クレデンシャルのダウンロードとトークンの生成を行ってください。
https://developers.google.com/sheets/api/quickstart/nodejs

```ts
import { promises as fs } from "fs";
import { google } from "googleapis";

(async () => {
  const credentials: GCPCredentials = await fs
    .readFile(`${__dirname}/../credentials.json`)
    .then((b) => b.toString())
    .then((s) => JSON.parse(s));

  const { client_id, client_secret, redirect_uris } = credentials.installed;

  const oAuth2Client = new google.auth.OAuth2(
    client_id,
    client_secret,
    redirect_uris[0]
  );

  const token = await fs
    .readFile(`${__dirname}/../token.json`)
    .then((b) => b.toString())
    .then((s) => JSON.parse(s));

  oAuth2Client.setCredentials(token);

  const sheets = google.sheets({ version: "v4", auth: oAuth2Client });
  const drive = google.drive({ version: "v3", auth: oAuth2Client });

  const createdSheet = await sheets.spreadsheets.create();

  await drive.permissions.create({
    fileId: createdSheet.data.spreadsheetId,
    requestBody: {
      type: "anyone",
      role: "writer",
    },
  });

  console.log(createdSheet.data.spreadsheetUrl);
})();

type GCPCredentials = {
  installed: {
    client_id: string;
    project_id: string;
    auth_uri: string;
    token_uri: string;
    auth_provider_x509_cert_url: string;
    client_secret: string;
    redirect_uris: string[];
  };
};

```
初心者ブロックチェーンに挑戦する　6

# いまだにGitHubは緊張する

 [UNCHAIN](https://unchain-portal.netlify.app/home)２日目。フロントエンドを構築する。初手は、サンプルコードをGitHubからもらってくることなのだが･･･・

　Flutter大学で共同開発を始めて半年だというのに、いまだにGItHubに苦手意識がある。その上今日はフォークだという。やったことありません。SSHだという。使ったことありません。イヤな予感だ。

　案の定、「わかってるはず」なガイドに従っていくと、「あなたにはアクセス権がない」と言われる。はあ・・・。Discordには各課題専門のチャンネルがあるので、そこを覗く。「できました〜」という景気のよいメッセージの間に、あったあった・・・「公開キーを自分でつくるんですねぇ。」という書き込み。ありがとうございます。あとはググる。

 よさげな記事を見つける。keyをつくる。でも最後の、「keyをコピー」ができない。
- 記事どおりのviコマンドで開いてくれない。（なぜかは知らない）
- finderから強引にvisual studioで開けると、見えるは見えるが、コピーできない（説明するのも面倒くさい理由で）
- finderからtextで開くと、記事に似た状態で表示されたので、一応それをコピーして続きに進む。

　新しい鍵を設定。
　クローンをつくる・・・

　だめじゃん。つくづく相性が悪い。「朝飯前」のつもりが10時になってしまった。朝ご飯食べよう。







https://qiita.com/tnatsume00/items/e147662368d02e6416d2
Oracle Analytics Cloud：列の追加提案をカスタマイズできるので、ますますデータセットが充実化していく話

# はじめに
Oracle Analytics Cloud（**OAC**）では、データセットを充実化する機能（エンリッチといいます）があります。

参考：[Oracle Analytics Cloud：データの内容に応じて列の追加を提案してくれるので、データセットが充実化していく話]()

この機能はサービスに組み込まれていますが、ユーザがカスタマイズすることもできます。
どのデータに対してどのようなエンリッチを提案するかをExcelファイルとして作成し、事前に登録しておきます。

# カスタムナレッジを準備する
今回は、都道府県に関するデータをロードする際に分析データを拡張するカスタムナレッジを作成しました。
カスタムナレッジはExcelで作成して、xlsxファイルとして保存します。
この例では、A列には都道府県名が入っています。
OACのデータセットに都道府県名が含まれている場合に、B列からE列のデータをエンリッチとして提案します。
A列のヘッダ名と実際のデータセットの列名は同一である必要はありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/deedd93b-8d5a-8c4b-aab0-84255175a21f.png)

OACに管理者としてログインします。
ナビゲーションメニューの「コンソール」をクリックし、「参照ナレッジ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/d4b8aa41-f3e3-0ac8-5ee5-2d0401298e3a.png)

作成しておいたExcelファイルを「カスタム・ナレッジの追加」にドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/0a869c13-9fa9-40f4-cb08-ca2c57f7edf9.png)

内容を確認して「OK」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/a720cff6-f08f-b2aa-2b14-ec4d1825e5a6.png)

# カスタムナレッジを試す
「作成」から「データセット」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/78da5be6-52a8-354e-3452-c7177c9a3d7d.png)

「居住地」という列に都道府県名が格納されているCSVファイルをアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/0050eb84-d772-85b6-26a7-8b599ebc4dca.png)

「居住地」列を選択すると、OACがカスタムナレッジに基づいてデータのエンリッチ（充実化）を提案してきました。
「地方」「緯度」「経度」の提案を受け入れることにします（クリックします）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/41be0f10-3015-106a-bf4b-509ec2759a2d.png)

データセットが拡張されました。
「適用スクリプト」ボタンをクリックして確定させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/313c36f9-239a-582f-ab48-d68f41dbd63c.png)

ワークブックを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/468e9a9a-e508-ab67-076c-73b50e3c6b69.png)

拡張した列を使って、ビジュアライゼーションを作成してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/7184d6e0-b5b8-3b85-f354-821312d4ac80.png)
salesforceのFlowBuilderでレコードIDを取得する方法

# やりたいこと

salesforceのフローを使って、プロセスを開始した時に表示しているレコードのレコードIDを取得してきたい。イメージとしてはURLが
```
https://hogehoge.lightning.force.com/lightning/r/Quote/xxxxxxxxxxxxxxxxxx/view
```
だった時の「xxxxxxxxxxxxxxxxxx」←ここを取ってきたい。

# やり方

[公式のヘルプ](https://help.salesforce.com/s/articleView?id=sf.flow_actions_considerations.htm&language=ja&r=https%3A%2F%2Fwww.google.com%2F&type=5)によると
>フローアクションでは、レコードの ID 項目の値をフローに渡すことができますが、それだけです。フローに recordId というテキスト入力変数があれば、アクションの実行時にレコードの ID がその変数に渡されます。ない場合は、レコード ID は渡されず、フローはそのまま実行されます。

とのこと。わかりにくい。が、なんかできそうってことはわかった。
やってみる。

1. FlowBuilderから新規フローの作成をクリック
1. 「新規リソース」をクリックしてレコードIDを入れるリソースを作っていく
    * リソース種別：変数
    * API参照名：recordId
    * データ型：テキスト
    * 複数の値を許可：チェックなし
    * デフォルト値：なし
    * フロー外部での可用性：「入力で使用可能」にチェック
1. これでreocrdIdという変数に取得したいIDが入ってくるのでこれを使ってレコードを取得する。例えばこんな感じ![スクリーンショット 2022-03-08 9.46.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/d71d83fc-221d-9b61-76a1-3a98ae239eaa.png)


うーん。
ヘルプに書いてある通りって言えばそうなんだけどわからんよな〜。というメモ。
sinatra で json を読み込んだ場合のエラー回避

# はじめに
`sinatra`で`json`を読み込んだ際、`undefined method bytesize`が発生しました。

sinatra undefined method bytesize で検索すると、sinatra と json の相性が悪いらしいのですが、`Hash -> json` の話が多いようです。

この記事は、`json -> Hash` 時のエラー回避策です。
# 状況
```ruby:error.rb
require 'net/http'
require 'uri'
require 'json'

def read_uri(url)
  uri = URI.parse(url)
  res = Net::HTTP.get(uri)
    
  json_data = JSON.parse(res)
```
最後の行で`undefined method bytesize`が発生。
# 対策
```diff_ruby:success.rb
def read_uri(url)
  uri = URI.parse(url)
  res = Net::HTTP.get(uri)
    
-  json_data = JSON.parse(res)
+  json_data = JSON.parse(res.chomp)
```
とりあえず、改行コードを削除するといい様です。
# 参照したサイト
https://www.meganii.com/blog/2011/12/15/1323900923/

https://stackoverflow.com/questions/1117272/error-happens-when-i-try-all-method-in-datamapper

https://teratail.com/questions/89476
VXLAN とは

## 勉強前イメージ

バーチャルなんとかLANだと思う！

## 調査

### VXLAN とは

Virtual eXtensible Local Area Network の略で、
簡単にいうとネットワーク越しにLANを実現するための技術で物理的に離れているLAN同士をくっつけることができます。
もう少し難しくすると、オーバーレイネットワークを使ってL3ネットワーク上にL2ネットワークを構築するトンネリングプロトコルのことで、
L2ネットワークを他のL2ネットワークとつなぐために、VXLANセグメントと呼ばれるネットワークをトンネリング技術を利用してIPネットワークにオーバレイすることで実現します。

### なんでVXLANが使われる？

サーバの仮想化が増加したことで、仮想ネットワークの需要も増えていきました。
物理ネットワーク上にオーバレイネットワークを構築することで仮想ネットワークを使用できるようになりました。

また、VXLANは拡張性もあります。
論理的にはVLANは4094個しか作れず、大規模ネットワークでは不足することがありました。
ですが、VXLANは1600万個作成でき、それによってクラウドベンダーがデータセンター間でリソースを割り当て
サーバ間の仮想マシンを移動することが可能になりました。

### 用語

ここでよく言われる用語をまとめてみました。

- オーバーレイネットワーク

物理的なネットワークの上に構築された仮想的なネットワークを指します。

- アンダーレイネットワーク

VXLANによって構築された、仮想ネットワークを指します。

- VTEP

Virtual Tunnel EndPointの略で、VXLAN構築するスイッチのことを指します。
仮想ネットワークをつなぐものとしてTunnelのEndPointです。

- VNI

VNIDとも呼ばれますが、Vxlan Network Identifierの略で、
VXLAN Network IDになります。
これで1600万を超える仮想ネットワークを構成することができます。

### 実際どうやって実現しているのか

Data Planeという技術を使っており、
片方から送信されるパケットをVXLAN構築するスイッチでカプセル化され、VXLANヘッダーを付与して相手のVXLAN構築するスイッチへ送信されます。
受け取ったスイッチはVXLANヘッダーを外し、受け取ったデータのカプセル化を解除して配下の端末へ送信されます。

送信されるデータの送信先はどの物理スイッチに接続されているかはControl Planeという技術を使って知ることができます。
VXLANに所属している端末の情報をBGPで交換することで、どの物理スイッチに接続されているかわかることができます。

## 勉強後イメージ

こういうのあるって初めて知ったよー
大規模ネットワークが必要な場所以外はあまりいらないかもだけど、これでDC間のネットワークを作ることができるのね。


## 参考

- [VXLAN について簡単にまとめてみる](https://nozawana44.hatenablog.com/entry/2019/01/07/205315)
- [VXLANとは](https://www.juniper.net/jp/ja/research-topics/what-is-vxlan.html)
- [VXLANとは](https://www.nic.ad.jp/ja/basics/terms/vxlan.html)
AWSドキュメント   CodeDeploy とElastic Load Balancing

AWS CodeDeployのユーザーガイドのCodeDeploy とElastic Load Balancingに関して記載
https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/integrations-aws-elastic-load-balancing.html

Blue/Green デプロイ
→ 古い方（blue）のインスタンスへのトラフィックはブロックされ新しい方（green）の方は許可される 
→ 切り替える際にロードバランサーが 新しい方（green）を登録して（先）、古い方（blue）のインスタンス登録解除する（後）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/e06551de-4b3f-beeb-c5fa-dfebc4be4fc0.png) 

インプレースデプロイ
→ インスタンスを登録解除してデプロイが完了したらインスタンスを再登録する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/b0bbaabf-ad6c-fdf2-f5ee-c99c3c15adbb.png)

Blue/Green デプロイ
Elastic Load Balancing ロードバランサーの背後でインスタンストラフィックを再ルーティングすることは CodeDeploy Blue/Green デプロイの基本です。

※以下、原文と参考
Blue/Green デプロイの場合、ロードバランサーは、最新のアプリケーションリビジョンのデプロイ先であるデプロイグループの新しいインスタンス (置き換え先環境) に対しては、指定したルールに基づくトラフィックのルーティングを許可し、前回のアプリケーションリビジョンの実行元である古いインスタンス (元の環境) からはトラフィックをブロックします。

置き換え先環境のインスタンスがロードバランサーに登録されると、置き換え元環境のインスタンスは登録解除され、終了可能になります。

青/緑のデプロイでは、デプロイグループでClassic Load Balancer、Application Load Balancer、またはNetwork Load Balancer を指定できます。CodeDeploy コンソールまたはAWS CLIをクリックして、ロードバランサーをデプロイグループに追加します。


インプレースデプロイ
インプレースデプロイ中は、ロードバランサーにより、デプロイ先のインスタンスに対するインターネットトラフィックのルーティングがブロックされ、そのインスタンスへのデプロイが完了した時点でインスタンスに対するトラフィックのルーティングが再開されます。

インプレースデプロイ中にロードバランサーが使用されないと、インターネットトラフィックはデプロイプロセス中に依然としてインスタンスにルーティングされる場合があります。その結果、お客様に表示されるウェブアプリケーションが破損していたり、不完全であったり、古いものであったりする可能性があります。インプレースデプロイで Elastic Load Balancing ロードバランサーを使用する場合、デプロイグループのインスタンスはロードバランサーから登録解除され、最新のアプリケーションリビジョンに更新されてから、デプロイ後に同じデプロイグループの一部としてロードバランサーに再登録されます。成功しました。CodeDeploy は、ロードバランサーの背後でインスタンスが正常になるまで最大 1 時間待機します。待機期間中にロードバランサーによってインスタンスが正常とマークされていない場合、CodeDeploy はデプロイ設定に基づいて、次のインスタンスに移動するか、デプロイに失敗します。

インプレースデプロイの場合、Classic Load Balancer、Application Load Balancer、または Network Load Balancer を指定できます。ロードバランサーをデプロイグループの設定の一部として指定できます。または CodeDeploy が提供するスクリプトを使用してロードバランサーを実装します。

参考

https://garafu.blogspot.com/2018/11/release-strategy.html
Rustで競プロやったときのTips

こんにちは。PythonParrotです。
今回はRustで競技プログラミングをやったときにやっておくと良さそうなこととか、覚えておいたほうが良いことを話していきます。

# AtcoderのRustのバージョンは1.42.0
Rustの2022/3/8時点での最新リリースは1.59.0。それに対してAtcoderのRustのバージョンは1.42.0。
そのため、1.42.0以降で実装された機能とかを手元でうっかり使ってしまってCEになるということが稀に良くある。

解決策としては以下の通り。
 - 手元でも1.42.0を使う
 - Editionを2018にしておく

Editionについては以下参照。

https://doc.rust-lang.org/stable/edition-guide/editions/creating-a-new-project.html


手元で指定したバージョンのRustを入れる話は以下を参照

https://qiita.com/tatsuya6502/items/8b31e2b162aff78787fe

後で紹介するCargo Atcoderを使うとそれがやりやすいのでオススメ。




# Cargo Atcoder
Atcoderに向けたCargo subcommand。
コマンドで「プロジェクトの作成」や「提出」ができるようになる。

https://github.com/tanakh/cargo-atcoder
## 設定
インストール方法や使い方などはReadmeに譲るとして、ここでは自分の設定を晒していく。

```toml
# 変更点だけ。
# dependencies added to new project
[dependencies]
# proconioを依存関係として追加しておく
proconio = "*"
# competitive = { git = "https://github.com/tanakh/competitive-rs.git" }

[project]
# to create `rust-toolchain` file, uncomment this line.
# AtcoderのRustのバージョンが1.42.0なのでそれに合わせる形に。
rustc_version = "1.42.0"

# source code template
# ソースコードテンプレートをinputの用意がすでにできている状態に置き換えておく
template = """
use proconio::input;
fn main() {
    input!{
    };
}
"""
```



ちなみに、設定ファイルは以下のディレクトリ以下の`cargo-atcoder.toml`ファイルである。


https://docs.rs/dirs/1.0.4/dirs/fn.config_dir.html

# proconio
競技プログラミングのための入力用クレート。
`input!`マクロを使うことで入力部分を楽に書ける。

https://docs.rs/proconio/latest/proconio/

# std::collectionsの把握
C++ほどとは言えないが、一通り揃ってる。


https://doc.rust-lang.org/std/collections/index.html

https://qiita.com/garkimasera/items/a6df4d1cd99bc5010a5e

## BTreeSet を MultiSet にするテク
知り合いから教えてもらったテクで、(要素, setのサイズとか適当な値)とかにする。
こんな感じ。

https://atcoder.jp/contests/abc241/submissions/29717299
StackSetsの実行権限（セルフマネージド） 

スタックセットを展開する上で管理ロールと実行ロールというものがあります
自動で作成されるとブラックベルトの実行権限（マネージド）のページに書いてあったがどっちが自動で作成されてどっちが自動で作成されないのか気になったので確認してみた

# まとめ
・マネージドロール（管理ロール）はスタック作成元で作られる（AssumeRole付いてる方）
・実行ロールはスタック展開先に作られる（AdministratorAccess付いてる方）
・（未検証）Organizationを利用したマネージドでスタックセット作成した場合は上の２つがどちらも作られる

# 知識補足

マネージド（今回しない方）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/d844c093-d054-d3bb-abaa-553698d230b7.png)

※画像内のリンク：https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacksets-orgs-enable-trusted-access.html

セルフマネージド（今回はこっち）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/8bb13963-2d84-c48e-5e01-70441a6fcf75.png)

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html

# 設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/f64b1f92-5ae8-9f9e-8d8f-9e719bfe0538.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/7e8f0676-7f04-225e-77d8-642146714610.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/f86549b3-261f-03df-d1ec-933ee1a29db5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/35350688-592a-6ac8-8dc6-be711d267938.png)

# 作成後に確認できたロール情報
管理ロール
AWS-QuickSetup-StackSet-Local-AdministrationRole
AWS のサービス: cloudformation
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/ef75c60c-f689-0f1e-9f54-e91357391bb5.png)

実行ロール
AWS-QuickSetup-StackSet-Local-ExecutionRole
アカウント: スタックセット作成元のアカウントID	
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/45c78d08-43c0-7a95-327d-3abd112eb78e.png)



参考：
https://d1.awsstatic.com/webinars/jp/pdf/services/20201006_BlackBelt_CloudFormation_DeepDive.pdf

https://dev.classmethod.jp/articles/cfn_organization_auto_deploy/
https://zenn.dev/mn87/articles/479df996045a8d
さくらサーバーのバックアップ&ステージングでもPHP includeを使えるようにする

さくらサーバーでステージング環境を作るためには、「バックアップ&ステージング」というメニューから作成できます。
このメニューの中にある「SnapUp」というサービスを使うと、本番サーバーの状態をそのままステージングにコピーすることができます。

SnapUpはホームページを丸ごとコピーできるサービスのようで、ロリポップでも使われているようです。
https://snapup.jp/

使い方等はこちらを参照してください。
https://webst8.com/blog/sakura-staging/

本番にあるWordpressなどをそのままの状態でコピーできるのは便利かもしれません。
私がハマったのは、Phpのインクルードを使用しているHTMLの状態をこのSnapUpで作成したステージング環境で利用したいと思ったのですが、Phpが動かず、「500 Internal Server Error」になってしまいました。

「.htaccess」の記述がまずいというのはなんとなくわかったのですが、どのように記述すればよいのかわからなった状態です。またステージングを利用する事もあるので、メモを残しておこうと思います。

##本番での記述
本番は次のように「php.cgi」を参照させる形で記載しました。
これをこのままステージングに持っていくことができませんでした。

````.htaccess
Action myphp-script /php.cgi
AddHandler myphp-script .php .html
````

##ステージング(SnapUp)での記述

````.htaccess
AddType application/x-httpd-php .php .html
````
こちらのページが参考になります。
https://oxynotes.com/?p=11278

ローカルでもこの記述でphpインクルードが使えるようになります。
AWS CodePipelineではまったこと

## ことの発端
CodePipelineを使ってCI/CDの仕組みを新しく作っていた時にアーティファクトファイルのパスを記載しているにも関わらずパイプライン側でアーティファクトファイルが見つからないと言われた。

- エラー内容

```
File [XXXXXX.json] does not exist in artifact [XXXXXX]
```

## はまった点
アーティファクトファイルはzip前提なのでzipファイル名をアーティファクトのファイルパスとして含む必要があった。当初再帰的に検索してくれるものだと思ったが違った。展開前提という事ですね。

- アーティファクト名/zipファイルのファイル名(.zip)を抜いたもの/対象ファイル

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/welcome-introducing-artifacts.html

## 参考
https://stackoverflow.com/questions/54524234/file-imagedefinitions-json-does-not-exist-in-artifact-testart-aws-codepipe
gitで社内サーバのリポジトリをクローンする手順

#社内サーバにあるrepo.gitをクローンする手順

Win + R →　CMD
↓
コマンドプロンプト上で、クローン先ローカルディレクトリに移動
または、クローン先ディレクトリをエクスプローラで開いて右クリック→Git Bash Here
↓
git clone [サーバ上の共有リポジトリのファイルパス]


##具体例
###CMDの場合(バックスラッシュ＝円マークが使えるので、エクスプローラ上でリモートリポジトリをShift＋右クリックし「パスをコピー」して
それをコマンドプロンプト上にペーストするだけ。)
```
git clone "\\fs\sub-business\products\apps\repo.git"
```

###Git Bashの場合(バックスラッシュではなくフォワードスラッシュを使う)
```
git clone "//fs/sub-business/products/apps/repo.git"
```
「誰のためのデザイン？」を読んだので、その記録

[誰のためのデザイン？　増補・改訂版　―認知科学者のデザイン原論 | D. A. ノーマン, 岡本明, 安村通晃, 伊賀聡一郎, 野島久雄 |本 | 通販 | Amazon](https://www.amazon.co.jp/dp/4788514346)

<img src="https://images-na.ssl-images-amazon.com/images/I/51uEWA1B3EL._SX340_BO1,204,203,200_.jpg" width=30% />

> 製品デザインの世界に衝撃を与え,大ロングセラーとなった初版から25年。デザインの原則は同じでも,文化は変わり,テクノロジーも大きく進化した。その間の学びと経験を加え,事例も一新,記述もさらにわかりやすく,全面改訂したノーマンの集大成!

という本。UXライティングについて調べる中で出てきた。古典のようで図書館でもすぐ借りられる。借りてみた。


## 要点 (興味深かったところ)

- シグニファイア
    - 例: https://www.pref.yamanashi.jp/yitc/design/jouhou/documents/vol_11.pdf
        - 例えば、何も付いていない板だけのドアがあった場合、人はドアを開けることができれば中に入ることが可能だと知覚できるが、どのようにしてドアを開ければいいのかを瞬時に判断できない。
        - しかし、ドアに平らな板が貼ってあれば押すことによって、ノブが付いていればノブを回して押すか引くかすることによって、ドアを開けることができると知覚しやすくなる。
        - ドアに分かりやすい特徴を持たせることによって、説明なしで誰でも使えるようになる。
- 電池の挿入方向を自由にする
    - どちらの向きで入れても構わない電池
- スリップとミステーク
    - スリップ
        - 意図せず失敗してしまう
    - ミステーク 
        - 誤解の結果失敗してしまう
    - 例: https://flowthink.jp/thinking/3-errors/
 
## 参考記事

ベストセラーとして多数記事あり。

[8000字&図解で要約『誰のためのデザイン？』D.A.ノーマン　デザインをするなら知っておくべき「人間中心デザイン」の提唱 - maglog](https://maglog.tokyo/the-design-of-everyday-things-jp-summeary/)
[「誰のためのデザイン？増補・改訂版」を読んだ｜Saori Takehara｜note](https://note.com/tkhrsor/n/n9cd104cbf66d)
[誰のためのデザイン？ を今更ながら読んでみた - 意識低い系（仮）](https://tadasix1982.hatenablog.com/entry/2016/03/05/222726)

> 行為の7段階理論 実行＝プランニング、解釈、実行 評価＝知覚、解釈、実行 ゴール
> 【例】

> - ゴールの形成（何をどうしたいか） 　＝寒くなってきたから身体を暖めたい
> - 行為のプラン（ゴールのためにどんな方法があるか） 　＝暖房付ける？毛布をかける？厚着をする？温かいスープを飲む？
> - 詳細化（2から選出したプランをどう実行するか） 　＝暖房をつけよう、自分で付けに行くか？誰かに頼む？リモコンで操作する？直接スイッチを押しに行く？
> - 行為系列の実行（3で決めたことを実行） 　＝リモコンでスイッチを入れてみよう！
> - 外界の状態の知覚（4を実行した結果どうなったか） 　＝暖かくなった！
> - 知覚したものの解釈（5の結果について考える） 　＝電源が正常に入って、温度設定が快適だったので部屋が暖かくなり身体が暖まった！
> - ゴールと結果の比較（やりたいことと結果に違いはないか） 　＝やりたいことができた！

> 1. 何を達成したいか？
> 2. 代替となる行為系列は何か？
> 3. 今どの行為ができるのか？
> 4. それをどうやっているのか？
> 5. 何が起こったのか？
> 6. それは何を意味するのか？
> 7. それで良いか？私はゴールを達成したのか？

[「誰のためのデザイン？」を読み終えた - はうすてんぼぶ](https://bob-mk2.hateblo.jp/entry/2014/03/18/003247)

## 思い出した例

https://nlab.itmedia.co.jp/nl/articles/1712/09/news028.html

https://togetter.com/li/1855155


なるほど「誰のためのデザイン？」という問いかけの答えがそのままテーマだよなという感想。利用者目線とは簡単に言うものの自分も視点を行き来しながらモノを設計していきたいものだと考えた。
以上読書記録です～。
2022/3/8主にITとかセキュリティの記事

Emotetの進化を受けて「EmoCheck v2.1」を公開 - 念のため最新版でチェックを
https://www.security-next.com/134659

「Firefox」が緊急アップデート - 複数のゼロデイ脆弱性を修正
https://www.security-next.com/134644

ふるさと納税支援サイトにPWリスト攻撃 - 2000以上のIPアドレスから
https://www.security-next.com/134615

勢い続くフィッシング攻撃 - ユニークURL、1日平均約270件
https://www.security-next.com/134607

「Emotet」感染で従業員を装ったメール送信 - マクロミル
https://www.security-next.com/134642

「えきねっと」のフィッシング、正規「自動退会処理」を偽装
https://www.security-next.com/134662

フィルタリング製品「i-FILTER」に脆弱性 - 更新して設定変更を
https://www.security-next.com/134665

サイバー攻撃に悪用される既知の脆弱性95個とは？　CISAが新たにカタログに追加(3/5)
https://www.itmedia.co.jp/enterprise/spv/2203/05/news033.html

偽メール、県内企業も標的　知人、取引先装いウイルス添付　県警「心当たりなければ確認を」(3/6)
https://nordot.app/873037951209226240?c=351539295472960609

【3月4日】掲載記事アクセスランキング・トップ5―1位はContiの内部チャットログ流出、2位はNVIDIA機密データ流出
https://jp.techcrunch.com/2022/03/04/techcrunch-article-ranking-2022-03-04/

FCA金融行動監視機構、50の仮想通貨会社への調査を進行中(3/4)
https://nextmoney.jp/?p=48562

はじめてのGoogle広告。初心者が最低限押さえるべきポイントを解説(3/4)
https://ferret-plus.com/58868

Windowsでキートップにないさまざまな文字を入力する方法を整理する(3/6)
https://gunosy.com/articles/eqXnZ

時代遅れの専門用語は、暗号資産の発展を妨げる【オピニオン】(3/6)
https://m.finance.yahoo.co.jp/news/detail/20220306-00161810-coindesk-bus_all

NVIDIA社員のパスワード数千件がネットに流出、ハッカー集団から奇妙な要求(3/6)
https://jp.techcrunch.com/2022/03/06/2022-03-04-nvidia-ransomware-hackers-demands/

アクセス解析とは？押さえておきたい基礎知識やおすすめツールを紹介(3/4)
https://ferret-plus.com/59376

ウクライナ、IT70社に協力要請　ロシア対抗へ担当副大臣(3/6)
https://www.nikkei.com/article/DGXZQOGN0602J0W2A300C2000000/

マネーロンダリング対策 国際機関が中東UAEの監視強化へ(3/5)
https://www3.nhk.or.jp/news/html/20220305/k10013516441000.html?utm_int=news-international_contents_list-items_019

2月デスクトップブラウザシェア、Chrome急増とEdge減少の日本(3/5)
https://news.infoseek.co.jp/article/mynavi_2376571/?tpgnr=it

Zoom・Slack・LINEなど種類豊富なWeb会議、SNS系なら時間無制限で使いやすい(3/7)
https://xtech.nikkei.com/atcl/nxt/column/18/01974/030300001/

M＆A後も油断は禁物、親会社システムを安易にコピーすればコスト高止まりの恐れ(3/7)
https://xtech.nikkei.com/atcl/nxt/column/18/01926/022700005/
Googleスプレッドシートでカタカナ→ローマ字に変換する数式（GAS不要・標準数式のみ）

# 結論
下記のスプレッドシートの「katakana2romaji」をご自身のシートにコピーして使ってください。
https://docs.google.com/spreadsheets/d/1yRK8a640VTDl-Jq2NVVcqcSKRVdzXmga9VlX7vyYGJM/edit?usp=sharing

### 使用方法
上記シートをコピーした後、
カタカナからローマ字変換を表示したいセルに下記の関数を入力してください。
※「A1」をカタカナが書いてあるセルを参照するように書き換えてください
```katakana2romaji.js
=regexreplace(join("",arrayformula(vlookup(split(regexreplace(regexreplace(regexreplace(regexreplace(A1,"\s", " "),"ー",""),"","+"),"\+(ァ|ィ|ゥ|ェ|ォ|ャ|ュ|ョ)", "$1"),"+",true,true),katakana2romaji!$A$7:$B,2,false))),"ッ([a-z])","$1$1")
```

# 解説　どのような手順で変換しているのか
「サッターフォ　リョウスケ」を例として説明します。

**①全ての空白を半角スペースに変換**
`=regexreplace(A1,"\s", " ")`
出力：サッターフォ リョウスケ

**②伸ばし棒（ー）を無くす**
`=regexreplace(①,"ー","")`
出力：サッタフォ リョウスケ

**③全ての文字の間に「+」を入れる**
`=regexreplace(②,"","+")`
出力：+サ+ッ+タ+フ+ォ+　+リ+ョ+ウ+ス+ケ+

**④+の後が ァ|ィ|ゥ|ェ|ォ|ャ|ュ|ョ のどれかなら+を取り一つ前の文字とセットにする**
`=regexreplace(③,"\+(ァ|ィ|ゥ|ェ|ォ|ャ|ュ|ョ)", "$1")`
出力：+サ+ッ+タ+フォ+　+リョ+ウ+ス+ケ+

**⑤+で分割**
`=split(④,"+",true,true)`
出力：[,サ,ッ,タ,フォ,　,リョ,ウ,ス,ケ,]

**⑥一文字ずつvlookupで表から探す**
※配列を一文字ずつ扱うためにarrayformulaで括っています。
※「ッ」のみ最後に変換を行うので「ッ」のままにしています。
※半角スペースも表の中にいれてエラーが出ないようにしています。
`=arrayformula(vlookup(⑤（一文字）,katakana2romaji!$A$7:$B,2,false))`
出力：[,sa,ッ,ta,fo,　,ryo,u,su,ke,]

**⑦結合する**
`=join("",⑥)`
出力：saッtafo ryousuke

**⑧「ッ」を一文字後ろのアルファベットに置き換える**
`=regexreplace(⑦,"ッ([a-z])","$1$1")`
出力：sattafo ryousuke

## 補足
・ひらがなも表に加えればひらがなも変換対応可能
・もう少しカスタマイズすればカタカナ3文字の特殊パターンを変換することもできる（「リョウ」を「ryo」など）
Webサイトへのアクセスを制限する方法

Webサイトをアクセスする人を制限する場合、いくつかの方法がある。
## ①Webサイトにたどり着きづらくする
Webサイトへのアクセスは、以下によって行われる。
* 他サイトからのリンク（検索エンジン含む）
* URLの直接入力

GoogleやYahoo!などの検索エンジンからのアクセスを防ぐためには、robot.txt（検索エンジンのロボット（クローラー）に対し、指示するテキスト。）などをドキュメントルートに設定して、検索エンジンに拾われないようにする方法がある。
ただし、この方法ではURLがバレたらアクセスできてしまいます。

もっと有効な方法としてはApacheの設定（Requireの設定）もしくは、ファイアウォールの設定などで、特定のIPアドレスからしか操作できないように制限することが考えられる。

社内サーバーなどでクライアントのIPアドレスを**固定できる**場合によく使われる。
## ②Webサイト内部に入れないようにする
会員制のWebサイトなど、接続元のIPアドレスが固定できない場合は、ユーザー認証が使われるのが一般的。

JavaScriptやPerl・PHPなどを使って、プログラムでログインの仕組みを作ったり、Apacheの機能を利用したBasic認証やDigest認証でユーザー名やパスワードを確認したりする。※Webサービスの場合は、Basic認証をあまり用いない。

### Basic認証とDigest認証の仕組み
Apacheでは、「.htaccess」を使ったBasic認証とDigest認証に対応している。どちらもサーバー側にユーザー名とパスワードのファイルを置いて、それを認証に利用する仕組み。

Basic認証は、それだけだと平文で通信されるため、**盗聴されてしまうと、パスワードが漏れることがある**。そのため、SSLでの暗号化とセットであることが多い。

一方、Digest認証はチャレンジ＆レスポンスという方式を使用しており、パスワードを直接通信網に流すことなく、１回限り有効な計算値をもって認証する。ただし、一部ブラウザやレンタルサーバーで対応していないケースもある。

Basic認証とDigest認証ともに、ユーザー名とパスワードを問う「.htaccess」ファイルと、正しいユーザー名とパスワードを記載したパスワードファイルを使用して認証を行う。パスワードファイルはBasic認証の場合は「.htpasswd」、Digest認証の場合は「.htdigest」。
### ApacheでBasic認証やDigest認証を設定する
デフォルトでは「.htaccess」は有効になっていないので、Basicn認証やDigest認証を有効にするには、「.htaccess」を有効にする必要がある。
これらは、Apacheの設定ファイル(etc/httpd/conf/httpd.conf）で変更する。設定ファイルの`<Directory "var/www/html">`以下に「AllowOverride None」となっている箇所を書き換える。

この「None」を「All」に書き直して保存すると、「.htaccess」が使えるようになる。変更を保存後、`systemctl reload httpd`コマンドでApacheを再起動する。
### パスワードファイルを作る
認証では、ユーザー名とパスワードの組み合わせが記述されたパスワードファイルをサーバーに置き、入力された情報と合致するかを確かめる。

パスワードファイルは以下の名称にするのが一般的。
* Basic認証の場合、「.htpasswd」
* Digest認証の場合「.htdigest」

このとき、サーバー側には生の状態ではなく、**ハッシュ化**されたパスワードが保存される。

:::note info
ハッシュ化とは、あんが桜花の一種で元のデータが予測できないよう、特別の計算式を使って変換した値のこと。生のパスワードの漏洩を防ぐ目的で使う。
:::
#### Basic認証のファイルの書式
```
ユーザー名：ハッシュ化されたパスワード
```
#### Digest認証のファイルの書式
```
ユーザー名：レルム：MD5でハッシュかした値
```
例）
```
banana:Please input password:4c24626e523af2ee637d45161544d538
```
#### 実際にBasic認証で使うパスワードファイルを作る方法
Apacheの機能（htpasswdコマンド）を使うことで、パスワードをハッシュ化することができる。ちなみにハッシュ化には「bcrypt」「MD5」「SHA1」「CRYPT」の４つの方式に対応している。
* 「.htpasswd」ファイルを生成するコマンド（/var/www/html/にbananaユーザーを記述しつつパスワードファイルを作成する
```
# htpasswd -c /var/www/html/.htpasswd banana
```
* すでに存在するパスワードファイルにユーザー名とパスワードを追記する場合は「-c」は不要。

#### ユーザーとパスワードを設定する方法
制限をかけたいディレクトリに「.htaccess」ファイルを置いて、認証機能を有効化する。全てのページに制限をかけたいのであれば「/var/www/html」ドキュメントルートに「.htaccess」ファイルを置く
* ファイルの書き方（Basic認証）
```
AuthType Basic
AuthName "Please input password"
AuthUserFile /var/www/html/.htpasswd
Require valid-user
```