OmniAICreator/Qiita-1.07M huggingface dataset:
PowerShellで独自クラス定義からCSV出力まで

型付きプロパティの定義まで出来ると他の言語と同じ様に使えます
ソースコードからテーブル等の設計書リバース生成を想定

# CSV出力クラス定義

```powershell
class CsvOutData
{
  # プロパティ
  [string] $PhysicalName
  [string] $LogicalName
  [string] $Detail

  # コンストラクタ
  CsvOutData([string]$ByPhysicalName,[string]$ByLogicalName,[string]$Detail){
    $this.PhysicalName = $ByPhysicalName
    $this.LogicalName = $ByLogicalName
    $this.Detail = $Detail
  }
}
```

# CSV出力クラス配列の定義

```powershell
$CsvOutDataList = New-Object System.Collections.ArrayList
```

# リストに値追加

二つのデータを追加する例
実際はソースコード等から抽出した情報をコンストラクタに引数として渡します

```powershell
$CsvOutDataList.Add((New-Object CsvOutData("datamodel1","☆☆表","〇〇に依存")))
$CsvOutDataList.Add((New-Object CsvOutData("datamodel2","△△表","〇〇と□□に依存")))
```

# 値確認

これだけで値が出力される

```powershell
$CsvOutDataList
```

# CSVとして出力(TYPE情報あり)

```powershell
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_TYPE情報ありカンマ区切り.csv"
```

# CSVとして出力(UTF8、TYPE情報あり)

```powershell
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_UTF8TYPE情報ありカンマ区切り.csv" -Encoding UTF8
```

# CSVとして出力(UTF8、TYPE情報あり、タブ区切り)

タブ区切りにしたい時もある

```powershell
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_UTF8TYPE情報ありタブ区切り.csv" -Encoding UTF8 -Delimiter "`t"
```

# CSVとして出力(UTF8、TYPE情報なし、カンマ区切り)

TYPE情報いらない

```powershell
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_UTF8TYPE情報なしカンマ区切り.csv" -Encoding UTF8 -NoTypeInformation
```

# まとめ

```powershell
# CSV出力クラス定義
class CsvOutData
{
    # 内部データ
    [string] $PhysicalName
    [string] $LogicalName
    [string] $Detail

    # コンストラクタ(初期値のセット)
    CsvOutData([string]$ByPhysicalName,[string]$ByLogicalName,[string]$Detail){
        $this.PhysicalName = $ByPhysicalName
        $this.LogicalName = $ByLogicalName
        $this.Detail = $Detail
    }
}

# CSV出力クラス配列の定義
$CsvOutDataList = New-Object System.Collections.ArrayList

# リストに値追加
$CsvOutDataList.Add((New-Object CsvOutData("datamodel1","☆☆表","〇〇に依存")))
$CsvOutDataList.Add((New-Object CsvOutData("datamodel2","△△表","〇〇と□□に依存")))

# 値確認
$CsvOutDataList

# CSVとして出力(TYPE情報あり)
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_TYPE情報ありカンマ区切り.csv"

# CSVとして出力(UTF8、TYPE情報あり)
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_UTF8TYPE情報ありカンマ区切り.csv" -Encoding UTF8

# CSVとして出力(UTF8、TYPE情報あり、タブ区切り)
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_UTF8TYPE情報ありタブ区切り.csv" -Encoding UTF8 -Delimiter "`t"

# CSVとして出力(UTF8、TYPE情報なし、カンマ区切り)
$CsvOutDataList | Export-Csv -Path "$HOME\Desktop\CSV出力_UTF8TYPE情報なしカンマ区切り.csv" -Encoding UTF8 -NoTypeInformation
```
【JavaScript修行】Reactのpropsって？

