OmniAICreator/Qiita-1.07M huggingface dataset:
CLOB型の(文字数ではなく)バイト数を返却するファンクションを自作(Oracle Database)

昔の記事（ https://gonsuke777.hatenablog.com/entry/20150129/1422535354 ）が間違っていたので、訂正を兼ねた記事を作成彡(ﾟ)(ﾟ)

CLOB型の(文字数ではなく)バイト数を返却するファンクションを自作してみます。

CONVERTTOBLOBプロシージャでCLOB型をBLOB型に変換して、
そのバイト数をDBMS_LOB.GETLENGTHを変換するやで彡(ﾟ)(ﾟ)

# 1. ファイルのバイト数と中身

下記のUTF-8エンコードのテキストファイル(2057850バイト)をOracle Databaseにロードして検証します。ASCII文字とひらがなと4バイトの文字を混ぜています。

```shell
ls -la clob_test2.txt
-rw-r--r--. 1 oracle oinstall 2057850 Aug 19 22:29 clob_test2.txt

cat clob_test2.txt

aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾…
aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾…
：
aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾…
aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾aaabbbcccあああいいいううう𡚴𡸴𣇄𣗄𣜿𣝣𣳾…
```

テキストファイルのロードは下記記事を参照彡(ﾟ)(ﾟ)

 > DBMS_LOB.LoadClobFromFileプロシージャを使って
 > テキストファイルを Oracle Database の CLOB型列 に ロードする。
 > https://gonsuke777.hatenablog.com/entry/20160815/1471259132


# 2. 自作ファンクションFNC_CLOB_LENBの作成

自作ファンクションの作成、前述した通りCONVERTTOBLOBプロシージャで
CLOB型をBLOB型に変換して、そのバイト数をDBMS_LOB.GETLENGTHを変換してます。

```sql
CREATE OR REPLACE FUNCTION FNC_CLOB_LENB(
  clob_in IN CLOB
)
RETURN NUMBER
IS
  blob_tmp BLOB;
  i_d_offset INTEGER;
  i_s_offset INTEGER;
  i_l_contxt INTEGER;
  i_warning  INTEGER;
BEGIN
  -- Initialize
  DBMS_LOB.CREATETEMPORARY(blob_tmp, FALSE, DBMS_LOB.CALL);
  i_d_offset := 1;
  i_s_offset := 1;
  i_l_contxt := 0;
  -- CONVERT CLOB to BLOB
  DBMS_LOB.CONVERTTOBLOB(
      blob_tmp                   -- dest_lob
    , clob_in                    -- src_blob
    , DBMS_LOB.LOBMAXSIZE        -- amount
    , i_d_offset                 -- dest_offset
    , i_s_offset                 -- src_offset
    , NLS_CHARSET_ID('AL32UTF8') -- blob_csid
    , i_l_contxt                 -- lang_context
    , i_warning                  -- warning
  );
  RETURN DBMS_LOB.GETLENGTH(blob_tmp);
END;
/

Function created.
```

# 3. 検証結果

結果は下記の通り、自作ファンクションの方は ls の結果と一致してるやで！彡(^)(^)

```sql
SELECT DBMS_LOB.GETLENGTH(C2), FNC_CLOB_LENB(C2) FROM TEST_CLOB;

DBMS_LOB.GETLENGTH(C2) FNC_CLOB_LENB(C2)
---------------------- -----------------
               1033498           2057850
```

# 4. 参考

以下のマニュアルと記事を参考にしました彡(ﾟ)(ﾟ)

 > Oracle Database PL/SQLパッケージおよびタイプ・リファレンス 18c
 > 93 DBMS_LOB
 > https://docs.oracle.com/cd/E96517_01/arpls/DBMS_LOB.html#GUID-A35DE03B-41A6-4E55-8CDE-77737FED9306
 > 　
 > oracle CLOBの項目のバイト数を計算するテクニック
 > https://qiita.com/wagase/items/39c29d3720901e6ef331
 > 　
 > Oracle Database SQL言語リファレンス 18c
 > NLS_CHARSET_ID
 > https://docs.oracle.com/cd/E96517_01/sqlrf/NLS_CHARSET_ID.html#GUID-733B03A0-CD66-4645-A323-401A176499E3
AWS EFS の特徴を知る

# 目的
可用性の高いジョブフロー管理システムを作成する際、各サーバでジョブフローの進捗状況をどのように共有するかが問題になる。
この共有方法に EFS が使えないかを検討するために、 EFS の特徴を知る。

# EFS とは？
Amazon Elastic File System の略で、 EC2 で利用するスケーラブルなネットワークファイルシステムを提供する。
2018年5月から東京リージョンでも使用可能となった。

## S3, EBS との違いは？
[aws EFS の公式ページ](https://aws.amazon.com/jp/efs/when-to-choose-efs/)にも説明がある通り、下記のような違いがある。

|  | EFS | S3 | EBS |
|:-:|:-:|:-:|:-:|
| レイテンシ  | 低  | 低  | 最低  |
| スループット  | 数GB単位/sec  | 数GB単位/sec  | 1GB単位/sec  |
| 可用性  | MultiAZ  | MultiAZ  | SingleAZ  |
| アクセス  | 複数EC2・オンプレサーバ  |  ウェブ | 1つのEC2  |

# メリット・デメリット
## メリット
* マネージドサービスなので管理が楽
* 高いレベルの可用性・耐久性がある
* 容量制限がなく、使用量に応じで容量が拡張される
* 利用方法が簡単

## デメリット
* コストが高い。1GB を保存すると、 s3 は約2円、EBSは約10円、EFS は約30円
# 使用方法
* EFS は AWS マネジメントコンソールから簡単に作成できる
* 使用する EC2 に nfs4 を入れる必要がある
* VPC が違う場合は ClassicLink を使ってマウントすれば良い
* [amazon-efs-utils](https://docs.aws.amazon.com/ja_jp/efs/latest/ug/using-amazon-efs-utils.html) を使えば EC2 から簡単に利用できそう

# さいごに
やっぱり複数 EC2 でファイル共有するためには EFS が使いやすそう。
次は実際に EFS を使って高可用性なワークフローシステムを作成してみる予定。
Azure Logic Appsのエラーを監視する

Logic Appsは各種サービスを繋げて利用することができる便利なサービスです。
なんらかのエラーでLogic Appsが失敗した場合に検知できるように監視設定を加えたいと思います。

# アラート作成

* Logic Apps画面より[アラート]を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/3a4c1bb5-e290-1891-da78-0f31c34aac30.png)

* [メトリックアラートの追加]を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/d1df589c-a60e-4737-d16b-87984a83101d.png)

* メトリックで[Runs Failed]を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/fd47ac0f-eb77-58fc-27be-907108b22d14.png)

* 条件を[次の値以上]に、しきい値を[1]に設定します。つまり、1回でもRuns Failedがカウントアップされたら発火するという条件です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/a46d3803-3db7-a948-6701-f2f0fcb5187d.png)

* 期間ですが、ここは監視要件に合わせて選択します。[直近5分]を選択した場合は、直近5分間で1回でもRuns Failedがカウントアップされたら発火するという意味になります。メトリックの仕様で1分毎に見にいくことになっているので、直近5分にした場合は、最短で6分後に検知するという意味ですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/10f5456c-c485-f852-c060-fe3d2ebdb473.png)

* 通知手段（メールなど）のその他の項目は要件に合わせて設定しましょう。

# 失敗系のメトリック
Logic Appsのメトリック一覧を見ると、失敗関連では以下の3つのメトリックが該当します。

* Runs Failed
* Triggers Failed
* Actions Failed

例えばSQL Databaseから1行取得してメールするというようなLogic Appsがあった場合の、各メトリックは以下のポイントを指しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/1126f8aa-9c0a-294f-9a53-9ff3cf88e744.png)

もし[1行を取得]アクションが失敗した場合、[Actions Failed]と[Runs Failed]メトリック値がそれぞれ1カウントアップされます。
両方のメトリックを監視するとアラートが重複しますね。

なのでLogic Appsワークフロー自体が失敗したことを検知する場合は、Runs Failedメトリックを監視しておけばよいかなと思います。

# Datadogで監視する場合

* [azure.logic_workflows.runs_failed]メトリックを監視してアラートを出します。  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/a5c14870-28d4-5254-71bc-4c15ac3b2d20.png)
MySQL接続時のPHP7とPHP5のコーディングメモ

####初めてQiitaに投稿します
ちょうど盆休みだったので、全く経験のないPHPでMySQLを連携させた簡易システムを作ってみました。
その際苦労した部分としてMySQL接続が上手くいかなかったので、その時の解決方法のメモ残したいと思います。

####私の開発環境
開発環境
XAMPP:7.2.8
Apache: 2.4.34
MariaDB(以下MySQL):10.1.34
PHP:7.2.8
OS:Windows10


