OmniAICreator/Qiita-1.07M huggingface dataset:
Google Assistant アプリで他の端末に処理を移す

何かしらの写真であったり地図であったり、
スキルの内容によっては視覚的に情報を提示したくなると思います。
しかし、Google Home などの端末ではディスプレイがないため
これらの情報を提示できません。

この問題を解決できるように
Google Assistant では適切な端末で情報が提示できるように
処理の続きを他の端末に移すことが可能です。

# やり方
`NewSurface()` というレスポンス用のクラスを使います
説明ページ: https://developers.google.com/actions/assistant/surface-capabilities#multi-surface_conversations

実装として最低限やることは主に2つです。

1. `NewSurface()` を呼んで他の端末に移動するか尋ねる
2. 専用のイベントをインテントで設定して、fulfillment で捌く

### 1. `NewSurface()` を呼んで他の端末に移動するか尋ねる
`NewSurface` クラスをレスポンスとして返すだけで
Actions on Google は以下のことをまとめてやってくれます。

* 他の端末に移動するかをユーザーに尋ねる
* 次のインテントに移るためのイベントの発火
* 連携している端末へのプッシュ通知

実際のコードを見てみましょう

```ts
import { NewSurface } from 'actions-on-google'

app.intent('TestIntent', conv => {
  const context = '「こちらをスマートフォンに送ってもよろしいですか？」の前に喋ってほしい内容'
  const notification = '通知のタイトル'

  conv.ask(new NewSurface({
    capabilities: ['actions.capability.SCREEN_OUTPUT'],
    context,
    notification,
  }))
})
```

このように開発者側は、処理を移したい先の端末の条件と
テキストをいくつか用意するだけでOKです。

実行すると以下のような流れが実現できます。
<img width="408" alt="new-surface.png" src="https://qiita-image-store.s3.amazonaws.com/0/102044/db353f3c-ccb6-40e5-ca67-bd46b139816d.png">


### 2. 専用のイベントをインテントで設定して、fulfillment で捌く
「こちらをスマートフォンに送ってもよろしいですか？」の問いに対して「いいえ」と答えるか、
「はい」と答えて通知を開くと `actions_intent_NEW_SURFACE` というイベントが発火します。
このイベントをキャッチする必要があるので dialogflow でインテントの設定を行いましょう。

