OmniAICreator/Qiita-1.07M huggingface dataset:
NGC CatalogのPyTorchコンテナイメージを使う


## 参考
- [Dockerfile内でconda activateする](https://wwacky.hateblo.jp/entry/2020/04/08/001838)
- [リモートマシンのDockerコンテナにVSCodeで接続して開発するための環境づくり](https://k-hyoda.hatenablog.com/entry/2020/11/29/180943#1-Docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%ABSSH%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B)


## 開発用コンテナ

コンテナイメージは[NGC Catalog](https://catalog.ngc.nvidia.com/)から選ぶ。

```Dockerfile:Dockerfile
FROM nvcr.io/nvidia/pytorch:22.04-py3

ARG PROXY_URL

RUN apt-get update \
    # SSHサーバをインストール
    && apt-get install -q -y ssh \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    # SSHサーバが動作するために必要なsockファイルが配置されるディレクトリを用意
    && mkdir /var/run/sshd \
    # rootでログインできるようにするため、パスワードを設定(ただしこのパスワードは使いません)
    && echo 'root:password' | chpasswd \
    # パスワードでのログインをできないようにする
    && sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config # 

# SSHで使用する公開鍵をここでコピーする
WORKDIR /
COPY id_rsa.pub /root/.ssh/authorized_keys
# SSHポートを公開する(Docker Composeで別のポートにバインドするので22番ポートのまま)
EXPOSE 22  # 必要？

# その他開発に必要なプログラムのインストールなど
RUN apt-get update

# conda仮想環境作成
RUN conda create -n myenv python=3.9
# 仮想環境の activate 
ENV CONDA_DEFAULT_ENV myenv
# コンテナログイン用設定
RUN echo "conda activate myenv" >> ~/.bashrc
RUN echo "PATH=${PATH}:/opt/conda/envs/myenv/bin" >> ~/.bashrc

# ライブラリのインストール
RUN pip install pyanom

#.bash_profileを作成し、.bashrcを読み込む（シェルスクリプト）
RUN echo "if [ -f ~/.bashrc ]; then  . ~/.bashrc;  fi" >> ~/.bash_profile
# 環境変数の書き込み
RUN echo "HTTP_PROXY=${PROXY_URL}" >> ~/.bashrc
RUN echo "http_proxy=${PROXY_URL}" >> ~/.bashrc
RUN echo "HTTPS_PROXY=${PROXY_URL}" >> ~/.bashrc
RUN echo "https_proxy=${PROXY_URL}" >> ~/.bashrc

CMD ["/usr/sbin/sshd", "-D"]
```

```:docker-compose.yml
version: '2.3'
services:
  worker:
    build:
      context: ./
      args:
      - PROXY_URL=$PROXY_URL
    environment:
    - NVIDIA_VISIBLE_DEVICES=all
    - NVIDIA_DRIVER_CAPABILITIES=all
    container_name: dev
    ports:
    - "48881:22"
    volumes:
    - ${PWD}:/work
    runtime: nvidia
    working_dir: /work
```


```:.env
PROXY_URL=http://user:pass@proxy_url:port
```


## jupyter用コンテナ

```Dockerfile:Dockerfile
FROM nvcr.io/nvidia/pytorch:22.04-py3

ADD ./jupyter_notebook_config.py /root/.jupyter/jupyter_notebook_config.py

# RUN pip install ...
```


```:docker-compose.yml
version: '2.3'
services:
  jupyter:
    build:
      context: ./
    container_name: dev-jupyter
    ports:
    - "21000:8888"
    volumes:
    - ${PWD}:/work
    runtime: nvidia
    working_dir: /work
    command: jupyter notebook 
```


```python:jupyter_notebook_config.py
c = get_config()
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888
c.NotebookApp.token = ''
```
Node.js  参考サイトとメモ

https://developer.mozilla.org/ja/docs/Web/JavaScript

https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb

https://eng-entrance.com/what-is-nodejs

## Node.js とは？

ブラウザ上という制限された環境でしか動けなかったJavaScriptを、PythonやRubyのように __OS上で__ 動かせるようにしてくれる __JavaScript実行環境__ が __Node.js__。

OSにNode.jsをインストールすると __node.exe__ ができる。
node.exeはJavaScriptコードを __実行するアプリケーション__ （JavaScript実行環境）。

Node.jsではJavaScriptでOSの機能にアクセスするプログラムを組むことができる。
つまりブラウザ上で動作していたときはできなかった自由なファイルの読み書きやネットワーク通信などのOSの機能を扱える。

Node.jsは元々 __大量の同時接続をさばけるネットワークアプリケーションの構築を目的__ に設計されたJavaScript環境。

__サーバサイド__ のJavaScript実行環境として紹介されることが多いが、現在では __クライアントサイドJavaScript__ の開発環境としても広く利用されている。

## Node.jsを使う目的

### 新しい仕様のJavaScriptまたはTypeScriptでクライアントサイドのプログラムを書く

ES2015以降の　JavaScriptは便利な機能がたくさん仲間入りしたが、既存のブラウザがその仕様に追いついてこれないという問題が発生した。
これを解決するために登場したのが __「新しい仕様で書いたJavaScriptファイル」を機械的に「旧仕様（ES5）のJavaScriptファイル」に変換する__ 手法。

この __変換を行うツール（トランスコンパイラ）__ の現在の主流がBabelであり、それを動かすための __環境として__ Node.jsがよく選ばれている。

### Webアプリケーションを作る

### モバイル/デスクトップ用のアプリケーションを作る

フレームワークはモバイルアプリケーションであればReact Nativeが、デスクトップアプリケーションであればElectronが使われることが多い。

### その他

ウェブサイトのアセットをバンドル（webpack）する
SassをCSSに変換（node-sass）する
テストツール（Jest）やコード検証ツール（ESLint）を使う
開発用の簡易Webサーバ（webpack-dev-server）をローカルで立てる
静的サイトをビルド（Gatsby）する
上記のようにNode.jsは様々な用途で使われている。


## Node.jsが得意なもの：　リアルタイムWeb

__リアルタイムWeb__ などの分野はNode.jsがとても強い。

リアルタイムWebとは、リアルタイムな反応が必要なWebの分野のこと。
FacebookのメッセージやGoogleスプレッドシートなど。LINE、Twitter、instagram、snapchat、Paypalなどもリアルタイム性が高い例。各種チャットツールも。

Node.jsでは「新しい情報が来た！」と知らせてくれる機能を割と簡単に実装できるので。

## Node.jsが得意とするもの：多数のアクセスがある場所

#### Node.jsの第一目標

__スケーラブルなネットワーク・プログラムを作成するための簡単な方法を提供すること__

スケーラブルというのは拡張可能という意味。

JavaやPHPでは、接続ごとに新しいスレッドが作られる。8GBのRAMで計算すると、最大ユーザー数は5000名以下しかアクセスができなくなる。これを増やそうと思ったら、コンピュータを増やすしかない。

Node.jsはこの問題を解決する数少ないプログラミング言語。シングルスレッドで非同期処理を行い、この問題に対応できる。
ただし、単純な処理以外にはそこまで強くない。一概に速度が速いとは言えない。

## Node.jsを使うときの注意点

Node.jsは小規模で機動性の高いWebアプリケーションを使うのが無難。
特に、リアルタイム性が必要なアプリに最適。
trello-api ボードに紐づいているカスタムフィールドの値をJSONで取得する


## 目的

↓のエンドポイントたたくとボードに入っているカード全部紐づいているJSONとれる。
でも、そのJSONだけだと、カスタムフィールドがよくわからない。とくにカスタムフィールドの名前と紐づけできてない。

https://trello.com/1/boards/XXXXXX/cards~~

それでボードごとのカスタムフィールドのリスト取るエンドポイント探した。
でも見つかりにくかった。なので、ここに書く。

## コード（javascript)

```javascript

var user_name = 'XXXXXXXX';

// APIキーとトークン
var api_key = 'XXXXXXXXXX';
var api_token = 'XXXXXXXXXX';

//ボードID入れる
getCustomFields("XXXXXXXXXXXXXXXXXX");

function getCustomFields(e) {
  var url = "https://api.trello.com/1/boards/"+e+"/customFields?key="+api_key+"&token="+api_token;
  Logger.log(UrlFetchApp.fetch(url, {'method':'get'}));
}

```
phpcbfによる自動フォーマットをactionsでやる際のチップス

# 概要
- 前提
    - GitHubにpushしたらGitHub actionsでphpcsを実行する、自動フォーマットはしていない
- この記事
    - phpcbfでフォーマットして問題なければgit commit実行に変更したい


# actionsファイル解説
処理の流れは、コードをチェックアウトし、それに対してphpcbfでfix、修正しきれていないものがあればエラー、修正しきれていればコミットする。

モノレポやコード分量が多い場合は `actions/checkout@v3` を使わずに自前でsparse-checkoutで変更分だけ持ってくると良い。

## Setup PHP with tools
[shivammathur/setup-php@v2](https://github.com/shivammathur/setup-php)で簡単にPHPと必要コンポーネントをざっくり導入する。

## Format code
phpcbfで自動フォーマットする。
`--standard` オプションでphpcs.xmlにまとめたルールを実行できる。これがないとデフォルトのルールで実行されてしまう。
```
phpcbf --standard=phpcs.xml . || true
```

次に、末尾の `|| true` について。
GitHub actionsは実行したコマンドのExit codeが0でないとエラー扱いでworkflowが終了してしまう。
https://docs.github.com/en/actions/creating-actions/setting-exit-codes-for-actions

phpcsの中の人によれば、phpcbf実行後のExit codeは以下の通りに分類される。
fixする対象のあるなしに関わらず先に進めたいので `|| true` とした。
https://github.com/squizlabs/PHP_CodeSniffer/issues/1818#issuecomment-354420927
```
Exit code 0 is used to indicate that no fixable errors were found, so nothing was fixed
Exit code 1 is used to indicate that all fixable errors were fixed correctly
Exit code 2 is used to indicate that PHPCBF failed to fix some of the fixable errors it found
Exit code 3 is used for general script execution errors
```

### 参考
- https://stackoverflow.com/questions/66626814/github-action-error-process-completed-with-exit-code-1

## Lint
修正しきれなかったコードがあるかチェックする。
前のphpcbf実行時のExit code 2以上かのチェックができればここは不要だが今回はしなかった。

修正しきれなかった場合は手動で直して再pushする運用。
ここでエラーがなければ自動フォーマット分をcommitする
```
phpcs --standard=phpcs.xml .
```

## Count changes
差分があればcommitするのでその確認。


## 実際のファイル
```php-formatter.yml
name: php-Formatter
on: [push]
jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 1

      - name: Setup PHP with tools
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.0'
          tools: composer, phpcs, phpcbf

      - name: Format code
        run: |
          # fix対象ファイルがあればfixに成功してもExit code 1になるのでExit code 0にする
          phpcbf --standard=phpcs.xml . || true

      - name: Lint
        run: phpcs --standard=phpcs.xml .

      - name: Count changes
        id: changes
        run: |
          echo "::set-output name=count::$(git diff --name-only --diff-filter=AMR | wc -l)"
          git add $(git diff --name-only --diff-filter=AMR)

      - name: Commit and push
        if: steps.changes.outputs.count > 0
        run: |
          git config user.name github-actions
          git config user.email hogefuga@github.com
          git commit -m "fix php format"
          git push
```
【UiPath】データテーブルの操作（4）データテーブルの比較

# はじめに

この投稿は、RPAツール「UiPath」で Datatable からデータテーブルを比較する方法について、個人的にまとめたものです。


# データテーブルの操作 シリーズ
DataTable の操作方法について記載した記事が、他にもあります。参考まで。


https://qiita.com/miya_gis/items/6c0dd40378db702bd4b2

https://qiita.com/miya_gis/items/edc3557f3dc7cf6b3cfd

https://qiita.com/miya_gis/items/171b3d12775c95f722c4

https://qiita.com/miya_gis/items/78dd08bc7f0b5497b83d

https://qiita.com/miya_gis/items/966113ce9732cb112c49

https://qiita.com/miya_gis/items/f45b67fbc2575f0d6d77

https://qiita.com/miya_gis/items/67eac96071aa7d7d24dd

# 2つの DataTable を比較する

たまに、2つの DataTable を比較したいときがあります。たとえば

- Excel の Sheet1 と Sheet2 にある表が「内容が全く同じか？」を確認する
- Excel の Sheet1 と Sheet2 にある表で「内容が同じ行」を取得・確認する
- Excel の Sheet1 と Sheet2 にある表で「内容が違う行」を取得・確認する

というような場合です。

この場合、アクティビティを並べて「力技」で処理することも出来ますが、以下のようなLINQ 式を使用すると、簡単に比較できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/37ea367f-2ed7-af46-aab7-386030b9d39c.png)



以下で説明します。

# ２つの DataTable が「完全一致」するか

2つのデータテーブルで、中身が「完全一致」するか？は、以下のように判定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/a6a88933-bcd4-7d7e-841e-23ee4dafaaaa.png)
判定は、`.AsEnumerable.SequenceEqual(比較するDataTable, DataRowComparer.Default)` で行い、全行の配列を比較をしています。比較方法をカスタマイズしたいときに「DataRowComparer.Default」を変更しますが、UiPathでは基本的に使わないので考慮不要です。

VBのコードにすると、以下のようになります。
``` VB
'// 中身が一致するか判定
Dim isSameContents As Boolean = _
    dt_1.AsEnumerable.SequenceEqual(dt_2.AsEnumerable, DataRowComparer.Default)

Console.WriteLine(If(isSameContents, "中身が一致一致", "中身が一致しない"))
```

https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.sequenceequal?view=net-6.0


# ２つの DataTable で「重複する行」を取得

2つのデータテーブルで「同じ内容の行」を取得するには、以下のように行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/d5e70f1c-430a-e695-09bf-240bd7fe5c8b.png)

DataTable1 と DataTable2 の両方に含まれる要素を「`積集合（Intersect）`」という方法で取得します。

VBのコードにすると、以下のようになります。
``` VB
'// 同じ行を取得
Dim enm_datarow As IEnumerable(Of System.Data.DataRow) = _
	dt1.AsEnumerable().Intersect(dt2.AsEnumerable(), DataRowComparer.Default)

'// 行数が 0 で無ければ DataTable に変換（0なら.Cloneで定義のみコピー／中身は無し）
Dim dt3 As DataTable = _
    If(enm_datarow.Count <> 0, enm_datarow.CopyToDataTable(), dt1.Clone)
```

DataTable 型にしたければ「.CopyToTable()」を付けます。ただし、CopyToTable は、対象データ行がない場合はエラーになるので、上記のように「件数の有無」で分岐させると安心です。


# ２つの DataTable で「ユニークな行」を取得

2つのデータテーブルで「それぞれにしか無い行」を取得するには、以下のように行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/65ebf7df-2a9a-23d4-5c9f-1c69546a0e1e.png)
DataTable1 から DataTable2 の行を取り除いた行を「`差集合（Except）`」という方法で取得します。

