OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】TableViewのセルを右からスワイプすると削除ボタンが出てくる

#1. 概要
筆者がTableViewのセルを左スワイプするメソッドを追加した時、なぜか設定した覚えのない右スワイプで、「削除」と書かれたボタンが表示されてしまいした。
原因を調べてみるとTableViewの仕様に関する重要なことがわかったので、ここに備忘録として書いておきます。

#2. 原因
TableViewには、"isEditing"というプロパティが存在します。
この"isEditing"がtrueの状態（以下、編集モードと呼びます）だと、セルを右からスワイプすることで削除ボタンが出るようになります。

そしてこの"isEditing"を制御するには、TableViewの"editingStyleForRowAt"というメソッドを用います。
"tableView.isEditing"はデフォルトではfalseなので、編集モードとそれ以外で削除ボタンの有無を変えるには、以下のように記述すればOKです。

```swift:MyTableViewController
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
    if tableView.isEditing {
        return .delete
    }
    return .none
}
```

しかしここで厄介なのは、"tableView.isEditing"はデフォルトでfalseなのにも関わらず、"editingStyleForRowAt"メソッドを記述しないと、TableViewが常に編集モードになってしまうという仕様です。

ここについては、公式ドキュメントにしっかり書いてありました。

>This method allows the delegate to customize the editing style of the cell located atindexPath. If the delegate does not implement this method and the UITableViewCell object is editable (that is, it has its isEditing property set to true), the cell has the UITableViewCell.EditingStyle.delete style set for it.

[tableView(_:editingStyleForRowAt:)]
(https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614869-tableview)

つまり、「このメソッドを実装しないとデフォルトで編集モードになるよ」ということです。
僕の場合、編集モードを実装せず削除ボタンも使わないので、以下のように".none"を返すだけの処理を書くことで解決しました。

```swift:MyTableViewController
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
    return .none
}
```

#3. 終わりに
筆者はSwift初心者なので、理解不足の点や間違っている箇所もあると思います。
その際にはコメントで指摘していただけると幸いです。
複数EC2のスケジュール操作(SSMAutomation)

