OmniAICreator/Qiita-1.07M huggingface dataset:
リフレクションできないFlutterで汎用的なORMを作る方法

Flutterだとリフレクションができないので、自作の薄いORMとが作りづらいのですが、リフレクションなしで汎用的にする方法を紹介します。
Nappsではこの方法を使ってfirestoreの薄いラッパークラスを作っています。

## リフレクションできないと何が面倒なのか？
Mapから生成できるEntityBaseを用意したときに、共通のRepositoryクラスでEntityクラスのfromMapを実行しエンティティのインスタンスが取得できたら便利そうですが、スタティックメソッドをジェネリクスを使って呼び出すことはできません。またFlutterではリフレクションもできないため、直接呼び出すこともできません。

``` dart
abstract class EntityBase {

   factory Entity.fromMap(Map map);

   Map toMap();
}
```

実際のエンティティのサンプル

``` dart
 class SampleEntity extends EntityBase {
   final String name;
   
   SampleEntity({@required this.name}

   factory Entity.fromMap(Map map) => SampleEntity(name: map['name'])

   Map toMap() => {
     'name': name
   }
}
```

## Builderクラスを使ってインスタンスを生成する
fromMapがスタティックメソッドになっているためジェネリクスに対応できないので、fromMapをインスタンスメソッドでラップしたBuilderクラスを用意します

``` dart

abstract class Builder<T> {
   
   T build(Map);
}

```

実際のビルダークラスのサンプル

``` dart

class SampleEntityBuilder extends  BuilderBase<SampleEntity> {
   
    SampleEntity build(Map map) => SampleEntity.fromMap(map);
}

```

Builderでラップすることで、`builder.build(map)`のように呼び出すことでエンティティのインスタンスを取得できるようになります



## Repository
Repositoryはbuilderを受け取ることで、mapからエンティティへの変換が必要になったときに、``builder.build(map)``を実行するだけで、エンティティのインスタンスを取得することができます。

``` dart

abstract class RepositoryBase<T extends EntityBase, S extends BuilderBase> {
   
  final S builder;

  RepositoryBase(this.builder);
}
```


## エンティティごとに用意するコード
エンティティごとに用意するコードをまとめると下記の３つになります

``` dart
 class SampleEntity extends EntityBase {
   final String name;
   
   SampleEntity({@required this.name}

   factory Entity.fromMap(Map map) => SampleEntity(name: map['name'])

   Map toMap() => {
     'name': name
   }
}
```

``` dart
 class SampleEntityBuilder extends  BuilderBase<SampleEntity> {
   
    SampleEntity build(Map map) => SampleEntity.fromMap(map);
}

```
``` dart
 class SampleRepository extends  RepositoryBase<SampleEntity, SampleBuilder> {
   
    SampleRepository():  super(SampleEntityBuilder());
}

```
qiitaの記事の作り方(とりあえず誰か教えての方用、 動画あり)

この記事では、qiitaの記事の作り方において、基本的なところをおさえていきます。

『PVを上げる記事の書き方とは!?』のようなものではなく、
**『qiitaで記事を書いてみたいけれど、qiitaのUIがよーわからん。
だれか簡単に教えてくれない?』勢に向けての記事となります。**

動画で見たい方はコチラからどうぞ。
https://youtu.be/EgZzqNz1HAY

---

【見た目について】
基本的には、下図スクショのように、
**左側のエディタだけ**に書きたいことを書いていけば問題ありません。
右側はプレビュー画面です。
***(unityに慣れている人であれば、左がScene、右がGameです)***

スクショ
<img width="1425" alt="a02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/f709d721-f109-2d2c-05ad-19243ef8163c.png">


---

【文字の装飾について】
左側のエディタでは、マークダウンと呼ばれる記載のしかたで、文字を装飾することができます。
自分は、**正直なところマークダウンの何がいいのかさっぱりわからない人**なのですが、
エディタの右上にあるはてなマークをクリックすれば、基本的な装飾の仕方について、
ポップアップで表示されます。
<img width="265" alt="a01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/6c12b62d-5383-63ab-13b9-d76053f33d1e.png">
はてなマークをクリックすると、下図のようにポップアップが表示されます。(大事なことなので二回書きました)
<img width="608" alt="a03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/651d5ac9-45bf-e0ec-28bf-538c1044c1f2.png">

---

【画像の挿入について】
エディタ上で、画像を挿入したい箇所をキークリックした状態で、
Finderなどからドラッグアンドドロップ!!
ただし、ファイル名は短くないと反映してくれなさそうなので、下図スクショのように、
適当な短いファイル名にしておくと良いです。
※動画収録中はスクショのデフォの名称のままアプデできた…
<img width="492" alt="スクリーンショット 2020-04-28 9.27.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/362cfe0f-46d6-6dd8-086d-fee872caed10.png">

---

【公開について】
画面右下にある**[↑Qiitaに投稿▲]**ボタン
内の▲をクリックすると、下図スクショのように、
- 下書き保存
- 限定共有投稿
- Qiitaに投稿
を選択することができます。ここら辺はご自由にどうぞ。
<img width="204" alt="a04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/f6e625a8-db12-54c3-2d6d-0f01449b3ff7.png">

---

以上となります。
ここまで読んで、なんとなくわかればとりあえず自分のナレッジのひとつやふたつ、
爆速であげてみてはいかがでしょうか。

---

【おまけ】
何かを書籍化する際にも言われていますが、
**何もプロが書いた最上級のナレッジだけが求められているわけではありません。**

***今書いているあなたのナレッジの価値が、
ターゲットとして、同じスキル感を求めている方が必要としているのです。***

qiitaでもnoteでもなんでもいいので、
とにかく自分の価値はどんどんみんなでシェアしていきましょう。
Ubuntu 20.04 oci8 for phpインストールエラーの対処

##はじめに
Ubuntu 18.04⇒Ubuntu 20.04のバージョンアップに伴い、phpが7.2⇒7.4にバージョンアップされたので、phpにoci8の設定をしたときに発生したときの対処メモ

##エラー内容
https://gist.github.com/Yukibashiri/cebaeaccbe531665a5704b1b34a3498e
を参考に、インストールをすすめたが、

```
pecl install oci8
```
で以下のエラーが発生

```
In file included from /tmp/pear/temp/oci8/oci8.c:49:
/tmp/pear/temp/oci8/php_oci8_int.h:58:10: fatal error: oci.h: No such file or directory
   58 | #include <oci.h>
      |          ^~~~~~~
compilation terminated.
make: *** [Makefile:194: oci8.lo] Error 1
ERROR: `make' failed
```

##対処方法
https://stackoverflow.com/questions/37080443/error-oci-h-no-such-file-or-directory
を参考に、以下を実行で解決

```
sudo C_INCLUDE_PATH=/usr/include/oracle/12.2/client64 pecl install oci8
```
Raspberry PiでOpenMediaVaultによるNAS構築

#OpenMediaVaultによるGUIベースでのNAS構築
4時間かかってやっとできました。そもそもRaspberry PiのOSをmicroSDカードでインストールする必要がありました(最近変更があったよう)。
小規模であればコマンドで共有ファイルを設定する方が楽かもと思いながらも、市販のNASはGUIベースで構築することがほとんどだと思うので、知っていて損はない。
git push でPermission denied (publickey). が出た場合の対処法

$ git push -u origin --all
で Bitbucketにプッシュしようとした際に

```
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

このように返された。


**要因**
公開鍵をBitbucketに追加していなかったからpushできなかった？



**解決したやり方**

```
$ cat ~/.ssh/id_rsa.pub
```
で公開鍵を出力

Bitbucketで公開鍵を追加する。

再度に
$ git push -u origin --all
でプッシュできた。
事務職の私がRPA(UiPath)開発担当した話①(レコーディング機能を使ったアクティビティの選び方)

##概要
この記事は、事務職の私がRPA開発を行っている部署からアドバイスを頂きながら定型業務を自動化していった際の開発メモになります。
※そのままの流れで現在、RPA開発部門に移籍しましたｗ

お客様先でのヒアリングでも内製化がうまくいかないといった話をよく聞くので、
私が事務職だった頃に手探りで開発していく上で役にたった小技や実際に開発をして躓いた箇所、
知っていると便利なPointをまとめていきたいと思います！

- 初めてUiPathを使用してシナリオを作成する人
- UiPathを使っているけど、アクティビティが何を使えばわからない人
- エラーが起きるけど、どうしたらいいかわからない人

向けに記述します。
上記3点に当てはまらなくても、復習用でご覧ください！

今回、私が使用しているUiPathのバージョンは、
**Studio 2019.10.2 Enterprise License**です。