VBのコードにすると、以下のようになります。
``` VB
'// ユニークな行を取得
Dim enm_datarow As IEnumerable(Of System.Data.DataRow) = _
	dt1.AsEnumerable().Except(dt2.AsEnumerable(), DataRowComparer.Default)

'// 行数が 0 で無ければ DataTable に変換（0なら.Cloneで定義のみコピー／中身は無し）
Dim dt3 As DataTable = _
    If(enm_datarow.Count <> 0, enm_datarow.CopyToDataTable(), dt1.Clone)
```

# 終わりに

いかがでしたでしょうか。なにかの役に立てば幸いです。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
C言語のビットシフトでエンディアン（バイトオーダー）を処理する

（『独習C』第13章の練習問題13.3の大問2）

32ビット整数に対するリトル・ビッグエンディアンの変換をビットシフトで行う関数：

```c
int32_t change_endian(int32_t x)
{
	return (x & 0xff000000) >> 24
		| (x & 0x00ff0000) >> 8
		| (x & 0x0000ff00) << 8
		| (x & 0x000000ff) << 24;
}
```

の意味について。

<br><br>

まず、32ビットで表すと以下の通り：

```
0xff000000 = 11111111000000000000000000000000
0x00ff0000 = 00000000111111110000000000000000
0x0000ff00 = 00000000000000001111111100000000
0x000000ff = 00000000000000000000000011111111
```


ここでは、変換したいやつ（32ビット整数）を

```
x = A B C D
```

と書く（ただし、A~Dはそれぞれ8ビット）。

以下のように計算される（`=`の記号は等号の意味です）：

```
x & 0xff000000 = A 0 0 0 (ここで 0 = 00000000 の8ビット)
(x & 0xff000000) >> 24 = 0 0 0 A ... ①

x & 0x00ff0000 = 0 B 0 0
(x & 0x00ff0000) >> 8 = 0 0 B 0 ... ②

x & 0000ff00 = 0 0 C 0
(x & 0000ff00) << 8 = 0 C 0 0 ... ③

x & 0x000000ff = 0 0 0 D
(x & 0x000000ff) << 24 = D 0 0 0 ... ④

return ① | ② | ③ | ④ = D C B A
```
ksnctf #22 Square Cipher

#Square Cipher

https://ksnctf.sweetduet.info/problem/22

a-z,A-Zのテキストが31×31で書かれている。

大文字を黒、小文字を白と置き換えて画像を作って見る。


1. まず大文字を1、小文字を0と置き換える。
1. 与えられたテキストを１次元から２次元に変換する
1. OpenCVを使って、1を黒、0を白で置き換えて画像を作る