![intent.png](https://qiita-image-store.s3.amazonaws.com/0/102044/ee76e95f-f47b-8b4c-76e1-1280cf251d47.png)

画像の中には入っていませんが、インテントの下部にある fulfillment の設定を Enable にするのを忘れずに。

ちゃんとインテントに入り fulfillment に処理が飛んでいれば以下のコードで会話を続けることができます。

```ts
app.intent('TestNewSurface', (conv, parameters, newSurface) => {
  if (newSurface.status !== 'OK') {
    // 最初と同じ端末で会話が続いてる
    conv.close('「いいえ」って言われた時の応答')

    return
  }

  // 通知がきた端末で会話が続いている
  conv.close('「はい」って言われた時の応答')
})
```

`newSurface.status` の中身を確認することで、ユーザーの応答がわかるので
よしなに処理の内容を変えてあげてください

「はい」の場合、端末は変わっていますが
会話は続いているので Context やらは引き継がれています。


# 捕捉
ここまでは説明のために、非常にシンプルにしてあります
ここからはよりよいアプリにするための補足です

### ユーザーの画面の状況の把握
もしかしたら、ユーザーが画面付きの端末で聞いてるかもしれませんし、
画面付きの端末と連携していないかもしれません。
そこで下記のような分岐を追加しましょう。

```ts
...
app.intent('TestIntent', conv => {
  const hasScreen = conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT')
  const hasDeviceWithScreen =
    conv.available.surfaces.capabilities.has('actions.capability.SCREEN_OUTPUT')

  if (hasScreen) { // 画面付きの端末の場合はそのまま返事
    conv.close('画面のある素敵な端末ですね')

    return
  }

  if (!hasDeviceWithScreen) { // 画面付きの端末と連携できていない場合はどうしようもない
    conv.close('この機能は画面付きの端末で利用することができます')

    return
  }

  const context = '「こちらをスマートフォンに送ってもよろしいですか？」の前に喋ってほしい内容'
  ...
```

### 複数の状況で `newSurface` を使いたい時
インテントの設定でイベントを設定しましたが、
`actions_intent_NEW_SURFACE` というイベントが常に発火することになります。

ですので複数の状況で使いたい場合は、
`conv.contexts.set` などを用いてコンテキストに情報を持たせると良いと思います。

### 端末の連携について
端末が連携しているかは同じGoogle Accountでログインしているかだけではなく、
Voice Matchを有効にしているかなど他の条件も必要なようです。

情報を共有するかどうかのチェックなどいろいろあるみたいで
完全に把握しきれてません。
もし知っている人がいたらコメントなどで教えてくれると嬉しいです。

# まとめ
ディスプレイ付きの端末がどんどん発売されて、アシスタントを使う端末も多様化してきます。
端末ごとに適した表示方法は異なるので良い体験を追求していきましょう
グラフの連結成分（エッジを列挙）

こんにちは。
[gonum/graph](https://godoc.org/gonum.org/v1/gonum/graph) を利用し、グラフの[連結成分](https://ja.wikipedia.org/wiki/%E9%80%A3%E7%B5%90%E3%82%B0%E3%83%A9%E3%83%95)（＝サブグラフ）内のエッジを列挙してみました。グラフは undirected multigraph で、エッジは複数の [lines](https://godoc.org/gonum.org/v1/gonum/graph/multi#Line) を持ちます。

```DepthFirst.EdgeFilter()``` へ ```edgeFunc()``` を渡し、サブグラフ単位で全ての ```lineID``` を列挙させています。
![graphviz.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/b33e3d11-ed99-5eb6-7c92-7192bffb9d6d.jpeg)

```console
$ go run walkFrom.go
input undirected lines: [[0 1] [1 2] [2 3] [3 0] [0 2] [1 3] [1 0] [4 4] [4 4]]
total 9 lines

lineID   ! edge
----------------
2        0 [2 3]
1        1 [1 2]
5        2 [1 3]
0        3 [0 1]
6        3 [0 1]
3        4 [0 3]
4        5 [0 2]
----------------
8        6 [4 4]
7        6 [4 4]
----------------
```

```walkFrom.go
package main

import (
	"fmt"
	"gonum.org/v1/gonum/graph"
	"gonum.org/v1/gonum/graph/multi"
	"gonum.org/v1/gonum/graph/traverse"
)

var iEdge int

func printLine(lID, mID, nID int64, iEdge int) {
	fmt.Printf("%d        %d [%d %d]\n", lID, iEdge, mID, nID)
}

func printHeader() {
	iEdge = 0
	fmt.Printf("\nlineID   ! edge\n")
	printSeparator()
}

func printSeparator() {
	fmt.Print("----------------\n")
}

func printLines(e graph.Edge) {
	mID, nID := e.From().ID(), e.To().ID()
	if mID > nID {mID, nID = nID, mID}
	l := e.(graph.Lines)
	for l.Next() {
		printLine(l.Line().ID(), mID, nID, iEdge)
	}
	iEdge++
}

func makeWalker(edgeFunc func (graph.Edge)) (walker traverse.DepthFirst) {
	walker.EdgeFilter = func(e graph.Edge) bool {
		if e.From().ID() <= e.To().ID() {
			edgeFunc(e)
		}
		return true
	}
	return walker
}

func walk(g *multi.UndirectedGraph, walker *traverse.DepthFirst, from graph.Node) {
	if !walker.Visited(from) && g.From(from.ID()).Next() {  // neither visited nor isolated node
		walker.Walk(g, from, nil)
		printSeparator()
	}
}

func walkAll(g *multi.UndirectedGraph) {
	printHeader()
	nod := g.Nodes()
	w := makeWalker(printLines)
	for nod.Next() {
		walk(g, &w, nod.Node())
	}
}

func makeGraph() *multi.UndirectedGraph {
	IDMAX := 9
	inputLines := [][]int64{{0, 1}, {1, 2}, {2, 3}, {3, 0}, {0, 2}, {1, 3},  {1, 0}, {4, 4}, {4, 4}}

	g := multi.NewUndirectedGraph()
	for i := 0; i <= IDMAX; i++ {
		g.AddNode(multi.Node(int64(i)))
	}
	fmt.Print("input undirected lines: [")
	for i, e := range inputLines {
		g.SetLine(g.NewLine(g.Node(e[0]), g.Node(e[1])))
	 	fmt.Print(e)
	 	if i < len(inputLines)-1 {fmt.Print(" ")}
	}
	fmt.Printf("]\ntotal %d lines\n", len(inputLines))
	return g
}

func main() {
	g:= makeGraph()
	walkAll(g)
}
```
kubectlで便利なコマンドライン引数たち

この記事は、[Nextremerアドベントカレンダー](https://qiita.com/advent-calendar/2018/nextremer)20日目の記事です。

# はじめに

この記事では、kubectl でよく使う便利なコマンドライン引数について紹介します。

# ログレベルの変更

kubectl に `-v` オプションを渡すことで、ログレベルを変更できる。

```shell
$ kubectl get po -v=9
```

レベルは 0 ~ 10 まで指定できる。0 ~ 4 はデバッグレベル、5 ~ 10 はトレースレベルのログを表示できる。

`-v=9` はよく使う。

# バージョンの表示をわかりやすくする

Kubernetes の API Server と Client のバージョンを確認するときに便利なオプション。

`--short` 引数をつけることで、バージョンだけの表示ができる。

```shell
$ kubectl version --short
Client Version: v1.13.1
Server Version: v1.13.1
```

# 変更を watch する

`-w` 引数をつけることで、変更を監視してくれる。 Get Pod や Event などで使えるオプション。

```shell
$ kubectl get po -w
NAME                               READY   STATUS    RESTARTS   AGE
getting-started-6b5fb85c86-mrm5f   1/1     Running   0          63m
getting-started-6b5fb85c86-qtm5r   0/1   Pending   0     1s
getting-started-6b5fb85c86-qtm5r   0/1   Pending   0     1s
getting-started-6b5fb85c86-qtm5r   0/1   ContainerCreating   0     1s
getting-started-6b5fb85c86-qtm5r   1/1   Running   0     6s
```

表示が崩れるのがいまひとつですが、外部のツールなしでサクッと変更を監視したいときに便利。

# ログを特定の時間から取得する

`--since-time` 引数をつけて `logs` を実行すると、特定の時間からログを取得できる。

```shell
$ kubectl logs --since-time='2018-12-18T09:00:00.000000000Z' hello-node-64c578bdf8-5vlmn
```

対応している日時の指定は [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) フォーマットのみ。

# おわりに

リファレンスとか、help を読みましょうぜってことですが、ついつい忘れがちで読み飛ばすことが多いので、メモとして。

# 参考

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-command
【Ruby】state_machine の小さなサンプルメモ

ほぼ参考リンクのままのメモ

## メモ

```ruby
require "state_machines"

class User
  state_machine :status, initial: :inactive do
    # 状態の定義
    state :active
    state :inactive

    # 状態が変わったときの動作を定義
    after_transition on: :activate, do: :after_active, :if => lambda {|u| u.uresi }
    after_transition on: :inactivate, do: :after_inactive

    # 状態を変えるときのメソッド
    event :activate do
      transition :inactive => :active
    end

    event :inactivate do
      transition :active => :inactive
    end
  end

  def uresi
    #true
    false
  end

  def after_active
    p "Activeになりました"
  end

  def after_active2
    p "うれしい！"
  end

  def after_inactive
    p "inActiveになりました"
  end
end

u = User.new
p u.status # => "inactive"
p u.active? # => false
p u.inactive? # => true

u.activate! # => "Activeになりました"
p u.status # => "active"

u.inactivate! # => "inActiveになりました"
p u.status # => "inactive"
```

## 参考
【Rails】 state_machineを使って状態を管理する - kzy52's blog http://kzy52.com/entry/2013/06/09/014233
Railsのmonth gemでbeginning_of_monthを使う方法

monthというgemがあります([GitHub](https://github.com/timcraft/month))

月のはじめの日や終わりの日を取得する`beginning_of_month`や`end_of_month`は、
Month gemではそれぞれ`start_date`, `end_date`になっているので注意する

```Ruby
this_month = Month.new(2018,12)

this_month.start_date #月初
=> Sat, 01 Dec 2018

this_month.end_date #月末
=> Mon, 31 Dec 2018
```
Laravelで既存のDBからmigrationsファイルを作成する「migrations-generator」（Laradock編）

###きっかけ
CakePHPで作ったアプリケーションをLaravelに移行中。
そのためにすでにテーブルはあるため、テーブルからマイグレーションファイルを作りたい。

###参考
以下を参考にした。（ありがとうございます。）
[Laravelで既存のDBからmigrationsファイルを作成する「migrations-generator」
](https://qiita.com/busyoumono99/items/a7173ad6b9b041da09dd)
ただLaradock環境でちょっとハマったので記事とした。
###環境
* Laravel5.5
* MySQL5.7
* PhpStorm2018.3

###migrations-generatorをインストール

[migrations-generator](https://github.com/Xethron/migrations-generator)をインストール。
GitHub記載の通り、以下でいける。
`composer require --dev "xethron/migrations-generator"`

※composerがローカルにない場合は以下でworkspaceコンテナに入ってから行うこと。
`docker exec -it laradock_workspace_1 bash`

###DB接続設定
プロジェクトフォルダの`.env`ファイルの`DB_DATABASE`、`DB_USERNAME`、`DB_PASSWORD`を修正する。
（Laravelの`.env`ファイル。Dockerの`.env`ファイルではない。）

###マイグレーションファイルを作成
以下でworkspaceコンテナに入る。
`docker exec -it laradock_workspace_1 bash`
（ホスト側から以下実行しても` SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known `となるので注意。）

GitHub記載の通り、以下でマイグレーションファイル一式作られる
`php artisan migrate:generate`

###感想
基本的にworkspaceコンテナに入って作業することでローカル環境の構築が不要となるという感覚がわかってきた。
（上記composerもworkspaceコンテナ内で実行するのが本来の使い方だと思う。）
でもいちいちworkspaceコンテナに入るの面倒くさい。

あとマイグレーションファイルを一旦作ってみたけどこれがどこまで役に立つのか正直未知数。
nestjsで既存のDBテーブル構造を使う方法

※ 備忘録

nestjs、AngularやIonic Frameworkととても親和性の高いフレームワークなのですが、ORMを使おうと思うとtableスキーマをローカルに持つ必要があります。新規プロジェクトだとそれでいいのですが、既存プロジェクトだとつらい単純作業になりますよね。

そこで、`typeorm-model-generator`を使って、自動生成してしまいましょう。

https://www.npmjs.com/package/typeorm-model-generator

# 使い方
npmでインストールして使います。

```bash
$npm i typeorm-model-generator -g
```

そうしたら `typeorm-model-generator` コマンドを使えるようになりますので、nestjsのプロジェクトトップディレクトリに移動して

```bash
$ typeorm-model-generator -h <host> -d <database> -p [port] -u <user> -x
[password] -e [engine]
```

と入力すれば、table構造を読み取って`output/`フォルダを自動生成します。例えばローカルの`DBName`というデータベースからtable構造を読み取るなら

```bash
$ typeorm-model-generator -h 127.0.0.1 -d　DBName -p 3306 -u root -x root -e mysql 
```

となります。便利ですね。
MVVMアーキテクチャのそれぞれの役割

<img width="1278" alt="スクリーンショット 2018-12-19 16.37.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/318907/4a85dd52-eceb-5263-af6a-73f2a55799a6.png">

## Model
・データベースにアクセスしデータを参照する。

## View
・Modelが参照したデータを表示する
・ユーザーが入力したデータを取得する

## ViewModel
・Viewが取得したデータをModelによりデータベースに保存しやすいように加工する。
・Modelが参照したデータをViewでユーザーが見やすく表示できるように加工する
※Model、Viewが参照、表示というそれぞれの役割に専念できるようにその間で橋渡し的な役割をするのがViewModel。
[WIP] わざわざ自作するまでもないAndroidのUIコンポーネント

常識的な話ですが、標準で提供されているのに自作している記事がかなり多い気がして気になったのでまとめておきたいと思います。他にもあるよという方はコメントなどで教えてください。

# Ripple エフェクト

```xml
android:background="?android:selectableItemBackground"
```

テーマにもよりますが、 AppCompat 系のテーマかつ Android 5.0 以上ではリップルのエフェクトが出ます。自分で Drawable などをつくって対応すると互換性のために Android 5.0 未満向けの Drawable をつくる必要がありますが、その必要もないので楽です。

```xml
android:background="?android:selectableItemBackgroundBorderless"
```

**Android 5.0 以上向け。**
View の枠をはみ出して丸く描かれるリップルを出したいときに使います。`ImageButton` に使うことが多いんじゃないかなと思いますが、その場合にたいていタップ領域が狭すぎてタップしづらいみたいなことが起きるので padding で調整しましょう。

# RecyclerView の区切り線

```java
// import android.support.v7.widget.DividerItemDecoration
RecyclerView rv = findViewById(R.id.rv);
rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
```

縦か横に線を引いて区切るくらいなら簡単にできます。また、RecyclerView の LayoutManager は XML でも設定できます。

# Dialog に ListView

`AlertDialog.Builder` にあります。わざわざ `setView()` する必要はありません。

```java
// import android.app.AlertDialog
// OR
// import android.support.v7.app.AlertDialog
new AlertDialog.Builder(this)
    .setItems(new String[]{"1", "2"}, (dialog, which) -> {})
    .show();
```
SpringでリクエストパラメータをEnumに変換する

## はじめに

Enumで扱うべき値を一旦Stringで取得して変換する作業が面倒だったので良い方法を探してました。

## 変換方法

Enumを用意して`@JsonValue`と`@JsonCreator`を使用して取得と生成処理を書く。

```java:EnvironmentType.java
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

import java.util.stream.Stream;

public enum EnvironmentType {
    PRODUCTION(1),
    STAGE(2),
    DEVELOP(3);

    private int value;

    EnvironmentType(int value) {
        this.value = value;
    }

    @JsonValue
    public int getValue() {
        return value;
    }

    @JsonCreator
    public static EnvironmentType create(Integer value) {
        if (value == null) {
            return null;
        }
        return Stream.of(values())
                .filter(v -> value.equals(v.getValue()))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException());
    }
}
```

リクエストで使用するBeanにEnum型を使用してプロパティを定義する。

```java:Request.java
import EnvironmentType;

public class Request {
    private EnvironmentType type;

    public EnvironmentType getType() {
        return type;
    }

    public void setType(EnvironmentType type) {
        this.type = type;
    }
}
```

## 終わりに

Jacksonのアノテーションを使えば楽に書けました。
user_data/sample で独自処理をおこないたかったけど

# はじめに
EC-CUBE2.12.xからEC-CUBE4.xにバージョンアップしたいという依頼。
なるべく外見は変わらないようにという要望もあり/user_data/sample.phpを/user_dataの下に設置できないか検討。
ちなみにsample.phpはDBアクセスもありそれに従い表示しなければならない。

# 管理画面からページ追加
## ページ追加
コンテンツ管理＞ページ管理から新規ページ作成
URL:sample ファイル名:sample.twig

```twig:sample.twig
{% extends 'default_frame.twig' %}

{% block main %}
サンプル

{% endblock %}
```

## ブラウザよりアクセス
/user_data/sample でページ表示できた。

# UserDataControlle編集
## Customize
DBアクセスしたいのでuser_dataのControllerをCustomizeにコピー
src/Eccube/Controller/UserDataController.php → app/Customize/Controller/UserDataController.php

ルーティングを設定しfunction編集

```php:app/Customize/Controller/UserDataController.php
namespace Customize\Controller;

use Eccube\Controller\AbstractController;
:
class UserDataController extends AbstractController
{
    /**
     * @Route("/%eccube_user_data_route%/{route}", name="user_data_sample", requirements={"route": "sample(?<!\/)"})
     */
    public function sample(Request $request, $route)
    {
        $Page = $this->pageRepository->findOneBy(
            [
                'url' => $route,
                'edit_type' => Page::EDIT_TYPE_USER,
            ]
        );

        if (null === $Page) {
            throw new NotFoundHttpException();
        }

        $file = sprintf('@user_data/%s.twig', $Page->getFileName());

        $event = new EventArgs(
            [
                'Page' => $Page,
                'file' => $file,
            ],
            $request
        );
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_USER_DATA_INDEX_INITIALIZE, $event);

        log_error('デバッグ：sample',[var_export($file,true)]);
        return $this->render($file);
    }

    /**
     * @Route("/%eccube_user_data_route%/{route}", name="user_data", requirements={"route": "([0-9a-zA-Z_\-]+\/?)+(?<!\/)"})
     */
    public function index(Request $request, $route)
    {
        :
    }
}
```

## ブラウザよりアクセス
/user_data/sample でページ表示できたが**ヘッダ部／フッタ部が表示されない**。


## TwigInitializeListener.php 編集
追いかけていくと src/Eccube/EventListener/TwigInitializeListener.php に以下のようなuser_dataの場合のコードあり

```php:src/Eccube/EventListener/TwigInitializeListener.php
public function setFrontVariables(GetResponseEvent $event)
{
    :
    if ($route == 'user_data') {
        $routeParams = $attributes->get('_route_params', []);
        $route = isset($routeParams['route']) ? $routeParams['route'] : $attributes->get('route', '');
    }
```

正直何をやっているか分からなかったけど

```php:src/Eccube/EventListener/TwigInitializeListener.php
public function setFrontVariables(GetResponseEvent $event)
{
    :
    if ($route == 'user_data' || $route == 'user_data_sample') {    // user_data/sampleのときもここを通るように追加
        $routeParams = $attributes->get('_route_params', []);
        $route = isset($routeParams['route']) ? $routeParams['route'] : $attributes->get('route', '');
    }
```

と変更。

## ブラウザよりアクセス
/user_data/sample でページ表示できたし**ヘッダ部／フッタ部も表示された**。

#まとめ
EC-CUBEコア部分である TwigInitializeListener.php を編集しないといけないので /user_data/ の下は静的ページ(Javaスクリプトで書き換えるのは可)だけ設置するようにしてコア部分を触らないようにすることにした。
(もっとやり方があるかもしれないけどとりあえず前に進まないといけないので) /user_data/sample ではなく /sample でアクセスすることしようと思う。
[Django] マスタデータの作り方

# この記事について

Django でマスタデータ（初期データ）を準備する方法についてのメモです。
以下の内容を説明します。

１．データの編集
２．データのエクスポート
３．データのインポート（コマンド or マイグレーション内での実行）


## １．データの編集

最初にデータベースにデータを登録します。データの登録には管理コマンドの`shell`を使ってもいいのですが、一般的にはデータベース管理ツールと呼ばれるソフトを使い、データベース内のテーブルをエクセルのように直接編集する方法を採ります。

データベース管理ツールは主に３種類存在しますが、大体機能は似たり寄ったりなので好きなものを使えばいいでしょう。

１．特定のデータベース専用のもの（phpMyAdmin, pgAdmin等）
２．IDE(PyCharm等)の機能として組み込まれているもの
３．フリーソフト

2018年現在で人気のフリーソフトは「TeamSQL」及び「DBeaver」です。「DBeaver」は知名度が低いですが日本語対応しているので初心者には使いやすいかと思います。

**DBeaverメモ**

- データベースから一度に取得する件数は、初期状態では200件と少なめです。データベースを選択した状態で「ファイル」⇒「プロパティ」と選択し、設定画面のEditor→結果セットにてフェッチサイズを変更しましょう（０で全件取得）

- エクセルのデータをテーブルにコピー＆ペーストする手順
 - １．エクセルの表をコピー
 - ２．テーブル表示の下の「新しい行を追加」をクリック
 - ３．新しい行全体を選択して、右クリックより「高度なペースト」を実行
 - ４．保存(Save)

## ２．データのエクスポート

データをテキスト形式でエクスポートし、どのタイプのデータベースへもインポートできるようにします。Djangoでは初期データとしてプロジェクトに付属させるファイルのことを**Fixtureファイル**と呼んでいます。Fixtureファイルはdumpdataコマンドで作成します。標準の出力フォーマットはJSON形式です（一応yml/xml形式も使える）。

```
manage.py dumpdata <app_name>.<model_name> > <file_name>.json
```

※ model_nameを省略するとアプリ全体が対象になる。

**エクスポートのメモ**

- 出力されたJSONファイルは整形されていません。IDEやテキストエディタの機能で整形しましょう。indentオプションでも可能ですが、ファイルの最初と最後がインデントされておらずちょっと微妙です。

- 日本語の文字列はunicodeの「¥uXXXX」形式にエスケープされます。文字列の内容の確認には[このようなツール](https://www.kwonline.org/u_esc_seq.php)を使います。

## ３．データのインポート

**※ initial_data.jsonによる初期データの投入はDjango 1.7+で廃止となりました。**

### コマンドによるインポート

アプリのディレクトリに`fixtures`というディレクトリを作り、エクスポートしたファイルを格納します。その後以下のコマンドを実行して対象ファイルをインポートします。file_nameに拡張子は不要です。loaddataの動作は「対象のidがあれば上書き、なければ新規登録」なので重複して実行してもエラーにはなりません。


```
manage.py loaddata <file_name> --app <app_name>
```

### migrationファイルによるインポート

migrationファイル内でloaddataコマンドを呼び出すことで、自動的に初期データを登録することができます。


手順１．以下のコマンドを実行して空のmigrationファイルを作る

```
manage.py makemigrations <app_name> --empty
```

手順２．作成された空のマイグレーションを書き換えてloaddataを組み込む。

```python 
from django.core.management import call_command
from django.db import migrations


def load_fixture(apps, schema_editor):
    call_command('loaddata', '<file_name>', app_label='<app_name>')


class Migration(migrations.Migration):
    dependencies = [
        ('sample', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(load_fixture),
    ]
```

適用の取り消しが必要な場合は`reverse_code`オプションを定義する。
参考：https://stackoverflow.com/questions/25960850/loading-initial-data-with-django-1-7-and-data-migrations

## 参考：

- [PengNote:Djangoでfixtureを使って初期データを投入する](https://blog.daisukekonishi.com/post/django-fixture/)
- [Qiita:Djangoの初期データ投入機能についてメモ](https://qiita.com/mimikun/items/61390da1d9a59aab3d6f)
vue.jsでv-forを使う時、imgタグや背景をいじりたい


imgタグのURLや、background-imageなどのURLを触りたい時

```vuejs

<ul class="list" v-show="hoge === 0">
    <li class="list-item" v-for="(n , index) in 20">
        <img class="list-item__image" :src="'https://hogehoge.com/no_'+ (index +1) +'.png'"> //1番目から
        <div class="list-item__background-image" v-bind:style="{height:10 +'px', width:10 +'px', backgroundImage:'url(https://hogehoge.com/no_'+ (index +1) +'.png)'}"></div>
    </li>
</ul>
```

`n.image`とかで情報を持っていればいいのですが、ない時に。。。
tar.xz・tar.gzコマンドメモ

# Macでtar.xzとかtar.gzとか使う機会があったのでメモ
## tar? xz? gzip?
tar.gzとかいう圧縮ファイル、MacやらLinuxやらでよく見るけど、そもそも何なんだって話で。  

### tar
➡︎ tape archivesの略でもともと磁気テープなどにバックアップをするときなどに使われた。
複数ファイルを一つにまとめた、いわゆる「アーカイブ」

### gzip
➡︎ ファイル圧縮方式の一つ、ZIPとはにて非なるもの。複数ファイルの圧縮ができない。

### xz
➡︎ gzipと同様、ファイル圧縮方式の一つ。gzipより圧縮率が高いらしい。


まとめると・・・tarはアーカイブでxz, gzipは圧縮(ファイルサイズ縮小)
xz, gzipは複数ファイルに対応していないので、tarしてからgzipとか面倒くさい感じになる。

## tar.gzとかtar.xzを扱うコマンドたち

### tar.xz(アーカイブ + xz圧縮)ファイル作成
```bash
$ tar cJvf archive.tar.xz dir/
```

### ディレクトリに入っていない場合
```bash
tar cJvf archive.tar.xz prefix*
```

### tarアーカイブしたあとxz圧縮の場合
```bash
tar cvf archive.tar dir
xz -v archive.tar
```

### tar.gz(アーカイブ + gzip圧縮)ファイルの場合
```bash
tar czvf archive.tar.gz dir/
```

### tarアーカイブしたあとgzip圧縮の場合
```bash
tar cvf archive.tar dir
gzip -v archive.tar
```

### 一括で展開(gzipもtarも同じコマンドでOK)
```bash
tar xvf archive.tar.xz
```

### xz展開だけ
```bash
unxz -v archive.tar.xz
```

### gzip展開だけ
```bash
gzip -dv archive.tar.gz
```
NuxtのプロジェクトをHerokuにデプロイするときに出たエラーの対処(備忘録)

Nuxtで作成したプロジェクトをいざHerokuにデプロイしようとしたときに以下のエラーが出ました。

```bash
To https://git.heroku.com/xxxxx-xxxxx.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/xxxxx-xxxxx.git'
```

Herokuは数ヶ月前に使っていたことがあり、前回と同じような手順でデプロイしてみましたが、ダメでした。このエラーの内容を辿っていくと

```shell
-----> Building dependencies
       Installing node modules (yarn.lock)
       yarn install v1.13.0
       [1/4] Resolving packages...
       error Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`.
       info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
-----> Build failed
 !     Outdated Yarn lockfile
       Your application contains a Yarn lockfile (yarn.lock) which does not
       match the dependencies in package.json. This can happen if you use npm
       to install or update a dependency instead of Yarn.
       Please run the following command in your application directory and check
       in the new yarn.lock file:
       $ yarn install
       $ git add yarn.lock
       $ git commit -m "Updated Yarn lockfile"
       $ git push heroku master
    
       https://kb.heroku.com/why-is-my-node-js-build-failing-because-of-an-outdated-yarn-lockfile
 !     Push rejected, failed to compile Node.js app.
 !     Push failed
```

このあたりでBuildが失敗しているようです。
今回のNuxtのプロジェクトでは`yarn`は使っていなかった（と思う）ですが、どうやらこの`yarn.lock`ファイルのバージョンが異なっているためBuildで失敗しているようです。この現象はyarnの代わりにnpmを使っていると起こりうるようです。そこで、プロジェクトで`yarn`を更新し、`yarn.lock`をコミットしてから再度Herokuへデプロイしたところ、無事にデプロイできました。


```shell:更新
yarn
```
```shell:commit
git add yarn.lock
git commit -m"Update yarn.lock"
git push heroku master
```

```shell:heroku
remote: Verifying deploy... done.
To https://git.heroku.com/xxxxx-xxxxx.git
 * [new branch]      master -> master
```
cssのobject-fitの使い方メモ

## 画像の縮小表示
とあるクライアントから、画像は縦横比率を保ち、そのまま表示してほしいという要望
「ふむふむなるほど」といつものように

```css

.box
 width: 300px
 height 300px
 overflow:hidden
 
 img
  width: 100%
  height: auto
```
にていしていたら

「これ違います」ときた

どうやら、縦横比率が違うものをそのままやりたいらしい

### イメージこういうの
<img width="1222" alt="スクリーンショット 2018-12-19 15.48.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/118047/f403c05d-dec6-db4e-96a5-686b555d326c.png">

## 対応策
```css

.box
 width: 300px
 height 300px
 overflow:hidden
 
 img
  width: 300px
  height 300px
  object-fit: contain;
  /*親と同じwidth,height　+ object-fit*/
```
で解決

### まとめ
普段あまりobject-fitとか使ってこなかったので、良い勉強になった
詳しい使い方や用途はまた調べるとして、
レイアウト的にあんまりレスポンシブの際に良いと思わないんだけどなぁぁ
という印象

まあ、クライアント次第ってことで、、、。
Excel VBAをJavaScriptに翻訳 その３

# はじめに
[**前回**](https://qiita.com/pooshikin/items/97f0abd38aa82fc9f664)では、VBAをJavaScriptに翻訳する簡単な翻訳機を作成しました。
今回は、VBAのMsgBoxとDate()をJavaScriptで定義します。
npm(Notable Pseudocode Mashups)はこれを実現するためのnode.jsのためのパッケージがたくさんあります。世界中のプログラマーが作ったパッケージをそのまま使うことができます。
必要なパッケージをローカルにインストールして、JavaScriptを作ります。

# 前提
* OS : Windows7以上
* PoweShellのターミナルで実行
* VSCodeでコード編集
* node.js環境構築済み

# tomtest.vb
JavaScriptへ翻訳する元VBAファイルです。

```VB
Debug.Print("Hello World")  ' Debug.Print
MsgBox("Hello World")       ' MsgBox
Debug.Print(Date)           ' Date()
```

# npmパッケージのインストール
## dialog
MsgBoxの機能を実現するために、npmからdialogをローカルにインストールします。
[**dialog**:https://www.npmjs.com/package/dialog](https://www.npmjs.com/package/dialog)
※ tomtest.vbと同じディレクトリの直下にインストールします。

```
npm install --save dialog
```
## date-time
Dateの機能を実現するために、npmからdate-timeをローカルにインストールします。
[**date-time**:https://www.npmjs.com/package/date-time](https://www.npmjs.com/package/date-time)

```
npm install --save date-time
```

# tomdef.js
今回の本題のJavaScriptになります。

```JavaScript
function Print(s) { console.log(s); };
function MsgBox(s) {
    var dialog = require('dialog');
    dialog.info(s);
}
function Date() {
    const DateTime = require("date-time");
    return DateTime();
}
/* 個別でも記述可能
module.exports.Print = Print;
module.exports.MsgBox = MsgBox;
module.exports.Date = Date;
*/
module.exports = { 
    Print: Print, 
    MsgBox: MsgBox, 
    Date: Date 
}; 
```
３つの関数を定義しています。
* **Print** : 引数 **s** を**console.log**でターミナルに出力します。
* **MsgBox** : 引数 **s** を**dialog.info**でダイアログボックスに出力します。
* **Date** : **date-time**の戻り値を返却する関数を定義します。

# tomtest.js
**tomtest.vb**を翻訳すると下記のJavaScriptを自動作成することになります。

```JavaScript
var f = require('./tomdef.js');

f.Print("Hello, world");    // Debug.Print
f.MsgBox("Hello, world");   // MsgBox
f.Print(f.Date());          // Date()
```
※VBAではDate()の'()'は省略されるが、JavaScriptでは'()'は明示する。

# 実行
ターミナルにて以下のコマンドを実行。

```
node tomtest.js
```
![tomtest.png](https://qiita-image-store.s3.amazonaws.com/0/239597/3a12f62a-5d7b-c13c-6d94-a016caf86891.png)
JavaScripの記述内容がそれぞれ実行されています。

# まとめ
npmのパッケージを利用して実現したい機能の関数を定義しました。
npmには他にもたくさんのすばらしいパッケージが用意されています。
これらのパッケージを流用または拡張して新たな機能を実現することも可能です。
次回は、**tomtest.vb**を**tomtest.js**へ翻訳するJavaScriptを作成します。
ログインシェルをfish shellにしているとVSCodeのOmnisharpがエラーを吐く

OSはmacOS High Sierraで確認した。

# ログインシェルをfish shellにしているとVSCodeのOmnisharpがエラーを吐く
## エラー内容
VSCodeでC#を書く時に下記の拡張機能を利用している。
https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp

この拡張機能がC#の補完をするのにOmnisharpを使用しているのだが、ログインシェルをfishにしているとOmnisharpが下記のエラーを吐く。

> [fail]: OmniSharp.MSBuild.ProjectLoader
        The reference assemblies for framework ".NETFramework,Version=v4.6" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend.

## 修正方法
ログインシェルをbashとかzshとかに変更してMacを再起動する。
VSCodeの再起動だけではだめだった。

## 原因
不明。
POSIX非互換だとかパスの区切りの方法が違うとか思いつくけどそこまで調べきれなかった。

はじめはdotnetかMonoのバージョンが関係するのかと思い、何度も別のバージョンをインストールしたが直らなかった。
PHPのバージョンを5.6から7.2に上げて開発してみた話

![adv2018.gif](https://qiita-image-store.s3.amazonaws.com/0/146076/561b3ee1-cb07-da95-36a5-b29adf15b470.gif)

このエントリーは[aratana Advent Calendar 2018](https://qiita.com/advent-calendar/2018/aratana) 20日目のエントリーです。

最近スマブラにハマっています筆者です。メインキャラはネスです、むしろそれ以外使えません。

さて、最近新規開発時のPHPのバージョンをPHP5.6からPHP7.2へとアップデートを行いました。
その際にハマったこと、便利だと思ったことなどつらつらとまとめていきたいと思います。

## なぜバージョンアップしたのか

今まで使用してきたPHP5.6は、セキュリティサポート期間が2018/12/31で終了します。[^1]
上記の理由もあり、このタイミングで1からシステムを開発するのにPHP5.6系を採用する恩恵が現時点でなかったため、バージョンアップして開発することを決定しました。
~~あと個人的にPHP7系で実装してみたかったのです（小声）~~

## ざっくりシステム概要

- 従来の環境
  - PHP 5.6.30
  - composer 1.2.0
  - PHPUnit 4.8.27

- 今回バージョンアップした環境
  - PHP 7.2.9
  - composer 1.7.3
  - PHPUnit 7.4.4

## PHP7.2系に移行してよかった点

### 厳格な型指定ができる

型指定をしてると妙な安心感がでてくるのは筆者だけでしょうか？
実際に下記内容を取り入れて開発を進めました！

- 厳格な型検査モード（`declare(strict_types=1);`）の指定
- 型宣言の記載

実際に取り入れてみて、大変といった印象はありませんでした。むしろ楽しいと思うくらいでした。w

```php:Message.php
<?php
declare(strict_types=1);

namespace Hoge;

/**
 * Class Message
 * @package Hoge
 */
class Message {

    /**
     * @var string
     */
    public $message = "";

    /**
     * @return string
     */
    public function get():string
    {
        return $this->message;
    }

    /**
     * @param $message
     */
    public function set(string $message):void
    {
        $this->message = $message;
    }
}
```

### use宣言がグループ化できる

これが地味に嬉しいポイントでしたw
Symfonyなどの大型フレームワークを使用する際にはかなり有り難いのではないでしょうか。

```php
use Hoge\{
    Fuga\InterFace1,
    Fuga\Class1,
    Class2
};
```

## 開発しててハマった点

### PHPUnitのクラス名

いつものようにテストコードを準備していると下記エラーが発生しました。

```bash
PHP Fatal error:  Class 'PHPUnit_Framework_TestCase' not found in /Users/hogehoge/fugafuga/tests/CommonTestCase.php on line 9
```

調べてみるとPHPUnitのクラス名 `PHPUnit_Framework_TestCase` がバージョン6.0から名前空間化されているとのこと。[^2]
使用しているクラス名を名前空間化された `PHPUnit\Framework\TestCase` に変更して無事にテストを通すことができました！

```php:MessageTest.php
<?php
declare(strict_types=1);

namespace Hoge;

/**
 * Class MessageTest
 * @package Hoge
 */
class MessageTest extends \PHPUnit\Framework\TestCase
{
    /**
     * @var Message
     */
    private $message;

    /**
     *
     */
    protected function setUp():void
    {
        parent::setUp();
        $this->message = new Message();
    }

    /**
     *
     */
    protected function tearDown():void
    {
        parent::tearDown();
    }

    /**
     *
     */
    public function testGetter():void
    {
        $message = "Getter Test.";
        $this->message->message = $message;
        $this->assertEquals($message, $this->message->get());
    }

    /**
     *
     */
    public function testSetter():void
    {
        $message = "Setter Test.";
        $this->message->set($message);
        $this->assertEquals($message, $this->message->message);
    }
}
```

## 最後に

まだPHP7.2系に移行したばかりで使いこなせていない感は拭えませんが、今までとほぼ変わることなく順調に開発を進めることができています。今のところは。。。
そのうち既存システムもPHP7系に。。。（小声）
その際はPHP5系と7系でのパフォーマンスの差などデータ収集してまとめたいなと思います。

*それでは、素敵なPHPライフを！！*

[^1]: [PHP: Supported Versions](http://php.net/supported-versions.php)参照。
[^2]: [PHPテストフレームワーク「PHPUnit 6.0」リリース](https://mag.osdn.jp/17/02/10/160000)参照。
shellを書いているときに躓いたところ

# 概要
現象は起きているものの、原因がわからなった問題から対処方法がわかったものを書き残します。

## コマンド実行後、返り値をshell内で扱うための変数

```zsh:特殊変数
php index.php #返り値のあるコマンド
echo $? #最後に実行された返り値が表示される
```

## ifで見かける　比較演算子

```zsh:比較演算子
#左右の値が等しければ真
if [ $? -eq 0 ]; then
  echo "No Problem :)"
fi

#左右の値が等しくなければ真
if [ $? -ne 0 ]; then
  echo "Have Problem :("
fi
```

## PHPからshellへ値を返すときの関数

```php:PHPからの書き方
<?php
//正常状態を返す場合
exit;
exit();
exit(0);

//異常状態を返す場合
exit(1);
exit(222);
︙
?>
```

## while内で使っていた変数をwhileの外でも使いたい場合
パイプを使った方法では期待した値が表示されませんでした

```zsh:期待した結果が表示されない
COUNT=0
cat 外部ファイルのパス | while read line
do
let COUNT++
done
echo $COUNT #whileでループされた分は表示されず、0が表示される
```

```zsh:期待した結果が表示される
COUNT=0
while read line
do
let COUNT++
done < 外部ファイルのパス
echo $COUNT #whileでループされた分だけ表示される
```

## 参考投稿
[Shell 特殊変数](https://qiita.com/a_yasui/items/ec4f75b300410af8958d)
[シェルスクリプト（bash）のif文やwhile文で使う演算子について](https://qiita.com/egawa_kun/items/196cd354c0d8e4e0fefc)
[シェルスクリプト最大の罠、while問題](http://www.atmarkit.co.jp/ait/articles/1209/14/news147.html)
[シェルスクリプトで外部ファイルに記述された変数を利用する方法](https://orebibou.com/2014/11/%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%A7%E5%A4%96%E9%83%A8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E8%A8%98%E8%BF%B0%E3%81%95%E3%82%8C%E3%81%9F%E5%A4%89/)
Vue.js 描画関数でのスコープ付きスロットとフォールバック

描画関数でスコープ付きスロットを吐き出したい場合は、`$scopedSlots`を使用する。

```html
<!-- 使用する側で適当な要素に`slot-scope`属性をつける -->
<hoge>
  <p slot-scope="{ text }">{{ text }}!!</p>
</hoge>
```

```ts
const Hoge = Vue.extend({
  render(h: CreateElement) {
    // コンポーネント側では`$scopedSlots`に各スロットに対応する描画関数（っぽい関数）が入る
    // 今回は名前なしスロットなので`default`に入る
    console.log(this.$scopedSlots); // { default: function() {...} }

    return h('div', [
      this.$scopedSlots.default({ text: 'hoge' })
    ];
  }
};
```

```html
<!-- 結果 -->
<div>
  <p>hoge!!</p>
</div>
```

描画関数内でのスロットのフォールバックについては関数の存在チェックすればよさそう。

```html
<!-- `slot-scope`を消す -->
<hoge>
  <p>{{ text }}!!</p>
</hoge>
```

```ts
const Hoge = Vue.extend({
  render(h: CreateElement) {
    console.log(this.$scopedSlots); // { } ← スコープ用の関数が入ってこない

    return h('div', [
      this.$scopedSlots.default
        ? this.$scopedSlots.default({ text: 'hoge' })
        : h('span') // フォールバック
    ];
  }
};
```

```html
<!-- 結果 -->
<div>
  <span></span>
</div>
```
JavaでDateをISO 8601 拡張形式で出力する

## はじめに
Spring BootでRESTful APIを作っている時に、レスポンスのDate型をISO 8601 拡張形式にフォーマットして返したかった。
フォーマットを探すのに時間がかかったので備忘録として残す。

## フォーマット

`yyyy-MM-dd'T'HH:mm:ssXXX`で出力できる。

```java:Test.java
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test {
        public static void main(String[] args) {
                Date d = new Date();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
                System.out.println(sf.format(d));
        }
}
```
```console
2018-12-19T15:46:06+09:00
```

## Spring Bootのレスポンスとして使用する

Spring Bootを使っていれば、レスポンスのJSON変換として**Jackson**を使用しているはず。
`application.yml`に以下の設定を追加することでデフォルトのフォーマットを指定できる。

```yaml:application.yml
spring:
  jackson:
      date-format: "yyyy-MM-dd'T'HH:mm:ssXXX"
      time-zone: "Asia/Tokyo"
```

Jacksonはタイムゾーンを指定しないと**GMTになる**。
基本的にタイムゾーン指定しておくのが良いと思う。

デフォルトのフォーマットではなく、明示的にフォーマットを変換したい場合は以下のように書く。

```java:Response.java
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;

public class Response {
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "Asia/Tokyo")
    private Date createdAt;

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }
}
```

## 終わりに
言語毎に微妙にフォーマットが違うので意外とハマる印象。
全部統一されないものか・・・・・
Barracuda Email Threat Scannerを試す

#はじめに
[Barracuda Email Threat Scanner](https://www.barracuda.co.jp/products/ets)が無償でメールベースの攻撃に対するスキャンとレポートをしてくれるとのことなので、お試ししてみました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/466b2e21-12d5-479c-78d9-100fcb7f5780.png)

#簡単なサービス説明
既にo365には基本的なウイルスなどの攻撃の対策は実施されていますが、それを通過してしまう受信してしまった悪意のあるメールや、ウイルス感染したPCから意図せず送信してしまったメールなどについてスキャンをして、その結果をレポートしてくれます。

#お試し環境説明
個人で所有しているo365サブスクリプションにmailtestユーザを作成。
そこに、実際に過去に別アカウントで受信した迷惑メールフォルダに入っているメールを適当にピックアップして受信トレイ、送信トレイに突っ込みました。

#スキャン手順

##Barracudaサイトに接続
[Free Email Threat Scan](https://www.barracuda.com/email_scan)サイトにアクセスします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/9e218773-08fb-2c7e-ccf0-cfe8ae35ff11.png)

画面下部の入力フィールドに検査対象のメールアドレスと本名を入力して「Sign Up」をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/968b5563-6c32-a5e3-f101-a03a3e351b9e.png)

次画面でo365のパスワードを入力して、「GET STARTED」をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/225809b9-51d5-9c8b-c302-64b9c32861a3.png)

o365のアカウントに接続する旨の画面に切り替わるので「CONNECT OFFICE 365 TO SCAN YOUR ACCOUNT」をクリックします。

o365の指定ユーザに管理者の承認が必要みたいですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/63ad0a3b-b484-d2b7-6b77-43952e9c333b.png)

o365の管理者アカウントで入り直して、mailtestユーザに全体管理者を割り当てて、再度実施します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/b2563472-3da0-6c55-4247-82deff110e86.png)

色々とアクセス要求している一覧が表示されますが、「承諾」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/a8729b14-8592-d575-dbba-72bccf5a99fc.png)

利用者情報の入力です。
メールアドレス部分は既に入力済みなので、Name、Company, Phone Number, Zip Code, Countryを適宜入力、選択して、「START THREAT SCAN」をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/8b37f994-d22b-f704-092a-35ceeb2c7b0c.png)

無事スキャンが始まりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/bf20823e-5bd4-8276-31e5-4f24e558d6c8.png)

しばらく待つとレポート画面に切り替わります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/be883b19-5728-4118-cbbb-c9161b9be226.png)

##レポート確認

メール総数が少ないのであまり有用なレポートは今回は取れませんでした。

一点、「Domain fraud risks」が1になっていますね。

詳細を確認すると

**The number of domains managed by your account that are not protected against fraud using DMARC. These domains can be used to send fraudulent emails on your behalf to employees, customers and business partners.**

**DMARCを使用して不正行為から保護されていない、お客様のアカウントで管理されているドメインの数。これらのドメインは、従業員、顧客、ビジネスパートナーにあなたの代わりに不正な電子メールを送信するために使用できます。**

ということで以下の記事を参考にDMARCを有効化すれば良いかと。

[DMARC を使用して Office 365 でメールを検証する](https://docs.microsoft.com/ja-jp/office365/securitycompliance/use-dmarc-to-validate-email?WT.mc_id=AZ-MVP-5002499)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/d268854c-e067-15d3-420b-930bfbe9ed8b.png)

指定したo365のユーザ全員に対するリスク一覧が出ましたので、最初に指定したユーザのメールボックスだけではなく、組織全員のメールが対象となっているようです。
(なので、o365への接続時にグローバル管理者権限が必要だったのですね)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137436/126b889c-12b0-facf-8cac-d30ddd7b7ece.png)

#おわりに
無料で利用できるとの事ですので、o365の「管理者」の方が一括でメールセキュリティ検査を行う場合に有効だと思いました。

業務用の本番環境のo365で試す資格が無いため、レポート結果の内容について色々確認することが出来ず残念でしたが、手順や要件は把握できたので今回の試用はよしということにしておきます。
CentOS7のJenkinsのポート番号を80番に変えられなかった話(変え方の話)


# CentOS7のJenkinsのポート番号を80番に変えられなかった話

適当にyumとかでインストールして適当にsystemctl start jenkinsでスタートして8080で起動したあとのお話。
こんな感じでポート設定すれば行けるでしょって思いました。

vi /etc/sysconfig/jenkins

```
JENKINS_PORT="8080"　
↓
JENKINS_PORT="80"
```
**ダメでした**

#原因

参考
https://confluence.atlassian.com/confkb/permission-denied-error-when-binding-a-port-290750651.html

Ports below 1024 are called Privileged Ports
なんか1024以下は特別なポートでrootとかじゃないと開けられないっぽい。

# 変え方の話

実行ユーザー変えちゃうかすれば行けると思う
けれど特にそこまでのこだわりはなかったのであきらめて8080に戻しました。
PWAだからServiceWorker大切

前回
「PWA初期化」
https://qiita.com/sanoh/items/430a50035d4dfab0de7d
でPWAなのにServiceWorkerが入っていなかったので追加。

■Step1:index.htmlの修正
---

```haml:index.html
<!-- index.html -->
<html>
<head>
    <title>Hello ServiceWorker.</title>
    <link rel="manifest" href="./manifest.json">
    <script>
        if ('serviceWorker' in navigator) {
          navigator.serviceWorker.register('./service-worker.js').then(function() { console.log('Service Worker Registered'); });
       }
    </script>    
</head>
<body>
    <h1>Hello ServiceWorker!</h1>
</body>
</html>
```

■Step2：ServicWorkerのJSを追加
---

```javascript:service-worker.js
// service-worker.js
self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
});
  
self.addEventListener('activate', function(e) {
  console.log('[ServiceWorker] Activate');
});
  
self.addEventListener('fetch', function(event) {
});
```

これでServiceWorkerが使えるようになりました。
URLエンコードされた文字列をchromeのコンソールで元に戻す

* 下記のようなURLエンコードされた文字列を日本語に戻したいが、外部のデコード系Webアプリにはアップロードしたくない場合、chromeのコンソールで日本語に戻すことができる。

例

```
https://www.amazon.co.jp/%E4%BB%BB%E5%A4%A9%E5%A0%82-%E5%A4%A7%E4%B9%B1%E9%97%98%E3%82%B9%E3%83%9E%E3%83%83%E3%82%B7%E3%83%A5%E3%83%96%E3%83%A9%E3%82%B6%E3%83%BC%E3%82%BA-SPECIAL-Switch/dp/B07FDW61HX?pd_rd_wg=3VHKc&pd_rd_r=4c99b210-e326-47f4-b9fc-313a195d4d31&pd_rd_w=MGwLF&ref_=pd_gw_ri&pf_rd_r=82VW0Y87BX5YXVS8WG8N&pf_rd_p=4bb0e5f8-e3f8-5a77-a295-0af28240fc86
```

* chromeメニュー --> More tools --> Developer tools --> Console でコンソールを開く
* `decodeURI("{デコードしたい文字列}")`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/281036/f9f18a8f-e6ae-68a9-8a8c-59d903b0cc66.png)
CakePHP 3 の Html ヘルパーを使って data:image 形式の画像を表示する

CakePHP 3.6 の Html ヘルパーを使って data:image 形式の画像を表示してみました。
# 課題
画像がファイルとして存在していなく、Base64エンコーディングされているデータだったり、1回のリクエストでHTMLと画像を送信しなければならないときなど、

```HTML
<img src="data:image/png;base64,iVBORw0...S3wF==">
```
というタグをヘルパーを使って出力しようとして、テンプレート内で、

```PHP
<?= $this->Html->image('data:image/png;base64,iVBORw0...S3wF=='); ?>
```
とそのまま data:image を突っ込んでも、

```HTML
<img src="appdata:image/png;base64,iVBORw0...S3wF==" alt="">
```
の "app" のようなアプリケーションのパスがついてしまってうまく表示してくれません。
# 解決法
Htmlヘルパーの image() メソッドは、内部的にはパスを整形して formatTemplate() メソッドを呼び出しているようなので、

```PHP
<?php
$imageData = 'data:image/png;base64,iVBORw0...S3wF==';
echo $this->Html->formatTemplate(
  'image', [ 'url' => $imageData ]
);
?>
```
で良さそうです。

```HTML
<img src="data:image/png;base64,iVBORw0...S3wF==" alt="">
```

src 以外の属性を付けたい場合は、

```PHP
<?php
$imageData = 'data:image/png;base64,iVBORw0...S3wF==';
$attributes = [
    'class' => 'header-image header-image-logo',
    'alt' => 'Header Image'
];
echo $this->Html->formatTemplate(
    'image', [
      'url' => $imageData, 
      'attrs' => $this->Html->templater()->formatAttributes($attributes)
    ]
);
?>
```
とすると、

```HTML
<img src="data:image/png;base64,iVBORw0...S3wF==" class="header-image header-image-logo" alt="Header Image"/>
```

のような結果が得られました。

[ICOOON MONO](http://icooon-mono.com/)さんから、[無料のタブレットアイコン素材2](http://icooon-mono.com/11053-%E7%84%A1%E6%96%99%E3%81%AE%E3%82%BF%E3%83%96%E3%83%AC%E3%83%83%E3%83%88%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E7%B4%A0%E6%9D%902/) の素材を使わせていただいて、実際に表示される画像をスニペット的に作りました。
ビューにコピペしていただければ動くと思います。
なお、ヒアドキュメントを使う場合、trim() と併用して前後のスペースを除くようにしておくのが無難ですね。

```PHP
<?php

$imageData = trim(<<<END_OF_IMAGE
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB/ElEQVRoQ+1asU4bQRB947igSoeAhh5MQYeEIgGV5VuXOFVaZNpIEeEXIgpaS5RUFHS3u3IFSNBQgZRAnwJk0VC5snbQKQ6Kwvns3Vs3aK7emfdm39u9lWYIE3xKqXUAPwB8mmB5jCW/mbljjMkwXVFCGoNWUUp1AOzEYOWbg5lPjTGfi4ooLEAp9Q3AgS9wzPXMvGeMGcmhqABKkuSBiOZjEgrI1dNaLwDgvNiRBSillgDcBQBGD3HO1ay1uVxGFtBoNDYqlcp5dDYBCZ1zm9baCy8Fms3mJjOf/RtERFtpmk61KF/ckQr4JgrY2NwQX1wpINbO/80jCoTuRCwlRAFRoKSXxEJiIbGQ3xtMnhIlHfMmXG4huYVKekosJBYSC8mP7I8HfG+Dks55DffFladErJ0Pvf1EAVHgvx2QQxx6mGJZSRR41woA+EpEN7HskpeHmVcBHE7aWPH6D0yTeFHuos7Q+y0gRpOPmR8BHAPYJaKPoQoGNfnq9XqtWq3+DAUdxi1rre+VUl+GhQSlGwwGK91u91de8LhGd4+IZoNQARDRWpqm10mStIkoG1nw/pj5yRgz593ozpAijBo8M/MtgDUimvFmn7EuMWqQ4WXDHicAtkPAI8Qcaa13g4c9MgKtVutDv9//DqANYDECqUlSXDrn9q21V+MWvwBaiKVPvJ+e4gAAAABJRU5ErkJggg==
END_OF_IMAGE
);

$attributes = [
    'class' => 'icon-tablet',
    'alt' => 'Tablet'
];

echo $this->Html->formatTemplate(
    'image', [
        'url' => trim($imageData),
        'attrs' => $this->Html->templater()->formatAttributes($attributes)
    ]
);

?>
```
laravelの開発環境をコマンド一発で作成

ジーズアカデミー Advent Calendar 2018 18日めです。
まだ、地球上では12月18日の場所があるのでギリギリセーフ。

## Who am I ?
ジーズアカデミーでiOSの講師をしています。
どうやらLaravelの講師もやることになりそうです。
インフラが好きです。

## TL;DR
超簡単（ほぼコマンド一発）にLaravel開発環境を作れるようにしてみました。
ちょっとだけ便利なツールも作ってみました。
講義をするときに大変なのは環境を揃えることだったりします。

## LaravelとPHPについて
Laravel良いですよね。アプリを作るの簡単でアホになれます。PHP7サイコーです。はやく[プロパティーの型指定](https://wiki.php.net/rfc/typed_properties_v2)使いたいです。ついでにジェネリクスとenumも実装して欲しいなとおもったけどそれなんてHHVM？
Eloquent使ってキッチリパフォーマンスだすのはSQL書くより難しかったり・・・。
Eloquent便利でもまだ今はSQLちゃんと書けた方がいいと思います。


## やったこと
docker使ってLaravelの開発環境を簡単に作れるようにしました。
Mac限定です。Windowsでも少し頑張れば動くと思います。
[laradock](https://laradock.io/)を元にしてコマンド1発で動くように（ただし[Docker Desktop](https://www.docker.com/products/docker-desktop)インストール済みでgit cloneした後）


## コンテナの構成
Laradockを土台にして作っています。Laradockは何でも入りすぎなので最低限必要なモノだけにそぎ落としてカスタマイズしてあります。
あとでDBを操作するツールも使えるようにしておこうかなと思っています。
デフォルトではmysqlを使うようになっていますがpostgresqlを使いたい場合は`laradock/docker-compose.yml`を編集して使えるようにして下さい。個人的にはpostgresqlの方が好きです。
<img width="851" alt="スクリーンショット 2019-02-02 20.54.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/183301/1854b2a2-f676-9e34-094b-14625e27b81b.png">

## 使い方
リポジトリ： https://github.com/taichi0529/laradev
環境を変更したい場合は`laradock/env-example`を先に編集して下さい。こちらもLaradockのファイルから大分そぎ落としてあります。
`laravel5．5`を使う事を前提にしています。

```bash
git clone git@github.com:taichi0529/laradev.git
cd laradev
./start.sh
```
問題無ければ`http://localhost:8888/`でアクセス出来るはずです。

## おまけ

```bash
./container-login.sh
```
でコンテナを選んでログイン出来ます。

## dockerについて

今更ですがdockerのコンテナは仮想マシンじゃありません。docker上でWindowsは動きません。
Linuxの機能を使って作られるコンテナをdockerが管理しています。
**Linux（カーネル）が本社でコンテナは支社**みたいなもんです。本社がリソース（会社だと人、PCだとCPUやメモリなどのリソース）を支社へ配分しています。Appleの支社にMicrosoftはなれないですよね。なのでWindowsは動かないです。
dockerが支社をバンバンつくってバンバン潰します。支社の中では本社のルールで動きます。つまりコンテナの中ではLinuxのプログラムしか動かないのです。
ちなみにMac上のDockerはMac上で動いているLinuxの上で動いています。で、このLinuxがどうやって動いているのかは仮想化やハイパーバイザーをググってみると良いかもしれません。

## 最後に
dockerもそうだしAWSなんかもそうだけれどネットワークのことを理解すると一気に扱いやすくなります。
オンプレサーバ60インスタンスをaws移行で3インスタンスに圧縮したときにハマった3つのこと


# はじめに
この記事は
「DeNAその2 Advent Calendar 2018」
23日目の記事です。

先日弊社からこのような記事が公開されました。
https://fullswing.dena.com/archives/2638

こちらの先陣として私のチームの開発サーバをオンプレからAWS(EC2)に移行したときのお話です。

※用語説明
`環境 = 主要なJenkinsJobやアプリサーバが動作する汎用開発環境の単位`

# オンプレ使用状況
openstack上の仮想マシン
スペック: `cpu:8core mem:12GB storage:200GB`
インスタンス数: 60
1インスタンスあたりの環境: 2
環境の合計: 120環境

# aws使用状況
Amazon EC2
インスタンスタイプ: `c4.8xlarge`
スペック: `cpu:36 mem:60GB storage:2.5TB`
EBS: 1つ (諸事情によりルートは別EBS)
インスタンス数: 3
1インスタンスあたりの環境: 40
環境の合計: 120環境

# 60インスタンスを3インスタンスに圧縮するメリデメ
### 圧縮するメリット
- コストを下げることが可能
    - サーバリソースの遊びが少なくなるため、その分のコストが浮きます
- 管理が楽になる

### 圧縮するデメリット
- インスタンスが1つ落ちたときの影響が大きい
- 工数がそこそこかかった (実績は1人月程度)
    - 昔からの負の遺産の改善やコミュニケーションも込み

# ハマった３つのこと
1インスタンスの同居環境数を `2 => 40` に対応させようとしたときにハマりました。

### ポートがバッティング
インスタンス数圧縮行うには、理論上1インスタンスにどれだけの環境を詰め込めるのか知る必要がありました。
試してみると、ポートの設計で最大10環境、スクリプト類で最大9環境、proxy(nginx)の設定で最大15環境まで対応していることがわかりました。
この環境数ではコスパが良くないので、これを40環境まで対応する改修を行いました。
ポートの設計 => バッティングしないように再設計
スクリプト類 => 環境名(例aaa01)の下一桁でアクセスポートを決めていた部分を二桁に対応
proxy => 管轄がインフラだったので依頼して40環境分アクセスできるように変更

### サーバリソースが足りない (memory / cpu / io)
なにも考えずに `c4.8xlarge` で40環境を一斉にアクティブな状態にすると、
`必要メモリは120GB以上`
`cpuは100%に張り付いてsshの応答すら返さない`
`iowaitでまくり`
`load average 200以上`
でまともに使用できませんでした。
<img width="792" alt="スクリーンショット 2018-12-22 21.19.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/6373/1a81a15c-ecbc-eb69-d561-ed724d8adb6c.png">
スペックを上げるとコストが・・・となります。
リソースをバカ食いしているのは `plackのworkerが世代交代する時の処理` だったので、worker自体の起動タイミングをチューニングしました。
各環境はすべてを毎日使っているわけではなく、120環境中平均して40環境ほどデイリーで使われていました。
なので、夜中に全workerをcronでstopし、朝の作業開始時に必ず実行するであろうJenkinsJobでworkerをstartさせるようにしました。
これにより、その日使われる環境分だけリソースを消費するようにできました。
`c4.8xlarge x ebs1つ` で20環境は同時に捌ける想定なので、3インスタンスあれば賄えました。

### スポットインスタンスが不安定
普通のオンデマンドインスタンスに比べて `スポットインスタンス` だと、コストを最大1/4程度に抑えることができます。
もちろんデメリットはあって、
`急にインスタンス中断する(落ちる)可能性がある`
`インスタンスタイプ/リージョン/az によって中断割合が違う`
`中断の頻度「<5%、5～10%」と言われてもなんだかよくわらない`
と、コストが低いだけの扱いづらさがありますが、コスト削減効果は大きいので利用することにしました。
そんな中選んだいい塩梅のインスタンスタイプが、 `c4.8xlarge` です。
※選んだ当時は `<5%` だったはずなんですが、いまは `5～10%` と少し落ちやすくなっています。
現状の運用では 1~2週間に1インスタンス程度のペースでランダムな時間帯に瞬断されます。
落ちにくいインスタンスタイプは他にもあるのですが、今回必要なスペックで絞るとなかなかいいものがなくて最終的にはここに落ち着いています。

瞬断の対応としては、spotがダウンする通知をメールで受けたり、regeonやazを各インスタンスでバラけさせたり、落ちた実績のあるazは使用しないようにしています。
今後この瞬断の影響が大きいようなら、一時的に同スペックのオンデマンドに切り替えてからゆっくり対応を考えようと思っています。

# さいごに : EC2以外のawsサービスは使わないの？
`コンテナ技術などの選択肢はなかったのか？` という質問をよく受けるのでそちらに答えておくと、
60インスタンスという規模の移行には影響する人も多く、移動は必須、期限もあって、これのための工数は確保されていない、という状況での対応だったので、最小工数で行うためにできるだけ同じ状態で移行させたいという意図がありました。
オンプレの開発サーバは私のチームはこれ以外にもあって、それらを移行するときに他のawsサービスも検討していくつもりです。
【Swift】Timerがズレる (遅延する) 時の原因と対処法

下記ブログの転載です
https://rc-code.info/ios/post-172/


iOSにて、**`UIScrollView`** と **`Timer`** を併用した際に **`Timer`** がずれてしまったので対応方法を備忘録。
今回は **`Timer`** の **`scheduledTime関数`** を利用した際の対応法をお伝えします。
&nbsp;

## Timer.scheduledTime関数 の使い方
**`Timer.scheduledTime関数`** の基本的な使い方は下記にまとめましたので、ご参考ください。
<a href="https://rc-code.info/ios/post-167/" target="_blank" rel="noopener">【Swift】加算型Timer（ストップウォッチみたいな）の作り方 〜Timerの基本的な使い方〜</a>
&nbsp;

## Timer がズレる (遅延する) 環境と原因
**`Timer`** がずれる環境ですが、**操作関連の処理が走っている時に発生しやすい**です。
僕の場合、**`UIScrollView`** の **`scrollViewDidScroll`** イベントが発火するタイミング、つまり**スクロールしている場合**にこの現象が起きました。

この現象が起こる原因ですが、**`Timer.scheduledTime関数`** を実行して作られる **`Timer`** が**画面操作の処理と同様モードとして `RunLoop` に設定されるから**です。
**`Timer.scheduledTime関数`** は **`Timer`** を作成し、その実行threadを **`RunRoop`** に **`defaultMode`** として**自動的に**登録します。

コードで書くとこんな感じです。

```swift:
RunLoop.current.add(timer, forMode: .default)
```

**`RunLoop`** は入力系（NSConnecionや画面操作など）の thread を処理していく機構です。

上記のコードで、**`forMode`** に **`.default`** と指定していますが、これは **`NSConnection`** 以外の入力系を処理する際に推奨・利用されるModeです。
つまり、**操作系の入力と同様のイベントとして処理される**ということです。

これが原因で、**`Timer`** が遅延します。
操作系の入力と同様に処理しているので、正確に **`Timer`** の実行処理をしたいのに、そちらの処理に時間をとられた結果 **`Timer`** の実行が遅れるわけです。
&nbsp;

## Timer がズレる (遅延する) 時の対処法
上記の通り、原因は **`Timer`** が操作系と同様のModeとして **`RunLoop`** に登録されているからです。
なので、**遅延が起きた時は明示的に下記のように `.common` モードとして登録する必要**があります。

```swift:
RunLoop.current.add(timer, forMode: .common)
```

**`.common`** Modeは **一般的な利用目的がある際に設定するモード** らしいです、（ようわからんw）
つまりアプリ内で必要に駆られて利用する場合（他モードのモーダルパネルやコネクション、操作のトラッキングを省く）に使えという事だと思います。

こちらを設定すれば、操作系との差別化が図られ、正常に動作すると思われますのでお試しください。
&nbsp;

## RunLoop操作時の注意点
**`RunLoop`** へ **`Timer`** を登録すると**強参照**になります。
なので、**プロパティとして `Timer` を持つ際は `weak` にしておくべき**です。

また、公式ドキュメントにもあるように **`RunLoop` は `threadSafe` なオブジェクトではありません**。
thread管理も同様に行なっている場合、予期せぬ強制終了などが起こり得るので、注意して実装しましょう！
&nbsp;

## 参考ドキュメント
<a href="https://developer.apple.com/documentation/foundation/runloop" target="_blank" rel="noopener">公式RunLoopドキュメント</a>
<a href="https://developer.apple.com/documentation/foundation/runloop/mode" target="_blank" rel="noopener">公式RunLoop.Modeドキュメント</a>
<a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html" target="_blank" rel="noopener">公式ThreadProgramingGuide</a>
&nbsp;