###DB接続が上手くいかなかった原因
まずDB接続が上手くいかなかった原因としては、参考にした書籍のXAMMPが古く、
PHP5.3.5に対応した記述のままだった為、PHP7.2.8に対応する記載に変える必要があった。


###今回の目的
PHP5.3.5のMySQL接続の部分をどのようにPHP7.2.8対応に書き換えればいいか記載してみたいと思います。

#元のコード

```
//PHP5.3.5.ver

<?php

//省略

//DB接続
$dsn = 'mysql:dbname=sampledb;hoat=localhost';
$user = 'root';
$password='';
$dbh = new PDO($dsn,$user,$password);
$dbh->query('SET NAMES utf8');


//  ～SQLの指令を記載～ //

//切断
$dbh = null;
?>

```

上記のコードをXAMPP:7.2.8の環境で実行してみましたが、うまく動作しなかったので
下記のコードに改良してみました。


##PHP7.2.8でMySQL接続できたコード

```
//PHP7.2.8.ver

<?php


//DB接続定義  
$db_user ="root";
$db_pass ="";
$db_host ="localhost";
$db_name ="phptest";
$db_type ="mysql";

//DSN組み立て
$dsn = "$db_type:host=$db_host;dbname=$db_name;charset=utf8";

//DB接続
try{

$pdo = new PDO($dsn,$db_user,$db_pass);

$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

print '接続に成功しました';

}catch(PDOException $Exception){
die('接続に失敗しました');
}


//  ～SQLの指令を記載～ //


//DB切断
$pdo =null;

?>

```


上記のように書き換えたらうまくMySQLの連携がうまくいきました。


今回突発的にPHP7をいじってみましたが、MySQL連携の構文とか
前のバージョンでは動いていた構文が新バージョンでは動かない
こともあるというのは大いに勉強になりました。もちろん、やりようによっては
動かせることもあると思いますが、PHP触って5日の人間には現状ここまでの考察が限界でした。
VSCodeのターミナルをWSLのものにする

## ターミナルの変更
VSCodeのターミナルを Windows Store からダウンロードできるbashに変更する方法。

VSCodeの設定を開き、
	"terminal.integrated.shell.windows": "C:/Windows/Sysnative/bash.exe",
とする。
C:/WIndows/System32/bash.exe とする記事も多いが、これは store のものとは別。
特に bash on windows の頃からやったぜ！ と食いついていた人は注意。