```python
import cv2
import numpy as np

#1次元→2次元
def convert_1d_to_2d(l, cols):
    return [l[i:i + cols] for i in range(0, len(l), cols)]

text = '''oomktvziqtaovmmpxzoqrzsxlpwpgoj
uDQEMISYnnVYnvyWRhHsDXnSCXAVVZj
tZbknedErdpvAwQWpUiLqOxIqpafvXp
dXoAVWcKppbEPuaqmXWjXJwRoRFOoEg
pDiRUXlQjKJlslskVpGwtljGyVJPxHv
bQsQNKxCsdYMdQPJiBmyrsuOrJQOtXg
pMekeinUaMoDXqFzweLKipkBuggnsUv
eQFYCJSKfBgHaJgZnZoWmOmAOJLVQHi
hljrplajyKNXtwmfOjRwOqcqeeplyzy
gkFOltsOyrPgIaerIaSjQQaVMyEhfyd
vEaRHbBzfrcwJbCZmHdddLpuEJwspbt
sXQGkwpKaTZmWJiZzpbkpHNiToawxKn
wJpIKbGhnLjVAJNcxrqkKEJCKCOocSv
mTRDNDpFtRUmcHoRELeSqXoGUIIsuYu
ajeHaSVlQGLaEprSQarDzTomJdAWfqb
zIJLHRBXMvNDegYeaoVRDuWBbdSBtLv
xIeKdAYwajGHMgRLDGgDinBiLNBgatb
kHepNsCQSJjTRmQrCHYWJqIPOVAUOer
rvhmZfmogPglGNuLyAuSivBctlvVfzb
qBJdHUkSaTArlgkhtHPyGhXOPkwmkBq
rvbzZfwvLtTnhyXVHPlwsuGZQnNiNcm
yCMtAVwYVgtZHVNznolGMBETIHFmoWj
wfezbysbvOzsAhxSZFFAfOouyHldEYh
gNHKKSFUtcUxfRyXHMugYBtAxBwDJZh
rHmsozuNeoJqyzMDHsNbUDwzaNLtdxr
bVmQMHyNndOWCZLnhrPxZXCYLDTWQre
aSiEEJjZtoRpUzgsxsiiGzvnRpKLMrk
qTzGCKvNhUhjrmCjAdwQAvkgqHyJZLm
sSxzwjxAnWesTszIxirRwcWIXUPtwwa
nTDEMTRGyhzdCtkTTDWbxdSjsNYlfXz
eawtidzosgaofjxxyfcdoiulemirqap
'''

#大文字を1、小文字を0
bin_list=[]
for char in text:
    if(char.isupper()):
        bin_list.append(1)
    elif(char.islower()):
        bin_list.append(0)

#1次元→2次元
bin_list_2d = convert_1d_to_2d(bin_list, 31)

#1を黒、0を白で画像作成
img = np.full((50, 50, 3), 128, dtype=np.uint8)
for i in range (31):
    for j in range (31):
        if(bin_list_2d[i][j]==1):
            cv2.rectangle(img, (i, j), (i+1,j+1), (255,255,255), thickness=-1)
        elif(bin_list_2d[i][j]==0):
            cv2.rectangle(img, (i, j), (i+1,j+1), 0, thickness=-1)
            
cv2.imwrite('q21_QRcode.png', img)

```

得られたQRコードを読み取るとFLAGが得られた。
【小ネタ】SharePointリストで条件式の編集をして入力不要な列を非表示にする

SharePointのリストにデータを追加するとき、他の列の値によってこの列は入力しなくていいということがありました。
例として以下のようなリストでは、favorite列が「なし」のとき、category列は入力しなくていいです。
このとき、入力不要なcategory列を非表示するために使った条件式の編集について紹介します。
![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/545544f3-b319-4750-bd03-6acbdc03f42f.jpeg)
条件式の編集についての紹介をする前に、
SharePointについて分かりやすいと思った記事

https://www.onamae-office.com/office365column/oaapp/sharepoint/

SharePointのリストについて分かりやすいと思った記事

https://qiita.com/y-hy-h/items/fbcf362d06935f8b86ab

## 条件式の編集をする
非表示にするために列の編集から条件式の編集をします。
やり方は以下画像の通りです。
![002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/415741c1-e620-35f0-9757-f3b720c5cba6.jpeg)
![003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/f080da6f-3d64-3688-d087-3d51ca512ee5.jpeg)
![004.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/55b18942-3164-ad84-b550-67d04cf10842.jpeg)
![005.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/d2239804-f874-43bf-ae14-9ed99e984628.jpeg)
```
=if([$favorite] == 'なし', 'false', 'true')
```
## 動きを確認
以下画像の通り、favorite列を「なし」にするとcategory列が非表示になります。
![006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/a2130b04-4ff8-051b-bae2-2fdd92963b85.jpeg)
![007.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2480832/91904b8f-449d-3abe-7fbc-057728d25e16.jpeg)
## 条件式の編集の応用
簡単に条件式の編集の別の使い方について紹介します。
##### 1.条件に一致したときのみ列を表示する
trueとfalseを逆にすることで上記までの例とは逆に条件に一致したときは表示します。
```
=if([$favorite] == 'なし', 'true', 'false')
```
##### 2.数値を条件にする
列の種類が数値の場合、不等号で条件を設定します。
```
=if([$quantity] > 5, 'false', 'true')
```
##### 3.空欄を条件とする
空欄を条件とする場合、「''」を設定します。
```
=if([$favorite] == '', 'false', 'true')
```
##### 4.条件が複数ある
条件1または条件2の場合に非表示とするような場合、「||」を使います。
条件1かつ条件2の場合に非表示とするような場合、「&&」を使います。
```
=if([$favorite] == '' || [$favorite] == 'なし', 'false', 'true')
=if([$favorite] == 'なし' && [$quantity] > 5, 'false', 'true')
```

条件式の編集を使うことでデータ入力の際、入力間違いを減らすことができるかなと思います。
以上、是非お試しください。
現場でよく使うネットワーク関連のコマンド

## 環境
Ubuntu20.4

## はじめに
Ubuntuでよく使われるネットワーク系の基本コマンドについてまとめてみました。

## 記事
IPアドレスを調べるコマンドです。
（ひと昔は、ifconfigコマンドを使っていたようですが、今では使われないようです。）
```
ip a
```

インターフェースがloとなっている127.0.0.1というアドレスは、ループバック用のアドレスです。NICが生きているかどうかを診断するために割り当てられているアドレスです。IPv6のアドレス、MACアドレスなど、不要な情報も一緒に表示されるため、見難いなと思う場合は、次のコマンドを使うと、IPv4のアドレスだけに絞って表示してくれます。
```
hostname -I
```

ホスト名を調べるコマンドです。
ホスト名とはWindowsでいうコンピューター名の事です。Linuxではホスト名といいます。Linuxの世界にNetBIOS名というものは存在しません。よって、名前解決はDNSで行います。WINSで名前解決を行う仕組みはLinuxにはありません。
```
hostname
```

デフォルトゲートウェイのIPアドレスを調べるコマンドです。
（ひと昔は、routeコマンドで表示していたようですが、今はrouteコマンドは使われないようです。）
```
ip route show
```

default viaで表示されているIPアドレスがデフォルトゲートウェイに該当します。

NICの情報を調べるコマンドです。
```
ip a
ip link
```

ip aコマンドはNICの情報以外にIPアドレスも表示するが、ip linkコマンドにすると、NICの情報だけに絞って表示します。

IPアドレスの設定が、ダイナミックなのスタティックなのかを調べるコマンドです。
```
cat /etc/netplan/01-netcfg.yaml
```

dhcp4: trueになっており、addressed: でIPアドレスの指定がなければ、DHCPから自動取得されていると判断できます。dhcp4: falseになっていて、addressed: にIPアドレスの指定があれば、固定IPで割り当てていると判断できます。

ARPテーブルを調べるコマンドです。
（ひと昔は、arpコマンドを使って表示していましたが、今では使われないようです）
```
ip neigh show
```

ARPテーブルとは、MACアドレスとIPアドレスの対比をメモリ上で管理しているテーブルです。普段、意識することはほぼないでしょうが、ネットワーク機器の設定を行っていて、自分のIPアドレスを頻繁に変更するようなことがあった場合は、ARPテーブルの情報が古いと変なネゴシエーションが発生して、接続に時間がかかってしまいます。そのような時は、自分でARPテーブルをクリアしてやると、ネットワークの接続が速くなります。（体感的にはあまり分かりませんが。理論的には速くなっているはずです。）意識することがあるとすれば、その時くらいでしょう。
【Unity】UnityEditorトラブルシューティング

# フライスルーモード時の移動速度が遅すぎる・早すぎる
`右クリックを押しながらWASDQE`を押すと移動できるフライスルーモードですが、`右クリック＋ホイール`の操作で速度を変更することができます。
【Swift】Swiftでログを出すならこれも出そう

# printしたのはいいものの、これはどこから出たログ？

## ログを出す(今回は簡易的に)
とりあえず、一番簡単で使いやすいprintで出そう！
``` swift
print("ここが呼ばれた！")
```
これでヨシっと。

## 実行
``` log
ここが呼ばれた！
ここが呼ばれた！
ここが呼ばれた！
ここが呼ばれた！
```
あれ？

## 複数出たのは他のところにも書いたから(ってことにしておく)
やば、これじゃ他の"ここが呼ばれた！"を消さないとわかんないよ、、

## 解決策
class名とメソッド名、ついでに行番号も出してあげる

``` swift
// class名
print(type(of: self)) // MainViewController

// メソッド名
print(#function) // viewDidLoad()

// 行番号
print(#line) // 20
```
これならだいぶ分かりやすくなる！！！

