OmniAICreator/Qiita-1.07M huggingface dataset:
gitlabとazure-adを連携する

gitlabとAzureAD連携できたのでその備忘録です。

####・AzurePortal側の設定

AzureADの画面からアプリの登録を実施

名前：Gitlab
タイプ：WebAPI
URL：`https://your-gitlab-url/`

アプリケーションIDを控えておく

設定から応答URLを追加
`https://your-gitlab-url/users/auth/azure_oauth2/callback`

権限を付与ボタンを押した

キーから鍵を追加

キーを登録した内容を控えておく（入力したパスワードが変換されてでてきたトークン）

アプリの登録の画面からエンドポイントを確認

####・gitlab側の設定

以下のとおり設定。

```
# cd /etc/gitlab
# cp -p gitlab.rb{,.`date +%Y%m%d`}
# ls
gitlab.rb           gitlab.rb.20180508  gitlab.rb.20180614   trusted-certs
gitlab.rb.20180501  gitlab.rb.20180518  gitlab-secrets.json
# vi gitlab.rb
# diff gitlab.rb{,.`date +%Y%m%d`}
171,172c171,172
< gitlab_rails['omniauth_enabled'] = true
< gitlab_rails['omniauth_allow_single_sign_on'] = ['azure_oauth2']
---
> # gitlab_rails['omniauth_enabled'] = false
> # gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
174,175c174,175
< gitlab_rails['omniauth_block_auto_created_users'] = true
< gitlab_rails['omniauth_auto_link_ldap_user'] = true
---
> # gitlab_rails['omniauth_block_auto_created_users'] = true
> # gitlab_rails['omniauth_auto_link_ldap_user'] = false
177,189c177,185
< gitlab_rails['omniauth_external_providers'] = ['azure_oauth2']
< gitlab_rails['sync_profile_from_provider'] = ['azure_oauth2']
< gitlab_rails['sync_profile_attributes'] = ['name', 'email']
< gitlab_rails['omniauth_providers'] = [
<   {
<     "name" => "azure_oauth2",
<     "args" => {
<        "client_id" => "****アプリケーションID****",
<        "client_secret" => "****アプリで登録したキー*****",
<        "tenant_id" => "****AADのディレクトリのID****",
<     }
<   }
< ]
---
> # gitlab_rails['omniauth_external_providers'] = ['twitter', 'google_oauth2']
> # gitlab_rails['omniauth_providers'] = [
> #   {
> #     "name" => "google_oauth2",
> #     "app_id" => "YOUR APP ID",
> #     "app_secret" => "YOUR APP SECRET",
> #     "args" => { "access_type" => "offline", "approval_prompt" => "" }
> #   }
> # ]

# gitlab-ctl reconfigure
# gitlab-ctl status
```
※omniauth_block_auto_created_usersをtrueにしてるのでデフォだとブロックされて管理者が解除する必要がある仕様。