##シナリオ作成する時に便利な機能
紹介していく機能は3つ。

- レコーディング機能
- デバッグ機能
- データスクレイピング機能

今回は、**レコーディング機能**について紹介します。

##レコーディング機能の使い方
レコーディング機能とは、ざっくり言うと下記3つになります。

- マクロの記録の操作感で自分の自動化したい操作をレコーディングできる
- 使用したアクティビティが一目でわかる
- シナリオ作成が難しい時に、作成方法の一つとして簡単にできる

初めてシナリオ作成する際、「どのアクティビティを使用したらいいのだろう？」と悩んでしまうことがあると思いますが、
レコーディング機能を使用することで、普段行っている操作をそのまま記録して自動的にアクティビティを選択して作成してくれます。

####「Webレコーディング」を使用してみる
![レコーディング機能.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614681/a3b719d7-aea4-fbab-3b76-e8a376ac4db1.png)

リボンタブの「レコーディング」機能を押下します。
レコーディング機能を押下すると、選択肢が出てきます。
自動化する対象に合わせてレコーディング機能の選択を変えていきます。

今回は、「乗換案内検索」のシナリオ作成をレコーディング機能で作成しました。
会社への経費精算で、煩わしい交通費検索の部分をレコーディング機能で自動化してみました。

今回、Webの乗換案内サービスを使用してロボットを作成します。
Web検索になるため、**レコーディング＞Web**を選択すると、「Webレコーディング」を使用することができます。

以下、作成したシナリオです。
![レコーディング機能6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614681/32ad9490-e748-559a-60f0-6e5d3dfa667f.png)
![レコーディング7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614681/1992f10e-3d2a-0493-fdc8-83ad804de5cb.png)

今回レコーディング機能で使用したアクティビティは「クリック」と「文字を入力」の2種類使用しています。
その使用したアクティビティを見ていきます。

##使用したアクティビティ紹介

####クリックアクティビティ
![レコーディング機能10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614681/b393fa77-2a2a-a4e3-b7b9-724687897a46.png)

クリックアクティビティのプロパティパネルで詳細設定が可能になります。

**《Point💡》**

- クリックをシュミレートにチェックを付ける
- ロボットで動かした際に動作が早すぎて、正常にクリックされない場合、裏の情報(セレクター)でクリックする位置特定しているため、クリックをしてから次の動作に正しく進む

####文字を入力アクティビティ

![レコーディング機能8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614681/aaf34a58-6408-e423-7d0b-370c46b19984.png)

レコーディング機能を使用して、文字を入力すると、入力値が表示されます。
その際に、**フィールド内を削除する**にチェックを入れます。

**チェックポイント💡**
フィールド内に削除にチェックを入れた方がよいケース

- 連続して検索条件を入力したい
- ログイン情報等をブラウザーが覚えていて自動入力してしまう時

フィールド内を削除にチェックを入れない方がよいケース

- 検索が一度のみでよい

![レコーディング機能9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614681/1b579f9e-fb1b-1e62-0fb1-5c66f2afccf5.png)

プロパティパネルでも自動的にフィールド内に削除にチェックが入っているのが確認できます。
次は、**入力をシュミレート**を見ていきます。

**《Point💡》**
入力をシュミレートにチェックを入れた方がよいケース

- ロボットで動かした際に正しく入力されたかどうか確認したうえで次の入力フィールドに移りたい場合
- 現在入力しているフィールド内で変換を行う場合や、次の入力フィールドと文字種が異なる場合(例：英字入力→漢字入力)

##補足
今回、使用したアクティビティ以外について。

####UI識別モードとは
UI識別モードとは、人間の目ではなく、コンピュータが見た、機械側から見たときに、このシステムはどういう構造に分かれているか認識するツールになります。

次回は、デバッグ機能について紹介していきたいと思います。
GET/POST

備忘録です。
間違いなどございましたらご指摘ください。

##クライアントとサーバーのやりとり
Webにおいてサーバとクライアント間のやりとりは基本的にHTTPというプロトコルを用いる。
HTTPとは、WebサーバとWebクライアントの間でデータの送受信を行うために用いられるプロトコル。
Webの世界でのやりとりは基本的にリクエスト/レスポンスで成立。

- クライアントからサーバへの要求することをリクエスト
- サーバからブラウザへ応答することをレスポンス

##HTTPの仕様
HTTPにはいくつかの仕様がきめられていて
GET/POSTというのはその仕様で取り決められたHTTPの一部。
（他にもHEAD/OPTIONS/PUT/DELETEなどが定義されている。）

##GET
GETは指定したリソースの表現を転送するようにリクエストするメソッド。
（つまり、何か情報を検索したり取得するために使うためのメソッド。）
例えば、ブラウザでURLを入力し検索するとき、無意識にGETメソッドを使っている。

GETメソッドを使ってデータを送信する場合は、**URLの後ろに送りたいデータを付与して送れる。**
(データを取得したい時に使用、データベースの書き換えが必要ない場合。)

##POST
POSTは指定したリソースを実装した機能に従って処理をする機能
GETとは反対に冪等でないかつ安全でないと定義されている。

POSTメソッドを利用してデータを送信する場合は、**HTTPリクエスト内のメッセージボディにデータを含めて送る。**
リクエストとして送信されるデータはメッセージボディ部に含まれる。
(メッセージボディは、HTTPリクエストのパラメータ内容を渡す場所)

以下のようなデータを変更したい時に使用。

- HTMLのformタグに入力された内容をDBへ登録する
- ブログの記事を投稿する
- 新しいユーザを登録する
- 既存のデータに新しい情報を付加する

##リクエストパラメーターの付加の方法
GETはURLにクエリとして追加することが可能
上記で説明したとうり、GETメソッドを使ってデータを送信する場合は、**URLの後ろに送りたいデータを付与して送れる。**
（データを取得したい時、データベースの書き換えが必要ない場合。）

【例】
GET: /foo/bar?itemId=xxxx-xxxx
「URL?パラメータ名=値」という形式
「?」パラメータのはじまり
「&」パラメータの切れ目
「=」挟んだ左側がGETの変数名、右側が渡される値