## 最後に
printで簡易的にログを出す時、僕は行番号あまり気にしないので以下のようなテンプレを作ってます。
``` swift
"\(type(of: self))　\(#function) \n 内容：ここが呼ばれた！)"
```
他にもこれ出せます！とかあったら教えてください！！！！

## 最後に
iOSアプリ開発をしています。
主にSwiftですが、最近は熱が入ってきてFlutterも🦾
色々やってます。もし良かったら見てってください。

https://sogablog.net/
JSONとは

# JSON（JavaScript Object Notation)
構造化したデータを表すためのデータ記述言語の一種です。
javaScriptと書かれているがそれだけが使えるわけではない。
多くの言語に対応している。

# データ構造を表すのに使われる
XMLと同じく木構造で表現できる。
違いは
### XML
・データとして文字列しか表すことができない
・全ての情報にタグをつける必要があるためにデータサーズがお大きくなりがち
・テキストの任意の場所にタグ付けできる
### JSON
・データとしてm字列以外に数値や空を意味するデータなども扱うことができる。
・データを括弧で囲んで構造を表すのでデータファイルは小さい
・タグによるマーク付けがないため、人間胃は読みにくいデータとなる。

# Web上でのデータのやり取りによく使われる
・DOMを介さずやり取りできる。
・XMLよりもデータが小さい
その分ネットワークの転送速度が早くなります。
JavaScriptがよく利用されるWebの世界では選択されやすいデータ形式となっている。
【js】Intersection ObserverAPIを使用してみたメモ

# Intersection ObserverAPIとは
直訳すると「Intersection（要素間交差）」を「Observe（監視）」するAPIです。
指定した要素がブラウザと交差したタイミングで、処理を発火させることができます。
スクロールしてターゲット要素が見えたらフワッと表示させるあのアニメーションなどが実装できます。

## サンプルソース
```script.js
const texts = document.querySelectorAll('.text'); //監視したいDOM要素格納
const imgs = document.querySelectorAll('.img_bg_box'); //監視したいDOM要素格納。今回は二種類のクラスを監視対象にしたいため。
//const text = document.querySelector('.text'); ->要素が一個だけならこれ。

const cb = function(entries,observer) {
    entries.forEach(entry => {
        if(entry.isIntersecting) {
			entry.target.classList.add('fade-in'); //監視対象が画面と交差したらfade-inクラス付与
         // observer.unobserve(entry.target); -> 監視停止。true条件に記述することで監視対象要素が画面と交差したら監視を停止する。
        } else {
            entry.target.classList.remove('fade-in') //画面外に出たらfade-inクラス削除
        }
    })
}

const options = {
    root: null,
    // 親要素や先祖要素を入れて、交差対象を調整できる
    rootMargin: "-100px 0px",
    // 交差の判定にmarginをつけることができる。初期値は0なので、ブラウザに入った瞬間処理が発火する。
    // -は内側を意味するので、上記の場合はブラウザの上下100px内側に入ったら処理が発火する。
	 //cssと同じような記述のショートハンドができるが、0であっても必ずpxか%とつけないといけない。
    threshold: 0.5
    // 交差の起点を設定できる。値は交差している割合。
    // 初期値が0。
    // 0は画面に監視対象が入った瞬間が起点。
    // 1は画面に監視対象が全て入った瞬間が起点。
    // 配列の形でも記述できる。
};
// IntersectionObserverクラスにはオプションを設定したオブジェクトを第二引数に取ることもできる。
// 上記にようにオブジェクトリテラルで、定数にオブジェクトの形で代入してオプション設定する。

const io = new IntersectionObserver(cb, options);
// IntersectionObserverオブジェクトのインスタンス生成。
// オプションを設定したい場合は、上記のように第二引数に、オプション格納した定数を渡す。
// オプション設定してないなら、第二引数はいらない。
texts.forEach(text => io.observe(text)); //監視したいdom要素が複数あった場合の構文。
imgs.forEach(img => io.observe(img)); 
//io.observe(text); ->監視したいdom要素が一つの場合はこれだけでok
```

## 解説
### コールバック関数定義
```script.js
const cb = function(entries,observer) {
    entries.forEach(entry => {
        if(entry.isIntersecting) {
			entry.target.classList.add('fade-in'); 
        } else {
            entry.target.classList.remove('fade-in') 
        }
    })
}
```
こちらのコールバック関数定義部分。発火した際に行われる処理です。
```
const cb = function() {
    entry.target.classList.add('fade-in');
 }
```
上記のような記述だけでも機能するが、 （entries）,（observer）という引数を取ることができます。
if文の条件文にentries.isIntersectingプロパティを記述することで、処理を分けることが可能です。
監視対象DOMがwindowに交差したらisIntersectingは`true`に、画面から出たら、isIntersectingは`false`に処理が移ります。

### オプション設定
```script.js
const options = {
    root: null,
    rootMargin: "-100px 0px",
    threshold: 0.5
};
```
IntersectionObserverはオブジェクトの形で三つのオプションを設定できます。
`const io = new IntersectionObserver(cb, options);`でインスタンス化する際にオプションを設定したオブジェクトを第二引数に取ることができます。
突然「Webアプリを認証連携（SAML／OpenID Connect）対応して」と言われたら

# 0. はじめに

　上司やお客様から突然「Webアプリを認証連携（SAML／OpenID Connect）対応して」と言われた場合、どうしますか？いずれ弊社（OSSTech株式会社）のような専門ベンダに連絡するとしても、その前に、ベースの知識を得ておくためにWeb上で情報を探してみるのではないでしょうか。
　認証連携（SAML／OpenID Connect）の仕様については既に多くのウェブページで解説されてますが、実現のための検討観点についてはあまり情報がないかも...という印象です。

　というところで本記事では、Webアプリを認証連携（SAML／OpenID Connect）対応されるエンジニアの皆様を意識し、検討時にベース知識を得るための情報源となるべく執筆します。
もし記事をお読みくださったら、ベンダ候補として弊社も加えていただけますと嬉しいです。


# 1. そもそも認証連携（Federation）とは？

　「認証サーバによってユーザが認証されたら、アプリとしても認証済みとして扱うよう連携する」、ということです。
認証連携のための標準仕様として SAML や OpenID Connect があり、既に広く普及してきています。

　１つの認証サーバに対して複数のアプリを認証連携で繋げた場合、そのシステム全体はシングルサインオン環境となります。シングルサインオンの文脈で既に解説している記事シリーズを書いていますので、必要に応じてご参照ください。
（突然「シングルサインオン（ＳＳＯ）を検討して」と言われたら [第１回](/hoshino_osstech/items/9a59bfd7b5722a8c3d33)、[第２回](/hoshino_osstech/items/cc735c065dfaf39fcffd)、[第３回](/hoshino_osstech/items/677bc385436d54e29a62)、[第４回](/hoshino_osstech/items/b49c6154f4c38737a9dc)、[第５回](/hoshino_osstech/items/502fc59fbcc06a182f87)）


　Webアプリを認証連携対応することで、大きくは以下のようなメリットを享受できます。

| # | 項目 | 説明 | 
|:---|:---|:---|
| 1 | 認証の強化 | アプリ自体で認証方式を様々用意しなくても、連携先の認証サーバを利用することで、多要素認証などの強固な認証を利用できる。 | 
| 2 | 販売機会増 | 標準仕様（SAML, OpenID Connect）での認証連携接続を前提としたシングルサインオン環境が普及しており、これが受注要件であった場合に販売機会を得られる。 | 


# 2. 検討項目

　認証連携対応を実施すると決まったら、どのように検討を進めたら良いでしょうか。
大枠としては、以下のような項目を検討する必要があります。
検討が難しい項目もあるかもしれませんが、ざっくりとでも予め検討しておくと、
その後弊社のような専門ベンダとの会話や詳細検討がスムーズに進むと思います。

| # | 項目 | 説明 | 
|:---|:---|:---|
| 1 | どちらの標準仕様にするか | 「認証連携先の認証サーバがどちらの標準仕様に従っているか」、が一番大きな要因になるかと思います。<br>　どちらかと言えば、エンタープライズ系や学術系は SAML が多く使われ、コンシューマ系は OpenID Connect が多く使われる印象です。両方とも対応するという選択肢ももちろんあります。 | 
| 2 | 認証サーバからどの情報を受け取りたいか | ・認証サーバとして、どのような形式でどのような値をアプリ側に渡すことができるか。<br>・アプリとして、どのような形式でどのような値を受け取りたいか。 |
| 3 | その他、アプリ-認証サーバ間連携において特別に期待する動作があるか | 例として以下のようなものがあります。<br>・シングルサインオン動作ではなく毎度認証したいか<br>・シングルログアウトをしたいか<br>・アプリ側から認証サーバに対して認証方式を指定したいか<br>・上記まで含め、標準仕様のどの範囲まで実現するか。<br>・etc... |


# 3. 実現方法

実現方法のバリエーションとしては、大別して以下のようなものがあります。

