OmniAICreator/Qiita-1.07M huggingface dataset:
特定のカラムで重複を排除し、重複排除に利用したカラム以外の列も取得するクエリ

##特定のカラムで重複を排除し、重複排除に利用したカラム以外の列も取得するクエリ
タイトルのようなことが出来るか？と聞かれて、即答できなかったので備忘録として記事にしました。

下記のようなテーブルがあったとする。
####社員情報テーブル（Staff）
| StaffId | Name | Department | JoinYear | 
|:-:|:-:|:-:|:-:|
| 001 | ディアボロ | 取締 | 1986 | 
| 018 | ブローノ・ブチャラティ | 護衛 | 1997 | 
| 019 | パンナコッタ・フーゴ | 護衛 | 1998 | 
| 022 | ナランチャ・ギルガ | 護衛 | 1999 | 
| 024 | レオーネ・アバッキオ | 護衛 | 2000 | 
| 025 | グイード・ミスタ | 護衛 | 2000 | 
| 026 | ジョルノ・ジョバーナ | 護衛 | 2001| 
| 003 | リゾット・ネエロ | 暗殺 | 1990 | 
| 020 | ホルマジオ | 暗殺 | 1998 | 
| 010 | イルーゾォ | 暗殺 | 1995 | 
| 005 | プロシュート | 暗殺 | 1992 | 
| 023 | ペッシ | 暗殺 | 1999 | 
| 011 | メローネ | 暗殺 | 1995 | 
| 015 | ギアッチョ | 暗殺 | 1996 | 
| 008 | ソルベ | 暗殺 | 1994 | 
| 009 | ジェラート | 暗殺 | 1994 | 
| 012 | スクアーロ | 親衛隊 | 1995 | 
| 013 | ティッツァーノ | 親衛隊 | 1995 | 
| 016 | カルネ | 親衛隊 | 1996 | 
| 006 | チョコラータ | 親衛隊 | 1993 | 
| 007 | セッコ | 親衛隊 | 1993 | 
| 021 | ルカ | その他 | 1998 | 
| 017 | マリオ・ズッケェロ | その他 | 1996 | 
| 014 | サーレー | その他 | 1995 | 
| 004 | ポルポ | その他 | 1991 | 
| 002 | ペリーコロ | その他 | 1988 | 
※入社年度は適当。

このテーブルから所属部門で重複を排除して、入社年度の早い人のデータを取得したい。
####期待する結果
| StaffId | Name | Department | JoinYear | 
|:-:|:-:|:-:|:-:|
| 001 | ディアボロ | 取締 | 1986 | 
| 018 | ブローノ・ブチャラティ | 護衛 | 1997 | 
| 003 | リゾット・ネエロ | 暗殺 | 1990 | 
| 006 | チョコラータ | 親衛隊 | 1993 | 
| 002 | ペリーコロ | その他 | 1988 | 

distinctでサクッと上手くいくかと思ったが、distinctをかける以外のカラムも取得したいということで悩んでしまった。
質問をした人の環境はMySqlだったので **distinct on** を使用することで解決したが、
自環境がSQLServerで**distinct on**はなくちょっとググっても該当するようなものがなかったので、
どうすれば良いかに考えてみたら、以下で出来た。

####実際のクエリ
```SQL:select.sql
select tempStaff.StaffId
      ,tempStaff.Name
	  ,tempStaff.Department
	  ,tempStaff.JoinYear
from (select rank() over(partition by Department order by JoinYear) as rk
            ,*
      from dbo.Staff) as tempStaff
where tempStaff.rk = 1
order by tempStaff.Department
```

**特定のカラムで重複を排除したい** という言葉でDistinctをどう使えばいいのかと悩んでしまったが、
集計関数を使用してグループ毎に順番を決めて先頭を取得すれば出来た。
もっと簡単なやり方を知っている方がいればご教示ください。

同じように困る人がいるかもしれないので、このタイトルにしておきます。
AWS Lambda Layers上でHeadless Chromeを動かすいくつかの方法

メモとして。

## chrome-aws-lambda

https://www.npmjs.com/package/chrome-aws-lambda

Lambda layersでの対応手順の記載もあり、Lambda layersを使うのであればこちらがおすすめ。
同梱されているChromiumのバージョンも新しめ。

## serverless-chrome

https://github.com/adieuadieu/serverless-chrome
https://github.com/adieuadieu/serverless-chrome/tree/master/packages/lambda

Lambdaでselenium+chromiumを使う場合の定番。ググればいろいろとやり方は出てくる。
同梱されているChromiumのバージョンはやや古め。

### lambda-layer-headless-chromium

serverless-chromeをcjkとLambda Layerに対応させるパッチのようなもの

https://github.com/pahud/lambda-layer-headless-chromium
Ruby コードレビューツール

##1.Rubocop(ルボコップ)
Rubyの静的コード解析ツール

```
group :development do
  gem 'rubocop', require: false
end
```

##2.Rubocopを実行
```
$ bundle exec rubocop
```

##3.設定ファイルを作成
.rubocop.yml

```
AllCops:
  # 除外するディレクトリ（自動生成されたファイル）
  # デフォルト設定にある"vendor/**/*"が無効化されないように記述
  Exclude:
    - bin/*
    - db/schema.rb
    - node_modules/**/*
    - db/migrate/*
    - vendor/**/*
  # Rails向けのRails copsを実行。"rubocop -R"と同じ
  Rails:
    enabled: true

# "Missing top-level class documentation comment."を無効
Style/Documentation:
  Enabled: false

# "Prefer single-quoted strings when you don't need string interpolation or special symbols."を無効
Style/StringLiterals:
  Enabled: false

# "Line is too long"を無効
Metrics/LineLength:
  Enabled: false

#'frozen_string_literal: true'を無効
Style/FrozenStringLiteralComment:
  Enabled: false
```

##4.違反を徐々に修正
①現在の違反を全て記録した上で、一旦違反ではないことにする
②記録した違反のうちに１つを、違反していることに戻す
③その違反を解消する

##5.現在の規約違反がまとめられた.rubocop.todo.ymlファイルを生成
```
$ bundle exec rubocop --auto-gen-config
```

##6.規約違反を自動で修正
.rubocop.todo.ymlの各設定の上にコメントアウトで「#Cop supports --auto-correct.」と書かれていれば、-aオプションを利用できる

```
$ bundle exec rubocop -a
```
font-feature-settingsが効かない時の確認点

font-feature-settingが効かない時に確認する点をまとめました。

#1. 見ているブラウザに対応していない？

2019年3月現在、ほとんどのモダンブラウザに対応しています。
IEですら、10から対応しているので、
閲覧しているブラウザのバージョンが古いことで
効いていないというのは考えにくいでしょう。
<img width="1269" alt="スクリーンショット 2019-03-23 21.06.20.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/102434/4f358058-331d-854b-112e-9e5d7b746698.jpeg">
Can I use... font-feature-settings
https://caniuse.com/#search=font-feature-settings

#2. ベンダープレフィックスが足りてない？
`-webkit-font-feature-settings: "palt";`
これだけ付与していれば大丈夫。

この記事を参考にしています。
**ベンダープレフィックスを検証したい場合に**
https://qiita.com/syo24/items/aa7cd9e7409d12454e80

この記事では、Autoprefixerのパラメータを用いて
対応する必要があるベンダープレフィックスを記載しています。

「日本で1%以上のブラウザーのみ」の場合は
-webkit-のベンダープレフィックスも必要ないようです。


#3. メイリオ・Noto Sans・MS ゴシック・MS 明朝で使えない
よく使われるこのフォントたちはfont-feature-settingsが効かないのでご注意。

###メイリオ
メイリオは等幅で制作されているフォントのため、字詰めができません。

###Noto Sans
Noto Sansは過去に字詰めができたようですが、
2019年3月現在、字詰めができません。

> 2018年6月29日現在、ウェブフォントの「Noto Sans JP」で字詰めできなくなっていることを確認しました。

https://qiita.com/sutara79/items/7f0c6365e5935311b1f8

またいずれできるようになるかもしれません。

###MSゴシック・MS 明朝
MSゴシック・MS 明朝はTure Typeというフォントの種類のため
字詰めができません。

字詰めができるフォントについて、詳しくはこちらをどうぞ。
**文字詰めできるCSSのfont-feature-settingsが凄い！ 日本語フォントこそ指定したい自動カーニング - ICS MEDIA**
https://ics.media/entry/14087/3


#4. Firefoxにて「ヒラギノ明朝」への字詰めが効かないバグ
実際に確認したのですが、
すみません。ソースは探してみたのですがありませんでした。。


##まとめ
意外と、ブラウザやベンダープレフィックスを気にしなくてよいでしょう。
気にするべきは「何のフォントを使っているか？」でしょうか。

font-feature-settingを当てたテキストへ
letter-spacingで文字間を開ける。
というスタイルが一般的かとは思いますが、
意外と字詰めできないフォントがあるので
使用は見出しのみに留めるなどがよいかもしれません。

Noto Sans、字詰めできるってよ。
となれば積極的に使っていきたいですね。
Android Studio 複数のプロジェクトの起動順番を変更

###Run->Edit Configurations... 

.idea/workspace.xml

<img width="498" alt="スクリーンショット 2019-03-22 18.09.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/125746/13f4c64c-9745-ec81-953b-9fd02cfde276.png">
Djangoでhtmlを表示する

