OmniAICreator/Qiita-1.07M huggingface dataset:
ask-sdkでClovaスキルを開発してみる

# ASKとCEK

自分はよく、AlexaとClovaのスキルを作るのだが概念がほとんど同じことに気づく。
たとえば、インテントだったり、スロットだったり。
どっちがどっちに似せたかはわからないが（言わない)ここまで似ているのに別々のSDKを使って、全く異なったコードを書くのはとても面倒である。

流石に同じエンドポイント（lambdaの同じ関数を使ったり)はよくない
しかし、同じSDKを使って、Alexaで使ったコードを丸っとコピーしてCEKに持っていけたらとても便利だ。

以前、[この記事](https://qiita.com/imajoriri/items/1b919b923246e69fe86e)にて`ask-sdk`とほぼ同じコードでかけるClova用のSDKを紹介したが、もういっそ`ask-sdk`をつかってClovaスキルを作ってみることにした。

# 流れ

1. CEKからイベントを取得
2. 取得したイベントをASK仕様に変換
3. ask-sdkでごにょごにょ書く
4. ask-sdkで作成されたレスポンスをCEK仕様に変換
5. CEKにレスポンスを返す。

(3)のask-sdkの中のコードは説明しません。ask-sdkを使ったことがある前提で説明します。

# exports.handler

```js:index.js
let skill;
exports.handler = async function (event, context) {
  if (!skill) {
    skill = Alexa.SkillBuilders.custom()
      .addRequestHandlers(
        LaunchRequestHandler,
        SampleIntentHandler)
      .create();
  }

  // CEKのイベントをASK仕様に変換
  var ASKEvent = conversionToASKEvent(event);

  // ask-sdkでのレスポンスのオブジェクト
  const ASKResponse = await skill.invoke(ASKEvent);
  
  // ask-sdkで作成されたオブジェクトをCEK仕様に変換
  var CEKResponse = conversionToCEKResponse(ASKResponse);

  return CEKResponse;
}
```

以下の部分でCEKからきたイベントJSONをASK風にします。(この関数は後述します。)

```js
var ASKEvent = conversionToASKEvent(event);
```

よって、以下のように`skill.invoke`が使用できます。

```
const ASKResponse = await skill.invoke(ASKEvent);
```

このままではレスポンスがASK風になってしまうので、以下でCEK風のオブジェクトに変換します。

```js
var CEKResponse = conversionToCEKResponse(ASKResponse);
```


# conversionToASKEvent

CEKのイベントオブジェクトをASK風にしているだけです。

```js
function conversionToASKEvent(CEKEvent){
  var ASKEvent = {
    version: CEKEvent.version,
    session: {
      new: CEKEvent.session.new,
      attributes: CEKEvent.session.sessionAttributes,
      user: {
        userId: CEKEvent.session.user.userId
      },
    },

    // requestはほぼ一緒なのでそのまま
    request: CEKEvent.request,
  }
  return ASKEvent;
}
```

# conversionToCEKResponse

レスポンスの仕様はちょろっと違います。
Clovaは現在ssmlが使用できないのですが、ask-sdkだと<speak>タグで囲まれてしまうので、いっそのこと`replace(/<.*?>/g, "")`で<tag>を全て消去しちゃってます。


```js
function conversionToCEKResponse(ASKResponse){
  var reprompt = undefined;
  if(ASKResponse.response.reprompt){
    var repromptText = ASKResponse.response.reprompt.outputSpeech.ssml.replace(/<.*?>/g, "");
    reprompt = {
      outputSpeech: {
        type: "SpeechList",
        values: [
          {
            type: "PlainText",
            lang: "ja",
            value: repromptText,
          }
        ]
      }
    }
  }

  var text = ASKResponse.response.outputSpeech.ssml.replace(/<.*?>/g, "")
  var CEKResponse = {
    version: "1.0",
    sessionAttributes: ASKResponse.sessionAttributes,
    response: {
      outputSpeech: {
        type: "SpeechList",
        values: [
          {
            type: "PlainText",
            lang: "ja",
            value: text,
          }
        ]
      },
      reprompt: reprompt,
      shouldEndSession: ASKResponse.response.shouldEndSession,
    }
  }
  return CEKResponse;
}
```

# 終わりに

こんな感じで試しに開発してみた動画です。

https://twitter.com/imasirooo/status/1020638215462576129

喋った。。。よかった。
gitのグローバル設定

## 背景
最近、RubyMineを使い始めたのですが、プロジェクトを開くとその配下に `.idea` というフォルダが勝手に作られてしまい、この `.idea` というフォルダは何も設定しない状態だとgitの追跡対象に含まれてしまいます...

`.idea` を `.gitignore` に書けばいいのでしょうか？？？
とはいえ、RubyMineを使っているのは会社で私のみ...
自分にしか該当しないフォルダをgitの追跡対象から外すために `.gitignore` に追加して、それをマスターにマージしてもらうのは何か気持ちが悪い...

そんな時にgitのグローバル設定をすることで、プロジェクト毎に `.idea` をgitの追跡対象から外さなくても、自身の環境でグローバルにgitの追跡対象から外せることを知りました！
そんな訳で超絶初心者の自分用メモとして投稿しようと思った次第です。
(これは `.idea` に限らずgitの追跡対象から外したいファイルやフォルダがあった時に有効です)

## 手順
*以下、ターミナル

- まずvimで `.gitignore_global` というファイルを新規作成(このファイルに除外対象にするファイルやフォルダを記載)

```ruby
vim ~/.gitignore_global
```

- vimで `.idea/` を　`.gitignore_global` ファイルに記載して保存する

```ruby
.idea/
~
~
~
```

- そして、最後に以下のコマンドを実行

```ruby
git config --global core.excludesfile ~/.gitignore_global
```

- 念のため、gitの設定ファイルを確認

```ruby
vim ~/.gitconfig
```

[core]の部分に今回gitの追跡対象外フォルダを記載した設定ファイルが `excludesfile` として追記されていることを確認

*今回は[user]の部分は関係ないです(初心者の方向けに一応、( )で説明を追記してます)

```ruby
[user]
        email = メールアドレス(gitで自身と紐付けるメールアドレスを記載)
        name = ユーザー名(gitで扱われる自身のユーザー名を記載)
[core]
        excludesfile = /Users/ユーザー名/.gitignore_global
~
~
~
~
~
```

`git status` を実行し、変更対象に `.idea` が含まれていなければOK

```ruby
> git status
On branch master
nothing to commit, working tree clean
```

## 参考記事
https://qiita.com/elzup/items/4c92a2abdab56db3fb4e
BEMを実際に使ってみて



#背景
BEMで開発すること半年たったので

#BEMとは
- Block（Webサイトを構成するパーツ）
- Element（Blockを構成する要素）
- Modifire（BlockやElementの見た目を変える要素）

命名規則はMindBEMdingがベース

```BEM:BEM記法
block
block__element
block__element--modifier
block--modifier
block--modifier__element
```

メリット/デメリットをさらっと書いてみます。

**メリット**
ソースコードの統一性を保つ
スタイルの汚染を防ぐ
HTML構造が明確になる
再利用・拡張性に優れる

**デメリット**
開発スピードが遅くなる
支持を得にくい

メリットを享受できるかどうかは、BEMをちゃんと理解しなきゃいけない


#破綻寸前になる前に

ちゃんと「コーディングルール」や「スタイルガイド」といったドキュメントを揃えておく



#BEMで躓いたところ

サムネイルとテキストがあるリストボックスです。
特にmodifierですね。。。

```HTML:HTML
<div class="box">
  <div class="box__thumb">
    <img src="" alt="" class="box__thumb-image">
  </div>
  <div class="box__body">
    <div class="box__heading">Blockの見出し</div>
    <p class="box__text">テキストテキストテキストテキスト...</p>
  </div>
</div>
```

これを外側と画像部分を角丸にしたいとしたらどうなるか？

```HTML:HTML
/* bad */
<div class="box box--soft">
  <div class="box__thumb">
    <img src="" alt="" class="box__thumb-image box__thumb-image--soft">
  </div>
  <div class="box__body">
    <div class="box__heading">Blockの見出し</div>
    <p class="box__text">テキストテキストテキストテキスト...</p>
  </div>
</div>

<style>
.box--soft { border-radius: 3px; }
.box__thumb-image--soft { border-radius: 3px; }
</style>
```

コンポーネントのベースにmodifierを追加し、その1つのmodifierに基づいて各子要素のスタイルを調整する

```HTML:HTML
/* good */
<div class="box box--soft">
  <div class="box__thumb">
    <img src="" alt="" class="box__thumb-image">
  </div>
  <div class="box__body">
    <div class="box__heading">Blockの見出し</div>
    <p class="box__text">テキストテキストテキストテキスト...</p>
  </div>
</div>

<style>
.box--soft { border-radius: 3px; }
.box__thumb-image--soft .box__thumb-image { border-radius: 3px; }
</style>
```

まだBEM歴が半年なので躓いたら追記していきます:frowning2:
pythonエラー：import: unable to open X server〜

ROSなどでpythonコードを実行しようとしたら以下のエラーが出た．

```
import: unable to open X server `' @ error/import.c/ImportImageCommand/366.
from: can't read /var/mail/datetime
```

# 原因と解決策
pythonコードがシェルスクリプトと勘違いしているようなので
pythonコードの一行目に`#!/usr/bin/env python`を挿入しておく
Azure特典の有効化とサブスクリプション更新時に注意すること(MSDN Subscription）

# Azureサブスクリプションの有効化

1.MSDN Subscriptionにログイン。（Safari、Chrome）
2.「特典」から「Azureの有効化」を選択。
3.画面の指示に従って情報を入力。

# MSDN Subscription更新時にAzureアカウントの手続きがいるか？　→　要らない
気になるのが、MSDN Subscriptionの期限切れの時。
（注意：2018年1月時点の情報です。）
###MSDN Subscriptionの契約更新###
特典番号が変わらない場合、Azureアカウントの特典を継続利用できる。
###MSDN Subscriptionを更新しない場合###
MSDN Subscriptionが失効すると<FONT color="red">**Azureも停止し課金は発生しない**</FONT>（しばらくは動く）。
新規に契約しなおすと特典番号が変わるため、再度Azure特典の有効化が必要になる。
データを引き上げる必要があるのであれば、MSDN Subscriptionの有効期限内にデータ引き上げを行っておくこと。
matplotlibで3次元グラフを描く

```python
# Jupyter Notebook で描く場合
%matplotlib inline

import numpy as np
import matplotlib.pylab as plt
from mpl_toolkits.mplot3d import Axes3D

def function_2(x):
    return x[0]**2 + x[1]**2

x = []
x.append(np.arange(-3.0, 3.0, 0.2))
x.append(np.arange(-3.0, 3.0, 0.2))

mg_0, mg_1 = np.meshgrid(x[0], x[1])
y = function_2([mg_0, mg_1])

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_wireframe(mg_0, mg_1, y)
plt.show()
```

![3d_figure.png](https://qiita-image-store.s3.amazonaws.com/0/7750/43f99135-1f8b-99f1-a1b1-38e21f59ad67.png)

## 参考
- [配列の要素から格子列を生成するnumpy.meshgrid関数の使い方](https://deepage.net/features/numpy-meshgrid.html)
- [Using numpy to build an array of all combinations of two arrays](https://stackoverflow.com/questions/1208118/using-numpy-to-build-an-array-of-all-combinations-of-two-arrays)
ツクールMVでメモ欄に不等号を書く方法

プラグイン作者向けの記事です。

ツクールMVのメモ欄でこんな記述を見ませんか？
> \<data>
> a.hp > 100
> \</data>

この記述方法でも解決できますが、note部分を見るためにデータを取り出す効率が悪いです。

こういった構造になっている部分は、条件式を書いたりする場合があります。
たとえば
> \<data:a.hp > 100>

こんな記述にしてしまうとデータが壊れて正しく動きません。
不等号がタグ閉じと勘違いされてしまうからです。
この問題ですが、右辺と左辺を交換することで解決できます。
> \<data:100 < a.hp>

条件式を要求するメモ記述は多いと思いますので、ぜひこのテクニックを使ってみましょう。
プラグイン側での対応も少なくて済むので、個人的にお勧めです。
~~（\<data>　 a.hp > 100 \</data>形式が嫌いなだけです）~~
Angular6でダッシュボードを作成したいと考えている開発者向けのサンプル

# _Ng6DashboardSample_ Angular6でダッシュボードを作成したいと考えている開発者向けのサンプル
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)


_Ng6DashboardSample_ は、Angular6においてAngular Materialによりダッシュボードを実現しようと考えている開発者向けのサンプルです。

_フルソースコード_,
<https://github.com/Ohtsu/ng6-dashboard-sample>

_ビデオ解説 (日本語)_,
<https://youtu.be/3mkYx1YFGoc>

_ビデオ解説 (英語)_,
<https://youtu.be/s4vXOOU9sp0>


## 概要 
   - _Ng6DashboardSample_ はダッシュボードのサンプルであり、Angular6におけるAngular Materialに依存しています。

   - _Ng6DashboardSample_ は、mat-grid, mat-card, mat-menu, mat-iconなどを利用しています。

   - _Ng6DashboardSample_ は、d3.js(ver4.3) および ng6-o2-chartを利用しています。
  

## 稼働環境

   - node.js
   - Typescript2
   - Angular6


## インストール

以下のように、Gitからクローンを作成します。

```bash
$ git clone https://github.com/Ohtsu/Ng6DashboardSample.git 
```

次に生成されたNg6DashboardSampleディレクトリに入り、以下のようにインストールを行います。

```bash
$ npm install 
```

## 起動

コマンドラインで以下のようにローカルサーバを起動すると、多くのチャートを含むダッシュボードが表示されます。


```bash
$ ng serve -o
```

  - ***初期画面*** 

  <img src="https://raw.githubusercontent.com/Ohtsu/images/master/ng6-material/dashboard-initial01.png" width= "640" >



## バージョン


   - Ng6DashboardSample       : 0.0
   - Angular6                   : 6.0.0
   - TypeScript                 : 2.7.2
   - @angular/material          : 6.2.1
   - d3.js          		: 4.3.0
   - ng6-o2-chart          	: 0.4.0



## 参考

- "Schematics", 
<https://material.angular.io/guide/schematics>

- "Angular 5, Angular 6 Custom Library: Step-by-step guide", 
<https://www.udemy.com/angular5-custom-library-the-definitive-step-by-step-guide/>


- "Angular 5, Angular 6用 カスタムライブラリの作成: 完全ステップ・バイ・ステップ・ガイド", 
<https://www.udemy.com/angular5-l/>



## 変更履歴

 - 2018.7.21 version 0.0 uploaded 

## 著作権

copyright 2018 by Shuichi Ohtsu (DigiPub Japan)


## License

MIT © [Shuichi Ohtsu](ohtsu@digipub-net.com)
Nginx 413 Request Entity Too Large

Nginxの「413 Request Entity Too Large」のエラー
原因は、Nginxとphp-fpmの「ファイルの扱いの限界を超えている」というエラー

これを直すためには、２ファイル編集します。

1. /etc/nginx/nginx.confの[client_max_body_size]
2. /etc/php.ini

## 1. /etc/nginx/nginx.confの編集
`$ vi /etc/nginx/nginx.conf`

```:/etc/nginx/nginx.conf
http {
    ...
    server {
        listen 80;
        server_name example.com;
        root [自分のrootディレクトリデフォルトは/usr/share/nginx/html];
        index index.php index.html;
        client_max_body_size 10m; # ここ重要！
    }
    ...
}
```

## 2. /etc/php.iniの編集
いじるphp.iniが環境によって違う可能性もあるので一応確認
### いじるファイルの確認
`$ php -i | grep php.ini`

```
Loaded Configuration File => /etc/php.ini
```
こういうの出てきます。

### 編集
場所は「post_max_size」と「upload_max_filesize」

viならば「/post_max」と「/upload_max」とかで検索かければすぐです。
`$ vi /etc/php.ini`

```:/etc/php.ini
...
post_max_size = 10M
...

...
upload_max_filesize = 10M
...
```

## 更新

`$ sudo systemctl restart nginx`
`$ sudo systemctl restart php-fpm`

これで私は、解決しました！
Vagrant 共有ディレクトリのパーミッション

VagrantでWordpressを入れて実験していると
パーティションの問題が発生します。

しかし、いくらvagrant側から[$ sudo chmod 777]などをやっても変えられません。

なんとパーミッションは、共有ディレクトリではvagrant側から変えられません。
ですが、、、

Vagrantfileをいじればいけます！！

```ruby:Vagrantfile
$ vi Vagrantfile
...
  config.vm.synced_folder "./", "/ws",
  mount_options: ['dmode=777','fmode=755']
...
```
dmodeはディレクトリのパーミッション
fmodeはファイルのパーミッション
実装で失敗したことから学んだこと

#結論から言えば、実装前には「充分な調査」をすることだ！

### 何を作ろうとしたか？
Bandcampの楽曲を紹介するサイト

## どこで失敗したか？
本当に開発終盤で気付いた
埋め込みタグに必要な項目を自分では取得できないことに気付いた

## なぜ、気付かなかったか？
埋め込みタグの内容を「全ては読まず」に実装を始めたこと
その時点で取得できるものなのか気付くべきだった

## 結果、どうしたか？
半自動で更新するサービスに切り替えた

## 今後
1. 必要な要素を取得できそうかを考えること[^1]
2. 具体的な実装方法を練ること

## 次回
具体的なサイト構築について語る！

## 参考
~~半自動だが実装したサイトは[こちら]()~~

[^1]: この段階では実際に実装できるか考えることとは別である、論理レベルで取得できそうか考えること
node.jsスクリプトの書き始めスニペット

node.jsで簡単なスクリプトを書く際にasync対応と終了コードを指定したかったので
スニペットにしました。

```javascript
'use strict';

async function main() {
    let ret = "hello";
    // throw new Error('reject!!');
    return ret;
}

if (require.main === module) {
    main()
        .then(resolve => {
            console.log(resolve);
            process.exit(0);
        })
        .catch(reject => {
            console.log(reject);
            process.exit(1);
        });
}
```
GAE/Goで、ファイルの変更を監視してオートビルドしてもらえない時

# はじめに
GAE/Goで開発中に、ファイルを変更してもそれを検知してオートリスタートしてくれなくなった。
これは開発効率にひびくため、ちょっと調べた。

公式ドキュメントには記述がなかったが、**`dev_appserver.py -h`**でオプション一覧を見渡したら、原因がわかった。

# 結論
いつかのversionから、 
`app.yaml`ディレクトリ下のファイルを監視するようになっているようで、
`app.yaml`よりも上の階層のgoファイルも監視させたい場合は、 
以下のように**`enable_watching_go_path=yes`**オプションを追加する必要がある。

```bash
$ dev_appserver.py --automatic_restart=yes --enable_watching_go_path=yes [app.yamlのpath]
```` 


`cloud sdk version 201.0.0`では、`enable_watching_go_path=yes`オプションをつけなくても、GOPATH以下を監視してくれていた。
そのため、最近アップデートしてはじめて出くわした。
MACからsshconfigを書いてパブリッククラウドへ自分で決めたホスト名でログインする

環境はmacbookair(HighSierra10.13.5)です。
それでは順番に書いて行きます。

#1.ssh環境を構築
+ homeのカレントディレクトリにsshフォルダを作成します。

```
$ install -m 0700 -d ~/.ssh
$ ls -la | grep ssh
drwx------   5 user  staff    160 Jul 21 12:49 .ssh
```

+ .sshフォルダへ移動し、authorized_keysフォルダを作成

```
$ mkdir authorized_keys
$ chmod 700 authorized_keys/
$ ls -la
drwx------   3 user  staff   96 Jul 21 12:39 authorized_keys
```


#2.パブリッククラウドから払い出された秘密鍵を配置
インスタンスを立てたらxxxx.pemというファイルがダウンロードできると思います。
*※ここではAWS想定で話してます*

+ 秘密鍵をディレクトリに配置します。

```
$ pwd
/Users/username/.ssh/authorized_keys
$  ls -la
-rw-------@ 1 username  staff  1692 Jul 21 12:39 test-aws01.pem
```

#3.sshconfigファイル

+ sshconfigファイルを作成します。

```
$ pwd
/Users/username/.ssh
$ vi config
$ chmod 600 config
$ ls -la
-rw-------   1 username  staff  186 Jul 21 12:49 config
```

+ configのサンプル

```
  #test-aws01
  Host         test-aws01　
  HostName     ec2-54-248-215-164.ap-northeast-1.compute.amazonaws.com
  User         ec2-user
  IdentityFile ~/.ssh/authorized_keys/test-aws01.pem
```
+ config解説

|No|対象|解説|備考|
|:--:|:----:|:----:|:--:|
|1|Host|sshでログインするサーバーを指定するときの名称|
|2|HostName|サーバーのグローバルIP、もしくはパブリックDNS名称|
|3|User|ログインユーザー名|AWSの場合はec2-user
|4|IdentityFile|鍵の置き場所|

#4.sshでログイン
+ HostNameで設定したホスト名を指定してsshでログインします。

```
$ ssh test-aws01
Last login: Sat Jul 21 03:49:48 2018 from softbank126161157126.bbtec.net

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
2 package(s) needed for security, out of 2 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-31-35-106 ~]$
```
【java】appendの中で"+"は使わない！

[前回の投稿](https://qiita.com/tor_2085/items/2455ee3a8bbbfb447abb)の続編です。

前回、Javaで文字列結合をするときはStringBuilderのappendメソッドを使うほうがいいと書きました。

しかし、appendの間違った使い方をしているコードをたまに見かけます。

#appendの間違った使用例
例えばこんなコード

```java
StringBuilder sb = new StringBuilder();
String val = "hoge";
sb.append("[" + val + "]")
```

`+`を使った文字列結合はそのたびにStringオブジェクトを生成するため処理速度が落ちます。

この例だと、`"[" + val + "]"`の部分でStringオブジェクトを生成してしまっているため、結局処理速度が落ちてしまいます。

#改善例
こうしましょう

```java
StringBuilder sb = new StringBuilder();
String val = "hoge";
sb.append("[").append(val).append("]");
```

`+`でつなぐのではなく、appendを複数回使ってつなぐのです。

では、改善前と改善後でどのくらい処理速度が変わるのでしょうか？

#処理速度の違いを検証
下記コードで処理速度を比べてみました。

```java
public class StringBuilderTest{
  public static void main(String[] args) {
    final int MAX_COUNT = 100;
    System.out.println("結合回数：" + MAX_COUNT + "回のとき");

    StringBuilder sb1 = new StringBuilder();
    StringBuilder sb2 = new StringBuilder();

    long resultTime1;
    long resultTime2;
    long startTime;
    long endTime;

    /********************* 改善前：append()内で文字列結合を行う場合 *********************/
    // 開始時間
    startTime = System.nanoTime();

    for (int i = 0; i < MAX_COUNT; i++) {
      sb2.append(Integer.toString(i) + "\n");
    }
    // 終了時間
    endTime = System.nanoTime();

    // 処理にかかった時間を算出
    resultTime1 = endTime - startTime;

    /********************* 改善後：append()を二回使う場合 *********************/
    // 開始時間
    startTime = System.nanoTime();

    // StringBuilderによる文字列結合
    for (int i = 0; i < MAX_COUNT; i++) {
      sb1.append(Integer.toString(i)).append("\n");
    }
    // 終了時間
    endTime = System.nanoTime();

    // かかった時間
    resultTime2 = endTime - startTime;

    System.out.println("① append()内で結合を行った時の処理時間：" + resultTime1 + "ナノ秒");
    System.out.println("② append()を二回使った時の処理時間：" + resultTime2 + "ナノ秒");
    System.out.println("② の方が " + (resultTime1 - resultTime2) + " ナノ秒速い");
  }
}

```

文字列結合を100回行った時の、処理速度の差を比較するプログラムです。

結果は以下。

![スクリーンショット 2018-07-21 19.11.21.png](https://qiita-image-store.s3.amazonaws.com/0/159675/05e348c3-d8d8-2f9f-31d7-3554627f4618.png)


`append`を二回使うほうが速いですね。
[Spring Boot] URLに含まれる文字列から動的にプロパティを取得する方法


Environmentを利用して動的にプロパティファイルから値を取得する。


#バージョン
spring boot 2.0.3.RELEASE

#プロパティファイル
```application.properties
sample.name=hoge
sample.age=20
```

# Environmentを利用したConfigurationクラス
EnvironmentをインジェクションしてgetPropertyメソッドを呼び出す。

```SampleProperty.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@Configuration
// @PropertySourceでプロパティファイルの場所を指定
@PropertySource("classpath:/application.properties")
public class SampleProperty {
	
	// Environmentをインジェクション
	@Autowired
	private Environment env;
	
	public String get(String key) {
		// Environmentからプロパティ値を取得
		return env.getProperty("sample." + key);
	}

}
```

# RestController（Configurationクラスを呼び出すクラス）
URLに含まれるパスをkeyとしてConfigurationクラスから値を取得する。

```SampleController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@Component
@RestController
public class SampleController {

	@Autowired
	private SampleProperty prop;

	@GetMapping(path = "/user/{key}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	public String getUser(@PathVariable String key) {
		
		String result = prop.get(key);
		
		if (result == null) {
			result = "値が取得できませんでした。";
		}
		
		return result;
	}
}

```

#動作確認
ブラウザからhttp://localhost:8080/user/name にアクセス

![spring1.png](https://qiita-image-store.s3.amazonaws.com/0/31363/a015be97-ad4d-591f-cc1d-d4bd4c476542.png)

ブラウザからhttp://localhost:8080/user/age にアクセス
![spring2.png](https://qiita-image-store.s3.amazonaws.com/0/31363/6117e004-1fcc-319a-37c0-d9fdf2ca153c.png)
UE4.19でスプライトが切れる。

#スプライトを更新すると、なぜか切れる時（UE4.19）

再読み込みすると参照している座標は適正なのに切れた画像になる。
![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/128851/3ad6c537-bc39-98f6-8a1a-abca979e8d30.jpeg)

適当に一時的に参照座標を変えてEnter。
![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/128851/06a35a79-1155-3940-a386-cdddfca4f118.jpeg)

直った。
![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/128851/b0ac71f2-cc58-8f64-476d-daa4533f8151.jpeg)
Lazurite ide入れてみた。

#概要
Lazurite ide 入れてみた。

#だめなとこ。
　classが無い。
　mathのサンプル無い。
　serboとpwm無い。
　Stringのサンプル無い。
　timerのサンプル無い。

#良いところ。 
　structでライブラリできてる。凄い。
　asmのサンプルある。
　シリアルLEDのライブラリある。


以上。
Laravel mix で element-ui やろうとしたらUIフォントがうまいこと出ないやつ

laravel mix で ドキュメント通りに導入しても、UIに使われているフォントがうまいこと設置されないので、

```js
mix.js('resources/assets/js/app.js', 'public/js').sourceMaps()
   .sass('resources/assets/sass/app.scss', 'public/css')
   .copy('node_modules/element-ui/lib/theme-chalk/fonts/element-icons.woff',
         'public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.woff');
```

のように copy() 関数を追加してpublicフォルダ内にフォントファイルが置かれるようにしました。
[こちら](https://qiita.com/sygnas/items/e09171288227f1f4e059)でやっておられることをLaravel mix でやっただけということです。

参考：[Vue.jsのコンポーネント集「Element」導入でハマったポイント](https://qiita.com/sygnas/items/e09171288227f1f4e059)
参考：[Laravel 5.6 アセットのコンパイル(Laravel Mix)
](https://readouble.com/laravel/5.6/ja/mix.html)
Android：GestureDetectorを使いながらMotionEvent.ACTION_UPを検知する

結論から書くと、`onTouch`で`MotionEvent.ACTION_UP`だけを検知させ、他のイベントは`GestureDetector`に丸投げすると実現できる。

## Javaサンプルコード
Kotlin使いの方は適宜読み替えてください。
`GestureDetectorCompat`にした場合は未検証ですが、同じ挙動になるはずです。

``` MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {

    private TextView sampleView;
    private GestureDetector gestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sampleView = findViewById(R.id.sampleView);
        sampleView.setOnTouchListener(this);

        gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                // do something
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                // do something
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                // do something
                super.onLongPress(e);
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                // do something
                return true;
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                // do something
                return true;
            }
        });
    }

    @Override
    public boolean onTouch(View v, MotionEvent e) {
        // ここで指が画面から離れたことを検知し、他のイベントはGestureDetectorに委ねる
        if (e.getAction() == MotionEvent.ACTION_UP) {
            // do something
        }

        return gestureDetector.onTouchEvent(e);
    }
}
```

## 補足
コード内の"do something"コメントのところに`Log`を仕込むと、動きを確認できます。
`GestureDetector`では他に`onSingleTapConfirmed`や`onFling`などもサポートされていますが、ここでは割愛しています。
詳しく知りたい方は、下記URLから公式ドキュメントをご覧ください。

https://developer.android.com/training/gestures/detector

また、上のコードでは`#onTouch should call View#performClick when a click is detected`という警告が出ます。
これについては、stackoverflowに回答がありました。