| # | 項目 | 説明 | 
|:---|:---|:---|
| 1 | 自社開発 | SAML や OpenID Connect のクライアント側機能を自社で開発してしまう。費用の面からも安全性の面からも、正直お勧めしません。 | 
| 2 | 各言語のライブラリ利用 | 各プログラミング言語にて、SAML や OpenID Connect のクライアント側機能がライブラリとして提供されていることがあり、Webアプリの言語と適合するものがあれば利用できます。 |
| 3 | ソフトウェア／モジュール利用 | 弊社からも提供しています [mod_auth_mellon や mod_auth_openidc](https://www.osstech.co.jp/product/mod_auth_mellon_openidc/) のようなソフトウェア／モジュールを利用する形です。Webアプリの前段に配備することで、Webアプリの言語に依存することなく、ほぼほぼ設定のみで実現することができます。 |


# 4. おわりに

　Webアプリの認証連携を検討することになった場合の情報源となるべく、そもそも認証連携がどのようなものであるか、主な検討項目として何があるか、実現方法のバリエーションとしてどのようなものがあるかを記しました。

　全てを予め検討することは難しいかもしれませんが、弊社のような専門ベンダと会話する前の全体像理解や初期検討の一助としていただけましたら幸いでございます。
Arduino経由でMIDI信号を改ざんする

レトロなDTM用MIDI音源には、操作パネルが無いものもあります
ハードウェアのMIDIコントローラー等はお高くつくのでPCだけでなんとか簡単にMIDI音源を操作できないかな。。。
と思ったことはありませんか？

今回は、Arduinoを使ってMIDI音源をコントロールしてみたいと思います

必要なもの
・Arduino&USBケーブル
　　Arduino UNOなど

・仮想MIDIドライバー
　　LoopMIDI
　　http://www.tobias-erichsen.de/software/loopmidi.html

・シリアル-MIDI変換ソフト
　　Hairless MIDI<->Serial Bridge 
　　http://projectgus.github.io/hairless-midiserial/

・MIDI音源
　　これがないと始まらない！？
　　※USB接続できないものは別途MIDIインターフェースが必要です


ArduinoやArduinoIDEで使用可能な各種開発ボードをUSBケーブルで接続します
![FThYrK2aAAAsLbo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71444/82587c88-6d2b-6d57-c8c7-c370d280c55a.jpeg)

Serial portにArduinoのCOMポート、MIDI OutにMIDI音源へのインターフェースを設定し、MIDI送信するアプリケーションの出力をloopMIDIにしてください

Arduinoにプログラムを転送するときは、左上のチェックボックスをOFFにしないと転送時にエラーになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71444/a758139d-7ebb-8e0b-47e7-fde9ee2cee10.png)

MIDI信号の受け取り方ですが
このように、１バイトずつMIDI信号を拾ってもよいのですが
```
	while (Serial.available() ) {
		data = Serial.read();
	}
```
MIDIライブラリというものがあるのでそちらを使うと簡単です
```
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
```
Arduinoのライブラリはこのようにグローバルにインスタンスを持つのが一般的な様です

まずは初期化
```
void setup()
{
	MIDI.begin(MIDI_CHANNEL_OMNI);
	MIDI.turnThruOff();
	Serial.begin(115200);
}
```
シリアル-MIDI変換ソフトの通信速度設定も115200に合わせておきましょう

メインループは大まかにこんな感じです
```
void loop()
{
	uint8_t ch, sts, d1, d2;

	if (MIDI.read()) {
		sts = MIDI.getType();
		d1  = MIDI.getData1();
		d2  = MIDI.getData2();
		ch  = MIDI.getChannel();

		// MIDIデーター改ざん処理

		// MIDIデーター送信
		MIDI.send( sts, d1, d2, ch);
	}
}
```
setupで、
```
MIDI.turnThruOff()
```
と記述して、そのままOUTにTHRUされないようにして、自分で
```
MIDI.send()
```
を使って改ざんしたデーターを送信してあげるという流れになります

例えば、すべてのバンクセレクトを０にする場合
```
		// MIDIデーター改ざん処理
		if (sts == midi::ControlChange && d1 == midi::BankSelect) {
			d2 = 0;
		}
```
の様な感じです
この場合のmidi::BankSelectは0（LSB）です
32（MSB）を設定してあげる場合は定義が無い様なので直値で追加してみてください

デバイス一覧に出てくるものであれば、Microsoft GS Wavetable Synth等のソフトウェア音源でも操作可能です

実際のところ、X68kの出たなツインビーがSC-55mkIIでちゃんと鳴らないってところからこのコーディングに至りました
ArduinoUNOにMIDIシールドを付けて、実機でも動作可能なのでぜひ試してみてください
【Laravel8】マイグレーション実行と同時に初期データを投入する

# マスタテーブルの初期データ、どうしてる？

マイグレーションでマスターテーブルを作成時、初期データを投入しておきたいケースが有る。
その場合、Seederを作成して下記のようなコマンドで実行するように記載されているケースをよく見る

```sh
php artisan db:seed --class=HogeSeeder
```

# 面倒くさいし人的エラーの元になりそう

これだと個人開発では良いが、 **開発途中で追加されたテーブルでさらに新しく開発者がアサインされてきた場合** などに、いちいちこれを実行してもらうのはかなり面倒くさいし、マニュアルに書くのも忘れそう。
大規模開発になるほど負の遺産と化すだろう。

うっかり

```sh
php artisan db:seed
```

までで実行してメインのデータがテストデータに初期化されてしまう恐れもある。

# マイグレーション実行時にデータを入れてしまいたい

そもそも、初期データなのだから、マイグレーションの実行（テーブル作成）と一緒に入ってこなければおかしいはず。
だって、**後から同一テーブルのデータ型が変わったりした場合、Seederも書き換えないといけないし、そうすると変更経緯がよくわからなくなってしまう。**