EC2をスケジュール起動/停止する際は、CloudWatchからSSMAutomationテンプレートの"StartEC2Instance"や"StopEC2Instance"を使うと、ノンコーディングで簡単です。
Qiitaにも参考になる記事がたくさんあるので、実装されたい方は以下などご参考ください。
[CloudWatch Events と Systems Manager で EC2の起動/停止をスケジュール化する](https://qiita.com/hayao_k/items/9a347d61b5b09a4e7755)
本記事は1スケジュールで複数EC2を操作した際に詰まった注意点を書きます。

#### 複数EC2指定時の注意点
"StartEC2Instance"や"StopEC2Instance"は、インスタンスIDを指定するだけで起動/停止ができます。

![CloudWatch.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174816/c71ee520-72bd-1892-5744-62aa884647ab.png)

InstanceIdパラメータは以下リファレンスによると複数ID指定可能です。
[AWS-StartEC2Instance](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-aws-startec2instance.html)
[AWS-StopEC2Instance](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-aws-stopec2instance.html)

```
InstanceId
型: StringList
説明: (必須) 停止する 1 つ以上の Amazon EC2 インスタンスの ID。
```
単一IDは以下のような指定で問題なく動作します。

```
# 正常終了
i-00000000000000000
```
複数IDの場合、以下のようなカンマ区切りで指定するとエラーになります。

```
# エラー
i-00000000000000000,i-11111111111111111
```
複数IDを指定する場合は以下のように入力ください。

```
# 正常終了
["i-00000000000000000","i-11111111111111111"]
```
急に書き方が変わるので、同じように詰まった方はご参考くださいー。
AWS Systems Managerパラメータストアあたりが関係するのですかね。今度調べてみます。
Ubuntuでスクロールができない問題


## 環境

WSL(Windows Subsystem for Linux)のUbuntuを使っています。
もともとスクロールできていたターミナルを開いたとき、なぜかスクロールできず困ったので、解決策の一つをご紹介します。

## 設定方法
①　ターミナルの上のところを、右クリック→「プロパティ」を開く
![フォト 2019-09-18 19.15.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497105/4c05d7ab-3285-2f1f-3436-95cf66bd7247.png)


②　「レイアウト」タブから、高さの数値を変更。問題発覚時、ここが50になっていました。。。そりゃあ画面の高さが小さすぎます。1000もあれば十分かと思います。


![フォト 2019-09-18 19.18.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497105/316094a8-1674-85b1-de9d-e6b83c364ab3.png)


これだけです。
調べると、コマンドやら何やら、いろんな方法が出てきたのですが、どれも効果がなく、、、
以下のサイトが大当たりでした。

### 参考文献
https://stackoverflow.com/questions/41774260/windows-10-bash-ubuntu-14-04-how-to-scroll-up
PHP の Trait ってなんだ

## Trait とは

- PHP 5.4.0 以降で導入されたコードを再利用するための仕組みのことです。
- いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。 

### Class との違い

- Trait の目的はあくまでも機能をまとめるためだけに限定されます。
- インスタンスを生成することはできません。

### 使うことのメリット

- 多重継承や Mixin に関連するありがちな問題を回避することができます。
- 振る舞いを水平方向で構成できるようになります。

### 優先順位

現在の基底クラスのメソッド → トレイトのメソッド → 継承したクラスのメソッド

### 実際に使ってみる。

簡単な例は公式に書いてあるので、ここではありそうな例として値を保存しようとした時のカスタムリクエストにバリデーションをかける時の処理をまとめてみます。
フレームワークは laravel5.5 を使っています。

#### before

```php5
use Illuminate\Validation\Validator;

class CustomRequest extends BaseRequest
{
    /**
     * @param  Validator  $validator
     */
    public function withValidator(Validator $validator)
    {
        $validator->after(function (Validator $validator) {
            $inputs = $this->validatedValues();

            // このバリデーションをTraitで再利用できるようにしましょう  ---------
            if ($inputs['sample']['hoge']) {
                $validator->errors()->add('hoge', 'error message.');
            }
            // ---------------------------------------------------------
            return $validator->messages()->isEmpty();
        });
    }
}
```

```php5

use Illuminate\Database\Eloquent\Model;

/**
 * Class Sample
 * Sampleテーブルを操作するModelクラスです。
 */
class Sample extends Model
{
    // Eloquent save etc...
}
```


#### after

CustomRequestと同じ階層に Trait を作ってみます。


```php5
use Illuminate\Validation\Validator;

/**
 * Trait CustomValidationRule
 */
trait CustomValidationRule
{
    /**
     * @param  Validator  $validator
     * @param  Sample  $sample
     */
    protected function checkHoge(Validator $validator, Sample $sample)
    {
        if ($sample['hoge']) {
            $validator->errors()->add('hoge', 'error message.');
        }
    }
}
```


```php5

use Illuminate\Validation\Validator;

class CustomRequest extends BaseRequest
{
    // 使用したいクラス内で Trait を宣言します
    use CustomValidationRule;

    /**
     * @param  Validator  $validator
     */
    public function withValidator(Validator $validator)
    {
        $validator->after(function (Validator $validator) {
            $inputs = $this->validatedValues();

            // Trait で宣言した関数を呼ぶ　---------------------------------
            $this->checkHoge($validator, (new Sample($inputs['sample'])));
            // ---------------------------------------------------------

            return $validator->messages()->isEmpty();
        });
    }
}
```


### 衝突の解決

- 同じ名前のメンバーを含む複数のトレイトを追加するときには、 衝突を明示的に解決しておかないと fatal エラーが発生するので注意が必要。


【参考： https://www.php.net/manual/ja/language.oop5.traits.php 】
Gitlab CIでruby gemsのアップデートとMRの自動作成ができるようになりました

[dependabot/dependabot-core](https://hub.docker.com/r/dependabot/dependabot-core)というdocker imageを使って、GitlabCIでruby gemsのアップデートをし、バージョンアップがあったものを自動的にMR作成できるようになりました。

# 事前準備
- gitlab access token作成
<img width="1459" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/ee7d9bc9-a7c5-f1af-906e-ab5ce2d6a2b2.png">

# .gitlab-ci.ymlを調整
## ruby gems更新用のJobを追加
`dependabot/dependabot-core`コンテナに望ましいバージョンのrubyがない可能性があるので、`rbenv`を用いてインストールしておく。
※プロジェクトの配下に`ruby`のバージョンを記載してある`.ruby-version`があるとします。
<img width="743" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/12b06d08-2bd6-6059-6806-8072d2eaed7b.png">

Jobを追加後の`.gitlab-ci.yml`ファイル

```yml:.gitlab-ci.yml
dependabot:
  image: dependabot/dependabot-core
  before_script:
    - git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
    - git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
    - echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
    - echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
    - source ~/.bash_profile
    - rbenv install -v `cat ./.ruby-version` --skip-existing
    - rbenv global `cat ./.ruby-version`
    - gem install bundler
    - bundle install -j $(nproc) --path vendor
    - curl -O https://raw.githubusercontent.com/dependabot/dependabot-script/master/generic-update-script.rb
    - curl -O https://raw.githubusercontent.com/dependabot/dependabot-script/master/update-script.rb
  script:
    - bundle exec ruby ./generic-update-script.rb
  only:
    - schedules
```
## .gitlab-ci.ymlに載っている`dependabot`以外のJobに`except: schedules`を追加
ruby gemsの更新だけなので、rspec/lintとかの実行はいりません

```yml:.gitlab-ci.yml
...
brakeman:
  stage: audit
  tags:
    - docker
    - gce
  except:
    - schedules
  script:
    - bundle exec brakeman -4 -A -w 1 -z
...
```

# ScheduleにJobを登録
<img width="1086" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/553b74d5-110d-1c25-ec29-306cb0b3bd1e.png">

# 動けるかを試してみる
<img width="1452" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/f8364056-d7e4-5f7e-be76-119158caf000.png">

# ２つのGemバージョナップがあったようで
<img width="1423" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/282d1f96-6947-4014-262f-ecc289c3d6c7.png">

# MRリストを確認
確かに、２つのMRが上がられました。
<img width="1459" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/5f53aa80-851b-750d-6e02-dd16cfd9f3f1.png">

いい感じ出来上がりました :confetti_ball: 
<img width="1396" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293473/6a3a98b5-ae02-9df9-3f6f-5a1020259a25.png">

あとは、緑の`merge`ボタンをクリックだけ。
1Passwordでパスワードを吹っ飛ばしてバックアップから元に戻す手順(Mac)

https://twitter.com/guttyar/status/1174250099771359238
このツイートの通りDiscordのパスワードを吹っ飛ばしたので、Time Macineバックアップから復活させた手順を残しておく。
多分今後数回やらかすのでその時のために。
**Mac用です。Windowsでは多分できません。**

# 手順
1. 1Passwordを終了。(![1Passwordのメニューアイコン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330547/d2b09aa5-76bf-3215-d154-7389a82a2241.png)<-みたいなのがメニューバーにあると終了できてない)
2. Wi-Fiを切る。(![MacのWi-Fiオフのメニューアイコン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330547/2bb48f57-4146-3312-5d32-afd7f02c949a.png)<-こうなっていればOK)
3. 復元するバックアップを選ぶ。(`/Volumes/<バックアップディスク>/Backups.backupdb/<バックアップした時間>`みたいなパス)
4. バックアップからデータベースを探してコピーする。
    1. `<バックアップフォルダ>/<ルートフォルダ>/ユーザ/<ユーザーネーム>/ライブラリ/Group Containers/2BUA8C4S2C.com.agilebits/Library/Application Support`に移動。
    2. フォルダのなかの`1Password`フォルダを適当な場所(デスクトップなど)にコピー
    3. `/ユーザ/<ユーザーネーム>/ライブラリ/Group Containers/2BUA8C4S2C.com.agilebits/Library/Application Support`に移動。
    4. 中の`1Password`フォルダの名前を適当に変える。(`_1Password`など)
    5. 手順4.2でコピーしたフォルダで`1Password`フォルダを上書き。
5. 1Passwordを起動。
6. マスターパスワードを入力、開くとバックアップのデータに変わっている。
7. 必要に応じて操作。(必要なパスワードをコピーするなど)
8. 1Passwordを終了。
9. 手順4.5で名前を変えたフォルダを削除。
10. 手順4.4で名前を変えたフォルダの名前を`1Password`に戻す。
11. 1Passwordを起動、マスターパスワードを入力して開くとまた作業をする前のデータに戻っている。
12. Wi-Fiをオンにする。
13. 必要に応じて操作。(コピーしたパスワードに更新するなど)

終わり

# 感想
データが吹っ飛ぶとびっくりする。
作業も怖かった。
**怖**かったです。
ところでこういうことできていいのか?
データが吹っ飛んだ時の顔↓(ニコニコ参照)
![溶かした顔](https://dic.nicovideo.jp/oekaki/674964.png)

# 参考
https://discussions.agilebits.com/discussion/comment/443473/#Comment_443473
@nuxt/axiosでCRUDする時のアクセス方法とデータの受け取り方【Nuxt + Express】

`import axios from 'axios'` ではなく、`@nuxt/axios`を `nuxt.config.js` に modules として登録すること使用できる。
axiosを使いデータベースをCRUDする時の頻出メソッドと、サーバーサイドへの値の渡し方、受け取り方のまとめ。
公式に載っていないものもあったので記載しておきます。
[公式はこちら](https://axios.nuxtjs.org)

```
"@nuxtjs/axios": "^5.3.6",
"body-parser": "^1.19.0",
"express": "^4.16.4",
"nuxt": "^2.0.0",
```

##Create 【$post】

```javascript:front.vue
this.$axios
  .$post('/',  querystring.stringify({ foo: 'bar' }))
  .then(res => {
    ...
  })
```


```javascript:back.js

app.post('/', (req, res) => {
  res.send(req.body.foo) // 'bar'
})
```
nodeではQueryStringを使ってデータを送ることが推奨されているよう。
QueryStringはnodeの標準で入っているモジュール。
フロントでセットしたデータは、サーバーサイドで`req.body`で参照できる。(body-parserが必要)
https://github.com/axios/axios#instance-methods
[Query String](https://nodejs.org/api/querystring.html)

##Read 【$get】
```javascript:front.vue
this.$axios
  .$get('/', { params: { foo: 'bar' }})
  .then(res => {
    ...
  })
```
```javascript:back.js

app.get('/', (req, res) => {
  res.send(req.query.foo) // 'bar'
})
```
フロントでパラメータをセットした場合、サーバーサイドでは`req.query`で参照できる。

##Update 【$put】
```javascript:front.vue
const userId = 123456789

this.$axios
  .$put(`/${userId}`,  querystring.stringify({ foo: 'bar' }))
  .then(res => {
    ...
  })
```

```javascript:back.js

app.put('/:id', (req, res) => {
  console.log(req.params.id) //123456789
  res.send(req.body.foo) // 'bar'
})
```
putメソッドは、サーバーサイドにアクセスする際にidが必要。
サーバー側のパス`:id`にフロントから送られたidがセットされ、`req.params`で参照できる。

データを送る際はpostメソッドと同じ送り方が使える。

##Delete 【$delete】
```javascript:front.vue
const userId = 123456789

this.$axios
  .$delete(`/${userId}`)
  .then(res => {
    ...
  })
```
```javascript:back.js

app.delete('/:id', (req, res) => {
  res.send(req.params.id) // 123456789
})
```
deleteメソッドもputと同様の送り方でidが必要。

## おまけ
Nuxt特有のasyncDataを使ってaxiosを使う際

```javascript:front.js
async asyncData({ app }) { 
  await app.$axios.$get('/')
    .then(res => {
      ...
    })
}
```
今回は以上です。
他にもNuxt特有の使い方が多いので、また学習が進み次第まとめます。
補足、修正などありましたらご教授いただけますと幸いです。
最後まで読んでいただきありがとうこざいます。
Pythonで名前付きの定数値を作成する方法

# はじめに
タイトルの通りPythonで名前付きの定数値を作成する方法について記載します。
私のメイン言語はCなのですがCで言うところの#defineやconstのようなものを作ることを目指します。あくまで**"ような"**ですので名前がついていてイミュータブルな(値が変更できない)ものぐらいに捉えてください。

# 環境
以下の環境で動作させています。`namedtuple`というデータ型が使えるPythonバージョンであればOS依存なく使えるものと思われます。

- OS
    - Windows 10 64bit
- Pythonバージョン
    - 3.6.6

# 作成例
Cで

```c
#define D_VERSION 0.01
#define D_TITLE   "sample"
```

のようなdefine値があったときPythonでは

```Python
from collections import namedtuple

D = namedtuple("Def", "VERSION TITLE")(
	VERSION	= 0.01,
	TITLE	= "sample"
)

# 使用例
print(D.VERSION)
print(D.TITLE)
```

と書くことにより実現できます。

# 細かい話
## namedtupleとは
オフィシャルドキュメントには
> 名前付きフィールドを持つタプルのサブクラスを作成するファクトリ関数

と定義されています。
`タプル`とはオフィシャルドキュメントには
> イミュータブルなシーケンスで、一般的に異種のデータの集まりを格納するために使われる

と書かれています。つまり定数の集合体です。これに名前がついたものが`namedtuple`となります。

## namedtupleの一般的な記述方法と今回の記述方法について
先程の例を一般的なnamedtupleの記述方法で記述すると以下のようになります(import等は割愛しています)。

```python
Def = namedtuple("Def", "VERSION TITLE")
D = Def(0.01, "sample")
```

せっかくのnamedtupleですのでよりわかりやすく書くと

```python
Def = namedtuple("Def", "VERSION TITLE")
D = Def(VERSION=0.01, TITLE="sample")
```

となります。
前述の通りnamedtupleはサブクラスを作成しますので上記コードでは`Def`というサブクラスが作成されることになります。
しかし今回の例では作成されたサブクラスを使い回す必要がなかったため(ユニークな名前付きの定数値を作りたいだけなので)サブクラスの宣言部分を取っ払い

```python
D = namedtuple("Def", "VERSION TITLE")(
	VERSION	= 0.01,
	TITLE	= "sample"
)
```

としてしまった次第です。

# 個人的な話
## Pythonで定数を扱いたい
私がPythonを使い始めたときに「Pythonで定数ってどうやって書くのかな？」と思い調べたところ殆どのサイトに

> Pythonに定数はありません。大文字アルファベットとアンダースコアの組合せで(変数を)記載するのが慣例です

と書かれていました。PEP 8(Pythonのコードスタイルガイドライン)にそう書かれているのでそうなのですが。「見た目だけで実態は変数だから凡ミス防げないよね」というのが正直な感想でした。
その後tupleを覚えたのですが

```python
D = (0.01, "sample")

print(D[0])
print(D[1])
```

これでは可読性が悪すぎる。
しばらく慣例通り大文字変数を使っていました。
その後諦めきれずに色々調べたところnamedtupleに出会った次第です。

# おわりに
PythonでもCの#defineっぽいものを使いたいという衝動からnamedtupleを使ってみました。Pythonの慣例からすると間違っているのかもしれません。完全にCプログラマーの自己満足です。
ただnamedtupleを使うと

- イミュータブルになるので安全
- ドット記法が使えるので辞書型より見やすい

等の利点があると思うので今後も(別の目的で)積極的に使っていきたいと思います。ただしパフォーマンスは悪いようなので多用は禁物かもしれません。

# 参考
本記事を書くにあたり以下のサイトを参考・引用しました。

- [namedtuple](https://docs.python.org/ja/3/library/collections.html#collections.namedtuple)
- [tuple](https://docs.python.org/ja/3/library/stdtypes.html?highlight=tuple#tuple)
- [PEP 8 - 定数](https://pep8-ja.readthedocs.io/ja/latest/#id38)
- [Pythonのdictをnamedtupleに変換してベンチ取ってみた](http://nekoya.github.io/blog/2014/06/02/config-namedtuple/)
Ruby on ReilsでルートのPrefix作成する方法およびDBデータのリンクを作る方法

## 現状

### 作成中のサイト
食べログみたいな飲食店情報サイトのポータルサイト

### 都道府県一覧ページ
```show.rb
<h1><%= @prefectures.prefname %>のお店一覧</h1>

<% @stores.each do |store| %>
    <% if store.prefecture == @prefectures.prefname %>
        <h3><%=store.name%></h3>
        <p><%=store.smoking%></p>
        <p><%=store.city%></p>
    <% end %>
<% end %>
```

上記で、表示させているのは各都道府県のページに住所がその都道府県に該当する店舗データを表示させています。

## Prefix作成方法
### Prefixの確認

```terminal

$ rails routes
                   Prefix Verb   URI Pattern 
                     root GET    /static#home
                    users GET    /users(.:format)          users#index
                          POST   /users(.:format)          users#create
                 new_user GET    /users/new(.:format)      users#new
                edit_user GET    /users/:id/edit(.:format) users#edit
                     user GET    /users/:id(.:format)      users#show
                          PATCH  /users/:id(.:format)      pref GET    
                          GET    /detail/:id(.:format)     store#detail
```

**link_toメソッド**でリンク先を作成しますが普段通りに**rails routes**を行ってもPrefixfaが設定されていないので別途設定を行います。
リンクを作成するのは**GET    /detail/:id(.:format) store#detail**になります。

### routes.rbの設定

```routes.rb
Rails.application.routes.draw do

  root 'static#home'
(省略)
  get '/detail/z_:id',   to: 'store#detail'
```

蒸気が現状のコードになります。
そこから下記の様に**as:**をつけることでPrefixを設定することができます。


```routes.rb
Rails.application.routes.draw do

  root 'static#home'
(省略)
  #asでPrefix の設定ができる
  get '/detail/z_:id',   to: 'store#detail', as: 'detail'
```


### 再度確認

```terminal

$ rails routes
                   Prefix Verb   URI Pattern 
                     root GET    /static#home
                    users GET    /users(.:format)          users#index
                          POST   /users(.:format)          users#create
                 new_user GET    /users/new(.:format)      users#new
                edit_user GET    /users/:id/edit(.:format) users#edit
                     user GET    /users/:id(.:format)      users#show
                          PATCH  /users/:id(.:format)      pref GET    
                   detail GET    /detail/:id(.:format)     store#detail
```

これでPrefix作成は完了です。

## DBデータのリンク作成方法

Prefix作成をしたのちにlink_toメソッドをしようして普段通りにpathを記載し

```ruby
<h3><%=link_to store.name , detail_path %> </h3>
```
pathの後ろにidが入る様に設定すれば完了（↓のコードで完成）

```ruby
<h3><%=link_to store.name , detail_path(store.id) %> </h3>
```

## 全体図

```show.rb
<h1><%= @prefectures.prefname %>のお店一覧</h1>

<% @stores.each do |store| %>
    <% if store.prefecture == @prefectures.prefname %>
        <h3><%=link_to store.name , detail_path(store.id) %> </h3>
        <p><%=store.smoking%></p>
        <p><%=store.city%></p>
    <% end %>
<% end %>
```

これでコンテンツの一覧およびリンク先の完成
GCPのVision APIを使って画像の文字認識(OCR)をやってみる

実務で使う機会があったので備忘録。
軽めのハンズオン。

# Vison APIって？
Google Cloud Platform(GCP)が提供しているAPI
> AutoML Vision を使用してクラウド内またはエッジにある画像から有用な情報を引き出し、事前トレーニング済みの Vision API モデルを活用して感情を検知し、テキストを理解できます。

らしいです。
詳しくは[こちら](https://cloud.google.com/vision/?hl=ja)

# セットアップ

GCPの登録やAPIのセットアップはこの記事を参考にしました。
[Google Cloud Visionを使ってみた](https://www.itbook.info/web/2016/11/google-cloud-vision%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F.html)

# コードを書く

公式ドキュメントが充実しているのでかなり参考になりました。
[Cloud Vision API ドキュメント](https://cloud.google.com/vision/docs/?hl=ja)

今回はPHPを使用します。

`$composer require google/cloud-vision`
まずはcomposerで公式から配布されているクライアントパッケージをインストールします。

このクライアントを使ってVision APIを呼び出す場合には 環境変数に認証情報を設定する必要があります。
`$export GOOGLE_APPLICATION_CREDENTIALS=PATH_TO_KEY_FILE`
セットアップ時にダウンロードしたキーを設定しておきましょう。

コードはサンプルを改変しつつこんな感じです。

```php
<?php
require __DIR__ . '/vendor/autoload.php';

use Google\Cloud\Vision\VisionClient;

$vision = new VisionClient();

$file_name = "sample.jpg";

$resource = file_get_contents($file_name);
$image = $vision->image($resource, ['TEXT_DETECTION']);
$annotation = $vision->annotate($image);

$text = $annotation->fullText()->text();

var_dump($text);
```

# 画像を投げてみる

実際に試してみます。
今回投げる画像はこちら。
![IMG_20190918_174713.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210932/65f2c690-dd0c-95e0-2d64-331c47100adf.jpeg)

返ってきたテキストはこちら。

```
"第3版
Understand Your Data and
Be More Productive
詳説
正規表現
Jeffrey E. F. Friedl
訳
O'REILLY
株式会社ロングテール/長尾 高弘
オライリー·ジャパン
"
```

文章ではないため文字は散らばっていますが，単語や人名は抜けなく読み取れていますね！すごい！

# まとめ
このAPIが無料で使えるのだから驚き。
さすが天下のGoogle

月1000リクエストまでなら無料，仮に超えたとしても個人で試す程度であれば数ドル程度だから全然使えます。
色々出来そうなので何か考えたいところ…

おわり。
bit全探索って何？

#ビット全探索とは
**二進数**と**ビット**を用いて、ある集合の**部分集合**を全列挙するアルゴリズムの事を言う。

例えば**ABC**という集合ならば、
**{},{A},{B},{C},{AB},{AC},{BC},{ABC}**という**８個の部分集合**に分けられる！
これをC++でプログラムを書くと...

```C++
#include <bits/stdc++.h>
using namespace std;

int main(){
    string t="ABC";
    for (int bit=0; bit<(1<<3); bit++){
        string s="";
        for (int i=0; i<3; i++){
            if (bit&(1<<i)) s+=t[i];
        }
        cout << "{" << s << "}" << endl;
    }
}
```
```C++
#出力結果
{}
{A}
{B}
{AB}
{C}
{AC}
{BC}
{ABC}
```
#問題と提出コード
以下の問題はbit全探索に慣れるためにそれを用いて記述しました。そのためこれらの問題には、より簡単な解法が存在します。
##第一問　C - Train Ticket 
###問題概要
４桁の番号が与えられる。番号と番号の間全てに+か-を挿入してその演算結果が7になるものを出力せよ。
###解法
'+'か'-'の2通りを全探索すれば良いことが問題文から見て取れます。高々2^3回のループなので全探索で問題ありません。

```c++
#include <bits/stdc++.h>
using namespace std;

int main(){
        string s,t;
        cin >> s;
        t=s[0];
        int sum=0;
        //2^3回ループ
        for (int bit=0; bit<(1<<3); bit++){
                int a;
                //文字列をintに変換
                sum=s[0]-'0';
                t=s[0];
                for (int i=0; i<3; i++){
                        a=s[i+1]-'0';
                        //bitが立ってたら+
                        if(bit & (1<<i)) {
                                sum+=a;
                                t=t+'+'+s[i+1];
                        }else{  //bitが立っていなかったら-
                                sum-=a;
                                t=t+'-'+s[i+1];
                        }
                }
                //和が7なら文字列を出力
                if(sum==7) {
                        cout << t << "=7" << endl;
                        break;
                }
        }
        return 0;
}
```

#まとめ
###①全ての部分集合をbitで０と１のみで表す！
###②集合を一つずつ分ける
ex)ABC→'A','B','C'
そのあと、if文で一文字ずつあるか無いかを確かめれば、if,else含めて、全てを参照することができる！
libra-coreでweb-client-walletの作成から、送金まで

#はじめに
Libra関連のjsライブラリが続々と出ていて、現状だと知る限りこのような選択肢があるようです。

##SDK
https://github.com/perfectmak/libra-core
https://github.com/bandprotocol/libra-web
https://github.com/bonustrack/libra-grpc

ついでにViewerとしては、次のようなものが用意されています。

##Viewer
https://www.libravista.com/
https://libexplorer.com/

LibravistaのAPIなども公開されているので、ここからAPIを通じて、mintなどを試すこともできます。
https://api-testnet.libravista.com/doc/

今回は、試しに、libra-coreを使ってwalletを生成したいと思います。
(本家のREADMEと同じ手順)
#実装

##env

```
//nodeのversionは12以上
$ nodebrew ls-remote
$ nodebrew install-binary v12.10.0
$ nodebrew use v12.10.0
```

##install
```
$ npm install libra-core --save
```

##アドレス作成~mint~確認まで
試しに10000Libraをwalletにmintします

```users.js
var express = require('express');
const libra_core = require("libra-core");
var router = express.Router();
router.get('/mint', function (req, res, next) {
  const LibraWallet = libra_core.LibraWallet;
  const LibraClient = libra_core.LibraClient;
  const LibraNetwork = libra_core.LibraNetwork;
  const wallet = new LibraWallet();
  const account = wallet.newAccount();
  async function mint(account, amount) {
    const client = new LibraClient({
      network: LibraNetwork.Testnet
    });
    await client.mintWithFaucetService(account.getAddress(), amount * 1e6);
  }
  mint(account, 10000);
  res.json({
    status: "ok",
    address: account.getAddress().toHex()
  });
});
```


https://www.libravista.com/address/f24590077b5e5bd47bece5f31475dccc324561a3775f59627db6bf5a84cf2ad8

<img width="898" alt="スクリーンショット 2019-09-18 17.54.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/18973ed3-83a9-cc64-4ccb-f136a061ae59.png">

#おしまい

ちょいちょいtestnetのupdateも実施されているので、これらSDKも影響を受けることがありそうな予感。

https://community.libra.org/t/testnet-update-september-4th/1630

#参考
https://api-testnet.libravista.com/doc/

https://github.com/bonustrack/libra-grpc

https://developers.libra.org/docs/assets/papers/the-libra-blockchain.pdf

https://github.com/libra/libra/tree/master/admission_control
コンポーネント中心のCSS設計

# はじめに
コンポーネントの考え方の自由度を高くして、いろいろなスケールのプロジェクトに合わせることができるCSS設計を考えた。

- OOCSSやSMACSSのようなオブジェクト指向ではなく、[ECSS](https://ecss.io/)の考えをベースにした。
- コンポーネントは抽象化を避け、管理しやすさを重視する。
- COMPONENTS／ELEMENTS／VARIANTで構成する。
- ファイル管理で文脈がわかるようにする。



#COMPONENTS
- 全てのUIパーツをコンポーネントで構成する。
- ２ワードをハイフン（-）で繋いで命名する。
- キャメルケース（camelCase）にすれば１ワードとしてカウント。
- コンポーネントごとにscssファイルを分けて管理する。

```:component-sample.scss
.component-sample { ... }
```



#ELEMENTS
- コンポーネントの子要素。
- コンポーネント名とアンダースコアでつなぐ。（BEMのElementのように）
- １ワードで命名する。
- 親コンポーネントと同じscssファイルに含める。

```:component-sample.scss
...
.component-sample_element { ... }
```


#VARIANT
- コンポーネントやエレメントの変種・バージョン違い。
- 複数のヴァリアントを併用して良い。
- 必ずコンポーネントやエレメントとセットで使用する。単独で使用しない。
- エレメントのような使い方はしない。

```:component-sample.scss
.component-sample {
    &.-variant { ... }
}
.component-sample_inner {
    &.-black { ... }
}
//NG
.-large { ... }
//NG
.component-sample {
    .-element { ... }
}
```

#ディレクトリ構造
それぞれを別のフォルダにして、上から順に読み込む。
#####RESET
CSSのリセット。あらゆるプロジェクトであらかじめ設定しておいた方が良いスタイル。
#####(DEVELOP)
開発用のレイヤー。実際のコードにならないscssの変数やmixinなどを入れる。
色、文字サイズ、z-index、要素の高さと幅、アイコンフォント、レスポンシブ設定などを書く。
#####BASE
基本設定。このファイルはHTMLタグに直接スタイルを書いてよいこととする。
例えば、htmlタグに全体に適応される文字設定を書いたりする。
#####COMPONENTS
全てのUIパーツ。
なるべく共通化を避け、機能ごとに分類するようにする。
プロジェクトの要件に合わせ、componentsフォルダ内で分類できる。複数のレイアウトの種類がある場合はlayoutフォルダ内で管理したり、画面のカテゴリでフォルダをつくったり、文脈が分かるように整理する。

#####例
```:sample
_scss
├── _base
│   └── _base.scss
├── _components
│   ├── _button-pageTop.scss
│   ├── _category_menu.scss
│   ├── _category_title.scss
│   ├── _common
│   │   ├── _common-footer.scss
│   │   └── _common-header.scss
│   ├── _global-navi.scss
│   └── _main-visual.scss
├── _develop
│   ├── _breakpoints.scss
│   ├── _color.scss
│   ├── _font.scss
│   ├── _mixin.scss
│   ├── _print.scss
│   ├── _size.scss
│   └── _zindex.scss
├── _reset
│   └── _reset.scss
└── common.scss
```

#その他のルール
#####推奨
- モバイルファースト。基本的にmin-screenのみを使用してレスポンシブを切り替える。
- 色や文字、サイズなどは全てscssの変数とし、_developフォルダ内で管理する。
- 縦方向のmarginルールを決める。(margin-top派でもmargin-bottom派でも良いが、ルールを決めるのが大事。）
- 文字サイズや余白の単位はremかvwを使用する。pxの使用は推奨しない。
- 要素の高さはできるだけpxで指定しない。ロゴのサイズや、Sass変数で管理した方が良いヘッダーの高さなどは例外。
- gulp-sass-globを使用し、アスタリスク（*）でscssのimportをする。
- 可能な限り言葉を略さない。タイトルは`title`と書き`ttl`と書かない。もし略語を使う時は用語集をつくり共有する。
- 例外箇所はコメントを書き、多くなってきたらプロジェクトとしてのルールを見直す。

#####禁止
- 抽象度の高い名前は避ける。（例：`.text-1`といったクラスは禁止）
- scssのextendは使用しない。依存関係が複雑になるため。
- !importantは使用しない。
- HTMLタグに直接スタイルを書かない。（BASEファイルは例外。その他ファイルで書く場合はコメントで例外だとわかるようにする。）
- idにスタイルを書かない。
- 汎用クラスは使わない。（例：いろんなcomponentsを大きくするクラスはつくらない。）
- 抽象的な接頭辞（Prefix）は使用しない。Componentsの名前で工夫し、略語を使う場合はプロジェクト内で共有する。

#まとめ
コンポーネントの自由度を高くした分、コンポーネント内で独自の設計が可能になる。メタなCSS設計とも言えると思う。大きな（複数人が関わる）プロジェクトではこの設計の上でさらに詳細な設計が必要となるだろう。そのような場合でもベースとしてこのCSS設計が役に立つと思う。
osrmのルート検索を関東データでお試し

# 0. 前提

1. osrmのセットアップが終わっている事
1. curlが使えること(ブラウザでもいいけど)
1. wgetが使えること(ブラウザでもいいけど)

**ディレクトリ構成**

```
    /home/tomonobu/work/
                        osrm-backend/ ... osrmをインストールしたディレクトリ
                        osm/          ... osmデータ用ディレクトリ
                           kanto/     ... 関東
                           berlin/    ... ベルリン
```

# 1. OSMデータのダウンロード

  関東 http://download.geofabrik.de/asia/japan/kanto-latest.osm.pbf

```console
  $ pwd
  /home/tomonobu/work/osm/kanto <== ここのディレクトリにダウンロードする

  $ wget http://download.geofabrik.de/asia/japan/kanto-latest.osm.pbf
```

# 2. OSMデータの展開

実行は osrmをインストールしたディレイクトリで

```console
$ pwd
/home/tomonobu/work/osrm-backend

$ osrm-extract   ../osm/kanto/kanto-latest.osm.pbf
$ osrm-partition ../osm/kanto/kanto-latest.osrm
$ osrm-customize ../osm/kanto/kanto-latest.osrm
```
# 3. サーバ起動

```console
$ osrm-routed --ip 127.0.0.1 --port 5000 --algorithm mld ../osm/kanto/kanto-latest.osrm
```

# 4. 始点と終点の緯度経度を決めよう

[Googleマップ](https://www.google.co.jp/maps/) → 右クリックで「この場所について」

- 始点 35.1617517,139.728336
- 終点 35.656327,139.792895

# 5. ルート作成

```console
$ curl --noproxy 127.0.0.1 'http://127.0.0.1:5000/route/v1/driving/139.728222,35.617534;139.792895,35.656327?alternatives=3&geometries=geojson' | jq 'def hexdec(i): "0123456789abcdef"[i:i+1]; {"type": "FeatureCollection", "features": [[.routes[].geometry] | [., keys] | transpose[] | {"geometry": .[0], "type": "Feature", "properties": {"stroke-width": 2, "stroke": ("#" + hexdec(15-.[1]*2) + hexdec(.[1]*2) + hexdec(.[1]*2))}}]}' > routes_kanto2.json
```

==> 成功

# 6. ルート表示

出来上がった routes_kanto2.json を
http://geojson.io
に食わせれば、ルートが表示される

EOF
tools 属性を使ってプレビュー表示

レイアウトプレビューで
```<ListView tools:listitem="@layout/list_custom_item" ```
のようにListViewにカスタムレイアウトを指定することで
プレビュー画面でリストアイテムを表示させることができる。

tools 属性を使うと、プレビュー画面がもっと便利になる。
https://developer.android.com/studio/write/tool-attributes.html

``` activity_list.xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:listitem="@layout/list_custom_item"/>

</LinearLayout>
```

いじょ。
PHPからdjangoのユーザ認証

## djangoのパスワード

PHPからdjangoのユーザ認証する方法を検討した。

## 参考資料
* Djangoドキュメント [Password management in Django](https://docs.djangoproject.com/en/2.2/topics/auth/passwords/)
* [hash_pbkdf2](https://www.php.net/manual/en/function.hash-pbkdf2.php)

## djangoはどのようにパスワードを保存しているか

djangoのデータベースは既定ではdb.sqlite3。sqlite3コマンドで中身を確認する。

```bash
$ sqlite3 db.sqlite3
```
```
sqlite> .tables
```

パスワードの入っているテーブルはauth_user。データベースのフィールド名を確認するためヘッダを表示する。

```
sqlite> .header on
```

ユーザを表示してみる。

```
sqlite> select * from auth_user
```

ユーザ名はusername，パスワードはpasswordに入っている。SQLで特定のユーザのパスワードを表示する。例えばjoeのパスワードは取り出すには，次のようにする。

```
sqlite> select password from auth_user where username==’joe’
```

パスワードは次の形式で保管されている。

    アルゴリズム$繰り返し数$ソルト$ハッシュ値

django 2.2時点で既定のアルゴリズムはpbkdf2のsha256（pbkf2_sha256），繰り返し数は150000。ハッシュ値はbase64エンコードされている。

PHPでパスワードからハッシュ値を生成するには，hash_pbkdf2()とbase64_encode()を使う。

```php7
$hash = base64_encode(hash_pbkdf2(“sha256”, $password, $salt, $iterations, 0, true));
```

データベースで取得したハッシュ値と$hashを比較すればよい。
Homesteadで複数サイトを見れるようにする（Nginxのバーチャルホストを使う）

`Homestead.yaml` の `sites` に2つ登録すると、Nginxの設定ファイルが2サイト分出来上がるので、バーチャルホストで分岐する感じ。


```yaml:Homestead.yaml
folders:
    - map: C:\aaaa\bbbb\app1
      to: /home/vagrant/app1
    - map: C:\aaaa\bbbb\app2
      to: /home/vagrant/app2

sites:
    - map: homestead.appa
      to: /home/vagrant/app1/public
    - map: homestead.appb
      to: /home/vagrant/app2/public
```

で、`hosts` に、↓を追加。

```
192.168.10.10 homestead.appa
192.168.10.10 homestead.appb
```

`vagrant reload --provision` する。

VM内で↓するとNginx用のファイルが2つある。

```bash
> ls  /etc/nginx/sites-enabled/
homestead.appa  homestead.appb
```

アクセスするURLを `http://homestead.appa` （or `http://homestead.appb`） にする。
MacOSXでUSBシリアル変換ケーブルを使う方法

### USBシリアルケーブルを使うシチュエーション
使うパターンはRaspberryPi接続等あるが、Ciscoのスイッチに接続したいとする。
コンソールケーブルが`RS-232C`と`RJ-45`のパターン。
このとき、RS-232C to USBのUSBシリアル変換ケーブルを使って接続するときがある。

[pc][usb] --- [usb][usbシリアル変換ケーブル][RS-232C] --- [RS232C][RJ-45] --- [cisco スイッチ]

例えば上記のような接続。
このとき、PC側はMacのときにはWindows同様ドライバ必要となる。
※ 最近はUSB接続もサポートしているようだ。参考：<a href="https://www.cisco.com/c/ja_jp/products/switches/catalyst-2960-l-series-switches/index.html#datasheets-literature">Cisco Catalyst 2960-L シリーズ スイッチ - Cisco</a>

#### 使ったUSBシリアル変換ケーブル
昔から秋葉原のこちらが使い勝手がよく今も使えると見える。
[ＵＳＢシリアル変換ケーブル　スケルトン](http://akizukidenshi.com/catalog/g/gM-00720/)
秋月電子さまさま。

ここで、サポートドライバがWindowsのみというのはよくある話。

#### Mac用のドライバを入手する
`PL2303` なことを確認する。
[PL2303 Mac OS X Driver Download  ]
(http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=229&pcid=41)

そこで、対応ドライバを見極めてこちらを入手して使う。
本日確認したバージョンでも、 1.6.2(PL2303_Mac OSX Drv_V1.6.2_20190723.rar)と
2019年もサポートされていて心強い。
直近でも `Mac OS High Sierra` version 10.15, 10.14, 10.13 ... とサポートあり。

ドライバは導入するだけ。

### terminalで接続
あとはターミナルで接続設定をすれば使えるようになる。
cuが使える。

```shell-session
$ cu -s 115200 -l /dev/tty.usbserial
```
接続時の速度指定と認識するデバイス名に注意。

また、 `screen` を使う手もある。

### 参考サイト
<a href="https://qiita.com/kobaboy/items/2e15805cf485de3ddf79">【シリアル接続】Mac でシリアルコンソールを利用してみた - Qiita</a>

こちらがとても詳しいし参考にしたサイトも助かる。
RxKotlinをつかってみたメモ書き


以前の現場でRxJavaを使って開発してたのですが、
RxKotlinもあるよ、ということなので、暇つぶしにつかってみた。

* 公式GitHub
  https://github.com/ReactiveX/RxKotlin

* 参考にしたページ（というかコピペ）
 https://medium.com/@laurence.liuuu/android-reactive-programming-with-reactivex-basic-examples-with-rxjava2-rxkotlin-and-rxandroid-d202ad64370d

``` gradle:app/build.gradle
android {
    ・・・(略)・・・
}
dependencies {
    ・・・(略)・・・
    implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
    implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
}
```
ライブラリは上記３つのみ追加すればOK。


``` Kotlin:RxKotlinBasicDialogFragment.kt
package com.example.myapplication

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxkotlin.toObservable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.dialog_reactive.*

class RxKotlinBasicDialogFragment : DialogFragment() {

    private lateinit var mDisposable: Disposable
    private var mResult: String = ""

    companion object {
        fun newInstance(): RxKotlinBasicDialogFragment {
            return RxKotlinBasicDialogFragment()
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val anyObservable = getList().toObservable()
        mDisposable = anyObservable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeBy(
                onNext = {
                    Log.i("onNext", it.toString())
                    mResult += "$it, "
                },
                onError = {
                    Log.i("onError", it.toString())
                },
                onComplete = {
                    Log.i("onNext", "DONE!!")
                    resultTextView.text = mResult
                }
            )
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.dialog_reactive, container, false)
    }

    override fun onDestroy() {
        super.onDestroy()
        mDisposable.dispose()
    }


    private fun getList(): List<Any> {
        return listOf(true, 1, 2, "Three", 4.0f, 4.5, "Five", false)
    }
}

```
![device-2019-09-18-173150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303516/3818ece0-bc94-4234-48db-195b23ca88e9.png)


あとで、FlatMapとかzipもためしてみる。。。
【Python】文字列から数値のみを抽出する

`'hehu44jh３dsjh8sjb3bf９９jk88hj100'`のような文字と数値が入り乱れている文字列の中から全角、半角関わらず数値のみを抽出し以下のようにリスト化する。

`'hehu44jh３dsjh8sjb3bf９９jk88hj100'` → `[44, 3, 8, 3, 99, 88, 100]`

```python
import re 

text = 'hehu44jh３dsjh8sjb3bf９９jk88hj100'

nums = re.sub('\\D', '-', text)
print(nums)

num_list = [int(n) for n in nums.split('-') if n]
print(num_list)
```

```python:実行結果
----44--３----8---3--９９--88--100
[44, 3, 8, 3, 99, 88, 100]
```
自作の顔検出APIを作成しIBM Cloudで公開する

OpenCVを使うと深層学習ベースの顔検出を実装することが可能です。本記事では[こちら](https://www.learnopencv.com/age-gender-classification-using-opencv-deep-learning-c-python/)の記事にあるコードをベースに、画像から人物の顔を検出し、性別、年齢を特定するAPIを作成し、IBM Cloudに公開する手順を紹介します。

# 1. コードおよびモデルの取得
以下からコードを取得します。

```
$ git clone https://github.com/schiyoda/FaceDetection.git
```

性別および年齢推定のモデルは前述の記事の中に下図の通りリンクがありますので、コードと同じフォルダにダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235649/10264928-30de-9ee9-e37f-bb1c16b2ae9e.png)

# 2. ローカルで実行
以下のコマンドで実行可能です。

```
$ python run_server.py 
 * Flask starting server...
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
```

顔検出は画像ファイルあるいは画像のURLをPOSTすることで実行可能です。

- 画像ファイルをPOST

```
$ curl -X POST -F img_file=@pexels-photo-1470110.jpeg http://0.0.0.0:5000/detectFace
```

- 画像のURLをPOST

```
curl -X POST -F url=https://images.pexels.com/photos/1470110/pexels-photo-1470110.jpeg http://0.0.0.0:5000/detectFace
```

いずれの方法でも以下のような応答が返ってきます。

```
{
  "faces": [
    {
      "age": {
        "confidence": "0.996", 
        "max": "12", 
        "min": "8"
      }, 
      "face_location": {
        "height": 505, 
        "left": 1789, 
        "top": 1023, 
        "width": 415
      }, 
      "gender": {
        "confidence": "1.000", 
        "gender": "Male"
      }
    }, 
    {
      "age": {
        "confidence": "0.995", 
        "max": "2", 
        "min": "0"
      }, 
      "face_location": {
        "height": 444, 
        "left": 1014, 
        "top": 1057, 
        "width": 380
      }, 
      "gender": {
        "confidence": "1.000", 
        "gender": "Male"
      }
    }, 
    {
      "age": {
        "confidence": "0.999", 
        "max": "32", 
        "min": "25"
      }, 
      "face_location": {
        "height": 526, 
        "left": 1402, 
        "top": 463, 
        "width": 413
      }, 
      "gender": {
        "confidence": "0.943", 
        "gender": "Female"
      }
    }
  ]
}
```

コードには含まれませんが、OpenCVで可視化すると以下のような結果が得られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235649/fbe5b495-dbbe-b27c-0497-50397375737b.png)

# 3. IBM Cloudにデプロイ
IBM Cloudの Cloud Foundry アプリとしてデプロイするには以下のようにします。

```
$ ibmcloud login
$ ibmcloud target --cf
$ ibmcloud app push アプリ名
```

デプロイ後は以下のように実行可能です。

```
curl -X POST -F img_file=@sample1.jpg http://アプリ名.mybluemix.net/detectFace 
{"faces":[{"age":{"confidence":"0.983","max":"12","min":"8"},"face_location":{"height":195,"left":677,"top":384,"width":160},"gender":{"confidence":"1.000","gender":"Male"}},{"age":{"confidence":"0.701","max":"6","min":"4"},"face_location":{"height":171,"left":383,"top":400,"width":146},"gender":{"confidence":"1.000","gender":"Male"}},{"age":{"confidence":"0.987","max":"32","min":"25"},"face_location":{"height":199,"left":530,"top":177,"width":158},"gender":{"confidence":"0.992","gender":"Female"}}]}

```
CentOSにphpを入れる

## 概要
CentOSにphp入れたい

## 関連用語
* rpm・・・redhat package manager。red hatで使用するパッケージを管理する
* yum・・・rpmパッケージを管理する。パッケージの依存関係を解決してくれる
* リポジトリ・・・ここでいうリポジトリは、rpmパッケージが保管されている場所のこと。

## epelリポジトリ追加
登録されているリポジトリ確認

```
# yum repolist
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: mirror.fairway.ne.jp
 * extras: mirror.fairway.ne.jp
 * updates: mirror.fairway.ne.jp
repo id            repo name          status
base/7/x86_64      CentOS-7 - Base    10,019
extras/7/x86_64    CentOS-7 - Extras  435
updates/7/x86_64   CentOS-7 - Updates 2,500
repolist: 12,954
```

epelリポジトリをインストール

```
yum install epel-release
```

再度リポジトリを確認

```
# yum repolist
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: mirror.fairway.ne.jp
 * epel: ftp.jaist.ac.jp
 * extras: mirror.fairway.ne.jp
 * updates: mirror.fairway.ne.jp
repo id          repo name                                      status
base/7/x86_64    CentOS-7 - Base                                10,019
epel/x86_64      Extra Packages for Enterprise Linux 7 - x86_64 13,384
extras/7/x86_64  CentOS-7 - Extras                              435
updates/7/x86_64 CentOS-7 - Updates                             2,500
repolist: 26,338
```

## Remiリポジトリ追加
Remiリポジトリを追加

```
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
```

リポジトリを確認

```
# yum repolist
・・・
remi-safe  Safe Remi's RPM repository for Enterprise Linux 7 - x86_64  3,601

・・・
```

## phpインストール

```
yum install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd
```

```
# php -v
PHP 7.0.33 (cli) (built: Aug 28 2019 14:11:09) ( NTS )
```

## 疑問点
* rpm -Uvhってインストール済みパッケージのアップデートじゃないの？なぜリポジトリ追加になるのかわからない

## 参考
[「yum install epel-release」や「--enablerepo=remi」の意味,本当に理解して使ってますか?](https://akamist.com/blog/archives/648)
[CentOS7にPHP7をyumでインストールする](https://qiita.com/inakadegaebal/items/b57cf10339978d638305)
[【 yum 】コマンド（基礎編）](https://www.atmarkit.co.jp/ait/articles/1608/29/news019.html)
[rpmとかyumとかよくわからず使ってないか？](https://qiita.com/ritukiii/items/cc22efd005a06b8d4a86)
プログラマにオススメのMarkdownエディタ？ メモアプリ？ #VsCode + VS Notes プラグイン に決まってるでしょ？

# メリット

- VsCode使える

以上。

# 今開いているプロジェクト(ワークスペース)と同じウィンドウ内、なおかつ別タブで使える！

gitでのファイル差分とか増やさないし！ 干渉しない。素晴らしい。

# サイドバーで管理できる！

![image](https://user-images.githubusercontent.com/13635059/65117663-30ddd400-da25-11e9-8d03-47ab8aa2bf87.png)

# 残念なところ

- 別のワークスペースからでは、サイドバー、コマンドでファイル削除できないっぽい。noteフォルダをワークスペースとして開くと可能。

![image](https://user-images.githubusercontent.com/13635059/65118002-8b773000-da25-11e9-8095-63ec7ee5c361.png)

# セットアップ

コマンドパレットで vsnotes setup とか入力

適当なディレクトリをメモ用に設定する。

![image](https://user-images.githubusercontent.com/13635059/65115965-5833a180-da23-11e9-9ff6-b1037a262338.png)
![image](https://user-images.githubusercontent.com/13635059/65115991-608bdc80-da23-11e9-80c3-dd54768d81a6.png)
![image](https://user-images.githubusercontent.com/13635059/65116968-6df59680-da24-11e9-8193-f7de2f4130fb.png)

# ノートを作る

タイトルを入れると勝手にマークダウンを作ってくれる。拡張子を指定することもできそう、


![image](https://user-images.githubusercontent.com/13635059/65116775-2969fb00-da24-11e9-87b9-bcf1a2e2a518.png)


![image](https://user-images.githubusercontent.com/13635059/65116867-4acae700-da24-11e9-8982-b7e53b1de97d.png)
![image](https://user-images.githubusercontent.com/13635059/65116870-4b637d80-da24-11e9-8e96-dc3cadf047bc.png)

(Mac環境でEnterを押した時、何度かうまく動かなかったけど、日本語入力とかが干渉してそう？)

# メモを一覧する、開く

![image](https://user-images.githubusercontent.com/13635059/65117218-ae551480-da24-11e9-80da-c74a6ac5e3b2.png)
![image](https://user-images.githubusercontent.com/13635059/65117248-b57c2280-da24-11e9-9418-2e9460e38ecf.png)



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2475








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
複数バージョンのOracle DBにODAC（ODP.NET）を用いてアクセスするアプリケーションを作る際の参照先DLLに関する注意点

#目的
ODACを利用してOracle DB(以下通じる場合はDBを省略)に接続するアプリケーションをVSで作成する場合、開発時にOracle.DataAccess.dllを参照する設定を行う。
アプリケーションの要件として複数のOracle(11g, 12c, 18c...)への接続が存在する場合、開発環境はどのような構成にすればよいかを考える。

#side-by-side実行におけるdll依存関係
[@IT](https://www.atmarkit.co.jp/fdotnet/technology/idnfw11_04/idnfw11_04_01.html)や[MSのページ](https://docs.microsoft.com/ja-jp/dotnet/framework/deployment/side-by-side-execution)で解説されているように、アプリケーションはside-by-sideで実行されるため、開発時に参照していたdllは、そのバージョンまでが一致していないとアプリケーションで利用されないという原則が存在している。
これは、意図していないdllを読み込むことに起因する実行時エラーを防ぐために必要な機能なのだが、Oracle.DataAccess.dllのようにアプリケーションと同梱して配置することが困難なdll(ライセンスの関係で、客先に配置してもらう必要があるため)を参照する際には注意が必要である。

#発行者ポリシーを用いたアセンブリバージョンのリダイレクト
side-by-side実行では、参照先と同じバージョンのdllしか読み込まれないのが原則だが、GACに登録されたdllを用いる場合、GAC内に発行者ポリシーファイルが存在すれば、使用するdllより新しいバージョンのdllを利用するように指定することが可能である。
アセンブリバージョンのリダイレクトや発行者ポリシーに関しては[「アセンブリ バージョンのリダイレクト」](https://docs.microsoft.com/ja-jp/dotnet/framework/configure-apps/redirect-assembly-versions)や、[「解説 インサイド .NET Framework ［改訂版］
第4回　アセンブリとバージョン管理」](https://www.atmarkit.co.jp/fdotnet/technology/idnfw11_04/idnfw11_04_02.html)
に詳しい説明が乗っているが、ODACの場合ODP.NETフォルダ配下にあるOracle.DataAccess.dllとODP.NET/PublisherPolicyフォルダ内のPolicy.x.xxx.Oracle.DataAccess.dllを登録してあげればアセンブリリダイレクトが定義される。具体的にはOraProvCfg.exeを用いて登録をすればよいのだが、その方法は[別途記事](https://qiita.com/bearbutler/items/3bb21b385505dc2f1c08)を記している。

#アセンブリリダイレクトの問題
実際に、Policy.4.112.Oracle.DataAccess.configなどをエディタで開いてみてもらえればわかるが、Oracle.DataAccess.dlアセンブリリダイレクトは、古いバージョンのdllを参照していたアプリケーションに新しいバージョンのdllを使うよう指示されている。
現在ODACの18.0.0を手元に所持してるが、ここには（CLR4.0では)11.2以降の全てのOracle.DataAccess.dllを参照しているアプリケーションは4.122.18.3のバージョンを使うように書かれている。
ここで注意したいのは、参照しているdllよりも古いバージョンのdllを使うような記述が書かれていない点である。
つまり、4.122.18.3のバージョンを参照して作成されたアプリケーションは、より古いバージョンのODACがインストールされた環境では動かなくなってしまうということだ。
サイトから最新版のODACをダウンロードしてきてインストールをした場合、このようなケースに陥る可能性が高い。

#解決策
アプリケーションが動かなくなることを避けるためには、以下のような対策を考える必要がある。
ひとつ目の解決策は、アプリケーションをインストールするサーバーのODACを最新版にすることだ。
発行者ポリシーが謳っている通り、Oracle.DataAccess.dllは後方互換性があるので、古いバージョンをアンインストールし、互換性のある最新のODACをインストールしてもらえれば問題は解決する。
ふたつ目は、開発環境で参照するdllのバージョンを一番古いバージョンに設定する方法だ。
VSの設定で参照するOracle.DataAccess.dllを古いものに設定すればGAC参照時には新しいdllにリダイレクトされるので、どのバージョンのOracleに対しても接続が保障されている。
なお、ODACは複数バージョンを一つのPCにインストールすることも可能なので、インストールした中から必要なdllを選んで参照してあげればよいのだが、複数バージョンをインストールする際には環境変数やレジストリの設定が自分の意図したとおりになっていない可能性があるため、注意が必要になるが、この問題に関しては別途ページを改めてまとめようと思う。
windows + virtualbox + vagrant でhomestead環境の構築

windows環境にHomestead環境をインストールする手順です。

# TL;DR

ほとんど[参考サイト](#参考)の手順に則っていますが、[homestead.ymlの編集](#homesteadymlの編集) の箇所だけUnix向けで、windowsでは調整が必要だったので公開します。

# 前提となる環境
各々インストールしている状態を前提とします。インストール方法については、[参考サイト](#参考)に記載があります。

- Git
- VirtualBox
- Vagrant

動作環境はwindows10 Homeです。

# Homestead環境の構築
コマンドプロンプト上で作業をします。作業はホームディレクトリを使用中。

##インストール
今回は最新リリースのv9.1.0を使用します。好きなバージョンを選んでいただければ。
ここも、指定するバージョンを除けば[参考サイト](#参考)と変わりはありません。

```cmd
> vagrant box add laravel/homestead
> git clone https://github.com/laravel/homestead.git Homestead
> cd Homestead
> git checkout v9.1.0
> init.bat
```

##Homestead.ymlの編集

Homestead.ymlを以下のように書き換えます。
デフォルトはUnixの形式になっているので、windowsのフォルダ形式で指定しなおす必要があります。

\<user_name\>の箇所は、各々のユーザで書き換えてください。
vimで開いて、`:%s/<user_name>/taro_hida/g`とか使うと便利です。

```
---
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox

authorize: C:\Users\<user_name>\.ssh\id_rsa.pub

keys:
    - C:\Users\<user_name>\.ssh\id_rsa

folders:
    - map: C:\Users\<user_name>\Homestead\code
      to: /home/vagrant/code

sites:
    - map: 192.168.10.10
      to: /home/vagrant/code/public

databases:
    - homestead

# ports:
#     - send: 50000
#       to: 5000
#     - send: 7777
#       to: 777
#       protocol: udp

# blackfire:
#     - id: foo
#       token: bar
#       client-id: foo
#       client-token: bar

# zray:
#  If you've already freely registered Z-Ray, you can place the token here.
#     - email: foo@bar.com
#       token: foo
#  Don't forget to ensure that you have 'zray: "true"' for your site.
```

`vagrant up`発行してしばらく待機し、プロンプトが返ってきたら`vagrant ssh`でログインしましょう。
sshが利用できるなら、`ssh vagrant@192.168.10.10 -i C:\Users\<user_name>\.ssh\id_rsa`でログインできます。
もちろん、RLoginなどのターミナルソフトからsshログインすることも可能です。

```
> vagrant up
..(略)..
> vagrant ssh
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124948/e83038bc-ba38-e8f0-5c8b-7e038c1c2c5d.png)

↑ ログイン後の画面。こういうAA出力すき

# 参考


- [Laravel開発のはじめかた Windows編](https://www.hypertextcandy.com/start-laravel-project-on-windows)
[AzureDevOps] PullRequestのdiff表示で空白の差分を無視することができない

AzureDevOpsでプルリクをレビューする時に、空白のみの差分は無視して重要なところだけをレビューしたいのにできない、という話。

# Githubでは
Githubだと [これ](https://github.com/tiimgreen/github-cheat-sheet#ignore-whitespace) でできるんですけどねぇ。クエリパラメータにw=1をつけるやつ。

# ホントにできないの？
本件、MSの Developer Community でも議論されているようですが、現時点(2019/9/18)ではムリみたいです…。

[In pull request, unchecked show and diff whitespace still shows a diff in white space](https://developercommunity.visualstudio.com/content/problem/508669/in-pull-request-unchecked-show-and-diff-whitespace.html)　とか

[pull request diff ignore whitespace](https://developercommunity.visualstudio.com/idea/365666/pull-request-diff-ignore-whitespace.html)　とか

> As noted in the posted solution, this behavior is as designed.
> Only leading and trailing whitespace is ignored, not whitespace within a line of code.

それっぽい設定項目があるのですが、先頭と末尾の空白しか無視してくれないみたいです。残念。
pythonによるjson,csvファイルのS３へのダウンロード、アップロード

## ダウンロード

### S3上のcsvファイルをデータフレーム型として取得

```python

import boto3
import pandas as pd
from io import StringIO

s3_get = boto3.client('s3')
objkey = container_name + '/' + filename + '.csv'
obj = s3_get.get_object(Bucket=bucket_name, Key=objkey)
body = obj['Body'].read()
bodystr = body.decode('utf-8')
df = pd.read_csv(StringIO(bodystr))
```

### S3上のjsonファイルを辞書型として取得

```python

import boto3
import json

s3_get = boto3.client('s3')
objkey = container_name + '/' + filename + '.json'
obj = s3_get.get_object(Bucket=bucket_name, Key=objkey)
body = obj['Body'].read()
bodystr = body.decode('utf-8')
js = json.loads(bodystr) 
```

## アップロード

### データフレーム型のデータをcsvファイルとしてs3にアップロード
```python

import boto3
import pandas as pd

s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)
df_csv = df.to_csv(index=None) # dfはデータフレーム型のデータ
objkey = container_name + '/' + filename + '.csv'
putobj = bucket.Object(objkey)
putobj.put(Body=df_csv)
```

### 辞書型のデータをjsonファイルとしてs3にアップロード

```python

import boto3
import json

s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)
objkey = container_name + '/' + filename +'.json'
putobj = bucket.Object(objkey)
putobj.put(Body=json.dumps(OrderedDict(json_data), ensure_ascii=False))
```
AndroidタブレットにUbuntuをインストールするの補足 ＆ ヘルプミー

##覚書##

Android9だと、XServer XSDLが再起動のループするという問題を加味しての解決方法

[AndroidタブレットにUbuntuをインストールするの補足](https://qiita.com/yetanothersu/items/152b96c6f59561800d07)

[XServer XSDL](https://play.google.com/store/apps/details?id=x.org.server&hl=ja) の代替として[bVNC](https://play.google.com/store/apps/details?id=com.iiordanov.freebVNC&hl=ja)を利用できそうです。

bVNCをインストール

UserLAndの設定
Sessionsタブで対象のリストを長押し -> Stop Session
Sessionsタブで対象のリストを長押し -> Edit -> Service Type:ssh -> vnc
フロッピーアイコンをクリック

対象のリストをタップ -> bVNCが自動起動
xfce4 が立ち上がる

以上

##追記##
ブラウザのインストール

```shell-session
$ sudo apt install chromium-browser
$ chromium-browser --no-sandbox
```
##ヘルプミー 助けてください##
Synaptic root権限で動かせず

##Android Linuxの根本的問題##
2019/12/16 追記
しばらく弄ってわかったこと
Androidによるアプリの切り替えを行うとメモリオーバーか、LINUXがオチる現象あり
Ubuntuを使うことで汎用アプリの利用を見据えていたが、そもそもAndroidってarm64じゃん、って話でソフトウェアが揃ってねーっす(-_-;)
Raspai3 がarm64？なら探せばあるのかな…？

##Special Thanks##
[HYPERでんち](https://dench.flatlib.jp/linux/userland)