https://stackoverflow.com/questions/24952312/ontouchlistener-warning-ontouch-should-call-viewperformclick-when-a-click-is-d

https://stackoverflow.com/questions/25390984/android-marker-ontouch-should-call-viewperformclick-when-a-click-is-detected?rq=1

対処としては、`onTouch`内で以下のように`performClick`を呼んでやると解消できるようです。

```
        if (e.getAction() == MotionEvent.ACTION_UP) {
            v.performClick();
            // do something
        }
```

ただ、今回の場合は`GestureDetector`でクリックイベントに対処するんだから、わざわざ`performClick`を呼ぶ意味があるのか？という気がします。
実際、`performClick`を呼ばなくても動きは問題なく見えます。
`OnTouchListener`と`OnClickListener`を併用している場合には考慮が必要になるのかもしれませんが、とりあえずAndroid Studioの警告を消すためには`performClick`をコールしておくのが無難であるようです。

## 最後に
記載内容に不備などがありましたら、教えていただけると助かります！
[WIP] 画像が重い、レスポンシブル、Retina対応、それ lazysizes で解決できます

lazysizesはsrcsetなどレスポンシブの画像や`iframe`、`script`、`widgets`にも対応した高速[ジャンクフリー]
(https://developers.google.com/web/fundamentals/performance/rendering/?hl=ja)で、SEOにも対応可能な、画像の遅延読み込み用ライブラリです。ライブラリを読み込むだけで、使えるようになりますよ。

レスポンシブな画像に関する開発においては最高の手法になることは間違いなし。
CSSの`meadia`属性とメディアクエリを共有して、レスポンシブの画像のサイズを自動で計算してくれる。CSSでのレイアウトと、HTMLでのコンテンツ・構造を分離するのに役立つはず。
使い方も超シンプル。しかも機能を拡張するための追加のプラグインもあるので使ってみてほしい。

## 使い方
1. まずは、ミニファイされたlazysizesのスクリプトをダウンロードして、Webページに読み込みましょう。
npmインストールすることも可能ですよ。

```shell

# npmコマンドの場合
npm install lazysizes --save 
# bowerコマンドの場合
bower install lazysizes --save
```

```javascript

<script src="lazysizes.min.js" async=""></script>
```

2. lazysizes のすごいところはJSの設定がいらないんだ。`<img>``<iframe>`に`lazyload`クラスを付け加え、`datasrc`, `data-srcset`属性で読み込む画像を設定してくれ。画像がロードされるまでの間、低画質で表示しておく仮画像は`src`要素に設定しておけば表示できるぞ。

```
<!-- レスポンシブなサイズの計算も自動でできるから便利だぞ: -->
<img
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w" class="lazyload" />
```

```
<!-- iframe も使えるぞ -->
<iframe frameborder="0"
	class="lazyload"
    allowfullscreen=""
    data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>
```

> WIP

## APIについて

### JS API

#### JS API - イベント

lazysizesはその動作を拡張もしくは変更するための3種のイベントを用意しています。
簡単なテキスト処理やファイル操作の問題と解法(自分用メモ)

# はじめに
テキスト処理やファイル操作の問題と解法に関する自分用のメモです。
ご参考になれば幸いです。

# 問題と解法の例
- 問題1：連番のファイルの中から、抜けている番号を探す。

```
ls -v "file_*.json" | sed 's/^file_//' | sed 's/\.json$//' | awk '$1!=p+1{print p+1"-"$1-1}{p=$1}'
```
ls -vで番号順にファイルを表示した後、sedで数字以外を削除して、awkで数字の抜けを探しています。[Finding gaps sequential numbers](https://stackoverflow.com/questions/15867557/finding-gaps-sequential-numbers)を参考にしました。

- 問題2：行番号のついたcsvファイルから特定の行番号を含む行のみを取り出す。

```
for number in $(cat row_numbers.txt); do cat input_file.csv | grep "^"$number"," >> output.csv ; done
```
ここでは
input_file.csv:行番号を含むcsvファイル
row_numbers.txt:取り出したい行番号を含むファイル
output_file.csv:取り出した結果を出力するファイル
としました。

- 問題3:あるキーワードを含むファイルを複数個まとめてあるディレクトリに移動

```
find . -name "*.xml" | xargs grep your_keyword | cut -d':' -f1 | sort | uniq | xargs -I {} mv {} dist_dir/
```
[mv files with | xargs](https://askubuntu.com/questions/487035/mv-files-with-xargs)を参考にしました。
Declarative Pipeline で Jenkins に保存された認証情報を利用する

## 認証情報を利用する

Jenkins の Declarative Pipeline で Jenkins に保存されている認証情報を利用する際に `environment`ディレクティブ内で `credentials()` というヘルパメソッドが利用できます。

```groovy
pipeline {
    agent any
    environment {
        CREDENTIALS = credentials('credentials-id')
    }
    stages {
        stage('Print Environment Variables') {
            steps {
                sh 'printenv'
            }
        }
    }
}
```

これにより、 `CREDENTIALS` という環境変数に認証情報が持っている値が格納され、認証情報の中身を環境変数から読み込めるようになります。

種類が `Secret text` の場合には項目 `Secret` に保存された値が入り、種類が `ユーザー名とパスワード` だと項目 `ユーザー名` と項目 `パスワード` に保存された値が `ユーザー名:パスワード` というコロンで結合した形で入ります。また、認証情報変数名の後ろに `_USR` をつけた環境変数(この例だと `CREDENTIALS_USR` )に `ユーザー名` が、認証情報変数名の後ろに `_PSW` をつけた環境変数(この例だと `CREDENTIALS_PSW` )に `パスワード` が入ります。

## 認証情報をパラメータ化する

認証情報をパラメータ化する場合には、 `parameters` ディレクティブに `credentials` というパラメータを設定し、 `credentials()` メソッドに **GString** で渡します。

```groovy
pipeline {
    agent any
    parameters {
        credentials(
            name: 'credentials',
            credentialType: 'com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl'
        )
    }
    environment {
        CREDENTIALS = credentials("${params.credentials}")
    }
    stages {
        stage('Print Environment Variables') {
            steps {
                sh 'printenv'
            }
        }
    }
}
```

```groovy
    environment {
        CREDENTIALS = credentials(params.credentials)
    }
```

というように、パラメータの変数を直接渡したくなりますが、以下のようなエラーが出てしまうので、必ずGStringで渡す必要があります。

```
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 10: Internal function call parameters must be strings. @ line 10, column 23.
           CREDENTIALS = credentials(params.credentials)
                         ^
```
ClickOnceでターゲットCPUを変更するとユーザー設定を引き継げない

# はじめに
サーバーリプレースでデータベース変更(Oracle 11g → PostgreSQL 9.6)になるため、アプリケーションの改修作業をしており、その中でClickOnceを使用したものがありました。

以前、別アプリケーションの改修作業をした際には、下記の方法でユーザー設定(user.config)を引き継げることが出来ました。

[ClickOnceでバージョンアップしても消えないデータの残し方](https://qiita.com/minoru-nagasawa/items/946831c9c0c3513dae12)

```csharp:データ引き継ぎ
    if (!Properties.Settings.Default.IsUpgraded)
    {
        Properties.Settings.Default.Upgrade();
        Properties.Settings.Default.IsUpgraded = true;
        Properties.Settings.Default.Save();
    }
}
```

# 調査
今回はユーザー設定(user.config)を引き継げなかった上に「プログラムと機能」には以前のバージョンが残ったままとなる原因を簡単なプログラムを作成して調査しました。

※ClickOnceでは、アセンブリバージョンで設定ファイル(user.cofig)が作成されるので、アセンブリバージョンを変更してしまうと前バージョンの設定を引き継げなくなる。ClickOnceを使う場合は発行バージョンでバージョンを管理する。よって、アセンブリバージョンは1.0.0.0のままにしておく。

##プログラム仕様
user.configには、"テスト"が初期値に入っておりテキストボックスに初期表示し、ボタンをクリックすることで値を書き換えることが出来る。

## 調査開始
発行バージョン 3.0.1.0、アセンブリバージョン 1.0.0.0
"テスト"から"ABC"に変更してユーザー設定を書き換えた。
![ClickOnceアプリ.png](https://qiita-image-store.s3.amazonaws.com/0/14053/60836653-0dd6-4468-c13b-084665814548.png)

発行バージョン 3.0.2.0、アセンブリバージョン 1.0.0.0
「プログラムと機能」でも以前のバージョンは消えて最新バージョンのみとなっている。
![ClickOnce重複なし.png](https://qiita-image-store.s3.amazonaws.com/0/14053/6a71c492-30e2-67be-258c-e61942ad128c.png)

初期表示に引き継いだ値が表示されています。
![ClickOnceアプリ.png](https://qiita-image-store.s3.amazonaws.com/0/14053/60836653-0dd6-4468-c13b-084665814548.png)

ここで一旦、発行バージョン 3.0.2.0 はアンインストール時に以前のバージョン 3.0.1.0 に戻す。

発行バージョン 3.1.0.0、アセンブリバージョン 1.0.0.0
プラットフォームターゲットをAnyCPUからx86に変更。

「プログラムと機能」には以前のバージョンが残ったままとなる。
![ClickOnce重複.png](https://qiita-image-store.s3.amazonaws.com/0/14053/488570c3-15cc-8aed-10b6-b7845c275173.png)

初期表示のまま、引き継いだ値が表示されない。
![ClickOnceアプリ3.png](https://qiita-image-store.s3.amazonaws.com/0/14053/ef17d3d3-99ae-4d4b-e10b-33f12de7b02f.png)


# 原因
ClickOnceの配布条件にはターゲットCPUも含まれているということになります。

このアプリケーションはmdbファイルの読み込み処理があり、64bit版Windowsには「Microsoft.Jet.OLEDB.4.0」が存在しないため、プラットフォームターゲットをAnyCPUからx86にしました。これ以外にもClickOnceでCrystalReportインストール時のlog4net Version=1.2.10.0エラーなどもあり、64bit対応に苦労した経緯があったのです。

* [64bit版Windowsでの「Microsoft.Jet.OLEDB.4.0」について](https://qiita.com/yaju/items/86314412741deb806366)
* [Visual Studio 2010のVisualStudioインストーラーでCrystal Reportsのlog4net.dll関連エラーのためインストーラーが作成できない](http://oyaji-pgm.blogspot.com/2013/03/visual-studio-2010visualstudiolog4netdll.html)
* [64bitOSで32bit版Crystal Reportsインストール](https://qiita.com/yaju/items/b81710fcde6dc4986f29#64bitos%E3%81%A732bit%E7%89%88crystal-reports%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)

# 対応
強引にユーザー設定(user.config)を引き継ぐ処理を入れようとしたら、Application Data の内容を読み取りしようとするとアクセス拒否されてしまうのです。
アクセス権限までどうこうするまでやりたくないので、ここは諦めてユーザーさんに設定値を再入力してもらうことにします。

もともとユーザー設定を引き継ぐ処理は入ってなくて、改修のついでに入れようとしたんだよね。次のバージョンからはターゲットCPUが同じになるのでユーザー設定は引き継がれる。

# 最後に
Windows 7のPCを購入するのも難しくなってきました。そうすると、Windows 10 64bit版のPCを購入することになります(今更32bit版にしないかなと・・・)
その割には、Officeは32bit版をインストールされたりするんだよな。

64bit版の「Microsoft.Jet.OLEDB.4.0」を提供しないから面倒くさいんだよね。

ClickOnceによるインストール自体がもう古いのかな。
PHPStan, phan を Docker Compose から実行する

## Docker イメージ

PHPStan は公式で docker イメージを提供しているので、それを使う。

[phpstan/phpstan](https://hub.docker.com/r/phpstan/phpstan/)

phan は公式で docker イメージを提供していないので、ここでは cloudflare が提供しているイメージを利用する。

[cloudflare/phan](https://hub.docker.com/r/cloudflare/phan/)

## 設定

```:ディレクトリ構成
- src/
    - .phan/
        - config.php  # phan 用設定ファイル
    - index.php       # 解析対象
    - phpstan.neon    # PHPStan 用設定ファイル
- docker-compose.yml
```

```yml:docker-compose.yml
version: "3"
services:

  phpstan:
    image: phpstan/phpstan:latest
    volumes:
      - ./src/:/app
    command: analyze

  phan:
    image: cloudflare/phan:latest
    volumes:
      - ./src:/mnt/src
```

それぞれマウント先を `/app` と `/mnt/src` とする。

### 設定ファイル例

以下、PHPStan と phan 用の最低限の設定例。

実際の目的に合わせて適宜書き換える。

設定項目については各ドキュメントを参照のこと。

* [PHPStan](https://github.com/phpstan/phpstan#configuration)
* [Phan](https://github.com/phan/phan#usage)

```yml:src/phpstan.neon
parameters:
	level: 7 # 目的に合わせて変える
	paths:
		- %currentWorkingDirectory%
```

```php:src/.phan/config.php
<?php

return [
    'target_php_version' => 7.1, // 目的に合わせて変える

    'directory_list' => [
        './',
    ],

    "exclude_analysis_directory_list" => [
    ],
];

```

## 実行

```bash:PHPStanの実行
$ docker-compose run --rm phpstan
```

```bash:phanの実行
$ docker-compose run --rm phan
```
【エラー】このアプリはお使いのpcでは実行できません

processingをインストールし、起動したときに「このアプリはお使いのpcでは実行できません」と出たので対処方法を簡単にメモ。

#環境
windows (64bit OS, x64 bit ベースプロセッサ)
processing 3.3.7 (winsows 64 bit)

#原因
zipファイルをLhaplusを使って解凍したときに、以下のようなエラーが出てた。

```
正常に解凍できません。CRCが一致しないか、出力先ファイルが使用中です。
```

どうやら大容量のファイルではZIP64というフォーマットが適用されており、これに対応していない展開ソフトではエラーになる模様。

#対策
Lhaplusではなくて、通常のエクスプローラーで展開したら普通にできた。

#ちなみに
windows 64bitでは普通にprocessing 32bitが動くので、どうしても動かなかったら、そっちを使ってもよいかも。

#参考
[大容量のzipを展開(解凍)できない　bad CRCなどのエラーが発生する場合の対処法](https://qiita.com/zakisanf05/items/6b305f505f9c96cd1935)
GraphiQL で Header が指定できない対応策

# 問題

GraphiQL は、シンプルで使いやすいものの、機能が乏しい。

例えば Header を指定できないので、ログイン情報（トークンなど）を Header `Authorization: Bearer TOKEN` で送信していると、送信できなくて詰む。

# 結論

Chromeの拡張機能(デスクトップもある） Altair 使うと良さげ。

https://github.com/imolorhe/altair

# 回避策

みんな困っているようで、調べていたら、下記の Issue にぶち当たった。

https://github.com/graphql/graphiql/issues/59

GraphiQL を使う限り、今の所は、ある程度Hackする必要がありそう。

## 1. GraphiQL を改造

無理矢理 Header を差し込む、静的なHTMLを作成する 

https://gist.github.com/sasso/3c3d728e0049d5b66a2c19b349b7f164

このHTMLを貼って、どこかに置いておけば良いので、楽かも。

## 2. Header を入れる拡張機能

https://github.com/graphql/graphiql/issues/59#issuecomment-254736162

## 3. Auth GraphiQL を使う

こちらで、 GraphiQL を Wrap したものがある。

https://github.com/vitalcode/auth-graphiql


## 4. Altair 使う

GraphiQL は、補完が強すぎてタイポする、一部の Macの Emacs バインディングが消える (`C-f` が使えなくてつらい) など、編集性能でも使いにくかった。
ので、この際乗り換えてしまおう。

https://github.com/imolorhe/altair

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103885/581b8cbb-492a-cbb1-58d8-e9a388034537.png)

補完は GraphiQL ほどではないけど、使いやすい。

# Appendix

同名のPythonライブラリがあるので注意。

https://github.com/altair-viz/altair
WP REST API　を使って独自エンドポイントを設定する。

#WP REST API　を使って独自エンドポイントを設定する。

参考資料
<a href="https://ja.wp-api.org/">WP  REST API　公式ドキュメント</a>
https://www.sofplant.com/blog/tech/wp-rest-api-tips/
<p>WordPress 4.7以降より、標準で利用できる様になった[WP REST API]を使って独自エンドポイントを設定し、クロスドメインでデータの取得、表示を行います。</p>




<p> wordpressサイトをhogehoge.jp</p>
<p>データを受け取り、表示するサイトをfugafuga.jpと仮定します。</p>

hogehoge.jp


functions.php内に記述してください。

```php:functions.php
<?php
//wordpressに用意されているアクションフックで独自APIを作成します。

add_action('rest_api_init', function() {
	register_rest_route( 'wp/v2', '/org_api', array(
		'methods' => 'GET',
		'callback' => 'org_api',
	));
});
function org_api( ) {

	$contents = array();//return用の配列を準備
	$myQuery = new WP_Query();//取得したいデータを設定
	$param = array(
		'post_type' => 'blog',
		'posts_per_page' => 3,
		'order' => 'DESC'
	);
	$myQuery->query($param);
	 if($myQuery->have_posts()):
		 while ( $myQuery->have_posts() ) : $myQuery->the_post();
				$ID = get_the_ID();
				$title = get_the_title();
				array_push($contents, array(
					"title" => $title,
					"id" => $ID
				));
		 endwhile;
	 endif;
	 return $contents;// WP REST APIを利用するときはjsonで返ってくる様に設定されているので、json_encodeは必要ありません。
 }
```

<p> http://hogehoge.jp/wp-json/wp/v2/org_api  にアクセスしjsonが返ってくることを確認してください。</p>
 <p>この時点でエラーが発生する場合はphp側の構文エラーなどが考えられます。</p>


データを受け取る。
クロスドメインで利用する場合はdataTypeにjsonpを指定します。
fugafuga.jp

```html:index.html
<p id="view_area"></p>
```

```html:wp_rest_api.js
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
	$(function(){
			$.ajax({
			type: 'GET',
			url: 'http://hogehoge.jp/wp-json/wp/v2/org_api?_jsonp=callback',//コールバック関数名を指定する。 
			dataType: 'jsonp',
			jsonpCallback: 'callback',//コールバック関数名を指定する。
			success: function (jsonp) {
					$(jsonp).each(function(index,el){
                    let id = (jsonp[index]['id']);
					let title = (jsonp[index]['title']);
						$('#view_area').append(
						'<p>' + id + '</p>'
                         + '<p>' + title  + '</p>'
						);
				});
			}
		});
	});
</script>
```

以上でデータの表示が可能かと思います。
データが取得できなかった際の処理などは省いております。
独自エンドポイントを利用することで、標準のAPIではちょっと取得しにくいデータや、(カスタム投稿など)
リクエストのurlに好きなパラーメータを渡し、php側で利用することで柔軟なデータの取得が可能かと思います。

```javascript:wp_rest_api.js
data : {
	'param' : 'key_word'
}
```

```php:functions.php

<?php
//wordpressに用意されているアクションフックで独自APIを取得します。

add_action('rest_api_init', function() {
	register_rest_route( 'wp/v2', '/org_api', array(
		'methods' => 'GET',
		'callback' => 'org_api',
	));
});
function org_api( ) {
$param = $_GET['param'];
}
```

<p>※エンジニアとしての経験が非常に未熟で間違いなどが多々あるかもしれません、ご了承ください。</p>
AWSのSSL証明書を更新(AWS Certificate Manager)

ごめんなさい。
気づいたらSSL証明書の期限が切れていましたorz

AWSでSSL証明書を作成（AWS Certificate Manager、略してACM）、
それをELBに割り当てていた場合に、
SSL証明書の期限が切れてしまった場合の対処方法です。

## この記事が役に立つ条件

1. ACMでSSL証明書を作成済み
2. 作成したSSL証明書はELBに割り当てている
2. そのSSL証明書の期限が切れてしまった
3. DNS設定はRoute53で行っている

## おおまかな手順

- STEP 1　まずは証明書を作り直す
- STEP 2　DNS検証を済ませる
- STEP 3　ELBへの割り当て

## STEP 1　まずは証明書を作り直す
どうやら期限切れの証明書は再利用ができず、もう一度作成しなおしのようです。

1-1） [ACM](https://console.aws.amazon.com/acm/home)を開いて **[証明書のリクエスト]** ボタンを押します。
1-2） **[パブリック証明書のリクエスト]** ラジオボタンを選択します。
　*※ ここは環境によって[プライベート証明書のリクエスト]になる場合もあるでしょう。*
1-3） **[証明書のリクエスト]** ボタンを押します。
1-4） **[ドメイン名*]** を入力します。　例 `hoge.com`
1-5） **[次へ]** ボタンを押します。
1-6） **[DNS の検証]** ラジオボタンを選択します。
1-7） **[確認]** ボタンを押します。
1-8） **[確定とリクエスト]** ボタンを押します。
1-9) しばらく待って[DNS 設定をファイルにエクスポート]()リンクを押下しcsvファイルをダウンロードします。
1-10） **[続行]** ボタンを押します。
　*※ このとき一覧に表示されるアイテムの中から自分が作成したSSL証明書の「識別子」を確認しておきましょう。STEP 3で必要になります。*

## STEP 2　DNS検証を済ませる
DNS検証を選んだのでCNAMEレコードを作成します。

2-1） ダウンロードしたcsvファイルを開きます。利用する項目は以下。

- Record Name
- Record Type（=CNAME）
- Record Value

2-2） [Route53](https://console.aws.amazon.com/route53/home)を開き、対象ドメインの管理画面へ移動します。
2-3） **[Create Record Set]** ボタンを押します。
2-4） 以下のとおりに入力します。

| 入力欄 | 設定値 |
|:---|:---|
| Name: | *csvのRecord Name* |
| Type: | CNAME |
| Value: | *csvのRecord Value* |
2-5） **[Create]** ボタンを押します。
2-6） [ACM](https://console.aws.amazon.com/acm/home)に戻って **状況** が `発行済み` になるのを待ってください。

## STEP 3　ELBへの割り当て

以上でSSL証明書が新たに作成できたので、これをELBに割り当てします。

3-1） [ELBの一覧](https://console.aws.amazon.com/ec2/v2/home#LoadBalancers:)を開きます。
3-2） 対象となるELBのチェックボックスを選択します。
3-3） **[リスナー]** タブをクリックします。
3-4） すでにSSL証明書が設定されていれば[変更]()リンクがあるはずですので、それをクリックします。
3-5） 証明書タイプは **[ACM から証明書を選択する (推奨)]** を選択します。
3-6） ポップアップされた証明書のプルダウンから、STEP1で追加したSSL証明書を選択します。
3-7） **[保存]**ボタンを押します。
3-8） [ACM](https://console.aws.amazon.com/acm/home)に戻って **使用中?** が `はい` になっていることを確認してください。

## さいごに

これでSSL証明書が更新されました。
対象のサイトにアクセスすると「期限切れ」のエラーメッセージが消えているはずです。
また、期限切れになった証明書を削除する場合は、ELBなどすべてのリソース割り当てを解除したのち、
ACMから対象の証明書を選択して「削除」してください。
みんなAdobe AIRでHTML5使えるの忘れすぎ

Adobe Airは、flashだけでなくHTML(HTML5)も使えるElectronみたいでなかなかイカす立ち位置なのに
Electronやnw.jsがキテるなか**何故AIRはもはや忘れ去られたように影が薄いのか**
##それぞれの特徴
| Electron                         |         |       Adobe AIR                          |
|:---------------------------------|:-------:|-----------------------------------------:|
| (Node.js+)HTML+JS+CSS            | 言語    | Flash、またはHTML+JS+CSS                  |
| Chromium                         | レンダラ | Safariと同じやつ                         |
| Chromiumをバンドル(めっちゃでかい) | 配布    | インストーラのみ、またはバンドル(コンパクト) |
| Win、Mac、Linux                  | OS      | Win、Mac、Linux(サポートは終了)、Android   |
###Electron
- 利点
    - Node.jsの恩恵
    - コミュニティが活発
    - 素晴らしいライセンス
    - 機能が豊富(BrowserWindowとかめっちゃいじれる)
        - **楽しい**
    - 例多し
- 短所
    - 重い、でかい(ファイルサイズ100MBは余裕)
    - スマホ無理(monacaなんかを使う必要がある)

###Adobe AIR
- 利点
    - Flashが使える
    - AIR自体は結構有名なのでランタイム入れてる人多い
    - まずまずなライセンス(LGPL)
    - スマホいける
    - 小さい(バンドルしても二十数MB~)
    - (Flashを利用した)例は、PC、Androidともに多し
- 短所
    - **情報量が少ない**(重要)
        - 特にHTMLの情報が絶望的に少ない。一応公式のがあるが

ChromiumやSafariと、どちらでもモダンブラウザのレンダラエンジンで恩恵を受けられる。
HTML5、WebGL、etc.
##結論
(\*´ω｀*)ﾊﾔﾚ
###ちなみに
20年ぐらい前からWindowsにすでに存在していたHTML Apprication(**HTA**)っていうのも忘れてはなりません。結構面白いですコレ
まぁ悪用した人のせいで検索結果が残念なことになっていますが
PC-88 機械語で文字出力

参考
[PC-8801 I/Oマップ](http://www.maroon.dti.ne.jp/youkan/pc88/iomap.html)

```
db 71           in      a, ($71)        ; 拡張ROMセレクト
f5              push    af
3e ff           ld      a, $ff          ; メインROM
d3 71           out     ($71), a

; putc
3e xx           ld      a, xx
df              rst     $18             ; OUTIO
f6 xx           or      xx
df              rst     $18

; puts
21 xx xx        ld      hl, xxxx
cd 50 55        call    $5550

f1              pop     af
d3 71           out     ($71), a
c9              ret
```

![putc.png](https://qiita-image-store.s3.amazonaws.com/0/257554/c716d531-4f9d-bce2-4c1b-aa56f697741f.png)

![puts.png](https://qiita-image-store.s3.amazonaws.com/0/257554/da3ea332-cbb1-e0d9-a365-9bf318b0a94d.png)
Gitlab Container Registryのお掃除

# はじめに
gitlabでソース管理を行い、CIにて[gitlab container registry] (https://docs.gitlab.com/ee/user/project/container_registry.html) にdocker imageを登録しています。
ディスク消費量が増え続けてきたのでゴミ掃除したお話です。

# 結論

- [gitlab-ctl registry-garbage-collect](https://docs.gitlab.com/omnibus/maintenance/#container-registry-garbage-collection)じゃ上手く消えない場合がある。
- [docker-distribution-pruner](https://gitlab.com/gitlab-org/docker-distribution-pruner)使ったらちゃんと消えました。

# 経緯
1年経過したころの話です。gitlab serverのディスク消費量、何かすごい増えているなーと気づいきました。
そして、
`/var/opt/gitlab/gitlab-rails/shared/registry`
のディスク消費量を確認すると・・・。

```
$ sudo du -s -h *
37G     artifacts
513M    cache
0       lfs-objects
32K     pages
89G     registry
0       tmp
$
```

となっており、untaggedなイメージの履歴が延々と残り続けているのでゴミ掃除を行う事にしました。

# registry-garbage-collectの実行
gitlab公式ドキュメントにそって、下記コマンドで実行してみます。

```
$ sudo gitlab-ctl registry-garbage-collect
```

5分くらいで終わりました！早い！でも・・・

```
$ sudo gitlab-ctl registry-garbage-collect
 ....
5726 blobs marked, 0 blobs eligible for deletion
ok: run: registry: (pid 32084) 0s
$ 
```

> **0 blobs eligible for deletion**

ん？消えていない・・・！なんでだろーと思い、色々探していると・・・下記情報が見つかりました。

https://gitlab.com/gitlab-org/gitlab-ce/issues/21690

なるほど。消えない場合があるみたいですね。で、
　https://gitlab.com/gitlab-org/docker-distribution-pruner
使えばうまい事消えるみたいですね。やってみましょう。


# docker-distribution-prunerの実行

## 事前準備
下記のように実行できるようにしました。

```
$ yum install go
$ go get -u gitlab.com/gitlab-org/docker-distribution-pruner
$ chmod 755  go/bin/docker-distribution-pruner
```

## 実行
実行してみます。

```
$ cd ./go/bin
$ sudo ./docker-distribution-pruner -config=/var/opt/gitlab/registry/config.yml -delete-old-tag-versions=false --delete
 ...
INFO[0000] BLOBS INFO: Objects/Unused: 258 / 4114 Data/Unused: 6.0 GB / 83 B
WARN[0000] DELETEABLE INFO: 5540 links, 4114 blobs, 0 other, 83 B
$
```

お、よさそうですね！削除結果は、バックアップフォルダに入っているので、一通り消えちゃいけないものが消えていないか確認して、バックアップフォルダも削除します。

```
$ cd /var/opt/gitlab/gitlab-rails/shared/registry
$ rm -rf docker_backup
```

### 補足
 - `--delete` を付けずに実行すれば何が削除されるか事前に確認することができます。
 - 実行した結果は、 `repositories.csv` に出力されています。imageの一覧等に確認する時に便利かも。。。
SymfonyのFormの基礎

SymfonyのFormの簡単な解説です。

詳細は[公式ドキュメント](https://symfony.com/doc/3.4/forms.html)を参照してください。

ステップは３つです。
1. Entityを作成
2. ControllerでFormの作成
3. Formのレンダリング

---

# Entityを作成

Entityはデータの箱で基本的にクラス変数とsetter, getterでできています。
フォームへ出力させるためにはsetterとgetterは必須です。
例えばタスクと期限を持つシンプルなTaskエンティティは以下のようになります。

```php:src/AppBundle/Entity/Task.php
class Task
{
    protected $task;
    protected $dueDate;

    public function getTask()
    {
        return $this->task;
    }

    public function setTask($task)
    {
        $this->task = $task;
    }

    public function getDueDate()
    {
        return $this->dueDate;
    }

    public function setDueDate(\DateTime $dueDate = null)
    {
        $this->dueDate = $dueDate;
    }
}
```

---

# ControllerでFormの作成

controllerでformを作成します。
下記の例のbuilderに対して `add` している第二引数でフォームの型を指定します。
こちらで指定した型でレンダリングされます。

```php:src/AppBundle/Controller/DefaultController.php
class DefaultController extends Controller
{
    public function newAction(Request $request)
    {
        // Taskに対して例としてダミーデータをセットしています
        $task = new Task();
        $task->setTask('Write a blog post');
        $task->setDueDate(new \DateTime('tomorrow'));

        $form = $this->createFormBuilder($task)
            ->add('task', TextType::class)
            ->add('dueDate', DateType::class)
            ->add('save', SubmitType::class, array('label' => 'Create Task'))
            ->getForm();

        return $this->render('default/new.html.twig', array(
            'form' => $form->createView(),
        ));
    }
}
```

---

# Formのレンダリング

twigファイルにてFormをレンダリングします。

```twig:app/Resources/views/default/new.html.twig
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
```

すると[こちら](https://symfony.com/doc/3.4/_images/simple-form.png)の画像のように出力されます。

---

時間があればもうちょっと追記するかも。

---

この記事およびコードは[Creative Commons BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)ライセンスに従います。
JavaScript版のAWSAppSyncClientにfragmentMatcherを設定する

# TL;DR 

union型を扱った時にJavaScript版のAWSAppSyncClientにfragmentMatcherを設定する方法がなかなかわからなかったので共有しておきます。
(apollo-clientの情報は結構見つかりました)

## version

```
aws-appsync@1.1.4
```

## code

JavaScript版と書いていますが以下はTypeScriptです。すいません。

```typescript
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import { AWSAppSyncClient, AUTH_TYPE } from 'aws-appsync';

const fragmentMatcher: IntrospectionFragmentMatcher = new IntrospectionFragmentMatcher({
  introspectionQueryResultData: {
    __schema: {
      types: [] // no types provided
    }
  }
});
const client: AWSAppSyncClient = new AWSAppSyncClient({
  url: ENV.awsAppSync.graphqlEndpoint,
  region: ENV.awsAppSync.region,
  auth: {
    type: AUTH_TYPE.OPENID_CONNECT,
    jwtToken: async () => getAccessToken()
  },
  cacheOptions: {
    fragmentMatcher: fragmentMatcher
  }
});

```
styled-components の mixin としての使い方が便利そう

最近 <a href="https://github.com/styled-components/styled-components" target="_blank" rel="nofollow noopener">styled-components</a> を触り始めています。
触っている中で便利だなと思った mixin としての使い方について書こうと思います。

## styled-components 概要

* CSS in JS の一種
* JavaScript の <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/template_strings" target="_blank" rel="nofollow noopener">タグ付きテンプレートリテラル</a>を使い、Reactコンポーネントに style を適用する
* 直接 React コンポーネントを定義出来るので、```className``` によるコンポーネント - style 間のマッピングを取り除くことができる

## mixin とは

sass などでおなじみだと思うので、<a href="https://sass-lang.com/documentation/file.SASS_REFERENCE.html#mixins" target="_blank" rel="nofollow noopener">sass公式ドキュメントの mixin の説明</a> を引用します。

> Mixins allow you to define styles that can be re-used throughout the stylesheet without needing to resort to non-semantic classes like .float-left.
>
> (意訳) Mixins は .float-left のような非セマンティックなクラスに頼ること無く、 stylesheet 全体で再利用できる style を定義できます。

以下に sass のサンプルコードを載せました。このように、継承とは違い、共通利用できる style を切り出して適用するイメージです。複数の mixin を適用することも出来ます。

```sass
=mixin-color
  color: white
  background: blue

=mixin-border
  border-radius: 5px

.small-button
  +mixin-color
  +mixin-border
  padding: 10px

.large-button
  +mixin-color
  +mixin-border
  padding: 20px
```

## styled-components での mixin の書き方

先程の sass のサンプルを styled-components で書き直してみると、このような形になります。

```javascript:sample.js
import styled, { css } from 'styled-components';

const mixinColor = css`
  color: white;
  background: blue;
`;

const mixinBorder = css`
  border-radius: 5px;
`;

const smallButton = styled.button`
  ${mixinColor}
  ${mixinBorder}
  padding: 10px;
`;

const largeButton = styled.button`
  ${mixinColor}
  ${mixinBorder}
  padding: 20px;
`;
```

<a href="https://www.styled-components.com/docs/api#css" target="_blank" rel="nofollow noopener">styled-components の CSS helper</a> を使うと、css を部分的に定義しておくことが出来ます。
あとは定義しておいた mixin を使いたいコンポーネントで呼び出すという形です。

styled-components は継承や関数による分岐もできますが、この形もかなり便利だと思います。

## 参考サイト

* <a href="https://qiita.com/taneba/items/4547830b461d11a69a20" target="_blank" rel="nofollow noopener">styled-componentsを使ったCSS設計</a>
* <a href="https://www.styled-components.com/docs" target="_blank" rel="nofollow noopener">styled-components: Documentation</a>
* <a href="https://github.com/styled-components/styled-components/blob/master/docs/tips-and-tricks.md#more-powerful-example" target="_blank" rel="nofollow noopener">styled-components/tips-and-tricks.md at master · styled-components/styled-components · GitHub</a>