そんなわけで調べてみたら、[できるじゃん](https://owenconti.com/posts/calling-laravel-seeders-from-migrations)。
https://owenconti.com/posts/calling-laravel-seeders-from-migrations

つまり、Seederを作成するところまでは同じだが、**`db:seed`の対象にはせず、マイグレーション実行時に`db:seed --class=HogeSeeder`を実行すれば良いということ**。

上記リンクを読めば95%くらい理解できると思うが手順を書いていく。

# 作成手順

## 1. マイグレーションとSeederを作成  

```sh
php artisan make:migration create_hoges_table
php artisan make:seeder HogeSeeder
```

## 2. マイグレーションを記述

ニ箇所に追記があるので注意。

```database\migrations\yyyy_mm_dd_time_create_hoge_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;  // ← 追記

class CreateHogesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('hoges', function (Blueprint $table) {
            $table->id();
            $table->string('name')->comment('ラベル');
            $table->timestamps();
        });

        // 追記：初期データの投入
        Artisan::call('db:seed', ['--class' => 'HogeSeeder']);
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('hoges');
    }
}
```

## 3. Seederを記述

```database\seeders\HogeSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class HogeSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        \DB::table('hoges')->insert(
            [
                [
                    'id' => 1,
                    'name' => 'ほげ',
                    'created_at' => now()
                ],
                [
                    'id' => 2,
                    'name' => 'ふが',
                    'created_at' => now()
                ],
            ]
        );
    }
}
```

## 4. マイグレーション実行

```sh
php artisan migrate
```


# 注意点

**テーブルの作成に成功してSeederの実行に失敗した場合、手動でテーブルの削除が必要になる。**

- migration履歴に残らない
- 当然ロールバック対象にもならない

なのでまずはマイグレーションとSeederを分けて、それぞれの実行に成功してからマージするのが良いと思う。
Firebase Security Rules の制約「リクエストあたり評価される式の最大数」の「式」のカウント方式について

Firebase Security Rules にはいくつかの制約がある。
それらは公式ドキュメントのこの箇所に書かれている。

https://firebase.google.com/docs/firestore/security/rules-structure?hl=ja#security_rule_limits

このうち、「リクエストあたり評価される式の最大数」の「式」のカウントの仕方について、
Googleの人がStack Overflowで解答していた。

https://stackoverflow.com/questions/55651525/firestore-rules-maximum-of-1000-expressions-to-evaluate-has-been-reached

書かれているカウント例を抜粋すると、

``true`` は 1
``true || false`` は 1 （左の true だけカウントされるらしい。）
``false || false`` は 3
``request.resource.data`` は 3
``関数呼び出し`` は 1

らしい。

なるほど、変数や || などもカウント対象なのね。

**余談：調べるまでの経緯**

XcodeのシミュレータとFirebaseのエミュレータを使って開発している時、Firestoreへの保存時にエラーが発生した。エラー変数をXcodeに表示すると、以下のようであった。

```
Unable to evaluate the expression as the maximum of 1000 expressions to evaluate has been reached.
```

何かの制約に引っかかったらしい。
という訳で、調べてみた。
Valhalla | docker imageをbuildし、日本全域の地図を読み込む

## はじめに

ValhallaはOpenStreetMapを元にしたルーティングエンジンです。公式のdocker imageがあるのですが、ドキュメントが不足しており初見ではどう使うのかなかなか分かりづらい状態です。試行錯誤した結果、build方法などが分かりましたので共有したいと思います。

- GitHub: 
  - https://github.com/valhalla/valhalla
- Docker Hub: 
  - https://hub.docker.com/r/valhalla/valhalla

## Dockerfile

例として日本全域の地図データを読み込んでいます。必要に応じて適宜変更してください。

```Dockerfile
FROM valhalla/valhalla:run-latest

WORKDIR /app
RUN wget http://download.geofabrik.de/asia/japan-latest.osm.pbf
RUN mkdir -p valhalla_tiles
RUN valhalla_build_config --mjolnir-tile-dir ${PWD}/valhalla_tiles --mjolnir-tile-extract ${PWD}/valhalla_tiles.tar --mjolnir-timezone ${PWD}/valhalla_tiles/timezones.sqlite --mjolnir-admin ${PWD}/valhalla_tiles/admins.sqlite > valhalla.json
RUN valhalla_build_tiles -c valhalla.json japan-latest.osm.pbf
RUN valhalla_build_extract -c valhalla.json -v

EXPOSE 8002

CMD ["valhalla_service", "valhalla.json", "1"]
```
Rustで蟻本の簡易テストの仕組みを作った

こんにちは。


蟻本は`C++`で書かれているため、自分のような`Rust`ユーザが手元で動かすには人間トランスパイルみたいなことをしないといけず、結構バグらせてしまってました。

## 確認方法(before)

```
> cargo run --bin 1-1a
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/1-1a`
> [標準入力を手で入力]
3
10
1 3 5
> [結果を目視で確認]
Yes
```

標準入力が1行ならまだ耐えられますが、
複数行になるともうめんどくさすぎて耐えられません・・・！

## 確認方法(after)

`test 1-1a`と入力すればチェックできるようにしました。

```
> test 1-1a
test for 1-1a
---INPUT----
3
10
1 3 5
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/1-1a`
---OUTPUT---
Yes
---RESULT---
OK
```

## 仕組み

シェルでごにょごにょしてます。仕組み自体は超シンプルです笑

https://github.com/okaponta/ant-book-rust/blob/main/test.sh

 - `test/in/[通し番号].txt`を標準入力として出力
 - 上記の標準入力をプログラムに渡して実行、標準出力を`test/output/[通し番号].txt`に書き出し
 - 期待値(`test/out/[通し番号].txt`)との差分を確認する。
   - 期待値通りならOKを出力
   - 期待値と異なる場合にはNGと期待値を出力

## 見た目

### 成功時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561891/4619c13b-9441-8439-7c67-100f77b35037.png)

### 失敗時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561891/97e41cc1-28c4-72e9-ccb4-4aad9980217e.png)

## 使用方法

- 下記リポジトリをチェックアウトする
- 対応する問題のソースコードを書き換える
- `source ./test.sh`にて`function`読み込み(1回だけやればいいです)
- `test [通し番号]`とコンソールで入力

https://github.com/okaponta/ant-book-rust

## 注意事項

 - 動くのは簡易的な1ケースのみです！最低限の動作確認程度に思ってください。
    - 複数テストケース実行できるようにしたいとも思いましたが、整備する気力も出なそうだったので、1ケースのみの用意になってます。。
 - 初級編までしか基本的に実装終わってません！
    - 中級編以降は随時追加していきます。。
    - やる気がでなかった問題などは飛ばしてしまっています・・・

## さいごに

やっつけ仕事のようなシンプルな仕組みでしたが、
導入してからだいぶ確認が楽になりました・・・

よかったら使ってください！！:crab:
(間違いやアップデートもあればPRいただけると喜びます:bow:)
VRMBlink　VRMモデルで自動で瞬きがしてほしかったんだ～!

# 目的

自動の瞬きをVRMモデルでもやりたい！

https://youtu.be/De3t7D-EMTU

https://github.com/blackpopo/QiitaLaboratory

# 参考

Unity-chan

https://assetstore.unity.com/packages/3d/characters/unity-chan-model-18705?locale=ja-JP

これのAutoBlink.csの改造バージョンです。

```VRMBlink.cs
using UnityEngine;
using System.Collections;

class VRMBlink : MonoBehaviour
{

	[SerializeField] bool isActive = true;				//オート目パチ有効
	[SerializeField] SkinnedMeshRenderer FaceMesh;	//EYE_DEFへの参照
	[SerializeField] int EyeCloseNum = 13;
	[SerializeField] float ratio_Close = 95.0f;			//閉じ目ブレンドシェイプ比率
	[SerializeField] float ratio_HalfClose = 30.0f;		//半閉じ目ブレンドシェイプ比率
	[HideInInspector]
	[SerializeField] float ratio_Open = 0.0f;
	private bool timerStarted = false;			//タイマースタート管理用
	private bool isBlink = false;				//目パチ管理用

	[SerializeField] float timeBlink = 0.4f;				//目パチの時間
	private float timeRemining = 0.0f;			//タイマー残り時間

	[SerializeField] float threshold = 0.3f;				// ランダム判定の閾値
	[SerializeField] float interval = 3.0f;				// ランダム判定のインターバル



	enum Status
	{
		Close,
		HalfClose,
		Open	//目パチの状態
	}


	private Status eyeStatus;	//現在の目パチステータス


	// Use this for initialization
	void Start ()
	{
		ResetTimer ();
		// ランダム判定用関数をスタートする
		StartCoroutine ("RandomChange");
	}

	//タイマーリセット
	void ResetTimer ()
	{
		timeRemining = timeBlink;
		timerStarted = false;
	}

	// Update is called once per frame
	void Update ()
	{
		if (!timerStarted) {
			eyeStatus = Status.Close;
			timerStarted = true;
		}
		if (timerStarted) {
			timeRemining -= Time.deltaTime;
			if (timeRemining <= 0.0f) {
				eyeStatus = Status.Open;
				ResetTimer ();
			} else if (timeRemining <= timeBlink * 0.3f) {
				eyeStatus = Status.HalfClose;
			}
		}
	}

	void LateUpdate ()
	{
		if (isActive) {
			if (isBlink) {
				switch (eyeStatus) {
				case Status.Close:
					SetCloseEyes ();
					break;
				case Status.HalfClose:
					SetHalfCloseEyes ();
					break;
				case Status.Open:
					SetOpenEyes ();
					isBlink = false;
					break;
				}
				//Debug.Log(eyeStatus);
			}
		}
	}

	void SetCloseEyes ()
	{
		FaceMesh.SetBlendShapeWeight (EyeCloseNum, ratio_Close);
	}

	void SetHalfCloseEyes ()
	{
		FaceMesh.SetBlendShapeWeight (EyeCloseNum, ratio_HalfClose);
	}

	void SetOpenEyes ()
	{
		FaceMesh.SetBlendShapeWeight (EyeCloseNum, ratio_Open);
	}
	
	// ランダム判定用関数
	IEnumerator RandomChange ()
	{
		// 無限ループ開始
		while (true) {
			//ランダム判定用シード発生
			float _seed = Random.Range (0.0f, 1.0f);
			if (!isBlink) {
				if (_seed > threshold) {
					isBlink = true;
				}
			}
			// 次の判定までインターバルを置く
			yield return new WaitForSeconds (interval);
		}
	}
}
```

これをアタッチしてFaceMeshにモデルのFaceのメッシュを割り当ててください。
以上！
scipy.stats: 関連2標本の平均値の差の検定 ttest_rel, ttest_1samp

# scipy.stats: 関連2標本の平均値の差の検定 ttest_rel, ttest_1samp

# 1.　テストデータの生成


```python
import numpy as np
x = np.array([63.6, 62.9, 41.1, 54.0, 45.0, 39.8, 62.4, 37.8, 45.5, 47.9])
y = np.array([69.7, 50.2, 48.7, 59.4, 52.8, 54.9, 76.9, 66.4, 50.1, 48.8])
```

# 2.　関連2標本の平均値の差の検定 `ttest_rel`


```python
from scipy.stats import ttest_rel
```

`ttest_rel(a, b, axis=0, nan_policy='propagate', alternative='two-sided')`

デフォルトで両側検定である。特に指定するなら `alternative='two-sided'` を指定する。

帰無仮説は「2 つの対応のある標本の母平均は等しい」である。

戻り値は $t$ 統計量と $p$ 値である。


```python
ttest_rel(x, y)
```




    Ttest_relResult(statistic=-2.3166916999976834, pvalue=0.045732821155958746)



帰無仮説が「最初に指定したデータの母平均のほうが小さい」という片側検定の場合には，`alternative='less'` を指定する。

$p$ 値は，両側検定の場合の 1/2 になる。


```python
ttest_rel(x, y, alternative='less')
```




    Ttest_relResult(statistic=-2.3166916999976834, pvalue=0.022866410577979373)



帰無仮説が「最初に指定したデータの母平均のほうが大きい」という片側検定の場合には，`alternative='greater'`。

なお，テストデータは `alternative='less'` の例なので，'greater' を指定すると $p$ 値は 0.5 以上になる。


```python
ttest_rel(x, y, alternative='greater')
```




    Ttest_relResult(statistic=-2.3166916999976834, pvalue=0.9771335894220207)



# 3.　1標本の母平均の検定 `ttest_1samp`

対応のある2標本データの差を計算して，`ttest_1samp` で検定することもできる。この場合は，「観察データが指定した母平均を持つといえるか」という検定になるので，母平均を `popmean` で指定しなければならない。

`popmean` はデフォルト値がないので，必ず指定しなければならない。

「対応のある2標本データの平均値の差の検定」では，帰無仮説を「差がない」とすることが多いので，それに対しての「1標本の母平均の検定」では `popmean=0` を指定することになろう。

しかし，`ttest_1samp` で `popmean` を指定できるのは，`ttest_rel` よりも優れている。`ttest_rel` は平均値の差は 0 と決めつけていて変更できないからである（多くの統計パッケージでは，「対応のある2標本データの平均値の差の検定」の場合にも，平均値の差の指定ができる）。


```python
from scipy.stats import ttest_1samp
```

`ttest_1samp(a, popmean, axis=0, nan_policy='propagate', alternative='two-sided')`


```python
diff = x - y
print('mean(x) = ', x.mean(), '  mean(y) = ', y.mean(), '  mean(diff) = ', diff.mean())
```

    mean(x) =  50.0   mean(y) =  57.79   mean(diff) =  -7.790000000000004


差を求めて `ttest_1samp` で検定する。帰無仮説は「差の母平均は 0 である」。これは，「元の対応のある 2 標本の平均値の差は 0 である」と同じことである。

特に指定しなければ両側検定（`alternative='two-sided`）が行われる。

戻り値は $t$ 統計量と $p$ 値である。


```python
ttest_1samp(diff, popmean=0)
```




    Ttest_1sampResult(statistic=-2.3166916999976834, pvalue=0.045732821155958746)



帰無仮説が「母平均は `popmean` より小さい」ならば，`alternative='less'` を指定する。

$p$ 値は両側検定の 1/2 になる。


```python
ttest_1samp(diff, popmean=0, alternative='less')
```




    Ttest_1sampResult(statistic=-2.3166916999976834, pvalue=0.022866410577979373)



帰無仮説が「母平均は `popmean` より大きい」ならば，`alternative='greater'` を指定する。

実際のデータが帰無仮説と逆になっていれば，$p$ 値は 0.5 より大きくなる。


```python
ttest_1samp(diff, popmean=0, alternative='greater')
```




    Ttest_1sampResult(statistic=-2.3166916999976834, pvalue=0.9771335894220207)



当然ながら `popmean` は 0 でなくてもよい。

例題では平均値の差は -7.79 であるが，もし帰無仮説が「母平均は -6 である（両側検定）」ならば，「そういうことはよく起きること」なので，$p$ 値は 0.05 より大きくなり，帰無仮説は棄却できないということになる。


```python
ttest_1samp(diff, popmean=-6)
```




    Ttest_1sampResult(statistic=-0.5323335228492759, pvalue=0.6073847139443715)
【jQuery】フォームの二重送信の防止





一度押したボタンは押せないようにします。
以下を追加するだけ！

簡単ですね。

一度押したボタンを押せないようにしています。
リロードしたらもとに戻ります。

```javascript
$(function(){
    $('input[type="submit"]').on('click', function(){
        $(this).prop('disabled', true);
        $(this).closest('form').submit();
    });
});
```
MacOS上のMicrosoft AutoUpdate (MAU) の更新間隔を変更する

更新間隔が短くて(2時間おき？)イライラしたので調べた。
M1 macだと機能しないとの記述もあって調査中。


# 参考/出典
https://superuser.com/questions/1544338/turn-off-microsoft-apps-microsoft-autoupdate-app-on-a-mac/


# 現在の設定を確認する
```
plutil -p /Library/LaunchAgents/com.microsoft.update.agent.plist
```


# 値を変更する

## 更新時間(秒)を変更
一週間(3600*24*7=604800)おきにチェック(のはず)
```
sudo plutil -replace StartInterval -integer 604800 /Library/LaunchAgents/com.microsoft.update.agent.plist
```

## 自動更新させない(未確認)
```
sudo plutil -replace Disabled -integer 1 /Library/LaunchAgents/com.microsoft.update.agent.plist
sudo plutil -replace RunAtLoad -integer 0 /Library/LaunchAgents/com.microsoft.update.agent.plist
```
オリジナルアプリ作成で考えること

オリジナルアプリ作成も佳境に入るかなという段階になってきたので、進捗をお話します。

# 進捗
何とかseederのデータベーステストまで終わりました。
この次は、スクレイピングでデータを取得しデータベースに保存するという工程に移ります。

# ここから・・・
スクールの講師の人に見てもらいながらやっていましたが、オリジナルアプリ作成に関しては、
自分で調べながらかつ分からないところを聞きながら、が基本と言うことでした。

# スクレイピングに関して
今回使うのは、Guotteというサービスです。
composerで使えるようにするところは分かりますが、そのあとが分からなくなるところだと思います。

# 現段階までのソースコード
https://github.com/kazunarigit/baystarsapp

上が現段階までのソースコードです。複雑なコードは一切ありません。
（デザインを無視しているので、そうなっているだけです）

デザインはsassなどでやったほうがいいのでしょうが、スクールの講師の人に聞いていないので抜けています。

以上が進捗です。
DatadogでGPUの使用状況を監視する

## 目的

DatadogでNVIDIA Management Library(NVML) 公開メトリクスを監視する設定をします。  
[公式資料](https://docs.datadoghq.com/ja/integrations/nvml/)の補足としてご参考下さい。

## Required

- Datadog
  - Datadogへの登録
  - DD_API_KEYの取得
- GPU: NVIDIA謹製
- OS: Ubuntu 18.04.2 LTS (Confirmed)
- Docker: 19.03.14 (Confirmed)

## 手順

### Datadog監視エージェントの起動

1. Docker imageの作成

    1. Dockerfile

        - 用意されている[Dockerfileの例](https://github.com/DataDog/integrations-extras/blob/master/nvml/tests/Dockerfile)をダウンロード。
        - 上記Dockerfileの末尾に、以下を追記。（＝conf.yamlの作成）

            ```dockerfile
            # Use example as is
            RUN mv /etc/datadog-agent/conf.d/nvml.d/conf.yaml.example /etc/datadog-agent/conf.d/nvml.d/conf.yaml
            ```

    1. Build

        ```bash
        docker build --build-arg=DD_AGENT_VERSION=latest -t datadog-nvml:latest .
        ```

1. 監視エージェントを起動し、監視を開始

    ```bash
    docker run -d --name my-datadog-nvml --env DD_API_KEY=<your-api-key> datadog-nvml:latest
    ```

1. GPUの監視設定がされている事を確認

    1. エージェントの状態を確認

        ```bash
        docker exec -it my-datadog-nvml s6-svstat /var/run/s6/services/agent/

        # OK:
        # up (pid xxx) xxxx seconds
        ```

    1. Checkにnvmlが有る事を確認 (Agent の status サブコマンドを実行し、Checks セクションで nvml を探します)

        ```bash
        docker exec -it my-datadog-nvml agent status | grep nvml

        # OK:
        nvml (1.0.1)
          Instance ID: nvml:xxxxx [OK]
          Configuration Source: file:/etc/datadog-agent/conf.d/nvml.d/conf.yaml

        # NG: No output > /etc/datadog-agent/conf.d/nvml.d/conf.yamlが存在しないor 内容がおかしい。> 手順1.1を見直す。
        ```

### 動作確認

1. GPUを使用してみる

    ```bash
    # Get a training script
    wget https://raw.githubusercontent.com/pytorch/examples/main/mnist/main.py

    # Start training
    docker run -v $(pwd):/work --rm --gpus all nvcr.io/nvidia/pytorch:21.03-py3 python /work/main.py --no-mps
    ```

1. GPUの使用状況を確認

- Datadogの[ダッシュボード](https://app.datadoghq.com/)にて

  1. インテグレーションを追加
     - ```Integrations > Integrations > NVMLと入力し検索 > Nvidia NVMLを選択 > Install```
  2. メトリクスを探し、追加
      - ```Metrics > Explorer > Graph > nvmlと入力し検索```
      - merics一覧
        - [Docs > Integrations > Nvidia NVML > 収集データ > メトリクス](https://docs.datadoghq.com/ja/integrations/nvml/#%E5%8F%8E%E9%9B%86%E3%83%87%E3%83%BC%E3%82%BF)
        - e.g.
          - nvml.gpu_utilization
          - nvml.fb_used

### 成功例
  - 学習スクリプトで利用したGPUの使用状況を、ダッシュボードで確認できた。 (終わり)
  ![datadog_nvml_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645138/fe8b4fc3-cbae-a4ce-8cfc-755a4a4d189b.png)
【OCI】FastConnectについていろいろ #5(冗長構成時のルーティング制御)

###はじめに
OCIのFastConnectを利用してユーザ側ネットワークと接続する際、
Oracle EdgeとCustomer/Partner Edge間のルーティング制御にはBGPのみがサポートされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/77d58e4f-eb78-fa70-8a5d-dce160562efe.png)
今回はOCIとユーザ側ネットワークをFastConnect経由かつ冗長化構成にした場合の
ルーティング制御について解説してみたいと思います。

###2つのVirtual Circuitを使った冗長構成
OCIとのFastConnect接続にオラクルプロバイダを利用、冗長化構成にした場合の構成イメージです。
今回はこちらの構成について解説してみようと思います。
※<font color="red">**[オラクルドキュメント「Connectivity Redundancy Guide」より引用][1]**</font>

[1]:https://docs.oracle.com/en-us/iaas/Content/Resources/Assets/whitepapers/connectivity-redundancy-guide.pdf

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/56e17c25-0ecc-9286-6227-2505b862e05f.png)



###ルーティング制御について解説
①Customer On-PremisesのルータからOCIのDRGにアドバタイズする経路情報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/a1d9bbd3-6da7-3e5d-0a32-cfd70978f872.png)

②OCIのDRGからCustomer On-Premisesのルータにアドバタイズする経路情報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/199fdadf-c136-15f8-b8d6-3737ad09620d.png)

③OCIのDRGから受信した経路情報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/4cb5900b-32a3-af75-7cc2-8d8261887d85.png)