<a href='https://qiita.com/kagami-r0927/items/e7026118241f70876f77' target='_blank'>Djangoチュートリアル　アプリ作成(1)[DBの設定・ブラウザで開く]</a>の続きです

# 1. templatesを利用してhtmlをブラウザに表示させる
<a href='https://qiita.com/kagami-r0927/items/e7026118241f70876f77' target='_blank'>Djangoチュートリアル　アプリ作成(1)[DBの設定・ブラウザで開く]</a>の後に操作を行なってください

# ツリー構造

```
mysite
├── __init__.py
├── __pycache__
├── settings.py
├── templates
│   └── hello.html
├── urls.py
├── views.py
└── wsgi.py
```
# settings.pyの変更
33行目くらいの`INSTALLED_APPS`を以下のように'hello'を追加します。

```settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hello',
]
```

# templatesディレクトリの作成

`mysite`直下に`templates`ディレクトリを作成します。
僕の場合は
この中に表示したいhtmlファイルを作成します。
ここでは例として "Hello, World" を表示させてみます。

```hello.html
<html>
    <head>
        <meta charset="utf-8">
        <title>Hello, World !!</title>
    </head>
    <body>
        <h1 class="hello">Hello, World !!</h1>
    </body>
</html>
```

# views.pyの変更
views.pyを以下のように変更してください。

```views.py
from django.views.generic import TemplateView
from django.shortcuts import render

class IndexTemplateView(TemplateView):
    template_name = "hello.html"

    def get(self, request):
        return render(request, self.template_name)
```

# urls.pyの変更

```urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
# views.pyが置いてある場所を指定
from hello.views import IndexTemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', IndexTemplateView.as_view()),
]
```

ここまでできたら、以下のコードをターミナルで実行してください。

```
$ python3 manage.py runserver
```
そして、以下のURLに行くと
http://127.0.0.1:8000/

<img width="400" alt="スクリーンショット 2019-03-22 17.50.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/285122/f17c6a7d-082c-bff3-f0f0-1020a405ea9a.png">


このように表示されます。

# 2. views.pyにテキストを書き込んでブラウザに表示させる
<a href='https://qiita.com/kagami-r0927/items/e7026118241f70876f77' target='_blank'>Djangoチュートリアル　アプリ作成(1)[DBの設定・ブラウザで開く]</a>の後に操作を行なってください

# ツリー構造
mysite
├── db.sqlite3
├── hello
│   ├── settings.py
│   ├── urls.py
│   ├── views.py
│   └── wsgi.py
└── manage.py

# views.pyの変更
以下のように変更してください。

```views.py
from django.http import HttpResponse

def hello_world(req):
    return HttpResponse('Hello, World!')
```

# urls.pyの変更
以下のように変更してください。

```urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
# views.pyが置いてある場所を指定
from hello.views import hello_world

urlpatterns = [
    path('admin/', admin.site.urls),
    path('views_hello/', hello_world),
]
```

ここまでできたら、以下のコードをターミナルで実行してください。

```
$ python3 manage.py runserver
```

そして、以下のURLに行くと
http://127.0.0.1:8000/views_hello/

<img width="174" alt="スクリーンショット 2019-03-22 18.05.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/285122/f4d6d67c-4099-4f8c-188b-27c72589eb57.png">


このように表示されます。
PHPで正規表現のマッチングを判断する方法

例えば入力された文字列が半角英数字の場合

<img width="672" alt="スクリーンショット 2019-03-22 17.57.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/364264/7854af81-d205-7ab6-752f-cf77da133b2c.png">


**preg_match(半角数字,文字列)**
この文字列の中身が、半角英数字
→これが正なら1を返す、誤りなら0を返す。
FirebaseとVue.js（Nuxt.js）に慣れようと思って参考にしたサイト

もうすぐゴールデンウィークですね。
10日も休みですね。
なにしよう・・・
ゴロゴロしててもきっと飽きるので、何かしようと今から興味のあることを探してます。

ふわっと知っているけれど、何かつくったことはないFirebaseをちょっとさわってみてみました。
参考にして、練習したサイトをまとめておこうと思います。（自分のために。）