一方、POSTはBodyをリクエストに含めることも可能。
また一般的にあまり使われないが、クエリを追加することもできる。
POST: /foo/bar?user="taro"
param:{"itemId": "xxxx-xxxx”}

##まとめ

- GETはリソースを取得するときに使うもの
- GETは情報を取得するときに使うもの
- POSTはリソースに対して特有の処理をするときに使うもの
- POSTは新しい情報の登録をするときに使うもの
CentOS7で複数ユーザーで同時に使用するJupyter Notebook環境を作る

# jupyterhub
Jupyter Notebookの環境を立てただけでは、複数ユーザーで同時に使用することは困難なので、ユーザー管理機能を追加する「JupyterHub」を用いて、Jupyter Notebookを使用できる環境を作ります。
## 環境
今回紹介する構築環境は以下です。
- OS：CentOS7.4　(docker)
- Anaconda3-4.3.1
- Python3.6.9
- 基盤：AWS　EC2
## 設定
#### CentOSコンテナ作成
```
docker run -it --privileged -d -p 888:8000  --name centos_cho centos:7 /sbin/init
```
#### 事前インストール
```
yum install wget
yum install bzip2
yum install sudo
yum install which
```
#### 以降、rootユーザで操作します
#### Anaconda3インストール
```
cd ~
wget https://repo.continuum.io/archive/Anaconda3-4.3.1-Linux-x86_64.sh
bash Anaconda3-4.3.1-Linux-x86_64.sh
※注意点：インストールディレクトリは/opt/anaconda3/にします。
```
#### jupyterhubインストール＆設定
```
conda install -c conda-forge jupyterhub
conda install notebook
npm install -g configurable-http-proxy
```
```
cd /opt/
jupyterhub --generate-config
vi jupyterhub_config.py
```
```
c.JupyterHub.ip = '0.0.0.0'
c.Spawner.ip = '127.0.0.1'
c.JupyterHub.port = 8000
c.PAMAuthenticator.encoding = 'utf8'
c.LocalAuthenticator.create_system_users = True
c.Authenticator.whitelist = {'user1', 'user1', 'user3'}
c.Authenticator.admin_users = {'user1'}
c.LocalAuthenticator.group_whitelist = {'group1'}
c.JupyterHub.statsd_prefix = 'jupyterhub'
c.Spawner.notebook_dir = '~/notebook'
```
#### ユーザ作成
```
groupadd group1
useradd user1
usermod -a -G group1 user1
passwd user1
mkdir -p /home/user01/notebook
chown user01:usergr /home/user01/notebook
```
#### 起動＆アクセス
```
jupyterhub --no-ssl
http://公開IPアドレス:888/
```
#### エラー解決
1.必要なら
```
yum install -y gcc-c++ make
```
2.ImportError: libsodium.so.23: cannot open shared object file: No such file or director
```
conda install -c conda-forge libsodium
```
3.ModuleNotFoundError: No module named 'nbconvert.exporters.base'
```
conda upgrade nbconvert
```
4./usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
```
strings /usr/lib64/libstdc++.so.6 | grep GLIBC
find / -name "libstdc++.so*"
cp /xxx/xxx/xxxx/libstdc++.so.6.0.21 /usr/lib64
cd /usr/lib64
rm -rf libstdc++.so.6
ln -s libstdc++.so.6.0.21 libstdc++.so.6
strings /usr/lib64/libstdc++.so.6 | grep GLIBC
```
[ファン制御] fancontorlの初期設定とエラー対処法

# 流れ

まず、`sensors`コマンドを打つ

```
sensors
```

ここで、

- システムがモジュールを認識している
- システムがモジュールを認識していない
 - CPUファンのrmpが0のとき

上記の時のそれぞれのやり方を次に示す


## その１  モジュールを認識 　◯

1. `sudo pwmconfig` をして設定する。設定ファイルは、` /etc/fancontrol `に保存される。　
2. `systemctl enable fancontrol` でサービスを有効化する。
3. `suspend`の復帰後にfancontrolをrestartする設定をする。`/lib/systemd/system-sleep/`に設定ファイル配置する
`systemd`の`system-sleep`配下にsuspendから復帰したときの動作を指定するシェルを作成します。(名前は何でも良いです。)

```sh:/lib/systemd/system-sleep/restart-fancontrol
#!/bin/bash
case "$1" in
post)
  exec service fancontrol restart
esac
```



## その2   モジュールを認識  ☓

### CPUファンが0rpmの時

★こちらを参考にしました★
https://github.com/lm-sensors/lm-sensors/issues/134#issuecomment-513506723

Linuxのブート設定を変更することで解決する。
`quiet splash`の後に`acpi_enforce_resources=lax`を追記する。

```:/etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi_enforce_resources=lax"
```
```terminal:設定の適用と再起動
sudo update-grub
reboot
```
```terminal:再び確認
sensors
```

- `その１  モジュールを認識 　◯`のやり方を実行する。


# エラー対処

## hwmonの割当が変わってfancontrolが実行できない

これはLinuxの仕様なので根本的な解決方法はないらしいので、hwmonの割当が変わったときのfancontrolサービスを複製していくのがベストな方法っぽいです。

### 例) hwmon2で設定した → 再起動 → hwmon2が見つかりません！

**解決方法**
1. hwmon2で設定した`fancontrol.service`を複製して`fancontrol-2.service`を作る
2. 新しく作ったserviceの`ConditionPathExists`を変更する。
3. `suspend`の設定に追記する。

```fancontrol.serviceを複製
sudo cp /lib/systemd/system/fancontrol.service /lib/systemd/system/fancontrol-2.service
```
```fancontorl-2.serviceを編集
[Unit]
Description=fan speed regulator
# Run pwmconfig to create this file.
ConditionPathExists=/etc/fancontrol-2
After=lm-sensors.service
Documentation=man:fancontrol(8) man:pwmconfig(8)

[Service]
ExecStartPre=/usr/sbin/fancontrol --check
ExecStart=/usr/sbin/fancontrol
PIDFile=/var/run/fancontrol.pid

[Install]
WantedBy=multi-user.target
```

```:suspendの設定
#!/bin/bash
case "$1" in
post)
  exec service fancontrol restart
  exec service fancontrol-2 restart
esac
```
【Rubyバージョン変更】Docker環境でrbenv, ruby-buildをインストールする

## はじめに
 Dockerで開発していく中でrubyのバージョン変更する必要が出て来たのでrbenv, ruby-buildをインストールしてrubyのバージョン変更を行う

### rbenvをインストール
/bin/bashでrbenvをcloneしてくる

```bash

git clone https://github.com/rbenv/rbenv.git
```
パスを通す

```bash

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
```

### ruby-buildをインストール
ruby-buildをcloneする

```bash

git clone https://github.com/rbenv/ruby-build.git
```

### rubyインストール
バージョン確認してrubyをインストールする

```
rbenv install -l
rbenv install 2.5.5
rbenv rehash
```


### 終わりに

Dockerfileを書くときに追加しておけば楽だった
競プロのライブラリ整理~逆元による二項係数の計算~

mod p(pは十分に大きいかつ素数)での二項係数を$O(n)$で前計算をして$O(1)$で求めるようにするライブラリを作成しました[^1]。

また、使用する際は[こちらのテンプレート](https://qiita.com/DaikiSuyama/items/9dba963ba74396b9b7fd)と一緒に使ってください。

また、**前計算をする必要がない場合などの亜種**もあり、詳しくは[けんちょんさんの記事](https://drken1215.hatenablog.com/entry/2018/06/08/210000)を参考にしてください。

```C++:combination.cc
vector<ll> fac,finv,inv;

//二項係数の前計算
//n:=二項係数xCyを求める時の最大のx
void COMinit(ll n) {
    fac.resize(n+1);
    finv.resize(n+1);
    inv.resize(n+1);
    fac[0]=fac[1]=1;
    finv[0]=finv[1]=1;
    inv[1]=1;
    FOR(i,2,n){
        fac[i]=fac[i-1]*i%MOD;
        inv[i]=MOD-inv[MOD%i]*(MOD/i)%MOD;
        finv[i]=finv[i-1]*inv[i]%MOD;
    }
}

// 二項係数の演算
ll COM(ll n,ll k){
    if(n<k)return 0;
    if(n<0 || k<0)return 0;
    return fac[n]*(finv[k]*finv[n-k]%MOD)%MOD;
}
```

[^1]: 逆元の計算方法については[けんちょんさんの記事](https://drken1215.hatenablog.com/entry/2018/06/08/210000)を参考にしてください。
awspec を Docker で動かして、AWSのリソースが正しく設定されているかを確認する

awspec ( https://github.com/k1LoW/awspec ) を使って、AWSのリソースが意図した通りに設定されているかを確認します。

CloudWatch event を使ってるシステムがありますが、サービスを運用していく過程で、CloudWatch event の設定が増え、設定漏れがでてくるようになりました。

CloudFormation 化することも上記の課題の対応になると思いますが、今回は awspec を利用して、 CloudWatch event の設定内容が意図通りに設定されているかを確認します。

サーバー環境に依存させたくないので、 awspec を Docker で動かします。


# この記事でわかること

- awspec を Docker で動かす方法
- awspec で AWSリソース CloudWatch event をテストする方法
- この記事内のソースは以下で公開しています。
    - https://github.com/katsuhiko/awspec-example

# 準備

## Gemfile の準備

bundler を使うので Gemfile へ `awspec` を設定します。

```:Gemfile
source 'https://rubygems.org'

gem 'awspec'
```

## Gemfile.lock の作成

awspec 用の Docker コンテナを作るときに Gemfile, Gemfile.lock ファイルがある前提としたいので、以下のコマンドを実行して事前に Gemfile.lock を作ります。

```sh
docker run --rm -it -v "$(pwd)":/home/app -w /home/app ruby:2.7 bundle install
```


## Dockerfile の作成

Gemfile, Gemfile.lock に従い、 `bundle install` をするのみの単純なコンテナです。

```dockerfile:Dockerfile
FROM ruby:2.7

ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock

RUN bundle install
```


## Docker ビルドの実行

ビルドして Image を作ります。

```
docker build -t awspec .
```


# awspec の設定


## awspec の初期化

`awspec init` を実行して、 awspec で必要となるファイルの雛形を作ります。

```sh
docker run --rm -it -v "$(pwd)":/home/app -w /home/app awspec awspec init
```

## secrets.yml の作成

コンテナ内で実行するため、 サーバー環境で用意する必要がある creadentials ではなく secrets.yml を使うようにします。

今回は CloudWatch event のテストを実行するのみであるため IAM ポリシーは「CloudWatchEventsReadOnlyAccess」のみで OK です。

```yml:spec/secrets.yml
region: ap-northeast-1
aws_access_key_id: xxxxxxxx
aws_secret_access_key: xxxxxxxxx
```


## テストケースの作成

CloudWatch event のテストケースを作成します。

今回は、「cloudwatch_event」リソースタイプを使います。
リソースタイプは以下で確認できます。

- https://github.com/k1LoW/awspec/blob/master/doc/resource_types.md

CloudWatch イベント名は「TestTestTest」で作成しています。
CloudWatch イベントが存在するか、有効となっているか、スケジュール設定は意図通りかを確認しています。


```ruby:spec/cloudwatch_event_spec.rb
require 'spec_helper'

describe cloudwatch_event('TestTestTest') do
  it { should exist }
  it { should be_enable }
  it { should be_scheduled('cron(0 2 * * ? *)') }
end
```


# awspec の実行

Docker コンテナ経由でテストを実行します。

```sh
docker run --rm -it -v "$(pwd)":/home/app -w /home/app awspec rake spec
```


# 補足） 既存リソースからテストケースの作成

Docker コンテナ経由で既存リソースからテストケースを作成することもできます。
secrets.yml を利用する場合、 `--secrets_path` オプションで secrets.yml を指定します。


```sh
docker run --rm -it -v "$(pwd)":/home/app -w /home/app awspec awspec generate cloudwatch_event --secrets_path ./spec/secrets.yml 
```

# 補足) Dockerイメージ再ビルド

```sh
docker build --no-cache -t awspec .
```
【Java】 ArrayListを配列に変換する

##ArrayListを配列に変換する方法と注意点

```java:ListToArray.java
//ArrayList生成
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("A");
arrayList.add("B");
arrayList.add("C");

String[] array = (String[])arrayList.toArray();

System.out.println("ArrayList = " + arrayList.toString());
System.out.println("配列 = " + Arrays.toString(array));
```
###結果（NG）
```
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
```
##なぜか
返すクラスを取得してみる

```java:ListToArray.java
//ArrayList生成
//中略
System.out.println(arrayList.toArray().getClass());
```
###結果
```
class [Ljava.lang.Object;
```
Object型配列が返ってきてる。。。

##修正
```java:ListToArray.java
//ArrayList生成
//中略
//配列の要素数に0またはarrayList.size()を入れる
String[] array = arrayList.toArray(new String[arrayList.size()]);
//String[] array = arrayList.toArray(new String[0]);　※処理が遅くなる（後述）

System.out.println("ArrayList = " + arrayList.toString());
System.out.println("配列 = " + Arrays.toString(array));
```
###結果（OK）
```
ArrayList = [A, B, C]
配列 = [A, B, C]
```

##深堀してみる
```java:java.util.ArrayList.class

public <T> T[] toArray(T[] a) {
   if (a.length < size)
     return (T[]) Arrays.copyOf(elementData, size, a.getClass());
     System.arraycopy(elementData, 0, a, 0, size);
     if (a.length > size)
         a[size] = null;
     return a;
}
```
System.arraycopy(elementData, 0, a, 0, size);
String[]をそのままコピーしていた。
~~new String[0]でした場合、Arrays.copyOf（3行目）に入り、要素を1つずつコピーするのため処理が遅くなります。~~　 2020/04/29更新

処理時間を検証してみました
　[【Java】 ArrayList→配列変換ではサイズを指定するべきなのか](https://qiita.com/j-work/items/2f6450436b3340244123/)



##ちなみに
toArrayの引数に指定できるのは変換元のArrayList<T>でしている型のみ
違うクラスをしていするとコンパイルエラーになる。
sudoで">"でファイル出力しようとすると、Permission deniedエラーが出る時の対処法

権限がないユーザがsudoでコマンドを実行して、かつ、">"でファイル出力する場合、ファイル出力のところで権限がないユーザが実行する事になるので、Permission deniedのエラーが出ます。

```
$ echo aiueo > hoge.txt
-bash: hoge.txt: Permission denied

$ sudo echo aiueo > hoge.txt
-bash: hoge.txt: Permission denied
```

解決するには、パイプでsudo teeに渡してあげる。teeコマンドは標準入力から受け取った内容を、標準出力とファイルに書き出すコマンド。

```
$ echo aiueo | sudo tee hoge.txt
aiueo
```
参考サイト
[sudo でファイルへのテキスト書き込み](https://kuratsuki.net/2018/10/sudo-%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%B8%E3%81%AE%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF/)
@escapingによる非同期処理

##はじめに
クロージャの属性@escapingによる非同期処理を理解するためのメモ
体系的に理解できたらまとめます。

###非同期処理をじっくり観察する
[こちら](https://qiita.com/ottijp/items/e45b65263c53037af1ee)の記事にあるコードを参考にしました。

```swift
class Foo {
    var storedClosure:(() -> Void)?
    
    func foo(closure: @escaping () -> Void){//非同期処理
        print("1")        //これを消すと2345678910
        print("2")       //これを消すと1345678910
        storedClosure = closure     // 一番最後に実行 これを消すと123456910
        print("3")//これを消すと1245678910
        print("4")//これを消すと1235678910
    }
    

    func callClosure() {
        print("7")//これを消すと12345689101112
        storedClosure?()//これを消すと1234567101112
        print("10")//これを消すと1234567891112
    }
}

class Bar {
    func bar(){
        let foo = Foo()
        foo.foo {
            print("8")
            print("9")//わたすクロージャ 関数の外
        }
        print("5")  //これを消すと12346789101112
        print("6")      //これを消すと123456789101112
        foo.callClosure()  //これを消すと1234561112
        print("11")   //これを消すと123456781012
        print("12") //これを消すと1234567891011
    }
    
}

let bar = Bar()
bar.bar()
```

くどいくらい数字をプリントさせ、実行の手順を確認し、わかることを挙げていきます。
・非同期処理というのは@escapingが書かれたクロージャを引数に持つ関数の中で行われている。
・非同期処理の一番最後にクロージャ指定した処理が来る。
・非同期処理を呼ぶ処理はそのまま同期処理
ミニマムなVue.jsコンポーネントプログラミングその４(静的なデータ取得)


その１：ミニマムなシングルコンポーネントVue
その２：ミニマムなルータ
その３：ミニマムなサブコンポーネント

今回は「ミニマムなデータ取得」です。

段階を踏んでやっていきたいと思います。

(1) 静的データの取得
　いわゆるVue.jsの十八番である、データバインディングを使います。
　Vue.jsのhello world的なプログラムで最初に紹介されますね。
　(なぜこの記事の場合、「その４」でようやくこれに言及することになったか、自分でも不明ですが)

(2) 動的データの取得
　サーバを立ててそこからResutFulなAPIによってデータを取得します。
　Scriptからは、axios(PromiseベースのHTTPクライアント)を使って、APIコールします。


今回は(1)です。


#VTuber部品作成(src/compnents/VTuber2.vue)

まずは、**静的に閉じた**画面コンポーネントを作成します。

```html

<template>
    <div>
        <ul>
            <li>名前:{{vname}}</li>
            <li>年齢:{{age}}</li>
            <li>身長:{{height}}</li>
        </ul>
    </div>
</template>

<script>
export default {
    name: 'Vtuber2',
    data() { 
        return {
            vname: '町田ちま',
            age: 16,
            height: 150
        }
    }
}
</script>
```

script内で実装するバインド変数は静的に初期化します。
ちなみに、コンポーネントとして生成するVueインスタンス内では、
dataメンバを関数実装しなければらないとあります。

JavaScriptの内部の動作に詳しくないのが歯がゆいですが、つまり、

コンポーネントは＜VTuber2/＞のようにHTMLに埋め込む。
つまりHTML要素として使えて、かつ、あちこちに複数埋め込むことが出来る。
とはいえ、それぞれ独立したインスタンスとして生成されない？
vname等の変数はグローバルスコープで共有される。
なので、関数化することで(Auto変数的な扱いになり)共有化を防ぐ。

ということでしょうか。めんどくさいな・・

(あー、コンポーネントをクラスインスタンスとして独立させられたらいいのになぁ)


#VTuber部品をHome画面に埋め込み

```html

<template>
  <div>
      <h1>VTuberプロフィール</h1>
      <VTuber2/>　　　　　　　　　　　＜＝＝ココ
  </div>
</template>

<script>
import VTuber2 from '../components/VTuber2.vue'

export default {
    name: 'Home',
    components: {
      VTuber2　　　　　　　　　　　　　＜＝＝ココ
    }
}
</script>
```
今回のサブコンポーネントはコンポーネント内に完全に閉じているので、テンプレートに埋め込みのもタグ要素だけです。

#実行
npm runn serveして、locahost:8081でアクセスすると、以下のように表示されます。
![範囲を選択_014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244766/08cfcef8-9a3e-c9a7-c3ca-09fbf7904d60.png)
premiere proの自作パネル拡張を作る

表題通り。基本的にPremiere ProではスクリプトをIDE経由からしか作れないのだけれど、githubにはそれを作るためのソースが転がってるのでそれをありがたく受け取る。

また、サンプルとして膨大な量のスクリプトがあるのでそれを使ってもお勉強できる。ありがてぇ。備忘録がてら導入方法をメモっていく。

元。
https://github.com/Adobe-CEP/Samples/tree/master/PProPanel

署名されていない拡張は使えないのでレジストリをいじる。

リンク先の画像の通り、PlayerDebugModeを1で追加する。

リンク元のPPropanelをフォルダごと、C:\Program Files (x86)\Common Files\Adobe\CEP\extensionsに追加する。

あとはVScodeで開いてうにゃうにゃやる！

## あとはメモがてら。間違ってる情報あるかもしれないので注意。

index.htmlがパネル本体。ここからevalでスクリプトを実行する。

実行スクリプトの呼び出しはext.jsで検索して読み込んでる。

基本的にはPPROディレクトリのpremiere.jsxを改変していけばお手軽にパネルありの拡張がつくれるはず・・・。
line notify を laravel5.7で使う

参考
https://qiita.com/YuyaSEKI/items/a368696c41619fd8066f

上記記事だと、アクセストークンが取得できない。
ということで。

# まずはCSRFをオフに

```app/Http/Middleware/VerifyCsrfToken.php

    protected $except = [
        'line/callback'
    ];

```

# app.php に 設定

```config/app.php

    'line_notify' => [
        'token_url' => 'https://notify-bot.line.me/oauth/token',//固定
        'client_id' => 'ssss',
        'client_secret' => 'eeeee',
        'callback_url' => env('APP_URL').'/line/callback',
        'csrf' => 'tokentest'//適当
    ],


```

# アクセストークンを取得するURLを生成

```LineController.php


public static function test(Request $request)
{
    $line_notify = config('app.line_notify');
    $url = 'https://notify-bot.line.me/oauth/authorize?response_type=code&client_id='.$line_notify['client_id'].'&redirect_uri='.$line_notify['callback_url'].'&scope=notify&state='.$line_notify['csrf'].'&response_mode=form_post';
    echo "<a href='".$url."'>".$url."</a>";
}

```

# 上記のコールバック先を取得


```LineController.php

public static function callback(Request $request)
{

    if(!empty($request->code)){
    
        $line_notify = config('app.line_notify');
    
        $data = [
            "grant_type" => "authorization_code",
            "code" => $request->code,
            "redirect_uri" => $line_notify['callback_url'],
            "client_id" => $line_notify['client_id'],
            "client_secret" => $line_notify['client_secret']
        ];
        
        $data = http_build_query($data, "", "&");
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $line_notify['token_url']); // 送り先
        curl_setopt($ch, CURLOPT_POST, true); // POSTです
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 送信データ
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 実行結果取得の設定
        
        $token = curl_exec($ch);
        curl_close($ch);
        
        $tmp = json_decode($token,true);//これやらんと、うまくデータを取得できない
        $token = $tmp['access_token'];//アクセストークン
        die;
        
    }


}


```


``アクセストークン取得OK!``


# 早速送信してみる

```

$token = 'ymantyozuao';

// リクエストヘッダの作成
$message = 'ひでちゃんでっせ';
$query = http_build_query(['message' => $message]);
$header = [
'Content-Type: application/x-www-form-urlencoded',
'Authorization: Bearer ' . $token,
'Content-Length: ' . strlen($query)
];

$ch = curl_init('https://notify-api.line.me/api/notify');
$options = [
CURLOPT_RETURNTRANSFER  => true,
CURLOPT_POST            => true,
CURLOPT_HTTPHEADER      => $header,
CURLOPT_POSTFIELDS      => $query
];

curl_setopt_array($ch, $options);
curl_exec($ch);
curl_close($ch);

```

``送信完了！``
deviseのconfirmable機能において、メール認証後にログイン状態にする方法


#前提条件
devise gem(ver.4.7.1)を用いて以下を完了していることが前提となります。

✅基本的なユーザーログイン機能を実装していること
✅confirmable機能を用いて、以下のようにメール認証機能を実装していること。
1. 新規登録画面で新規登録情報(アドレス、パスワード２回)を入力する
2. 1.で入力したアドレスにページリンク付きアカウント確認メールが送信される
3. 2のリンクからログイン画面に転送される (新規登録完了)
4. ログイン画面でアドレス、パスワードを入力する
5. ログイン完了し、ホーム画面にジャンプする
# 実現したいこと
確認メールのリンクをクリックすると登録完了はもちろん、自動でログイン状態になるようにしたい。(上記の動作で言うと、4.をスキップするイメージ)

# 方法
confirmations_controllerに以下を追記する。

```ruby:users/confirmations_controller.rb
..
private
  def after_confirmation_path_for(resource_name, resource)
    sign_in(resource)
    root_path
  end
```
簡単に解説すると、```after_confirmation_path_for```はメール認証をした後に実行されるメソッドです（そのまんまですが）。
ここに```sign_in```メソッドをオーバーライドすることでユーザーはログイン済み状態となります。
```root_path```は、ログイン後にリダイレクトしたいページとします。

routeファイルに以下を追記する。

```ruby:route.rb
..
  devise_for :users, controllers: {
    confirmations: 'users/confirmations'
  }
..
```
deviseで用意されたコントローラーをカスタマイズする場合、対象のルートを指定する必要があります。

これで完成です。
メール認証後ログイン状態となり、指定したURLへジャンプします。

# 注意
ユーザーが新規登録の際、間違ったemailアドレスを記入した場合、たまたまそのemailを受け取った第三者にアカウントを乗っ取られてしまう可能性があるので、注意が必要です。


# 参考：
[How To: Add :confirmable to Users](https://github.com/heartcombo/devise/wiki/How-To:-Add-:confirmable-to-Users#redirecting-user)
sklearnのget_scorerについてメモ

scikit-learnのversionは0.21.3。
accuracy_scoreを直接使う時とget_scorer('accuracy')では引数が異なる。
https://github.com/scikit-learn/scikit-learn/blob/95d4f0841/sklearn/metrics/_scorer.py#L393-L398

```
 $ python
Python 3.6.10 |Anaconda, Inc.| (default, Mar 25 2020, 23:51:54)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from sklearn.metrics import get_scorer, accuracy_score
>>> from sklearn.linear_model import LogisticRegression
>>> accuracy_score([1, 2, 3], [4, 5, 3])
0.3333333333333333
>>> get_scorer('accuracy')([1, 2, 3], [4, 5, 3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __call__() missing 1 required positional argument: 'y_true'
>>> estimator = LogisticRegression().fit([[10], [12], [13]], [1, 2, 3])
/home/hidetomo/.pyenv/versions/miniconda3-4.3.30/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)
/home/hidetomo/.pyenv/versions/miniconda3-4.3.30/lib/python3.6/site-packages/sklearn/linear_model/logistic.py:469: FutureWarning: Default multi_class will be changed to 'auto' in 0.22. Specify the multi_class option to silence this warning.
  "this warning.", FutureWarning)
>>> estimator.predict([[10], [11], [12]])
array([3, 3, 3])
>>> get_scorer('accuracy')(estimator, [[10], [12], [13]], [1, 2, 3])
0.3333333333333333
```
Swift SwiftUI、Listの1行内に2個のボタン配置はダメ、一緒に押下される

# Code

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        List() {
            HStack {
                Button(action: {
                    print("Push A!")
                }, label: {
                    Text("A")
                })
                Button(action: {
                    print("Push B!")
                }, label: {
                    Text("B")
                })
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

# Result

## Aボタンを押下

```tex
Push A!
Push B!
```

## Bボタンを押下

```tex
Push A!
Push B!
```

どちらを押そうが一緒。
行が押されている為。
Formも一緒。
List・Formの役割からすれば当然か。
Toggleを複数配置するのは大丈夫です。
Linux でディスクのマウントに失敗しても起動してほしい時は fstab に nofail オプションを付けるとよさげ？

# そもそもこの記事を書くに至ったきっかけ
## やらかした
自宅で運用している Raspberry Pi につないだ USB HDD を一個減らしたんだけど、fstab をいじるのを忘れた。

## 結果起きたこと
SSH でログイン不可能な状況に！
通常ヘッドレスで運用してるのだけど、慌ててディスプレイを繋いでエラーを見てみたら、何やら emergency mode とやらに入っている。
キーボードを繋いでキーを押しても同じエラーメッセージをぐるぐるしてて、ディスプレイとキーボードを繋いでも復旧作業できず。

## 対応したこと
起動不能になった Raspberry Pi の micro SD を引っこ抜いて、別の Raspberry Pi に USB カードリーダー経由で接続。
んで、適当なディレクトリにマウントして、起動不能になった Raspberry Pi の fstab を以下のように変更。

```shell:fstab変更前
/dev/sdb1 /mnt/hoge ext4 defaults 0 0
```

```shell:fstab変更後
/dev/sdb1 /mnt/hoge ext4 defaults,nofail 0 0
```

これで元のマシンに micro SD を差し込んで起動しなおしたところ、マウント時のエラーを無視して復活。
あとから何が起きたものかと、fdisk -l で見てみたら、/dev/sdb1 に今までつながってたドライブが /dev/sda1 に引っ越してた。

# 調べて分かったこと
どうやら、fstab に書かれているドライブが見つからなかったりエラーがあったりすると、Linux はあっさり起動を諦めて emergency mode に入るらしい？
（ディストリビューションによって違うのかもしれませんが、やらかし起点の取り急ぎ調査なので、詳しい方いたら教えてください。）

# ベストプラクティス
**Linux において、取り付け取り外しが行われる類のディスクを fstab でマウントするときは、nofail オプションを付けとくとよさげ。**

多分、クラウド上の仮想マシンとかでも、仮想 VHD をマウントする設定を fstab に書いた後にクラウド側の管理操作で取り外して、うっかり OS をリブートしてしまったら同じような状況に陥る気がする。
transformersによる感情分類

```
from transformers import pipeline,AutoModelForSequenceClassification

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

model = AutoModelForSequenceClassification.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")

nlp = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)

print(nlp("I hate you"))
print(nlp("I love you"))
```

# 参考
https://huggingface.co/transformers/usage.html
初心者によるプログラミング学習ログ 301日目

#100日チャレンジの301日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
301日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>301日目　2h<br>・xdデザインカンプからのサイト模写<br>・レスポンシブ化<br><br>メディアクエリで相当悩んだ・・・<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1254864693241327616?ref_src=twsrc%5Etfw">April 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Mac初心者のためのusdz_converter

#usdzファイルとは
簡単に言うと、usdzを使うことでiPhoneにおいてめちゃくちゃ簡単にARができるようになる形式です。
言うのは簡単ですが、こいつ、なかなか変換するのが難しいです。
基本的にMacを使うことを前提としているのでMacユーザーでないとできない上コマンドラインを使うのでハードルが高いです。
（最近はsketchfabやらAdobeAeroでできるようになったので割と簡単にできるようになってます）

今回はオールドなコマンドラインを使うやり方でusdzへの変換を行います。

#方法 -準備-
まず以下のページに移動します。
https://developer.apple.com/download/more/

左上の検索窓で**USDPython**と検索し、適当なバージョンのものをダウンロードします。
(Enter押さないと検索されません)
![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446399/f7c691eb-1eee-b274-1f1c-dad588d501f4.png)
ダウンロード後は適当な場所に解凍し、インストールします。（デフォルトで大丈夫です）

解凍したら当該でディレクトリに移動します。
**USD.command**というスクリプトがあるので起動します。
![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446399/2738a246-efd8-9f45-f131-19bbf580425a.png)
本来であれば先ほどインストールしたファイルにPATHを通さなければならないのですが、ここから起動した場合はすべてのPATHが入った状態でコマンドを実行できます。

試しに環境変数を表示させてみましょう。
コマンドライン上で以下のコマンドを打つと

```
printenv PATH
```
![スクリーンショット (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446399/d510157b-5a9b-409f-b1b8-17e6a95c3a70.png)
このようにちゃんと環境変数が設定されています。

#方法 -usdzへの変換-
では本題のusdzへの変換を行います。
まずはコマンドライン上で当該ファイルの場所に移動します。

```
cd 移動先のパス
```
Macの移動先のパスはパスの知りたいファイルを右クリックした状態でoptionキーを押すことで「～のパス名をコピー」が表示されコピーできます。
また、現在のディレクトリが分からないときは

```
pwd
```
で現在のパスが分かります。

そして

```
crun usdzconvert ファイル名.obj 書き出したいファイル名.usdz
```
でusdzへの変換ができます。

**注意**
ほかのusdzに関する記事で<font color="Red">**usdzconvert**</font>ではなく<font color="Red">**usdz_converter**</font>と書いてあることがありますが仕様が変わった様です。気を付けましょう。
今後も変わる可能性がありますので、```xcrun: error: unable to find utility "usdz_converter", not a developer tool or in PATH```が出た際は```printenv PATH```か何かで確認するとよいかもしれません。
その他にもOptionが変更され、例えば```- color_map ファイル名.jpg ```は```diffuseColor ファイル名.jpg ```のように変わっており、過去のサイトを参照する場合は注意が必要です。
QNAPにEntware-stdをインストールする




## 2行で概要

* QNAPに QNAP Club Storeの非公式なレポジトリを設定
* QNAP管理画面のQPKG Storeから Entware-stdをインストールする


## 手順

### 1. QNAP管理画面にログイン

### 2. App CenterにレポジトリのURLを登録する
   
2-1. App Centerに行く
2-2. 右上にある設定マーク(パラメータアイコン)をクリック
2-3. ３つのタブの真ん中にある「アプリレポジトリ」のタブをクリック
2-4. 「追加」ボタンを押して、QPKG StoreのレポジトリのURLを登録
   　接続情報に以下を書く。ログイン情報は不要。
   　名前: QPKG Store
     URL: https://www.qnapclub.eu/en/repo.xml
2-5. 「閉じる」ボタンを押して終了
   

画像付きの英語の手順は以下を参考にする
Qnapclub Store
https://www.qnapclub.eu/en/howto/1
   

これでレポジトリの追加が完了

### 3. Entware-stdの追加

* AppCenterの左に QPKG Storeというアイコン+文字が表示されるのでクリック
* 「アプリをインストールしてません」と表示される
* 右上の検索アイコンをクリックして、「Entware」で検索
* 現時点(2020年4月28日)だと Entware-3x-std 1.00, Entware-ng 0.97, Entware-std 1.02が出てくる
* Entware-std 1.02(2020/01/07)をインストール
  → 注意)サードパーティ製で、デジタル署名されてないので、NASセキュリティに影響が及ぶ可能性があります、という警告が出ます。リスクを理解した上で、チェックボタンをクリックしてインストールしましょう。



## 過去のQNAP用パッケージマネージャーの流れ

QNAPのパッケージマネージャーで検索すると色々出てきて混乱するが、以下のような流れ?

* ipkg?
* Optware
* Entware
* Entware-ng
* Entware-3x (カーネル 3.x以上に特化)
* Entware (Entware-ngとEntware-3xの統合)
　Entwareには2つあり、区別するために Entware-stdというのがある


参考: 以下のコメント欄
https://qiita.com/nak1114/items/b534cd3bd79db3e3f256
TypeScriptでキャンセル可能なsetTimeOut()関数を作る

## はじめに
TypeScriptを書いていてキャンセル可能なsetTimeOut関数が欲しいなと思ったので書きました。もっといい書き方があれば教えていただきたいです！！

## 実装
他にもいくつか方法はあると思いますが、今回は引数に遅延時間(duration)とコールバック関数を渡すと、実行開始の関数とキャンセル用の関数が帰ってくるような仕組みにしました。

```typescript

const disposableTimeOut = (duration: number, callback: () => void): {
  on: () => Promise<void>,
  dispose: () => void,
} => {
  let timeOutId: NodeJS.Timeout | null;
  let resolve: () => void
  const on = () => new Promise<void>((_resolve) => {
    resolve = _resolve;
    timeOutId = setTimeout(() => {
      callback();
      timeOutId = null;
      resolve();
    }, duration)
  })
  const dispose = () => {
    if (timeOutId) {
      clearTimeout(timeOutId);
      timeOutId = null;
      resolve();
    }
  }

  return {
    on,
    dispose,
  }
}
```

## 使用例
```typescript
const disposable = disposableTimeOut(1000, () => {
  console.log('1秒たったよ！！ ワイワイ！！')
}

// タイムアウトしたい関数を実行する
await disposable.on();

// キャンセルしたいところでキャンセル(破棄)する
disposable.dispose();
```

## さいごに
↑みたいな感じで動きます！！
SPA(nuxt) + API(Rails) + S3 + CloudFrontホスティングでファイルダウンロードでCORSエラー

この記事ではNuxt.jsで構築したSPAサイトで、CloudFrontホスティングのデータのダウンロードに失敗した時の解決について書いています。

# 事象

SPAサイトを表示しているブラウザのConsoleにて、エラー。ファイルのダウンロード機能が使用できない。

```
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'https://****************' is therefore not allowed access.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
```

### 考察

ん？　APIサーバーはOriginの許可は問題なくやっているし、その証拠にSPAでのサイト閲覧は問題なくできている。
ここででているのは、Frontend → どこ？？？


### 原因

ファイルがあるのはS3なので、S3のCORS設定を行わないといけなかった。

`Amazon S3` → `バケット` → `アクセス権限` → `CORSの設定`

```
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
```

大切なのは

`<AllowedOrigin>*</AllowedOrigin>`

です。これだと全てのOriginを受け入れてます。
*を適宜アクセス元Frontendのoriginに変更すればよい。

無事ダウンロードができる用意なりました！
ubuntu18.04LTSでターミナルからParaviewを起動する


#1.[Paraview公式サイト](https://www.paraview.org/download/)からダウンロード
以下のようなページに飛ぶ
<img width="500" alt="a.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591933/87e41393-f791-fa9b-a373-e511441bcb69.png">

任意のバージョンとLinuxを選択しダウンロード

#2.任意のフォルダに移動させ解凍する
今回は/usr/local/で解凍

```
tar xvfz ParaView-5.8.0-MPI-Linux-Python3.7-64bit.tar.gz
```
バージョンは自分のダウンロードしたものに合わせる

#3.Pathを通す
bashrcに以下を追記

```
export PATH=/usr/local/ParaView-5.8.0-MPI-Linux-Python3.7-64bit/bin:$PATH
```
追記後は忘れずにsourceする

```
source ~/.bashrc
```

#4.起動してみる
どのディレクトリでもよいので以下を打つ．

```
paraview
```
動いた
<img width="500" alt="2020-04-28 02-23-32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591933/3b6da042-2b8e-8061-afdc-eb4a9e26c2f7.png">
DDMS覚書

JAVAのランタイムエラーが出たら

AndroidStudio\jre　フォルダをコピー
↓
C:\Users\user\AppData\Local\Android\Sdk\tools\lib\monitor-x86_64　フォルダ内にに貼り付ける。

```
AndroidスタジオがインストールされてるフォルダのJREフォルダをコピーして、
monitor.exe　のある AndroidSDKのパスへペーストすると
DDMSが起動するみたい
```

https://stackoverflow.com/questions/48988385/android-device-monitor-jre-jdk-error
Railsで gem install mysql2 でなかなかうまくいかない件

この記事では RailsでGemを入れる時に`mysql2`がやっかいで入らないのを解決する記事です。
同様の記事はかなりたくさんあるのですが、2020/04/28現在、全部やってもうまくいかなくてGithubのissueとStackOverFlowでなんとかいったのでその紹介です。
mysql5.7や8.0使いたいのに5.6に戻す系は自分的には目的に沿ってないのであくまでもポジティブに攻めてます。（いつも）

# エラー

```
ld: library not found for -lssl
```

特に解決につながった参考記事

 - https://github.com/brianmario/mysql2/issues/795
 - https://stackoverflow.com/questions/57047085/ld-library-not-found-for-lssl-while-installing-mysql2-gem

# やったこと 1 `xcode-select --install`

そもそも、人によってうまくいくパターンが異なるのは、それぞれの環境での「どこまでやったか」が異なることが大きいと思います。

なので、やったことを書いていきます。

```zsh
xcode-select --install
```

そもそもやってないとだめなのかどうか微妙。
これで解決した人もいるらしい。

# やったこと2 `openssl` をインストールしてパス通す
```
brew install openssl
または
brew install openssl@1.1
```

ののち、インストールの最後のログに出るパスを通す。

```
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I/usr/local/opt/openssl/include"
または
export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"
```
私は@1.1で両方やりました。
また、これを プロジェクトルート/.bundle/config に追加するやり方もありますね。
以前はうまくいってましたが、最新PCではこれではうまくいかなくなってました。

# やったこと3 `LIBRARY_PATH`

opensslのインストールののち、

```
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/opt/openssl/lib/
```

# やったこと4 (2)の内容をoptionでつけてgem install

```
gem install mysql2 -- --with-cflags=\"-I/usr/local/opt/openssl/include\" --with-ldflags=\"-L/usr/local/opt/openssl/lib\"
```

これだけだとうまくいかないけど、(3) `LIBRARY_PATH` と両方やるとうまくいった感がありました。
(3), (4)をやれば(1)がいらないのかどうかはもはや不明ですが、ここまででなんとかなりそうだと思ってます。

以上となります。

### PC新調、OSアップデートなどでよくひっかかるこのエラー、ハマる人が減ることを祈ります。
Railsチュートリアル備忘録 -SSL編-

# 初めに
SSL(Secure Sockets Layer)とはーカルのサーバからネットワークに流れる前に、大事な情報を暗号化する技術。ログイン機構をセキュアにしたり、 セッションハイジャック (Session Hijacking) の脆弱性に対しても多くの利点を生み出す
# RailsでSSLを使うことを強制する
```config/environments/production.rb
  config.force_ssl = true
```
# 追加中...
本番用のWebサイトでSSLを使えるようにするためには、ドメイン毎にSSL証明書を購入し、セットアップする必要がある
[Railsの開発環境でHTTPSを有効にする](https://blog.y-yagi.tech/posts/rails_ssl/)
[git] rsa公開鍵を作成

- 開発環境：macbookpro, terminal

ローカルからGithubにPushした際に出たエラー

```
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
```

## id_rsaを更新する
```
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

$ pbcopy < ~/.ssh/id_rsa.pub
```
これでクリップボードにコピーされているので、
Githubの
Settings -> SSH and GPG Keys　へ進み緑のボタンから追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600462/438bf710-fa90-42ea-6194-b416a96d4077.png)

`pbcopy`とすると`cat`して選択してコピーする手間が省ける。


参考：[Permission denied (publickey). fatal: Could not read from remote repository. #23](https://github.com/facebookresearch/deepmask/issues/23)
Pythonにおいて、関数の最後の()はどのような意味でしょうか？

(ほぼ未経験での質問なので、質問の仕方にも不備があるかもしれません…ご了承ください)

〇質問内容
Pythonにおいて、例えば、
rgs=linear_model.LinearRegression()
はrgsというオブジェクトを宣言しているという理解です。
最後の()はどのような意味なのでしょうか？

〇背景

from sklearn import linear_model
rgs=linear_model.LinearRegression
rgs.fit(train_X, train_Y)
print(rgs.coef_)
print(rgs.intercept_)

というコードを書いて、以下のエラーが発生しました。

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-75-bf048a96c6eb> in <module>
      1 from sklearn import linear_model
      2 rgs=linear_model.LinearRegression
----> 3 rgs.fit(train_X, train_Y)
      4 print(rgs.coef_)
      5 print(rgs.intercept_)

TypeError: fit() missing 1 required positional argument: 'y'

結論から言うと、コードの２行目を
rgs=linear_model.LinearRegression()
とすればエラーが発生せず、正しい結果が得られたのですが、どうしてそうなったのかがよくわからず…。
質問見づらく申し訳ありませんが、回答いただけるとありがたいです！よろしくお願いいたします。
ゼロから始めるLeetCode Day5 「1266. Minimum Time Visiting All Points」

#概要
海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

その対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイト。

せっかくだし人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

基本的にeasyのacceptanceが高い順から解いていこうかと思います。

前回
[ゼロから始めるLeetCode Day4 「938. Range Sum of BST」](https://qiita.com/KueharX/items/f0182e346828eb5cfd09)

# 問題
[1266. Minimum Time Visiting All Points](https://leetcode.com/problems/minimum-time-visiting-all-points/)

リストでx軸とy軸の座標が複数与えられるのでその全ての座標へ訪れるための最短時間を求めよ、という問題ですね。

なお、ルールとして、
1秒間に、垂直方向、水平方向に、または斜めに1単位移動できる。
与えられた順番と同様の順番に座標に到達する必要がある
という制約があります。

例１をみると、グラフの最短経路の出し方なんて知らんし・・・となってしまうかもしれませんが、この問題でとりあえず解けるようにするための重要な考え方としては、最短経路を求めるには単純にそれぞれの与えられた座標からより差が大きい方の数値から引けば良いという点です。
ここで大事なのは差をそのまま取得するのではなく、絶対値を取得するということです。

Pythonには組み込み関数で`abs()`があるのでそれを使うだけで大丈夫です。

```Python
class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        sec = 0
        x1,y1 = points.pop()
        while points:
            x2,y2 = points.pop()
            sec += max(abs(x2-x1),abs(y2-y1))
            x1,y1 = x2,y2
        return sec
# Runtime: 56 ms, faster than 84.71% of Python3 online submissions for Minimum Time Visiting All Points.
# Memory Usage: 13.9 MB, less than 100.00% of Python3 online submissions for Minimum Time Visiting All Points.
```

まず`sec`ですが、secondの略で、移動時間の加算のための変数を用意します。

そして今回はスタックのpopを使いました。
Pythonのpopは引数を指定しない場合、末尾（最後）の要素を削除します。

解答のテストケースでは`[[1,1],[3,4],[-1,0]]`が使われているので、この場合はx1,y1には-1,0が代入され、x2,y2には3,4がそれぞれ代入されます。
そしてそれぞれx2からx1を、y2からy1を引いた後、大きい方の数値を抽出するためにmax関数を使い、`sec`に代入します。
その後にx1,y1にx2,y2を代入し、それをpointsの要素数がなくなるまでループさせ、最後に差の最大値の総和である`sec`を返す、という関数です。


以上のようにシンプルな答えにまとまったと思います。

また、for文での回答も作れます。

```Python
class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        sec = 0
        current = points[0]
        for point in points[1:]:
            sec += max(abs(current[0] - point[0]), abs(current[1] - point[1]))
            current = point
        return sec
# Runtime: 64 ms, faster than 32.15% of Python3 online submissions for Minimum Time Visiting All Points.
# Memory Usage: 13.9 MB, less than 100.00% of Python3 online submissions for Minimum Time Visiting All Points.
```

ただ、こちらは少し遅いですね。

スタックの勉強も兼ねて前者のような実装をした方が勉強になって良さげですね。
MacでOSアップデートしたら、Alfredでアプリケーション表示がダブるんですけど？？

# なにが起きたか
MacをCatalinaにアップデートしました。
直後、Alfred4でアプリケーションをひらこうとしたら

  - `/System/Volumes/Data/Applications`
  - `/Applications`

この2箇所に重複表示されるようになった。

# 解決方法
Alfredで`reload`と打つと、`Reload Alfred Cache`が出てくるのでこいつをたたく。
それだけ。
キャッシュの問題だったんですね...。

# 参照
:bow:

https://superuser.com/questions/1454743/why-are-the-apps-in-system-volumes-data-applications-and-applications-the
arxivとACL Anthologyのpdfページからワンクリックでランディングページに遷移するボタン

[arxiv](https://arxiv.org/)や[ACL Anthology](https://www.aclweb.org/anthology)でpdfを見ているときに、bibとかが欲しくてランディングページに行きたいことがよくあります。（e.g., [pdfページ](https://www.aclweb.org/anthology/D15-1075.pdf)から[ランディングページ](https://www.aclweb.org/anthology/D15-1075/)）
このちっちゃい煩わしさを解消するためのボタンを、chromeに設置したのでまとめます。

## chromeのブックマークボタンでjsを動かせる

URLバーの下にある「よく使うサイト」をおいておくブックマークですが、そのターゲットリンクを`javascript:...`とすることで、jsをかんたんに動かせます。
（html内の`<a href="javasctipt:...">`と同じです。）

これを使えば、ボタンを押したときにURLをチェックし、pdfページだったら対応するランディングページに遷移するボタンが作れます。

## 作ったもの

正規表現を使ってやってみました（他の方法でも全然できます）

```js
 const acl_pattern = /(https:\/\/www.aclweb.org\/anthology\/[A-Z][0-9]{2}-[0-9]{4})\.pdf/;
 const arxiv_pattern = /https:\/\/arxiv\.org\/pdf\/([0-9\.]+?)\.pdf/;
 
 const acl_match = window.location.href.match(acl_pattern);
 if (acl_match !== null) {
 	window.location.href = acl_match[1];
 }
 
 const arxiv_match = window.location.href.match(arxiv_pattern);
 if (arxiv_match !== null) {
 	window.location.href = 'https://arxiv.org/abs/' + arxiv_match[1];
 }
```
（普段jsを書かないので、`const`にすべきか`var`にすべきかよくわからなかったが動いたのでokにする）

これを適当にminifyして、ブックマークに追加（`javascript:...`の`...`にminifyした文字列を入れる）すると完成です！
minifyは`js minifier`でぐぐるとツールがたくさん見つかります。

正規表現を追加していけば他のサイトにも対応できます。

## 終わりに
- 論文がpdfのURLで共有されたときに、内心「めんどいな」と思っていたので、同じことを感じている人もいるかと思い共有しました。
- 正規表現はちゃんとチェックしてないので、動かないページもあるかもしれません。
- ブックマークで指定できるURLの長さに制限があると、あんまりたくさんのサイトは追加できないかもしれないです。
- 論文の情報が乗ってるページってランディングページっていうのだろうか？
Promiseを用いる非同期処理

#同期処理と非同期処理

* 同期処理：プログラムを上から下へと順番に処理を行う（途中で時間のかかる処理があるとそれ以降の処理が全てストップしてしまう）．
* 非同期処理：結果を待たずして次に進む処理

```Javascript:
unction asyncFunc(param) {
  // 非同期処理
  setTimeout(() => {
    console.log(param)
  },100)
}

// 順番が前後する例
function test() {
  console.log('1')
  // 非同期処理
  asyncFunc('2')
  console.log('3')
}
test()
```
```:出力
1
3
2
```

##Promiseを用いて非同期処理を実装
非同期処理の実装には，処理（関数）を返却する際にPromiseオブジェクトを用いる．

```Javascript:

function asyncFunc(param) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (param === 'b') {
        //エラー時
        return reject({data: err})
      }
      //正常終了時
      return resolve(param)
    }, 100)
  })
}
```

ここでPromiseオブジェクトについてまとめる．
Promiseオブジェクトは引数に非同期処理である関数のみをとる．また，非同期処理に渡ってくる引数は```resolve```と```reject```のふたつの関数．
```resolve```
非同期処理が成功した際に，resolve関数にその成果となる値を渡す．
```reject```
非同期処理が失敗した際に，reject関数に問題となるエラーオブジェクトを渡す．

##非同期処理とasync/await
非同期処理を実装する```Promise```と```async/await```はセットと考えて良い．
非同期処理において，ある処理を待ってから次の処理に進みたいときに用いるのが```await```であり，またその際に関数の頭につけなければいけないのが```async```なのである．

##thenとcatchとfinally
非同期処理では，それ以降の処理を記述する際にthen/catch/finallyが用いられることがある．
```then```
非同期処理が成功した際にその結果を受けて続けて行う処理．
```catch```
非同期処理がエラーの際に，catchを行うことでエラーオブジェクトを取得可能．
```finally```
非同期処理が成功しても失敗しても必ず行われる処理．

```js:
async function testAwait() {
  const ret1 = await 
  asyncFunc('a')
  console.log(ret1)
 
  const ret2 = await 
  asyncFunc('b').catch(err => err.data)
  console.log(ret2)

  const ret3 = await 
  asyncFunc('c').then(data => data + 'c')
  console.log(ret3)
}
```
```:出力
a
err
cc
```

また，これ以外に複数のPromise処理を連結して行うためのメソッド```all```がある．

```js:
async function testAwait2{
  const rets = await Promise.all([
    asyncFuncPromise('d'),
    asyncFuncPromise('e'),
    asyncFuncPromise('f')
  ])
  console.log(rets)
}
```

```:出力
['d','e''f']
```
日時を日本時間で表示する

## 目的
アプリ内で作成したレコードを表示させる際に、デフォルトのUTC（協定世界時）からJST（日本標準時）に変更し表示させる。

### 準備
事前にアプリケーションの基本的な機能が実装されているものとして話を進めます。
まずユーザーでもなんでもいいので、テーブルにレコードを作成します。
Sequel ProなどのGUIツールで確認すると、`created_atカラム`に日本時間よりも約9時間遅い時間で作成されたことになっているはずです。ここから日本時間で表示する設定をしていきます。

### 手順
`config/application.rb`に以下の記述をします。

```Ruby:config/application.rb
# 省略

class Application < Rails::Application
  config.time_zone = 'Tokyo'

end

```

アプリを立ち上げた段階で既にコードが用意されているので、その中から`class Application`を探し、その中にタイムゾーンの記述をします。

この後、必ずサーバを再起動してから確認してください。でないと表示が変わりません。

また表示方法としては、

```
created_at.strftime("%Y/%m/%d %H:%M")
# →2020/01/01 のように表示できます。
```

などとすることで、見やすい表示となります。



### 補足
GUIツールで確認すると、`created_at`の時間自体は変更後も変わりません。（UTCのまま）
あくまで、画面に表示させるときにUTC（協定世界時）からJST（日本標準時）に変換してくれるようなイメージです。