OmniAICreator/Qiita-1.07M huggingface dataset:
monorepo内のReact Nativeのバージョンをアップグレードするのに苦労した話

## 概要

とあるプロジェクトで使っているReact-Nativeで作成されたアプリにて、React-Nativeのバージョンを`0.55.4`から`0.57.1`に変更する中で詰まった事について書く。

なお、当プロジェクトは`lerna`を用いたmonorepoを活用しており、React-nativeのプロジェクトはそのmonorepoの一つである。

`react-native init`で作成されたプロジェクトの為、Expoは使用していない。

## React Nativeのバージョンが上がる際の変更点

React Nativeのバージョンが上がると、主に以下の変更が行われる。
**太字**が今回の変更で特徴的だった箇所である。

- `build.gradle`や`info.plist`など、各ネイティブアプリのビルドに必要なファイルの変更
- `react`等の使用しているdependenciesのバージョンの変更
- **RN`0.56.0`にてBabelのバージョンが6から7に変更**
- **RN`0.57.0`にて、`rn-cli.config`で使用される`metro bundler`の書き方が変更**

各変更に対してどの様なアプローチをとったかを記載する。

### `build.gradle`等の変更
React-nativeのバージョン上げで変更されたファイルを楽に変更する手段として
[react-native-git-upgrade](https://github.com/facebook/react-native/tree/master/react-native-git-upgrade)が存在する。

しかし！

monorepo上で他のmonorepoのpackagesに依存している場合、失敗してしまう。
(2018/12/10現在、[別の理由](https://github.com/facebook/react-native/issues/21241)でRN57以降では使用できない)

なので、[rn-diff-purge](https://github.com/pvinis/rn-diff-purge)というレポジトリ上で記載されている各アップグレードの差分をみて手動でファイルの変更を加えていた。

`info.plist`等、手動で変えていくには辛いものがあったが作業自体は時間がかかるのみで難しくはなかった

### `react`等のdependencyの更新
`package.json`を更新して`lerna bootstrap`でpackageの更新を行った

### Babelのバージョンを6から7に変更

Babel6から7への変更でpackage名に大幅な変更が加わった

`babel-core`から`@babel/core`への変更や、
`babel-preset-env`から`@babel/preset-env`への変更である

また、Babel7になるにあたってpreset-stage-系列が廃止されたので、必要なpluginを探して取ってくる必要があった。

加えて、RN0.57ではreact-native用のpresetの名前が`react-native-preset`から[`metro-react-native-babel-preset`](https://github.com/facebook/metro/tree/master/packages/metro-react-native-babel-preset)へ変更された。

### rn-cli.configのフォーマットが変更された
monorepoでreact-nativeを使っていて、packages内に他に`react-native`へ依存しているpackageがある場合metro bundlerでエラーが発生してしまう。
そのため、`rn-cli.config`にて重複するreact-nativeをblacklistに入れるようmetro bundlerを設定する必要がある。

その他、react-nativeでtypescriptを使用する際にもこの設定が必要となる。

RN0.57から、このrn-cli.configの書き方が変更された。
設定方法は[metroの公式サイト](https://facebook.github.io/metro/docs/en/configuration)に記載されている。

また、RN0.57が使っているmetroは`blacklist`へのパスが少し変更されている。
だが、あまりドキュメントが豊富とは言えないので、trial and errorで試していく必要があった。

```rn-cli.config.js
const blacklist = require('metro-config/src/defaults/blacklist')
```

[metro-with-symlinks](https://github.com/MrLoh/metro-with-symlinks)というrn-cli.config生成用のツールがある事をあとになって知った。使ってはいない。

# まとめ
react-nativeのprojectをmonorepoで管理していると、monorepo特有の詰まり方等があって少し苦労した。


# 最後に
　本記事は We Are JavaScripters!【執筆初心者歓迎】 Advent Calendar 2018 (https://adventar.org/calendars/2972) の 12/10 担当分の記事です。

WeJS2周年おめでとうございます！
ソースコードの可読性を上げるための工夫

##はじめに
エンジニアとして「クソコードだ」って言われると辛いですので、そのために日々いいコードを書けるように努力しています。いいコードの定義人それぞれですが、自分にとって「いいコードは読みやすいコード」になりますので、読みやすいコードを書けるためにちょっとした工夫を紹介したいと思います。

##使う英語を調べる
当然ですがプログラミング言語ほぼ英語になりますし、変数やメソッド名も英語で付けますので、たまに可読性を上げるために英語力の方が問われているではないかって思ったします。命名などをするために自然な英語を使った方がわかりやすいですが、自分英語ネイティブではないので、使おうとする名前は本当に存在しているか、ニュアンス合っているかどうかのを確かめるために毎回ネットで調べています。まず単語自体を調べて、意味と品詞を確認します（よく英語と思ったら実は和製英語とか、動詞として使ってるけど英語だと名詞になっているとかありますので）。あと自分使いたいシナリオで調べて、ネイティブのエンジニアだとみんなどんな名前にしているのを参考しています。
##Ifを使わない
[現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法](https://www.amazon.co.jp/dp/B073GSDBGT/ref=cm_sw_r_cp_ep_dp_NPIdCbQ02FFBM) を読んでから、`If`文を使わないようにしています（もちろん`Boolean`の判別など逆に`If`文を使ったほうがわかりやすい場合がありますので、完全に使わないわけではないです）。やはり何かを修正する時、既存のコードへの修正を最小限に済ませたいとみんな自然になりますので、最初から`If`文使ってしまうと、ロジックが変わる度にIfに分岐を追加したり,さらに`If`の中に条件分岐を入れたり、最終的にネストが深くなって読みづらくなるわけです。
逆にIfを使わない場合、メソッドに分割したり、クラスにまとめたり、他の実現方法を考えないといけなくなります。また処理の流れ（手続き）より本来実現すべきことに注目して考えるようになりましたので、可読性だけではなく、 より適切な実装ができると思います。~~あとコーティングが上手くなった気がします~~ 。
##メソッド名を決めてから詳細を書く
コーティングし始めた時、とにかく動くものを早く作りたいので、とりあえず処理を一気に書いて、動くことを確認できてからちゃんとした名前をつけたり、リファクターしたりしていました。正直リファクターしたつもりであっても、大体メインな処理の流れを変えずに、すでに書いているコードに合わせて調整するだけなので、最終のコードは処理の流れに合わせて手続きになりがちです。
それで書き方を変えてみました。実装したいものについてどんなメソッドが必要なのか、詳細を書かずに名前（あとScalaで開発していますので戻り値の型も）だけ全部定義します。それでメインな処理を組みます。上手く組めない時や、処理を見てメソッド名に違和感を感じた時は、コードの構造が適切ではないか、メソッドが適切に分割されていないので、最初から定義し直してもう一回組んでみます。メインな処理を上手く組めて、かつメソッド名が正しく自分の役割を表現できているのを確認できてから、各メソッドの詳細を実装します。

Scalaのコードになりますがイメージとしてはこんな感じです↓
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/158482/68be3771-3ad7-a0e0-e789-0f18f89a20e5.png)

このやり方で実装すると、最初からメソッドが実装したいものに合わせて分割されていますので、手続きではなく実装に合った構造にできますし、メインの処理がスッキリになって読みやすくなります。
もしどうしても上手く名前つけられない場合は、実装したい内容をリストアップして文字にみることで大体できるようになります。それでもできない場合はビジネスロジックや仕様にまだ不明確なところがありますのでもう一回確認した方がいいと思います。
##コメントを書かない
正確に言うと、「コメントがなくても意図を伝えられるように」コードを書くことです。まず情報が間違っているや、そもそも情報がないコメントは、読む人を混乱させてしまうので、書かないほうがいいと思っていますし、コメントで正確なメッセージを伝えるのは、コードで正確なメッセージを伝えると同じくらい難しいと思っています。であればコメントなしでコードだけでメッセージを伝えることに集中すれば、（多分）難しさが半分になるはずです。またコードが変わる度にコメントの内容もそれに合わせて更新しないといけないので、更新漏れを防ぐためにも、最初から書かずに全てコードを正にしたほうがいいと思います。
もちろんコメントが必要な場合もあります。コードでどうしても表現できない（「環境の制限でこう実装しないといけなくなったー」とか）、その時はちゃんと意図（WHY）を記載するようにコメント書きます。
Lambda Layersで共通パッケージを作る (ロギングを例にして)

AWS re:InventでリリースされたLambda Layersの機能を使うと、パッケージをLambda間で共有して使えます。
この楽さを試すために、例として、どんなLambdaからでも呼び出して使いそうな、CloudWatch Logsに固定のフォーマットでログ出力するパッケージ (命名: `cwlogging`) をLayer化してみます。

今回の前提はPython3.6です。

# cwloggingを作る
作ります。よくあるやつです。logStrでログフォーマットを決めています。

```python:cwlogging.py
import datetime

# Lambdaログ出力(CloudWatch Logs)関数
def logging(errorLv, lambdaName, errorMsg):
    loggingDateStr=(datetime.datetime.now()).strftime('%Y/%m/%d %H:%M:%S')
    logStr = loggingDateStr + " [" + errorLv + "] " + lambdaName + " " + errorMsg
    # CloudWatch Logsに出力
    print(logStr)
    # ログ文字列を返却
    return logStr
```
# cwloggingをzip化
お作法に従う必要があります。
公式ドキュメントを読むと、pythonの場合は「python」ディレクトリを作って、その下に.pyを格納する必要があるようです。
先ほど作ったcwlogging.pyを以下のようにzip化して、s3にアップロードします。

```bash
$ mkdir python
$ mv cwlogging.py python/
$ zip -r cwlogging.zip python/
$ aws s3 cp cwlogging.zip s3://lambdalayertest/
```
# Lambda Layersの作成
Lambdaの管理画面に行くと、左側に「Layers」が増えています。
「Layers」の管理画面から、s3上の.zipのパスを指定してアップロードすると、Layerが出来上がります。
今回アップロードしたLayerは`import cwlogging`とすることで呼び出せます。

# Lambda関数からLayerをimport
Lambda関数のコードは、テストなので簡単にいきます。
忘れずに `import cwlogging` を書いて、先ほどのLayerをインポートします。

```python:lambda_function.py
import cwlogging

# lambda_handler
def lambda_handler(event, context):
    # TODO implement
    cwlogging.logging("INFO", "LambdaLayerTest", "This is test.")
    
    return ''
```

# Lambda関数からLayerを参照
Lambda関数の下に、Layerの参照状況を示す画面があります。
![lambdalayer2.png](https://qiita-image-store.s3.amazonaws.com/0/211986/bdaf5624-91d4-2d02-18ce-e6b895c86813.png)
ここで「レイヤーの追加」を押して、Lambda関数とLayerを接続します。
![lambdalayer1.png](https://qiita-image-store.s3.amazonaws.com/0/211986/53172dd3-8866-484d-b956-b09dcb10a6cc.png)

# Lambdaを実行する
Lambda関数からLayerを参照できるようにした後、Lambda関数を実行すると、以下の通りの結果となります。
Lambda関数からLayerを呼び出して処理できていることが分かります。
![lambdalayer4.png](https://qiita-image-store.s3.amazonaws.com/0/211986/e2ae83b0-c2d7-9a08-59c3-c7cbbd80b5f2.png)
別のLambda関数からこの`cwlogging`を呼び出す時も、別のLambda関数の.zipに固めるのではなく、
同じようにLambda関数からLayerを参照できるようにして、コード内で`import cwlogging`してあげるだけで良いです。

Lambda Layersの登場で、どのLambda関数でも実行するような共通処理があれば、
その処理をLayer化することで、手軽に再利用できるようになりました。便利です。

# 参考文献
[AWS Lambda Layers](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html) - AWS公式
Unity Tiny を運用型ゲームの観点から流し見

# はじめに

Unity Tiny が触れるようになりました。
https://blogs.unity3d.com/jp/2018/12/05/project-tiny-preview-package-is-here/

小型の Unity ランタイムとのことですが、運用型のプロダクト開発に適しているのかの観点でさらっと流し見したポイントを押さえてまとめます。

なお、 Unity Tiny 自体のインストール手順などは省略します。

# ポイント

## プロジェクト構成

JavaScript 実行環境(ブラウザ)においても DoD は有効なんですね。
リリースまでには TypeScript が C# に変わるそうですが、また魔変換ですかね。

ECS 前提の作りになっているので、メモリアクセスの実行速度は最適化される(らしい)。

ECS 自体がこれまでの Unity が必須としていた実装手法ではないので、Unity を学習済みだからといってノウハウが流用できるとは限らず、ある程度の学習コストは覚悟した方が良い。
そういう意味では、もともと Unity を使っていなくても導入はしやすい。


## ランタイム

いらすとやの画像を一つ含んだだけのほぼ空のプロジェクトで 751 KB。
特筆するほど軽量なわけではなく、むしろこの必要経費に対してアプリケーションコードが上乗せされる。

<img width="1186" alt="スクリーンショット 2018-12-10 17.58.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/42873/df94a3e8-3069-23d9-8836-7df0c10cba5c.png">

実行時パフォーマンスは本稿では扱わない。

## 画像リソース

バンドルした画像が Base64 で扱われており、スクリプト上に平分で定義されている。
アプリケーションにバンドルする以外のアセット取得手法が現時点で提示されておらず、また、圧縮テクスチャへの自動変換や実行環境別の自動振り分けなどはない。

<img width="1035" alt="スクリーンショット 2018-12-10 17.55.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/42873/f0ef8db4-47c5-c7f7-fe83-4ecc31feec51.png">

運用型コンテンツの観点からは、正直、辛い側面が多い。

- 画像データが必要以上に大きく表現される、というか静的に定義されているのでリソースの量だけメモリ圧迫
- Base64 ってことは DOM 通してる、GC がブラウザまかせ
- DOM を触らせてくれるような I/F が見当たらない (あったらすいません)
- スクリプト上にまとまって定義されているため、一部の画像を差し替えた場合でもスクリプトが再 DL になる
- 公開したくない画像を予め仕込むなどができない



## その他

#### 将来的には C# に移行するので npm パッケージは使えない

TypeScript のままの方が良いのでは。
AssetStore で Tiny 向けのアセットが出てくるのを待つよりも、npm の既存のモジュールを活かした方が良いと思う。

#### 画像などのリソースは、利用しているもの全てバンドルされる

デザイナーさんがあたりを付けるためのダミー画像などもバンドルされる。
CDN などへのビルド~デプロイのパイプラインの柔軟性が低い。エディタ拡張に期待。
また、テクスチャを動的に差し替えたい場合などの手法が今回のサンプルでは提示されていない。
(DOM で持っているので、WebGL に流す前にインスタンスがつかめれば・・・)


# まとめ

画像リソース周りの仕様から、カジュアルゲーム向けに使わないと辛い、という所感でした。
動的に画像を取得して表示できた後も、Tiny の API から DOM メモリ管理ができないとロングサイクルのゲームプレイは難しい。
カジュアルゲームを量産する感じなら、試してみても良いかもしれない。
個人的には DoD の流れは好き。
合成数列の和 (Pascal)


|合成数列の和|https://qiita.com/advent-calendar/2018/composite-number|
|:--|:--|
|Python(/Ruby)|https://qiita.com/cielavenir/items/dcbd839b0c66af1bc971|
|Crystal|https://qiita.com/cielavenir/items/1a0dd1a94aca9935f5aa|
|Kuin|https://qiita.com/cielavenir/items/47fd18fc68055d990599|
|Swift|https://qiita.com/cielavenir/items/6cde3b20866c842dc9e2|
|Kotlin|https://qiita.com/cielavenir/items/f58eaa30f90781229a6d|
|Pascal|https://qiita.com/cielavenir/items/35c2fc54ca16b620c9c7|

```pas:composite.pas
program composite;
var i,s,n,cnt: longint;

function isqrt(n: longint): longint;
var
	x: longint;
	y: longint;
begin
	if(n<=0) then
		isqrt:=0
	else if(n<4) then
		isqrt:=1
	else begin
		x:=0;
		y:=n;
		while((x<>y) and (x+1<>y)) do begin
			x:=y;
			y:=(n div y+y) div 2;
		end;
		isqrt:=x;
	end;
end;

function isPrime(i: longint): boolean;
var
	j: longint;
begin
	isPrime:=true;
	if i<2 then isPrime:=false;
	for j:=2 to isqrt(i) do begin
		if(i mod j < 1) then
			isPrime:=false;
	end;
end;

begin
	read(n);
	i:=2;
	cnt:=0;
	s:=0;
	while(cnt<n) do begin
		if(not isPrime(i)) then begin
			s:=s + i;
			cnt:=cnt + 1;
		end;
		i:=i + 1;
	end;
	writeln(s);
end.
```
合成数列の和 (Kotlin)


|合成数列の和|https://qiita.com/advent-calendar/2018/composite-number|
|:--|:--|
|Python(/Ruby)|https://qiita.com/cielavenir/items/dcbd839b0c66af1bc971|
|Crystal|https://qiita.com/cielavenir/items/1a0dd1a94aca9935f5aa|
|Kuin|https://qiita.com/cielavenir/items/47fd18fc68055d990599|
|Swift|https://qiita.com/cielavenir/items/6cde3b20866c842dc9e2|
|Kotlin|https://qiita.com/cielavenir/items/f58eaa30f90781229a6d|
|Pascal|https://qiita.com/cielavenir/items/35c2fc54ca16b620c9c7|

```kotlin:composite.kt
fun isqrt(n:Int):Int{
	if(n<=0)return 0
	if(n<4)return 1
	var x=0
	var y=n
	while(x!=y&&x+1!=y){x=y;y=(n/y+y)/2}
	return x
}

fun isPrime(i:Int):Boolean{
	if(i<2){
		return false
	}
	for(j in 2..isqrt(i)){
		if(i%j<1){
			return false
		}
	}
	return true
}

fun main(args: Array<String>){
	val n=readLine()!!.toInt()
	var i=2
	var cnt=0
	var s=0
	while(cnt<n){
		if(!isPrime(i)){
			s+=i
			cnt+=1
		}
		i+=1
	}
	println(s)
}

```
Laravel 【多対多】 カウントと並び替え

## 前提
今回は下記項目を登録する想定で書いてます。
（商品に複数のタグを登録できる多対多の関係）

- 商品
- タグ

## やりたいこと

- 注目タグ（商品に登録されている数の多いタグ）を作成したい
- 注目タグを商品に登録されている数の多い順に表示させたい

## 最初に

- 商品一覧と、それに紐づくタグを表示させるページを作成する
- ひとつの商品に、複数のタグを登録できるものとする
 - 商品(items)テーブル、タグ(tags)テーブル、中間テーブル(item_tag)を作成・使用
 - 商品(items)モデル、タグ(tags)モデルを作成・使用

##### DB

| items            | tags              | item_tag           |
|:-----------------|:------------------|:-------------------|
| id               | id                | id                 |
| name             | name              | item_id            |
| created_at| created_at        | tag_id             |
| updated_at        | updated_at        |

##### Model
```php:Item.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
   public function tag(){
     return $this->belongsToMany('App\Tag', 'item_tag', 'item_id', 'tag_id');
   }
}
```
```php:Tag.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
   public function item(){
     return $this->belongsToMany('App\Item', 'item_tag', 'tag_id', 'item_id');
   }

}
```

## 実装

```php:IndexController.php
<?php

namespace App\Http\Controllers\Index;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Item;
use App\Tag;

class TopController extends Controller
{
  public function index()
  {
     $items = Item::get();

     //withCountメソッドでリレーションの数を取得
     $attentionTag = Tag::withCount('item')
     ->orderBy('item_count', 'desc')
     ->get();

     return view('index', compact('items', 'attentionTag'));
  }
}
```



'item_count'は一体どこから…？

↓

**リレーション結果の件数を実際にレコードを読み込むことなく知りたい場合は、withCountメソッドを使います。件数は結果のモデルの{リレーション名}_countカラムに格納されます。**
（[Laravel 5.7 Eloquent：リレーション](https://readouble.com/laravel/5.7/ja/eloquent-relationships.html#many-to-many-polymorphic-relations)参照）

便利…{リレーション名}_countカラムをテーブルに作成していなくてもよいのだ…

####できた
これで商品に登録されている回数の多い順にタグを取得できました。
WordPress5.0 カスタム投稿でのGutenberg使用方法

# WordPress5.0のカスタム投稿
今回もWordPress5.0のメモ書きです。
様々な案件でカスタム投稿機能を使われる方が多いかと思うので誰かの参考になれば幸いです。

詳しくは[こちら](https://github.com/WordPress/gutenberg/issues/12442)のIsuuを見てください。

要約するとカスタム投稿機能を使うと強制的にクラシックエディターに戻ってしまいます。
※案件によっては助かる場合も・・・・

そこで[Isuu](https://github.com/WordPress/gutenberg/issues/12442)に上げられているのを発見したので、今回はその適用方法です。

# register_post_type()に設定を加える
カスタム投稿機能を使用可能にする関数にパラメーターを1つ加えることにより、Gutenbergが適用されます。

```PHP
'show_in_rest' => true
```
この「show_in_rest」パラメーターをtrueにすることでカスタム投稿でもGutenbergが反映されるようになるみたいです。
また、その際に「supports」パラメーター内に「editor」が設定されていることが必須のようです。
※「title」が無くてもGutenbergが適用されます。

このパラメーターはWordPress REST APIを使用してカスタム投稿の記事を取得したい場合に使用します。
JavaScriptで作られているGutenbergもREST APIを通してデータを取得しているようなので、
このパラメーターがTrueである事が使用条件になっているのでしょう。

全体的には下のようなコードになります。

```php
register_post_type(
		'customPost',
		array(
			'labels' => array('ラベルのなんやかんや'),
			'menu_position' => 5,
			'public' => true,
			'has_archive' => true,
			'rewrite' => array(
				'slug' => 'customPost',
				'with_front' => false
			),
			'show_in_rest' => true, // Gutenberg使用時に必要
			'supports' => array(
				'title',
				'editor', // Gutenberg使用時に必須
				'revisions'
			),
			'map_meta_cap' => true
		)
	);
```
シクシク素数列 (Pascal)


|シクシク素数列|https://qiita.com/advent-calendar/2018/4949prime-series|
|:--|:--|
|Crystal|https://qiita.com/cielavenir/items/4c95fdf14b7a247e51e0|
|Kuin|https://qiita.com/cielavenir/items/60993a2b2885690a3a4a|
|Swift|https://qiita.com/cielavenir/items/db4c93532a53bfa33ac2|
|Kotlin|https://qiita.com/cielavenir/items/f3ccdd5ebf245aba417c|
|Pascal|https://qiita.com/cielavenir/items/4c962db6825d9a5eb511|

```pas:4949.pas
program sksk;
var i,n,cnt: longint;

function isqrt(n: longint): longint;
var
	x: longint;
	y: longint;
begin
	if(n<=0) then
		isqrt:=0
	else if(n<4) then
		isqrt:=1
	else begin
		x:=0;
		y:=n;
		while((x<>y) and (x+1<>y)) do begin
			x:=y;
			y:=(n div y+y) div 2;
		end;
		isqrt:=x;
	end;
end;

function isPrime(i: longint): boolean;
var
	j: longint;
begin
	isPrime:=true;
	if i<2 then isPrime:=false;
	for j:=2 to isqrt(i) do begin
		if(i mod j < 1) then
			isPrime:=false;
	end;
end;

function is4949(i: longint): boolean;
begin
	if(i <= 0) then
		is4949:=false
	else if( (i mod 10 = 4)or(i mod 10 = 9) ) then
		is4949:=true
	else
		is4949:=is4949(i div 10);
end;

begin
	read(n);
	i:=2;
	cnt:=0;
	while(cnt<n) do begin
		if(is4949(i) and isPrime(i)) then begin
			write(i);
			if(cnt < n - 1) then
				write(',')
			else
				writeln();
			cnt:=cnt + 1;
		end;
		i:=i + 1;
	end;
end.
```
[PHP] Trait の private は使用しているクラス上では普通に使える件

マジで？って思ったので

皆さんこんにちは
PHPで実装するとき、当然のようにメソッドにアクセス権をつけるわけです。
公開する`public`, 自身、および継承先の中でのみ使用できる`protected`, 自身の中でしか使えない`private`...。
今更何いってんだって思うかもしれんのですが、このアクセス権がいい感じに作用しないケースがあったので、簡単にまとめます。

名前のセンスとか、気にしちゃだめよ？

# バージョン

PHP 7.2.4 です。

# trait
traitはコードを再利用する仕組みの一つです。
個人的なイメージは「特定の処理のまとまりをお手軽に導入する仕組み」となっています。

使い方は簡単で

```Operation.php
<?php
namespace Niisan;

trait Operation
{
    public function go() :string
    {
        return 'go';
    }
}
```
 というtraitを作ると

```User.php
<?php
namespace Niisan;

class User
{
    use Operation;
}
```
みたいなクラスを作ったときに

```test.php
<?php
require(__DIR__ . '/../vendor/autoload.php');

$user = new Niisan\User;
echo isOk($user->go() === 'go');

function isOk($state)
{
    if ($state) return "0K\n";
    return "NG\n";
}
```
を動かすと

```
$ php test.php
OK
```
のように実行できます。
つまり、`Operation` trait にあったコードがそのまま`User`クラスで使用できるということです。

# trait のアクセス権検証
## 外部からの使用
次に、traitにアクセス権を設定してみましょう。

```Operation.php
<?php
namespace Niisan;

trait Operation
{
    public function go() :string
    {
        return 'go';
    }

    protected function wait() : string
    {
        return 'wait';
    }

    private function stop() :string
    {
        return 'stop';
    }
}
```
こいつを普通に使ってみます。

```test.php
echo isOk($user->wait() === 'wait');
```
でも、これはアクセス権により弾かれます。

```
Uncaught Error: Call to protected method Niisan\User::wait()
```
当たり前ですね。
当然、private メソッドでも同じです。

```test.php
echo isOk($user->stop() === 'stop');
```

```
Uncaught Error: Call to private method Niisan\User::stop()
```
アクセス権は効いているようです。

## 内部からの使用
念の為内部から使うことを考えてみます。
まず、以下のようなメソッドを定義して、内部から使用する仕組みを作ります。

```User.php
<?php
namespace Niisan;

class User
{
    use Operation;

    public function operate(int $num)
    {
        if ($num == 1) return $this->go();
        if ($num == 2) return $this->wait();
        return $this->stop();
    }
}
```
テストはこんな感じで作ります。

```test.php
echo isOk($user->operate(1) == 'go');
echo isOk($user->operate(2) == 'wait');
echo isOk($user->operate(3) == 'stop');
```
すると、こんな感じになります。

```sh
# php test.php
0K
0K
0K
```
いや、待って、privateで落ちてくれないの？

とりあえず、trait で private にしたメソッドは、そのtraitを使用しているクラス内では、普通に参照できるっぽいです。

## 継承先での使用
継承先で使用することを考えてみます。

```Boss.php
<?php
namespace Niisan;

class Boss extends User
{
    public function operate(int $num)
    {
        if ($num == 1) return $this->go();
        if ($num == 2) return $this->wait();
        return $this->stop();
    }
}
```
テストはこんな感じ

```
$boss = new Niisan\Boss;
echo isOk($boss->operate(1) == 'go');
echo isOk($boss->operate(2) == 'wait');
echo isOk($boss->operate(3) == 'stop');
```

```sh
# php test.php
0K
0K

Fatal error: Uncaught Error: Call to private method Niisan\User::stop() from context 'Niisan\Boss' in /var/www/src/Boss.php:10
```
エラー出ました。

# 結論
trait は単純に継承の代わりをしているわけではなく、
「trait の中にある内容を、クラス定義に書き込んでいるのと同等」
であるということらしいです。
なので、trait のなかで private 定義しても、使用しているクラス上では普通に使用できます。

# まとめ
というわけで、trait のアクセス権の挙動について、少し調べました。

いや、コードレビューのときに、trait の中のprivate メソッド使っているのテスト通っていたので、なんでやろうなぁ？って思っただけなんです。
Resource interpreted as Stylesheet but transferred with MIME type text/plain のエラーの対処法

# エラー状況
[Herokuにこんなサービス](https://intense-escarpment-47506.herokuapp.com/)をアップしています。（メルカリだけ使えないので対応中です）
AWSに、unicorn + nginx + capistranoを使用し、[こちらの記事を参考に](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)作業を進め、ブラウザからアクセスすることに成功しました。
しかし、CSSが反映されていませんでした・・・JSや画像は読み込めておりasset周りに問題はなさそう。実際に検証画面からNetworkタブを見てみても、間違いなくCSSやJSや画像が読み込まれている・・・なのにCSSだけ反映されていない、そんな状況でした。

# ConsoleにWarningが出ていた
検証画面のConsoleには、記事タイトルのワーニング：Resource interpreted as Stylesheet but transferred with MIME type text/plain　が出ていました。
ローカルでサービスを起動してみても出てきましたが、Herokuにアクセスした場合はワーニングが出てこなかったので、ここが悪さをしているのではないか・・・

# nginxのmime.typesが読み込めていなかった
Webサービス用のnginx設定ファイルがあるのですが、その中に以下のmime.types読み込みの設定をすることで解消できました。設定場所は、httpブロックの中です。


```webservice.conf
http {

    include  mime.types;

}
```
nginx用のconfファイルには上記が最初から記入してあり、下記のように、webサービス用のconfをIncludeする設定が含まれていました。

```nginx.conf
http {

    include  mime.types;

    include /etc/nginx/conf.d/*.conf;

}
```
そのため、nginx.confを読み込んでからwebservice.confを読み込む・・・問題ないな！と勘違いしていました。実際は調べたところ、webservice.confのみが読み込まれており、mime.typesのincludeは反映されていなかったので、追記してみたところ解消した次第です。
一緒に解決法を探してくださったAmazon Loftの技術者の方ありがとうございました。

このエラーの解消法は探しても見当たらなかったので記事にしてみました。
誰かのお役に立てれば幸いです。
goroutineとスレッドの違いって？

この記事は、[Go3 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/go3) の11日目の記事です。

##はじめに
Goにはgoroutineという並行処理を簡単に実行できる機能があります。
goroutineは「goroutineとは軽量スレッドである」と説明されていますが、結局goroutineとスレッドって何が違うのかということを調べてみました。

まず最初に言うとgoroutineの実体はスレッドです。
ですが大きく3つの違いがあります。順番に見ていきましょう。

##メモリ消費量

スレッドのデフォルトスタックサイズは Windows だと 1 MB、Linux だと 2 MB で
goroutineは数キロバイトで済みます。
必要に応じてヒープ領域を割り当てたり開放したりします。一方でスレッドはスレッド間のメモリが干渉し合わないように「スタックガードページ」と呼ばれる 1Mbの領域の確保から始めます。
数キロバイトで済む goroutine に比べると、10 KB だとしても100〜200倍の違いがあります。

##生成と破棄に要する時間

スレッドは生成と破棄のたびに OS に要求を投げて、それが完了して返ってくるのを待つため時間がかかります。
一方で goroutine では、生成と破棄に関する操作を非常に低コストで行うことができます。

##スイッチングに要する時間

スレッドがブロックされると、別のスレッドがスケジューリングされます。 プリエンプティブ方式でスレッドがスケジューリングされ、スレッドの実行がスイッチされる際にスケジューラーは全てのレジスタ、つまり 16種類の汎用レジスタ、PC(プログラムカウンタ)、SP(スタックポインタ)、16種類の XMM レジスタ、 FP co-processor の状態、16種類の AVX レジスタ、そしてモデル固有のレジスタを別の場所に保存したり、保存したそれらをレジスタに戻す処理が必要になります。これはスレッド間で迅速にスイッチングしたい場合に、無視できません。
goroutine は協調してスケジューリングされ、スイッチングが発生したときも、たった 3つのレジスタ(PC、SP、DX)しか保存したり、レジスタに戻したりしません


##まとめ
Goは並行処理をするにあたってgoroutineを使うことによってメモリ消費量を抑えてました。
メモリ使用量が多くなり過ぎると、スワップが発生し性能低下を招くため、小さなメモリ使用量で済むというのは大きな利点だと思います。
ここで述べた以外にもgoroutineはスレッドよりも起動時間が早かったり、メモリ消費量がすくないためスレッドに比べてもより多く
の並行処理を実行することができるとも言われています。（他にも利点は色々とある)
並行処理が簡単に実行できて、スレッドよりも数多くの並行処理を実行できるgoroutineという機能があるGoは最高ですね。
（気付いた点等ございましたら、お知らせください)
Team Foundation Server 2017 ビルド

オンプレミスの Team Foundation Server (TFS) 2017 を利用しています。タスク管理とソース管理として使っているのですが、この度、ビルドに挑戦してみました。結果、ビルドが壊れたらすぐ分かるようになったので、良かったと思います。

プロダクトのアーキテクチャは C++/MFC です。プロダクトによって事情は様々かと思いますが、参考になれば幸いです。以下、TFS のバージョンによる差異があるかもしれませんが、ご了承ください。

## 1. エージェント プールの追加
1. TFS で **コレクション設定** > **エージェント プール** を開く。
2. **新しいプール** をクリックする。
3. **名前** を入力する。
4. **OK** をクリックする。

## 2. エージェントのセットアップ
1. ビルド用のマシンにログインする。
2. TFS で **プロジェクト設定** > **エージェント キュー** を開く。
3. **エージェントのダウンロード** ボタンをクリックする。
4. ダウンロードした ZIP ファイルを _C:\agent_ 等に展開する。
5. Windows PowerShell または cmd.exe を実行する。
6. `.\config.cmd` を実行する。

(追記) ※エージェントをサービスに登録する場合は、管理者として実行する必要があります。

```
サーバー URL を入力する > http://<サーバー名>:8080/tfs/
認証の種類 を入力する (Integrated の場合は、Enter キーを押します) > <Enter>
エージェント プール を入力する (default の場合は、Enter キーを押します) > <プール名>
エージェント名 を入力する (<クライアント名> の場合は、Enter キーを押します) > <Enter>
作業フォルダー を入力する (_work の場合は、Enter キーを押します) > D:\_work
エージェントをサービスとして実行しますか? (はい/いいえ) を入力する (N の場合は、Enter キーを押します) > <Enter>
```
これで、 エージェントの一覧に <クライアント名> が現れます。

### (追記) エージェントをサービスとして実行する場合

続けて、サービスを実行するユーザー アカウントの入力を求められます。

```
エージェントをサービスとして実行しますか? (はい/いいえ) を入力する (N の場合は、Enter キーを押します) > y
サービスに使用するユーザー アカウント を入力する (NT AUTHORITY\NETWORK SERVICE の場合は、Enter キーを押します) > <Enter>
```

アカウントは services.msc (管理ツール > サービス) で後から変更できます。サービスは _VSTS Agent (<サーバー名>.<クライアント名>)_ という表示名で登録されるようです。

## 3. エージェントの実行
1. Windows PowerShell を **管理者として実行する**。
2. `.\run.cmd` を実行する。

これで、 エージェントの一覧で **状態** が _オンライン_ になります。

どうしてわざわざ管理者として実行しているのかというと、ビルド生成物の中に COM があり、**ビルド後のイベント** で登録しているからです。管理者権限で実行した PowerShell から run.cmd を実行すれば、 COM の登録ができます。

### (追記) エージェントをサービスとして実行する場合

サービスを管理者権限で実行するには、ログオンに _ローカル システム アカウント_ を指定すればよいでしょう。

## 4. ビルド定義の追加
1. TFS プロジェクトで **ビルドとリリース** > **ビルド** を開く。
2. **新規** ボタンをクリックする。
3. **テンプレートの選択** で _.NET デスクトップ_ を選択して **適用** ボタンをクリックする。
4. 適宜設定を編集する。（後述）
5. **保存** ボタンをクリックする。

これで、一覧に新しいビルド定義が現れます。

## 5. ビルド定義の設定のポイント

### タスク タブ
- **ソリューション** : .sln を指定することも .vcxproj を指定することもできますし、ワイルドカードを使うこともできます。.sln 間に依存関係がある場合は、粒度と順序を工夫してタスクを追加します。
- **Visual Studio のバージョン** : 私のところでは _Visual Studio 2015_ を指定しています。
- **プラットフォーム** : `$(BuildPlatform)` となっていて、 **変数** タブ内でこの値を `win32` と設定してあります。ここが空白の場合、規定の（おそらく .sln で最初に出現する）プラットフォームがビルドされます。
- **構成** : `$(BuildConfiguration)` となっていて、 **変数** タブ内でこの値を `release` と設定してあります。ここが空白ですと、 `debug` を指定したことになってしまいます。

タスクの右クリックから _有効_ / _無効_ を簡単に切り替えられるのが、設定の調整のときには便利です。不要なタスクは、削除してもよいですが、 _無効_ にしておくのでもよいでしょう。

### トリガー タブ
- **継続的インテグレーション** : ここを _有効_ にすると、ソースがチェックインされる度にビルドします。ビルド時間が長くチェックインが多い場合は、これは難しいですね。
- **スケジュール済み** : ここを _有効_ にするといわゆるデイリー ビルドを仕掛けることができます。私のところでは、今はこちらを有効にしています。

### オプション タブ
- **エージェント** > **規定のエージェント キュー** : 追加した <プール名> を設定します。
- **エージェント** > **ビルド ジョブのタイムアウト(分)** : これを超えるとビルドがキャンセルされます。ログには「エージェント <エージェント名> で実行されているジョブが、最大実行時間 `hh:mm:ss` を超えました。」と書かれます。初期値は _60_ 分ですが、必要に応じて伸ばしてください。
- **複数構成** : ここを _有効_ にすると、 Debug 構成と Release 構成を両方ビルドするような設定が作れます。「ビルド」階層と「プロセス - タスク」階層の間に「構成」階層ができる感じです。

設定は試行錯誤しながら調整していけば良いと思います。

---
Viveを使って配信するときにOBSにSteamVRのカメラや両目のレンダリングが映ってしまう現象

すべてのカメラのTarget Eyeを　Noneにしてみてください
![sadfasdfa.PNG](https://qiita-image-store.s3.amazonaws.com/0/262130/311d1818-c6ca-d562-9b2e-6d6889332aea.png)
テスト自動化で考慮すること

自動化を行うときに、スクリプティングで考慮すべきことをまとめる。
なお、WEBサービスでE2Eテストを前提としている。


# 自動化を行う場所の判定

- テスト自動化は、品質を上げるためであり、カバレッジを上げるものではない。
- 自動化はテスト準備のための効率化にも使える。
- すべてをスクリプティングしようとすれば、ROIが成り立たなくなる。
- 自動化に向くところを見極める （参考　アジャイルテスト４象限　Q2がメイン）


<IMG SRC="https://qiita-image-store.s3.amazonaws.com/0/267085/7a68a91d-d783-2bd1-0b3b-34de94ad6f64.png" >





# 変更に強いAutomation Scripting

## 課題
- システムに小さい変更が発生すると、自動化が動かなくなる
- システム変更のテスト自動化の影響が大きく、その修正・テスト工数が大きくなる

## 対応
### テストウェアアーキテクチャの検討
テスト自動化には、スクリプト、テストデータ、結果期待値、実行結果等さまざまな生成物から構成されている。
テストの効率を上げるために、これらを簡単に、速やかにアクセスできるようにすることが求められる。

- 生成物の保存場所、名前ルールを考慮する（ライフサイクル、探しやすさ　等）
- 繰り返し実行を想定し、１回の実施の生成物のセットの管理方法

### 抽象レベルの検討
テスト自動化を実装するときに、保守性を上げるために、いくつかのソフトウェア抽象レイヤーを考慮する必要がある

- DATA DRIVEN : データとスクリプトを分離する
- KEYWORD DRIVEN : キーワード（一連のアクション、例えばログイン処理）に詳細を隠蔽（オブジェクト指向に近しい）し、そのキーワードを扱いシナリオを組む
- MODEL BASED : テストシナリオをモデルとし、その単位で処理を隠蔽する
- TOOL INDEPENDENCE : テスト自動化が、システムの実装に依存しない（マルチ環境、内部実装変更等でも動く）実装

### 保守性の検討
システムが小さな変更があったとしても、自動化のシステムの更新がないようにする。

- 再利用性の高いモジュール化
- シンプル
- テストケースに依存しない
- コーディング、開発プロセス標準化
- 不要になったスクリプトは削除

### テスト結果の効率化
テスト結果の期待値と実際値の比較を、テスト実行中、もしくはテスト実行後に実施する。
その時に、ラバストな比較、センシティブな比較のバランスを考慮する。

- センシティブなテストは、多くの情報をチェックし（画面の全要素、関連データ全てなど）するため、時間がかかる。
- ラバストなテストは、最低限の情報をチェックするため、多少変更が入っても成功するし、実行時間が少ない。




# 運用を考慮したAutomation Scripting

## 課題
CIなどで繰り返し実行する時に、毎回同じ動きをする必要がある。
環境、スクリプト、データ等を適切に運用しないと、肥大化しテスト自動化の仕組みが不明なものになる

## 対応

### ドキュメント

- スクリプトの仕様（どういった機能をテストするものか）
- データソースの仕様（テストデータのIFなど）
- テンプレートで標準化（何をするのか、どうやって呼び出すか、どんな結果が出るか　等）

### 依存性

- いつ実施しても動く（特定時間しか動かないものは除く）
- どこで（各種ブラウザ等、実行環境）実施しても動く
- 何回実施しても動く
- 並行実施しても動く


### FALSE FAIL ,FLAKT TEST (たまに失敗する) への対応

- 実行開始時に、初期化を行う。（不適切な環境状態から開始して失敗することを防ぐ）
- 実行終了時に、クリーニングを行う。（不要データ削除など、次回他のテストが動かしても問題ないようにする）
- テストが失敗した時、壊れた環境、途中のトランザクション等をクリアにする
- テスト環境のリソースが複数のテスト実行で衝突しないようにする。（互いに干渉するテストの場合）
- 十分なスペックのテスト環境
- 待つ処理がある場合、ランダムなwait時間を使う
- タイムアウトなどで失敗するときは、リトライなどを入れる

### 実行速度の考慮

- 複数の実行環境を用意してパラレルに実行
- １タスクの処理を最低限にする（途中で失敗し再実行するとき、最低限の被害にとどめる）
- １タスク、限られた機能のテストに絞る（一機能特化してテストできるようにする）
- 想定外の事象でテストが中断しても（タイムアウト等）自動で再開する仕組み
- テスト実行時間の可視化（ボトルネックの調査をしやすくする）

### 実行結果分析の考慮

- 失敗したときに容易に原因分析できるログ、スクリーンショット等を残す
- 簡単にテスト結果、原因がわかるレポートを出力する
- 失敗原因（期待値と異なる、環境問題　等）を細分化する（重要でない失敗はスキップさせるため）
- テストメトリックスを自動でとれるようにする
- 同じスクリプトを実施した場合、基本的に処理時間は同じ（大きく異なる場合、何かが問題がある）

### データ

- 不必要なデータは削除する（不明なテストデータを残さない）
- データファイル名の適切化
- 共通なデータは、デフォルトデータとして切り出す
- データのフォーマット、データの定義などのドキュメントを残す
- シンプルなフォーマット、データ仕様
- スクリプトはデータ依存性を低くする
- 本番のデータに近い状態（コンテンツ、データサイズ　等）が望ましいが、個人情報は匿名化する




# 参考文献
- ISTQB Advanced-Test-Automation-Engineer-Syllabus <A HREF="https://www.istqb.org/downloads/category/48-advanced-level-test-automation-engineer-documents.html"> LINK </A> 
- A Journey through Test Automation Patterns <A HREF="https://www.amazon.com/Journey-through-Test-Automation-Patterns/dp/1727504887"> Amazon site</A>
- More Agile Testing: Learning Journeys for the Whole Team <A HREF="http://www.informit.com/articles/article.aspx?p=2253544&ranMID=24808">Agile Testing Quadrants</A>


# 最後に

自分はこういう観点でコーディングしてるよ～といったアイデアがあれば、ぜひコメントください！
vwとremを組み合わせて、4Kディスプレイを考慮した文字サイズを設計する


#はじめに
[Advent Calendar 前日](https://qiita.com/shouchida/items/c23072d2b8e2b8be2e92)の投稿を見て驚きました。

「内容がかぶった！！！」

偶然なのでしょうがない。
ちゃんと住み分けできるよう、続きのような内容に軌道修正しました。
この記事では、`<html>`の`font-size`はデフォルトの16pxのまま、4Kディスプレイまで考慮した`font-size`を設計する方法を紹介します。

#デザインについて
ウェブサイトをデザインする時、文字サイズはある画面幅での固定値が指定されます。
その固定値のまま4Kディスプレイで見ると、文字が小さくなり過ぎ、デザインの印象が変わってしまいます。
それを解決するため、ブラウザ幅に対してのサイズを指定する単位`vw`を使うのですが、注意しないと文字サイズが小さくなり過ぎたり、大きくなり過ぎてしまいます。

#設計について
今回はブラウザ幅を限定して、要素の`font-size`に`vw`を指定します。
それ以外のブラウザ幅の時は`rem`を指定します。

- 1440pxの横幅でデザインされていることとする。
- 基本の文字サイズは16pxとする。
- ブレイクポイントと文字サイズのルールは、以下に設定する。

|ブレイクポイント|サイズルール|サイズ例|
|:-----------------|:------------------:|:------------------:|
|768px|||
||固定（rem）|16px|
|1440px（デザインサイズ）|||
||変動（vw）|16px ~ 40px|
|3600px（デザインサイズの2.5倍）|||
||固定（rem）|40px|



#CSS (Scss)

```scss
html {
  font-size: 16px;
}
.text {
  @include responsive-font-size(16); //本文
}
.title {
  @include responsive-font-size(24); //見出し
}
```

```scss
@mixin responsive-font-size($size:16)  {
  @include min-screen(768) {
    font-size: get_rem($size);
  }
  @include min-screen(1440) {
    font-size: get-vw($size, 1440);
  }
  @include min-screen(3600) {
    font-size: get-rem($size * (3600 / 1440) );
  }
}
```

```scss
// 切り替え
@mixin min-screen($size) {
  @media screen and (min-width: $size) {
    @content;
  }
}

// 文字サイズ計算
$base-font-size: 16;
@function get-vw($size:16, $viewport:320) {
  @return (100 / $viewport) * $size * 1vw;
}
@function get-rem($size:16) {
  @return ($size / $base-font-size) * 1rem;
}
```

#まとめ
この方法ではベースとなる`font-size`は16pxのまま、ブラウザ幅に合わせて各要素の`font-size`を`vw`と`rem`で流動的に切り替えています。
もし、ベースとなる`font-size`を`vw`で変化させ、各要素の`font-size`を`rem`で設定する方法が知りたければ、[こちら](https://qiita.com/shouchida/items/c23072d2b8e2b8be2e92)の記事をご覧ください。

4K、5Kといったディスプレイを使う人が増えてきています。
その人達のために、最優先ではないけれど最低限の設定をしておくと良いと思います。
文字サイズをベースにして`margin`を`em`で設定することで、余白のコントロールもしやすくなります。
あとはデザインの文脈に合わせて、部分的な対応をしましょう。以上です。
Django で MariaDB を使う

Dejango のディフォールトのデータベースは sqlite3 ですがそれを　MariaDB に切り替える方法です。

MariaDB が動作していることを確認

```bash
sudo systemctl status mariadb
```

python の　mysqlclient をインストール
>Arch Linux では

>```bash
sudo pacman -S python-mysqlclient
```

>Ubuntu では

>```bash
sudo pip3 install  mysqlclient
```

>次のライブラリーが必要です。

>```bash
sudo apt install libmariadb-dev-compat libmariadb-dev
```

MariaDB に
user: django
password: tiger123
データベース: django
を作成

```text
MariaDB [(none)]> create user 'django'@'localhost' identified by 'tiger123';
Query OK, 0 rows affected (0.046 sec)

MariaDB [(none)]> create schema django;
Query OK, 1 row affected (0.001 sec)

MariaDB [(none)]> grant all on django.* to 'django'@'localhost';
Query OK, 0 rows affected (0.013 sec)
```


確認方法

```bash
mysql -udjango -ptiger123 django
```

proj01 というプロジェクトがあるとして、
proj01/settings.py を編集

```py:proj01/settings.py
（省略）
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'USER': 'django',
        'PASSWORD': 'tiger123',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
                'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
                },
    }
}
（省略）
```

設定の変更を反映する

```bash
python manage.py migrate
```

データベースを使ってみる

```text
$ python manage.py dbshell
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 43
Server version: 10.5.12-MariaDB-1build1 Ubuntu 21.10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [django]>
```

>スーパーユーザーの作成

```bash
python manage.py createsuperuser
```

>パスワードなどを入力
>メールアドレスは、test@test.com で可。

開発サーバーを起動

```bash
python manage.py runserver
```

ブラウザーで http://127.0.0.1:8000/admin/ にアクセス
![admin.png](https://qiita-image-store.s3.amazonaws.com/0/179446/4349d758-3b1b-f3cc-0ad1-62a142722bee.png)

ログインしてユーザーなどを作成
![user.png](https://qiita-image-store.s3.amazonaws.com/0/179446/b7db3a7d-71fd-78a6-f692-72e37b67871f.png)

MariaDB には次のテーブルが作成されています。

```text
MariaDB [django]> show tables;
+----------------------------+
| Tables_in_django           |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.8.5
$ python -m django --version
3.1.1
```
PHP Carbonを使って日付差分から期間をxx日xx時間xx分の自然な日本語フォーマットに変換する



100分だったら1時間20分
100時間だったら4日4時間
みたいな変換をします。
私のググり方が良くないのか、全然見つからなかったので備忘録。
秒には対応しておりません。

```
/**
 * ex. 2018/12/05 00:00:00, 2018/12/10 00:00:00 => 5日間
 * ex. 2018/12/07 00:00:00, 2018/12/10 10:50:00 => 3日10時間50分
 * ex. 2018/12/10 00:00:00, 2018/12/10 20:08:00 => 20時間8分
 * ex. 2018/12/10 00:00:00, 2018/12/10 00:50:00 => 50分間
 */
```

```php
    /**
     * 日付差分を算出し、xx日間xx時間xx分のフォーマットに変換する
     * @param string $start_datetime yyyy-mm-dd H:i:s Carbon::parse()で処理可能な形式ならなんでも
     * @param string $end_datetime
     * @return string|null データ不整合の場合はnullを返す
     */
    public function diffFormatCarbonDatetime($start_datetime,$end_datetime){
        if (empty($start_datetime) || empty($end_datetime)) {
            return null;
        }
        $start_carbon = Carbon::parse($start_datetime);
        $end_carbon   = Carbon::parse($end_datetime);
        if ($start_carbon->gt($end_carbon)) {
            return null;
        }
        // 差分計算
        $diff_days    = $start_carbon->diffInDays($end_carbon);
        $diff_hours   = $start_carbon->diffInHours($end_carbon);
        $diff_minutes = $start_carbon->diffInMinutes($end_carbon);
        // 日付差分を自然な日本語にする(0の日時分は非表示とする)
        $result_string = '';
        $string_kan_flg = false; // 最後に"間"をつけるか否か
        if ($diff_days > 0) {
            $result_string .= $diff_days.'日';
        }
        if ($diff_hours > 0) {
            $diff_hours = ($diff_hours < 24)? $diff_hours : $diff_hours%24; // 100hなら4日間分の96hを切り落とし4hとする
            if ($diff_hours > 0) {
                $string_kan_flg = true;
                $result_string .= $diff_hours.'時間';
            }
        }
        $diff_minutes = ($diff_minutes < 60)? $diff_minutes : $diff_minutes%60; // 100分なら1時間分の60を切り落とし40分とする
        if ($diff_minutes > 0 || ($diff_days === 0 && $diff_hours === 0)) { // 0分のときは、0日0時間の場合のみ0分を表示する
            $result_string .= $diff_minutes.'分';
        }
        // どこにも"間"が無いなら最後につける
        $result_string = ($string_kan_flg)? $result_string : $result_string.'間';
        return $result_string;
    }
```
create-nuxt-appでスタートしたプロジェクトの設定をあとから変更する

以下の例は、「やっぱりEslint/Prettierを使いたい」ケースです。

## 必要なパッケージを追加する

```shell
yarn add eslint eslint-loader babel-eslint eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier prettier
```

- eslint
- eslint-loader
- babel-eslint
- eslint-plugin-vue
- eslint-config-prettier
- eslint-plugin-prettier
- prettier


## 設定ファイルを用意する

```javascript:.eslintrc.js
// example
module.exports = {
    root: true,
    env: {
        browser: true,
        node: true
    },
    parserOptions: {
        parser: 'babel-eslint'
    },
    extends: [
        'plugin:vue/recommended',
        'plugin:prettier/recommended'
    ],
    plugins: [
        'vue',
        'prettier'
    ],
    rules: {
        'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
        'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
    }
}
```

```json:.prettierrc
{
    "semi": false,
    "singleQuote": true
}

```

nuxt.config.jsに当該箇所を追加

```javascript:nuxt.config.js
module.exports = {
    // ...
    build: {
        /*
        ** You can extend webpack config here
        */
        extend(config, ctx) {
            // Run ESLint on save
            if (ctx.isDev && ctx.isClient) {
                config.module.rules.push({
                    enforce: 'pre',
                    test: /\.(js|vue)$/,
                    loader: 'eslint-loader',
                    exclude: /(node_modules)/
                })
            }
        },
        // ...
    },
    // ...
}
```

## 実行

```shell
./node_modules/.bin/eslint --ext .js,.vue --ignore-path .gitignore .
```

nuxt-appでeslint/prettierをオンにしてプロジェクトを作成した場合は、
下記のような`lint`と`precommit`がscriptに設定される

```json:package.json
{
    "scripts": {
        "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
        "precommit": "yarn lint"
    }
}

```
IFTTTのアプリを使って外から家電コントロールしてみた

# 背景

今年の暑い夏に、、、奥さんから一言でスタートしました。

以下、実際にあったやりとり。
妻: 家から帰ると暑い。どうにかできないの？
僕: へ。。確かに暑いね。。
妻: ...。
僕: 作ってみせます。

ということでエンジニア魂に火が付いた僕がやってみた物語。
(仕事ではモバイルエンジニアをしています。kotlin大好き。swiftも好き。)

# 準備するもの

- [Raspberry Pi3 Model B](http://amzn.asia/ewyQz0C) (Amazonで売っているスターターキットがオススメです。OS入ってるし。。)
    - MacでもWindowsでもOK
- [RM mini 3](http://amzn.asia/4n5p1pC) (日本国内で技適を取ってないので日本国内で使用する場合は気をつけましょう。)
    - eRemoteを使えばいいと思うけど、、、少し高い。。
- [IFTTT](https://ifttt.com/)
    - アカウント作っとこう
- [dataplicity](https://www.dataplicity.com/devices/)
    - Paspberry PiをWebブラウザからアクセスできる優れもの。
- Node-RED
    - 言わずもがな。

# フロー

想定しているフローは
IFTTTのButton Widget -> httpでAPI叩く -> Raspberry Pi -> RM mini3 -> 家電(僕の場合はエアコン)
![フロー.png](https://qiita-image-store.s3.amazonaws.com/0/62340/84c66145-1c67-19b0-f36a-5a918290a3af.png)

# 手順

1. Raspberry piを初期セットアップする。
    - スターターキットはすでにOSインストールされているので端折ります。
    - Wifiのセットアップまで。
2. python-broadlinkをラズパイにインストールする。
    - 仰せの通りに。(http://intellectualcuriosity.hatenablog.com/entry/2017/05/12/201643)
    - git clone https://github.com/mjg59/python-broadlink.git
    - ライブラリのインストールを行う ( sudo pip install broadlink )
3. 赤外線をラズパイに覚えさせる。
    - broadlink_discoveryを実行する。
        - ./broadlink_discovery
    - vi hogehoge.device
    - ./broadlink_cli --device @hogehoge.device --learnfile aircorn.on
        - エアコンのonボタンをRM mini3に向けて送信
    - ./broadlink_cli --device @hogehoge.device --learnfile aircorn.off
        - エアコンのoffボタンをRM mini3に向けて送信
    - ./broadlink_cli --device @hogehoge.device --send aircorn.on
        - エアコンがつく！！おー
4. dataplicityをセットアップ
    - これすごいですよねー。ブラウザからラズパイをリモートアクセスできるサービスなんですよ。
        - 1台だけなら無料！！スバラシー
    - 登録すると以下のような感じで表示されます。(今電源入れてないので左端が赤くなっています。。)
    - <img width="200" alt="スクリーンショット 2018-12-10 9.28.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/62340/5e516fd9-cbfe-b5c5-d2d0-fb78d5dc1040.png">
    - ここでnode-redで遊ぶ。
5. node-redで遊ぶ。
    - 外から叩けるようAPIを定義する。
    - https://〇〇.dataplicity.io/command/aircorn_onを叩いてエアコンがONになったら成功！
6. iftttにログインする。
    1. My Applets　→ New Applet
    2. thisにButton widgetを選択し、thatにwebhookを選択する。
    3. 名前を入力し、定義したURL( https://〇〇.dataplicity.io/command/aircorn_on )を入力する。
7. iPhone(もしくはAndroid端末)にiftttをダウンロードし、同一アカウントでログインを行う。
8. iPhoneのウィジェットをイジイジ。。編集ボタンをタップ。(歩数が出るの恥ずかしいですね。)

<img width="200" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/62340/bdc8fb52-cfc3-39e2-4dcb-ca5cc41bac60.png">
9. 一番上にIFTTTアプリにして完成！！

<img width="200" alt="Screen Shot 2018-12-10 at 18.07.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/62340/fdb694c4-7cba-3545-c02e-5ca092ee6b41.png">
10. そうするとButton Widgetが表示されます！！押したらエアコンがつきました！！感動

<img width="200" alt="Screen Shot 2018-12-10 at 18.07.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/62340/283134be-b0db-00eb-f51e-84eb9c331317.png">

# 実際に使ってみた感想

- 感動する
- ラズパイのセキュリティを強化せねば、、と思い始める。
- これなら色々動かせるぞ、、と奮起した瞬間に引越しが決まってまだ引越し先に導入できず。
- 奥さんからお褒めの言葉を言われる。
- 子供も喜ぶ。(と思う)

# おまけ

- よくありますが、Google Homeからの連携も同じようにできました。(変更したのはiftttですが)
- ただ、あまり使われずに悲しい思いをしてます。
- eRemoteの方が使いやすそうだな、、、と思っております。

# これからの展望

- とりあえず、スマートホームにするべく赤外線で指示与えるものはコンプリートしたいと思います。
【AWS】EC2のSMTP許可申請

#はじめに
EC2インスタンスでのメール送信には制限があるとのことで（全然知りませんでした）、解除申請の手順を記します。
正常に機能していたアプリのメール送信ができなくなってアワアワしていたらマネージャが優しく教えてくれましたw
抽象的なサービスを利用する際は自分の設定に自信を持たなきゃですね。

#作業開始
##ググる
”EC2 メール　制限　申請”でググると[とてもよきサイト](https://cloudpack.media/11249)が見つかりました。
少し情報が古いかな？と思いましたが全然余裕でわかりやすかったです。感謝です！

##申請
サイト文中のURLからAWSの申請ページに遷移。
別タブでAWSコンソールにログインしてるとアカウントのメアドが自動で入力されています。
ちなみにここで言うrootアカウントとはIAMユーザで出していない親アカウント（Organizationを使って組んだ子AWSルートアカウント、とか）を指すようです。

あとは[申請方法のスライド](https://www.slideshare.net/AmazonWebServicesJapan/aws-42885668)に倣えばOK。
私はEメール上限緩和申請のみ行いましたので投稿をためらうくらいシンプルでした。。Submitでリクエスト受けつけたよ、の旨のページに遷移。
あとはAWSから返事が来るまで待ち状態、と思いきや申請から数十分後に完了のメール受信しました。
問い合わせを受け付けたからちょっと待ってね！程度の内容かと勘違いしていました。。

#参考にしたサイト
文中のrDNSってなんなんだと思いググりました、CCNAの黒本を執筆されているGeneさんの[ネットワークのおべんきょしませんか？](http://www.n-study.com/network/2001/08/dns_3.html)に3章だてでわかりやすく解説されています。ことばの意味そのままでIPからドメインを引くとのことです。語彙。。

簡単ですが以上です。
RxSwiftにコントリビュートするまでの軌跡

# はじめに
この記事は、[CyberAgent 19新卒 エンジニア Advent Calendar 2018](https://adventar.org/calendars/3342)の13日目のものになります。
また、[岩手県立大学 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ipu)の13日目のものでもあります。ｗ

# コントリビュートしようと思った経緯
もともと僕は機会があればOSSにコントリビュートしたいなと考えていましたが、なかなか何をしたら良いのかわからず動き出せずにいました。
僕は自分のアプリでも業務でもRxSwiftを使う機会が多く、たまたま自分がよく使うDriverで、使いたい関数が実装されておらず、やってみようと思いました。
今回は僕がRxSwiftのDriverにtakeを実装するまでの手順を書いてみたいと思います。

# 最初にまとめを..
大きめのOSSプロジェクトには、大抵の場合Contributor向けのガイドが用意されているので、それを読んだ上で従い、コミットしましょう。

# 手順

## 1. Contributor向けのガイドを探す
大抵のプロジェクトには入っているであろう、[README](https://github.com/ReactiveX/RxSwift/blob/master/README.md)をまずは読みます。
その中に `Contribute` という部分がないかを探します。
RxSwiftのREADMEはとてもしっかり書かれていて、

Help out Check out [contribution guide](https://github.com/ReactiveX/RxSwift/blob/master/CONTRIBUTING.md)

という部分があるので、クリックして[CONTRIBUTING.md](https://github.com/ReactiveX/RxSwift/blob/master/CONTRIBUTING.md)に飛びます。


## 2. CONTRIBUTING.mdを読む
RxSwiftにコミットする内容は４つに分類されています。

1. Issue fixes
2. Performance improvements
3. Documentation improvements
4. New operators (read carefully!)

今回の場合は新しい関数の追加だったので、4. のNew operators (read carefully!)に当たります。

> read carefully! 

👀

### General Rule
ここにはすべてのContributor向けのメッセージが載っています。
要約すると、

1. PRのtargetはdevelopにする
2. PRを出す前に./scripts/all-tests.shを実行し、passすることを確認する
3. CHANGELOG.mdを更新する

という感じです。

### New operators
今回は新しい関数の追加なので、ここを読みます。
> If you're thinking about adding new operators to RxSwift, please make sure you discuss them via an [issue](https://github.com/ReactiveX/RxSwift/issues) first.

内容を要約すると、
1. 必要としている機能は[RxSwift Community](https://github.com/RxSwiftCommunity/)にあるかも知れないから先に見てね
2.  ReactiveXにあるオペレータは[RxSwiftExt](https://github.com/RxSwiftCommunity/RxSwiftExt)にあるかも知れないから先に見てね
3.  いずれにしてもまずはIssueで話そう！

> 3.  いずれにしてもまずはIssueで話そう！

とのことだったので、とりあえずIssueを立ててみました。
[Add operator take to SharedSequenceConvertibleType #1761](https://github.com/ReactiveX/RxSwift/issues/1761)

## 3. Issueでの議論
[Add operator take to SharedSequenceConvertibleType · Issue #1761 · ReactiveX/RxSwift · GitHub](https://github.com/ReactiveX/RxSwift/issues/1761)
にて、SharedSequenceConvertibleTypeにはdelay, startWith, skipなどが実装されているのでtakeもあってもよいのではないかという話をしました。

> Can't make a decision on this, but that's where my opinion stands more or less. Would have to defer to[@kzaher](https://github.com/kzaher)for final word.

@kzaherの言葉を待とうとのことだったのですが、なかなか返信が来なかったので、先にPRを出してみました。多分優先度の高い議論ではなかったのでしょう。
Googleの人だし、絶対に忙しい。w

## 4. PullRequestを出そう
まず最初に、RxSwiftのプロジェクトがでかすぎてどのファイルをいじれば良いのかわからず、困りました。ですが、既に追加されているオペレータがあるということを手掛かりにコードジャンプで編集すべき場所を見つけられました。

今回提出したPRはこれになります。
[Add operator take in SharedSequence by kzumu · Pull Request #1786 · ReactiveX/RxSwift · GitHub](https://github.com/ReactiveX/RxSwift/pull/1786)

ですが、まだマージされていないんですよね。ｗ
早く見てくれますように。

# 最後に
こんな流れでPRを出すところまでできました。
余談ですが、最近では[BoostNoteのコミュニティ](https://github.com/BoostIO/boostnote-mobile#community)に参加して、iOS App Renewalのチャンスを伺っています。
年明けから始動するらしいので楽しみです。
こういう活動を行っているおかげか最近少しずつ英語力がついてきたような気がして楽しいです。
海外で仕事とかしてみたいなぁ。

最後までお読み頂きありがとうございました！
intra-mart チーム開発時、開発環境の簡単な配布方法

## 前提
 - intra-mart Accel Platform
 - intra-martが動作する環境セットアップ済（テナントセットアップ完了）  
 セットアップ方法は下記記事が詳しいです。IM-BOX(Apache Cassandra)の導入は回避したほうが無難です  
[intra-mart実践入門の作成記録 #010 執筆用intra-mart環境構築](https://qiita.com/hiroaki-kushida/items/f3202d8d1a794e47ea70)  

## やりたいこと
 - 各開発者の端末に開発サーバー（デバッグサーバー）を構築したい
 - DBは共有したい
 - IM-Workflow、IM-BISなどの定義情報を共有したい

## やりかた概要

 - Storageディレクトリがローカルにある場合、ネットワークドライブに移して共有します  
 Storageディレクトリのパス指定は設定ファイルにあるので、そちらも変更します  
  [intra-mart  ストレージ設定ファイル](https://www.intra-mart.jp/download/product/iap/setup/im_configuration_reference/texts/im_core/storage-config/index.html#%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%83%AB%E3%83%BC%E3%83%88%E3%83%91%E3%82%B9%E8%A8%AD%E5%AE%9A)
 - 構築済のResinディレクトリをまるごとコピーして配布します  
 それだけでDB接続情報は共有されます

## 応用編
別拠点間で開発する場合や外注する場合です。
Resin、DB、Storageさえ共有できればいいのでResin、Storageはそれぞれ圧縮して配布します。
DBはダンプを取って配布します。
適用先の環境に合わせてDB接続情報とStorageのパスを修正すれば開発環境が動作するはずです。
[intra-mart DB接続設定](https://www.intra-mart.jp/download/product/iap/setup/im_configuration_reference/texts/resin/resin-web/index.html#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E8%A8%AD%E5%AE%9A)
Matplotlib+Jupyterで方眼紙風グラフをつくる

# 概要
Illustratorを使っていたとき、雰囲気を出すために（？？）方眼紙に描いたような指数関数グラフが欲しくなりました。適当な曲線で作るのは嫌だし、グラフツールはデータを用意しなければいけません。y = a^xぐらいデータを用意しなくとも一瞬で出してほしいところですが、ともかくMatplotlibの出番です。

**方眼紙スタイル**にするために、x軸y軸を等スケールでプロット、外枠なし、目盛り数字なしで表示させました。この状態を実現するのに意外と多くの設定を必要としたので記録に残します。

## 出力例
<img src="https://qiita-image-store.s3.amazonaws.com/0/266433/57e4dcb0-4777-43a5-39b3-e5b44273346d.png" width="400px">
$ \qquad y = e^x \quad (-10 \leqq x \leqq 2) $

## コード

```python
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-10, 2.1, 0.1)
y = (np.e)**x

plt.plot(x, y)

#x軸とy軸を同じスケールで
plt.axis('scaled')

#目盛りを刻む間隔を調整(1刻みならlist(range(...))で十分ですが、
#対数目盛りにしたいときなどラムダ式をいじってください)
plt.xticks(list(map(lambda x: x, np.arange(-10,3))))
plt.yticks(list(map(lambda y: y, np.arange(0, 8))))

#グリッド表示
plt.grid(linewidth=0.5)

#外枠をすべて非表示
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['bottom'].set_visible(False)
plt.gca().spines['left'].set_visible(False)
plt.gca().spines['right'].set_visible(False)

#目盛りの表示設定
plt.tick_params(
    axis='both',
    which='both',
    left=False,           #外枠目盛りを非表示
    bottom=False, 
    labelleft=False,      #外枠目盛りの数字を非表示
    labelbottom=False
)

#各形式で出力
plt.savefig("expgraph.png", format="png", dpi=400, transparent=True)
plt.savefig("expgraph.svg", format="svg", transparent=True)
plt.savefig("expgraph.eps", format="eps", transparent=True)
plt.savefig("expgraph.pdf", format="pdf", transparent=True)

plt.show()
```
## リポジトリ
https://github.com/Napier-JP/Scrapbook
じゃんけんアプリを作ってみよう！！

#解答の手順
###元となる、ひな型のプログラム

```ruby:
def janken
    puts "[0]:グー\n[1]:チョキ\n[2]:パー"
    player_hand = gets.to_i

    program_hand = rand(3)

    jankens = ["グー", "チョキ", "パー"]

    puts "あなたの手:#{jankens[player_hand]}, わたしの手:#{jankens[program_hand]}"

    if player_hand == program_hand
      puts "あいこで"
      # 返り値を返す
    elsif (勝ちの条件)
      puts "あなたの勝ちです"
      # 返り値を返す
    else
      puts "あなたの負けです"
      # 返り値を返す
    end
  end

  next_game = true

  puts "最初はグー、じゃんけん..."

  # じゃんけんを繰り返す
  while next_game do
    next_game = janken
  end
```

###２．解答コード

```ruby:
def janken
    puts "[0]:グー\n[1]:チョキ\n[2]:パー"
    player_hand = gets.to_i

    program_hand = rand(3)

    jankens = ["グー", "チョキ", "パー"]

    puts "あなたの手:#{jankens[player_hand]}, わたしの手:#{jankens[program_hand]}"

    if player_hand == program_hand
      puts "あいこで"
      # 返り値を返す
      janken = true
    elsif player_hand - program_hand == -1 || player_hand - program_hand == 2
      puts "あなたの勝ちです"
      janken = false
    else
      puts "あなたの負けです"
      janken = false
    end
  end

  next_game = true

  puts "最初はグー、じゃんけん..."

  # じゃんけんを繰り返す
  while next_game do
    next_game = janken
  end
```

###３．じゃんけんアプリで得られた学び
####randメソッド

randを使うと乱数を生成できること。randメソッドに引数として数を渡すと「0」から「渡した数 - 1」の間でランダムに数を返せる

```ruby:
rand(100) # => 0〜99の中から１つ数字をランダムに返す
```
####じゃんけんの手をつくる

```ruby:【自分の手】0〜2までの手をターミナルから入力する
player_hand = gets.to_i
```

```ruby:【相手の手】乱数で0〜2までの数値を生成する
program_hand = rand(3)
```

じゃんけんの手は文字列ではなく数値として扱うこと。その方が簡単だから。

####勝ち、負け、あいこの判定（条件式）を書く
```ruby:【あいこ】
if player_hand == program_hand
#あいこの条件は自分と相手の数値が一緒のとき
 puts "あいこで"
　　return　true
```
```ruby:【自分の手が勝ち】
elsif player_hand - program_hand = -1 || player_hand - program_hand = 2
#ここで書いている勝ちの条件は
#自分　−　相手　=　-１　または自分　-　相手　=　２のとき
 puts "あなたの勝ちです"
　　return　false
```
```ruby:【自分の手が負け】
else
#あいこと勝ちの条件を書いたので、負けの条件は書かない
 puts "あなたの負けです"
　　return　false
```
あいこの場合はもう一度じゃんけんをさせたいので、１番に評価をさせるために<strong>最初に書くこと。</strong>返り値はtrueかfalseで返すこと。
####あいこのときに、もう一度じゃんけんをさせる

```ruby:
next_game = true

  puts "最初はグー、じゃんけん..."

  # じゃんけんを繰り返す
  while next_game do
    next_game = janken
  end
```
if文で返り値がtrueであれば、変数next_gameに代入され、whileメソッドが実行される。メソッドの中身はjankenを呼び出すことでじゃんけんを繰り返すことができる。
####gets
入力待ち状態になります。
入力されるまでプログラムは動きません。
####to_iメソッド
文字列を数値に変換します。
ユーザーが打った数字は文字列の数字です。
それを数値に変換します。