参考：
[How do I use Bash on Ubuntu on Windows (WSL) for my VS Code terminal?](https://stackoverflow.com/questions/44450218/how-do-i-use-bash-on-ubuntu-on-windows-wsl-for-my-vs-code-terminal)

なお、こちらに同じものを公開しています
[VSCodeのターミナルをWSLのものにする](http://blog.xhift.com/2018-08-20/change_vscode_terminal_to_wsl/)


---
お仕事募集しております
[株式会社xhift](http://xhift.com/)

北千住でコワーキングスペースも運営しておりました。再開したい！
[Bono Prince(ぼのプリ)](http://xhift.com/bonopri/)

---
git push origin masterでPermission denied (publickey)が表示された


```
$ git pull origin master
Permission denied (publickey).
fatal: Could not read from remote repository.
```

と表示された時の対処法。
理由はよく分からないですが対処法だけ書きます。

```terminal
$  cd ~ #cd~はホームディレクトリに移動,windowsならcd..で親ディレクトリに移動できる
$  cd .ssh
$ ssh-keygen -t rsa -C "自分がgithubに登録したアドレス"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/user/.ssh/id_rsa):
/Users/user/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase): #空欄で可
Enter same passphrase again: #空欄で可
Your identification has been saved in /Users/user/.ssh/id_rsa.
Your public key has been saved in /Users/user/.ssh/id_rsa.pub.
...以下略
```
エクスプローラーを開いてローカルディスクを選択。

![Image 20180819 234038.jpg](https://qiita-image-store.s3.amazonaws.com/0/169545/b98a6401-97a9-a95a-4aee-f0418c86ee48.jpeg)
ユーザ>Owner>.sshに移動。
id_rsa.pubをメモ帳などで開く。
中身をコピーする。
[github](https://github.com/)からsettingの中のSSH and GPGkeysを選択。
New SSH keyをクリック。タイトルのところを適当に入力し、keyのところに先ほどコピーしたものを貼る。
![2018-08-20 (2).png](https://qiita-image-store.s3.amazonaws.com/0/169545/2cc44460-1c12-7bc9-9693-2093b4592cc4.png)

これで元通りにpushできるようになったと思います。
##参考
[gitへpushできないときの対処法](http://blog.just1factory.net/programming/131)
機密解除された「1,300万ページのCIA文書」がオンラインで公開されたので、それにあやかってデータを取ってみる

#好評されたCIAの機密文書
　スノーデン氏がリークしてからというもの、Appleのローンチのように徐々に公開されてきた機密文書。
　今回はオンラインで公開（前は知らない）されたので、機械学習で使えるかも？なんて思いスクレイピングでデータを取ることにしました。

#環境
- Python 3系
- Chrome Driver(Selenium)

#ページ数が94015ページとたいへん多くて時間がかかる
　いまのところ１ページ4 sec.くらいで終わっているので、全体のデータが取得できるのに５日くらいかかる。
　自分の端末だけでいまのところ動かす予定だが、何か良い方法がないだろうか・・・
※ページ数が多いためPDFのダウンロードについては行わず、PDFのhrefを取得して一括でダウンロードする予定。

ソースはこちら↓
https://github.com/chibadai/selenium_PDF_Downloader/blob/master/download_cia_pdf_pre.py
stack-polymorphicについて

次の2つはどちらもコンパイルが通る

```lisp
(module
  (func (export "test") (param $i i32) (result i32)
    (block (result i32)
      i32.const 1
      br 0
      ;;i32.const 2
    )
  )
)
```

```lisp
(module
  (func (export "test") (param $i i32) (result i32)
    (block (result i32)
      i32.const 1
      br 0
      i32.const 2
    )
  )
)
```

バグかと思ったが、仕様に書いてあった。

https://www.w3.org/TR/wasm-core-1/#-href-syntax-instructionshtmlsyntax-instr-controlmathsfbrl

![WebAssembly_Core_Specification.png](https://qiita-image-store.s3.amazonaws.com/0/5978/dbac84d6-8eba-ac7e-13da-21e9b35b6434.png)

https://www.w3.org/TR/wasm-core-1/#instructions%E2%91%A2

![WebAssembly_Core_Specification.png](https://qiita-image-store.s3.amazonaws.com/0/5978/28997fb6-7a20-dfb7-e076-3cf80d0420e6.png)

stack-polymorphicというのがよくわからないのですが、後続の命令の引数に対して「齟齬がない限り」どんな型とでも考えてもらっていいよ、ということのようです。

このblockの返り値が[i32]であれば良いので、こちらであればbrの型は[i32]->[i32]となり、

```lisp
    (block (result i32)
      i32.const 1
      br 0
    )
```

こちらであればbrの型は[i32]->[]となる。

```lisp
    (block (result i32)
      i32.const 1
      br 0
      i32.const 2
    )
```

unconditional control transfer（問答無用でジャンプする）のときにしか使われないようなので、実質的にはその後の命令は型チェックだけすれば良くて、実装はしなくて良い。
【Rails】関連付けされたモデルのCSVインポートの方法は？

Item（商品）登録時に親モデルであるShop（店舗）、子モデルであるship_date（出荷日）を同時に一括でCSVインポートしたいと考えています。

現状、shop_idを含めたアップロードまでは成功しましたが、子モデルである「ship_date（出荷日）」を含める方法で行き詰まっています。


もしご存知でしたらご教示頂けますと嬉しいです！

```Ruby:item.rb
belongs_to :shop
has_many   :ship_date

  def self.import(shop, file)
    CSV.foreach(file.path, headers: true) do |row|
      item = find_by(id: row["id"]) || new
      shop.items.create! row.to_hash.slice(*updatable_attributes)
    end
  end

  def self.updatable_attributes
    ["name", "kana", "price"]
  end
```
```Ruby:items_controller.rb
  def import
    Item.import(@shop, params[:file])
    redirect_to root_url, notice: "商品を一括で追加しました。"
  end
```
PHPでlaravel使ってみた

PHPフレームワークのlaravelを使ってみた。

### 環境

- Mac High Sierra 10.13.5
- PHP 7.1.16
- composer 1.5.6
- laravel 5.6.33

### 手順

- composerの導入確認    
laravelはcomposerのコマンドを使って入れるので、まず、composerが入っていることを確認

```bash
$ composer -V
Composer version 1.5.6 2017-12-18 12:09:18
```

- laravelのプロジェクト作成

```bash
$ composer create-project --prefer-dist laravel/laravel [プロジェクト名]
Installing laravel/laravel (v5.6.33)
  - Installing laravel/laravel (v5.6.33): Downloading (100%)
Created project in [プロジェクト名]
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 70 installs, 0 updates, 0 removals
  - Installing vlucas/phpdotenv (v2.5.1): Downloading (100%)
...
..
```

- インストールすると以下のようなディレクトリ、ファイルが作成される
（下記は第一階層だけ）

```bash
.
├── app/
├── artisan
├── bootstrap/
├── composer.json
├── composer.lock
├── config/
├── database/
├── package.json
├── phpunit.xml
├── public/
├── readme.md
├── resources/
├── routes/
├── server.php
├── storage/
├── tests/
├── vendor/
└── webpack.mix.js
```

- ローカル開発サーバ起動

```bash
$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>
```

- ブラウザで http://127.0.0.1:8000 とすれば、サンプル画面が表示される

### 参考
https://qiita.com/da-sugi/items/7ee7a458aad4209bab01
https://readouble.com/laravel/
webRTC 超低遅延化を目指して VRのサーバー処理

スマホVRは、手軽で楽しいが処理能力の制約がある。また、360度映像の配信において、360度全ての映像を常に送り続ける必要はない。
つまり、見ている方向を検知してその部分だけの映像を遅れるようにすれば、映像のサイズも小さくなるので遅延が少なくなるはず！(配信側PCのCPUは上がると思うが)
全て、コンピューターでやって映像だけ送ってしまおう！
そうすれば超低遅延化できるはず！　という記事のまとめです。

[webRTC 超低遅延化を目指して VRのサーバー処理(1)](https://qiita.com/kiyu_knowledges/items/1f91bf115b79250c4ed8) [更新 : 2018.08.19]

- 方法を探る
    - どのアプリケーションを使うか
- Unityからクライアントまで
    - Unityで360度映像を表示する
        - Unityのダウンロード
            - 独り言
        - sphereに360度映像を貼り付ける
    - Unity内部のカメラ映像をsyphon経由で出力する
        - 問題
            - CamTwistを二回経由する問題
        - 改善
            - 360度映像をUnityで再生する

[webRTC 超低遅延化を目指して VRのサーバー処理(2)](https://qiita.com/kiyu_knowledges/items/7090c21c913dd103fb13)[更新 : 2018.08.20]

 - 双方向通信
    - Unity内のカメラと視聴デバイス同期
        - 方法
            - websocketによる通信
        - カメラ姿勢の同期
            - スマホの姿勢推定
                - A-Frameを使う
                    - A-frameのバグ?
            - クライアント → サーバー
            - サーバー → Unity
        - アスペクト比を同期する
            - クライアント側
            - Unity側
    - Unityから送信した映像を表示する
        - CamTwist → 配信用ブラウザ → クライアント
    - テスト

webRTC 超低遅延化を目指して VRのサーバー処理(3)

 - 双方向通信の改善
    - Syphonの出力サイズをインタラクティブに変更する
wheneverを使って設定したcronをDocker上で動かす

## やりたいこと

* cronを使ってRailsのRakeタスクを動かしたい
* crontabにはRailsの[whenever](https://github.com/javan/whenever)を使って設定したい
* Docker環境で動かしたい

productionで使う予定はないので雑に解決してしまったが、ひとまず動いた方法をメモする

## 解決策概要

* Dockerfileでcronをインストール
* Dockerfile上で`whenever --update-crontab`する
* cronをフォアグラウンドで動作させる
  * Dockerだとcron動かない問題解消のため
* wheneverによるcron設定時に環境変数を渡す
  * cronから環境変数が見えなくてrakeが動かない問題解消のため

## 結果

各種ファイルはこんな感じ

``` Dockerfile
# Dockerfile
FROM ruby:2.5.1
RUN apt-get update -qq && apt-get install -y build-essential
RUN apt-get install -y cron # cronインストール
RUN mkdir /app-name
WORKDIR /app-name
ADD Gemfile /app-name/Gemfile
ADD Gemfile.lock /app-name/Gemfile.lock
RUN bundle install
ADD . /app-name

RUN bundle exec whenever --update-crontab # wheneverでcrontab書き込み
CMD ["cron", "-f"] # cronをフォアグラウンド実行
```

``` config/schedule.rb
ENV.each { |k, v| env(k, v) } # 環境変数をwheneverにいい感じに書き込んでもらう
set :output, error: 'log/crontab_error.log', standard: 'log/crontab.log' # ログを書き出すようにしておくとデバッグが楽
set :environment, :development

every 1.minute do
  rake "task:name"
end
```

``` docker-compose.yml
version: "3"
services:
  app:
    build: .
    container_name: app-name
    ports:
      - "3000:3000"
    tty: true
  db: 
    # 他コンテナの記載は省略
```

## その他

* デバッグ時は立ち上げたコンテナに`docker exec -it app-name bash`とかでアタッチしてがんばる
  * `crontab -l` でcrontabに書き込まれたか確認
  * catコマンドで`config/schedule.rb`で設定したログファイル確認

## 参考資料


* https://stackoverflow.com/questions/43559233/rails-whenever-and-docker-cron-tasks-doesnt-run
* https://blog.fakiyer.com/entry/2016/04/05/205206
* http://www.cotegg.com/blog/?p=1606
* http://miyasakura.hatenablog.com/entry/2017/04/10/173827
LINE APIを触ったことないやつがRepl AIを使って基本的なBOTの開発をするまで～その１～

#はじめに
　先日参加した【大阪】Bot Developers Meetup - LINE Bot開発者の勉強会でチャットボットの話題が出てまだ触ったことがなかったので作ってみることにした。
参加したイベント：https://line.connpass.com/event/95135/

#書く理由
　記事を見てると、「LINE Devに登録」とか環境周りについては所見では止まる箇所が多いと思ったためこの記事で保管できれば、というモチベーションで書いてます。

#道のり
- LINE Developerへ登録
- LINE@でやりとりをプログラムでできるようにする
- Repl AIを使ってBOTの作成

#参考にした記事

https://tech.plaid.co.jp/making-line-bot-in-five-minutes/
・herokuのチュートリアルページ
https://devcenter.heroku.com/articles/getting-started-with-python
・
https://qiita.com/krocks96/items/67f7510b36945eb9689b#_reference-867c95b75a67b2cfc29c


#止まったところ

- LINE DeveloperとLINE@Managerでそれぞれが連携して設定をしなければいけないところ
- herokuを使ったgitでのdeployが、チュートリアルの途中でエラーが起こったこと

↓
↓
↓
↓
↓
↓
↓


#herokuのリモートリポジトリでfatal errorが出たときのコマンドサンプル
・http://nao3-nao3.hatenablog.com/entry/2018/01/17/122333
・https://stackoverflow.com/questions/18406721/heroku-does-not-appear-to-be-a-git-repository

```error.windows
fatal: 'yourappname' does not appear to be a git repository
fatal: Could not read from remote repository.

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

```対応コマンド.windows
heroku git:remote -a yourappname
```
UWSCのマクロ作成について

Windowsアプリケーションで3000個のデータを作成するタスクが舞い込んできたわけですが、手作業ではやってられない&毎年発生する業務なので、UWSCのマクロを書き自動化しました。その際に感じた反省点や雑感などをダラダラ書きます。

## 反省点

### Option Explicitを文頭に付けるべきだった。
VBAとかも同じですが、文頭にOption Explicitを書くことで変数宣言を強制でき、可読性の向上が期待できます。

### KBD関数を使う時はSENDSTRを使えないか考えるべきだった。
パスワードで英数字を入力する際にKBD関数で仮想キーを送信する方法を最初は考えますが、押すボタンの数だけ行がかさみ可読性が落ちます。

```uwsc:FillPassword.uws
//0を5回入力する(Before)。
KBD(VK_0,click,10)
KBD(VK_0,click,10)
KBD(VK_0,click,10)
KBD(VK_0,click,10)
KBD(VK_0,click,10)

//「;」を使って1行で書けっちゃ書ける。
KBD(VK_0,click,10);KBD(VK_0,click,10);KBD(VK_0,click,10);KBD(VK_0,click,10);KBD(VK_0,click,10);

//0を5回入力する(After)。
SENDSTR(GETID("タイトル名","クラス名"), "00000")
```

また、KBD関数はWindowのIDを指定できないので、そのとき前面にあるWindowに仮想キーを送信します。KBD関数はあまり使わない方が吉と考えます。

### GETID関数で値が帰るタイミングとボタンが入力できるタイミングは一致しない。
当たり前ですが、これを考慮せずにスクリプトを書くと結合テストでエラーが出ます。

```uwsc:ExecuteApp.uws
//GETIDの第３引数に−1でアプリケーションが起動するまで待つ。
GETID("タイトル名","クラス名",-1)
SLEEP(2)
```

アプリ起動後にSLEEP関数で2秒くらい待ってあげるとエラーがでる確率が下がります。

### 画面解像度に依存させるべきでなかった。
画面サイズが1920×1080ならうまく動くけど、より小さいサイズでリモート画面を立ち上げると動かなくなることがあります。録画機能をベースにスクリプトを作成する際、ACW関数でWindowのサイズと位置が操作されますが、これは画面解像度に依存しているので注意が必要です。MOUSEORG関数を使えばアプリを中心に相対座標指定できるらしいです。

## TIPS

### カレントディレクトリは実行するスクリプト(.uws)の配置場所。
uwsc.exeの格納場所がカレントになると思いこんでましたが、実行するスクリプトを格納するディレクトリがカレントになるみたいです。スクリプト内でEXEを呼び出す際は相対パスで書いてあげると配布しやすくなり、幸せになれますね。

### ログオフした状態では仮想キーの送信などができない。
スクリプト実行中にログオフやmstscのリモート接続の切断、最小化をすると、スクリプトは動いているが、仮想キーの送信などの操作がされない状態になります。たしかに、[公式サイト](http://www.uwsc.info/faq.html#N44)にも「BTN, KBD, CHKIMG等」がログオフ状態では使えないと書いてある。プロファイルがアンロードされた状態では画面を操作できないのかな？

### 使ったツールとか。
Visual Studio2012未満を使っているなら、標準で「Spy++」というツールがダンロードされていると思いますので、そのツールでGETID関数使用時に必要なタイトル名とクラス名を取得できます。Windows SysinternalsのProcess Monitorでも同じような機能が使用可能です。
ウィンドウハンドルに送っているメッセージの中身も確認することができます。

## 雑感

### 画像認識について
RPAの醍醐味である画像認識の機能がUWSCにもあります。気になる精度についてですが、悪くないと思いました。簡単なことしかしていませんが、不具合もなく、うまく動いてくれました。

### PowerShellとの連携について
PowerShell関数を使えば、PowerShellのスクリプトを直接呼び出すことができます。TEXTBLOCKの中にスクリプトを書くことでファイルを分けずに済みます。ただし、引数にパスを与える時は工夫しなくてはいけないため、骨が折れます。

### UWSCが持つ組み込み関数について
以下の点について不満に感じました。

* ウィンドウハンドルに直接メッセージを送る機能がない。
* 一括で取得したWindowsハンドルのIDを返す機能がない。

逆に以下の点はうれしい機能でした。

* ショートカットキーを押下できるSCKEY関数がある。
* GETSLIDERでスクロールバーの状態を確認できる（ただし、SETSLIDERの機能が貧弱）。

### やっぱ、UIPathすげー
ライセンスの問題がなければ、UIPathを使いたかった。細かい制御をあまり意識することなく、そこそこな機能が実装できます。UWSCの場合、少し凝った操作をするためにはWindowsの細かい知識(ハンドルとか)が必要になることがあるように思いました。
Firebase&PolymerでWebアプリを始める

#Polymerのインストール

##Polymer CLIのインストール

node.jsのバージョンを確認
`node --version`

※node.jsが入っていない場合は、[こちら](https://nodejs.org/ja/)からインストール

npmを最新版をインストール
`npm install npm@latest -g`

gitのバージョンを確認
`git --version`

※gitが入っていない場合は、[こちら](https://git-scm.com/downloads)からインストール

Bowerの最新版をインストール
`npm install -g bower`

Polymer CLIをインストール
`npm install -g polymer-cli`

※Polymer CLIのインストール時にエラーが出る場合は、node.jsのバージョンを落としてから再度試す。過去バージョンのインストールは[こちら](https://nodejs.org/ja/download/releases/)

##Polymer本体のインストール

Polymerをインストールするフォルダを作成
`mkdir polymer-20-test`

作成したフォルダに移動
`cd polymer-20-test`

Polymerを初期化
`polymer init`

※Polymer2を選択(polymer-2-starter-kit)

ローカルサーバを起動
`polymer serve`

#Firebaseを始める

##プロジェクトを始める

Firebaseのサイトにアクセス [こちら](https://firebase.google.com/)

「スタートガイド」から「**プロジェクトを追加**」を選択

- プロジェクト名
- 地域 / ロケーション

を入力・選択し、同意のチェックボックスにチェックを入れて、「**プロジェクトを作成**」をクリック

#PolymerにFirebaseを追加

##polymerfireをインストール

インストールは[こちら](https://www.webcomponents.org/element/firebase/polymerfire)

**DOWNLOAD**からコマンドをコピーしてペースト

src/my-app.htmlにpolymerfireをインポート
`<link rel="import" href="../bower_components/polymerfire/polymerfire.html">`

firebase-appのタグを追加

```html:my-app.html
<firebase-app
  auth-domain="polymerfire-test.firebaseapp.com"
  database-url="https://polymerfire-test.firebaseio.com/"
  api-key="AIzaSyDTP-eiQezleFsV2WddFBAhF_WEzx_8v_g"
  storage-bucket="polymerfire-test.appspot.com"
  messaging-sender-id="544817973908">
</firebase-app>
```

Firebaseの、Project Overviewから「**ウェブアプリにFirebaseを追加**」をクリック

firebase-appのattributeを自分のプロジェクトのものに書き換えていく
Azure Kubernetes Dashboardの起動

#概要
Microsoft Azure Kubernetes Dashboard の起動方法を紹介します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/71e1292c-5f3e-d27b-07e2-c8a24aeb00ea.png)


#1. AzureにKubernetes serviceを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/5c1bd4bf-b164-0bf0-cf26-6c0add3742a5.png)


#2. Clusterができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/5dfb6c9b-fd13-2b31-7f63-295d63c49f7b.png)

#3. Kubernetes ダッシュボードを表示をクリックすると手順が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/036a4204-5f3e-23e8-9206-90f0e21b9a4e.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/8a80115b-5571-1e3a-1179-f6f68b5040fc.png)

#4 Azure CLI 2.0のインストール
https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli?view=azure-cli-latest

#5 Azure CLI 2.0の起動
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/67cdf8ad-1b0d-9ed3-d1c7-d8074f28e4b3.png)

#6 ログイン
```powershell:
az login
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/07c31735-4d7d-9909-b2cf-beacaed6ca41.png)


#7. CLI に kubectl がまだインストールされていない場合、次のコマンドを実行します。
azure-kubctlをインストールします。パスを設定します。

```powershell:
az aks install-cli
set path=%path%;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Users\admintemp\.azure-kubectl
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/c48bf2b8-d5b4-790f-d5e3-b6f195d95b17.png)


#8. 次のコマンドを実行して、クラスターの資格情報を取得します。

```powershell:
az aks get-credentials --resource-group test-snoro-aks --name cluster1
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/3594be8f-0398-8d70-0a91-39eed8756d0e.png)

#9. 次のコマンドを実行して、Kubernetes ダッシュボードを開きます。
```powershell:
az aks get-credentials --resource-group test-snoro-aks --name cluster1
```
Azure Kubernetes Dashboardが起動しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/0b08c3f6-d4c1-e658-61ed-822d9d4adb6e.png)


#10. ノードが３つ出来ています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/1e923e05-4951-5075-3966-84717eb4eac3.png)


Azure上では仮想マシンが3つできています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/d5f60879-daac-1bd0-8f9d-ff3c958b8396.png)

OSもLinuxです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154505/673e9aa6-9bca-7c58-8d72-97fb0dcb64b9.png)
Node.js向けORM Objection.jsを使ってみた(7) - Eager loading

## Eager loading

QueryBuilderのeagerメソッドを使用することで、Eager loadingを実行できます。

Eager loadingを使用することで、N+1問題を解決できます。

## 使用例

### 単一のリレーションを取得する

eagerメソッドの引数に、リレーション名を指定する。
(ModelのrelationMappingsプロパティのキーを指定する)

```javascript
const projects = await Project.query()
  .eager('tasks');

console.log(
  projects.every(
    project => project.tasks.every(task => task instanceof Task)
  )
); // true
```

デフォルトでは、以下のようなSQLが実行される。

```sql
select "projects".* from "projects";

select "tasks".* from "tasks" where "tasks"."projectId" in (1, 33, 34);
```

### 2つ以上のリレーションを同時に取得する 

`[]`で囲み、カンマ区切りで複数のリレーション名を指定する。

```javascript
const projects = await Project.query()
  .eager('[tasks, members]');

console.log(
  projects.every(
    project => project.tasks.every(task => task instanceof Task)
  )
); // true

console.log(
  projects.every(
    project => project.members.every(member => member instanceof User)
  )
); // true
```

デフォルトでは、以下のようなSQLが実行される。

```sql
select "projects".* from "projects";

select "tasks".* from "tasks" where "tasks"."projectId" in (1, 33, 34);

select "users".*, "projectMembers"."projectId" as "objectiontmpjoin0" from "users" inner join "projectMembers" as "projectMembers" on "users"."id" = "projectMembers"."userId" where "projectMembers"."projectId" in (1, 33, 34);
```

### 入れ子になったリレーションを取得する

eagerメソッドの引数として、各リレーション名をドットでつないだ文字列を渡す。

```javascript
const projects = await Project.query()
  .eager('members.tasks');

console.log(
  projects.every(
    project => project.members.every(
      member => member.tasks.every(task => task instanceof Task)
    )
  )
); // true
```

デフォルトでは、以下のようなSQLが実行される

```sql
select "projects".* from "projects";

select "users".*, "projectMembers"."projectId" as "objectiontmpjoin0" from "users" inner join "projectMembers" as "projectMembers" on "users"."id" = "projectMembers"."userId" where "projectMembers"."projectId" in (1, 33, 34);

select "tasks".* from "tasks" where "tasks"."assignedTo" in (1, 2, 23);
```

### 特定のリレーションに対してフィルターを適用する

modifyEagerメソッドを使用する。

```javascript
const projects = await Project.query()
  .eager('members.tasks')
  .modifyEager('members.tasks', builder => {
    // projects[].members[].tasksを、締め切りの昇順で並び替える
    builder.orderBy('deadline', 'asc');
  });
```

デフォルトでは、以下のようなSQLが実行される。

```sql
select "projects".* from "projects"

select "users".*, "projectMembers"."projectId" as "objectiontmpjoin0" from "users" inner join "projectMembers" as "projectMembers" on "users"."id" = "projectMembers"."userId" where "projectMembers"."projectId" in (1, 33, 34);

select "tasks".* from "tasks" where "tasks"."assignedTo" in (1, 2, 23) order by "deadline" asc;
```

## 参考

https://vincit.github.io/objection.js/#eager-loading
less/moreコマンドのシンタックスハイライト等設定

## 背景
GNU source-highlightを使うと、コードをlessやmoreで見るときに色付けしてくれるらしい。
便利そうなので試してみる。

## 出来上がり例
手元の環境でのスクリーンショット。
<img width="322" src="https://qiita-image-store.s3.amazonaws.com/0/133931/e4956ab1-13c7-953c-7fff-4f4b7b4bf126.png">

## MacOS（homebrew）でのインストール

```shell
brew install source-highlight
```

homebrewの場合。
手元の環境だと/usr/local/bin/にsrc-hilite-lesspipe.shが出来る。


## 環境変数設定
src-hilite-lesspipe.shへのパスは通ってる前提。

lessだけ、色付けだけの最低限の場合。
環境変数でMOREも設定しないとmoreでカラーにならなかった。

```shell
export LESSOPEN="| src-hilite-lesspipe.sh %s"
export LESS="-R"
export MORE="-R"
```

その他の設定をつけた場合。

```shell
export LESSOPEN="| src-hilite-lesspipe.sh %s"
export LESS="-MR"
export MORE="--quit-if-one-screen -MR"
```

-Mは画面下で表示してくれる情報を増やす。
--quit-if-one-screenで1画面に収まる場合にはmoreを自動で終了。閲覧のためのcatみたいな使い方が出来る。

## 参考
[[Qiita] エンジニアなら知っておきたい lessコマンドtips 11選](https://qiita.com/ine1127/items/64b5b6cf52471c3fe59c)
[[Qiita] lessコマンドを少し便利にしておく](https://qiita.com/hatchinee/items/586fb1c4915e2bb5c03b)
WiFi・スマホ連携対応のアクションカメラのライブ映像をPCから見る


アクションカメラをUSBカメラとしてではなくWiFiでPCに接続して、映像をストリーミング再生したいが、PC用のアプリがない、Webブラウザから閲覧できない、PCからの接続方法が公開されていない等の場合にとる手順をメモしておきます。Crosstour CT7000(GoProクローンのアクションカメラ) + Packet Capture(パケット解析用Androidアプリ) + Windows PC + VLCメディアプレイヤーの組み合わせでのみ確認しましたが、他のアクションカメラでも同様につなげられると思います。また、この方法はWiFi対応の監視カメラでも使える場合があります。

# 大まかな手順
1. アクションカメラとスマホを任意の専用アプリで連携し、その通信のパケットをキャプチャする。
2. キャプチャしたパケットの情報をもとにカメラのRTSPのURLを確認する。
3. 2.で確認したURLをVLCメディアプレイヤーに入力してストリーミング再生させる。

# 具体的な手順
1. スマホ上でPacket Captureを起動し、画面上部右上の「▶1」アイコンをタップする。
2. アプリの一覧が出るので、アクションカメラ用のアプリを検索し、選択する。
3. 該当アプリのパケット監視が始まるので、アクションカメラとスマホをWiFiでつなげ、アプリでストリーミング動画を閲覧する。
4. すぐにパケットがとれ始めるので、Packet Captureに戻って最新のキャプチャを選択する。
5. ポート番号が「554」のパケットがRSTPに関するものなので、これを選択する。
6. URLを探し、「rstp://」から「?」の1字前までを控えておく。(例: rstp://192.168.1.1/MJPG)
7. PCからWiFi経由でアクションカメラに接続する。
8. VLCメディアプレイヤーを起動する。
9. メニューバーから「メディア」>「ネットワークストリームを開く」の順にクリックし、ダイアログが表示されたら6.で控えたURLを入力し、「再生」ボタンをクリックする。
10. 動画の再生が開始する。
Python3とBeautifulSoupとrequests使ってブクログの本棚に本を登録

# はじめに
図書館で借りた本のログを取りたいなと思い、ブクログに本を自動で登録できないか確かめてみた。
最近さぼりがちだけど、昔からブクログ使ってるので、これができれば、もっと楽にログを残せそう。

# コード
こんな感じ。
ログインして、`keyword`で検索して一番最初に出てきた結果の`id`を取得して本棚に`add`する。

```python
from bs4 import BeautifulSoup
import requests

payload = {
    'service':'booklog',
    'ref':'',
    'account':'xxx',
    'password':'yyy',
}

s = requests.Session()
res = s.post('https://booklog.jp/login/login', data=payload)
res.raise_for_status()
# print(res.text)                                                                    

payload1 = {
    #    'keyword': 'AI',                                                            
    'keyword':'超AI時代の生存戦略 : 「2040年代」シンギュラリティに備える34のリスト \\
大和書房',
    'service_id':'1',
    'index':'Books',
}

res = s.get('https://booklog.jp/search', params=payload1)
res.raise_for_status()
# print(res.text)                                                                    
soup = BeautifulSoup(res.text)
book_id = soup.find_all('a',class_='add-item')[0].get('href')
# print(book_id)                                                                     

payload = {
    '_method': 'add'
}

res = s.post('https://booklog.jp' + book_id, data=payload)
res.raise_for_status()
# print(res.text)                                                                    
```

いい感じに本棚に登録されたことを確認した。

# おわりに
前回、図書館の貸出図書リストを取得できたので、これと繋いで、うまいことやろうと思う。

[Python3とBeautifulSoup使って図書館で借りた本をスクレイピング - Qiita](https://qiita.com/iton/items/047dbf5aa4c07434be5e)

ブクログの利用規約見ると、サーバーに大きな負荷かけなかったら問題なさそう。
責任はおえないけど。
https://booklog.jp/term
第11条（禁止事項）

# 参考
[ブクログ Webやアプリで本棚管理できる/読書好きのためのブックレビューコミュニティ](https://booklog.jp/)
[Requests の使い方 (Python Library) - Qiita](https://qiita.com/sqrtxx/items/49beaa3795925e7de666)
[PythonとBeautiful Soupでスクレイピング - Qiita](https://qiita.com/itkr/items/513318a9b5b92bd56185)
[[Python] BeautifulSoup で Webスクレイピングをしてみる - ゾンビでもわかるPythonプログラミング](http://python.zombie-hunting-club.com/entry/2017/11/08/192731)
部分的にReactを使う

Reactで最初から最後まで作るときは、「全機能が1つの巨大なコンポーネントに入っている」「React外で書くコードは、その巨大なコンポーネントを、変化するような`props`を指定せず`render`するだけ」というようなコードになることも多いかと思います。多くのReactの解説もそれが前提となっています。

ただ、別な仕組みで作ったHTMLにReactを混ぜこみたい、あるいは既存のサイトを徐々にReactへ移行したい、という場合には、部分的にReactを入れることが必要となってきます。もちろん、Reactでもそのような使い方は可能です。

# Facebook社でも

まず、`ReactDOM.render`は、1ページに対して複数回呼んでも構いません。バラバラなDOMノードに`render`すれば、それぞれがReactのルートとして働きます。そして、Reactが書き換えるのは指定したDOMノードの**内部だけ**ですので、そこ以外のDOMには影響なく、一部だけにReactを適用することができます。

実はFacebook自身も、既存のDOMにReactのコンポーネントを混ぜて運用している、とのことです。

> In fact, this is exactly how React is used at Facebook. This lets us write applications in React piece by piece, and combine them with our existing server-generated templates and other client-side code. （[Reactのリファレンス](https://reactjs.org/docs/integrating-with-other-libraries.html#integrating-with-other-view-libraries)より）

# 更新の方法

もちろん理想的に言えば、「最初にマウントしてあとは外部からの操作の必要がない」ようにコンポーネントを作っておくのがいいのでしょうけど、他のライブラリと連携するなどの事情で、一度`render`したものの`props`を変えざるを得ないことがあります。

このような場合、再度`ReactDOM.render`しましょう。2回目の`render`が同じコンポーネントであれば、再作成ではなく差分更新として処理されます（[リファレンス](https://reactjs.org/docs/react-dom.html#render)）。逆に、何らかの都合で「同じコンポーネントだけど完全に再作成したい」ような場合は、「いったんアンマウントしてから再度`render`する」「`key`を違えたもので`render`する」などの方法があります。

# アンマウント

ブラウザの遷移でしか`render`したものの必要性が変化しないのなら考える必要はないのですが、「別なライブラリで作ったコンポーネントの内側にReactのコンポーネントを入れたので、親コンポーネントがアカウントされる場合にはReactを外さないといけない」、あるいは「ページ遷移をpjaxなどで行っているので、JavaScriptは別に後始末する必要がある」などで、Reactをアンマウントする必要がある場面も出てきます。

このようなときには、`ReactDOM.unmountComponentAtNode`でアンマウントできます。
Windowsへのソフトウェアインストール

#git
参考：[Windows で Git - 2017冬](https://qiita.com/kikuchi_kentaro/items/8734cedbab9a0f1ada9f)

- [Git for Windows](https://gitforwindows.org/)から取得するインストーラーを使用する。
- cmdからgitコマンドを使える。

#node/npm
参考：[Node.js / npmをインストールする（for Windows）](https://nodejs.org/en/)

- [公式サイト](https://nodejs.org/en/)から取得するインストーラーを使用する。node/npm両方入る。
- インストール先フォルダにPathを通す。
- cmdからnode/npmが使える。
プログラミング初心者が１冊の本を参考に勉強して入ったツボについて

掌田　津耶乃さんが書かれた「PHPフレームワーク　Larevel入門」という本を参考に勉強しています。
Eloquent ORMのbelongsTo結合を勉強中に入ったツボについて書いてみます。

まず、２つのテーブルを作りました。

<img width="834" alt="スクリーンショット 2018-08-19 21.15.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/256864/65d2b4ac-6019-b730-c9a9-84f4e4132d6b.png">

主テーブルにあたるpeopleテーブル

<img width="1027" alt="スクリーンショット 2018-08-19 21.15.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/256864/357719d9-d3cb-5b50-1ef2-5401bb5f1dc0.png">

従テーブルにあたるboardsテーブル。

やりたかったのは、belongsTo結合で
従テーブル（borders)側から関連する主テーブル(people)を取り出すこと。

下記はBoardのモデルです。

<img width="1075" alt="スクリーンショット 2018-08-19 21.59.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/256864/1151f798-b5d0-c541-2db4-35f5b8eee516.png">

実際に/boardにアクセスしてみると、

<img width="1010" alt="スクリーンショット 2018-08-19 22.01.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/256864/98f72c0d-647c-81be-38dd-5c6f73164486.png">

エラーになりました。
自分はエラー画面をみると混乱するという属性持ちなので、
このときもなぜ、エラーになったのかわからず、自分を攻撃し続けていました。
エラーがわからなかったのは、本の通りにやったのになぜ？という考えがあったからだと思います。

後日、勉強を教えていただいているメンターのかたにエラーの原因を教えて頂きました。

"Trying to get property 'name' of non-object"
空の名前の配列をgetしようとしたことによるエラーでした。

従テーブルにはperson_idがあるけど、
関連するidが主テーブルにないというとでもない設計ミスでした。

<img width="716" alt="スクリーンショット 2018-08-19 22.17.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/256864/bf327a86-1c13-be3d-d1a5-092de28055ec.png">

Board ModelのgetDataメソッドを修正。

<img width="1003" alt="スクリーンショット 2018-08-19 22.19.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/256864/46842b03-2778-7877-f24d-de7f7dc69f52.png">

エラーが消えました。

反省点
本を書いた方はコードを書いている側がどのようなテーブルを作っているかなんて、
把握できない（できるはずもない）。
テーブルを作った本人が誰よりも把握しているべきだし、多数のテーブルを扱うときはより慎重にならなくてはならない。
本だけに頼るのではなく、自分のテーブルにあったコードを考え、情報を集め、
エラーになっても混乱せず、冷静に対処できなければならない。

ということが骨身にしみたエラーの話でした。
#001 8/19 Swift


Q1.Swiftでメソッドを追加する時、"Action"メソッドが提示されない

[udemyのSwift講座](https://www.udemy.com/learn-howtomake-snsapp/learn/v4/overview)で勉強しています。
レッスン５で、ストーリーボードから、コードにコネクションしようとした際に、Acitonメソッドが選択できなくなっているところで、躓きました。
いろいろ模索して解決出来ると嬉しいのですが…
<img width="435" alt="スクリーンショット 2018-08-19 22.16.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/280936/4804f34f-7e38-a77f-13f8-fafc2e261e33.png">


Q2.クラスを作成した時の謎エラー

これは後で修正すれば良さそうなのですが、コネクション関係でこんなエラーも出てます。
<img width="353" alt="スクリーンショット 2018-08-19 22.20.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/280936/1ced137b-c010-2857-e933-d6d3b37af5c8.png">

初心者なので、一歩一歩頑張って行きたいと思います。
解決したら、記事を更新します。
CowboyでCookieを扱う

CowboyでCookieの使い方を学んだので備忘録的に残しておきます。

## はじめに

ErlangやCowboyの環境構築や設定は以下の記事にまとめてるので気になる人はやってみてください。
[CowboyでHello Worldのサンプルを動かしてみる](https://qiita.com/kobatako/items/456642c42017e17cadca)

## ハンドラーの準備
まずはCowboyで呼び出すハンドラーの準備をします。パスに応じてハンドラーを呼び分けたりしますが今回は全てのリクエストは一つのハンドラーが受けるようにします。

```erlang:sandbox_app.erl
start(_StartType, _StartArgs) ->
    Dispatch = cowboy_router:compile([
        {'_', [
            {'_', toppage_handler, []}
        ]}
    ]),
    {ok, _} = cowboy:start_clear(http, [{port, 8010}], #{
        env => #{dispatch => Dispatch}
    }),
    sandbox_sup:start_link().
```
`toppage_handler`ハンドラーが全てのリクエストを受け止めてくれます。なのでリクエストのたびにこのハンドラーが呼ばれます。
今回はテンプレートエンジンにErlyDTLを使いました。
そしてCowboyを8010ポートで待ち受けるように設定します。

## Cookieを扱う
### Cookieをセットする

では実際にCookieを扱ってみます。Cowboyのサンプルでもありましたが、Cookieに値のセットと値の取得を繰り返すサンプルになります。ではさらっと全体像を。

```erlang:toppage_handler.erl
init(Req0, Opts) ->
    NewValue = integer_to_list(rand:uniform(10000)),
    Req1 = cowboy_req:set_resp_cookie(<<"server">>, NewValue,
            Req0, #{path => <<"/">>}),
```

`NewValue = integer_to_list(rand:uniform(10000)),`ではランダムな値を取得します。Cookieの値が入れ替わるのを確認するためランダムな値を取っています。

`Req1 = cowboy_req:set_resp_cookie(<<"server">>, NewValue, Req0, #{path => <<"/">>}),` でCookieに値をセットしています。第一引数の`<<server>>` はCookieの値、第二引数にCookieの値を入れています。第三引数にReq objectをセットし、第四引数にCookieのオプションを渡します。今回のオプションではCookieのパスを設定しています。
返り値として新しいRep objectを返します。

### Cookieの値を取り出す
次は、Cookieの値をハンドラー内で取り出す処理です。

```erlang:toppage_handler.erl
    #{client := ClientCookie, server := ServerCookie}
        = cowboy_req:match_cookies([{client, [], <<>>}, {server, [], <<>>}], Req1),
```

`#{client := ClientCookie, server := ServerCookie} = cowboy_req:match_cookies([{client, [], <<>>}, {server, [], <<>>}], Req1)`で値を取り出します。
返り値にCookieのclientとserverをマップとして返します。第一引数ではどの値を取り出すかを決めます。第一引数は`{Cookieのキー名, 制約, デフォルト値}`でのタプルのリストを渡しています。

これでCookieの値の取得を行うことができました。

### Cookieのオプションたち

最後に、`set_resp_cookie` のオプションとして設定できるものを記載していきます。

* max_arg => 失効するまでの時間
* domain => 有効なドメイン
* path => Cookieを設定するパス
* secure => HTTPSのみ有効
* http_only => HTTPのみ有効

## まとめ

簡単ではありましたが、CowboyのCookieの扱い方でした。
もっといろいろしようかと思いましたが、これ以上することがないので（悲しい、、、）。
別の記事でCookieを使っていろいろするのを書こうと思います。
スクレイピングの学習 Python3系 その3

# 前回の内容
[スクレイピングの学習 Python3系 その2](https://qiita.com/mizssy07/items/0f4ca2d7e6f9e022c5e2)

# 改善点
- 一旦ローカルではなくGoogleスプレッドシート上にファイルを出力してみる
- 特定のファイルを開き、取得したタイトルとURLを書き込む

# 手順
- Google ColaboratoryでGoogleスプレッドシートを開く
- 既に取得済みの値から、A列にタイトル、B列にURLを書き込む

# 追加したコード
```python:
# !pip install gspread
from google.colab import auth
from oauth2client.client import GoogleCredentials
import gspread

# 認証処理
auth.authenticate_user()
gc = gspread.authorize(GoogleCredentials.get_application_default())

# ファイルを開く
# 'マイドライブ/sheet/#ファイル#'というスプレッドシートをオープン
sh = gc.open_by_key('1###Y') 
worksheet = sh.get_worksheet(0) # 書き込み用ワークシートを指定

# 抽出したa要素をセルに入れ込む
for i, tag in enumerate(tags, 1):
    name = tag.string #　記事名の取得
    url = tag.get("href") #リンクの取得
    worksheet.update_cell(i, 1, name)  # 座標指定(行,列) # CSVに記入
    worksheet.update_cell(i, 2, url)
```

# 全体のコード
```python:
# coding: UTF-8
# !pip install gspread
from bs4 import BeautifulSoup
import requests
from google.colab import auth
from oauth2client.client import GoogleCredentials
import gspread

# 認証処理
auth.authenticate_user()
gc = gspread.authorize(GoogleCredentials.get_application_default())

# ファイルを開く
# 'マイドライブ/sheet/#ファイル#'というスプレッドシートをオープン
sh = gc.open_by_key('1###Y') 
worksheet = sh.get_worksheet(0) # 書き込み用ワークシートを指定

# アクセスするURL = ニュートピ
url = "https://newstopics.jp/"

# htmlを取得、BeautifulSoupで扱う
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser') # BeautifulSoupの初期化

# aタグの中から、class=titleの含まれたものを取得
tags = soup.find_all("a", {"class": "title"})

# 抽出したa要素をセルに入れ込む
for i, tag in enumerate(tags, 1):
    name = tag.string #　記事名の取得
    url = tag.get("href") #リンクの取得
    worksheet.update_cell(i, 1, name)  # 座標指定(行,列) # CSVに記入
    worksheet.update_cell(i, 2, url)
```

# 補足
- `gspread`はimportだけだと使えない。`!pip install gspread`でインストールしてあげる必要あり。(一旦インストールしてしまえばランタイム接続中は再度インストールする必要なし。)
- for文は`enumerate`を使用して第二引数を1からに指定。スプレッドシート上の座標を指定するのに使用。
- `sh = gc.open_by_key('###') `ファイルのリンク先IDを入れる([参考リンク](https://uepon.hatenadiary.com/entry/2018/04/08/110916))
- `update_cell`以外にもセル指定の仕方がある([参考リンク](https://qiita.com/hid_tgc/items/3f6f97c58c84457bf00c))

# 詰まったところ
- gspreadのinstallをせずにimportしてエラーを吐いていた
- pandasで作った行を挿入しようとしたが出来なかったので`enumerate`を利用してセル単位での書き込み形式にした

# 次回への課題
- 法律周りの確認
- ~~CSVでダウンロード~~
- 1時間に1回取得などの動き
- 重複する内容を取得しないようにする
- 次ページ以降の取得
- 元リンクを取得
- ローカル環境で動かす
- APIを使用してスプレッドシートにアクセス new
cronでnpm scriptを実行する際に詰まったら

## やりたいこと
cronでnpm scriptを定期実行させたい

## 設定
```
$ crontab -e
```

```
* * * * * cd /path/dir/ && npm script
```

## 実行できない、なぜ？
ログを出して確認してみる。

### cronの実行ユーザを確認する

```
crontab -e
```

cronの実行ユーザをログに書き出す

```
* * * * * whoami > /home/username/cron.log 2>&1
```

ログを確認する

```
$ cat /home/username/cron.log
```

### PATHを確認する

cronで実行する際のPATHを確認する

```
* * * * * echo $PATH > /home/username/cron.log 2>&1
```

ログを確認する

```
$ cat /home/username/cron.log
```

該当するユーザで実行する際のPATHを確認する

```
$ echo $PATH
```

## 結論
自分の場合は、cronで実行する際のPATHとユーザで実行する際のPATHが異なっていたために、npm　scriptが実行できなかった。

ので、cronで実行する際のPATHをユーザで実行する際のPATHに合わせてやったら、npm scriptが実行されるようになった。

```
$ crontab -e
```

```
PATH= #ここにPATHを設定してやればOK

* * * * * cd /path/dir/ && npm script
```
macOSでも日本が入力できるInputField

> 時間ができたらまともにかく

標準のInputFieldはどうやっても無理です。ハンドラで小細工してももっと下のところに問題あるので無理。無理。

TextMesh Pro の InputField が下回りを自作してて、それを使うと大丈夫。
ただし、Calet周りのエラーハンドリングに漏れがあり、IME仮確定状態におけるスコープで強制的に空のtextを参照してしまう場合に例外を吐く箇所がある。

一応、一番目立つところだけ対処すれば、ある程度は実用的。
（見つけるたびに例外ハンドリング追加してく...）

'/Users/User名/Library/Unity/cache/packages/packages.unity.com/com.unity.textmeshpro@1.2.4/Scripts/Runtime/TMP_InputField.cs'

の2330行目あたりを

```
try {
  if (caretPositionInternal > 0)
  {
      m_Text = text.Remove(GetStringIndexFromCaretPosition(caretPositionInternal - 1), 1);
      caretSelectPositionInternal = caretPositionInternal = caretPositionInternal - 1;
      stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(caretPositionInternal);
  }
  m_isLastKeyBackspace = true;
  SendOnValueChangedAndUpdateLabel();
}
catch(System.ArgumentOutOfRangeException e){
  Debug.Log(e.Message);
}
```

問題は、Packmanagerで入れてる場合、アップデートのたびにこれをしなくてはいけない（許容範囲）

そして、CloudBuildとかでビルドするときに、これの適用が外れるというところで、どうしたもんかい。。。

### 追記 : 例外対応

無を参照する系で、TMP_InuptField.csの2934行目付近でもなんかよく起きる。
適当にチェックを追加。

```
            int currentLineIndex = 0;
            int nextLineStartIdx = 0;

            if((textInfo.characterInfo != null) && (textInfo.characterInfo.Length > startChar)){
                currentLineIndex = textInfo.characterInfo[startChar].lineNumber;
            }
            if((textInfo.lineInfo != null) && (textInfo.lineInfo.Length > currentLineIndex)){
                nextLineStartIdx = textInfo.lineInfo[currentLineIndex].lastCharacterIndex;
            }
```
StanとRでベイズ統計モデリング(アヒル本)をPythonにしてみる - 10.3 再パラメータ化

[実行環境](https://qiita.com/shngt/items/ce6f2c3ef348cd80f432)

### インポート

```python
import numpy as np
from scipy import stats
import pandas as pd
import pystan
import matplotlib.pyplot as plt
from matplotlib.figure import figaspect
%matplotlib inline
```

### データ読み込み

```python
salary2 = pd.read_csv('./data/data-salary-2.txt')
```

# 10.3 再パラメータ化
## 10.3.1 Nealの漏斗

```python
fit_a = pystan.stan('./stan/model10-8a.stan', chains=1, iter=4000, seed=1234)
fit_b = pystan.stan('./stan/model10-8b.stan', chains=1, iter=4000, seed=1234)

ms_a = fit_a.extract()
ms_b = fit_b.extract()

xx, yy = np.mgrid[-5:5:30j, -5:5:30j]
points = np.c_[xx.ravel(), yy.ravel()]
x, y = points[:, 0], points[:, 1]
lp = np.log(stats.norm.pdf(y, loc=0, scale=3)) + np.log(stats.norm.pdf(x, loc=0, scale=np.exp(y/2)))
lp[lp < -15] = -15

_, axes = plt.subplots(1, 2, figsize=figaspect(1/2), sharex=True, sharey=True)
for ms, ax in zip([ms_a, ms_b], axes):
    cs = ax.contourf(xx, yy, lp.reshape(xx.shape), vmin=-15, vmax=0)
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    ax.scatter(ms['r'][:, 0], ms['a'], s=1, c='k')
    plt.setp(ax, xlabel='r[1]', ylabel='a', xlim=xlim, ylim=ylim)
plt.show()
```
![fig10-5.png](https://qiita-image-store.s3.amazonaws.com/0/103085/d5b661b7-a748-9979-7818-1db9e71f9396.png)

## 10.3.2 階層モデル

```python
data = {col: salary2[col] for col in salary2.columns}
data['N'] = salary2.index.size
data['K'] = salary2['KID'].max()
fit = pystan.stan('./stan/model8-4c.stan', data=data, seed=1234)
```
モードラインのモード名表示を短縮する

今さらですが、
モードラインのモード名表示を短縮する方法はマイナーモードとメジャーモードでは異なります。

# マイナーモード

マイナーモード名を短縮するときは、そのモードをロードしたあとで`diminish`を使います。


```el
(when (require 'diminish nil 'noerror)
  (eval-after-load "company"
      '(diminish 'company-mode "Cmp"))
```

# メジャーモード

メジャーモード名を短縮するときは、`diminish`を使わず、そのモードにフックして`mode-name`変数を直接書き変えます。

```el
(add-hook 'emacs-lisp-mode-hook 
  (lambda()
    (setq mode-name "Elisp"))) 
```
# 実際の使用例
 
私はMELPAから落としたパッケージには`use-package`の`:diminish`キーワードを使っています。→ [こちら](https://qiita.com/gnrr/items/063ea0a0c9634e5b4601)にまとめました。

対して、それ以外のEmacs標準のモード名は`use-package`を使わず下記のようにしています。[^1]

[^1]: `safe-diminish`ありがたくパクらせていただきました。


```el
(defmacro diminish-minor-mode (file mode &optional new-name)
  "https://github.com/larstvei/dot-emacs/blob/master/init.org"
  `(with-eval-after-load ,file
     (diminish ,mode ,new-name)))

(defmacro diminish-major-mode (hook new-name)
  `(add-hook ,hook #'(lambda ()
                    (setq mode-name ,new-name))))

;; minor mode
(diminish-minor-mode "eldoc" 'eldoc-mode "doc")

;; major mode
(diminish-major-mode 'emacs-lisp-mode-hook "Elisp")

```


# 参考
[use-package でモード名を全消し or 短縮する](https://qiita.com/gnrr/items/063ea0a0c9634e5b4601)
[diminish](https://github.com/myrjola/diminish.el)
[safe-diminish](https://qiita.com/tadsan/items/c859c5c04724cbda75fc#diminish)
[cleaning up the mode-line](http://emacs-fu.blogspot.com/2010/05/cleaning-up-mode-line.html)
Pythonを勉強する上でとても参考になったものたち

<br>
全くズブの素人だった自分がそれなりにPythonが理解できた教材を備忘録的に紹介します。

<h2>【保存版】プログラミングを無料で学べる学習サイトを目的別に整理してまとめてみた</h2>
https://dividable.net/programming-school/recommended-programming-learning-service/

とても分かりやすく学習ルートを紹介してくれているブログ記事です。（Qiitaじゃなくてごめんなさい）
これを見て自分もPythonを勉強する気になりました。

<h2>Progate</h2>
https://prog-8.com/languages

先述したブログ記事の中でも触れてある初心者入門用のオンライン学習サイトです。
すべての項目を閲覧するには月額980円かかるのですが、入門用の書籍なんか買うより断然お得でさらに分かりやすいのでオススメです。
ブラウザが表示できたらどんな環境でも（言い過ぎ？）学習を始められる点がとてもよかったです。
（Rubyの講座がとても充実していたので時間を見て挑戦しようと思っています。。。）

<h2>Aidemy</h2>
https://aidemy.net/courses

こちらも先ほどと同じくオンライン学習サイトになっています。
プロゲートが様々な言語を網羅しているのに対して、こちらは<b>AI</b>や<b>機械学習</b>に特化した内容になっています。
同じく月額制で学習を進める事ができますが、コース（一つの授業）を買い切って学習する事もできます。
（8月末まで<b>TikTok</b>で<b>Aidemy</b>を紹介する事で受講に使うチケットが1枚もらえるらしいです。）
参考URL貼っておきますので我こそはという方は是非！
https://prtimes.jp/main/html/rd/p/000000055.000028316.html

<h2>予備校のノリで学ぶ「大学の数学・物理」</h2>
【大学数学】線形代数入門①(概観&ベクトル)【線形代数】
https://www.youtube.com/watch?v=svm8hlhF8PA
【大学数学】線形代数入門②(行列)【線形代数】
https://www.youtube.com/watch?v=ltFl0FpLTzQ&t=338s

次はすこしプログラミングとは離れるのですが、Pythonでは「Numpy」というとってもとっても便利なライブラリがあります。
先述した<b>Aidemy</b>にも講座がありますが、行列の計算などを出力する場面が出てきます。
自分は恥ずかしながら勉強をしてこなかった人間ですので、全くチンプンカンプンの時にこのチャンネルに出会い救われました。
とても分かりやすくそしてジャストミートに同じ計算方法を扱っているのでとても重宝しました。
（その他の動画も大学数学や物理なんかを扱っていて見ているだけで楽しそうです。）

実際に使ったのはここまでで、この後は便利だなと思ったサイトor今後使う予定のサイトをずらーっと並べておきます。
<h2>cousera</h2>
https://www.coursera.org/
全部が英語で心折れそうですが有志による日本語訳が付いているそうなので頑張ってみます。
<h2>Udacity</h2>
https://classroom.udacity.com/courses/ud359/lessons/664109694/concepts/6853492770923
こちらはyoutube動画で字幕があるので何とかなりそうです（笑）




<h2>最後に</h2>
と、まあ一番最初のブログを見てもらえばこれを見る必要なんかないんですけどね！！！
ただYoutubeの予備校のノリで学ぶ「大学の数学・物理」はとてもオススメなので是非見てみてください！
API仕様書書くならswagger v2.0からv3.0に変更する際のポイント

## はじめに
最近、API仕様書の作成に[swagger](https://swagger.io/)を使い始めて`swagger2.0`と、`openapi3.0.0`で作成しました。その時にバージョンの違いで記載方法に変更点があったので、メモ代わりとして記載します。

## v2.0
とりあえず一番シンプルな形

```yaml
swagger: '2.0'
paths:
  /api/regist:
    post:
      consumes:
        - application/x-www-form-urlencoded
      parameters:
        - name: hoge_id
          in: query
          description: クエリパラメータ
          type: integer
          required: true
        - name: hoge_name
          in: formData
          description: 名前
          required: true
          type: string
        - name: age
          in: formData
          description: 年齢
          required: true
          type: string
        - name: comment
          in: formData
          description: コメント
          type: string
          required: true
          maxLength: 1000
    responses:
      200:
        description: ok
```
![screencapture-localhost-81-2018-08-19-20_33_05.png](https://qiita-image-store.s3.amazonaws.com/0/239829/756219c3-8faa-b73f-c64c-0d2ed427a83c.png)



## v3.0
```yaml
openapi: 3.0.0
paths:
  /api/regist:
    post:
      parameters:
        - in: query
          name: id
          required: true
          description: クエリパラメータ
          schema:
            $ref: '#/components/schemas/id'
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/RequestBody'
      responses:
        200:
          description: ok
components:
  schemas:
    id:
      type: string
      example: '1'
    name:
      description: 名前
      required:
        - name
      type: string
      example: テスト太郎
    age:
      description: 年齢
      required:
        - age
      type: string
      example: '18'
    comment:
      description: コメント
      required:
        - comment
      type: string
      maxLength: 1000
      example: コメントコメント
    RequestBody:
      type: object
      required:
        - name
        - age
        - comment
      properties:
        name:
          $ref: '#/components/schemas/name'
        age:
          $ref: '#/components/schemas/age'
        comment:
          $ref: '#/components/schemas/comment'
```
![screencapture-localhost-81-2018-08-19-21_09_49.png](https://qiita-image-store.s3.amazonaws.com/0/239829/cc10c4b4-6268-9cb2-bc8d-2b54cf5092b4.png)



## v3.0との変更点
- `body`と`formData`が`requestBody`にまとめられる
- schemaの定義方法

```yaml
v2.0
definitions:
  - comment:
v3.0
components:
  schemas:
    - comment:
```
- `type`はschemaで定義
- `required: true`ではなく対象を指定
- 見た目：v3.0ではdescriptionの内容がmodelsの中に記載

## さいごに
個人的にv2.0の方がdescriptionが見やすいので、v3.0は好ましくないですね..。
お客さんに見せる事を考えるとdescriptionが見やすい位置にあることも重要ですし。