前[ちょこっと勉強した](https://qiita.com/irico/items/84203d3d17d3368e9bf0)Reactをもう少し勉強します。

参考
https://qiita.com/morrr/items/c32a4916d55373b64c70
https://ja.reactjs.org/docs/components-and-props.html

##コンポーネントのprops
なんか前ではクラスを作るには２種類〜とか書いてましたが、
ファンクションで作るのがもっともシンプルな方法らしいです。

```react

function hello(props) {
  return <h1>Hello, {props.name}</h1>;
}
```

`props`・・・コンポーネント内外でパラメータをやりとりする仕組み。

そして前回扱っていたクラスで上記と同じ意味の物をかくと...

```react
class Hello extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
```

Reactでは、上のファンクションの式＝下のクラスになる、という理解で良さそうです。


##コンポーネントを描写
描写は`ReactDOM.render`を利用します。
上記のコンポーネントを渡す場合、このように記述します。

```react
<Hello name="Irico" />
```

```react:コンポーネントの描写
function Hello(props){
  return <h1>hello,{props.name}</h1>;
}

ReactDOM.render(
  <Hello name="Irico"/>,
  document.querySelector('body')
)
````
これでbodyに`hello,Irico`と表示されます。

ちなみに...
>補足: コンポーネント名は常に大文字で始めてください。
React は小文字で始まるコンポーネントを DOM タグとして扱います。例えば、<div /> は HTML の div タグを表しますが、<Welcome /> はコンポーネントを表しており、スコープ内に Welcome が存在する必要があります。
とのことなので、**コンポーネント名は今後大文字**で記述していくことにします。


##コンポーネント蜜月関係
コンポーネントからコンポーネントへの参照も簡単にできます。
だからコンポーネント内でコンポーネントを利用するのも楽勝です。


```react
function Hello(props){
  return <h2>Hello,{props.name}</h2>;
}

function Repeat(){
  return(
    <div>
      <Hello name="Irico" />
      <Hello name="Zyako" />
      <Hello name="Chirimen" />
    </div>
  );
}

ReactDOM.render(
  <Repeat />,
  document.querySelector('body')
  
)
```
「Hello,Irico
Hello,Zyako
Hello,Chirimen」
と問題なく表示されています。

`Repeatコンポーネント`が`Helloコンポーネント`を参照して、
それを描写することができました。


##propsにおける禁忌
>全ての React コンポーネントは、自己の props に対して純関数のように振る舞わねばなりません。

という禁忌があります。
引数に変更を加えないものを**純関数**といって、`props`を扱う関数は
これでなくてはダメだ！ということです。

```javascript
function Func(arg){
   return arg + 1;     //純関数
}
function Func(arg){
   return arg++       //純関数ではない
}  
```
neovimでvim-slimのシンタックスハイライトが適用されない

neovimのslimシンタックスハイライトのプラグイン[vim-slim](https://github.com/slim-template/slim/blob/master/README.jp.md)をインストールしたが、なぜかハイライトが適用されなくて嵌りましたので備忘録

# 結論

プラグイン管理にdeinを利用してtomlファイルで管理していたのですが、なぜかそれだと正しくインストールされていませんでした。なのでneovimを立ち上げて以下のコマンドを叩いて手動でインストールすると反映しました。

```vimscript
:call dein#add(’slim-template/vim-slim’)
:call dein#install()
```

```dein_lazy.toml
~
[[plungins]]
repo = 'slim-template/vim-slim'
on_ft = ['slim']
~
```

## 色々やったこと

この後は色々苦労した事を書いていますので、不要な方は読み飛ばしてください。

[github](https://github.com/slim-template/slim/blob/master/README.jp.md)では色々issueが書いてあるので、その辺の問題が出ているんじゃないかと思い、最初はそこを疑って以下を試しました。

ますは、READMEにもあるfiletypeがslimとして正しく認識されない問題
確かに、slimファイルを開いても、set syntax?とすると

```vimscript
syntax=
```

[github](https://github.com/slim-template/slim/blob/master/README.jp.md)にもあるように以下の一行をinit.vimに追加します。

```vimscript
autocmd BufNewFile,BufRead *.slim setlocal filetype=slim
```

するとslimとして認識するようにはったのですが、

```vimscript
syntax=slim
```

しかし、ハイライト表示されませんでした、そのあと散々ググっても上記の件しか出てこなく、他のpluginとの干渉のために、既存のdein.tomlとdein_lazy.tomlの内容を変更して調査しても改善されず。最終的にはneovimとdeinとvim-slimだけの構成にしても、反映しないのでおかしいぞ！と思い~/.cache/dein/repos/github.com/を見てみると、なんとインストールされていないではないですか！！、:call dein#update()やら:call dein#recache_runtimepath()やら:call dein#install()を散々やったのですが...なぜかtomlでvim-slimがインストールできないようです。

原因はイマイチわかりませんが手動でのインストールでようやくシンタックスハイライトを適用されました。

<img width="762" alt="スクリーンショット 2019-07-29 14.49.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86321/861cf03f-cb65-52ba-ce15-19e750504177.png">
Google Coral Edge TPUボードとNVIDIA Jetson Nano Devボード - ハードウェア比較

（記事の出所：Medium 作者：Manu Suryavansh，切り取る）

NVidiaとGoogleの両社は最近、EdgeAIをターゲットとした開発ボード、および開発者、メーカー、趣味専門家を引き付けるためのコスト面での開発を発表しました。 どちらの開発ボードも主に推論を目的としていますが、限定的な移転学習の再トレーニングをサポートしています。 Edge TPUはウェイトインプリンティング技術を使用したトランスファーラーニングトレーニングをサポートしています。 両方の開発キットは、USB、イーサネット、microSDスロットなどのようなさまざまなコネクタを持つ開発ボードに接続されたSOM（システムオンモジュール）で構成されています。これは、使用できる2つの開発キットのハードウェアの比較です。 Edge TPU USBスティックではなく、シングルボードコンピュータ（SBC）として。 記事全体を読みたくない場合は、WifiやBluetoothなどの重要な周辺機器が含まれているため、Coral Edge devキットの方がコスト的にやや優れていますが、Jetson Nanoはソフトウェアサポートが優れています（INT8とFP16推論）。 ）

![微信图片_20190606175850.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/baaa673a-65ce-0ad6-54c8-b48ee656d767.jpeg)


![微信图片_20190404110322_副本.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/d5fc3942-0d92-3b2c-a775-5a691951c373.jpeg)

### Google Coral Edge TPU開発ボード
キット全体のサイズは -  88 mm x 60 mm x 22 mm、SOMのサイズは -  48 mm x 40 mm x 5 mmです。 したがって、人々は異なるフォームファクタの独自のベースボードを設計してSOMに接続することもできます。 このボードには、u-bootブートローダーが付属しているだけで、後でMendel linuxのようなイメージをロードすることができます。
Coral SOMのNXP iMXMプロセッサには、Vivante GC7000 liteグラフィックスGPUもあります - グラフィックス以外にも使用できますか？ 

Google Coral Edge TPU ここでそれを買う: https://store.gravitylink.com/global


### NVIDIA Jetson Nano Devキット
ここのサンゴ板のように、SOMもベースボードに接続します。 Jetson SOMは少し大きく、69.6 mm x 45 mmです。 ボードはUbuntu 18.04ベースの環境が付属しています。

以下は、2つのボードのハードウェア機能の比較です：

![微信截图_20190729132654.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/fbf962b3-9b36-1489-a3b8-55a5290a195b.png)

#### パフォーマンス
Nvidiaは、Jetson NanoとRaspberry Pi 3、Google Coral Edge TPUボードなどの他のSBCとのパフォーマンス比較をいくつか提供しています：
![1_v77qD0ZOVPfFwMzFEK5Gjg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/36bd98d0-6c1f-0c2c-b9c6-d752ce381cee.png)

Coral Edge TPUボードは、量子化を意識したトレーニングでトレーニングされていない事前トレーニング済みモデルを実行できないため、ごくわずかな結果しかありません。 上記の結果で、JetsonはFP16精度を使用しました。

### 結論
私の意見では、コーラルエッジTPU開発ボードは以下の理由からより優れています :
1. $149 の Coral devボードはJetson Nano（$99）より少し高価ですが、Jetson Nanoでは外付けのWiFiドングルを購入する必要があります。
2.さらに、サンゴボードのNXP iMX8 SOCには、ビデオ処理ユニットと、従来の画像およびビデオ処理に使用できるVivante GC700 lite GPUが含まれています。 また、温度センサー、周囲光センサーなどの他のセンサーと通信するために使用できるCortex-M4F低消費電力マイクロコントローラーもあります。

![微信图片_20190531135348.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/5845eccf-1b30-eff1-b925-ce499e1a77e4.jpeg)


JetsonにはVideoエンコーダとデコーダユニットもあります。 さらにJetson Nanoは、Pytorch、MXNetのような他のディープラーニングフレームワークに対するより良いサポートをしています。 FP16推論およびINT8推論用のNVidia TensorRTアクセラレータライブラリもサポートしています。 Edge TPUボードは8ビット量子化Tensorflow liteモデルのみをサポートしており、量子化対応トレーニングを使用する必要があります。
TypeScriptで配列の要素をUnionで取得する

# 結論

```ts

const array = ['山田', '田中', '鈴木'] as const;
type LastNames = typeof array[number]; // => '山田' | '田中' | '鈴木'
```

## 何がしたかったか

`as const`で定数化した配列の要素のうち、いずれかを受け取るよう関数を書きたかったのですが、地味に悩みました。
`配列の0番目の要素|残りの要素`みたいな形で再帰的にやるのか？とか、`keyof`でとってきた中から`'0'`だけ省いて？とか色々考えましたが、前者はかなり面倒、後者はarrayのプロパティがずらずら付いてきてしまうので断念。

そのときふと、`keyof`で取得した中に`number`がいたので、試してみたらあっけなく出来ました…。

## 追記

`keyof any[]`をすると、配列のメソッドのキー名等も取り出されてしまいますが、インデックスのみが欲しい場合、`type PickIndex<T extends any[]> = Exclude<keyof T, keyof any[]>;`で実現できます。

```ts

const array = ['山田', '田中', '鈴木'] as const;
type PickIndex<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>;
type Indexes = PickIndex<typeof array>; // => '0' | '1' | '2'
```
VirtualBox共有フォルダの設定

# 共有フォルダが使えないことを解決

下記リンクを参照して共有フォルダのマウントは解決できました。

>[[Windows10] Virtualboxの仮想マシン(CentOS8)にGuest AdditionsをインストールしてWindowsフォルダを共有]
(https://qiita.com/wz7777/items/2e62932f2ad5baf2e6a3)

## 必要のパッケージ（CentOS8でのテスト）：
```shell
yum install -y kernel kernel-headers kernel-devel gcc bzip2 make perl elfutils-libelf-devel
```

## 必要のパッケージ（Debian10でのテスト）：
```shell
apt install linux-headers-4.19.0-6-amd64 gcc make perl
```

# 注意事項
・VBoxLinuxAdditions.runの実行後、OS再起動の必要がある
・デフォルトでは、VirtualBoxグループユーザ（rootも使用可）しか使えないので、下記コマンドで特定ユーザをVirtualBoxのグループ（vboxsf）に追加しました。

```shell
#usermod -aG vboxsf uniqpirlo
```

uniqpirloユーザで再ログインして共有フォルダが使えるになりました！
【Rails】終了できない！A server is already runningの対処！

##はじめに
railsをいじっていると、pumaを起動させたままターミナルを閉じたりすると
pumaが終了出来なくなることがあるのでメモを残します。

#### エラー文
```terminal
A server is already running. Check /app/tmp/pids/server.pid.
```

##症状

```terminal
ec2-user:~/environment/develop (master) $ rails s
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
A server is already running. Check /home/ec2-user/environment/develop/tmp/pids/server.pid.
Exiting
```

`control+C`で終了できなくなりました。

##解決方法
上記のコードに書いてある`/home/ec2-user/environment/develop/tmp/pids/server.pid`を開くと
ポート番号が書いてあったので、kill -9で強制終了させます。

```terminal
kill -9 番号
```

**これで、`rails s`で再起動すればOKです**

#追記
これを打ち込んだ方が、簡単に削除出来ます！

```console
$ rm -f tmp/pids/server.pid
```

docker使ってる方は、Makefileとかに下記を定義しておくと楽です。

```makefile
run:
docker-compose exec web /bin/bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b 0.0.0.0"
```

これで``make run``て打てば、Railsの起動が楽になります。
CircleCIでHomebrewをキャッシュする方法


CircleCIのmacOS ビルドイメージにはHomebrewがプリインストールされているため、`brew install` を使用するだけで、パッケージをインストールできます。
しかし、そのまま使うとインストールにとても時間がかかるためキャッシュを利用して速度を上げます。

## 方法

キャッシュ対象は下記

- `$HOME/Library/Caches/Homebrew`
  - ダウンロードしたフォーミュラのキャッシュ
- `/usr/local/Homebrew`
  - metadataなど

`save_cache` 前に `brew cleanup` で不要なキャッシュを削除する。

## 完成したconfig.yml

```.circleci/config.yml
version: 2.1

jobs:
  build:
    macos:
      xcode: "10.2.1"
    steps:
      - restore_cache:
          keys:
            - homebrew-v1-
      - run: brew update
      - run: brew install cowsay
      - run: brew upgrade
      - run: brew cleanup
      - save_cache:
          key: homebrew-v1-{{ epoch }}
          paths:
            - /Users/distiller/Library/Caches/Homebrew
            - /usr/local/Homebrew
      - run:
          name: cowsay hi
          command: cowsay Hi!

workflows:
  build-and-test:
    jobs:
      - build

```

## Before / After

[![Image from Gyazo](https://i.gyazo.com/cba007248a414eb1dc00b15da7bdb2e3.png)](https://gyazo.com/cba007248a414eb1dc00b15da7bdb2e3)

[![Image from Gyazo](https://i.gyazo.com/dc5adb39120e741047c0927a563e0ea8.png)](https://gyazo.com/dc5adb39120e741047c0927a563e0ea8)

`restore_cache`に時間がかかるようになりますが、`brew update`の時間が短縮されます。
二分探索法

2分探索を書く機会があったので、メモとして記述しておきます。

<h1>2分探索とは</h1>
データを探索するときに使うアルゴリズム。
ソート済みのデータの範囲を絞りながら探索を続けることできる。
高速に探索を行う手法。


２分探索は全体の配列から半分ずつ範囲を絞りながら、検索するアルゴリズムなだけに
はやい。

```Sample.java

int algorithm(int[] data, int target) {
    int retrieve = -1;
    int left = 0;
    int right = data.length - 1;
   
    while(left < right){
        int mid = (left + right)/ 2;
        if(data[mid] == target){
            return mid + 1;
        }else if(target < data[mid]){
            return right = mid;
        }else {
            return left = mid + 1;
        }
    }
    return retrieve;
}
```


<h1>まとめ</h1>
ソート済みであるなら、２分探索の方が良いですね
docker-machine で作ったEC2上にntp を設定

docker-machine で作ったEC2 のホストで時間が無茶苦茶ズレている事に気づいた。
ntp を設定する

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/set-time.html

```
$ docker-machine ssh my-machine
$ sudo apt update
$ sudo apt install chrony
$ sudo vi /etc/chrony/chrony.conf
```

```
server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4
# ↑pool の前の行にこの行を追加
pool 2.debian.pool.ntp.org offline iburst

## 中略一番下
# ポートを無効化してサーバーとして動作させない
pool 0
```

```
$ sudo systemctl restart chrony
$ chronyc sources -v
210 Number of sources = 5

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current synced, '+' = combined , '-' = not combined,
| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 169.254.169.123               3   4   377     0  -2985ns[-3000ns] +/-  430us
^- ntp.netviscom.com             2   6    37     1  +6070us[+6070us] +/-   82ms
^- 74.208.26.225                 1   6    37     2  +6171us[+6171us] +/-   39ms
^- 0.time.dbsinet.com            2   6    37     1   +816us[ +816us] +/-   55ms
^- ha82.smatwebdesign.com        2   6    37     1   +828us[ +828us] +/-   61ms
```

> 返される出力では、^* が優先時刻ソースを示します。 

とのこと

すでに時間がめっちゃズレているので 強制的に合わせる
password は root のパスワードではなく、 /etc/chrony/chrony.keys に書いてある

```
$ sudo chronyc
chrony version 2.1.1
Copyright (C) 1997-2003, 2007, 2009-2015 Richard P. Curnow and others
chrony comes with ABSOLUTELY NO WARRANTY.  This is free software, and
you are welcome to redistribute it under certain conditions.  See the
GNU General Public License version 2 for details.

chronyc> password
Password: # ここ
200 OK
chronyc> makestep
200 OK
chronyc> ^D
```

時間が合ったら成功

```
ubuntu@tdb-dev:~$ date
Wed Jul 17 02:25:30 UTC 2019
```
【ORACLE】既存オブジェクトのCRATE文がほしい

### やりたいこと
- 既存オブジェクトの Crate 文がほしい。

### 方法
####①sqlplus でログインする
####②出力フォーマットを設定しておく
```.sql
SQL> SET LONG 10000
```
```.sql
SQL> SET PAGES 0
```
####③ GET_DLL コマンドを使用して取得する

```.SQL
SQL> SELECT DBMS_METADATA.GET_DDL('オブジェクトの種類', 'オブジェクトの名前', 'スキーマ名') FROM DUAL;
```
|名称|説明|
|:---|:---|
|オブジェクトの種類| TABLE とか、VIEWとかいれるよ|
|オブジェクトの名前| 対象オブジェクト名|
|スキーマ名|省略も可能。省略したときは現在のスキーマ名|

たとえば、USER というテーブルの CREATE 文を取得したい。
使用するスキーマは現在のスキーマのときは以下の SQL 文となる

```.SQL
SQL> SELECT DBMS_METADATA.GET_DDL('TABLE', 'USER') FROM DUAL;
```

実行を行うと、たとえば下記のようなCREATE文がかえる。

```.SQL
 CREATE TABLE "HOGE"."USER"
  (    "USER_ID" NUMBER(2,0),
       "USER_NNAME" CHAR(10),
 USING INDEX PCTFREE 0 INITRANS 2 MAXTRANS 255  NOLOGGING
 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
 TABLESPACE "USERS"  ENABLE
  ) PCTFREE 0 PCTUSED 99 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
 TABLESPACE "USERS"
```
Microsoft Azure メンテナンス通知

こんにちは、kc-dreamです。
今回は、Microsoft Azureでのメンテナンスメールについてご紹介していきます。

##メンテナンス通知について
Azureでは、年に一度程度の頻度で、仮想マシンの再起動を伴うメンテナンスが計画しております。
特に何月、と決定されているわけではなく、時期は不定期ですが、通常行われる VM 再起動を伴わないメンテナンスで行えないような、ハードウェアの BIOS・ファームウェア アップデートや、基盤側の OS などソフトウェアの大幅な更新といった目的で行われます。

Azureでは、メンテナンスや大きな障害等がある際にメール通知を行える仕組みがあります。
※各サブスクリプション毎に設定が必要

本記事では、この仕組についてご紹介していきます。

##通知の種類
大きく分けて4種類あります。

**(1) サービスの問題**
ユーザーに今すぐ影響を及ぼす Azure サービスの問題。

**(2) 定期的なメンテナンス**
お使いのサービスの可用性に将来影響を及ぼす可能性のある今後のメンテナンス。

**(3) 正常性に関する勧告**
ユーザーが注目する必要のある Azure サービスの変化。 Azure の機能が非推奨となるタイミングや、使用量のクォータを超えた場合に関する例も含まれます。

**(4) リソース正常性**
Azureサービスの問題でリソースが影響を受けている際に確認いただくことが可能となります。
※2019/07/29時点ではプレビューとして提供


##設定方法
**(1)~(3)の設定方法**
AzurePortalより、[モニター]から[Service Health]を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229923/051806df-4ece-acbb-2f94-806813c9590e.png)

[サービス正常性アラートの作成]を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229923/0824f2a6-a19e-95d1-6f7c-ac5bb11760b5.png)

必要事項を入力し、作成することで通知が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229923/9d166772-8e19-4c39-91fb-ad71cfa94601.png)

**(4)の設定方法**
AzurePortalからの設定は現時点ではできません。
本記事では、詳細を省かせていただきますが、下記リンクを参考にして頂ければ簡単に設定可能です。
※本機能は2019/07/29時点ではプレビューとなっております。

[Resource Manager テンプレートを使用して Resource Health アラートを構成する](https://docs.microsoft.com/ja-jp/azure/service-health/resource-health-alert-arm-template-guide)

##参考情報
[Azure Monitor を使ってメンテナンス通知を受け取る](https://blogs.technet.microsoft.com/jpaztech/2017/09/15/maintenance_notification/)

[[2018/3/26更新] 新規リリースされた “Azure Monitor” 機能を使って、利用中のリソースに影響しうるメンテナンスや障害のメール通知を受け取る](https://blogs.technet.microsoft.com/jpaztech/2017/04/10/notifyshdupdate/)

[サービス正常性](https://docs.microsoft.com/ja-jp/azure/service-health/service-health-overview)

[Azure Resource Health の概要](https://docs.microsoft.com/ja-jp/azure/service-health/resource-health-overview)

[Resource Manager テンプレートを使用して Resource Health アラートを構成する](https://docs.microsoft.com/ja-jp/azure/service-health/resource-health-alert-arm-template-guide)

[Resource Health は Azure の状態や Service Health ダッシュボードと何が違うのでしょうか。](https://docs.microsoft.com/ja-jp/azure/service-health/resource-health-faq#how-is-resource-health-different-from-azure-status-or-the-service-health-dashboard)

[サービス通知のアクティビティ ログ アラートを作成する](https://docs.microsoft.com/ja-jp/azure/service-health/alerts-activity-log-service-notifications)
PowerShellでGrepしてファイルへ出力する手順

ログファイルをWindowsで検索する際に、役立つと思います。
3つのコマンドレットを組み合わせて実現します。
# 環境確認
```PowerShell
PS > $PSVersionTable.PSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      17134  858
```
# ログファイルを標準出力に書き出す
文字コードをオプションで指定しています。

```PowerShell
PS > Get-Content -Encoding UTF8 .\hoge.log
```
# Grepする
fugaは検索対象です。

```PowerShell
PS > Select-String -Path .\hoge.log fuga
```
# 検索結果をファイルに出力する
出力ファイル名と出力内容を指定します。

```PowerShell
PS > Set-Content -Path .\fuga.log -Value hoge
```
# ログファイルをGrepしてファイルにリダイレクトする
上記のコマンドレットを ```|``` で連結して使用します。

|No|項目|意味|
|---|---|---|
|1|hoge.log|検索対象のログ|
|2|huga|検索対象のワード|
|3|result.log|出力ファイル|

```PowerShell
PS > Get-Content -Encoding UTF8 .\hoge.log | Select-String fuga | Set-Content .\result.log 
```
# 参考
[公式Docs](https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-windows-powershell?view=powershell-6)
[それ PowerShell でできるよ](https://qiita.com/cd01/items/da9a36582372e7d0a7f6)

以上です。
Nginx版:mkcertを使ってローカル環境でもDockerでも楽々SSL

# 背景

[mkcertを使ってローカル環境でもDockerでも楽々SSL](https://qiita.com/ProjectEuropa/items/37b0cfbe0d2347d8e16a)はApacheだったので、Nginx版です。

## mkcertのインストール

mkcertのインストールは[mkcertを使ってローカル環境でもDockerでも楽々SSL](https://qiita.com/ProjectEuropa/items/37b0cfbe0d2347d8e16a)と一緒です。

```
brew install mkcert
mkcert -install
mkcert localhost 127.0.0.1
```

`localhost+1.pem` `localhost+1-key.pem`が生成される。

`./cert-key/localhost.pem`
`./cert-key/localhost-key.pem`
に置いておきましょう。
名称は何でもいいですが、
ここでは**localhost+1.pem**から**localhost.pem**
**localhost+1-key.pem**から**localhost-key.pem**
に名称を変えています。

## docker-compose.ymlの記述

```docker-compose.yml
version: "3"
services: 
  nginx:
    build: ./
    ports:
      - 80:80
      - 443:443
```

## Dockerfileの記述

```dockerfile
FROM nginx:alpine

COPY nginx.conf /etc/nginx/nginx.conf
ADD ./cert-key/localhost.pem /etc/certs/localhost.pem
ADD ./cert-key/localhost-key.pem /etc/certs/localhost-key.pem
```

## nginx.confの記述

```conf
events{
}
http{
    server {
        listen 80 default;
        server_name localhost; 
    }
    server {
        listen 443 ssl;
        ssl_certificate /etc/certs/localhost.pem;
        ssl_certificate_key /etc/certs/localhost-key.pem; 
    }
}
```

`events`がないと
`no "events" section in configuration`とエラーがでます。

## docker-compose の起動

```
docker-compose build
docker-compose up -d
```
でdocker-composeを起動する。

[localhost](https://localhost/)にアクセスしてhttpsでも表示できれば成功。

<img width="898" alt="スクリーンショット 2019-07-29 13.55.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133718/00051432-cceb-94d8-7905-c347208d1bcb.png">
【rails】ブラウザのタブに好きなアイコン(favicon)を設定する

#はじめに
 アプリを作っているときに、ブラウザのタブのアイコンが無いことに違和感を覚えたので、調べて設定してみました。
 調べたところ、`favicon(ファビコン)`を設定すれば簡単に設定できることが分かりました。
<img width="206" alt="460a366dc6362e55cdb39eb5c3e82d3f.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456505/4176fbca-745f-d8a4-e4f1-40d98d9053a6.png">

#好きな画像をfavionに変換
[こちらのサイト](https://ao-system.net/favicon/)に行き好きな画像を`favicon`に変換します。

ファイル指定後、下にある`favicon.ico作成`ボタンを押した後、`ダウンロード`ボタンを押します。
ダウンロードした`favicon.ico`を、railsの`image`フォルダに保存してください。

#コードを追加
あとは、`application.html.erb`の`<header>`内に、以下のコードを追加するだけです。

```erb:application.html.erb
<%= favicon_link_tag 'favicon.ico' %>
```

**これで、faviconが設定できます！**
AWS EC2インスタンスへのbrowser-based SSH connectionのやり方

#AWS EC2インスタンスへのbrowser-based SSH connectionのやり方

こんなのがありました。AWSのブラウザ上でSSH接続できる。
![Screenshot from 2019-07-29 13-31-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/c218d2d1-7423-6d0b-dc83-df8e068a1608.png)

![Screenshot from 2019-07-29 13-33-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/39f97ca3-1b27-2252-8b21-2706a6e3bc7e.png)
しかしこのままConnectボタンをクリックしてもTry againとエラーメッセージが出て使えない。
どうやらEC2 Instance Connectというものをインストールしなければならないようだ。
公式サイト：[New: Using Amazon EC2 Instance Connect for SSH access to your EC2 Instances](https://aws.amazon.com/blogs/compute/new-using-amazon-ec2-instance-connect-for-ssh-access-to-your-ec2-instances/)

公式サイトにはいろいろ書いてあるが、EC2 Instance ConnectをEC2インスタンスにインストールするだけでうまくいった。

[AWS EC2インスタンスへのSSH接続の仕方](https://qiita.com/atomyah/items/01e3a56cdee1c0d12665)でSSH接続したら、以下のコマンドを走らせる。

```bash
$ sudo apt install ec2-instance-connect
```
(Fedra系はyumで）

<br>
以上です:grinning:
![Screenshot from 2019-07-29 13-40-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/9f283e79-bd2b-8c1d-6c4c-af49a0ec6a03.png)


443ポートを開けるとか（自分ひとりで使うなら）IAMで新しくポリシーを作るとかいらないです。
<br>
文系学生のプログラミング学習8日目ーPythonで再帰をやってみたー


今回はPythonで再帰をやってみました。
再帰による回文判定とFractal図形を描きました。

#回文判定

再帰をつかった回文判定です。

```
def palindrom(string):
    if len(string) < 2:
     return("true")
    elif string[0] == string[len(string)-1]:
     return(palindrom(string[1:len(string)-1]))
    else:
     return("false")
```

if len(string) < 2 といのがbase caseといって最も基本的なパターンになります。
それ以降がrecursive caseで再帰をしていく部分になります。
１文字の場合もちろんtrue。複数文字の時は最初の文字と最後の文字が同じ場合、再帰をつかって２番目と最後から２番目を比較します。
初めは再帰が何なのか分かりにくかったので、自分の書いた再帰のコードが上手く動くととてもうれしいです。


#Fractal図形

再帰をつかって同じ図形を何個も連続して描くことが出来ます。上手くいくと模様のようになってとてもきれいです。

```
import turtle as t

def fractal(n, size):
    if n == 1:
        t.forward(size)
    else:
        t.left(45)
        fractal(n - 1, size)
        t.right(90)
        fractal(n - 1, size)
        t.left(45)

```

はじめにturtleという図形を描くものをimportします。
nは図形のレベルみたいなもので、１回ごとにレベルを１つずつさげていき、n=１になるとスクリプトが止まります。

n=3の場合以下のような図形が出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407598/fdfae672-9bb1-7c60-e237-079c1105d077.png)


これをn=7にすると以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407598/0c7ebefd-6139-5efc-9a9a-77c1080e5965.png)


n=3の図形がいくつも組み合わさっていることが分かります。
この図形の他にも雪の結晶のような図形も作成できます。

自分のやったことをブログで伝えるのって本当に難しいということを最近実感します。
頭では分かっていても、言葉で書くって難しいですね。

終わり
KMSの、IAM含めた権限まわりの挙動

インスタンスの開始(StartInstances)
・[IAM Admini][KMS policy none] -> OK
・[IAM 「KMS Power」][KMS none] -> NG
・[IAM 「KMS Power」][KMS 「キーユーザー」] -> OK
・[IAM none][KMS 「キーユーザー」] -> OK
・[IAM CreateGrantだけ][KMS none] -> OK

そもそもの前提として、今回実験で使用したCMKはデフォルトで画面で作ったまま、ユーザ周りの設定しか変えていない。そのようなCMKでは、
https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam

```json
{
  "Sid": "Enable IAM User Permissions",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:root"},
  "Action": "kms:*",
  "Resource": "*"
}
```

のようなキーポリシー（KMS上概念、not IAM概念）が含まれている。これはどういう意味かというと、
「IAMポリシー側で、CreateGrantなど各権限がついていたら、その権限についてはKMSでも許可します」という意味だと思われる。
Progate の Ruby on Rails コース Ⅺ で  bcrypt のエラーが頻発した時

Gemfileの最後に以下を追加

```
gem 'bcrypt'
```

```
bundle install
```

```
rails g  migration change_users_columns
```

```20190728171409_change_users_columns.rb
class ChangeUsersColumns < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :password_digest, :string
    remove_column :users, :password, :string
  end
end
```

```console
$rails console

irb(main):001:0> user = User.find_by(id: 1)
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "takuya", email: "takuya-matsuda@prog-8.com", created_at: "2019-07-21 04:20:44", updated_at: "2019-07-21 07:35:38", image_name: "1.jpg", password_digest: nil>
irb(main):002:0> user.password = "ninjawanko"
=> "ninjawanko"

irb(main):003:0> user.save
   (0.1ms)  begin transaction
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ?  [["email", "takuya-matsuda@prog-8.com"], ["id", 1], ["LIMIT", 1]]
  User Update (0.5ms)  UPDATE "users" SET "updated_at" = ?, "password_digest" = ? WHERE "users"."id" = ?  [["updated_at", "2019-07-29 03:58:04.111440"], ["password_digest", "$2a$12$k6loAsf7Y1OxYh.bdzihhew2jaSqZL/9M5Zck6rbYk3S5TUWRw7tG"], ["id", 1]]
   (2.7ms)  commit transaction
=> true
```

```user.rb
class User < ApplicationRecord
  has_secure_password # いきなりこの書き方をするので戸惑いガチ
  
  validates :name, {presence: true}
  validates :email, {presence: true, uniqueness: true}

  def posts
    return Post.where(user_id: self.id)
  end
end
```

これでこのレッスンは終了だが、この状態でログインしようとするとpasswordカラムがなくなったことによるエラーがでる。それは次のレッスンの以下のコードに編集することでなくなる。

```user_controller.rb
def login
    @user = User.find_by(email: params[:email])
    if @user && @user.authenticate(params[:password])
      session[:user_id] = @user.id
      flash[:notice] = "ログインしました"
      redirect_to("/posts/index")
    else
      @error_message = "メールアドレスまたはパスワードが間違っています"
      @email = params[:email]
      @password = params[:password]
      render("users/login_form")
    end
  end
```
【obniz】自分だけのコントローラで遊べるPvPブラウザゲームを作った

# はじめに
[obniz](https://obniz.io/)を使えば，HTMLとJavaScriptでかんたんにマイコンを扱うことができてしまいます．さらにobnizはオンラインで書き込んで実行できるので，買ってきて即IoT！なんてことも可能です．
![product_obnizboard.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468679/b8757d17-4b7f-b1f6-72e2-db701cb43997.jpeg)
(https://obniz.io/ja/products)

とはいえ，アイデアのほうはそう簡単に出てこないものです(僕がそうでした:fearful:)．

そこで，いろんな人がobnizを触るきっかけになればいいなと思い，obnizを使って遊べる簡単な対人ゲームを作ってみました！
[obniz-park](https://obniz-park--takasago.repl.co/)
この記事では，obniz IDによるログインの実装と，ゲームの楽しみ方について書きます．

# obniz IDによるログイン
今回作ったゲームの対象ユーザーは「[obniz board](https://obniz.io/ja/products)を持っている人」なので，専用のログインフォームをつけてみました．
<img width="561" alt="login.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468679/7332bb1a-4d61-9fcd-8487-50479c608700.png">
obniz boardをお持ちの方はご存知かと思いますが，obniz boardにはobniz IDという固有の数字がそれぞれに割り当てられています．また，アクセストークンを発行することで不正な利用を防ぐことも可能です．
これらを入れるだけでゲームは始められます．obniz boardが入場チケットになっているようなイメージで，発想次第ではもっと面白いことができそうな気がしています！
この仕組みは以下のような流れで作られています．

<img width="396" alt="スクリーンショット 2019-07-29 11.54.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468679/1e27e241-23f2-a292-ab31-fe0ec4d60f59.png">

今回のようにユーザの記録をデータベースに保存するなどの永続化をしない場合，obnizへの接続だけで本人確認が完了します．つまり，クライアント(JavaScript)だけでログインが作れてしまいます！
実際のコードは以下のようになっています：

```JavaScript:login.js
obniz = new Obniz("<OBNIZ_ID>", {
    auto_connect: false,
    access_token: "<ACCESS_TOKEN>"
});
tryConnect(obniz);

// 接続判定をする関数
async function tryConnect(obniz) {
    let connected = await obniz.connectWait();
    if (connected) {
        // ログイン成功処理
    } else {
        alert("ログインに失敗しました。やり直してください。");
        // ログイン失敗処理
    }
}
```
[公式ドキュメント(obniz connection)](https://obniz.io/ja/doc/sdk/doc/connection)によると，`new Obniz()`時に`auto_connect`を`false`にしておくことで，自動接続を切ることができます．
これに加え，`obniz.connectWait()`を使うことで，接続可能かどうかを真偽値で判断できます．今回はこれを利用して接続判定を行いました．

# 遊び方
[obniz-park](https://obniz-park--takasago.repl.co/)
遊ぶ時に必要なものは：

- obniz
- 使いたいセンサー
- obnizとセンサーを繋げるために必要なコード片

だけです．
ログイン後のゲーム画面は以下のようになっています．パックマン:no_mouth:みたいなイメージです．
<img width="861" alt="park.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468679/c9aa1d4a-c7c1-a26d-5a7a-46554c43314f.png">
画面上部の灰色のエリアがゲーム画面で，水色の正方形が自機となっています．自機を動かして黄色いドットに触れていくことでスコアが上がっていきます．このスコアは同時に接続しているユーザと競うことができ，スコアとランクがゲーム画面下部に表示されます．
どうやって自機を操作するのかは，あなたの持っているセンサーと書くプログラム次第です．画面下部のエディタでプログラミングを行います．そんなに難しいことはなく，センサ値と上下左右の移動を結びつけるだけです．初期状態ではジョイスティックを接続した場合のプログラム例が記入されているので参考にしてみてください．エディタ上部のAPPLYボタンでプログラムを反映でき，RESETボタンで書き込んだプログラムを解除できます．
具体的なコード記述の説明は[こちら](https://github.com/takasa5/obniz-park)のREADMEから読めます．
他にも，ジャイロセンサを使って傾けて動かすなど，面白そうなコントローラが作れそうです．[GitHub](https://github.com/takasa5/obniz-park/blob/master/static/example.js)にいくつかサンプルも公開しています．
**重たい処理を書くとブラウザが止まってしまう恐れがあります．自己責任でお願いします:frowning2:**

# おわりに
obnizがインターネットに簡単に繋げる性質を使って，obnizユーザがオンラインで集まってワイワイできるようなものを作ってみたいという試みでした．
実際にやってみていただけるとわかりますが，PvPのためのWebSocket通信送受信による操作ラグが結構あってストレスフルです．もっとうまい実装ができればよかったのですが…要勉強です．
お読みくださりありがとうございました．指摘やアドバイスなどありましたらコメントなどよろしくお願いします．
Railsのautoload_pathの中身を表示する

## Railsでautoloadパスを追加
appの下にserviceクラスを作った時など、`application.rb`に`config/application.rb`を追加した。

```config/application.rb
config.autoload_paths += %W(
  #{config.root}/lib/
  #{config.root}/app/services/
)
```
ただし、実際これでちゃんと読み込めているのか不安になる。
今まではわざわざconsoleで`lib`の下などの関数が動くか試していた。

## ActiveSupport::Dependenciesを呼び出す
gem `active_support`の中のmodlue `ActiveSupport::Dependencies`のコードを見てみると、

```
mattr_accessor :autoload_paths, default: []
```
とあり、外部から`autoload_paths`にアクセスできる。これをconsoleで呼び出せば、autoload_pathの中身が見れるようだ。

```ruby

[1] pry(main)> ActiveSupport::Dependencies.autoload_paths
=> ["/var/www/{service_name}/lib/",
    "/var/www/{service_name}/app/services/",
    "/var/www/{service_name}/app/assets",
    "/var/www/{service_name}/app/controllers",
    "/var/www/{service_name}/app/controllers/concerns",
    "/var/www/{service_name}/app/helpers",
    "/var/www/{service_name}/app/jobs",
    "/var/www/{service_name}/app/models",
    "/var/www/{service_name}/app/models/concerns",
    "/bundle/gems/devise-4.6.2/app/controllers",
    "/bundle/gems/devise-4.6.2/app/helpers",
    "/bundle/gems/devise-4.6.2/app/mailers",
    "/bundle/gems/activestorage-5.2.3/app/assets",
...
```
これで毎回関数を呼ばずにちゃんと読み込まれていることがわかる。安心安心。

## 備考
configの設定を変えた後は、consoleで`reload!`をしても反映されない。
`application.rb`を変更した後は再度`rails c`する必要がある。
ログオフ時間をコマンドで取る

勤怠データ用に退勤時間(=ログオフ時刻)をまとめて取りたい。
イベントビューア重いからね。

```powershell

Get-EventLog system -After 2019-07-01 | Where-Object {$_.EventID -eq 7002} | Sort-Object Index | Select-Object TimeGenerated
```

・Afterの時間を設定することで任意の時間が取れる。
・必要なら-beforeを使って範囲指定してもよい。
・EventIdはログオフを意味する7002を指定。ログインなら7001を指定する。
AWS CodeDeploy用appspec.yml「hooks」セクション用スクリプトにてタグの値を環境変数として利用する方法

以下、AWS公式ページにて、デプロイライフサイクルに対応したスクリプトと利用できる環境変数群が指定されている。 
 https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html#appspec-hooks-server

ただ、公式ページのやり方だと、`DEPLOYMENT_GROUP_NAME` というデプロイメントグループ名を表すための環境変数を使って、そのEC2インスタンスがproductionなのかstagingなのかを判別する方法のみ記載されており、デプロイメントグループを直書きする気持ち悪さと、無駄なif文が記述されてしまう。

「hooks」セクション用スクリプト(シェル)にてタグの値を環境変数として利用する方法を探してみたので、メモとして残しておく。

# 対応の概要
以下の3ステップを順番に対応する。

1. aws-cliがEC2上で利用できるようにする。
2. aws-cliの「フィルター」と「クエリー」の検索条件となり得る値を準備する。
3. aws-cliの機能「フィルター」と「クエリー」を活用したロジックを「hooks」セクション用スクリプト(シェル)に記述

# 1. aws-cliがEC2上で利用できるようにする。
AWSコンソールからIAMの管理画面に移動して、グループを作成 → EC2操作をできるロールをグループにアタッチ(今回は、AmazonEC2FullAccess) → ユーザーを作成(アクセスキーをダウンロード) → 作成したグループにユーザーを追加

個人的には、`Amazon Linux 2 AMI (HVM), SSD Volume Type`という無料のマシンイメージを活用しているので、EC2上にssh接続して、以下コマンドを実行してaws-cliにする。
`sudo yum install -y aws-cli`

aws-cliをインストールしたら、そのままEC2上で先ほど作成したユーザーのアクセスキー情報を設定する。
`aws configure`
※以下の文言が順次表示するので設定する

~~~
AWS Access Key ID [None]: <IAMでのCodeDeploy用ユーザー作成でメモしたアクセスキーID>
AWS Secret Access Key [None]: <IAMでのCodeDeploy用ユーザー作成でメモしたシークレットアクセスキーID>
Default region name [None]: ap-northeast-1
Default output format [None]: json
~~~

# 2. aws-cliの「フィルター」と「クエリー」の検索条件となり得る値を準備する。

結論としては、インスタンスメタデータから、稼働中のEC2のインスタンスIDをaws-cliの「フィルター」と「クエリー」の検索条件として活用するようにする。 

試しに、EC2上でインスタンスIDを取得するために以下コマンドを実行
`curl -s http://169.254.169.254/latest/meta-data/instance-id`

※169.254.169.254はリンクローカルアドレスで、インスタンスからのみ有効
※現在接続しているEC２インスタンスIDが表示されればOK

参考： 
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

# 3. aws-cliの機能「フィルター」と「クエリー」を活用したロジックを「hooks」セクション用スクリプト(シェル)に記述

~~~Node.js:Node.jsでのEC2に設定したタグを活用した環境変数設定例（シェル）
# instance メタデータから対象EC2インスタンスのインスタンスID情報をfetch
# NOTE: 詳細：https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)

# インスタンスIDを介してEC2インスタンスのタグ情報(NodeEnv)の値を取得
EXPORT_ENV=$(aws ec2 describe-tags \
             --filters "Name=resource-type,Values=instance" "Name=resource-id,Values=$INSTANCE_ID" "Name=tag-key,Values=NodeEnv" \
             --query 'Tags[]|[0].Value')

export NODE_ENV=$EXPORT_ENV
~~~

# 後述
aws-cliの「フィルター」と「クエリー」の検索条件となり得る値を準備するのに大変苦労した。
最初は、`hostname -I` して取得したIPアドレスを使って、以下のように検索条件となり得る値を調べようと以下のような記述を試していた。

~~~
INSTANCE_ID=$(hostname -I)

# インスタンスIDを介してEC2インスタンスのタグ情報(NodeEnv)の値を取得
EXPORT_ENV=$(aws ec2 describe-instances \
                     --query 'Reservations[].Instances[?PrivateIpAddress==`$INSTANCE_ID`]|[0][0].Tags[]|[0].Value')

~~~
しかし、`$INSTANCE_ID`という記述箇所がバッククォートに囲まれているためなのか、変数に設定したIPアドレスが意に沿う形で展開されず、この方法では実現できなかった。。。

他に最適なやり方があったら、ぜひ知りたいと思う。
【Clojure入門備忘録】apply関数

Clojure入門中です。Scalaをやっていたので、Scalaのapplyとは明らかに異なるapply関数に戸惑いました。
そこでメンターが色々と教えてくれたので、咀嚼するために（+世の中に還元できたらいいなという気持ちで)軽くまとめました。


## Clojureにおけるapplyとは
可変長引数と対になるようなもので、最終引数のシーケンスの中身を取り出して適用してくれる。

まあ概要はこんな感じ。以下で説明していく。

## そもそも可変長引数ってどんなのだっけ
可変長引数(variable argument)とは、関数に与えた0個以上の実引数を1つのシーケンス(≒リストのようなもの)にまとめてくれるもの。

### `& <名前>` で可変長引数にできる

```clojure:まあこんな感じ
dev> (defn hello [& who]
  (println who))
#'dev/hello
dev> (hello "hoge")
(hoge)
nil
dev> (hello "hoge" "hoge")
(hoge hoge)
nil
```

### 標準ライブラリの`+`, `-`, `*`, `/` も可変長引数関数
```clojure:まあこんな感じ
dev> (+)
0
dev> (+ 0)
0
dev> (+ 1 2)
3
dev> (+ 1 (- 1 2 3) (* 1 2 3))
3
```

## で、可変長引数だと何ができないのか
ベクター `[1 2 3]` があって可変長引数関数 `+` を適用しようとしたとき、単純に適用することはできない。

```clojure:まあこんな感じ
dev> (let [xs [1 2 3]]
       (+ xs))
Execution error (ClassCastException) at java.lang.Class/cast (Class.java:3606).
Cannot cast clojure.lang.PersistentVector to java.lang.Number
```
`+` は引数として0個以上の数値(`java.lang.Number`)型の値を期待している。
とはいえ、ベクターの個々の要素を手でバラバラにして適用するのは汎用性に欠ける :innocent:

そこで `apply` の出番。

## じゃあapplyをどうやって使う？
シンプルに `apply` をつければいい。

```clojure:まあこんな感じ
dev> (apply + 1 2 3 [4 5])
15
dev> (apply + [1 2 3 4 5])
15
```
上記はいずれも(+ 1 2 3 4 5) と等価である。
Clojureでは標準ライブラリ関数にも可変長引数関数がとても多いらしく、コレクション(シーケンス)に可変長引数関数を適用したい状況で `apply` をよく使うとのこと。

## 最後に
勉強したことを整理するために備忘録的に書きました。
何か間違っていることや補足したい点があったら優しくマサカリを投げてください。
もっと簡単にDockerでNuxt.jsを始めてみる(続Dockerでローカル環境を汚さずにNuxt.jsを始めてみる)

# 背景

[Dockerでローカル環境を汚さずにNuxt.jsを始めてみる
](https://qiita.com/ProjectEuropa/items/d9ee1b8c96084e3bab55)がだいぶ古くなってきたので、もっと簡単にやってみる。

## 試した環境
Docker for Mac (macOS Mojave)

## docker-compose.ymlの記述

```yml
version: "3"
services: 
  node:
    build: ./
    working_dir: /home/node/app
    volumes:
      - ./:/home/node/app
    ports: 
      - 3001:3000
    environment: 
      - HOST=0.0.0.0
```

## Dockerfileの記述

```dockerfile
FROM node:10.16.0-alpine

RUN npm install -g @vue/cli nuxt create-nuxt-app
```

docker-compose.ymlの同ディレクトリで以下を実行

```shell
docker-compose build 
docker-compose run node npx create-nuxt-app ./ #選択肢は適当に
```

create-nuxt-appが終了したらば、

```
docker-compose run --service-ports node npm run dev
```
[docker-compose runそのまま使うとポートフォワーディングが聞かない問題](https://github.com/docker/compose/issues/1259)があるので`--service-ports`をオプションにつける。

[localhost:3001](http://localhost:3001/)
[![Image from Gyazo](https://i.gyazo.com/8d5d44c38ff01b5c1463c056ad8b429a.png)](https://gyazo.com/8d5d44c38ff01b5c1463c056ad8b429a)にアクセスしてデフォルト画面が出れば完了。

## 更新

[DockerでNuxt.js on TypeScriptを始めてみよう
](https://qiita.com/ProjectEuropa/items/87e859866d378f00564c)TypeScriptを導入してみました。

[レンタルサーバーFTPでもTravis CI使ってCIしたい](https://qiita.com/ProjectEuropa/items/7f2370b4a8d024d6e97c)
レンタルサーバーFTPでもCIを導入してみました。
1秒で分かる joins, includes, preload, eager_load

## 1秒で分かる部分

| メソッド     | テーブル結合    | クエリ | 条件絞り込み | Association キャッシュ | 使い所                                                                      |
|--------------|-----------------|--------|--------------|------------------------|-----------------------------------------------------------------------------|
| `joins`      | INNER JOIN      | 1      | ○            | ☓                      | 条件絞り込み                                                                |
| `left_join`  | LEFT OUTER JOIN | 1      | ○            | ☓                      | 条件絞り込み                                                                |
| `eager_load` | LEFT OUTER JOIN | 1      | ○            | ○                      | Assiociation先をRubyで読む                                                  |
| `preload`    | なし            | 1以上  | ☓            | ○                      | 複数Assiciationを先読みしておく場合。複雑なJOINでslow queryになるような場合 |
| `includes`   | 場合による      | 1以上  | 場合による   | ○                      | eager_loadかpreloadを使い分けてる                                           |

## 参考

- https://qiita.com/k0kubun/items/80c5a5494f53bb88dc58
- https://moneyforward.com/engineers_blog/2019/04/02/activerecord-includes-preload-eagerload/
【JavaScript修行】promiseループですごい詰まった

何に詰まったかというと、forループ内でプロミスを回そうとして全然上手くいかなかったんです。

```javascript
function(){
   for(let i=0,i<DATA_DAYS;i++){
      fetch(~~)
      .then(res=>
     //~~~省略~~~
```
これじゃ上手く行きませんよね。
全部のforが回ってから動かす、っていうのがどうも難しくて悪戦苦闘。そしてこの記事を見つけました。

https://qiita.com/progre/items/5666f4a333cc2d032d15
まさに探していた内容が！
forでとった１つ１つのプロミスを`Promise.all`を使って
確認するというものです。

>```javascript
var promises = [];
for (var i = 0; i < takusan; i++) {
    promises.push(omotaiPromise(i));
}
Promise.all(promises)
    .then(function (results) {
        // results配列の各要素で結果が取れる
    });
```

これを参考にしつつ、見事抜き出したかった配列を作ることができました。

```javascript:完成
let promises = [];
for(let i=0;i<DATA_DAYS;i++){
  promises[i]=
    fetches.fetchNHK(i)
    .then(res=>{
      count[i] = res.list.e1.length;
      day[i] = moment(i,'days').format('MM月DD日');
    })
}

Promise.all(promises)
.then(res =>{
// 以下配列を使った処理
}
```

すごいぜ！

##追記 async/awaitでかく
`async/await`でかくとかなりにスッキリとしたコードになりました。

```javascript:async/await
async function forFethches(){
  for(let i=0;i<DATA_DAYS;i++){
      await fetches.fetchNHK(i)
      .then(res=>{
        count[i] = res.list.e1.length;
        day[i] = moment(i,'days').format('MM月DD日');
      })
  }
}

forFethches()
.then(res =>{
   //配列に対しての処理
})
```
`async/await`も使いこなせるようにならないとな、と思いました。
@megmism さんありがとうございました！
PayPal でゲスト決済を許可するならサポートに電話しよう

## 設定をオンにしても許可されない？
PayPal アカウント不要（また作成不要）でクレジットカード決済を許可するためには、アカウント設定以下の「PayPalアカウントプションサービスをオン」にする必要があると案内されています。しかし日本では（？）決済ユーザーやセラーアカウント利用状況などに左右されるが、設定オンだけではゲスト決済は許可されないらしい。

#### ※公式情報 
[PayPal アカウントの設定ポイント - Qiita](https://qiita.com/PPJP/items/9b089d44d48c9b245eb3#%E5%A3%B2%E3%82%8A%E6%89%8B%E4%BF%9D%E8%AD%B7%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8B%E8%A8%AD%E5%AE%9A)
[Enable guest payments - PayPal Developer](https://developer.paypal.com/docs/integration/direct/payments/guest-payments/#)

## カスタマーサポートに依頼すると許可設定をしてくれる
そこでカスタマーサポートに連絡して「ゲスト決済を可能にしたい」と依頼すると、担当や話し方にもよるが「設定変更の申請をする」と返答がもらえる。このゲスト決済有効設定は隠し設定らしく電話での依頼でしか対応していないとのこと。24時間ほどで設定完了の連絡がくる。

## 注意：ゲスト決済をされたものは売り手保護対象から外れる
注意すべきはゲスト決済では売り手保護がなくなる点である。完全に保護されないとなるとその他の決済代行サービスより見劣りする状態になる。簡単にオフにできない隠し設定であり、適用範囲の制御もできない。日本では表に出していないのは、むやみな利用を制限し売り手保護を優先しているからだろう。


## 結論
カスタマーサポートで対応してもらえるが、是が非でもゲスト決済を有効にしたい場合以外に利用するのは避けた方が良い。
[Linux]ファイル名にコマンド実行日時を差し込む方法

## はじめに
mysql の dump 生成時に毎回ファイルの生成日時を手でファイル名に加えていましたが、どうにかならんものかと思って調べてみたらすでに先人からすばらしいヒントが残されておりました。**Linux ではバッククオートされた文字列はコマンドとして解釈されるそうです。**

参考：
[Linuxのシェルやコマンドにおけるバッククォートの使い方 | UX MILK](https://uxmilk.jp/27649)

> シングルクォートは囲った中身を文字列として主力するのに対して、バッククォートは囲った中身をコマンドとして実行しその結果を出力します。

## つまり
こういうことが可能です。

```sh:bash
# ファイル生成
$ touch my_text_`date "+%Y_%m_%d_%H_%M_%S"`.txt

# 確認
$ ls
my_text_2019_07_25_23_04_22.txt
```

```sh:$(...)版（これでもOK）
$ touch my_text_$(date "+%Y_%m_%d_%H_%M_%S").txt
```


`date "+%Y_%m_%d_%H_%M_%S"` で取得した日付時刻の文字列をそのままファイル名に使うことができています。これと同じことを mysql の dump 実行時に出力するファイル名に指定すれば、ファイル名にコマンド実行時の日付時刻を含めることが可能ということです。

```sh:使用例(※mysqldumpコマンドの細かいオプションは省略)
mysqldump -uxxxxxx -pxxxxxx --databases some_db_name > /path/to/my_dump_`date "+%Y%m%d_%H%M%S"`.dump
```

こんなかんじですね。やったぜ！

## ちなみに
なお、個人的には `$(...)` のほうがバッククオートよりもコマンドを実行している感があってわかりやすいとおもいました。(あくまで個人の感想です)
LogAnalyticsのデータ取得時間の調査方法

こんにちは、kc-dreamです。
前回の記事に引き続き、LogAnalyticsについての補足を書いていきます。

##LogAnalyticsのデータ取得時間の調査方法
LogAnalyticsは各種環境のデータを収集/分析するためのサービスです。
Azure基盤で各種データを収集するので、タイミングによってはデータの取得までに時間がかかることがあります。

例えば、LogAnalyticsを使用してアラートを設定している場合、データの取得時間及びしきい値によってアラートが発報してしまう可能性があります。
そういった場合にデータ取得にかかった時間を調べるためのqueryが用意されているので、本記事で紹介します。

###SampleQuery
```rb
Heartbeat
| where TimeGenerated between(datetime(20yy-mm-ddT00:00:00) .. datetime(20yy-mm-ddT00:00:00))
| extend IngestionLatency = ingestion_time() - TimeGenerated
```

上記はHeartbeatのデータ取得にかかった時間を調べるSampleQueryです。


```rb
Heartbeat
| where TimeGenerated between(datetime(20yy-mm-ddT00:00:00) .. datetime(20yy-mm-ddT00:00:00))
#TimeGenerated=エージェントがデータの送信を行った時間

| extend IngestionLatency = ingestion_time() - TimeGenerated
#IngestionlLatency=取り込みにかかった時間
#ingestion_time()=データが取り込まれた時間
```
取得時間は[*ingestion_time()*]から[*TimeGenerated*]を差し引いた値からデータの取り込みに要した時間を算出可能です。

##参考情報
[Azure Monitor でのログ データ インジェスト時間](https://docs.microsoft.com/ja-jp/azure/azure-monitor/platform/data-ingestion-time)

[Azure LogAnalytics 概要についてまとめてみた](https://qiita.com/kc-Dream/items/c91cbe7deb61ba96707d)

[Azure LogAnalyticsでWindowsServerを監視してみた](https://qiita.com/kc-Dream/items/e1ffed2b9be931bb73a0)
pgAdmin4を日本語化する

pgAdminをインストールしたら、英語表記だったので日本語に直しちゃいましたー
備忘録を兼ねての投稿です。


① [File ] - [ Preferences ] を選択する。 
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401570/2757a543-04b0-6ecb-eeaa-1d324aebd256.png)

② [ Miscellaneous ] - [ User language ] を選択する。
　右ペインにある[ User language ] を [ Japanese ] に変更する。
　右下の[ Save ] を押下する。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401570/8a66fa79-e226-51cc-8fea-7f695356c750.png)

③ [ F5 ] キーを押下し、画面更新をする。

日本語化完了。
[Swift 5]UISearchBarのクリアボタン(X)が押された時の動作を実装する

UISearchBarを使ってインクリメンタルサーチを実装している時の備忘録です。

検索文字を入力すると、SearchBar内にクリアボタンが表示されます。



そのクリアボタンを押すと、入力テキストが削除されますが、

その時、検索結果を操作したいですよね。



しかし、検索した限りでは、UITextFieldでいうの`textFieldShouldClear(_ textField: UITextField) -> Bool`のようなメソッドが見当たりませんでした。見逃しているだけだったら、すみません。

そこで、UISearchBarDelegateの`searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)`を使用することにしました。

```swift
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        results.removeAll()
    }
}
```

やっていることは極簡単です。

検索テキストが変更された時、検索文字列が空であれば、という条件を設ければOKです。

こうすることで、クリアボタンを押した際に`if searchText.isEmpty`の中身が実行されます。

参考：https://stackoverflow.com/questions/29135594/uisearchbar-x-button-pressed
JFreeChart-積上げバーチャート-UIで特定データを強調する


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java

package jp.avaj.lib.chart;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.data.category.DefaultCategoryDataset;

/**
■ JFreeChart-積上げバーチャート-UIで特定データを強調する

・積上げバーチャートは、合計の変化はよく見ることができる.
・しかし一番下のデータ以外は変化が分かりにくい.これを他のデータの変化も見えるようにしたい.
・ArcStackedBarChartEmphasizeWinでデータ選択画面を表示し、選択されたデータの折れ線グラフを積上げバーチャートの上に表示する.

 */
public class Chart08_04 {
  // 目次-積上げバーチャート(StackedBarChart)
  A_Chart08 a_Chart08;
  // 目次-Artery-JFreeChart用のライブラリ
  A_Chart00 a_LibChartSampeContents;

  public static void main(String[] args) {
    // 表示データの作成
    DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
    {
      //
      dataSet.addValue(136.5,"商品A","2016");
      dataSet.addValue(206.1,"商品A","2017");
      dataSet.addValue(296.7,"商品A","2018");
      //
      dataSet.addValue( 40.5,"商品B","2016");
      dataSet.addValue(105.7,"商品B","2017");
      dataSet.addValue(199.4,"商品B","2018");
      //
      dataSet.addValue(150.5,"商品C","2016");
      dataSet.addValue(87.5,"商品C","2017");
      dataSet.addValue(40.0,"商品C","2018");
    }
    //
    CategoryAxis catAxis = new CategoryAxis();
    NumberAxis numAxis = new NumberAxis();
    // 積上棒グラフにはStackedBarRendererを使用する
    StackedBarRenderer renderer = new StackedBarRenderer();
    CategoryPlot catPlot = new CategoryPlot(dataSet,catAxis,numAxis,(CategoryItemRenderer)renderer); // (1)
    JFreeChart jfreeChart = new JFreeChart("売上構成の変化",(Plot)catPlot);
    //
    ChartFrame cFrame = new ChartFrame("売上構成の変化",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);

    // 特定商品の売り上げを抽出⇒折れ線グラフを追加する
    new ArcStackedBarChartEmphasizeWin(cFrame,catPlot);
  }
}


```
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/5e60d133-e8af-1021-784b-eeaf22f4888c.png)
Coral USB TPU AcceleratorをWindows端末で(疑似的に)使ってリアルタイムで物体検知をする

## 【目的】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/1b241581-35d3-f926-cb72-003046d42133.png)
Coral USB TPU AcceleratorをWindows端末で(疑似的に)使ってリアルタイムで物体検知できるようにします。


## 【内容】
[【Coral USB TPU AcceleratorをWindows端末で(疑似的に)使う (VirtuaBox編)】](https://qiita.com/rhene/items/e7574715844784b86a15)の続きです。
Coral社提供のサンプルプログラムを使ったリアルタイム物体検知がうまく動かなかったので、再挑戦します。


## 【VMにWebカメラを認識させる】
まずはVMにWebカメラを認識させます。
[【Coral USB TPU AcceleratorをWindows端末で(疑似的に)使う (VirtuaBox編)】](https://qiita.com/rhene/items/e7574715844784b86a15)で作ったVMを実行した状態で、以下の操作を行います。

- [デバイス]＞[Webカメラ]＞[<使いたいカメラを選択>]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/efa5585f-b759-2f1d-87d9-e34c9ad32599.png)

上記の操作を行った上で、VM上でターミナル画面を開き以下のコマンドを実行します。

```bash:check_video
ls /dev/video*
```
以下のような表示が返ってくればUSBカメラを認識しています。

```bash:check_video_結果
/dev/video0  /dev/video1
```

## 【物体検知用のプログラムの作成】
公式が提供している[gstreamerを使ったサンプル](https://github.com/google-coral/examples-camera/tree/master/gstreamer)を実行してみましたが、うまく動かすことができませんでした。
OpenCVのVideoCaptureができることは確認していたので自作しようと思いましたが、時間の関係(言い訳)で下記の記事の「MobileNet-SSD-TPU-sync.py」を利用させていただきました。
[【RaspberryPi3(USB2.0)とLaptopPC(USB3.1)でGoogle Edge TPU Acceleratorを使用してMobileNet-SSD v2の動作スピードを検証してみました（MS-COCO）】](https://qiita.com/PINTO/items/dd6ba67643bdd3a0e595)

ちなみについ先日、[【github - google-coral】](https://github.com/google-coral/examples-camera)が更新されてOpenCV用のサンプルが追加されていましたが、イマイチなんですよね…

プログラムの内容的には、OpenCVのVideoCaptureを使ってカメラ画像を取得し、取得した画像をTPUの物体検出モデルに投入し、結果をBoundingBoxで表示しています。
今回利用したモデルは「MobileNet SSD v2」という、モバイルデバイスでも使えるように軽量化したモデルです。
高速で比較的高精度の認識ができるのが特徴です。


## 【プログラムの実行】
下記コマンドを実行することで、上記で保存したプログラムを実行します。

```bash:run_ssd
python3 MobileNet-SSD-TPU-sync.py
```
うまく動くと、以下の画像のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/a276383b-3544-1c53-e157-90c9128a4680.png)

画像では、85%の確率で「bottle」と66%の確率で「tv」を検出しています。
背景のコンソール画面の数字は検出モデルでの推論にかかった時間です。
一回あたり「0.0165 sec」というかなり高速で検出できています。
Edge TPUを使わずCPUのみで実行した場合、Core i7で0.1秒、ラズパイ3Bで4秒程度かかりますので、Edge TPUによってかなり速度が向上していることがわかります。

なお、検出画面の右上にフレームレートが表示されていますが、「15FPS」しか出ていません。
処理自体が0.016秒で終わっているのであれば60FPS以上出るはずですが、使っているUSBカメラが15FPSまでしか取り込めないため100%の性能が出せない状態になっています。

とはいえ、動くことは確認できたので、とりあえずはこれで良しとします。

## 【最後に】
とりあえず、擬似的ではありますがWindows環境でEdgeTPUを動かすことは可能になりました。
では、この環境を使ってなにかするのか?といえば、特に考えていません。
業務上Windows端末を使わざるを得ないので、使い慣れた端末を利用しつつEdgeTPUを使った開発が行えるかな?って言うぐらいにしか考えていません。
あと、客先でデモする際にも持ち物を減らせるかな?
客先によっては情報機器は持ち込みが厳しいので、できるだけ持ち込むものは減らしたいですからね。