④Customer On-Premisesルータから受信した経路情報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/9ed1bd7f-76b7-9e5b-3468-1af449e70d43.png)

⑤経路制御結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/2661b91f-beee-5327-b4ee-b22bdab99b4e.png)







###まとめ

###参考情報
【OCI】FastConnectについていろいろ #4(マルチクラウド構成)

###はじめに
オンプレミス環境にあるシステムをリフトしたり、新しいシステムを稼働させる環境として利用したりと
パブリッククラウドの利用用途は様々です。
その際ですが、各パブリッククラウドはコストの設定も違えば、得意とするワークロードも違ったりします。

まだ運用・管理面やパフォーマンス(特にネットワーク)面から1つのクラウドサービスに集約することが
多い状況ではありますが、OCIのFastConnectをはじめとするクラウドのプライベート接続サービスと
各社プロバイダの高帯域/低レイテンシなクラウド接続サービスが比較的に安価に利用できるようになった
今では各クラウドサービスの良いとこどりしたマルチクラウド構成も検討しやすくなっています。

今回はOCIと他社クラウド間におけるマルチクラウド構成についてご紹介したいと思います。


###OCI⇔Azure

【InterConenct】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/ee59de26-00dd-e5c0-a18e-33a2aaa382f2.png)
両社クラウド間の設備はあらかじめ相互接続されています。
ユーザはFastConnect(Oracle Cloud)とExpressRoute(Microsoft Azure)を利用して
各クラウドの仮想ネットワーク間をセキュアにつなぐことが可能です
(OCI⇔Azure間の相互接続のことを「InterConnect」と呼んでいます)

