OmniAICreator/Qiita-1.07M huggingface dataset:
3次元空間リコンストラクション・デジタルアバター 　　関連記事

Facebook による空間Replicaの記事。
Githubにデータがあり使用可能。AIトレーニングのシミュレーションにレプリカ空間を利用。
How Facebook researchers’ realistic simulations help advance AI and AR
Replica and AI Habitat are key to developing experiences like social presence and intelligent assistants
https://tech.fb.com/facebook-reality-labs-replica-simulations-help-advance-ai-and-ar/

Facebookによるフォトリアリスティックな人間アバターの研究
Facebook is building the future of connection with lifelike avatars
The Codec Avatars project is all about defying distance
https://tech.fb.com/codec-avatars-facebook-reality-labs/
OpenGrokの公式Dockerイメージでソース検索サーバーを立てる

## まえおき

だいぶ昔に [OpenGrok+Dockerで、使い捨てソース検索エンジンをつくる](https://qiita.com/YusukeIwaki/items/3f855202e9c00247d5c7) っていう記事書いてたんですが、時は流れ、いまは https://github.com/OpenGrok/docker で公式にDockerイメージが提供されています。

## docker-composeで。

/opengrok/src っていうところを対象にインデックスするよ！ということらしいので、

```docker-compose.yml
version: '3'
services:
  opengrok:
    image: opengrok/docker:latest
    volumes:
      - .:/opengrok/src:ro
    environment:
      REINDEX: 0
      INDEXER_OPT: "-i d:node_modules -i d:vendor"
    ports:
      - 8888:8080
```

みたいな感じでcomposeファイルを作って、 docker-compose upすればよさそう。
（既存でdocker-compose使っているなら、単純に `opengrok:` 配下を付け足せばOK）

http://localhost:8888/ にアクセスすれば、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/60f7989f-8d78-67c4-8dd0-75aacd3d7fe4.png)

しばらく待ったら使えるようになるはず。


## 気になるところ

なんか `INDEXER_OPT: "-i d:node_modules -i d:vendor"` が仕事してない気がする。

https://github.com/oracle/opengrok/blob/master/opengrok-indexer/src/main/java/org/opengrok/indexer/index/Indexer.java#L537
には定義あるんだけどなー・・・

そのうちちゃんと調べる。
def文及びlambda式不使用で関数を作る挑戦

## はじめに
初心者プログラマーながらアウトプットにも挑戦してみようと思い記事を書くことにしました。 
 
※以下の記事で使用している`内包表記内でのyield式の使用`は3.7で非推奨、3.8以降で動かないことが判明しています。[参照](https://docs.python.org/ja/3/reference/expressions.html#yieldexpr)

### 環境
• python3.6.1 

## TL;DR
位置引数を受けるものなら標準ライブラリの使用まで妥協し実現できた。 
キーワード引数の受け取り方は不明 

## 詳細
この試みを思い立ったきっかけは何処かでyieldを式として使えるという記事を見たことです。 
と言うわけで位置引数一つを取る事が可能になりました。 

```python
next(
    func for func in (
        (
            0 for _args, _return in iter([[], [None]].copy,None)
            if _args.append((yield _return[0])) or [[
                0 for arg in _args 
                for _return[0] in (arg,) if not print('arg is', arg)
            ]] and _args.clear()
        ),
    ) if [next(func)]
).send
```

次に必要なのは複数の引数をどうにかしてこれに渡す事です。 
max/min関数が誂え向きでした。と言う訳で複数の位置引数を取れるようになります。 
functool.partialで小細工をして、 
 
```python
next(
    __import__('functools').partial(
        max, _return,
        key = next(
            func for func in ((
                0
                for _ in iter(int,1)
                if _args.append((yield 0)) or 
                ((_return.__setitem__(0,None) or [[
                    0 for _return, *args in (_args,)
                    for _return[0] in (args,) if not print('args are', args)
                ]] and _args.clear())
                if ((_args[0] is _return and _args.count(_return)==1 or _args.clear()) and len(_args)==_count) else _return.__setitem__(0,'error'))
            ),) if [next(func)]
        ).send
    )
    for _return, _count, _args in ((['error'], 1+2, []),)
)
```
 
 
以下のコードはこれらを利用し、再帰処理的に階差計算をするものです。
そのままやると、動かしている最中のジェネレーターにsendは送れないと怒られるので毎度生成される様にしてあります。 

```python
next(func for func in ((0 for _args, _return in iter([[], [None]].copy,None)if _args.append((yield _return[0])) or [[0 for N in _args for _return[0] in (next(func for func in ((0 for _args, _return in iter([[], [None]].copy,None)if _args.append((yield _return[0])) or [[0 for f in _args for _return[0] in (f()(f, N)[0],)]] and _args.clear()),) if [next(func)]).send((next(__import__('functools').partial(max, _return,key = next(func for func in ((0for _ in iter(int,1)if _args.append((yield 0)) or ((_return.__setitem__(0,None) or [[0 for _return, f, n in (_args,)for _return[0] in (1 if n==1 else f()(f, n-1)[0]*n,)]] and _args.clear())if ((_args[0] is _return and _args.count(_return)==1 or _args.clear()) and len(_args)==_count) else _return.__setitem__(0,'error'))),) if [next(func)]).send)for _return, _count, _args in ((['error'], 1+2, []),)) for _ in range(N)).__next__),) ]] and _args.clear()),) if [next(func)]).send
```

階乗といえば個人的には`reduce(int.__mul__, range(1,6))`ってするのが好きです

## まとめ
def文又はlambda式アレルギーのあるお子様のいるご家庭でもpythonは安心してお使いいただけます。
難しい事がわからなくともワンライナーはパズルとして気軽に挑戦し、楽しめるので暇つぶしに最適です。
Amazon Photosと同期してファイル更新日が上書きされた写真群をできるだけ撮影日時に近い日付でGoogleフォトに保存する

# 困っている状況

- Amazon Photosでファイル同期すると、ローカルファイルの時刻のうちmtime(更新日時)とatime(アクセス日時)が更新されてしまう
- Exif情報のあるファイルは良いが、Exif情報のないファイルの場合はAmazon Photoで同期した日に撮影したかのように見えて困る
- Google Photosに移行したいが、上書きされてしまったファイル情報は戻らず困っている

# Google Photosの挙動を確認

- Exif情報があれば、Exif情報のDateTimeOriginalを日時として採用するらしい
- Exif情報がなければ、mtime(更新日時)を日時として採用するらしい

# 課題

上記を踏まえると、Amazon Photosのアプリに上書きされたmtimeを参照してしまうExif情報を含まない画像が、Amazon Photosで同期した日時の写真として認識されてしまうのが問題であり、何らかの方法で撮影日時を認識させてやれば良い。

# 対策

- 全ファイルをなめて、Exif情報を含む画像ファイルは処理をパスする
- Exif情報を含まない画像の場合、
    - バックアップファイルのExif情報がないか探す
    - ローカルファイル、バックアップファイルのctime,mtime,atimeを全て読み込み、最も古い日時をもってmtimeを上書きする
        - 実際にはLinux上にあるバックアップファイルのctimeはmtimeと同じようなタイミングで更新されるため、Windows上にあるctimeを参照することが専らとなる

# コード

## Exif情報の読み込み

細かいことは、[python3のPILでexifが読み込めない時 \- Qiita](https://qiita.com/hadacchi/items/1c8994245e7d5caeba2d)を参照。

```python
def get_exiftime(path):
    '''
    Parameters
    ----------
    path : string
    
    Returns
    -------
    exiftime : datetime
    '''
    try:
        with Image.open(path) as im:
            exifdict = piexif.load(im.info['exif'])["Exif"]
            return datetime.datetime.strptime(
                        exifdict[36867].decode(),
                        '%Y:%m:%d %H:%M:%S'
            )
    except:
        # 今回はExif情報を読み込めなくても処理継続する
        return None
```

## ctime、mtimeの読み込み

わざわざリストで返却しているのは、後で連結するため

```python
def get_cmtime(path):
    '''
    Parameters
    ----------
    path : string
    
    Returns
    -------
    ctime : datetime
    mtime : datetime
    '''
    fstat = os.stat(path)
    return [datetime.datetime.fromtimestamp(fstat.st_ctime), datetime.datetime.fromtimestamp(fstat.st_mtime), ]
```

## ループ

フォルダ構造からファイル名から完全にそのままバックアップされていることを想定した処理なので注意。

```python
srv_dpath = 'サーバのディレクトリへのパス'
loc_dpath = 'ローカルディレクトリへのパス'

# ディレクトリとか非画像ファイルとかの除外は環境に合わせて実装してちょ
flist = ['ファイル名のリストだと思いネェ']

for filename in flist:
    loc_fpath = f'{loc_dpath}/{filename}'
    srv_fpath = f'{srv_dpath}/{filename}'
    loc_exiftime = get_exiftime(loc_fpath)
    if loc_exiftime is not None:
        continue
    else:
        srv_exiftime = get_exiftime(srv_fpath)
        if srv_exiftime is not None:
            # バックアップにのみExif情報を含む場合。もし自動処理するならsrv_fpathをloc_fpathにコピーすればいい。
            raise Exception('local file was changed!')
        else:
            oldesttime = sorted(get_cmtime(srv_fpath) + get_cmtime(loc_fpath))[0]
            newtime = time.mktime(oldesttime.timetuple())
            #os.utime(srv_fpath, (newtime, newtime))  # サーバも修正するのは勇気がいるので、ご利用は計画的に
            os.utime(loc_fpath, (newtime, newtime))
```
夏は特に欠かせない！デスクファン

今年も夏が近づき暑くなってきました:sunny:

この時期にPCで作業しているといつも以上にPCも熱を持ち始め、
CPUに負荷がかかってしまいます。
また、暑いと手汗でキーボードがベタベタしてきたりと
悩みも多い季節。


そこで！！

今回無印良品のUSBデスクファン（低騒音ファン）を購入しました！!
![P0qn7rjxSk2q4eU1bWZ%Wg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372857/a981b312-ec6c-66e1-7891-dc9d7ab85da2.jpeg)

色はBLACKにしました。

この製品には首振りタイプ（税込3490円）のものと固定タイプ（税込2490円）のものがあります。
また、色は白、黒、ピンクの３色あります。
風の強さは２段階の調整が可能です。

![SYFw%HAsSBad7v9ZxGChvg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372857/f3688ecf-e08f-bf32-5688-a597d651a259.jpeg)
![ZKioERAhREuH2QwAf10rYw.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372857/59fb26b4-bc66-a8eb-96b4-2fa669de4d96.jpeg)
無印さんらしい箱もとてもシンプルでこの表の扇風機のイラストを見ているだけでもなんだか涼しそうw

さて、実際に使ってみた感想を紹介しましょう！
![G4UgkzhJQRe5pmCVJwJMOg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372857/67d89219-1cd8-6d74-a163-f9bd1c9a6932.jpeg)

思いの外、静かで、きちんと風も当たるし涼しい！
キーボードに当てながら使うことでMacBookの熱も効率よく逃げそうです。
さらに手汗も抑えられました。うまく向きを調整すれば、自分の体にもあたり、
真夏のPC作業も涼しく乗り越えられそうです😊


ぜひ、デスクファン使ってみてください👍
HTMLとCSSでのフォームの基礎的な作り方

HTMLとCSSを用いて自身についてのサイトを作成しているのですが、プログラミング言語の中ではデザイン性の重要度が高く少し苦戦を強いられています。
今は書いたコードがすぐに反映される[VSCode](https://code.visualstudio.com/)のLiveServerという拡張機能を用いて、納得いくまで何度も試しています。
その中で、今回はフォームについて復習をかねて説明したいと思います。

# フォーム

 ```form.html
<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>お問い合わせフォーム</title>
    <link rel="stylesheet" href="form.css">
</head>
<body>
    <div class="form">
        <p>お名前</p>
        <input>
        <p>メールアドレス</p>
        <input>
        <p>お問い合わせ内容</p>
        <textarea></textarea><br>
    </div>
    <div class="contact-submit">
        <input type="submit" value="送信">
    </div>
</body>

```
デザイン性は置いといて、とりあえず簡単なフォームは完成しました。
ここで注意したいのは、inputは他の要素とは違って</>で閉じる必要がない点です。
いつもついクセで、閉じタグを使用してしまいそうになります。



```form.css
.form input {
    width: 300px;
    margin-bottom:10px;
    border: 1px solid;
    font-size: 18px;
}

.form textarea {
    height: 100px;
    width: 300px;
    margin-bottom:10px;
    border: 1px solid;
    font-size: 18px;
}

.contact-submit input {
    width: 150px;
    text-align: center;
}
```

CSSの方では、inputの大きさ、textareaの大きさ、送信ボタンの大きさを調節しました。
この数値は、個人的に一番しっくりきた大きさです。


# まとめ
今回はtypeを使用せずに書きましたが、日時などはtypeを用いた方が圧倒的に便利なので勉強していきたいです。
フォームは、どれくらいの長さの文章が送られてくるかやサイトによってベストな大きさは変わるので、すぐにサイトに合ったベストな大きさを見つけられるようになりたいですね。
Safariのキャッシュ対策にFirefox Focusが便利な件

## Firefox Focusがモバイル向けWebサイト開発に便利な件
モバイル向けWebサービスを開発しているときに、動作確認するときにキャッシュやローカルストレージの情報をクリアしたい時があると思います。
Safariの場合「設定」アプリからデータ消去が可能ですが、他のサイトのログイン情報が消えたりするので不便です。

そこで私が利用しているのが「Firefox Focus」アプリです。元々はプライバシー保護のためのブラウザアプリですが、キャッシュがローカルストレージが完全に消えるので動作確認に重宝しています。
ぜひお試しください。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
連想配列を複数キーでソートする関数を作る関数

入力によってソート基準が変わるような状況があったので探してもすぐ出てこなかったので作ってみた。
（ググり力が足りないのかもしれない）

``` javascript
 
 /*
  * keys: ソートキーの配列
  * order:  1:asc -1:desc
  */
 
 const genSortFunc = ( keys, order = 1 ) => (a, b) => {
   return keys 
     .map( key => {
     if (a[key] == b[key]) return 0
     
     return order * ( a[key] > b[key] ? 1 : -1 )
   })
   .find( o => o != 0) || 0
 }
 
 
 const array = [
   {name: 'a', key1: 1, key2: 1, key3: 1},
   {name: 'b', key1: 0, key2: 1, key3: 0},
   {name: 'c', key1: 1, key2: 0, key3: 0},
 ]
 
 console.log( array.sort(genSortFunc(['key1','key2'])))
 console.log( array.sort(genSortFunc(['key2','key3'])))
 console.log( array.sort(genSortFunc(['key1','key2'], -1)))

```


map.findしなくても、forEachで0(等価）以外が出たところで落としたほうが速いかも。
virtualenv環境構築に伴うエラー：dyld: Library not loaded: @executable_path/../.Pythonやpathの問題

#Pythonの環境構築でのエラー
プロジェクトでpythonを用いた環境構築をする必要があった。
github上のrepositoryをクローンして、指定のINSTALL.mdにしたがってインストールを進めていった。
そこで、`virtualenv`をインストールする必要が出てきた。
こうすべきだったという点や、異なる点があればご教示いただけますと幸いです。

##前提
- [ドキュメント](https://swapps.com/blog/how-to-configure-virtualenvwrapper-with-python3-in-osx-mojave/)の手順通りに`virtualenv`,`virtualenvwrapper`をインストールした。
- pyenvを過去にインストールしていた。
- パッケージマネジャはpipでvirtualenvを仮想環境構築に用いたい。

##開発環境
- macOS Mojave ver10.14.5
- zsh
- pip

##エラー①
```zsh
$ python3
dyld: Library not loaded: @executable_path/../.Python
Referenced from: /Users/name/.pyenv/versions/3.7.3/bin/./python3.7
Reason: image not found

$ which python
/Users/name/.pyenv/shims/python
```
##原因
よくわからず。あまり理解していない状態で`virtualenv`,`virtualenvwrapper`を導入してしまったことによるかもしれない。

##対策
pyenvを削除し、pythonの再インストールを。
ただ、これによりpythonがグローバルに再インストールされてしまいvirtualenvのpathと紐づかなくなってしまった。

```zsh
$ which python
/Users/name/.pyenv/shims/python

$ rm -rf /Users/name/.pyenv
$ brew uninstall pyenv
$ brew reinstall python
  ~Python has been installed as
  /usr/local/bin/python3
$ which python
/usr/bin/python
```
##エラー②
virtualenv下でのpathが変わらず。
[ドキュメント通り](https://swapps.com/blog/how-to-configure-virtualenvwrapper-with-python3-in-osx-mojave/)に再度やってみた。

```zsh
$ cd virtualenv_project
$ which python
/usr/bin/python
$ which pip
/Users/name/.virtualenvs/virtualenv_project/bin/pip
```
しかし変わらず。
##対策
そこでzshrcにvirtualenv下でのpathを追記した。

```vim:.zshrc
+ export VIRTUALENVWRAPPER_PYTHON=/usr/local/opt/python/bin/python3.7
```

すると

```zsh
$ cd home
$ which python
/usr/bin/python
$cd virtualenv_project
$ which python
/Users/name/.virtualenvs/virtualenv_project/bin/python
```
##反省

- まずは核となるドキュメントを参考にすること。
- エラー文をよく読むこと。
- いらないものは整理した方がいい場合が多い。(pyenvとvirtualenvのどっちを使うのか)
- ドキュメントにインストールするものが書いてあっても、鵜呑みにせずにまず中身を調べてどのような働きをするのかを理解した上でインストールする。またアンインストールも然り。

##参考文献
[How to configure virtualenvwrapper with python3 in OSX Mojave](https://swapps.com/blog/how-to-configure-virtualenvwrapper-with-python3-in-osx-mojave/)
2019年夏編コンテナランタイムの年表

Dockerのバージョンによってコンテナ実行中に動くプロセスが違うのなんなんだろうと思って[コンテナランタイムについて色々調べた](https://www.kaitoy.xyz/2019/06/15/k8s-ecosystem-container-runtimes/)ら、意外と広い世界が広がっていて面白かったので年表にした。
![cr-chronicle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110166/1a351ec7-6b40-6698-0be3-39464b6f1a1a.png)

しかしこういう時ロゴ無いの困る。
CRI…
Nowで簡単デプロイ

# 概要
サーバレスデプロイメントプラットフォームのNowによるデプロイの自動化方法を紹介します。

# [Now](https://zeit.co/now)について
使用するNowのバージョンはv2です。

## 導入
### npm
```shell
$ npm install -g now
```

### yarn
```shell
$ yarn global add now
```

### ログイン
```shell
$ now login
```

# CLIによる手動デプロイ
[now.json](https://zeit.co/docs/v2/deployments/configuration)を作成し、`now`コマンドを実行するとデプロイできます。

## Next.jsアプリにおけるnow.jsonの例
```json:now.json
{
    "version": 2,
    "name": "example-app",
    "builds": [{
        "src": "next.config.js",
        "use": "@now/next"
    }],
    "routes": [{
        "src": "/(.*)",
        "dest": "/$1"
    }]
}
```

## デプロイ
```shell
$ now
```

## 本番環境に向けてデプロイする場合
now.jsonのaliasに本番環境で使用するドメインを記述することができます。
https://zeit.co/docs/v2/domains-and-aliases/aliasing-a-deployment

```json:now.json
{
  "version": 2,
  "alias": "example-domain.com"
}
```

aliasで指定したURLにデプロイする場合は以下のコマンドを実行します。

```shell
$ now --target production
```

aliasをコマンドで直接指定してデプロイすることもできます。

```shell
$ now alias https://get-started-hwbbrak5g.now.sh example-domain.com
```

ドメインはNowのダッシュボードで購入できます。

# GitHub連携で自動デプロイ
NowのダッシュボードのGitHub Integrationから連携することができます。
<img width="874" alt="スクリーンショット 2019-06-18 23.17.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217930/ea8168a2-9be6-288b-b9cc-5321a280c8a0.png">

連携すると、連携したレポジトリのmasterへのコミットを本番環境へ自動的にデプロイしてくれるようになります。
また、他のコミットでもデプロイが行われユニークなURLが割り当てられます。
URLを共有して、コミットごとの開発状況を簡単に共有することができるのが便利だと感じました。
これらの機能の有効/無効化の設定などもnow.jsonに記述できます。
https://zeit.co/docs/v2/deployments/configuration/?query=autoalias#github.enabled

# AzurePipelinesでデプロイ
Nowは上述したようにGitHub連携の自動デプロイが強力なので、単にデプロイ自動化の用途でなら必要はほぼほぼありませんが、テストを実行してからデプロイしたい場合などはCIツールを利用すると良さそうです。
今回はAzurePipelinesを利用してみました。
AzurePipelinesでは設定をazure-pipelines.ymlに記述します。
Next.js + テストツールはJestの想定です。

```yaml:azure-pipelines.yml
trigger:
- master

variables:
  CI: true

jobs:
- job: Ubuntu
  pool:
    vmImage: 'ubuntu-latest'

  steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '10.x'
    displayName: 'Install Node.js'

  - script: |
      npm install
    displayName: 'npm install'
  - script: |
      npm run test
    displayName: 'exec test'
  - script: |
      npm run build
    displayName: 'exec build'
  - script: |
      npm install --global now
      now --target production --token xxxxxxxxxxx
    displayName: 'exec deploy'
```

非対話モードでJestを実行するために、環境変数CI=trueを設定しています。
Nowにログインしていない状態なのでデプロイするにはtokenが必要です。
tokenはダッシュボードで作成できます。
<img width="1023" alt="スクリーンショット 2019-06-18 23.38.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217930/c830cb61-ff1e-c364-95a2-e87764f823f6.png">
これでmasterにcommitした時、自動でテストが実行されて、本番環境にデプロイされるようになりました。
競プロ参戦記 #51 Successive Subtraction | diverta 2019 2

ARC 相当の企業主催コンテストです。B/C で詰まってしまい、ぎりぎり滑り込んでのC完でした。

## diverta 2019 Programming Contest 2

- この連載記事では、着手した問題の考察を自分なりに書いていきます。
    - 前回: [競プロ参戦記 #50 Sum Equals Xor | ABC 129 - Qiita](https://qiita.com/vain0x/items/e74a23d5c62711f95ea0)
- 問題の詳細は問題一覧を参照してください。
    - 問題一覧: https://atcoder.jp/contests/diverta2019-2/tasks

## A - Ball Distribution

問題概要: N 個のボールを K 人に配る。どの人にも少なくとも1個のボールを配る。最も多くのボールが配られた人と、最も少ない数のボールが配られた人の、配られたボールの個数の差の最大値を求めよ。

### A: 考察

K=1 なら、「最も多くの」と「最も少ない数の」が同じ人になるので、「配られたボールの個数の差」は 0 です。

K≥2 なら、すべての人にボールを1個ずつ配った後、残りを1人に押し付けるのがベストです。このとき個数の差は、1個ずつ配ったボールを除くボールの個数なので、N-K です。

筆者の回答 (Rust, AC): https://atcoder.jp/contests/diverta2019-2/submissions/5925143

## B - Picking Up

問題概要: 2次元平面上に N 個のボール (点) がある。以下の操作を行うとき、コストの最小値を求めよ。

操作:

- 2つの整数 p, q を好きに選ぶ。ただし p = q = 0 はダメ。
- 回収されていないボール (x, y) を1つ選んで回収する。直前に座標 (x-p, y-q) のボールを回収していたのでなければ、コストが1増える。すべてのボールが回収されるまで繰り返す。

制約:

- 1≤N≤50

### B: 考察

(p, q) をどう決めるか、(p, q) を決めたときの最小コストをどう計算するか、という2つの問題があります。

後者から考えます。コストのルールは、以下のように言い換えられます。

- ボールを回収するたび、コストが1増える
- ボール (x, y) を回収した直後に (x+p, y+q) のボールを回収するたび、コストが1減る

適切な順番でボールを回収するとコストを最小化できます。端のボールから順番に回収すればコストの減少を取り漏らすことはありません。

したがって、ボールを座標でソートして、端から順番に回収し、コストが減少するボールが見つかればそちらを優先して回収する、という手続きで最小のコストを計算できます。

残るは (p, q) をどう選ぶかです。(x, y) と (x+p, y+q) のような位置関係のボールのペアが存在するときのみ、(p, q) は候補になります。というのも、そうでなければコストの減少が全く起こらないので、最小コストは明らかに N-1 だからです。

候補であるボールのペアの差は O(N^2) 通りありますが、N が小さいので、全通り試せます。

筆者の回答 (Rust, AC): https://atcoder.jp/contests/diverta2019-2/submissions/5936352

## C - Successive Subtraction

問題概要: 長さ N の整数列 A が与えられる。以下の操作を N-1 回行った後、残る唯一の要素の値の最大値を求めよ。また、その最大値を得るための操作手順の一例をあげよ。

操作: 数列から2つの要素 x, y を取り除き、数列に末尾に要素 (x-y) を加える

制約: 2≤N≤ 10^5, |A(i)|≤10^4

### C: 考察

大混乱になりました。

誤った考察の例としては `(数列の最大値) - (残りの最小値)` で最大化できる (できない) とか、少なくとも半分の要素は最終的にマイナスになる (ならない) といった勘違いをしましたが……そのあたりはスルーして考察を整理します。

はじめに気づくのは、最終的な値は Σ±A(i) のような式で表せることです。例えば A = [2, 3, 5, 7] のとき、最後の要素の式は以下のようなものがありえます。

- (2-3)-(5-7)
- 2-(3-(5-7))
- 5-(7-(3-2))

いずれにせよ展開すると ±2±3±5±7 です。

そのため、最後の要素として「引き算の入れ子になった式」の代わりに「最終的に各 A(i) につく符号」を考えてよいです。

符号の組み合わせとしてどんなものがあるか考えます。直観的に「すべてプラス」と「すべてマイナス」はなさそうです。念のため、これを詳しく確認しましょう。N≥2 なので、最後の要素は A(i) を葉とするツリーで表せます。

```
    (2 - (5 - 3)) - 7

         (-)
        /   \
     (-)     7
     / \
    2  (-)
      /   \
     5     3
```

左端の葉ノード (上の例では 2) は最終的にプラスです。一方で、根ノードの右の子ノードの左端の葉ノード (7) は最終的にマイナスです。したがって、「すべてプラス」「すべてマイナス」はありません。

逆に他のパターンはすべて存在します。後述の手順で構築できるからです。

結局、最大値は「負の要素になるべくマイナスをつける (すべてマイナスにはしない)」という戦略で決定できます。

### C: 構築

次に構築です。

操作で x, y を取り除くとき、x, y の最後の符号を最初に決めた通りに (例えば、x にプラス、y にマイナスをつくように) 達成するには、どうすればいいでしょうか。そのためには、最後の要素の式を展開したときに x-y の符号がプラスになるか、y-x の符号がマイナスになることが条件です。

これは「最後の要素の式を展開したときにつく符号」(以下、最後の符号)を要素だけでなく、操作で作った式についても考えられるということです。

そこで、「最後の符号がプラスになる要素」の集合と「最後の符号がマイナスになる要素」の集合を用意します。この2つの集合から要素を取り出して x-y か y-x を作って片方の集合に入れる、という操作を繰り返すと、集合がだんだん小さくなるので、問題が解けそうです。

注意点は構築が正しく完了するかどうかです。「最後の符号がマイナス」の要素がなくなった時点で「最後の符号がプラス」の要素がちょうど1つならOK、そうでなければ失敗になります。x-y と y-x のどちらを作るか選ぶ際に、要素数が少ない方の集合に入れられる要素を作る (同じならプラス側の集合に入れる) ことにすればよいです。

こうして構築ができました。

筆者の回答 (Rust, AC): https://atcoder.jp/contests/diverta2019-2/submissions/5933935
【GitHub】コードレビューツールのPull Pandaを一部触ってみた

# はじめに
Microsoft傘下のGitHubがPull Pandaを買収したことで無償利用できるようになったという記事を読んで、実際にインストールして試してみました。:edit-request:
[Pull Panda is joining GitHub!](https://pullpanda.com/github)

# Pull Pandaとは
[Pull Panda](https://pullpanda.com/)とはコードレビューワークフローを効率化するためのツールで主に下記3つの機能があります。

- Pull Reminders
レビュー要求を通知するツール

- Pull Analytics
コントリビューター情報やプルリク情報を可視化するツール

- Pull Assigner
コードのレビュー割り当てを自動化するツール

<img width="1103" alt="スクリーンショット 2019-06-18 22.46.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/8314bced-fc14-9ba1-57d8-0aac47a7240b.png">

# 触ってみた
※Pull AssignerはGit Hubでteamsを作成する必要があり試せていないです。

こちらから[ログイン](https://pullpanda.com/pricing)してGitHubやslackの連携をします。
**※Personal accountsはサポートされておらず、organization accountsのみでした。**

### Pull Analytics

#### PRのサマリ情報
<img width="876" alt="スクリーンショット 2019-06-18 22.52.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/de97d7e5-543b-5c32-2299-2296a91ca8f7.png">

#### OPENになっているPR一覧
<img width="874" alt="スクリーンショット 2019-06-18 22.52.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/b10c0df7-e768-6b81-7b1e-1fc0a40c4770.png">

#### OPENになっている古いPRとマージまで時間の掛かったPR
<img width="884" alt="スクリーンショット 2019-06-18 22.58.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/1ceedaa3-cd49-49cf-1919-65addbb018a6.png">

## Pull Reminders
設定することでslackにリマインダーを送ることが可能です。

#### Team全体のリマインダー
スケジュールと通知する内容を設定できます。

<img width="464" alt="スクリーンショット 2019-06-18 22.54.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/edd0b507-c8f0-cd83-dac8-b462e90fea4a.png">

プルリクを作成した際の通知です。
<img width="592" alt="スクリーンショット 2019-06-18 22.35.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/be82d8e3-c3b8-2d3d-af70-bd3b00015a36.png">


#### 個別のリマインダー
こちらはslackでDMが届くようになります。
<img width="655" alt="スクリーンショット 2019-06-18 22.54.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/3d7434df-35d2-4edd-f6f4-c70af3485a20.png">

# 感想
リマインダー機能に関しては便利だと感じました。

ただ、Analyticsに関しては自分はそこまで使用しないと思います。
作成したプルリクやアサインされているプルリクに関してはGit Hubのほうが分かりやすかったです。
<img width="950" alt="スクリーンショット 2019-06-18 23.27.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/1403e2c7-02b1-1039-8c9b-c69edc089add.png">

Microsoftが買収してからGitHubのプライベートリポジトリ無料やSponsors機能できたりどんどん便利になっているので、とても楽しいです:qiitan:
find, xargs, grepコマンドで検索　備忘メモ

# 実行コマンド

```terminal
$ find ファイルパス -type f | xargs grep -n '検索したい文字列'
```

- ファイル内の対象の文字列を検索
- ヒットしたファイルのみ出力

## コマンド解説
- **find**
    - ファイルやディレクトリを検索するコマンド
    - 参考：https://eng-entrance.com/linux-command-find


- **-type f**
    - 検索対象をファイルのみに限定して検索するオプション
    - 参考：https://eng-entrance.com/linux-command-find#-type_f


- **xargs**
    - 「xargs」は、「標準入力やファイルからリストを読み込み、コマンドラインを作成して実行する」というコマンド
    - 例えばあるコマンドの出力をパイプでxargsコマンドに送り込み、別のコマンドの引数として指定するといった使い方ができる
    - 例：xargs [オプション] コマンド [コマンドの引数]
    - 参考：https://www.atmarkit.co.jp/ait/articles/1801/19/news014.html


- **grep**
    - ファイル内の文字を検索するコマンド
    - 参考：https://eng-entrance.com/linux-command-grep


- **-n**
    - 検索結果に行番号を表示するオプション
    - 参考：https://eng-entrance.com/linux-command-grep#-n


## 出力結果

```terminal
$ find . -type f | xargs grep -n 'hoge'
./xxx/yyy/zzz/sample.php:100:        public function hoge()
・
・
・
```

- 上記のように出力される
【メモ】django-csvimport




読み込むことが可能なcsv。一番最後に,をつけないと生合成が取れない謎。完全にバグ

```
"住所CD","都道府県CD","市区町村CD","町域CD","郵便番号","事業所フラグ","廃止フラグ","都道府県","都道府県カナ","市区町村","市区町村カナ","町域","町域カナ","町域補足","京都通り名","字丁目","字丁目カナ","補足","事業所名","事業所名カナ","事業所住所","新住所CD"
60000000,1,1101,11010000,"060-0000",0,0,"北海道","ホッカイドウ","札幌市中央区","サッポロシチュウオウク",,"　","（該当なし）",,,,,,,,,
60840600,1,1101,11010000,"060-8406",1,0,"北海道","ホッカイドウ","札幌市中央区","サッポロシチュウオウク",,"　","（該当なし）",,,,,"北海道テレビ放送　株式会社","ホツカイドウテレビホウソウ　カブシキカイシヤ","北１条西１丁目６番地",,

```

準備

```
>>>  pip install django-csvimport
...
...  INSTALLED_APPS = (
...  ...
...  'csvimport.app.CSVImportConf',  # use AppConfig for django >=1.7 csvimport >=2.2
...  )
```

```
pip install messytables 
```
```
pip uninstall python-magic
pip install python-magic-bin==0.4.14
```
```
html5lib
も古いとエラーが出る。
undefined _baseと出て、正しくはbaseになるらしいけど。
ライブラリは修正したくないしな。
```


```
>>> makemigrations your_app
>>> migrate

```
カスタムボタンを作る

画像を使ったカスタムボタンを作成してみたので、手順を残したいと思います。

```swift:ContactsTableViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()
         
    let inviteButton =  UIBarButtonItem(image: UIImage(named: "invite"), style: .plain, target: self, action: #selector(self.inviteButtonPressed))
            
    let searchButton = UIBarButtonItem(image: UIImage(named: "nearMe"), style: .plain, target: self, action: #selector(self.searchNearByButtonPressed))
            
    self.navigationItem.rightBarButtonItems = [inviteButton, searchButton]
}

```

UIBarButtonItemクラスを作成し、`UIImage(named: "invite")`でボタンの画像を指定しています。
画像の名前を指定して下さい。
`#selector`でタップしたときの処理を記載しています。

`navigationItem.rightBarButtonItems = [inviteButton, searchButton]`でどこに配置するかを定義しています。
今回は`navigationItem.rightBarButtonItems`なので、右上の方に表示させています。
さらに、`[inviteButton, searchButton]`でinviteButtonから右に配置しています。

見て把握できるのがいいですね。
配列のボタンは画面の右から配置されることだけ注意が必要です。

####参照
[【iPhoneアプリ開発】UINavigationBarに複数のUIBarButtonItemを配置する方法
](https://akio0911.net/archives/27557)
AWS Summit 2019 Tokyo （6/14 基調講演）


聴きながらとったメモ

登壇者：アマゾン ヴァイス・プレジデント・テクノロジー Marco Argenti

### マイクロアーキテクチャとコンテナ

* モノリシックな設計では、一部を止めると全体に影響する。
* マイクロサービスでは影響が全体に波及しない設計にできる。
* AWSのサーバーにはインスタンスとコンテナがある。
* コンテナで一番簡単に使えるのはECS。
* コンテナを動かすインスタンスをAWS側で管理する仕組みがFargate。
* コンテナを動かすもう一つの仕組みはEKS（Elastic Container Service for kubernetes）

### サーバーレスアーキテクチャとLambda（ラムダ）

* サーバーレス(サーバーの管理を完全に忘れる)という考え方のパイオニアはアマゾン。
* Lambdaはモニタリング、ロギング等も提供している。その上にユーザーはアプリケーションを構築できる。
* サーバーインフラに全く注意を向ける必要がない。
* コカコーラでは、AWSのLmandaを使って自動販売機を新しいものにした。
* サーバーの管理には以下が必要
	* 一貫したコミュニケーション管理
	* 完全な可視性
	* 障害分離と保護
* AWS App Meshを使うと、障害がどこで起こっているかをすぐに発見することができ、ネットワークの制御ができる。


### クラウド・データレイクとデータベースサービス

* データとは保存するだけのものではなく、みなさんのビジネスにとっての知能である。
* ネットフリックスではフルテーブルスキャンで32分かかっていた処理を3分に短縮した（昨日の講演でパラレルクエリ使ってるって話だった）。
* 大量の関係性のあるデータベースを扱うのに向いているのはAmazon Naptune。
* 時系列データの扱いに向いているのはAmazon TimeStream。
* マイクロ秒単位の遅延しかないElasticCache。
* 高速なキーバリューデータベースが必要な場合はDynamoDBが最適。マルチリージョン、マルチマスタで、ミリセカンド遅延のデータベース。
* DynamoDBはどんな規模でも信頼できるパフォーマンスを発揮する。
* フォートナイトというゲームではDynamoDBで1分あたり1億2500万以上のイベントを処理している。
* 大量のデータを保存した状態を「データレイク（データの湖）」と呼んでいる。
* S3にデータを保存すると、そこからアマゾンのデータ分析サービスを活用できる。
* レイクフォーメーションによって、データレイクから分析まで、ユーザーからの可視性を担保する。
* アマゾンではデータ保存だけでなく分析サービスも提供している。
	* Amazon Kinesis
	* Amazon Athena：非構造化データにクエリを走らせて分析することができる。Spark Hadoop等とも連携ができる。
	* Amazon Quick Sightによってデータの可視化が簡単にできる。
	* Amazon Redshiftによって簡単にコスト効果高くデータ分析ができる。大規模データベースをまたいだ複雑なクエリが可能。
* 数十億のエッジデバイスからデータが集まってきている。
* 2025年には750億のデバイスがネットに繋がる。
* AWS IoTは最も完全なIoTプラットフォーム。AWS IoTではサーバーサイドからエッジデバイスまで一貫して環境を用意している。
* AWS IoTを使ってアレクサと連携する仕組みを構築している。
* トラクターメーカーのヤンマーはトラクターをAWS IoTに接続し、収穫量予想サービスを提供している。
* 自動車メーカーのフォルクスワーゲンでは、122以上の製造工場をAWS IoTを使ってネットワークに接続し、製造工程の解析を行なっている。
* AWS IoTにより土壌の状態管理を行なっている企業もある。
* 電力会社エネルでは、エネルギーの利用状況を解析し、エネルギーの節約を実現している。

### AI・機械学習について

* アマゾンにおいて機械学習は長い歴史を持つ（本の推薦、在庫管理など）
* 機械学習への取り組みはAWS上で行われることが最も多い。
* スマートニュースは記事分析にAmazon SageMakerを使っている。
* アマゾンの機械学習サービスには「サーバーインフラ・フレームワーク提供」「機械学習提供」「AI提供」の３つがある。
* フレームワークとして、TensorFlow、mxnet、PyTorch、GLUON、Kerasを提供している。
* 機械学習の運用コストの大半は推論においてかかっている。
* Elastic Inferentiaが今年後半に提供される。推論のコストを1/10にすることができるチップ。
* Amazon SageMakerを使うと推論も実行できる。推論コストを75%まで削減できる。
* AIの提供では、あらかじめ決まった機能を提供するもの（文章解析、画像解析、商品レコメンドなど）。


#### 登壇者：メルカリ最高技術責任者 名村 卓

* メルカリではAWSもAI・マシンラーニングを使っている。
* ユーザーの撮影した写真から、それに近い商品を検索する仕組みにAIを用いている。
* EKSのコンテナでAIのトレーニングを行なっている。
* S3の高い可用性、充実したイベントフック、充実したツール群とエコシステムがあるためよく使っている。
* 出品者が商品の社員を登録した時点でAIがその商品名等を予測して自動的に入力してくれるシステム。
* splunkというプラットフォームをAWS上で動かして、さらにLambdaやFargateとも強調するシステムを構築している。
* データのリアルタイム処理にKinesisを使っている。

#### 登壇者：パナソニック 㹧䃵 猧䒽

* vierukaは来客分析において、エッジデバイス側で画像のAI処理を行っている。
* エッジ側で不具合があっても駆けつけの必要がないので出張費ゼロ円。
* 稼働しながら機能追加していける。
* エンドユーザーの現場で発生するデータを収集することで、エンドユーザーに必要な機能が提供できる。

#### 登壇者：シンセティックゲシュタルトCEO　島田 幸輝

* 「人工知能により科学研究を自動化し、天才に依存せずに科学研究の成果を社会に提供する」企業。
* ひとつの医薬品を開発するのに2000億円以上のコストと10年以上の時間がかかっている。
* 人工知能により装薬。ロボットによる実験によって創薬にかかるコストと時間を節約する。
* SageMakerの分散処理によって仮説検証プロセスにかかる時間が1/10になって。
* 解析速度は518万倍
* 理論から分子設計するのではなく、総当たりで最も良い分子設計を発見するというアプローチ。
* 仮説検証の速度と精度が上がる。
* 開発者は、どうやって設計するか、から、どうやって人工知能に問題を解かせるか、というほうにマインドチェンジした。
AWS Summit Tokyo 2019 （6/14 Amazon DynamoDB Deep Dive）


聴きながらとったメモ

登壇者　アマゾンソリューションアーキテクト 成田 俊

* アマゾンで買い物をするサイトはバックエンドにDynamoDBを使用している。
* 高速で一貫した性能。
* 99.999%のSLA。
* DynamoDBはテーブルでデータを分割し、アイテムとしてデータを保存する。
* 各アイテムはアトリビュート（列）を持っているが、データごとにアトリビュートが違っていてもいい。
* ソートキーはオプションだが、ソートキーをつけることで幅広い検索ができる（範囲検索とか）。
* パーティションキーとソートキーを指定してGet/Put/Update/Deleteする
* DynamnoDBでACIDトランザクションが可能になった。これによって複数の処理が全て成功するか全て失敗するか、という設計ができるようになった。
* 内部ではパーティションキーを元にItemの保存位置が決まり、スケールのためにパーテーションという単位で分散保存している。
* パーテーションは３つのコピーを持つことで冗長性を確保している。
* パーティションキーとソートキーだけで検索できない場合はセカンダリインデックスを使う。
* LocalSecondaryIndexは同じパーティションキーでの検索に使う。
* GlobalSecondaryIndexはパーティションキーをまたいで検索できる。
* クライアントがテーブルに対して更新処理を行うと、GlobalIndex用のテーブルに対して非同期に更新を行う。
* バーストキャパシティによって、過去300秒分で使わなかったキャパシティを使用してバーストできる。
* オートスケーリングできる。
* アクセスされるキーに偏りがあると負荷が偏るため、パーティションキーの設計時には書くパーティションに分散されるように考慮する必要がある。
* あるパーティションに負荷が偏った場合に、Adaptive Capacity機能によって、他のパーティションのキャパシティを負荷がかかっているパーティションにもってこれる。
* オンデマンドによってサーバー料金ではなく、リクエストに対して課金できる。
* オンデマンドとインスタンスは運用中に設定変更で変更できる。
* Scale fearlessly with amazon dynamo db adaptive... というセッションが参考になる。
* 「サーバーレスアプリケーション向けのDB 設計ベストプラクティス」
* NoSQLは正規化しすぎると効率が落ちることがある。非正規化し、データは多少重複していてもアプリから操作しやすい構造にする。
* N:MリレーションではtableとGSIによって双方向の関係性を保存する。
* GSI OVERLOADINGにより、セカンダリインデックスの数の制約を超えた設計が可能になる。
MAツールの黒船、Amazon Pinpointの凄さを語る

# 記事の目的

AWS主催のAmazon Pinpointセミナーを受講。結果、既存のMAツールを終わらせる可能性があるなと実感。
そのため、本記事では以下について述べてみる。

**1. Martechの目指す場所**
**2. マーケティングの課題と未来**
**3. Amazon Pinpointとは？**
**4. Amazon Pinpointの概念**
**5. 活用事例、他サービスとの連携**
**6. Pinpoint & Personalizeの可能性**

# Martechの目指す場所
Martechとはmarketing x technologyを組み合わせた略語。
ただ、目指すべきゴールは昔と変わらずOne To Oneマーケティングの実現で、
一人一人に最適なマーケティングだと思っている。

# マーケティングの課題と未来
One To Oneマーケティングを人手で実行すると工数・人件費がえぐいため、
実行してる企業は少ないはず。この課題を解消するために、Martechがブームに
なりつつあるのかなと。

Martechがどこに向かうか、以下の２つが予測として挙げられる。

## エンドポイント同士の連結：
ユーザのタッチポイント（GoogleやFacebook、Lineなど）は750億にのぼる。
今後の動きとして、2025年までのタッチポイント同士の相互接続マーケティングが
実現されると予測されている。

例えば、Twitterで新商品の認知を行ったユーザが、Facebookで承認に
興味・関心を持つような広告が配信されるパターンである。
つまり、マーケティングチャネル同士が連結されユーザに
最適なチャネルが構築されていく。

そのため、媒体や広告メニューごとに担当者がアサインされることが
非効率であり、カスタマージャーニーが俯瞰できる担当者と、
効果を可視化できる分析基盤が必要となっていくだろう。

## パーソナライズの推進：
ある調査によると、84%のユーザは自分自身を個人としてのコミュニケーションを
望んでいたが、実現できていると考えているマーケットリーダーは51%に
とどまるらしい。

これは、ユーザ毎にチャネルやメッセージのパーソナライズが不足していると
考えていることがうかがえる。ユーザ毎に最適なメッセージを送ることはもちろん、
ユーザが欲しいタイミングでコミュニケーションしてほしいと考えているのだ。

最終的には、ユーザ毎に最適なページ・UIも変えていくことが求められる
かもしれない。ユーザ毎にパーソナライズが進むことは止められない流れだろう。

# Amazon Pinpointとは？
マーケティングの成功に不可欠な要素は以下と考えられている。
　・ユーザ毎に最適化されたメッセージ
　・チャネルをまたいだ自然で連続した顧客体験

これには膨大な実験が必要だろう。すなわち、「いつ」「誰に」
「どんなメッセージ」を送り、「結果」を知ることが必要だ。
この課題を解決するのがAmazon Pinpointだ。

Amazon Pinpointのサービスで以下のことが可能となる。
　・モバイルプッシュ、SMS、Eメールなど複数チャネルを
　　経由したコミュニケーション
　・ユーザのターゲティング、セグメンテーション
　・通知を行った後の行動解析やダッシュボードによる可視化

公式ドキュメントは以下にある。
https://aws.amazon.com/jp/pinpoint/

# Amazon Pinpointの概念
Amazon Pinpointには３つの概念が存在する。

## 1.チャンネル：
配信プラットフォームのことを指し、以下の4つが用意されている。
　・プッシュ通知
　・SMS
　・メール
　・ボイス（現在、日本対象外）

上記に加え、カスタムチャネルを構築することができる。
これは、Lambda Fucntionと連携することで、Pinpointで配信リクエストが
あると、配信先などの情報がLambda Functionに渡され、自由な配信が可能となる。
例えば、実行対話的なチャットボットも構築可能なのだ。

## 2.セグメント
チャネルを配信するターゲットのこと。
Pinpointで事前に定義された基本セグメントが用意されており、
すぐに配信が可能となっている。

また、ユーザとカスタム属性を組み合わせたインポート機能も
存在する。セグメントファイル（CSV、json）を作成したのちに、
S3へアップロードすれば、任意のターゲティングが可能だ。

※ セグメントファイルで指定可能な属性は以下を参照してほしい。
　https://docs.aws.amazon.com/ja_jp/pinpoint/latest/userguide/segments-importing.html#segments-importing-available-attributes


## 3.キャンペーン：
ターゲットとチャンネルに対して、「いつ」どんな「メッセージ」を
送るかを決定する。Amazon Pinpointは顧客アプローチの実験場所として扱うため、
以下の機能が備わっている。

### A/Bテスト
A/Bテストではメッセージまたはスケジュールの2つ以上の処理が含まれる。
複数のメッセージやタイミングを設定し、どちらの設定が効果的かを検証できる。

例えば、あるメッセージを定期的に送るのがよいのか、顧客があるアクションを
行った場合にのみ送るのが良いかを検証することができる。
また、キャンペーン内でメッセージ配信量のコントロールも可能だ。

### 分析と可視化
Amazon Pinpointにはダッシュボードが用意されており、キャンペーンに
対するメールのオープン率やアプリプッシュオープン率、最終的な収益が
いくらになったかを可視化することができる。

また、Amazon PinpointをKinesisと連携しストリーミングすることが可能だ。
これにより、S3やRedShiftにデータを出力させて、独自の分析を行うことも可能だ。

# Pinpoint & Personalizeの可能性：
アプリプッシュやメールの結果をAmazon Personalizeに組み込むことができる。
Amazon Personalizeはクラウド環境で構築できるレコメンドエンジンで、
ユーザが商品に対するアクションを送付することで、ユーザが購入しやすい
商品を返してくれるサービスだ。

個人的には、これらのサービスの掛け合わせがOne To Oneマーケティングの
近道と考えている。ユーザが反応しやすい商品を機械学習に推論させ、
限られたユーザにプッシュ通知することが可能となる。

これにより、無駄なユーザへの配信を防ぎ、有望なユーザにのみ配信が可能だ。
個人的にはアップリフトモデルを搭載したSageMakerと連携して配信最適化が
進むのではないかと考えている。

# 最後に
マーケティングがITと連携し、高度にデジタル化していくことは避けられない。
また、AIと組み合わせたパーソナライズも今後は起こっていく流れであると
考えられる。

マーケターとエンジニアが、仲良く手を取り最適な顧客体験を作っていくことに
なるだろう。
AWS Summit Tokyo 2019（6/14 Kubernetes on AWS）


聴きながらとったメモ

登壇者：AWS ソリューションアーキテクト 河野慎吾

### コンテナ

* コンテナとはOS内の独立した環境で実行する技術（コンテナ ~= Docker）
* 依存関係をパッケージング
* Dockerにはビルド・シェア・ランの３つのフェーズがある。
* Dockerfileに全てのビルド手順を書く。
* 出来上がったイメージをイメージレジストリに登録する。
* コンテナホストで（自分のPCやEC2上など）でDockerイメージを走らせる。
* コンテナユースケース
	* マイクロサービス
	* ジョブ実行
	* CI/CD
	* 機械学習
* RUN（コンテナ実行）フェーズでの課題。
	* コンテナホストが停止したら、その上で走ってたコンテナ全滅する。
	* スケールをどのようにするか？

### Kubernetes

* Kubernetes（k8s）はオープンソースのコンテナオーケストレーションツール。
* Kubernetesで動かせるように設計すれば、場所を変えても同様に動作する（Runs anywhare）
* Kubernetesの最小単位はPod。Podの中に関係性の深いコンテナを複数入れることがある。


### EKS

* Serviceでロードバランス等の機能を提供する。
* DeploymentでPodを配置し、ローリングアップデート等を行う。
* EKSを使うとkubernetesのコントロールプレーンをマネージドサービスとして使用できる。
* 既存のエコシステムがそのまま動く。
* Kubernetesの運用（バージョンアップ等）をAWS側でやってくれる。
* EKSのロードバランサーはElastic Loadbarancer。SSL証明書やRoute53との連携もできる。
* つまり、KubernetesマニフェストでAWSのサービスをコントロールできる。
* Podレベルとノードレベルの２種類のオートスケールがある。ノードレベルはAWSのオートスケール機能と連携。
* Podは負荷が上がると自動的に増えていくが、EC2のキャパシティ限界に達して増殖が停止する。
* その状態になるとEC2インスタンスが追加され、新しいノードでPodのオートスケールが行われる。
* Codeシリーズによりデプロイメントパイプラインを構築して運用する。
* Amazon ECRはフルマネージド型のコンテナイメージレジストリ。
* EKSからデータストアとしてAurora DynamoDB、ElastiCacheなどが使える。
* EKSWorkshopで手を動かしながら学べる。AWS BlackBeltでさらに深く学ぶことができる。
Heroku push時にcan't find gem bundler (>= 0.a) with executable bundle

##背景
Heroku push時にbundler関係でエラー発生したのでメモ。
rbenv versions:
system
  2.3.1
  2.3.7
* 2.5.0 (set by /Users/hogehoge/rails/weaver/.ruby-version)
  2.5.1

##エラー内容
```
vendor/ruby/heroku-18/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)
```
たまにこのエラー見る。bundlerインストールで解決できたようなと思いながら、ググると、、
下記の記事がヒットしました！エラー内容似てる！
https://qiita.com/sshuuu/items/213b4e82167317e1ebb3

この記事によると、Gemfile.lockに記載されているBUNDLE_WITHのバージョンがインストールされているbundlerのバージョンと異なっていることが原因とのこと。
なるほど。調べてみる。

bundler-v:
Bundler version 2.0.2

```ruby:Gemfile.lock
BUNDLED WITH
   2.0.2
```

え、、違わないんだが、、。どういうこと、、。

かなりハマりましたが、結論をいうとGemfile.lockに記載されているBUNDLE_WITHのバージョン2.0.2を手動で、1.17.3に変更。
次にバージョン1.17.3のbundlerをインストール。
あとは、下記の流れで、もう一度herokuにpushで解決できました！

```ruby:Gemfile.lock
BUNDLED WITH
   1.17.3
```
```
gem install bundler -v '1.17.3'
bundle install
git add -A
git commit -m "hoge"
git push
git push heroku master
```

Gemfile.lockは基本的に触らないものと考えていたので、手動で変更させることになかなか気がつきませんでした。
参考になれば幸いです。
AWS Summit Tokyo 2019（6/13 AIと機械学習）


聴きながらとったメモ

## Amazon SageMaker Deep Dive

* 高性能な組み込みアルゴリズムを使える。
* モデル・アルゴリズムをMarketplaceで提供
* 分散学習をサポートしており、わずからコード変更で複数クラスタで分散学習できる。
* 一度学習すれば、モデルをコンパイルすることでエッジを含めて様々な環境で利用できる。
* ワークフロー構築を助けるツールとしてSageMaker Python SDKなどがある。
* `import sagemaker.mxnet import MXNet` 等として利用する。
* `sagemaker.deploy(instance_count=1 )` のようにデプロイする。
* コンテナによる環境の統一化（SageMakerコンテナには色々すでに入れてある）
* SageMakerコンテナが立ち上がると、特定のディレクトリにS3から読み込んだトレーニングデータやテストデータが置かれる。
* Jupyter Notebookが簡単に立ち上がる。
* トレーニングの終わったモデルはS3に保存される。
* アプリでは、例えばLambdaからモデルを使うことができる。
* データ収集→クリーンアップ→データ変換。ラベルづけ→トレーニング→モデル評価→本番環境にデプロイ→推論・監視→（もどる）
* AWS Step FunctionsやApache Airflowでトレーニングからデプロイまでを自動化できる。
* 継続的なモデルのアップデートを行う。
* とにかく自動化、自動化、自動化しきれないところは半自動化。
* Step WorkdsはJSONベースでステートマシンを記述できる。
* Lambdaなどのサービスに対応。
* Cloud Watch Eventでスケジュール実行やイベント実行できる（１週間に一回、モデルを再トレーニングするとか）。
* 機械学習パイプラインを構築して、自動的にMLモデルを再学習していくことが必要。
* Apache AirFlowで同様にフローをPythonを使って記述できる。
* SageMakerは過去のトレーニングジョブを残しておいてくれるため、過去の環境情報やトレーニングに使ったデータ等も残っており、あとから検証できる。
* 再学習で課題になるのがアノテーション。
* 教師データの質が、そこからできるモデルの質を決定する。
* モデルの精度を担保するには人でのラベルづけも必要。
* 画像分類、物体検出、セマンティックセグメンテーション、文章分類の４つは、SageMakerを使うと簡単に実現できる。
* はじめは人間がラベルづけして、十分高い精度を出せるようになったら自動アノテーションを行う。
* 重要なのは、データ収集からはじまるワークフロEーを素早く構築すること。
* 推論コスト = インスタンス数
* 学習にコストがかかるイメージだが、実運用では推論にお金がかかる。
* SageMakerではプロダクション用のRestAPIが簡単に立ち上がる。
* `Estimator.deploy` を実行すると、裏ではEndpoint Configにもどついて、EndPointにモデルがデプロイされる。
* エンドポイント作成の流れ
	* Model
	* Endpoint configuration
	* Endpoint
* エンドポイントの更新は、ブルーグリーンデプロイメントが行われ、古いモデルを残したまま新しいモデルが保存される。
* デプロイのリスクを軽減する仕組み。
	* １つのエンドポイントの裏に複数のバージョンのモデルがある。
	* 最初はトラフィックの10%を新しいモデルに流し、90%を古いモデルに流しながら様子を見て、徐々に新しいモデルに流す割合を増やすことができる。
	* オートスケーリングにより、必要ない時間にはインスタンスを寝かすことでコストを削減できる。
	* 推論コストを抑えるための選択肢として、 `Batch Transform Job` `E;astoc Omferemce` `Sagemaker Neo` がある。
	* Neoを使うと、様々なフレームワークとインフラを組み合わせることができる。
AWS Summit 2019 Tokyo（6/13 Deep Dive on Amazon Aurora）


聴きながらとったメモ

## Amazon Aurora MySQL/PostgreSQLの内部構造

登壇者： Yoav Eilat

* 3AZに数百〜数千インスタンスのストレージノードを配置
* それぞれにAZに２つづつ、合計６つのデータコピーを保存。
* 10GB単位で64TBまで自動的にスケールする（データ保存領域を気にする必要がない）。
* データは６ノードに非同期・並列で書き込む。
* ４つのノードに書き込めた時点で書き込み成功とみなす。
	* ４つ未満で終わったら書き込み失敗。この場合の際書き込みはアプリ側で行う。
* ３つのノードから読み込めた時点で読み込み成功とみなす。
* DBインターフェイスからの要求は一旦Inccomming Queueに入り、そこからUpdate Queueに送られて更新処理を行う。
* 読み込み時間は本家MySQLの2.5倍、本家PostgreSQLの2倍高速
* 複数のAZに最大１５のリードレプリカを置くことができる。リードレプリカはマスターに昇格可能。
* MySQLは通常５つのステップでデータを同期する。
* Auroraが早い理由は、データストレージが各ノードで共有されているから。
	* MySQLはノードごとに独立したストレージを持つが、Auroraは各ノードのストレージが共有されている。
	* プライマリが書き込むと、変更が他のノードにすぐにいきわたる。
	* プライマリ以外は、読み込みのみ行う。
* インプット/アプトプット時間が1/8ですむ。
* 負荷状況に応じてレプリカの追加を自動的に行うAuto-scalingレプリカにできる。
* Aurora Global Databaseを使えば複数のリージョンにデータベースを分散配置できる。
* データの同期を行うのはデータベースアプリケーションではなく、ストレージレベルで行われるため早い。
	* リージョン間レプリケーションの遅延は1秒未満。
* 仮にマスターを配置したリージョンが完全に落ちても、コンソールから別のリージョンをマスターに指定すれば1分以内に復旧できる。
* Parallel Query（並列クエリ）によりクエリが高速化できる。
* MySQLのロックでは、すべての対象データがロックされてしまう。Auroraではひとつひとつの行がそれぞれ管理されており、ロックが並列に行われる。
* 通常のデータベースでは5分ごとにチェックポイントが作られ、データベースが完全にクラッシュした場合はそこから再開できるが立ち上げに時間がかかることがある。Auroraにはチェックポイントという概念がなく、復旧後の読み込み時に並列・分散・非同期にデータ復旧が行われていく。したがって非常に高速にデータベースを復旧できる。
* 通常、データベースをバックアップしてキャッシュをウォームアップするのに5分程度の時間がかかる。しかしAuroraの新機能であるCluster Cache Managementにより、ウォームアップされたキャッシュを使って起動されるため、30秒程度でトップレンジの速度での読み書きが可能になる。
* Aurora Backtrackにより、バックアップから復元せずに過去72時間のどこかの時点に数秒で戻すことができる。
* Fast Database Cloningにより、データのクローンをClone Storage上に持ち、（ここで時間切れ）
PHP　Excetionについての理解を深めるためにメモ

#はじめに
Excetionについての理解を深めるためにメモ

#例外を呼び出すとき
```php
$flag = false;
try {
	if(!$flag) {
		throw new Exception("flag is false.");
	}

} catch(Exception $e) {
	echo $e->getMessage();
}
```

###実行結果
>flag is false.


#今一度、動作の流れを確認
もう決まり文句みたいにtry-catchと例外クラスを使っているが、今一度、丁寧に流れを追ってみる

```throw new Exception("flag is false.");```

例外を発生させるためにはtryブロックで囲む必要がある。
例外が発生した場合は、Exceptionクラスのインスタンスをthrowする
throwされた例外はcatchで補足される

ここでExceptionクラスの公式を確認。

```php
public Exception::__construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )
```

Exceptionクラスのコンストラクタの第１引数でエラーメッセージをセットしているのね。

で、 ```catch(Exception $e) ```の$eは、Exceptionクラスのインスタンス


# Exceptionクラスのメソッドいろいろ
```php
$flag = false;
try {
	if(!$flag) {
		throw new Exception("flag is false.");
	}

} catch(Exception $e) {
	echo $e->getMessage().PHP_EOL;
	echo $e->getPrevious().PHP_EOL;
	echo $e->getCode().PHP_EOL;
	echo $e->getFile().PHP_EOL;
	echo $e->getLine().PHP_EOL;
	echo $e->getTraceAsString().PHP_EOL;
}
```

https://www.php.net/manual/ja/class.exception.php

#独自例外クラス
独自の例外クラスも例外クラスを継承するだけなので簡単

```php:myexception.php
class MyException extends Exception { }

$flag = false;
try {
	if(!$flag) {
		throw new MyException("flag is false.");
	}

} catch(MyException $e) {
	echo $e->getMessage().PHP_EOL;
}
```

もちろん独自の例外クラスにメソッドを作成することもできる

```php:myexception.php
class MyException extends Exception {
    public function getClass() {
        return __CLASS__;
    }
}

$flag = false;
try {
	if(!$flag) {
		throw new MyException("flag is false.");
	}

} catch(MyException $e) {
	echo $e->getMessage().PHP_EOL;
	echo $e->getClass().PHP_EOL;
}
```

###実行結果
>flag is false.
>MyException
AWS Configのオンラインセミナー受けてみた

「[AWS Black Belt Online Seminar AWS Config](https://www.slideshare.net/AmazonWebServicesJapan/20190618-aws-black-belt-online-seminar-aws-config)」の自分向けメモ
AWS Configって何？......レベルの人向け


## 構成管理の課題
 - 構成ドキュメントと実設定の整合性の担保
 - システム拡張に伴う管理工数の増大

## AWS Config概要
 - AWSリソースのインベントリ管理、構成変更サービス
    - AWSリソースの構成変更を検知し、記録の保存、過去の構成状況、依存関係の確認
 - 構成変更の記録を保存し、トレースが可能
    - ターミネートされたEC2の確認
 - リソース間の関係（リレーションシップ）も管理している
 - 双方向の依存関係を確認できる
    - 高度なクエリを利用して、特定のセキュリティグループを利用しているEC2を確認

## AWS Config Rules概要
 - AWS Configで取得した変更情報を評価できる
 - 評価してSNSで通知も可能
 - 準拠すべきルールを事前に設定し、ルールに沿った構成変更が行われているか評価する

### ルールの種類
2種類ある

#### マネージドルール
 - AWS提供のルール

#### カスタムルール
 - Lambdaベースでルールを作成可能
 - トリガータイプは任意
 - Lambda実行時にConfigからイベントパラメータがセットされる
 - Lambdaの実行結果をAWS Config Rulesに返却する

### トリガータイプ
ルール評価実行のタイミング

#### 設定変更時
 - 関連リソース作成、変更時

#### 定期的
 - 任意のタイミング
 - AWS Configがスナップショットを取るとき

### 修復アクション
 - コンプライアンス違反のリソースに対して、ルールに関連付けられた修正アクションを実行
 - SSM Automationドキュメントを使用したカスタムの修正アクションを設定
 - コンプライアンス違反の検出ログからLambadaをトリガーすることも可能

## ユースケースとベストプラクティス
### ユースケース
 - リソースに指定したタグがあるかどうか
 - EC2インスタンスがSSMで管理されているか
 - S3のパブリック読み書きが許可されていないか
 - RDSスナップショットが未公開か

#### GitHub上で公開されているコミュニティベースで作成されたルールもある
 - Lambda関数がVPCに紐づいているか
 - S3 VPC Endpointが各VPCで有効か

#### OS構成情報の管理例
 - SSMインベントリでソフトウェアの導入状況を確認
 - 導入状況をAWS Configで記録・監視
 - 違反があった場合
    - 修復アクションとしてSSM Automationを実行
    - CloudWatch Events　⇒　Lambda実行

### ベストプラクティス
20個ある

#### 記録対象
 - 全アカウントと全ンリージョンで全ての操作を記録する
 - 全リソースで設定変更を記録する
 - グローバルリソースは1リージョンで記録し、重複記録を防ぐ

#### 保存先
 - 改ざんできないように安全なS3バケットにヒストリーとスナップショットを保存する
 - 保存先のS3バケットの公開設定（マネージドルール）をチェックする

#### マルチアカウント
 - 複数アカウントの構成を管理する場合、管理用アカウントを作成、集中管理する
 - 集約ビュー機能でデータの集約が可能


## 料金
### AWS Config
 - リソースに対して記録された設計項目単位
 - 0.003USD/記録

### AWS Config Rules
 - アクティブだったルール数/月だが変更予定
 - 2019年8月1日から以下
    - 最初の100,000ルールの評価：0.001USD
    - 次の400,000ルールの評価　：0.0008USD
    - 次の500,001ルールの評価　：0.0005USD

## まとめ
 - 何に対して、誰が、いつ、何をしたかを自動で、継続的に記録し、確認することができる
MacにLaravel5.8+Postgresqlをインストールする

# 概要
MacのローカルにLaravelの開発環境を構築した手順の記録です．MacOS + Homebrewで構築しています．

# 環境
- macOS Mojave 10.14.5
- homebrew 2.1.6

# 導入したもの
- PHP 7.3.5 (Homebrew)
- composer 1.8.6 (Homebrew)
- postgresql 11.3 (Homebrew)
- Laravel 5.8.23

# 手順
## PHP,composer,postgresqlの導入

コマンドラインで次のコマンドを入力し，PHP・composer・postgresqlをインストールします．

```console
brew install php
brew install homebrew/core/composer
brew install postgresql
```

## PHPの設定
Laravelでtinkerを使う場合は

```php:~/.config/psysh/config.php
<?php
return [
    'usePcntl' => false,
];
```

を作成します．

## Postgresqlの設定
はじめに，パスを通します．

```console:~/.bash_profile
export PATH=/usr/local/Cellar/postgresql/11.3:$PATH
```

すでに他のパスがある場合は，適切な場所に挿入してください．追記後，

```console
source ~/.bash_profile
```

で，再読込します．DBをUTF-8で初期化する場合は，

```console
initdb /usr/local/var/postgres -E utf8
```

を使います．パスを通し終えたら

```console
postgres -D /usr/local/var/postgres
```

でpostgresを起動します．起動後，

```console
psql -l
```

で，データベースの一覧が表示されます．そこで，postgresに

```console
psql -U Macのユーザー名 -d postgres
```

でログインします．ログインしたら，

```
postgres=# \du
```

で，role情報を一覧表示してみます．もし，一覧にpostgresがなければ

```SQL
postgres=# CREATE USER postgres SUPERUSER; 
```

で，postgresユーザを作成します．必要ならば他のユーザも作成します．また，パスワードを付ける場合は

```SQL
CREATE USER postgres WITH PASSWORD 'password' SUPERUSER;
```

とします．あるいは，コンソールから

```console
createuser -U Macのユーザ名 -P 追加するユーザ名
```

としても作成できます．その後，Laravelで用いるデータベースを

```SQL
postgres=# CREATE DATABASE データベース名 OWNER ユーザ名
```

で作成します．


## Laravelのインストール
インストールしたcomposerを用いて，Laravelをインストールします．

```console
composer global require "laravel/installer"
```

インストール後，パスを通すため，~/.bash_profileに次を追記します．

```console:~/.bash_profile
export PATH=$PATH:$HOME/.composer/vendor/bin
```

こちらも先程と同様に再読込します．

## プロジェクトの作成
次のコマンドでLaravelプロジェクトを作成します．

```console
composer create-project --prefer-dist laravel/laravel プロジェクト名
```

作成されたら.envとconfig/database.phpをpostgres用に編集します．

```:.env
DB_CONNECTION=pgsql
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=データベース名
DB_USERNAME=ユーザ名
DB_PASSWORD=パスワード
```

```php:config/database.php
'default' => env('DB_CONNECTION', 'pgsql'),
```

編集後，Laravelを

```console
php artisan serve
```

で起動して完了です．

### 参考
- [Mac OSにLaravelローカル開発環境構築](https://qiita.com/da-sugi/items/7ee7a458aad4209bab01)
- [MacにPostgreSQLをインストール](https://qiita.com/_daisuke/items/13996621cf51f835494b)
- [php 7.3 で tinker が動かない](https://teratail.com/questions/169061)
画面回転やSplit View等により画面サイズが変更した場合にレイアウトを再計算したい

縦と横向きでレイアウトを変えたい時や、レイアウトを微調整したい時に使えます。
画面回転時やSplit View時にはviewWillLayoutSubviews()が呼ばれるので、そこにレイアウトを調整する処理を記述しましょう。

```:swift
// レイアウト開始直前に呼ばれる
// 画面回転時やSplit View適用時
override func viewWillLayoutSubviews() {
    // レイアウト調整処理を記述する
    // 例えば、View.reloadData()
}
```
【TypeScript】event.target と event.currentTargetの違いについて

# 概要

`event.target.value` を取得しようとするとTypeScriptに怒られてしまったため、event.targetについて調べ直しました。
ソース例はReact + TypeScriptで書いています。

### エラー例

```tsx

function Example() {
  const event = (event: React.KeyboardEvent<HTMLInputElement>) => {
    console.log(event.target.value); // ここで怒られる
    // プロパティ 'value' は型 'EventTarget' に存在しません。ts(2339)
  };

  return (
    <div>
      <input type="text" onKeyDown={event} />
    </div>
  );
}

```

EventTargetはElementだけではなく、window等もターゲットになりえるためエラーを吐いているようです。

[MDN | EventTarget](https://developer.mozilla.org/ja/docs/Web/API/EventTarget)

> Element および document、window は、最も一般的なイベントターゲットですが、他のオブジェクトもイベントターゲットになります。例えば、XMLHttpRequest、AudioNode、AudioContext 他。

## 解決法

### 解決法1

```tsx

const event = (event: React.KeyboardEvent<HTMLInputElement>) => {
    console.log((event.target as Element).value); 
    // キャストすることで無理やり Element とする
  };

```

キャストをして、 `event.target` を Element型とすることで無理やりエラーを消します。
エラーは消えますが、あまりいい感じはしません。

### 解決法2

```tsx

const event = (event: React.KeyboardEvent<HTMLInputElement>) => {
    console.log(event.currentTarget.value); 
    // currentTargetを使用する
  };

```

currentTargetを使用することで、エラーを消します。
しかし、currentTargetとは何でしょうか？
次はtargetとcurrentTargetの違いを見ていきます。

## targetとcurrentTargetの違い

codeSandBoxに実験例を置いています。
https://codesandbox.io/s/event-target-yzz1i

![event-taget.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327783/d00240a7-ccfb-67b9-dfd6-14b4e33ff0c2.gif)

上記では青枠をparentとしてonClickイベントをアタッチし、子要素の黄枠をchildrenとしています。

event.target と event.currentTarget の違いですが、
`target` はイベントを呼び出した要素を参照し、
`currentTarget` はイベントハンドラーをアタッチした要素を参照するようです。
そのため `target` は変化し、 `currentTarget` は変化しませんでした。

## 参考

[MDN | Event.target](https://developer.mozilla.org/ja/docs/Web/API/Event/target)
[MDN | Event.currentTarget]
(https://developer.mozilla.org/ja/docs/Web/API/Event/currentTarget)
[MDN | EventTarget](https://developer.mozilla.org/ja/docs/Web/API/EventTarget)
[stack overflow | Why is Event.target not Element in Typescript?](https://stackoverflow.com/questions/28900077/why-is-event-target-not-element-in-typescript)
PySNMPで取得したIPv6アドレスを省略表記で出力する

Python の SNMPライブラリである PySNMP で取得した IPv6アドレスは、そのままの形ですと非常に使いづらいです。
IPv6省略表記に成型出力するようにした備忘録となります。

<b>・環境</b>
Server OS: CentOS 7.5
Python Ver: 3.6.8

##取得情報の変形について
今回はPysnmpでOID`1.3.6.1.2.1.4.34.1.3.2(ipAddressIfIndex)`の情報を取得する場合を考えます。

Pysnmpで取得したIPv6アドレスに該当する個所は以下のようになります。
`22.3.5.56.4.0.0.17.0.0.0.0.0.0.0.6`
8bitずつピリオドで区切られてかつ10進数表記です。

<b>これを</b>

`1603:0538:0400:0011:0000:0000:0000:0006`
のように16bitずつコロンで区切られた16進数表記に変えたうえで


<b>`1603:538:400:11::6`</b>
最終的に省略表記にして出力します。

##Python3 コード
SNMPコミュニティ名等は任意のものをご記載下さい。

```python:ipv6_sample.py

from pysnmp.hlapi import *
import ipaddress
import sys

argvs = sys.argv

def ipv6_search(host) :

    oid = "1.3.6.1.2.1.4.34.1.3.2"

    # snmp情報を取得する
    for (errorIndication,
         errorStatus,
         errorIndex,
         varBinds) in nextCmd(SnmpEngine(),
                              CommunityData('コミュニティ名'),
                              UdpTransportTarget((host, ポート番号)),
                              ContextData(),
                              ObjectType(ObjectIdentity(oid)),
                              lexicographicMode=False
                              ):

          # 取得できたインタフェース分繰り返す
          for name, val in varBinds:
              spr1 = str(name).split('.')
              spr2 = str(val).split(' ')
              iplist = ''
              for i in range (12,28):
                  # iplistに各オクテットを16進数に変換し0埋めして足していく
                  iplist += str('{:02x}'.format(int(spr1[i])))
                  if i % 2 == 0 or i > 26:
                      continue
                  else:
                      # 所定の位置にコロンを加える
                      iplist += ":"
              # ipaddressモジュールでIPv6短縮形にして表示
              print ("Ifindex:%s,ipv6address:%s" % (spr2[0],ipaddress.IPv6Address(iplist)))


if __name__ == '__main__':

    ipv6_search(argvs[1])
```

##実行結果
以下のように、対象ネットワーク機器のインターフェースが持つIPv6アドレスを短縮表記で取得できます★
今回は合わせてIPv6アドレスを持つインターフェースのindexを取得するようにしていますが、用途に応じて好きな情報を取得します。

```
$ python if_ipv6_sample.py 情報取得したいネットワーク機器のIP
Ifindex:20,ipv6address:1603:538:400:11::6
```