## まずは
Firebaseについてですね。
[公式サイト](https://firebase.google.com/?hl=ja)

ドキュメントがいっぱいなので、公式サイト読むだけでもだいたいなにができるか、
困った時どうしたらいいのかはわかると思います。

## 参考にしたサイト

読んだだけのサイトはとてもいっぱいあるので、手を動かしてみたものだけにしました。

### [Vue.js + Firebase を使って爆速でユーザ認証を実装する](https://qiita.com/sin_tanaka/items/ea149a33bd9e4b388241)

なんだかよくわからずにサイトに沿ってコピペしていったら、動くものができた！
すごい！！

### [【Firebase】Vue.jsで作ったWebアプリを公開する方法を解説【初心者向け】](https://public-constructor.com/firebase-hosting-vuejs-for-beginners/)

ホスティングもやってみようと思い、上でつくったやつを公開してみることに。
なんかわかんないけど結構てこづった・・・

> “firebase init”が完了すると、first-firebaseディレクトリの配下に “.firebaserc” と “firebase.json” が作成されています。

ここの部分、何回　`firebase init`　しても、`firebase.json` が作られず・・・
でも、実際は私が思っていた場所とは違うところにできていて、そのファイルを本来いて欲しい場所に移動したら解決しました。

公開と公開停止をやりました。とても簡単。

この問題解決するために参考にしたサイト
[Vue.js によるアプリを Firebase で Hosting する最短の道](https://qiita.com/Satachito/items/4a00b402970d657a88f3)
[Firebase Hostingに静的サイトをデプロイする手順のメモ](https://qiita.com/rubytomato@github/items/b83caa01fc9c4993f526)
[5分でvueのアプリを作りfirebaseにhostingする](https://qiita.com/okaokaokaokatoru/items/ea4181f65a09115518ec)

### [FirebaseとNuxt.jsを使ってユーザ認証関係を簡単に作ってみる+1ヶ月前の自分に教えたいリンク集](https://qiita.com/redshoga/items/da5c0e247e0df314a257)

さっきやった内容をNuxt.jsで。
普段Nuxt.jsつかっているので、こっちのほうがなじみがあり・・

しかし、なぞのエラーでつまずいた。
それに関してはメモしたので、そちらで。
[node-v57-linux-x64-glibcがなんちゃら〜ってエラーが出た時の解決方法](https://qiita.com/mimoe/items/0e71e7633c79828c7b83)

### [Nuxt.jsとFirebase Authenticationでログイン認証を作る](https://www.non-standardworld.co.jp/20548/)

ほぼほぼおさらいですね。

最後の、ログインしたら表示が変わるところが変わらないーって思ったけど、数秒したら表示が変わって、あ、時間かかってただけ？ってなりました。
これはしょうがないんかな？

## おわり

そんな感じで、とても簡単でした〜

つまずいたのは、Firebaseとはあまり関係ないとこばっかｗ

なにつくろうかな〜
ってか、何かつくるのかな？
WinActorで困った話　その３　～ウィンドウ名の管理編～

#今回の内容
こんにちは。
前回投稿から間が空きました。
今回はWinActorでシナリオを作成する場合に疎かになりがちな、ウィンドウ名の管理について書いていきます。
これをちゃんと管理しなかったせいで、シナリオが動かないことがありましたので。
ちょっと前振り長いかもしれません…が実例が無いと実際にどういう時に必要な対処かイメージ出来ないと思いますので敢えて書かせてもらいます。

#作ったシナリオが動かない？！（前振り）
###対象のシステムについて
最初に書きましたがWebシステムでもクラサバ系システムでも、**ログイン情報でウィンドウタイトルが変わるシステム**が存在します。
（個人的には、ウィンドウタイトルよりかは画面上に表示した方がいいと思うんですが…タブブラウザとかだと表示しきれないし）
今回シナリオ作成したシステムも、正にそんなシステムでした。
###動かない？！
シナリオ作成後、担当者を呼んで実際の動きを見てもらったのですが、自分でログインで実行をすると問題なく動くのに、担当者でログインすると**ログイン即エラー**となりました。
###原因
エラーの内容を見てみると「ウィンドウ名が見つかりません。」と表示されました。
どうやらウィンドウ名がログイン情報に合わせて可変になるため、自分と担当者のログイン情報が異なるために合致するウィンドウ名が存在しないためエラーになった模様。（ウィンドウ名はこんな感じでした【ログイン[名前]】
#ウィンドウ名を管理しよう！
##本題
前振り長かったですが、今回のようなシステムに対してWinActorでシナリオを作成する場合、ポチポチとアクションを設置するだけだと折角作ったシナリオが動かないことがあります。
その原因になりやすいのが**「ウィンドウ名」が異なるor見つからない**ことによるエラーだと思います。
##ウィンドウ名の管理はどこで行う？
ウィンドウ名は、フローチャートウィンドウにある**ウィンドウ識別ルール**で行います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/311963/5d9886d0-0e4f-9c87-c296-dcde01a6d3fb.png)
ちゃんとマニュアルに書いてるんですけど、チュートリアルとかじゃ取り上げてないのであまり意識しないと思います。
##ウィンドウ識別ルール画面についてと使い方
これがウィンドウ識別ルールの画面です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/311963/9637474f-7ddb-a120-bdd6-309522a7d294.png)
この画面の左にある**ウィンドウ識別名**から編集したい識別名をクリックし、右にある**ルール**で編集することが可能です。
例えば今回はウィンドウタイトルが「Lh」を含んでいる場合にアクション対象にするには、下図のようにします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/311963/ee1f06e6-812a-ccef-0be4-0c095a9e4c05.png)
これだけでウィンドウタイトルに「Lh」が含まれていればアクションを実行させることが可能になります。
前振りで可変だった「ログイン[名前]」というウィンドウタイトルも**識別方法：を含む、文字列：ログイン**とすることで、どのユーザでログインしても対応可能となりました。
##ウィンドウ識別名はどのタイミング作成される？
作成されるタイミングは、**アクションのウィンドウ識別名でウィンドウを選択した時**です。（キャンセルすれば作られません）
そのためアクションを作成する度にウィンドウを選択しまくると、膨大な量のウィンドウ識別名が作られることになります。
#管理とテクニック
ウィンドウ識別名については、今までの内容でわかってもらえたと思います。（わかってもらえてると嬉しいです…！）
しかし、作成タイミングの通り油断しているとあっという間にウィンドウ名が膨れ上がり、管理が出来なくなる、エラーの温床になるといったことが起こります。
なので、自分は以下のようなことを気をつけています。
###ウィンドウ識別名をつける
ウィンドウ識別名は自分で分かりやすい名前に変更が可能です。（デフォルトは選択した時のウィンドウ名）
ルールに記載されているウィンドウタイトルとは、別の名前をつけることが出来るので、自分で管理しやすい名前にしましょう。
###ある程度ウィンドウ名はまとめる
シナリオを作っていると似たような画面や変わらないタイトルの機能があると思います。
そういう場合は、いっそ１つのウィンドウ識別名で管理出来るように１つにまとめ、複数の画面で識別名を使いまわします。
###敢えてルールを触らない
ウィンドウタイトルが完全一致している方が好都合な時もあります。
そういう場合は識別名の編集に留めておいて、ルールは触らないようにしましょう。
###ウィンドウタイトル以外は触らない
「ウィンドウクラス名」「プロセス名」に関しては触らない方が無難です。
アプリが持っている特有の情報なので、下手に触ると予期せぬエラーが発生する可能性があります。
ルールでウィンドウタイトルが被っても、上記の項目で判別されます。
###不要な識別名は消す
ウィンドウ識別名を整理すると、どのノードにも紐付かない識別名が残ります。
これは画面上に未使用のものを削除するボタンがあるので、こちらで削除しましょう。
#まとめ
今回のウィンドウ識別名というのは、普段シナリオを作っていると管理が疎かになりやすいところです。（何せアクション設定するだけでどんどん増える…）
この辺りを意識するようにすると、メンテナンスが非常にしやすくなりますし、エラーも減ると思います。
効果測定したわけじゃないですが、シナリオ実行中もこの辺りの検索が少なくなることでスピードが上がるかもしれません。（願望）
まぁ、とにかく整理整頓は重要！ということです。
今回の記事が参考になれば幸いです。
ではでは！
StyleGANをVOICEROID立ち絵に適用する

StyleGANをイラスト、アニメに適用している人は多いようです。
(https://twitter.com/search?q=stylegan&src=typd)

StyleGANが画像のスタイルをうまく捉えられるということであれば、それが顕著なデータセットを用意したら面白い結果が得られるのではないかと思い、そのようなデータとしてVOICEROIDの立ち絵から顔画像を持ってくることを考えてみました。

# VOICEROID立ち絵

[VOICEROID素材まとめ Wiki*](https://wikiwiki.jp/voirosozai/)から画像を収集しました。
headless Chrome, selenium, BeautifulSoupでリンク先のプレビュー画像を取得し、[lbpcascade_animeface.xml](http://ultraist.hatenablog.com/entry/20110718/1310965532)にて検出できた領域を無理やり64x64にリサイズしたものを訓練データとしています。
結月ゆかり、弦巻マキ、琴葉茜・葵、東北ずん子、東北きりたんの6人分、画像数約6600枚を訓練データとしています。

# ランダムな単一画像の出力

オリジナルのstyleganをsubmoduleとするリポジトリを用意し、手軽に試せるコードをGoogle Colaboratoryに用意しました。

[evaluate-vroid.ipynb - Colaboratory](https://colab.research.google.com/drive/1zbn0z3rYeZZ_uGuT6jtCMyrzxDjdxvEn#scrollTo=MJPKfv4ZSeDx)

乱数のシードを30としたときの出力例を以下に示します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/31714/df672462-dff2-a5bb-ee72-7205ee404813.png)

# 2方向マッピング

[StyleGANの2方向マッピング - Qiita](https://qiita.com/angeart/items/694fdd6eb83e07ea932a)を参考に、使うモデルだけを変えて実行できるようにしました。

[StyleGAN 2way mapping - Colaboratory](https://colab.research.google.com/drive/1x3g2b2oySdmJ19k2tStnOWD8POdckB_v#scrollTo=Qt9YG5WiQJ7C)

以下は出力例です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/31714/0dd7e83e-947a-dc92-f020-0d472151038c.png)

## 感触

データ数が少ない割にはそこそこ結果を出せている印象です。ただ、画風がかなり異なる画像(線の太さ、デフォルメの強弱等)があるための影響が大きい感じがします。

また、取得した画像は他の画像と部分的にオーバーラップしているケースもあったため、その影響も見られます(上から2段目、3段目の左側)。
今回はプレビュー画像をそのまま使ったので、もっと綺麗な状態の配布素材画像を直接使うようにすればこの問題は解決できそうです。しかし、配布方法が人によって異なっており自動収集が難しいという課題があります。

# 課題

NVIDIAのStyleGAN実装は、推論にもGPUが必要です。計算グラフの中でGPUの指定が陽にされているためです。
allow_soft_placementを指定して無理やりCPUで処理させようとすると、
```
UnimplementedError (see above for traceback): Generic conv implementation only supports NHWC tensor format for now.
         [[node Gs/_Run/Gs/G_synthesis/4x4/Conv/Conv2D (defined at <string>:168) ]]
```
conv2dがUnimplementedErrorを発生させて動きませんでした。NCHW形式にしたら動くんでしょうか。

# 配布ファイル

* [訓練済みモデル](https://drive.google.com/file/d/1H2RNWlES9F-iU9o8s8wRT5JqKDZVfmEq/view?usp=sharing)
* [単一出力](https://colab.research.google.com/drive/1zbn0z3rYeZZ_uGuT6jtCMyrzxDjdxvEn)
  * https://github.com/knok/vroid-stylegan
* [2方向マッピング](https://colab.research.google.com/drive/1x3g2b2oySdmJ19k2tStnOWD8POdckB_v)
通信出来てんの？ tcpdump 

### tcpdump
ネットワークのトラフィック確認に利用  

Wiresharkを使えばいいのに、なぜかこっちの情報を見ていたのでメモ  


> こいつら生きてんの？

とか

> 壊れてね？

とか思った時に役に立つのか？  


### ポート54321に関わるトラフィックをログに書き出す

```
sudo tcpdump -i en0 port 54321 -p -s0 -w sample.log
```

| オプション  | 内容 |
|---|---|
| -i | インタフェースを指定 |
| -p | プロミスキャスモードにしない |
| -s | キャプチャのバッファサイズを指定 0は無制限 |
| -w | キャプチャ結果をファイルに出力する |



### ログファイルからパケットを読める形式で表示

```
sudo tcpdump -r sample.log -Atvvv | less
```

| オプション  | 内容 |
|---|---|
| -r | パケットをfileから読み込む |
| -A | パケットの内容を ASCII で表示する |
| -t | ダンプ行に時間を表示しない |
| -v | 詳細な情報を表示 |


### 所感
2日で存在忘れそう  
軽々使いこなしているパイセンいたらカッコいいけど
[oneWEX] コンテンツマイナーの地図ビューの使い方

# 概要
oneWEX v12.0.2.2 では、コンテンツマイナー画面で地図ビュー（Map visualization）が使えます。
デフォルトではUSの地図が使えますが、日本の地図を使うカスタマイズ例を紹介します。

[Map visualization in Watson™ Explorer Content Miner](https://www.ibm.com/support/knowledgecenter/SS8NLW_12.0.0/com.ibm.watson.wex.ee.doc/c_onewex_map_visualtization.html)


# 手順
###1. Mapファイルの準備
地理情報を表す[GeoJSON](http://geojson.org/)形式のファイルを準備する。
今回はこちらを利用させて頂く。.geojsonファイルをダウンロード。
[GitHub/Data of Japan](https://github.com/dataofjapan/land/blob/master/japan.geojson)

###2. REST APIでMapファイルをoneWEXへアップロード
####① "https://[oneWEXのアドレス]/docs/"にアクセス
Swagger UIが表示されるので、[Authenticate]で認証を通す。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/6555d1fa-f19f-c6e2-c8b1-3a80ec1875dc.png)|
|:-:|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/d648feb0-8f24-4783-ba1e-411741f6ce42.png)|
|:-:|


####② FileResource から POST /api/v1/fileResources Create a file resource　を開き、Try it outをクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/822948ef-871d-32c8-0efa-627060204485.png)|
|:-:|


####③ bodyの箇所を以下のように更新
"propertyNames"には、手順１．で用意したGeoJSONファイル中の"properties"で使用されているキーを指定する。今回は、ダウンロードしたGeoJSONの"nam_ja"に都道府県の日本語名が入っており、地図で表示したいファセットの値も都道府県名であるため"nam_ja"を指定。

```json
{
    "description": "JapanMap",
    "id": "string",
    "metadata": {
        "lastModified": 1531288825136
    },
    "name": "JapanMap",
    "tags": {
        "propertyNames": ["nam_ja"],
        "saveToLocal": true
    },
    "type": "map"
}
```

####④ Executeをクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/025254e4-4709-3808-c178-2d15a79cac2a.png)|
|:-:|


####⑤ Response bodyに表示されるidをコピー

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/7ccc4dbb-a61a-bea1-c01e-4a7f5ad2bddf.png)|
|:-:|





####⑥ FileResource から POST /api/v1/fileResources/{fileResourceId}/upload Update a file resource content　を開き、Try it outをクリック

####⑦ fileRerouceId に手順⑤でコピーしたidを入れ、fileにダウンロードしたGeoJSONファイルを指定してExecuteをクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/81879004-906c-36de-a5f0-c6658b06607b.png)|
|:-:|

####⑧ レスポンスコード200が返ることを確認

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/af4d40d4-2867-91af-f3ed-aa20d091fa93.png)|
|:-:|


###3. コレクションの設定

管理コンソールからでもコンテンツマイナーからでも設定可能。
コレクションの[ファセット] タブで、地図形式で表示したいファセットの[視覚化タイプ]をマップにし、[リソース]を自身がアップロードしたMapファイル名を指定して[保管]。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/1fa96ed5-d019-c210-9919-1637ddf02eae.png)|
|:-:|


ファセットの設定を保管すれば、索引付けの再作成をしなくても地図ビューが表示される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/248948/55199cf3-8b09-de62-8b71-a2778525474d.png)|
|:-:|



以上です。
Firebaseでサイトを公開する

#Firebaseにてプロジェクトを作成する
[Firebase](https://firebase.google.com)にログインし、コンソールからプロジェクトを作成してください。
地域は日本に設定しましょう。

#ローカルでプロジェクトと同じ名前のディレクトリを作成
1. ローカルのデスクトップにFirebaseで作成したプロジェクトと同じ名前のディレクトリを作成
2. 作成したディレクトリの下に公開したいアプリのディレクトリの名前を、「public」に変更して入れる

#Node.jsのインストール
[こちら](https://nodejs.org/ja/)から手順に従ってnode.jsのインストール
・node.jsの確認

```
$ node -v
```
・npmの確認

```
$ npm -v
```

#firabase-toolsのインストール
```
$ sudo npm install -g firebase-tools
```

・firebaseの確認

```
$ firebase -V
```

・firebaseへのログイン

```
$ firebase login
```

#プロジェクトの設定
・プロジェクトのディレクトリへ移動し、下記コマンド実行
 
```
$ firebase list
```
すると、ProjectIDが表示されるので、コピーしておく。

・コピーしたProjectIDを利用してinitializeする

```
$ firebase init --project=[コピーしたProjectID]
```

その後、順番に質問に答えていく
・? Which Firebase CLI features do you want to setup for this folder? Press Space 
to select features, then Enter to confirm your choices.
→Hostingを選択(シフトを押してEnter)

・? What do you want to use as your public directory?
→public

・? Configure as a single-page app (rewrite all urls to /index.html)?
→No

・File public/index.html already exists. Overwrite?
→No

最終的にこれが出ればOK

```
Firebase initialization complete!
```

#公開する

```
$ firebase deploy
```

**これだけ！！！**
Elasticsearch Queryのキャンセル

# はじめに

ながーくかかるクエリを実行している時に、ふとキャンセルしたい時ってありませんか？
そんな時に使える手が[`X-Opaque-Id`](https://www.elastic.co/guide/en/elasticsearch/reference/6.6/tasks.html#_identifying_running_tasks)を使ったキャンセルです。

# 長くかかるクエリのキャンセル

## 普通に実行した場合

例えばこんなクエリを投げて見ます。

```
curl -i -H 'Content-type: application/json' http://localhost:9200/.monitoring-*/_search -d'{"size": 10000}'
```

環境にもよるとは思いますが、レスポンスが返ってくるまで結構かかります。
レスポンスが返るまでは[Task Management API](https://www.elastic.co/guide/en/elasticsearch/reference/6.6/tasks.html)を使えば、実行中のクエリを見ることはできます。
ただし、どんなクエリを実行しているのかまでは、このAPIでは見ることができません。

単発のクエリを実行し値得る場合は、

```
# curl 'http://localhost:9200/_tasks?pretty&actions=*search'
```

で出てきたタスクのIDを使ってキャンセルすれば良いでしょう。
でも、複数のクエリを実行している場合は、どれが本当にキャンセルしたいものかわかりません。

## X-Opaque-Idを使用したリクエストの特定

リクエスト時に`X-Opaque-Id`ヘッダを付加して実行します。

```
curl -i -H "X-Opaque-Id: 123456" -H 'Content-type: application/json' http://localhost:9200/.monitoring-*/_search -d'{"size": 10000}'
```

この状態でタスクを確認すると、

```
# curl 'http://localhost:9200/_tasks?pretty&actions=*search,*fetch*'
{
  "nodes" : {
    "RqHPIcbRRIyDb3uqTwzmDQ" : {
      "name" : "RqHPIcb",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "roles" : [
        "master",
        "data",
        "ingest"
      ],
      "attributes" : {
        "ml.machine_memory" : "16681828352",
        "xpack.installed" : "true",
        "ml.max_open_jobs" : "20",
        "ml.enabled" : "true"
      },
      "tasks" : {
        "RqHPIcbRRIyDb3uqTwzmDQ:9252" : {
          "node" : "RqHPIcbRRIyDb3uqTwzmDQ",
          "id" : 9252,
          "type" : "transport",
          "action" : "indices:data/read/search",
          "start_time_in_millis" : 1553242069549,
          "running_time_in_nanos" : 475068030,
          "cancellable" : true,
          "headers" : {
            "X-Opaque-Id" : "123456"
          }
        },
        "RqHPIcbRRIyDb3uqTwzmDQ:9278" : {
          "node" : "RqHPIcbRRIyDb3uqTwzmDQ",
          "id" : 9278,
          "type" : "direct",
          "action" : "indices:data/read/search[phase/fetch/id]",
          "start_time_in_millis" : 1553242069698,
          "running_time_in_nanos" : 326060299,
          "cancellable" : true,
          "parent_task_id" : "RqHPIcbRRIyDb3uqTwzmDQ:9252",
          "headers" : {
            "X-Opaque-Id" : "123456"
          }
        }
      }
    }
  }
}
```

てな感じで、レスポンスにヘッダ情報が付加されて返ってきます。
これでどのクエリか特定できるので、そのタスクIDを使ってキャンセルをする、と。

# おわり~~に~~らない

~~curlで実行している分には、curlのプロセスをkillしちゃえば（＝コネクションが切れる）、Elasticsearch的にはクエリがキャンセルされるらしいので、それでも良いといえば良いかと。~~
コネクションを切ったときにキャンセルされるのかどうか、確証が持てない・・・

## コネクションを強制的に切った場合

調べて見たら、どうやらキャンセルはされずにElasticsearch内部では処理が続く。なので、コネクションをぶちぶち切って、都度新しいリクエストを送るとリソースを使いまくる（Rallyなんかはデフォルト60秒でコネクションを切るので、それはそれはヤバイことになるかな・・・）。

## タイムアウト（クエリパラメータ、リクエストボディ）を指定した場合

QueryPhase でシャードに対して実行したクエリが timeout 指定時間以内に戻らない場合にタイムアウトと判定。タイムアウトになると、当該シャードに対する FetchPhase は実行されない。結果として、FetchPhase が実行されたシャードに関する結果だけが返る。

タイムアウトが起きていなければ、レスポンスは

```json
{"took":704,"timed_out":false,"_shards":{...
```

となるが、タイムアウトになった QueryPhase があると、

```json
{"took":704,"timed_out":true,"_shards":{...
```

となる。
AWS[EC2]で自動デプロイコマンド入力したらエラーが出た

##はじめに
TwitterでAWSを使えるエンジニアは強いというツイートを見たのでAWSに登録してEC2を進めています。
そこで自動デプロイをしようとしたらエラーが出てきたので少しでも困っている人のためになればと思い、共有したいと思います。


##エラー内容

自動デプロイコマンド

```console:ターミナル
bundle exec cap production deploy
```

```console:ターミナル
Traceback (most recent call last):
 	1: from /Users/自分の名前/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/
sshkit-1.18.2/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
/Users/自分の名前/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.18.2/
lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute':
 Exception while executing as EC２のアカウント rake exit status: 1 (SSHKit::Runner::ExecuteError)
rake stdout: Nothing written
rake stderr: Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install
rake aborted!

Uglifier::Error: Unexpected character '`'

Tasks: TOP => assets:precompile

```


##原因
最後から2行目のUglifierというものが悪さをしているみたいです。
なのでこいつを退治します。

##解決策
config/environments/production.rbの
`config.assets.js_compressor = :uglifier`をコメントアウト
もそ、プログラミングを学ぶ【Ruby & Rails復習編】〜paramsがわからない〜

相変わらずエラー問題に大苦戦中の もそ。
解説文の意味がまったく掴めず、もはやプログラミングというより読解力スキルの問題では...？という気もしないでもないのですが、地道に身につけて行こうと思います。

さて今日は、paramsについて書いていきます。
あろうことか商売道具のiPadをうっかり忘れてきてしまったので、今日は手描きのデータをスキャンして載せます。


##パラメータとは？
さっそくですが、こちらの図を見て下さい。
左側は入力フォームを表示しているビュー、右側はこのビューに紐付いているコントローラです。

![無題12.jpeg](https://qiita-image-store.s3.amazonaws.com/0/372174/b3f12fa3-c2d9-a9da-add3-553f6ac14602.jpeg)


この図の場合のパラメータは、**"ビュー"でフォームに入力された情報**、つまり画像URLとテキスト本文のことです。
この情報は、**"キー"と呼ばれる情報名**と一緒にコントローラへ送られます。

コントローラは、入力フォームから受け取った情報（＝パラメータ）と、情報の名前（＝キー）をテーブルに渡します。

##paramsとは？
paramsは**ハッシュ**の形（情報の入った箱）をとったデータです。
先ほどコントローラがテーブルに渡したパラメータを取得する指示する必要がありますよね。
この指示を出すための記述が**paramsメソッド**になります。
![無題13.jpeg](https://qiita-image-store.s3.amazonaws.com/0/372174/51bd815d-f7a0-66fa-0a43-18870227850c.jpeg)

情報の受け渡しはコントローラが担当するので、**記述するのはcontroller.rbファイル**になります。

```
params[:キー名}

params[:image] => "http://mosotopochisample0322.jpg"
params[:text]  => "もそとぽち"
```

ここで注意したいポイントが２つあります。
まず１つめは、**キー名は格納されるテーブルのカラム名と同じ**であること。
カラム名とキー名が一致しないと、情報を渡したり取り出しができずにエラーとなってしまいます。

またコントローラがparamsメソッドで取りだした情報は、ビューで表示されます。
ビューは見た目を担当する部分なので、html.erbファイルで記述されますよね。
ということは、html.erbファイル内でキー名を指定する必要があります。
そのため**HTML内で属性名を正しく指定できているか**が２つめのポイントになってきます。

html.erbで属性値を間違えてしまうと、コントローラは
「え？そんなキーないし情報出せないよ？」
と情報を呼び出せず、エラーを起こしてしまいます。

--
今回はparamsメソッドの説明と一緒に、気をつけるべきエラーについても書いてみました。
実際のエラー文を解決しながら学習すると「あ、この部分がおかしいから具体的にこういう動きしていたんだな」と気付きが多く、とても勉強になります。
理解するまでは気が遠くなりそうですが、頑張ろうと誓ったもそでした。続く。
中間テーブルとのアソシエーションでエラーが出る。

##エラー内容
has_many throughでなんとかなんとかって出てくる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/297896/d5c7ba3c-7482-bfd8-f5a3-7f0fb5c2ecc1.png)


##エラー元のソースコード

```ruby:group.rb
class Group < ApplicationRecord
  has_many :users, through: :group_users
  has_many :group_users
end
```

##原因と考えられるもの
エラー文から`group_users`が中間テーブルのアソシエーションの後に来てることが原因だと考えた。

##解決コード

```ruby:group.rb
class Group < ApplicationRecord
#group_usersのコードをthroughの前に持ってくる。
  has_many :group_users
  has_many :users, through: :group_users
end
```
Apacheのインストール

ソースコードからApacheをインストールしてみました。
※2018.05にインストールした際の手順です

Apache：[http://httpd.apache.org/](http://httpd.apache.org/)　《Ver.2.4.33》
APR：[http://apr.apache.org/download.cgi](http://apr.apache.org/download.cgi)　《Ver.1.6.3》
APR-util：[http://apr.apache.org/download.cgi](http://apr.apache.org/download.cgi)　《Ver.1.6.1》


## Apacheのダウンロード

```bash:
$ wget http://ftp.jaist.ac.jp/pub/apache//httpd/httpd-2.4.33.tar.gz
```

## Apacheの解凍 
ダウンロードしたファイルを解凍して、解凍後、作成されたディレクトリに入る

```bash:
$ tar -xvzf httpd-2.4.33.tar.gz
$ cd httpd-2.4.33
```

## APR・APR-utilのダウンロード・解凍
Apacheと同様の手順

```bash:
# APR
$ wget http://ftp.jaist.ac.jp/pub/apache//apr/apr-1.6.3.tar.gz
$ tar -xvzf apr-1.6.3.tar.gz

# APR-util
$ wget http://ftp.jaist.ac.jp/pub/apache//apr/apr-util-1.6.1.tar.gz
$ tar -xvzf apr-util-1.6.1.tar.gz
```

## APRとAPR-utilを/srclib/の中に移動
Apacheをmakeする際に一緒に自動でコンパイルされるため、`/srclib/`配下に解凍したものを置くだけでOK!

```bash:
$ mv apr-1.6.3 /home/erina/httpd-2.4.33/srclib/apr
$ mv apr-util-1.6.1 /home/erina/httpd-2.4.33/srclib/apr-util
```

## コンフィグ,コンパイル,インストール
マシンの環境にあわせたMakefileを生成した後、コンパイルを行い、実行ファイルを作成

```bash:
$ ./configure --with-included-apr
$ make
$ make install
```
※`libiconv`が邪魔してmakeがエラーの場合は以下を実行後コンフィグ

```bash:
$ rm /usr/local/include/iconv.h
$ make distclean
$ ./configure --with-included-apr
$ make
$ make install
```
## Apacheの起動・停止・再起動
Apacheのある階層で実行する
### 起動
```bash:
$ /usr/local/apache2/bin/apachectl -f /usr/local/apache2/conf/httpd.conf
# http://xx.xx.xx.xx(IPアドレス)/ で「It Works!」の画面が表示されたらOK！
```
### 停止
```bash:
$ /usr/local/apache2/bin/apachectl stop
```
### 再起動
```bash:
$ /usr/local/apache2/bin/apachectl restart
```
Visual Studio CodeのFix JSONでJSONを書くストレスを減らす

地味にちゃんと書くのがストレスになるのがJSONです。プロパティ名もダブルクオートで括ったり、最後の要素にカンマをつけてはいけなかったり。

フォーマットに気を使っていると思考の妨げになります。

そこでおすすめしたいVisual Studio Codeの機能拡張が[Fix JSON](https://marketplace.visualstudio.com/items?itemName=oliversturm.fix-json)です。

なんとなくJSONっぽい構造テキスト(`Jsonic`)を書いて、`Fix JSON`を実行するとキレイなJSONに整形してくれます。

↓公式ページから引用

![Fix JSON](https://github.com/oliversturm/vscode-fix-json/raw/master/images/run.gif)

最初だけでなく、一回整形されたJSONも、JSON風にラフに修正して`Fix JSON`すると整形してくれます。

ファイルの一部のみがJSONという場合も、範囲選択をすれば整形してくれます。

この拡張機能でJSONを書くことがだいぶ楽になったのでご紹介でした。
node-v57-linux-x64-glibcがなんちゃら〜ってエラーが出た時の解決方法

主に自分用のメモなので、時系列と解決方法だけ書きます。
エラーをコピーすることもできていないｗ（下の似たような現象が起きているページとだいたい同じだった。）

下記の記事どおりに進めていたら、accountのページが表示できず、、

https://qiita.com/redshoga/items/da5c0e247e0df314a257

似たような現象が起きているだろう下記のページを参考に消して再インストールとかしても解決せず、、、

https://stackoverflow.com/questions/49758008/nodejs-error-failed-to-load-grpc-binary-module-because-it-was-not-installed-fo
https://github.com/grpc/grpc-node/issues/97

とにかく、こいつがなんか怪しそう・・・
`node-v57-linux-x64-glibc`

たどり着いた記事がこちら。

https://stackoverflow.com/questions/50479816/node-v57-linux-x64-glibc-grpc-node-node-missing-when-using-clasp-on-linux/50493985

ここに書かれていたとおりにやったら、（cdのパスは自分のエラーに表示されていたやつに変更して）

```
cd /usr/local/lib/node_modules/grpcc/node_modules/grpc/src
sudo npm --unsafe-perm install
```

これで解決した！！
[C# Tip] 1ステイトメントには1変数宣言

開発チーム用、社内メモ

わかりずらいので、ローカル変数は１行ずつちゃんと指定してくださいまし。

```csharp

public class YourBadCode
{
   private string name1, name2;
}

public class MyGoodCode
{
   private string name1;  // name for 1
   private string name2;  // name for 2
}
```
WebViewでYoutubeを再生中にバックグラウンドにするとどうなるか？

## 実験内容
WebViewでYoutubeを再生中にバックグラウンドにするとどうなるか？

### 手順
1. アプリのWebViewでYoutubeを再生する
2. 端末のホームボタンを押す（アプリがバックグラウンドになる）
3. ブラウザのYoutubeが停止するか？

期待値は、バックグラウンドで動画の再生が止まり、音もならない

## 結果
**OS4系のみバックグラウンドでも動画は止まらず、音声が流れ続けた。**
しかも電源を押して端末をスリーブ（画面OFF）にしても音が流れ続けた！

機種は Galaxy S3α

OS５以上はバックグラウンドにすると勝手に再生が止まった。

## 対応策
WebViewを実装ときは `webView.onResume()` と ` webView.onPause()` をちゃんと書こう！

こんな感じで

```kotlin

    override fun onResume() {
        super.onResume()
        webView.onResume()
    }

    override fun onPause() {
        super.onPause()
        webView.onPause()
    }
```

これを実装してOS４系で、Youtubeを再生してバックグラウンドにすると動画再生が止まり、音がならなくなった！

## onResume/onPauseを実装しないとどうなるか？
Googleから「Youtbeの規約を守らなかった」とみなされ、Playストアからアプリが削除される。

WebViewで動画を表示するさいは気をつけましょう！

## 実験に使用したコード
https://github.com/ikemura23/Android-Kotlin-Lab/blob/webview-onResume-onPause/app/src/main/java/com/ikemura/android_kotlin_lab/webview/WebViewFragment.kt
GPU(NVEnc)対応FFmpegのポータブルなDockerfile

# TL;DR

* NVEnc(NVIDIAのGPU)対応のFFmpegのDockerfileを作成し，シングルタスクのコンテナでポータブルなエンコード環境を作りました
    * [作成済みのDockerfile](https://github.com/myoshimi/ffmpeg-nvenc) をGithubで公開しています
    * nvencを含むバイナリファイルは再配布禁止なので，自分でDockerイメージをビルドして使用します
* Dockerコマンドでffmpegの処理を呼び出せる，快適なエンコード環境を整えます
    * ```docker run``` コマンドに，入力ファイルとオプションを指定して実行することで，動画の処理を実現します

# 準備

* nvidiaのGPUを搭載したDockerホスト（Dockerを動かすマシン）
* nvidia-docker2がインストールされたDocker環境
    * [docker-ce](https://qiita.com/myyasuda/items/cb8e076f4dba5c41afbc)と[nvidia-docker2](https://github.com/NVIDIA/nvidia-docker#quickstart) をインストールしておく
    * AWS EC2 g3s.xlargeで動作テストをしています

# 使い方

## Dockerイメージ ffmpeg-nvenc のビルド

* ffmpeg-nvencのDockerイメージをビルドします．
    * 初回のイメージビルドは時間が掛かります（20分くらい）．一度イメージを作ってしまえば，Dockerのキャッシュが効くので再実行しても高速に終わります．

```bash
git clone https://github.com/myoshimi/ffmpeg-nvenc
cd ffmpeg-nvenc
sudo docker build -t ffmpeg-nvenc .
```

## エンコード実行の例

[blender](https://www.blender.org/)で作られたクリエイティブ・コモンズの動画[Big Buck Bunny](https://peach.blender.org/)をエンコードする手順です．以下のコマンド例では， [BBB Sunflower version](http://bbb3d.renderfarming.net/download.html)の1080p60fpsの動画を使用しています．

```bash
# カレントディレクトリにある動画ファイル（bbb_sunflower_1080p_60fps_normal.mp4）を，
# GPUでh.265エンコードします．
# 実行後のファイルがbbb_sunflower_1080p_60fps_normal_h265.mp4として作られます．
docker run --rm --runtime=nvidia \
    -v ${PWD}:/tmp/ ffmpeg-nvenc:latest \
    -stats \
    -i /tmp/bbb_sunflower_1080p_60fps_normal.mp4 \
    -vcodec hevc_nvenc \
    /tmp/bbb_sunflower_1080p_60fps_normal_h265.mp4
```

コマンドのキモは，（動画ファイルがある）カレントディレクトリを不揮発ボリューム```/tmp```としてffmpeg-nvencコンテナがマウントして，ffmpegコマンドの入力ファイルとして使用することです．

その他のオプションは以下のとおりです．
Dockerイメージ指定(ffmpeg-nvenc:latest)より前はdockerのオプション，イメージ指定より後はffmpegのオプションです．

|オプション|オプションの対象|効果|
|-------|-------|---|
|--rm   |docker|状態が終了(exited)になったらコンテナを削除する|
|-v     |docker|コンテナがマウントする場所（カレントディレクトリ）を指定する|
|-stats |ffmpeg|処理の進行状況を標準出力に表示する|
|-i     |ffmpeg|入力動画ファイル（コンテナがカレントディレクトリを/tmpにマウントしているので，コンテナから見たとき，/tmpがホストのカレントディレクトリになる)|
|-vcodec|ffmpeg|ビデオコーデックの指定（後述）|

# vcodecの指定

vcodecオプションを変更すると，コーデックを変更できます．

| Processor | codec | -vcodec    |
|-----------|-------|------------|
| CPU       | H.265 | libx265    |
| CPU       | H.264 | libx264    |
| GPU       | H.265 | hevc_nvenc |
| GPU       | H.264 | h264_nvenc |

# Dockerfileでやっていること

[nvidia/cuda:10.0-devel-ubuntu18.04](https://hub.docker.com/r/nvidia/cuda)をベースに，必要なライブラリをインストールし，ffmpegをビルドしています．

Dockerfile内でビルドしているライブラリは以下の通りです．

* NASM
* YASM
* libx264
* libx265
* libvpx
* libfdk-aac
* libmp3lame
* libopus
* nv-codec-headers

# 参考

* https://github.com/myoshimi/ffmpeg-nvenc
* [Ubuntu 18.04にDockerをインストールする](https://qiita.com/myyasuda/items/cb8e076f4dba5c41afbc)
* [github NVIDIA/nvidia-docker](https://github.com/NVIDIA/nvidia-docker#quickstart)
yum-cronを使おう

# 勝手にyum updateさせたい！
趣味でちょこちょこっと触るさくらVPS。
なんかやらかして停止するのは何も実害がない（かえって勉強になる）が、パッケージが古いまま放置されてはセキュリティ上問題があるかもしれない。
そこで自動でyum updateしてもらえるyum-cronを導入しよう。
OSはCentOS 7.6。

本番系サーバーではバージョンが変わることによって障害が起きたりするといやので設定していない。

# 導入
さあ！
## インストール
yum一発である。

```bash:console
[root@xxxxx ~]# yum -y install yum-cron
```

## 設定ファイルを編集
一行変えるだけである。

```bash:console
[root@xxxxx ~]# cp -p /etc/yum/yum-cron.conf /etc/yum/yum-cron.conf.org
[root@xxxxx ~]# vi /etc/yum/yum-cron.conf
[root@xxxxx ~]# diff /etc/yum/yum-cron.conf /etc/yum/yum-cron.conf.org
20c20
< apply_updates = yes
---
> apply_updates = no
```

## スタート、自動起動設定
教科書どおりの操作のみ。

```bash:console
[root@xxxxx ~]# systemctl start yum-cron
[root@xxxxx ~]# systemctl enable yum-cron
```
うほ！かんたん

# オプション：メール通知貰えるようにする
なんとyum-cron標準で、処理結果をメールしてくれる機能がある。
yum-cron.confに設定すると甲斐甲斐しくメールで報告くれるのだ。

```bash:console
[root@xxxxx ~]# vi /etc/yum/yum-cron.conf
[root@xxxxx ~]# diff /etc/yum/yum-cron.conf /etc/yum/yum-cron.conf.org
20c20
< apply_updates = yes
---
> apply_updates = no
41c41
< emit_via = email
---
> emit_via = stdio
51c51
< email_from = root@example.com
---
> email_from = root@localhost
[root@xxxxx ~]# systemctl restart yum-cron
```
root@example.comのところは自分の持ってる適切なアドレスにしてね。
macOS Mojaveでpyenvを使ったPythonのインストール時に出るZipImportErrorの回避方法

# はじめに

macOS Mojaveでpyenv経由でPythonをインストールしようとすると次のような`ZipImportError`が発生します。

```shell-session
$ pyenv install 3.7.2
python-build: use openssl from homebrew
python-build: use readline from homebrew
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...
python-build: use readline from homebrew

BUILD FAILED (OS X 10.14.3 using python-build 1.2.9-19-g7d02b246)

Inspect or clean up the working tree at /var/folders/zd/wbvzn4ls3_xbtv033b0mp3hw0000gn/T/python-build.20190322153042.29836
Results logged to /var/folders/zd/wbvzn4ls3_xbtv033b0mp3hw0000gn/T/python-build.20190322153042.29836.log

Last 10 log lines:
  File "/private/var/folders/zd/wbvzn4ls3_xbtv033b0mp3hw0000gn/T/python-build.20190322153042.29836/Python-3.7.2/Lib/ensurepip/__main__.py", line 5, in <module>
    sys.exit(ensurepip._main())
  File "/private/var/folders/zd/wbvzn4ls3_xbtv033b0mp3hw0000gn/T/python-build.20190322153042.29836/Python-3.7.2/Lib/ensurepip/__init__.py", line 204, in _main
    default_pip=args.default_pip,
  File "/private/var/folders/zd/wbvzn4ls3_xbtv033b0mp3hw0000gn/T/python-build.20190322153042.29836/Python-3.7.2/Lib/ensurepip/__init__.py", line 117, in _bootstrap
    return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/private/var/folders/zd/wbvzn4ls3_xbtv033b0mp3hw0000gn/T/python-build.20190322153042.29836/Python-3.7.2/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip._internal
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
```

# 解決方法

解決策としてmacOS SDK headersを`/`にインストールする方法が載っているサイトが多いのですが、そのインストールの手順は不要です。

既にヘッダーファイルは存在するため、`CFLAGS`にmacOS SDK headersのパスを渡してあげればよいです。

```shell-session
$ CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install 3.7.2
```

# 参考

https://github.com/pyenv/pyenv/issues/1219#issuecomment-429331397
C言語からOracle接続する

Linux C言語からOracleへ接続する方法がないか調べたので自分用にメモして残します。

## 今使ってるのは…
Pro*Cを使って、接続･CRUD操作しています。
プリコンパイルが必要なくらいで、書き方もわかりやすく作りやすいです。

## では何故調べているか
警告オプションを付けるとすごいんです。
出力される量がorz
生成部分の指摘が多く、手が出ません。

また、SQL調整するにもコーディングになるので要件対応や保守になるとメンテナンスが苦しい。(めんどくさい)
SQLを実際に発行して実験してから直す感じになるので、もう少しスマートに作成、調整がしたいんです。

## 他に知ってるのは？
OCIでコーディングしているのを見た事があります。
使おうと思った時にはインストールされていなかったのもありますが、コーディングがPro*Cに比べてかなり複雑だったのも、引いてしまった理由になります。

## では、実際に使える方法は何がある？
まずはグーグル先生に聞いてみました。
そしたらミドルウェアの一覧を掲載しているページがありました。
http://www.doppo1.net/oracle/middleware.html

ここから見るとLinux-C言語で対応できるのは

- OCI
- Pro*C
- ODBC

ODBCを使ったC言語サンプルってのが見たことない。
Oracleで直接いろいろ探したほうが見つかるかも？
ODBCサンプルあるかもしれないし、OCIサンプルのチェックと合わせて
Oracleのページを散策

Oracle Call Interface
https://www.oracle.com/jp/database/technologies/appdev/oci.html

お、これだこれだ。
とページを読んでいくと
> **「Oracle Database Programming Interface for C (ODPI-C)」**
Oracle Database Programming Interface for C (ODPI-C) is a new open source library of C code that simplifies the use of common OCI features for Oracle Database drivers and user applications.

###なに？
これは、自分が探している答えなのではないか？

OracleのODPIページ
https://oracle.github.io/odpi/
お、ドキュメント・サンプルがありますね。
インストール手順も書いてある。
ソース？GitHubだと？

oracle/odpi
https://github.com/oracle/odpi
こっちのほうが新しいし！
READMEがOracleのページ内容と同じですね。GitHubだけチェックすればよさそう。

残念ながらODPI-Cを使っている日本語記事は見つからなかったけど
これは十分試す価値がありそうなものを見つけました。

機会を得ることができたら、ODPI-Cで作成してみます
Djangoの使い方～デプロイ編①～

##はじめに
[Djangoの使い方～オブジェクト作成編～](https://qiita.com/connecrew-sugiyama/items/2471ee5b06d8c53c6a53)の続きです。
今回は前回作成したログイン画面からログインする方法と、
デプロイの準備までやります！

##ログイン方法
ログインするにはユーザーを作る必要があります。
コマンドラインでpython manage.py createsuperuserを入力します。

```ruby:command-line
(myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser
```

こんな感じで作ります。入力中はパスワードが見えませんが大丈夫です。

`Username: admin
Email address: admin@admin.com
Password:
Password (again):
Superuser created successfully.
`

ブラウザに戻って作成したユーザーでログインします。
こんな画面が出ます。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/376013/723a08ea-a996-21da-ef39-93e1f9252239.png)

PostsのPOSTを追加から2~3個公開記事を作ってみましょう。

##デプロイの準備
Gitリポジトリを始める
コンソールを開き、djangogirlsディレクトリで下のコマンドを実行します。

```ruby:command-line
$ git init
Initialized empty Git repository in ~/djangogirls/.git/
$ git config --global user.name "Your Name"
$ git config --global user.email you@example.com
```

ベースディレクトリ内で .gitignore という名前のファイルを作成します。
次の内容で新しいファイルを作成して下さい。

```ruby:.gitignore
*.pyc
*~
__pycache__
myvenv
db.sqlite3
/static
.DS_Store
```

 "djangogirls" フォルダ内に .gitignore という名前で保存して下さい。


ドット「.」から始まるファイル名の作成方法が分からない方は下記参照して下さい。
[Windowsエクスプローラーでドットファイルを作成する](https://qiita.com/sgur/items/745e0ee02c69b50bf9e5)


変更を保存するためにコンソールで下のコマンドを実行します。

```ruby:command-line
$ git add --all .
$ git commit -m "My Django Girls app, first commit"
 [...]
 13 files changed, 200 insertions(+)
 create mode 100644 .gitignore
 [...]
 create mode 100644 mysite/wsgi.py
```

##GitHubにコードをプッシュする
Githubで "my-first-blog"というリポジトリを新規作成します。
左側にあるNewを押してください。
"READMEで初期化する"チェックボックスをオフのままにし、.gitignoreオプションを空白にして、ライセンスをNoneのままにしておきます。
![github1.PNG](https://qiita-image-store.s3.amazonaws.com/0/376013/fc1660ed-c0aa-4e37-151d-4097c103e368.png)
これでcreate repositoryしましょう。
![github2.PNG](https://qiita-image-store.s3.amazonaws.com/0/376013/05b1928a-7ac4-a1b0-22b3-419a7070e523.png)
リポジトリをクローンするためのURLがでてきます。これは次で使います。

自分のコンピューター上のGitリポジトリをGitHub上のGitリポジトリに結びつけます。
コンソールに次のように入力します。このURLは上の画像のURLと一緒にして下さい。

プロキシがある場合はコマンドラインで
```git config --global http.proxy http://[proxy_host]:[proxy_port]
```を行ってから下記を行ってください。

```ruby:command-line
$ git remote add origin https://github.com/<your-github-username>/my-first-blog.git
$ git push -u origin master
```

GitHubのユーザー名とパスワードを入力すると、次のように表示されます

```ruby:command-line
Username for 'https://github.com': ola
Password for 'https://ola@github.com':
Counting objects: 6, done.
Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)

To https://github.com/ola/my-first-blog.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
```

これでコードがGitHub上にプッシュされました。

##おわりに
次はpythonanywhereを使ってデプロイします！
次回→[Djangoの使い方～デプロイ編②～](https://qiita.com/connecrew-sugiyama/items/5080052e564334672bd6)
Tableau Prep Builder の使い方 - Index 列 (行 ID 列) を追加する

#製品名称が変わりました。新たな名称は Tableau Prep Builder です。
Tableau Server 2019.1 がリリースされたタイミング (2019 年 2 月) で Tableau Prep で作成された flow が Tableau Server 上にパブリッシュ可能になりました。このアップデートを機に、製品名称が変わっています。これまで Tableau Prep と呼んでいたものは Tableau Prep Builder という名称に変わりました。Tableau Prep Builder 2019.1.2 のバージョンから名称変更となります。
なお、Tableau Server 上で flow を管理、動作する機能は Tableau Prep Condutor と呼ばれ、Tableau Data Management Add-on と呼ばれる新ライセンスで利用できる機能群の一部となります。
https://www.tableau.com/ja-jp/pricing/teams-orgs

#Index 列 (行 ID 列) の追加
##やりたいこと
さて、本題に入りたいと思いますが、実現したいのは以下の例です

|製品|売上|
|---|---|
|A|20|
|B|50|
|C|70|
|D|90|
このテーブルを売上順にソートして、一意な列 (=Index) を追加してあげます。

|Index|製品|売上|
|---|---|---|
|1|D|90|
|2|C|70|
|3|B|50|
|4|A|20|

##Tableau Prep Builder の機能で一発で実現できるか
残念ながら Tableau Prep Builder では現状 Index 列を追加するための機能はありませんし、表計算関数など一部の関数もサポートされておりません。
Tableau の Idea サイトでは既に多くの機能拡張要望が来ていることから、実業務でのニーズが高いものと思われます。早く実装されてほしいです。
[idea] Add Record ID / Index feature in Tableau Prep
https://community.tableau.com/ideas/8714
[idea] Tableau Prep: Add Table Calculations - especially Index() and PreviousValue()
https://community.tableau.com/ideas/8732

##じゃあ、どうするか
Tableau Prep Builder の標準機能を組み合わせて実装します。
まず、計算フィールドを作成して列を結合します。STR 関数は数値を文字列型に変換してくれます。ソートキーという名前にしておきましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/41e4a170-6934-626a-49ee-d34fe6b539e1.png)
つぎに、ステップを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/e93ea74c-66e8-d200-afc9-21ca86563e12.png)
わかりやすいように色分けしておきましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/54d5453c-c369-de6e-7eed-99f037de56b8.png)
ここで、クリーニング 2 をクリーニング 1 の右側にドラッグアンドドロップして 結合 (JOIN) します。これらは同じテーブルなので、いわゆるセルフジョインをしていることになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/702fae3f-2cda-b0be-cb94-7ceb4056b2b0.png)
結合句を以下のように指定します。この結合条件に沿って行が増幅されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/6476bc48-3163-a2de-d5d3-a4fff9e3eaa1.png)
結合した結果は以下の表のようになります。あとはソートキー列でカウント取ってあげれば、一意の Index 列を追加できそうな感じがしますね。

|ソートキー|製品|売上|
|---|---|---|
|20A|A|20|
|20A|A|20|
|20A|A|20|
|20A|A|20|
|50B|B|50|
|50B|B|50|
|50B|B|50|
|70C|C|70|
|70C|C|70|
|90D|D|90|
集計の追加
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/9f2e2c26-ced3-e283-1287-c1b28cf36766.png)
製品、売上 を "グループ化したフィールド" に。ソートキーを "集計フィールド" に入れてカウントします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/204b4f46-602d-dddc-4282-d8d353264223.png)
右クリック -> フィールド名の変更 で 名前を Index としておきましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/050b41f2-5742-0d01-1ad1-c92b1e2d57b6.png)
出力の追加
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/7291c143-f5a1-e9e3-613c-5dd3ca47a873.png)
無事に欲しい形のアウトプットが作成できました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246284/a2f41004-e444-10ce-10a9-d8d9e07b819e.png)

#まとめ
正直いって、こんなことやらずにボタン ポチっとレベルで実現できてほしいところですが、それは今後の製品アップデートに期待しましょう。
なお、この方法だと途中のステップで行が増幅されるので、大量データで同じことをやる場合はくれぐれもご注意ください。

#参考サイト
Creating unique Row IDs in Tableau Prep
http://technowhisp.com/2018/12/11/tableau/creating-unique-row-ids-in-tableau-prep/
UE4　C++　参照クラスのポインタ取得

他のクラスの変数を参照したいのですが、UE4をPLAYすると該当する参照ポインタがnullだと怒られます。
プログラムでは、確かに参照するポインタに何も設定していないように見えます。
そこで、参照するポインタに設定するようコンストラクタでコードを書きたいのですが、どのように描いたいいか
UE4もC++も初心者のためわかりません。

以下に参照する側のソースファイルを記述します。
参照される側については、通常のメンバ変数と記述しているだけです。
	UPROPERTY(EditAnywhere, category = "Countdown")
	int32 CountdownTime;

参照する側
AMyActor::Tick(float DeltaTime)メソッドにて
	if (Countdown->CountdownTime < 1) {
　　　　　　;
	}
で、他のクラスのメンバ変数を参照していますが、Countdownがnullだと怒られます。
確かにCountdownは、設定していませんので、コンストラクタで設定しようとしています。


どなたかお教えください。




以下参照する側ソースファイル
ヘッダーファイル MyActor.h
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class HOWTO_VTE_API AMyActor : public AActor
{
	GENERATED_BODY()

public:	
	// Sets default values for this actor's properties
	AMyActor();
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(EditAnywhere)
	class ACountdown* Countdown;               //参照される側のクラスポインタ定義

};

コードファイル MyActor.cpp
#include "MyActor.h"
#include "Countdown.h"

//	ACountdown cnt;

// Sets default values
AMyActor::AMyActor()
{
	PrimaryActorTick.bCanEverTick = true;
//??	Countdown = CreateDefaultSubobject<ACountdown>("Countdown");
//??	Countdown = (ACountdown*)GetDefaultSubobjectByName("Countdown7");
}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{

//	Super::Tick(DeltaTime);

	if (Countdown->CountdownTime < 1) {
　　　　　　　;
	}
}
phpでkindleの情報を収集する

##リンクの取得
```php
  <?php
    require_once("./phpQuery-onefile.php");
    $html = $header = 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36';
    $options = array('http'=> array('header' => $header));
    $ctx = stream_context_create($options);
    $html = file_get_contents("https://www.amazon.co.jp/s/ref=sr_nr_n_0?fst=as%3Aoff&rh=n%3A2250738051%2Cp_36%3A20000-40000%2Cn%3A%212250739051%2Cn%3A2275256051%2Cn%3A2293143051%2Cn%3A2430812051&bbn=2293143051&ie=UTF8&qid=1552806492&rnid=2293143051",false,$ctx);


    #ここでhtml全文を取得している
    $phpobj = phpQuery::newDocument($html);

    #hタグを取得
    #複数のクラスがあるなら、すべて記述しないと取ってこれない
    $headers = $phpobj["li[id^='result_'] a[class='a-link-normal s-access-detail-page s-color-twister-title-link a-text-normal']"];

    #attr("href")でリンクを取得
    #attr("title")でタイトルを取得
    foreach ($headers as $header) {
      echo pq($header)->attr("href")."<br>";
      echo "-------------------------------<br>";
    }

  ?>
```
id^='result_'は先頭行を一致させている。result_0など後に数字が着ていれば、データを取得する。正規表現みたいなもの。
kindleのaタグにはいろいろクラスがついているが、一つだけを指定しただけじゃ情報は取得できない。つけられているクラスの情報をすべて指定することで、全部取ってこれる。
【エンジニアから見た、デザイナとエンジニアとの意識の違いと共通点】 #hedgehogs #共創LT

# 要約

- 非エンジニアから普段「細かい」とよく言われるエンジニアの自分ですら、デザイナの意見には「細かい」と思うところがあった。しかし、それはとても大事な細かさなのだ。
- 仕事の目的や、最終的な理想とするところは、デザイナでもエンジニアでも同じなのだと分かって心強く思った。

# 本文　
先日、[「デザイナー × エンジニア = ∞」を実現するために僕らがやれること](https://noengineering-nolife.connpass.com/event/121305/)と題したイベントに参加してきました。

自分はサーバサイドをメインに担当するプログラマですが、以前自社サービスを開発したときにフロントの担当者が作成したHTML,CSSを組み込む機会がありました。

そのプロダクトは結果として、あまり好ましいものにはなりませんでした。

また、そもそも、**作っても使ってもらえずに機能を削除する**こともままあり、エンジニアとしては辛い思いもしました。

そこで、ユーザの使い勝手に直結するUIデザインの領域にいる人の話を聞くことで、何か改善のヒントになればと思い参加しました。

結果としては、とても良い経験が出来ました。主催の方にはとても感謝しています。
自分の意見としては上記にまとめましたが、詳細は以下となります。

## 非エンジニアから普段「細かい」とよく言われるエンジニアの自分ですら、デザイナの意見には「細かい」と思うところがあった。しかし、それはとても大事な細かさなのだ。
以前、余白やデータの段組みなどが当初のデザインと仕上がったUIとで少しでも異なった場合にとても残念がっていたデザイナさんを拝見したことがあります。

その当時は「こまかいところまで気にし過ぎなんじゃないの？」と思っていましたが、イベントでデザイナさんの発表を聞いてそれは間違っていたんだと分かりました。

たんなる拘りではなくて、それはきちんと**デザインの原理原則に則ったもの**だということがわかったからです。それも、何度も何度も試行錯誤して、ようやく出来上がったデザインなんだと。

領域は違っても、その思いは共感できました。

エンジニアがソフトウェア工学に則って簡潔なコードを削り出す情熱と同じように、**デザイナが身を削り出して磨き上げたその1px**に対して、エンジニアはきちんと意味を理解する責任があると思いました。

## 仕事の目的や、最終的な理想とするところは、デザイナでもエンジニアでも同じなのだと分かって心強く思った。
自分はプログラマとして、機能に対する目的を確認するように日ごろ意識しています。
つまり、「何のためにやるのか」ということです。

ソフトウェアは目に見えないし、手に取って触感を確認することもできません。誰のどんな問題を解決したいのか分からないと、見当違いなものが出来上がります。使ってももらえない。

これはとても辛いことです。

デザイナさんも、認識齟齬が引き起こす問題については同じ意識を持っているように思いました。

その解決のための取り組みとして、

- 実装前に、動きまで含めたプロトタイピングで製品の目的を意思疎通しようと試みる
- クリティティブブリーフ（なんのために、だれに、なにをするのか？をまとめた資料。）を作って誰でも見れるようにしておき、実装する前の認識のズレを防ごうとする

といったことが紹介されていました。

ソフトウェア開発にも共通することですが、「**なるべく可視化して全員が見て取れる状況にしておく**」というのはとても大事なことです。

特にデザインは目に見えるものを作るので、**成果物に対する目的意識を可視化する**ことに強いプロフェッショナリズムを感じました。目に見えるからこそ、目的意識を持たないと「見える」ことに騙されて本質が見えなくなってしまうのではないかと。

「見える化」というのは良く聞く言葉ですが、デザイナにとってのそれには、「目的とその手段について、本質まで踏み込んで可視化する」という意識の高さがあると思いました。

情報に優先順位をつけて重要なものを見えやすいように配置することは、自分には意識が及ばないことでした。

## 最後に
エンジニアとデザイナでは、共感できるポイントがいくつもあることが分かりました。
また、懇親会で話をさせてもらい、どちらも良い仕事をするために、お互いを分かり合いたいという思いも強くあることがわかりました。

これには、とても勇気を貰えました。

これからは、デザインに対する原理原則の理解を深めていこうと意識しましたし、
専門分野の垣根を越える工夫として、普段は見えないものへの興味を積極的に持っていこうと思いました。
DBの整合性チェックを制約ではなくコードでやる発想

||DB制約|DB整合性チェックをコードでやる|自動テスト|
|:-:|:-:|:-:|:-:|
|テスト対象|データ|データ|ロジック|
|変更容易か？|×|○|○|

データに対するテストはロジックに対するテストで検出できないバグを検出可能です。
例えば、銀行で、全ての口座のin out、全てのATMのin outの合計が0になるというテストは、口座とATMに関する多くのロジックをテストできます。

銀行ならシステムの変更頻度が低いので(実際どうかしりませんが)、DB制約でもいいかもしれませんが、ウェブサービスのように変更頻度が高い場合、DB制約だと保守性が悪くなります。

かといって、自動テスト + カバレッジ100%だと、テストケース漏れを防げません。

そこで、DB整合性チェックを用意して、本番DBをチェックしておけば、良いのでは？