####ユーザのログイン
で、自分のアカウントセッティングする画面からazureっぽい窓マーク（connect）と書いてあるのをポチっとして
![gitlab-azuread-connect-mask.png](https://qiita-image-store.s3.amazonaws.com/0/25031/ea0913c2-3458-88dc-417d-4ff7ab8c6d19.png)

サインアウトすると
窓マークが出てるのでぽちっとするとログインできるようになりました。
（二段階認証設定してあるなら入れる必要有）
認証の手段が一個増えただけって感じですね。AzureAD側で認証してあるならID/PW入力が不要なとこが便利に。
既存使い続けるで問題ないならなにもしなくても大丈夫。

####参考
https://docs.gitlab.com/ce/integration/azure.html
https://docs.gitlab.com/ce/integration/omniauth.html#initial-omniauth-configuration
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/active-directory-protocols-oauth-code
https://serverfault.com/questions/874484/gitlab-and-oauth-to-azure-ad
Djangoのテスト時に "ValueError: Missing staticfiles manifest entry" が起きたら

エラーの原因と回避方法は「[[Django]DjangoのテストをDEBUG=Trueで実行する](https://qiita.com/tnnsst35/items/cbe06d81bc8fb3c9c4ab)」と同じです。状況が少し違ったので、新たな記事を書くことにしました。

# エラーが起きた状況

Django 2.0 での開発中、`manage.py test myapp` を実行したところ、静的ファイルが見つからずにエラーになってしまいました。

```console
$ python manage.py test my_app
Creating test database for alias 'default'...
System check identified no issues (0 silenced).

(snip)

  File "/usr/local/lib/python3.6/site-packages/django/contrib/staticfiles/storage.py", line 422, in stored_name
    raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)
ValueError: Missing staticfiles manifest entry for 'my_app/css/default.css'

----------------------------------------------------------------------
Ran 1 test in 0.949s

FAILED (errors=1)
Destroying test database for alias 'default'...
```

settings.py では `DEBUG=True` を指定しており、ブラウザ上では該当の CSS ファイルが正しく参照できているので、最初は原因がわかりませんでした。

# エラーの原因

エラーの原因は、settings.py で `DEBUG=True` が指定されていても `manage.py test` すると `DEBUG=False` とみなされてテストが実行されるためでした。

`DEBUG=False` で実行されても静的ファイルが見つかるように `manage.py collectstatic` すればよいのですが、まだ開発中のため避けたいところです。

# エラーの回避方法

[Django 1.11 から追加された `--debug-mode` オプション](https://docs.djangoproject.com/en/2.0/ref/django-admin/#cmdoption-test-debug-mode) を指定すれば、`DEBUG=True` が指定されたものとして実行されます。

```console
$ python manage.py test --debug-mode my_app
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 1.501s

OK
Destroying test database for alias 'default'...
```

[チケット #27008](https://code.djangoproject.com/ticket/27008) で、このオプションの追加が議論されていました。
[Django] プロジェクト構成のベストプラクティスを探る - ５．ユーザーモデルに最小限のカスタマイズを入れる

##この記事について
Djangoで本番運用やチーム開発を行うに当たって、プロジェクトの初期構成にどのように手を入れたらよいかを、The Twelve Factorsなどを参考にまとめたメモです。

##参考

- [Django公式 ユーザーカスタマイズ方法](https://docs.djangoproject.com/ja/2.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project)
- [Django ユーザー カスタマイズ方法（自作記事）](https://qiita.com/okoppe8/items/10ae61808dc3056f9c8e)
-  [Two Scoops of Django 1.11] (https://www.amazon.co.jp/dp/0692915729)
- [現場で使える 基礎 Django（技術書典4バージョン）](https://booth.pm/ja/items/823251)

## 既存のユーザーモデルに手を入れる意味

Djangoのプロジェクトにはユーザーモデルが最初から定義されていますが、このユーザーモデルをそのまま使ってしまうと、データベース定義の関係で後からユーザー定義を拡張しづらくなるので、とりあえず最初にカスタマイズクラスを作ってしまうのがセオリーとされています。

参考：[Djangoでは常にカスタムUserを使用すべき](https://qiita.com/NAKKA-K/items/7627b6a22f364941b989)

また、デフォルトのユーザーモデルにいくつか問題があるので、合わせて最初から修正しておきましょう。

## デフォルトのユーザーモデルの修正点

### full_name を追加

英語圏以外の人にとってfirst_nameとlast_nameの方式は扱いに困ります。新たにfull_name（名前）という項目を作り、ユーザー登録画面ではfirst_name、last_nameを非表示にしてしまいましょう。これは「Two Scoop Of Django」で推奨しています。

### [任意] アクセス権限項目を非表示にする

「管理者権限（スーパーユーザー権限）」を使えば管理画面上で以下のアクセス制御が可能です。

- 管理者
 - ユーザー情報の編集を含む全機能が使える
- 一般スタッフ
 - アプリの利用と管理画面から自分のパスワード変更ができる

段階的な権限設定が必要ないなら「グループ」「ユーザー別パーミッション」の項目は無くてもいいので、ユーザー登録画面で非表示にしましょう。

### [任意] 「一般スタッフ権限」のデフォルトをTrueにする

[こちらの記事](https://qiita.com/okoppe8/items/54eb105c9c94c0960f14)で紹介したような利用者全員にスタッフ権限が必要なアプリでは、スタッフ権限のデフォルトをTrueにしてユーザー登録画面で非表示にしておく方が親切です。

上記の設定を反映させたのが以下のサンプルコードです。

## サンプルコード

★ 最初に「users」という名前のアプリケーションを新規追加する。

```python:config/settings.py

INSTALLED_APPS = [
    ...
    'users.apps.UsersConfig',
]

AUTH_USER_MODEL = 'users.User'
```

```python:users/models.py

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _

class User(AbstractUser):

    # 名前の追加
    full_name = models.CharField(
        verbose_name='名前',
        max_length=100,
        blank=True
    )

    # 既存メソッドの変更
    def get_full_name(self):
        return self.full_name

    # スタッフ権限のデフォルトをTrueに変更
    is_staff = models.BooleanField(
        _('staff status'),
        default=True,
        help_text=_('Designates whether the user can log into this admin site.'),
    )
```

```python:users/admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from .models import User

@admin.register(User)
class AdminUserAdmin(UserAdmin):

    # 変更前コードは django.contrib.auth.admin.py 参照

    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('full_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_superuser')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    list_display = ('username', 'email', 'full_name')
    search_fields = ('username', 'full_name', 'email')

```

```python:users.apps.py
from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'
    verbose_name = "ユーザー管理"
```
[学習用]Rubymineのデータベース画面でPostgresqlへ接続出来なくてハマったが解決できた流れ

![postgresql.PNG](https://qiita-image-store.s3.amazonaws.com/0/132580/ce997ea5-cbf6-ca8e-ec99-42dd42a23562.png)

コマンドからは接続できるし、起動も確認。
ウェブ画面からも書き込みできるに、Rubymineのデータベース接続画面から接続できなくて
ハマった話。

無事に解決できましたので、手順を忘れずに書いておきたい。


#1:postgresql.conf の修正
```
$ su postgres
Password:
$ vi /etc/postgresql/9.5/main/postgresql.conf
```

/etc/postgresql/9.4/main/postgresql.conf に上記の部分にあるコメントを解除して
変更します。

```
listen_addresses = '*'
port = 5432
```




#2:pg_hba.conf の修正
/etc/postgresql/9.4/main/pg_hba.conf に下記を追加します。
一番下の行に追加しました。

```
host all all 0.0.0.0/0 trust
```

#3:PostgreSQL 再起動
```
$ exit
$ sudo service postgresql stop
$ sudo service postgresql start
```

postgres から exit して再起動します。


#4:ポート確認
```
$ sudo netstat -ntlp
tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN 2284/postgres
```

上記のように表示されれば解決です。


#5:外部からのポートアクセスの調べ方
```
$ nc -v -z -w 3 192.168.**.** 5432
Connection to 192.168.**.** 5432 port [tcp/postgresql] succeeded!
```
$ nc -v -z -w 3 <サーバのアドレス> <ポート番号>
上記のコマンドで調べられました。
succeededって出てれば繋がってます。

```
$ cd testbbs
$ rails s
```

これで無事に接続出来てました。

#Rubymine側の設定
Host を localhost から IPアドレス へ変更しました。

![postgresql.PNG](https://qiita-image-store.s3.amazonaws.com/0/132580/ce997ea5-cbf6-ca8e-ec99-42dd42a23562.png)

データベースをRubymineから簡単に追加、閲覧できるようになりました。
mail gemで添付ファイルを付けてみたら

Rails環境とは言え、普通の配信ルート以外でメールを作成する必要があったので、[mail gem](https://github.com/mikel/mail)を直接使ってみたのですが、1箇所ハマってしまいました。

# メール作成時の書式について

今回の件とは直接関係ないですが、mail gemは、メールの各要素を指定するにあたって、各種の記法に対応しています。


```ruby
# Readmeから引用

# 宣言的な書き方
mail = Mail.new do
  from    'mikel@test.lindsaar.net'
  to      'you@test.lindsaar.net'
  subject 'This is a test email'
  body    File.read('body.txt')
end

# 代入
mail['from'] = 'mikel@test.lindsaar.net'
mail[:to]    = 'you@test.lindsaar.net'
mail.subject = 'This is a test email'
```

説明の進めやすさの関係上、箇所によって書式が違うことがありますが、本質的な違いはありません。

# 添付ファイルを付けたら…！

もともとのコードとして、`Hash`に入ったメールの各要素を、ループを回して`Mail`オブジェクトに入れていました。

```rb
mail = Mail.new
hash.each { |key, val| mail[key] = val }
```

そして、こうして作った後に、`mail.attachments = { 'filename.ext' => content }`のようにしたところ、事件が起きました。ファイルはついたものの、`body`が消滅してしまったのです。

# Multipurpose Internet Mail Extensions

よく「MIMEタイプ」と言われますが、そのMIMEを略さずに書くと上のようになります。もともとメールが発祥だったのです。

そして、メールにファイルを添付するとか、HTMLとテキストの両方を入れるなどは、`multipart`という仕組みになっています。

## 今回の件の対策

メールが`multipart`になったのであれば、正しく`text_part`として本文を投げ込めば通るかなと試してみたら、無事成功しました。

```rb
mail.text_part = Mail::Part.new { body hash[:body] }
```
Chef + test-kitchenで依存関係を持ったクックブックテスト環境構築

#問題
ChefDK の test-kitchen で複数のクックブックを使う場合、test-kitchen 実行クックブックにおいて、他のクックブックを呼び出す為の設定追加が必要

- Berksfile
    - クックブックの場所を指定
        - ここで場所が正しく指定されば、.kitchen.ymlのrun_listで直接別cookbookのrecipeを指定することすら可能に
- metadata.rb
    - このクックブックが依存するクックブックを指定


#環境
- test-kitchen実行クックブック
    - source


- test-kitchen環境のクックブックから呼び出される、ローカル環境上に存在するクックブック
    - target


#クックブック作成
```bash

$ chef generate cookbook source
...
$ chef generate cookbook target
...

```

#クックブックの場所、および依存関係設定
```bash


$ cd source

$ echo "depends 'target'" >> metadata.rb # sourceクックブックがtargetクックブックに依存することを設定

$ vi Berksfile
...

```

```ruby:Berksfile
# frozen_string_literal: true
source 'https://supermarket.chef.io'

cookbook 'target', path: '../target' # この指定を追記

metadata

```

- supermarket.chef.ioにあるクックブックの場所は指定不要
- source chef_repo: '..' 指定
    - Chef Repositoryは親ディレクトリーであるとして、個別のクックブックの場所を指定しないことも可能
    - 再読込には対象クックブックのバージョンupが必要
    - この場合でも一度 ~/.berkshelf/cookbooks に取り込んでから配布 
- git: にて、github上のプロジェクトも指定可能
    - 自分で使うクックブックをgithub上にあげておけば、別環境への横展開時に自動的に取ってきてくれるのでにかなり便利

参照
[About Berkshelf](https://docs.chef.io/berkshelf.html)








#動作確認


```bash

$ echo "include_recipe 'target::default'" >> recipes/default.rb
$ echo "log 'source'" >> recipes/default.rb

$ echo "log 'target'" >> ../target/recipes/default.rb

$ vi .kitchen.yml # 必要に応じてplatforms: の - name: ubuntu-16.04 コメントアウトなど

$ kitchen create 
...

$ kitchen converge
...
          1:chef-14.2.0-1.el7                ################################# [100%]
       Thank you for installing Chef!
       Transferring files to <default-centos-7>
       Starting Chef Client, version 14.2.0
       Creating a new client identity for default-centos-7 using the validator key.
       resolving cookbooks for run list: ["source::default"]
       Synchronizing Cookbooks:
         - target (0.1.0)
         - source (0.1.0)
       Installing Cookbook Gems:
       Compiling Cookbooks...
       Converging 2 resources
       Recipe: target::default
         * log[target] action write
         
       Recipe: source::default
         * log[source] action write
         
       
       Running handlers:
       Running handlers complete
       Chef Client finished, 2/2 resources updated in 02 seconds
       Finished converging <default-centos-7> (0m25.50s).
-----> Kitchen is finished. (0m28.40s)
```
正しくsource, targetクックブックが読み込まれ、実行されている。
VimでInsertモードからNormalモードに切り替える時に自動で英数入力に切り替える (for Mac High Sierra)

#VimのNormalモードで日本語入力が鬱陶しい
latexの文章を自分のテキストエディタで書いている時，日本語入力のままNormalモードでコマンドを打ってしまい，Vim操作にならず手間がかかることが多々あったので，InsertからNormalに切り替えるときに自動で英数入力に切り替える方法を調べた．

#KarabinerではSierra, High Sierraでの方法がわからない
キーバインドを自由に設定できる[Karabiner](https://pqrs.org/osx/karabiner/)では，Sierra，High Sierraにおいて複数キーを複数キーにリマップすることができないらしい．自分でもやってみたがうまくいかなかった．

#Hammerspoonを利用するとできた
[Hammerspoon](https://www.hammerspoon.org/)は，macOSに関する様々な処理を自動化するツール．

https://blog.freedom-man.com/macos-sierra-keyremap/
このサイトを参考に，設定してみる．
[Hammerspoon](https://www.hammerspoon.org/)をインストールし，起動 -> Enable Accessibilityをクリック -> セキュリティとプライバシーのプライバシーでHammerspoonにチェック
このあと，configをいじる．
File -> Open configで，init.luaファイルを編集．

```lua:init.lua

local function keyCode(key, modifiers)
   modifiers = modifiers or {}
   return function()
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), true):post()
      hs.timer.usleep(1000)
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), false):post()      
   end
end

local function keyCodeSet(keys)
   return function()
      for i, keyEvent in ipairs(keys) do
         keyEvent()
      end
   end
end

local function remapKey(modifiers, key, keyCode)
   hs.hotkey.bind(modifiers, key, keyCode, nil, keyCode)
end

remapKey({ 'ctrl' }, ']',  keyCodeSet({
    keyCode('escape'),
    keyCode(';', {'ctrl', 'shift'})
}))

hs.hotkey.bind({"cmd", "alt", "ctrl"}, "R", function()
  hs.reload()
end)
hs.alert.show("Config loaded")
```
コードの説明は下の参考にしたサイトでみていただければと思う．
このようにファイルを設定した後，File -> Reload configで，configをリロードする．
これでInsertからNormalにスムーズに切り替えができるようになった．
ちなみに，カタカナ入力をオンにしている場合はうまくいかない場合があるので，
システム環境設定 -> キーボード -> 入力ソース -> 日本語
から，カタカナ，半角カタカナのチェックを外しておくとうまく行くと思う．

めっちゃ参考にしたサイト：
https://blog.freedom-man.com/macos-sierra-keyremap/
Android Studioでライブラリを取り込む３つの方法

<h3><strong>3種類があります。</strong></h3>
<h6><strong>A. libs配下にjarを配置</strong></h6>
jarのファイル名はandroid-support-v4.jarとする。
${module}/libsフォルダを作成する
moduleは適宜変更してください。
jarファイルを${module}/libsフォルダに配置する
${module}/build.gradleにjarのパスを指定するため以下のように追記

<pre>
dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile files('libs/android-support-v4.jar')
}
</pre>

<h6><strong>B. ライブラリのprojectフォルダを読み込む</strong></h6>
facebook sdkなどを組み込むときに用いる。
今回はGit Submoduleを利用して、ライブラリを取り込む。
取り込むライブラリはJohnPersano/SuperToastsを使わせてもらいました。
ライブラリプロジェクトが手元にある場合は、dependenciesの追加からでOKです。

<h6><strong>C. 外部のリポジトリからローカルに取り込む</strong></h6>
Maven Centralなどにjarやaarが公開されている場合に用いることが出来る。

${module}/build.gradleにリポジトリを指定する記述を追記する。
<pre>
dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile files('libs/android-support-v4.jar')
    compile project(':SuperToasts:supertoasts')
    compile 'com.github.sakebook:DialogHelper:0.1.1@aar'
}
</pre>
GithubにPushしても芝（Contributions）に草が反映されない時は

# はじめに

会社の同僚が「毎日githubにpushして芝生の全部に草生やす」と、実践してるみたいで僕も真似してて1週間くらいで気付いたことがありました。

「全然草は言えてない！！」確認してみたら真っ白。

<img width="1030" alt="スクリーンショット 2018-06-14 11.55.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/200cc819-e73c-59d5-d04d-4c3bb7f83d83.png">

今まで、そんなことなかったのに、、、そこで、調べてみました。。

# 原因

調べたところ、どうやら**自前の開発環境とGitHubで登録しているメールアドレスが一致していないと草が生えないようです**。

GitHubに登録しているメールアドレスの調べ方は「Github > Settings > Public profile > Public email」に表示されているメールアドレスです。最近、自前の開発環境をCloud9でも開発をしていて、そこで登録しているgithubのメールアドレスが確かに一致してませんでした。

# 一致させましょう

ローカルの方のメールアドレスの確認方法

```bash
$ git config user.email
```

これでメールアドレス再設定できます

```bash
$ git config user.email [example@exampl.com]
```

上のメールアドレスをgithubに設定したメールアドレスと同じにしてpushすれば、草生えます！

<img width="1009" alt="スクリーンショット 2018-06-14 12.24.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/b7985bc1-5ea0-a003-371e-b7a981a2fe96.png">


ちなみに、githubの方にもメールアドレスを追加することもできて、そうすれば、これまで登録されてなくて草生えてない所も一気に生やせます。

<img width="1048" alt="スクリーンショット 2018-06-14 12.16.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/c4ed9d8b-c909-1093-ac4c-7e4c39c58c82.png">

めでたしめでたし。

# 参考

- http://shopetan.hatenablog.com/entry/2015/06/04/005755
- https://qiita.com/k6i/items/28d0668ce4f16938f73a
- https://mask.hatenadiary.com/entry/2016/01/16/195541
react-native&firebase サンプル

#react-native firebaseサンプル
<br/>
###やりたいこと
・FirebaseのRealtimeDatabaseにどのように追加されていくのか知りたい(RDBとの違いの吸収)
※react-nativeでのfirebaseの書き方の練習ではない

###つくるもの
・追加だけのtodoみたいなやつ

###前提
・firebaseに登録して、RealtimeDatabaseを使ってみようと思ってプロジェクトを作ったが設計の仕方がわからない。RDBは使ったことある。


ソース：[firebase-sample](https://github.com/shoichi1023/firebase-sample)

上のソースでは足りないので、firebaseフォルダの中に下記を追加

```config.js
export default {
    API_KEY: "",
    AUTH_DOMAIN: "",
    DATABASE_URL: "",
    STORAGE_BUCKET: "",
}
```

###結果どうだったか
まず、RDBと違うところ、当たり前だが私はわからなかった。
<br />
**テーブルとか事前に作らなくていい**
<br />
え？うそでしょって思った
DBって先に場所作って、その場所を指定して入れていくものじゃないの？？って
違った。

Firebase RealtimeDatabaseって、jsonファイルみたいなもので、空のjsonに、keyを指定して値を入れていく感覚。
もっとかみ砕いていえば、

```example.js
var array = [];
array['key'] = value;
```

みたいな感覚。

特徴的な部分は
groupと呼ばれるもの(下記で言うt_userのところ)があって、そこにデータが入れられていくこと。
RDBと照らし合わせながら考えてみたいと思う。
<br />
##RDB
![image.png](https://qiita-image-store.s3.amazonaws.com/0/260113/6ccb7b71-dad5-c2f8-e6ff-09be769a467c.png)

こうだとすると

##RealtimeDatabase
![image.png](https://qiita-image-store.s3.amazonaws.com/0/260113/26b244e6-13d2-3f49-a9f9-701954ce81da.png)

こんなイメージ

##RDB

```hogehoge.sql
select id, name, age from t_user;
```

だとすると

##RealtimeDatabase

```hogehoge.js
import firebase from './firebase/firebase';

const db = firebase.database();
const t_user = db.ref('t_user');


/********constructor内**********/

t_user.on('value',snapshot=>{
 this.state.rs.push({
  'id': snapshot.val('id'),
  'name': snapshot.val('name'),
  'age': snapshot.val('age')
 });
});

/**********************/

```

こんな感じのイメージ
詳しくはここに載ってる
[firebase データの取得](https://firebase.google.com/docs/database/admin/retrieve-data?hl=ja#value)

リレーションの仕方とかは上のことを理解したうえでこの人の記事を読むとわかりやすかった。

[Firebase Realtime DBを実践投入するにあたって考えたこと](https://qiita.com/1amageek/items/64bf85ec2cf1613cf507)
<br />
設計の仕方とか内部処理の仕組みとかをもう少し学んでいきたい。
<br>
GPSの研究　その5

#概要
GPSを理解したかった。
RINEXから、衛星位置データ算出してみた。

#サンプルコード

```
from NavParser import *
from Utils import Utils
from Geometrias.Punto3D import Punto3D
from Proyecciones.Cargeo2Geo import Cargeo2Geo

def main():
	navParser = NavigationParser('brdc0590-1.11n')
	pass

if __name__=="__main__":
	main()

```


#結果

```
sat G02
epoca nav 2011-02-28 14:00:00
PosSat 6262234.031370984 -14613110.981922923 21254935.229655903


sat G04
epoca nav 2011-02-28 14:00:00
PosSat 19040661.998708855 -8311756.524602333 16532658.634675292


sat G07
epoca nav 2011-02-28 14:00:00
PosSat 26078664.69836943 5588070.077162541 -239561.27794465935


sat G08
epoca nav 2011-02-28 14:00:00
PosSat 24470813.305349953 -95731.17177840695 -10965308.78942738


sat G10
epoca nav 2011-02-28 13:59:44
PosSat 10946425.106999923 -13217422.981333993 19960118.04486387


sat G13
epoca nav 2011-02-28 14:00:00
PosSat 17400028.443231095 1461399.2922087098 19887536.270703305


sat G17
epoca nav 2011-02-28 14:00:00
PosSat 21078475.93615281 -13351300.07070003 -8639709.183587706


sat G20
epoca nav 2011-02-28 14:00:00
PosSat 14385911.569008492 20514420.345839 8765413.838559393


sat G23
epoca nav 2011-02-28 14:00:00
PosSat 9336918.80677975 12048291.269695656 21723935.800126303

```
PlantUMLで縦に要素を並べる

縦書きというと語弊がありそうですが・・・。

```uml
agent hoge
agent fuga

hoge -> fuga
```

とやるとhogeとfugaが横に並びますが、

```uml
agent hoge
agent fuga

hoge --> fuga
```

`-->` （ハイフン2つ）でつなぐとhogeとfugaが縦に並びます。
Laravel で MariaDB の CRUD (その 4 Create)


## こちらのページの続きです。
>[Laravel で MariaDB の CRUD (その 3)](https://qiita.com/ekzemplaro/items/247b0c9066c2b21d0bb5)
新規作成機能を作ります。

<ol>
<li>ルーティングを確認</li>
>articles/create があることを確認

```bash
php artisan route:list
```

<li>一覧ページに新規作成のリンクをつけます。</li>

```php:resources/views/articles/index.blade.php
{{-- layoutsフォルダのapplication.blade.phpを継承 --}}
@extends('layouts.application')

{{-- @yield('title')にテンプレートごとにtitleタグの値を代入 --}}
@section('title', '記事一覧')

{{-- application.blade.phpの@yield('content')に以下のレイアウトを代入 --}}
@section('content')
<div>
    <a href="/articles/create">新規作成</a>
</div>
<table>
 @foreach ($articles as $article)
        <tr>
    <td>{{$article->title}}</td>
    <td>{{$article->body}}</td>
        <td><a href="/articles/{{$article->id}}">詳細を表示</a></td>
        </tr>
  @endforeach
</table>
@endsection
```

<li>ビューの作成</li>

```php:resources/views/articles/create.blade.php
{{-- layoutsフォルダのapplication.blade.phpを継承 --}}
@extends('layouts.application')

{{-- @yield('title')にテンプレートごとの値を代入 --}}
@section('title', '新規作成')

{{-- application.blade.phpの@yield('content')に以下のレイアウトを代入 --}}
@section('content')
  <form action="/articles" method="post">
    {{-- 以下を入れないとエラーになる --}}
    {{ csrf_field() }}
    <div>
      <label for="title">タイトル</label>
      <input type="text" name="title" placeholder="記事のタイトルを入れる">
    </div>
    <div>
      <label for="body">内容</label>
      <textarea name="body" rows="8" cols="80" placeholder="記事の内容を入れる"></textarea>
    </div>
      <input type="submit" value="送信">
    </div>
  </form>
@endsection
```

<li>コントローラーの修正</li>

```php:app/Http/Controllers/ArticlesController.php
// 略
    public function create()
    {
        return view('articles.create');
    }
// 略
    public function store(Request $request)
    {
  // モデルからインスタンスを生成
  $article = new Article;
  // $requestにformからのデータが格納されているので、以下のようにそれぞれ代入する
  $article->title = $request->title;
  $article->body = $request->body;
  // 保存
  $article->save();
  // 保存後 一覧ページへリダイレクト
  return redirect('/articles');
    }
// 略
```

<li>サーバーを起動してブラウザーで確認</li>

```bash
php artisan serve
```

>http://localhost:8000/articles
![laravel_jun1405.png](https://qiita-image-store.s3.amazonaws.com/0/179446/112b2ad2-5ad4-ecd8-5c03-6fbe8bd146c5.png)

>新規作成をクリック
![laravel_jun1406.png](https://qiita-image-store.s3.amazonaws.com/0/179446/1a589949-a201-2697-950a-db12d22005c8.png)

>送信をクリック
![laravel_jun1407.png](https://qiita-image-store.s3.amazonaws.com/0/179446/3e8a94df-09aa-a663-cca1-709ff69b8085.png)

</ol>

## 次のページ
[Laravel で MariaDB の CRUD (その 5 Update)](https://qiita.com/ekzemplaro/items/c25e0615fa2edaad594c)
TensorFlowをインストールしてみる

やることねぇなぁ～…どうするよ～、暇だぁ～…そうだ、右も左もpythonも分からないけど機械学習やってみよう！(唐突)ってことで、windows10環境でできないかなーって色々ググってみてCPU版TensorFlowってやつがあったのでインストールしてみるぞって軽い感じでやってみた時のメモとか諸々

自分用に書いたものなので参考にしないでね

##Anacondaをインストール
・https://www.continuum.io/downloads

インストールするときpythonのバージョンを選択する必要があるので最新バージョン(私の環境では3.6)を選択すればいいと思います。

インストールが終わって起動したら
Environment→Createをクリック

<img width="960" alt="anaconda.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/264189/7bd4c6be-1e30-6896-c008-39d4d24801fc.png">


名前は…自分のわかりやすいのでいいと思います
<img width="465" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/264189/e644a986-d6a1-6a8f-cf2c-d6c27ed854ba.png">

##tensorflowのインストール
base(root)の下に先ほど作ったやつが追加されるので▶→open terminalでターミナルを立ちあげる

tensorflowインストール
```pip install --ignore-installed --upgrade tensorflow```

pythonを起動
```python```

Hello World出すぞい
> import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))

警告出たけど…まぁええわ(寛容植物)
ターミナル閉じるで
>exit()
deactivate
exit

今回はここまで。所要時間は大体２～３時間くらいでしたね…
Webカメラでラクラク開閉通知

# 内容
webカメラを使ってサクッと開閉通知を作る。

##環境
WindowsOS
Webカメラ

##仕組み
### OpenCVで、部屋の電気の写真（128px*128px）を撮る
部屋の電気以外をなるべく写さないのがポイント

```
c = cv2.VideoCapture(0)
c.set(3,128)
c.set(4,128)
r, img = c.read()
```
### 写真のRGBを取得

```
rgb = cv2.split(img)
```
RGBそれぞれ行列で返ってくる。
### RGBの値の大きさで、しきい値を設定し、それを超えれば、open、下回っていれば、closeにする。
画像に写っている蛍光灯の部分の1pxを選ぶ。今回は、左から40px、上から40pxの1pxをとってきた。
~~縦128px、横128pxであることを参考にして、自力で探し出す。~~
![photo.jpg](https://qiita-image-store.s3.amazonaws.com/0/236125/9d36aac6-e2bf-e1a7-369c-b4f5df3b97eb.jpeg)


**（カメラを少しでもズラすと、取るべき1pxが変わってしまうので注意）**

```
 if(rgb[0][40][40] > 220):
     print("ROOM is open")
 else:
     print("ROOM is closed")
```
しきい値は、220とした。
蛍光灯がついているときは、だいたいrgb[0][40][40]は255に近い値になっている。

###ここまでの処理を任意のペースで繰り返す。

```
While(True):
  ---
  ---
  time.sleep(60*5)
```

##全体のコード

```
While(True):
  c = cv2.VideoCapture(0)
  c.set(3,128)
  c.set(4,128)
  r, img = c.read()
  rgb = cv2.split(img)
   if(rgb[0][40][40] > 220:
       print("ROOM is open")
   else:
       print("ROOM is closed")
  time.sleep(60*5)
```

##おわりに
これをtweepyなどを用いて、Twitterで通知できるようにすれれば完成
メッセージング基盤（MQTT Broker、Apache Kafka、MQ）の特性を比較してみた

# はじめに

メッセージング基盤ソフトウェアとして代表的なMQTT Broker、Apache Kafka、MQを様々な観点で比較した表を作成しました。
各メッセージ基盤ソフトウェアは設計思想が異なることから同じ指標で比較することが困難な点もあり、無理矢理比較している項目もあります。
また、パフォーマンス観点の指標値はハードウェアリソースやメッセージサイズ、システム構成・設定により大きく変わるものですので、詳細は参考資料のパフォーマンス・レポートを参照ください。
こちらの比較表はあくまで各ソフトウェアの特性を掴むための参考資料としてご利用ください。

# メッセージング基盤ソフトウェア特性比較

※ MQTT Broker、MQの製品には情報の入手のしやすからIBM製品を比較対象製品として選択しました。

![メッセージング基盤比較表.jpg](https://qiita-image-store.s3.amazonaws.com/0/259419/bbcd7fb3-7464-bd45-411a-00b8ded26b56.jpeg)

# 参考資料

表内で引用している参考資料は、以下の通りです。

※1 IoT MessageSight v2 Generally Available today!
https://developer.ibm.com/iotplatform/2016/06/10/iot-messagesight-v2-generally-available-today/

※2 IBM IoT MessageSight 2.0.0 Message size
https://www.ibm.com/support/knowledgecenter/en/SSWMAJ_2.0.0/com.ibm.ism.doc/Developing/devmsgsize.html

※3 MessageSight V1.2.0.2 Performance Report
http://www-01.ibm.com/support/docview.wss?uid=swg22009511

※4 WebSphere MQ Telemetry V7.5 - Performance Evaluations
http://www-01.ibm.com/support/docview.wss?uid=swg24034416 

※5 "3.3 Producer Configs"
https://kafka.apache.org/documentation/

※6 Does Kafka scale well for big number of clients?
https://stackoverflow.com/questions/41473583/does-kafka-scale-well-for-big-number-of-clients

※7 "3.1 Broker Configs - message.max.bytes"
https://kafka.apache.org/documentation/

※8 Benchmarking Apache Kafka: 2 Million Writes Per Second (On Three Cheap Machines)
https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines

※9 IBM MQ 8.0 MB より長いメッセージの処理
https://www.ibm.com/support/knowledgecenter/ja/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q026360_.htm

※10 IBM MQ V8.0 for Linux on x86_64 Performance Report
http://www-01.ibm.com/support/docview.wss?uid=swg24038996
同じ列に、複数のwidth指定がなされているとき、列幅はどうなるか？


# 背景
tableの列幅を指定するには、col/colgropuで指定する方法と、td/th要素で指定する方法の2つがあります。
そのため、列幅の指定が重複する場合があります。
列幅の指定が重複したときの動きでハマッたことがあるので、まとめました。

# 前提条件

## 用語
* セル要素: td要素, th要素
* 列要素: col要素, colgroup要素

## ブラウザ
* Firefox 60.0.2 (64 ビット)

## CSS

```css:sample.css
    table {
      table-layout: fixed; /* 列幅を固定レイアウトにする */
    }

    table,td,th {
      border: 1px solid black;
      border-collapse: collapse;
    }

    th {
      background-color: gray;
    }

    td,th {
      /* td/th要素でwidthを指定したときと、col要素で指定したときの幅が同じになるようにする */
      box-sizing: border-box; 
    }
```

## 基準とするHTMLのtable

```html
  <table>
    <colgroup>
      <col><col>
    </colgroup>

    <thead>
      <tr>
        <th>A</th><th>B</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1A</td><td>1B</td>
      </tr>
      <tr>
        <td>2A</td><td>2B</td>
      </tr>
    </tbody>
  </table>
````  


## 確認方法
各列に対して、widthの指定を複数設定します。
そのとき、実際に表示される列の幅を、ブラウザの開発ツールで確認します。


# 結果

<p data-height="459" data-theme-id="0" data-slug-hash="WyOVJB" data-default-tab="html,result" data-user="yuji38kwmt" data-embed-version="2" data-pen-title="widthの指定を複数設定したときの、列幅を確認する" class="codepen">See the Pen <a href="https://codepen.io/yuji38kwmt/pen/WyOVJB/">widthの指定を複数設定したときの、列幅を確認する</a> by yuji38kwmt (<a href="https://codepen.io/yuji38kwmt">@yuji38kwmt</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
## 複数のセル要素にwidthを指定した場合

```html
  <table>
    <colgroup>
      <col><col>
    </colgroup>

    <thead>
      <tr><th style="width:50px;">A</th><th style="width:150px;">B</th></tr>
    </thead>
    <tbody>
      <tr><td style="width:100px;">1A</td><td style="width:100px;">1B</td></tr>
      <tr><td style="width:150px;">2A</td><td style="width:50px;">2B</td></tr>
    </tbody>
  </table>
```

* 最も大きいwidthが採用される
* td,thによる優先度の違いはない
* 行番号による優先度の違いはない（後勝ち,先勝ちではない）


## col要素とcolgroup要素の両方にwidthを指定した場合

```html
  <table>
      <colgroup style="width:100px;">
        <col style="width:50px;"><col style="width:150px;">
      </colgroup>
      
    <thead>
      <tr><th >A</th><th>B</th></tr>
    </thead>
    <tbody>
      <tr><td >1A</td><td>1B</td></tr>
      <tr><td >2A</td><td>2B</td></tr>
    </tbody>
  </table>
  ```
  
* colgroup要素のwidthより、col要素のwidthが採用される


## col要素とセル要素の両方にwidthを指定した場合

```html
  <table>
      <colgroup >
        <col style="width:50px;"><col style="width:150px;" >
      </colgroup>
      
    <thead>
      <tr><th style="width:150px;">A</th><th style="width:50px;" >B</th></tr>
    </thead>
    <tbody>
      <tr><td >1A</td><td>1B</td></tr>
      <tr><td >2A</td><td>2B</td></tr>
    </tbody>
  </table>
  ```
  
* 最も大きいwidthが採用される
* col要素、セル要素による優先度の違いはない


# まとめ
* 同じ列に、複数のwidth指定がなされているとき、最も大きいwidthが採用される
* ただし、col要素とcolgroup要素の両方にwidthが指定されている場合は、widthの大きさにかかわらず、col要素のwidthが採用される
 

# 【補足】tableのwidthを決めるアルゴリズム

以下のページに書いてありますが、理解できませんでした。。。  
[W3C CSS3 3.8.3. Computing Column Measures](https://www.w3.org/TR/css-tables-3/#computing-column-measures)
https://drafts.csswg.org/css3-tables-algorithms/Overview.src.htm
ChainerでXORを学習してみた。

Chainer でTrainerの使い方を学ぶためにXORを学習してみました。
入力データを作るところで躓いてしまいましたが、
[ ( [ 入力1 ] , ラベル1 ) , ( [ 入力2 ] , ラベル2) , ... , ( [入力N ], ラベルN) ]
のように整形したところうまくいきました。
Iteraterで各データセットごとに分けられ、更にUpdater内のConverterで入力とラベルに分けられているようです。

```py
import chainer
from chainer import functions as F
from chainer import links as L
import numpy as np
from chainer.training import extensions

class MLP(chainer.Chain):
    def __init__(self):
        super(MLP,self).__init__()
        with self.init_scope():
            self.Affine1 = L.Linear(2,10)
            self.Affine2 = L.Linear(10,2) # ２値分類の時は，出力層を２，n値分類の場合はn個用意する
        
    def __call__(self,x):
        z1 = F.relu(self.Affine1(x))
        z2 = self.Affine2(z1)
        return z2
    

data = np.array([ [0,0], [0,1], [1,0], [1,1]], dtype='float32')
#target = np.array([[0,1],[1,0],[1,0],[0,1]], dtype = 'int32')
target = np.array([0,1,1,0], dtype = 'int32')
#分類問題の時，教師ラベルはone hot vectorでなく，分類数のint型の値とする必要が有る。
#すなわち，２値分類であれば[0 or 1], 3値分類の場合は[0 or 1 or 2]となる

dataset = chainer.datasets.TupleDataset(data, target)
train_iter = chainer.iterators.SerialIterator(dataset,4)
test_iter = chainer.iterators.SerialIterator(dataset,4,repeat = False,shuffle = False)

model = L.Classifier(MLP())

optimizer = chainer.optimizers.Adam(0.01).setup(model)
updater = chainer.training.StandardUpdater(train_iter,optimizer)


trainer = chainer.training.Trainer(updater,(500,'epoch'),out = 'result')
trainer.extend(extensions.LogReport())
trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'main/accuracy', 'test/loss', 'test/main/accuracy','elapsed_time']))
trainer.extend(extensions.Evaluator(test_iter, model))

trainer.run()
```
Laravel で MariaDB の CRUD (その 2)

## こちらのページの続きです。
[Laravel で MariaDB の CRUD (その 1)](https://qiita.com/ekzemplaro/items/3cf92cac872987f2f857)
MariaDB の テーブル article の全データを JSON で表示するところまでできています。
そこから、テーブル表示が出来るようにします。

<ol>
<li>ビューを用意</li>

```bash
mkdir resources/views/layouts
```

```php:resources/views/layouts/application.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>@yield('title')</title>
</head>
<body>
  @yield('content')
</body>
</html>
```

```bash
mkdir resources/views/articles
```

```php:resources/views/articles/index.blade.php
{{-- layoutsフォルダのapplication.blade.phpを継承 --}}
@extends('layouts.application')

{{-- @yield('title')にテンプレートごとにtitleタグの値を代入 --}}
@section('title', '記事一覧')

{{-- application.blade.phpの@yield('content')に以下のレイアウトを代入 --}}
@section('content')
<h1>こんにちは</h1>
@endsection
```

<li>コントローラーを修正</li>

```php:app/Http/Controllers/ArticlesController.php
    public function index()
    {
        //
 $articles = Article::all();
//      return $articles;       // コメントアウト
  return view('articles.index'); // 追加 
    }
```

<li>サーバーを起動</li>
　この段階での表示の確認

```bash
php artisan serve
```

>ブラウザーで、
http://localhost:8000/articles
にアクセス
![laravel_jun1401.png](https://qiita-image-store.s3.amazonaws.com/0/179446/bf60e767-1236-4179-fd4c-c634075a7f48.png)

<li>ビューの修正</li>

```php:resources/views/articles/index.blade.php
{{-- layoutsフォルダのapplication.blade.phpを継承 --}}
@extends('layouts.application')

{{-- @yield('title')にテンプレートごとにtitleタグの値を代入 --}}
@section('title', '記事一覧')

{{-- application.blade.phpの@yield('content')に以下のレイアウトを代入 --}}
@section('content')
<table>
 @foreach ($articles as $article)
        <tr>
    <td>{{$article->title}}</td>
    <td>{{$article->body}}</td>
        </tr>
  @endforeach
</table>
@endsection
```

<li>コントローラーの修正</li>

```php:app/Http/Controllers/ArticlesController.php
// 略
    public function index()
    {
        //
 $articles = Article::all();
   return view('articles.index', ['articles' => $articles]);
    }
// 略
```

<li>サーバーを起動してブラウザーで確認</li>
>http://localhost:8000/articles
![laravel_jun1402.png](https://qiita-image-store.s3.amazonaws.com/0/179446/47e8169b-477d-7c65-9dc3-4b05258e0a18.png)

</ol>

## 確認したバージョン

```text
$ php artisan --version
Laravel Framework 10.37.3
```

## 次のページ
[Laravel で MariaDB の CRUD (その 3)](https://qiita.com/ekzemplaro/items/247b0c9066c2b21d0bb5)
WebFontでアイコン設置(アイコンフォント)

こんにちは。

ボタンアイコンの`::before` ` ::after`オンパレードな作図と、1px単位の微調整に疲れてしまったので、何か良い方法は無いか探していた所、アイコンフォントなる物を見つけ、使用感も良かったので備忘録。

# アイコンフォント
1アイコンが1記号文字として収録されている、アイコンのみのフォントファイル。
通常のフォントファイルと同様に、大抵は下記主要フォーマットのうちいずれかをサポート。

- TrueType (ttf)
- OpenType (otf)
- WebOpenFont Format (woff)
- Embedded OpenType (eof)

# メリット & デメリット
## メリット
何より「アイコン構成部品同士のレイアウトが崩れない」に尽きるでしょう。
そもそも「1文字」なので、崩れようがありません。
設置する際のCSSも、最低限`font-family` `content: "Unicode番号"`があれば動くので、記述量が少なくなりコードが見やすくなる点も挙げられます。

## デメリット
あくまで「文字」なので、アニメーションには弱いです。
回転させたり変化させたり、そういった用途には向きません。

# 使ってみる
## フォント選定
有名所はいくつかありますが、Kazuyuki Motoyama氏作成の`LigatureSymbols`を使用します。
理由は、フォントファイルサイズと収録アイコン量のバランスが丁度良いからです。
アイコンデザインもスッキリしていて個人的には好みです。

[LigatureSymbols - Kazuyuki Motoyama](http://kudakurage.com/ligature_symbols/)

上記の公式ページからzipファイルで入手可能です。

## 書いてみる
主に設定画面への誘導用として用いられる事が多い、歯車アイコンを設置してみます。

```css
@font-face {
    font-family: LigatureSymbols;
    src: url("LigatureSymbols.ttf") format("truetype");
}
```
まずはフォント定義
`url(...)`はフォントファイルの配置場所により適宜変更

```css
.icon {
    font-family: LigatureSymbols;
    font-size: 2em;
    cursor: pointer;
    margin: 0;
    padding: 0;
}
```
アイコンを配置する際の共通クラス

```css
.icon.options::before {
    content: "\E055";
}
```
`.options`は歯車アイコンのUnicode番号`\E055`を適用する為のクラス
Unicode番号は`content`にて指定しなければならないので、ここだけ`::before`を使う

```html:html
<label class="icon options">
    <button onclick="openOptions();" hidden></button>
</label>
```
お好みでHTMLに適用して完了

## 仕上がり
![options.png](https://qiita-image-store.s3.amazonaws.com/0/253070/af4d6d42-c356-4212-92a3-996e6478062a.png)
良い感じ！

ちなみにこれはElectronアプリゆえ、わざわざ`onclick`からの`remote.BrowserWindow`で開かないといけないワケ。

~~VSCodeのダークテーマっぽい配色にすれば、どんな駄作でもそれっぽく見えるって1048576回は言ってる~~

# まとめ
アイコンフォント、圧倒的に便利でした。
導入も簡単なので、サクっとアイコンを置きたい時は良い選択肢になると思います！
独自リスナーの作り方

#はじめに
あるクラスで処理を行ってその結果をActivityや別クラスに通知したい場合、どのようにすればよいか。
本記事では、独自でリスナーを作り、それを特定のクラスで受け取る例を書いていきます。

#リスナーとは
あるイベントが発生してくれたことを通知してくれるもの、

#登場人物
* <b>リスナー  </b>
イベント発生通知をしてくれる。

* <b>インターフェース  </b>
イベントの通知元と通知先の仲介役。基本的にインターフェースを通して通知先に通知する。

* <b>レシーバー  </b>
イベントを受け取る。

#具体例

### Calculation
```java
public class CalculationListener {

    private ResultInterface listener;

    public Calculation(ResultInterface listener) {
        this.listener = listener;
    }

    public void calc(int a, int b) {
        int sum = a + b;
        this.listener.result(sum);
    }
}
```

### ResultInterface
```java
public interface ResultInterface {
    void result(int sum);
}
```

### MainActivity
```java
public class MainActivity extends AppCompatActivity implements ResultInterface {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Calculation obj = new CalculationListener(this);
        obj.calc(10,20);
    }

    @Override
    public void result(int sum) {
        String msg = String.valueOf(sum);
        Log.d("MainActivity", msg);
    }
}
```

もしくは

```java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Calculation obj = new CalculationListener(new ResultInterface() {
            @Override
            public void result(int sum) {
                String msg = String.valueOf(sum);
                Log.d("MainActivity", msg);
            }
        });
        obj.calc(10,20);
    }
}
```
### 結果
```java
MainActivity: 30
```

# 解説
### 上記コードにおける、登場人物。

* リスナー　→　CalculationListener
* インターフェース　→　ResultInterface
* レシーバー　→　MainActivity

### ポイント
1. CalculationListenerオブジェクト生成時、<b><span style="color: #ff5252">リスナー（CalculationListener）に通知先（MainActivity）を教えておく</span></b>。
2. CalculationListenerで計算したあと、<b><span style="color: #ff5252">インタフェースを通して</span></b>通知先に計算結果を教えてくれる。

# まとめ
MainActivityを自分自身だとすると、自分の連絡先を警察に教えておき、財布がみつかったら教えた連絡先に電話してください。
のような感じ。
URLSessionを用いた通信

# 背景
モバイルアプリ作っていると、APIで外部からデータを引っ張ってきたいと思うことが良くあります。
そういったときにAlamofireなどのサードパティーのライブラリを使いがちで、URLSessionを使ったことがない人がまあまあいると思います。そこでURLSessionを用いた基礎を書いていきます。

# 必要クラス

### URLSession
ダウンロード周りのAPIを提供するクラス。<br>
通信に必要なセッションを生成する。

### URLSessionConfiguration
ダウンロードやアップロードする際、必ず設定すべき最初の手順。<br>
バックグラウンド動作の有無や、タイムアウト時間など様々な設定をすることができる。

### URLSessionTask
ファイルなどをダウンロードするなどのタスクが、URLSessionによって実行される。<br>
下記のサブクラスによって振る舞いを決定することができる

* URLSessionDataTask：ダウンロードする（小さいデータ）
* URLSessionDownloadTask：ダウンロードする（大きなデータ）
* URLSessionUploadTask：アップロードする

### URLRequest
プロトコルまたはURLスキームに依存しないリクエストを行うことができる。<br>
URLRequestを使わない場合GETメソッドでのリクエストしかできないが、
URLRequestを使うとPOSTメソッドでのリクエストを行うことがきる。

# 使い方
上記のクラスを用いてGETメソッドとPOSTメソッドでリクエストを投げる最小構成を書いていきます。

## GETメソッド

```swift
class HTTPClient {
    func get() {
        let config: URLSessionConfiguration = URLSessionConfiguration.default
        let session: URLSession = URLSession(configuration: config)
        let url: URL = URL(string: "http://example.com")!
        
        session.dataTask(with: url, completionHandler: { (data, response, error) in
            // do something
        })
    }
}

let client: HTTPClient = HTTPClient()
client.get()
```

## POSTメソッド
```swift
class HTTPClient {
    
    func post() {
        let config: URLSessionConfiguration = URLSessionConfiguration.default
        let session: URLSession = URLSession(configuration: config)
        let url: URL = URL(string: "http://example.com/post")!
        var req: URLRequest = URLRequest(url: url)
        req.httpMethod = "POST"
        req.httpBody = "post test".data(using: .utf8)
        
        let task = session.dataTask(with: req, completionHandler: { (data, response, error) in
            // do something
            print(error!)
        })
        task.resume()
    }
}

let client: HTTPClient = HTTPClient()
client.post()
```
GETでもPOSTでも書き方はほぼ同じで、POSTのときはURLRequestでhttp methodとhttp bodyの指定が必要です。
【Drupal8】メール送信内容を手っ取り早く確認したい

Drupal開発時、Dockerなどを使っているとメールが上手く送信できない事がある。
メールを送信できるようにする環境設定を棚上げしてメール送信内容だけ確認したい場合のTips。

自作モジュールないしソースがいじれる既存のモジュールが必要。
hook_mail_alter(&$message) が、メール送信時に呼ばれるのでこれを利用する。
drupal_set_message()で画面表示するときは改行されない（＜br＞タグも無視される）。

フラッシュメッセージでの表示と、テキストファイルへの書き出しとを行っている。テキストファイルの保存パスは以下の該当箇所を修正すること。


```
function {モジュール名}_mail_alter(&$message)
{
    dump($message);

    $str_header = '';
    foreach ($message['headers'] as $key => $value) {
        $str_header .= $key." : ".$value."\n";
    }
    $str_body = '';
    foreach ($message['body'] as $key => $value) {
        $str_body .= $value;
    }

    $data = '[ID]'.$message['id']."\n"
           .'[SUBJECT]'.$message['subject']."\n"
           ."\n"
           .'[HEADER]'."\n"
           .$str_header
           .'[BODY]'."\n"
           .$str_body;
    file_put_contents ('/{ここにメールの内容をテキストにしたものを保存するパスを記述}/mail_'.date('Ymd_His').'.txt', $data);

    drupal_set_message('[ID]'.     $message['id'],      'status', true);
    drupal_set_message('[SUBJECT]'.$message['subject'], 'status', true);
    drupal_set_message('[HEADER]'. $str_header,         'status', true);
    drupal_set_message('[BODY]'.   $str_body,           'status', true);

    //リダイレクトを阻害する場合
    //exit;
}
```
Pandasで偏差値を出す


偏差値を出したかったが分からなかったので調べました。

##環境
The version of the notebook server is: 5.4.0
Python 3.6.4 |Anaconda custom (64-bit)| [GCC 7.2.0]

##前置き
今回偏差値を出しますが、分析対象のデータがすべてあるので
「母分散・母標準偏差」となります。


##データ
| id       |       name |    score    |
|:-----------------|------------------:|:------------------:|
| 1             |              A |        45        |
| 2             |              B |        32        |
| 3             |              C |        67        |
| 4             |              D |        40        |
| 5             |              E |        55        |

##ソース

```python

import pandas as pd
df = pd.read_csv('./data.csv')
# dict =  {'id': [1, 2, 3, 4, 5], 'name': ['A','B','C','D','E'], 'score': [45, 32, 67, 40, 55]}
# df = pd.DataFrame.from_dict(dict)

df_score = df['score']
df_score_std = df_score.std(ddof=0)
df_score_mean = df_score.mean()
df['DeviationValue'] = df_score.map(lambda x: round((x - df_score_mean) / df_score_std * 10 + 50)).astype(int)

df
```

##説明

pandasをimportしてdfにcsvを読み込みます。
写経する場合csvを作るのも面倒なのでDataFrameをdictから作ります。

```python
import pandas as pd
df = pd.read_csv('./data.csv')
# dict =  {'id': [1, 2, 3, 4, 5], 'name': ['A','B','C','D','E'], 'score': [45, 32, 67, 40, 55]}
# df = pd.DataFrame.from_dict(dict)
```

対象のカラムを指定してdf_scoreという名前のSeriesを作ります

```python

df_score = df['score']
```

まず標準偏差を求めますが、引数に何も指定しない場合（デフォルト）は不偏分散・不偏標準偏差の計算になります。
そこで ddof=0 という引数を指定して母分散・母標準偏差の計算にする必要があります。

```python

df_score_std = df_score.std(ddof=0)
```

次に平均値を求めます。

```python

df_score_mean = df_score.mean()
```

偏差値の求め方は下記となります
偏差値 = (得点 − 平均点) ÷ 標準偏差 × 10 + 50

```python

df['DeviationValue'] = df_score.map(lambda x: round((x - df_score_mean) / df_score_std * 10 + 50)).astype(int)
```
ここがわかりづらいのでもう少し詳しく書くと
df_score.mapはSeriesの各要素に対して自分で定義した関数を適用する関数です。
lambdaはlambda式というPythonの無名関数です

```python

lambda 引数:処理内容
```

少し式を分解しないとわかりづらいのでfor文で書くとこうなります
dfをイテレートしながら偏差値を計算し、リストに追加していきます。
その後Seriesに変換してDataFrameと結合しています。

```python

# lambda x: round((x - df_score_mean) / df_score_std * 10 + 50)).astype(int)
dv_ary = []
for index, row in df.iterrows():
    x = row['score']
    a = (x - df_score_mean) / df_score_std * 10 + 50
    b = round(a)
    dv_ary.append(b)

# Seriesに変換
dv = pd.Series(dv_ary).astype(int)
# DataFrameと結合
df['DeviationValue'] = dv
```
 
##結果

| id       |       name |    score    | DeviationValue|
|:-----------------|------------------:|:------------------:|:------------------:|
| 1             |              A |        45        |48|
| 2             |              B |        32        |37|
| 3             |              C |        67        |66|
| 4             |              D |        40        |44|
| 5             |              E |        55        |56|


##参考

https://www.sejuku.net/blog/23677
https://note.nkmk.me/python-pandas-dataframe-for-iteration/
https://it-engineer-lab.com/archives/1065
https://note.nkmk.me/python-pandas-map-applymap-apply/
TypeScriptではclassそのものを単体でエクスポートすることはできない

# 単体の何かをエクスポートするということ

JavaScriptでは、こんな感じでexport文を書くことができます。

```js:module.js
module.exports = class Module {
  foo() {
    return "foo"
  }
}
```

これをimportするには以下のように書きます。

```js:main.js
const Module = require("./module");
new Module().foo();
```

要は、ファイル内にクラスを一つしか書かず、名前をつけずにexportすることができるわけです。

# TypeScriptで書くとどうなるか
```ts:module.ts
export = class ModuleA {
  foo() {
    return "bar";
  }
}

// [ts] ECMAScript モジュールを対象にする場合は、エクスポート割り当てを使用できません。
// 代わりに 'export default' または別のモジュール書式の使用をご検討ください。
```

# 困ること
jsで書かれたnpmライブラリを取り込むときに型情報が付けられません。
↓こんなライブラリがあって、tsから使いたいけど型情報がない。せっかくなら型を定義して使いたい。

```js:npmLib.js
module.exports = class Module {
  foo() {
    return "bar";
  }
}
```

自分で型を定義しようとすると・・・
うまくいかない。

```ts:npmLib.d.ts
declare module "npmLib" {
  ここにうまく書く方法がない
}
```

# 自分がやった対処
外部モジュールをラップしました。

```ts:Wrapper.ts
// import形式だと型情報がうまくいかない
// import * as Module 
// [ts] モジュール 'npmLib' の宣言ファイルが見つかりませんでした。'hoge/npmLib/hoge' は暗黙的に 'any' 型になります。
// `npm install @types/npmLib` を試すか (存在する場合)、`declare module 'npmLib';` を含む新しい宣言 (.d.ts) ファイルを追加してください
const OrgModule = require("npmLib");

interface ModuleType {
  new(): ModuleType;
  foo(): string;
}

export const Module: ModuleType = OrgModule;
```

以上です。よろしくお願いいたします。
VueJSでcode-prettifyを使ってページにソースコードを表示する

[公式](https://github.com/google/code-prettify)には、CDNとaddEventListener(Load)による実装方法の記載しか無かったので、
VueJSでの実装方法を簡単に記しておきます。

## 実装方法
code-prettifyはファイルを読み込んで実行するため、ページが再レンダリングされたときに再実行されず、機能しなくなります。
ページがレンダリングされる度に実行するために、[mounted](https://jp.vuejs.org/v2/api/index.html#mounted)と[nextTick()] (https://jp.vuejs.org/v2/api/index.html#Vue-nextTick)を使用して実装する必要があります。

## mountedとは
mountedとは、Vueインスタンスが生成時に行う一連の初期化をする過程の中で、インスタンスがマウントされた後に呼ばれる、DOM要素にアクセスすることができるライフサイクルフックです。
公式ドキュメントの[ライフサイクルダイアグラム] (https://jp.vuejs.org/v2/guide/instance.html#%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%80%E3%82%A4%E3%82%A2%E3%82%B0%E3%83%A9%E3%83%A0)を一読し、初期化の過程を理解しておきましょう。

## nextTick()とは
Vueはdataの変更に基づいてDOMを更新しますが、dataを変更しただけではレンダリングに反映されません。
nextTick()を使用することで、DOMの更新後にレンダリングに反映させることができます。

これは、Vueのdataが変更された後でページがレンダリングされる前に実行されるためです。
実際にはnextTick()に登録したコードがDOMの更新後に(コールバックで)呼び出されてます。
公式ドキュメントの[非同期更新の理解] (https://012-jp.vuejs.org/guide/best-practices.html#%E9%9D%9E%E5%90%8C%E6%9C%9F%E6%9B%B4%E6%96%B0%E3%81%AE%E7%90%86%E8%A7%A3)で、仕組みについて見ておくと、イメージしやすいかと思います。

## mountedとnextTick()の組み合わせ
mountedとnextTick()を組み合わせることで、DOM要素にアクセスできるようになったタイミングで、ページがレンダリングされる度にコードを実行することができます。

```javascript
mounted: function () {
  this.$nextTick(function () {
    // レンダリングする度に実行
  })
}
```
## サンプルの実装前の準備
**まずはcode-prettifyをダウンロード**
https://github.com/google/code-prettify/tree/master/distrib

**サンプルで使用したバージョンはこちら**
"vue": "^2.5.11"

**ディレクトリ構造はこちら**

```
/root/
   ├ App.vue
   ├ main.js
   ├ mixin.js
   ├ /vendors/
       ├ /google-code-prettify/ (ダウンロードしたファイル)
   ├ /components/
       ├ sample.vue
```

## サンプルのソースコード

```main.js
// VueとVueRouterを読み込む
import Vue from 'vue'
import VueRouter from 'vue-router'

// code-prettifyを読み込む
import './vendors/google-code-prettify/prettify';

// コンポーネントを読み込む
import App from './App'
import Sample from './components/sample'

// ルーターのインストール
Vue.use(VueRouter);

// ルート設定
const routes = [
  {
    path: '/',
    component: App,
    path: '/sample',
    component: Sample,
  }
];

// ルーターインスタンス作成
const router = new VueRouter({
  routes: routes
});

// Vueインスタンス作成
const app = new Vue({
  el: '#app',
  router: router,
});
```

```App.vue
<template>
  <div id="app">
    <ul>
      <router-link tag="li" to="/">Home</router-link>
      <router-link tag="li" to="/sample">Sample</router-link>
    </ul>
  </div>
</template>

<style>
  /* code-prettifyのスタイルを読み込む */
  @import './vendors/google-code-prettify/prettify.css';
  @import './vendors/google-code-prettify/skins/sons-of-obsidian.css';
</style>

```

```sample.vue
<template>
  <pre class="prettyprint lang-html linenums">
    <div>hoge</div>
  </pre>
</template>

<script>
export default {
  mounted () {
    this.$nextTick(() => {
      PR.prettyPrint();
    })
  },
};
</script>
```

## さらにmixinでモジュール化すると使い回しがききます

```mixin.js
module.exports = {
  mounted () {
    this.$nextTick(() => {
      PR.prettyPrint();
    })
  },
};
```
``` sample.vue
<template>
  <pre class="prettyprint lang-html linenums">
    <div>hoge</div>
  </pre>
</template>

<script>
import mixin from '../../mixin';

export default {
  mixins: [mixin]
};
</script>
```