<font color="red">**[【InterConnectを経由する場合のアーキテクチャ】][1]**</font>

[1]:https://docs.oracle.com/ja/solutions/learn-azure-oci-interconnect/index.html#GUID-A3BCA684-47C4-4644-90E8-99A7E3E0A6FE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/bad12c07-53e1-a803-4089-46b6eff0d933.png)


(InterConnectが利用可能なRegion)
※MicrosoftロゴがついているRegionが対象
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/0c6c6195-0273-0dbc-880b-19439a72af44.png)

###OCI⇔AWS
<font color="red">**[【Megaportを経由する場合のアーキテクチャ】][2]**</font>
OCIのFastConnect及びAWSのDirect Connectとの接続のための仮想回線にVXC(それぞれ1本ずつ※計2本)を、
OCIとAWS間のBGPピアリング及びルーティング制御のためのルータとしてMegaport Cloud Routerを用いた構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/ebe2c097-0f26-9b24-779b-90b51ef6833c.png)

<font color="red">**[【Equinix Fabricを経由する場合のアーキテクチャ】][3]**</font>
OCIのFastConnect及びAWSのDirect Connectとの接続のための仮想回線に
Equinix Fabric Virtual Connection(それぞれ1本ずつ※計2本)を、
OCIとAWS間のBGPピアリング及びルーティング制御のためのルータとしてNetwork Edge Virtual Rouetrを用いた構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/8ac31ea0-9bcd-45e7-e8e7-b76c4baf3a3b.png)

[2]:https://docs.oracle.com/ja/solutions/multicloud-arch-using-megaport/index.html#GUID-FEF79AC1-2EC5-4F5A-99E9-67CCC26E90A0
[3]:https://docs.oracle.com/ja/solutions/oci-aws-equinix/index.html

###まとめ
今回はOracle Cloudとマルチクラウド接続する際の構成例についてご紹介しました。
簡単にまとめますと、

・OCI⇔Azure間のInterConnectはクラウド間の配線やルーティング制御のための装置を
　ユーザ側で用意することなくFastConnectとAzureの契約だけで相互接続を実現します。
　なお、両者のパートナシップによって接続された回線は最短距離で結ばれ、
　高品質/低レイテンシーの通信環境を提供します。
・OCI⇔Azure以外のパブリッククラウド(この記事ではAWSを例に挙げています)間接続は
　NaaSであるMegaportのサービスを利用する方法と、FastConnect Locationの
　データセンター事業者でもあるEquinix社のサービスを利用する際の構成が代表的です。
　どちらのサービスも有名パブリッククラウドサービスとの接続をサポートしており、
　マルチクラウド構成に適したサービスになっています。
・OCIと他社クラウド間接続は今回紹介した方法以外に通信プロバイダを利用する方法もあります。
　例えば<font color="red">**[KDDI社のマルチクラウドゲートウェイ][6]**</font>はOCIとAWS両方に対応しており、
　網内を折り返してクラウド間通信を行うことができます。
　拠点間接続のための回線やクラウド間接続までを1つのプロバイダに集約したい場合は
　こちらの選択肢もありますね。

###参考情報
<font color="red">**[Megaport社サービス紹介ページ][4]**</font>
<font color="red">**[Equinix社サービス紹介ページ][5]**</font>

[4]:https://www.megaport.com/ja/
[5]:https://www.equinix.co.jp/
[6]:https://biz.kddi.com/service/multi-cloud-gw/
【OCI】FastConnectについていろいろ #3(OCI非対応環境からの接続)

###はじめに
前回はFastConnectの3つの接続モデルについてご案内しました。
3つの接続モデルはどちらもOCIに対応している環境(プロバイダ、コロケーション)からの接続を想定していますが
ユーザの既存環境が必ずしもOCIに対応しているとは限りません。というか非対応環境であることも多々あります。
今回はOCI非対応環境からの接続について考えてみたいと思います。


###OCI非対応環境
以下の通り、拠点とOCI間をFastConnect経由で接続したいが
FastConnect Locationにコロケーション環境を持っていなく、
利用中のプロバイダにもOCI接続サービスが存在しないケースが考えられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/808d0062-f8ca-2228-0d7e-783e6ee07e02.png)


###OCI非対応環境からのOCI接続
【対策①】
ユーザ拠点の1ヵ所にOCI対応プロバイダ回線を新たに開通させ
既存利用のキャリア網と相互接続することによってOCIとの通信経路を確保する方法。
この方法を選択する場合は相互接続ポイントとなる拠点がきちんとしたデータセンターであることが望ましい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/e1742150-be5b-0210-d359-dc828a99bceb.png)
【対策②】
Oracle Providerのデータセンターにコロケーション環境を設け、既存利用回線を新たに引き込む。
さらにOracle Provider回線を新規に開通させ相互接続することでOCIとの通信経路を確保する。
この方法はユーザの拠点としてきちんとしたデータセンターが存在しなく対策①での対応が不可の場合に有効である。
コロケーション環境を用意するためのコストが発生することと、コロケーション環境の追加により
ユーザへの運用・管理の負荷が増えるので検討時のネックとなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/836cb09f-b935-6f64-f490-7e06d90c9d0c.png)
【対策②の構成例】
オラクルプロバイダのサービスを組み合わせてOCI非対応環境とOCI間の経路を構築した例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/4100cf5e-9b92-4140-e3ae-2dfe0a67e31a.png)
<font color="red">**[①ONUお預かりサービス][1]**</font>
既存利用プロバイダ回線の引き込み先としてキャリア終端装置(ONU)やCPEなどを置くための
スペースと電源を提供します
<font color="red">**[②仮想マネージドルータ][2]**</font>
既存利用プロバイダのCPEとの相互接続及びOracle EdgeとのBGPピアリングを行うための
装置のマネージドサービスです
<font color="red">**[③ネットワーク接続サービス(ATBeX)][3]**</font>
コロケーション環境とOracle Cloud間の接続サービスです

[1]:https://www.attokyo.co.jp/connectivity/onu.html
[2]:https://www.attokyo.co.jp/connectivity/m-router.html
[3]:https://www.attokyo.co.jp/connectivity/atbex.html

###まとめ
今回はFastConnectいろいろの第2回目として接続モデルについてご紹介しました。
各接続モデルの特徴について簡単にまとめると以下の通りになると思います。

①Oracleプロバイダ
プロバイダ設備とOracle設備間がすでに接続されており
仮想回線の作成のみでOracle Cloud間の経路が確保できるため
<font color="red">**申込から開通までの納期が短いこと**</font>が特徴と言えます。

②サードバーティ・プロバイダ
プロバイダ設備とOracle設備間をユーザごとに専用の物理回線で接続するため
<font color="red">**高いセキュリティとパフォーマンス**</font>が特徴です。

③コロケーション
FastConnect Location内の短距離における接続になるため<font color="red">**配線のコストが安価**</font>な上、
<font color="red">**接続モデルの中で最も高いパフォーマンスが出せるモデル**</font>になります