OmniAICreator/Qiita-1.07M huggingface dataset:
UnityのCompute Shaderを使ってライフゲームを作ったけど先を越された話

# UnityのCompute Shaderを使ってライフゲームを作ったけど先を越された話

---
本記事は[ライフゲーム Advent Calendar 2017](https://qiita.com/advent-calendar/2017/life-game)の13日目の記事です。
直近では2日の[shiro0922](http://d.hatena.ne.jp/shiro0922/20171202)さんがIchigoJamでライフゲームを実装していました。

---

こんにちは。[sp4ghet](https://twitter.com/sp4ghet)です。

UnityのComputeShaderというGPGPUが扱える機能を利用したライフゲームを実装した話をしようと思っていました。

しかし！[Unity Advent Calendarの8日目](https://qiita.com/fuqunaga/items/e0c93c0f419bdec4ce0e)にfuqunagaさんが先に同じことを実装しており、見事な解説も合わせて書いていたので今回は実装した報告だけにしておきます。

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">ComputeShaderでConway&#39;s Game of Lifeしてみた <a href="https://t.co/ccNew0onC2">pic.twitter.com/ccNew0onC2</a></p>&mdash; sp4ghet (@sp4ghet) <a href="https://twitter.com/sp4ghet/status/924878488359854085?ref_src=twsrc%5Etfw">October 30, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">たくさんあってもちゃんとfps出るgpuおしゃれ <a href="https://t.co/wlnqavDEEw">pic.twitter.com/wlnqavDEEw</a></p>&mdash; sp4ghet (@sp4ghet) <a href="https://twitter.com/sp4ghet/status/925198576283766785?ref_src=twsrc%5Etfw">October 31, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">マルチチャンネルにしてもあまりおもしろくならなかった <a href="https://t.co/9vl0dpHOb7">pic.twitter.com/9vl0dpHOb7</a></p>&mdash; sp4ghet (@sp4ghet) <a href="https://twitter.com/sp4ghet/status/925878255487512577?ref_src=twsrc%5Etfw">November 2, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">中から見てRGBの直行色空間じゃない何かでやったらかろうじて救いようがありそう <a href="https://t.co/VaNCfoiuWB">pic.twitter.com/VaNCfoiuWB</a></p>&mdash; sp4ghet (@sp4ghet) <a href="https://twitter.com/sp4ghet/status/926544954582745088?ref_src=twsrc%5Etfw">November 3, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
新卒エンジニアとして半年ちょっとで得た気づき

新卒でエンジニアとしてデータ基盤関連の部署に入って、この約半年とちょっとで学んだことをまとめたいと思います。そして振り返って特に大事だと思ったことについて書いていこうと思います。

# 自己紹介
　まず自分の紹介からなのですがもともと物理系の院に通っており、fortranをひたすら書いていた状態からエンジニアとして新卒で入社しました。入社半年前にやばいと思いpythonなどを軽く触っていましたが、ほぼ経験なしの状態でしたがOJTでいきなり現場に入りました。自分と似た境遇の人がどのくらいいるかわかりませんがそのような人々に対して何か参考になるところがあれば幸いです！
　部署はデータ基盤系の部署と兼務でデータを使った何でも屋の部署に配属されました。何でも屋の方ではまだあまり活動をできていなかったので主にデータ基盤系の部署の話が中心になります。


# やってきたこと
　自分の整理も兼ねてやってきたことを箇条書きにしてますが、基本的に読み飛ばしちゃって大丈夫です！
個人的に大きな気づきがあったところは赤字にしています。

| 時期       | 内容 |学んだ知識    |
|:-----------------|:------------------|:------------------|
|4月~5月             |・データ基盤理解のために運用の仕事を中心に行う |SQL|
|           |アカウント発行・データ連携対応・障害対応|Python・AWS|
||上司の趣味によりruby使いになる(railsチュートリアル制覇)|Ruby|
|6月~8月|郵便番号をデータ基盤に連携する（初のデータ開発的な動き？）||
||社内用botのエンハンスで機能追加や内部処理のapi化（Jenkins）|Chatops・Jenkins・api|
||<font color="Red">定常モニタリング用にredashをterraformで作成し始める</font>|terraform・docker・ECS・redash|
||<font color="Red">アカウント作成webアプリをフルスクラッチで書き始める（rails）</font>|rails|
|9月~10月|<font color="Red">jenkinsとGHEの連携を使って自分の開発周りを自動化する</font>||
||データ連携作業から延長してモニタリングレポートの作成（Tableau）|Tableau|
||slack botのエンハンス（snippetを使ったり）||
||社内のデータ基盤ユーザーに利用者アンケートを取り始める||
||アカウント作成webアプリが<font color="Red">完成と同時にDBの構造、命名規則等の指摘を受けまくる</font>|ドメイン駆動（触りのみ）・要件定義|
|11月~12月|社内向けデータ基盤勉強会を開催する||
||<font color="Red">S3でwebアプリを簡単に実装（サーバーレス）</font>|js|
||slack botの裏側をjenkinsからapi gatewayに（サーバーレス）|api-gateway・lambda・AWS batch|

#半年ちょっとエンジニアをして思ったこと

　感じたことはたった一つだけで<font color="Red">いかに自分の開発スピードを加速できるか</font>に全てがかかっているということです。先輩の受け売りになりますが自分の能力yを```y=ax+b```で表すとしたらaをあげることが重要ってことを実感しました。そして自分の開発スピードを加速させるために意識したことが以下の三つです。

1. できるエンジニアの近くで作業する（運と行動）
2. 開発で自動化できるところは早い段階で済ませる（Jenkins）
3. 変更を前提で開発を行う（terraform、docker、サーバーレス）

　一つ目は説明はいらないですね笑。２つ目は特に強調したいところで、自動化が上手くなるにつれてどんどん開発スピードが加速します。現在gitにコードをあげればその後は全てJenkinsがやってくれる状態にしてています。３つ目に関してはterraformとdocker、サーバーレスを例に挙げていますが、普段のコードの書き方でも気をつけた方が絶対いいです。（```DBの構造、命名規則等の指摘を受けまくる```の時に生き残れたのは少しだけこれを意識した設計になっていたからだと思います）

# 最後に
　三つを気づきとして挙げたのですが成長率をあげる方法という意味では無限に手段があると思っています。今後もエンジニア方面に限らず成長率をいかにあげるかを常に考えていきたいです。
Kaggleで大人気！XGBoostに関する備忘録

## はじめに
現在取り組んでいる機械学習系の卒業研究の中でXGBoostを使おうと思い、あれこれ調べたので、自分の思考の整理代わりにも、記事にしてまとめようと思います！

## XGBoostとは？
逐次的に弱学習器を構築し、予測モデルを生成するものをブースティングといい、その中でも弱学習器を構築する際に損失関数の最小化に勾配降下法を用いるものを勾配ブースティングと言います。
その勾配ブースティングをC++で実装し高速化したものが、XGBoostです。
世界的なデータ解析コンテストサイト"Kaggle"では、2015年に出された問題29問のうち、なんと17問がXGBoostを用いたモデルが１位となっています。

XGBoostの利点は、
- 欠損値が多いなどのスパースなデータに対して、事前に木の分岐の方向を決めるアルゴリズムを採用している。
- 並列分散処理により、モデルの探索を高速化している。
- CPU外でも学習が回せるため、大規模なデータも処理できる。
などが挙げられます。

## XGBoostのハイパーパラメータ
XGBoostの公式ドキュメントから、チューニングすべきであろう主なハイパーパラメータを以下にまとめます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/215663/027e64ef-ac8f-80ac-7c44-8e06948c1d47.png)

pythonでパラメータを指定する際には、'eta'は'learning_rate'、'lambda'は'reg_lambda'とする必要があるみたいです。

## 実装
XGBoostを用いて、日本版Kaggleの"DeepAnalytics"の銀行の顧客ターゲット問題に取り組んでいきます。
以前、筆者がインターンしている会社の技術ブログで他手法での取り組みを紹介しているので、問題の詳細は[こちら](http://kysmo.hatenablog.jp/entry/2017/12/01/103745) をご覧ください。

以下、学習モデル作成に用いたコードです。

```python:XG_model.py
import pandas as pd
from sklearn.cross_validation import train_test_split
import math
import numpy as np
from sklearn.metrics import classification_report, roc_auc_score, precision_recall_curve, auc, roc_curve
import xgboost as xgb

#csvファイルを読み込む
df = pd.read_csv('remake_train.csv')

df_except_y = df.drop(["y"], axis=1)
X = df_except_y.as_matrix()

# 目的変数に "y " を利用
y = df['y'].as_matrix()

# 必要なライブラリのインポート
from sklearn.grid_search import GridSearchCV
# 動かすパラメータを明示的に表示
params = {"learning_rate":[0.1,0.3,0.5],
        "max_depth": [2,3,5,10],
         "subsample":[0.5,0.8,0.9,1],
         "colsample_bytree": [0.5,1.0],
         }
# モデルにインスタンス生成
mod = xgb.XGBRegressor()
# ハイパーパラメータ探索
cv = GridSearchCV(mod, params, cv = 10, scoring= 'roc_auc', n_jobs =-1)

#　trainデータとtestデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 0)

# 予測モデルを作成
cv.fit(X_train, y_train)
 
#予測    
y_train_pred = cv.predict(X_train)
y_test_pred = cv.predict(X_test)
```
今回は、learning_rate,max_depth,subsample,colsample_bytreeの４パラメータをグリッドサーチを用いて、チューニングしました。

| パラメータ | 探索する値 | 採用された値 |
|:-:|:-:|:-:|
| learning_rate  | 0.1, 0.3, 0.5  | 0.1  |
|  max_depth | 2, 3, 5, 10  |  3 |
|  subsample | 0.5, 0.8, 0.9, 1.0  |  1.0 |
|  colsample_bytree | 0.5, 1.0  | 1.0  |

上記のように、ハイパーパラメータがチューニングされました。

この学習モデルを用いて推定を行うと、結果は、AUC値で0.93238となりました。
前回ランダムフォレストで取り組んだ結果はAUC値0.93560だったので、多少精度が落ちる結果になりました。。

## 最後に
今回色々と調べてみて、ハイパーパラメータの内容や実装方法など理解を深められましたが、
数式的な理解がまだ浅いため、直感的にパラメータをチューニングしてしまったのが反省点です。
元の論文を読み込んで、さらに理解を深めていきたいと思います！

## 参考文献
今回の記事作成にあたって、以下の記事を参考にさせていただきました。
[xgboost公式ドキュメント](https://xgboost.readthedocs.io/en/latest/)
[xgboost-github](https://github.com/dmlc/xgboost)
[勾配ブースティングについてざっくりと説明する - About connecting the dots.](http://smrmkt.hatenablog.jp/entry/2015/04/28/210039)
[XGBoostの主な特徴と理論の概要](https://qiita.com/yh0sh/items/1df89b12a8dcd15bd5aa)
Ingressエージェント100人ぐらいにOSM化の感想を聞きました

この記事は[OpenStreetMap Advent Calendar 2017](https://qiita.com/advent-calendar/2017/osmjp)の13日目として投稿しています。

Ingressのスキャナー地図がOSM由来に変更されたので、マッパー兼業エージェントの1人としてG+でエージェントの皆さんにアンケートしてみました。
2017/12/06 - 2017/12/13の期間に146名から投票いただき、結果はご覧の通りです。

| 選択肢           | 人数 | 割合 |
|:----------------|-----:|----:|
| とても良くなった  |    3 |  2% |
| ちょっと良くなった|    5 |  3% |
| 以前と変わらない  |   46 | 32% |
| ちょっと悪くなった|   44 | 30% |
| とても悪くなった  |   48 | 33% |

回答者の活動地域の分析などは行っていませんが、やはり今まであった道路が消えた、位置がずれている等の感想が多いようです。
かといって私のいる北海道の編集状況を見る限りでは、新人マッパー大量爆誕ということもなく、不満は感じつつもOSMに登録してまで直すことはせずに我慢するとか、とりあえず登録だけしてみたけどよくわからないので放置というエージェントが多いようです。
北海道に関してはエージェント数の多い札幌のマッピングが進んでいるため、道路や建物について特に不満を覚える状況ではないのかもしれません。
何件かOSMを紹介する投稿をしたものには、普段交流あるフォロワー（主に北海道内のエージェント）以外からのフォローもいただいており、興味はあるという方はいると思うので、今後もできる範囲で紹介は続けていこうと思います。

1年後に同じアンケートをしたらどうなってるかな？

![2017-12-13Gplus.png](https://qiita-image-store.s3.amazonaws.com/0/221421/4b0a449f-ce47-a558-599c-bd1aa8c85c13.png)
https://plus.google.com/u/0/+mMikanZuki/posts/3HKe5tjwSVZ
UnityのWWWでjsonをポーリング

1秒ごとにjsonを読みに行くコード。
コルーチンが何なのかよくわかってませんが、とりあえず動いた。


```csharp

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Polling : MonoBehaviour {

	private string path = "https://hoge.com/json/hoge.json";
 
	void Start () {  
		Request();		
	}

	void Request()
	{
		// コルーチンを実行  
		StartCoroutine ( RequestJson(OnRequest) );		
	}
	
	void OnRequest()
	{
		Debug.Log("complete");
		Invoke("Request",1f);
	}
	
	IEnumerator RequestJson (Action callback) {
     
		using(WWW www = new WWW(path)){
 
			yield return www;
 
			if(!string.IsNullOrEmpty(www.error)){
				Debug.LogError("www Error:" + www.error);
				yield break;
			}
 
			Debug.Log( www.text );
			JSONObject json = new JSONObject(www.text);

			callback();

		}
             
	}
	
}

```

### ※追記　WWW → UnityWebRequest　に改造

```csharp
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class ApiPolling : MonoBehaviour {

    protected string _url = "https://hoge.com/json/hoge.json";
    protected string _json = "";
    protected JSONObject _jsonObject;


    void Start () {  
        Request();      
    }

    void Request()
    {
        
        // コルーチンを実行  
        StartCoroutine ( RequestJson(OnRequest,OnError) );      
    }

    void OnRequest()
    {
        Debug.Log("OnRequest");
        Invoke("Request",1f);
    }

    void OnError(){
        //error
        Debug.LogWarning("ApiPolling err");
        Invoke("Request",1f);
    }

    IEnumerator RequestJson (Action callback,Action callbackError) {

                UnityWebRequest www = UnityWebRequest.Get(_url);
                www.timeout = 1;

                yield return www.Send();

                if(www.isNetworkError) {
                    Debug.LogWarning(_url);
                    //Debug.LogError("www Error:" + www.error);
                    callbackError();
                    yield break;
                }
                else {
                    _json = www.downloadHandler.text;
                    _jsonObject = new JSONObject(_json);
                    callback();
                }
    }

}

```
Cognos Analytics にてフォルダをインポートする際の手順

#**概要**
Cognos Analyticsに限らずCognos BIにてフォルダをインポートする際の手順と気を付ける点について記載します。
尚、エクスポートでも共通しておりますがインポートの最小単位もフォルダ単位です。

#**環境**
OS:Windows10
Cognos:Cognos Analytics v11.0.8

#**手順**
１．Cognos Analytics起動

２．左下の管理より「管理コンソール」を押下
Cognos Administrationを起動

３．設定タブのコンテンツ管理より
インポート対象のエクスポートファイルの「詳細」を押下

４．「プロパティーを設定」のエクスポートタブからターゲット名を確認し「キャンセル」で戻る

５．Cognos Analyticsに戻り
先ほど確認したターゲット名が命名されているフォルダが存在するか確認

６．5で確認したフォルダが存在すればこの場所にインポートされるが、存在しなかった場合ターゲット名のフォルダを作成しておく

７．Cognos Administrationに戻り
設定タブのコンテンツ管理画面右上にあるインポートアイコンよりインポートファイルを作成

８．配布アーカイブにインポートする対象のファイルを選択し「次へ」を押下

９．名前を記入し「次へ」を押下
（個人的にエクスポートファイルアイコンとインポートファイルアイコンの見分けが一見つき辛いのでファイルに-imp,-expとつけると分かり易い）

１０．「共有フォルダー、ディレクトリー、およびライブラリーのコンテンツ」を確認しチェックを入れオプションをインポートする条件に合わせ選択し「次へ」を押下

１１．こちらもインポートする条件に合ったオプションを選択し配布記録を選択し「次へ」を押下
※配布記録については以下を参照
最小：配布の集計情報のみを保存する。メモリ消費が最小
標準：配布の進捗情報と集計情報を保存する。デフォルトのオプション
トレース：配布の詳細すべてを記録する。メモリ消費量は最大

１２．インポート概要を確認し「次へ」を押下

１３．「保存して一回実行」にチェックが入っている事を確認し「終了」を押下

１４．「実行」を押下

１５．「OK」を押下

１６．ステータスタブの「過去の処理」よりインポートが成功しているかステータスを確認
シェルスクリプトで無効なメールアドレスをはじく

ずっと昔に下書きして放置していたスクリプトを晒してみます。

# 用途

- メルマガ配信用のリストから規約に準拠していないメールアドレスの行を除外したいときに使います。
- ついでにblacklist.txtに定義したメールアドレスがあればそれも除外します。
    - blacklist.txtはバウンスメールから拾ったメールアドレスをまとめただけの一覧

# 実装

```bash
#! /bin/bash

# blacklist.txtをソート＆重複除外してsorted_bl.txtを作成
cat blacklist.txt |
sort -k 1,1 |
uniq > sorted_bl.txt

# members.txtから規約に違反しているメールアドレスなどを除外してmembers_temp.txtを作成
cat members.txt |
grep -P '^(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'\''*+/=?\^'\`'{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'\''*+/=?\^'\`'{}~|\-]+))*)|(?:'\"'(?:\\[^\\r\\n]|[^\\'\"'])*'\"')))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'\''*+/=?\^'\`'{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'\''*+/=?\^'\`'{}~|\-]+))*))).+$' |
grep -v -P '^.+?@xxx.jp' > members_temp.txt

# members_temp.txtをメールアドレスの昇順にソートした後、sorted_bl.txtと結合
# blacklist.txtに存在しない行は先頭にタブ文字が入るため、タブ文字で始まる行をgrepで抽出
# sedで先頭のタブ文字を消去し、ソートしたものをmembers_filtered.txtに出力
cat members_temp.txt |
sort -t$'\t' -k 1 |
join -t$'\t' -1 1 -2 1 -a 2 -o 1.1,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,2.10,2.11,2.12,2.13 sorted_bl.txt - |
grep '^'$'\t' |
sed -e 's;^\t*;;g' |
sort -k 1 > members_filtered.txt

# 中間ファイルを削除
rm -f sorted_bl.txt
rm -f members_temp.txt
exit 0
```

# あとがき

現職では一切使わないので修正はしないと思います。
修正したほうがいい箇所を見つけられた方は修正リクエストいただけるとうれしいです。
Rails 開発環境 構築　2017/12

#　ECサイトの勉強用にRubyonRailsを構成してみる
##まずはRubyを入れるぜ！！
環境はこちら⇒OS:WINDOWS10　pro　64bit

rubyインストーラーをここから[ここから](https://rubyinstaller.org/downloads/)ダウンロードしセットアップ開始
RubyInstaller2の画面になってなんか三択選べるようになる。
え、英語か・・・ガクブル
![image.png](https://qiita-image-store.s3.amazonaws.com/0/222774/9858fe3f-f3a3-00ea-140f-262d2b4c2e9b.png)

こんな感じの意味か？
1.基本的なインストール
2.すでにインストールしてある前提でアープデート
3.よくわからんが、MYSY2最新版入っている前提で、MinGWも入れるぜ？ってことかな?

[この](https://qiita.com/Ted-HM/items/4f2feb9fdacb6c72083c)投稿によると
>MinGWとはWindows上で使えるGNUのツールチェインのひとつだ

まあ・・・よくよからんから、とりあえず、ENTER押してみるよね。（笑）
なんか始まったぞ！！msys2-x86_64-20161025.exeのDLに失敗。
↓
中止だ！！止め方わからんから、とりあえず右上の×連打・・・ふう止まった。

回線が遅かったせいか?
仕方ない、手動で[ここから](http://www.msys2.org/)msys2-x86_64-20161025.exeをDLしてインストしてみるか。
↓
MSYS2のshell(ターミナル?)が起動。なんかここでアップデートしとけっていう記事を見かけたからやってみる。

>pacman　-Su　　

※pacmanはMSYS2のパッケージ管理ソフトらしい。

・もう一度rubyのインストーラーでセットアップをする。
今度はRubyInstaller2の画面の２、アップデートを選択
↓
色々検証、ダウロード、アップデート、至れり尽くせり。

・バージョン確認
>ruby -v
ruby 2.4.2p198 (2017-09-14 revision 59899) [x64-mingw32]

無事rubyは入ったようだ。

##次はRailsを入れるぜ！！

>gem install rails

これだけでいいらしい。

だがしかし・・・そんなうまい話はない。
>ERROR:  Error installing rails:
        ERROR: Failed to build gem native extension.
・・・以下呪文のような英文がいっぱい。

ああ、なんか無理っぽい( ;∀;)。気になったのもはこの文言。

>You have to install development tools first.

なんか先に入れろって言ってるのかな・・・そういえば・・・

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222774/46064850-3b55-d23d-c576-d7b276088649.png)

これで「２」選択したあと終了しちゃったから怒ってるのかい？
勝手な推測のもと。もう一度「３」を選択してやってみた！！

そしてもう一度、
>gem install rails

なんか色々始まったぞ！！いけるのか？

>rails -v
Rails 5.1.4

きたぁぁぁぁぁぁ(;'∀')
Error starting userland proxy: Bind for 0.0.0.0:XXXX failed: port is already allocated

## Bind for 0.0.0.0:8000 failed: port is already allocated

自分の場合上記のエラーが出た。
コンテナは全てストップしているが、ポートが占有されてゾンビ化しているらしい。
Dockerを再起動しても治らないらしい。

PIDを調べる
`$ sudo lsof -i:8000`

```
COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node    72234    muu   13u  IPv6 0x6d0e948670f199df      0t0  TCP *:irdmi (LISTEN)
```

PIDをKillして解決
`$ kill -9 72234`
[WordPressテーマ] 子ページの一覧をショートタグで取得する

WordPressテーマを作成していて、ショートタグで子ページ一覧を表示しようとした時に使った関数とコードを書いておく。

### get_the_ID()

固定ページのIDを取得するのに使用した。

[関数リファレンス/get the ID - WordPress Codex 日本語版](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_the_ID)

### get_page_children()

親ページで子ページの一覧を取得する際に使用した。

[関数リファレンス/get page children - WordPress Codex 日本語版](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_page_children)

### wp_strip_all_tags()

投稿データ(固定ページ)からHTMLを削除した抜粋を取得するのに使用した。

[関数リファレンス/wp strip all tags - WordPress Codex 日本語版](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_strip_all_tags)

### 日本語の切り出し

日本語にような2バイト文字は`substr()`で切り出そうとすると◆の様な文字列が出てしまい上手く切り出せない。この場合、`mb_substr()`を使うことで上手く切り出すことが出来る。なお、日本語は2バイトであるため第二引数には、`切り出したい文字数/2`を指定する必要がある。今回は`the_excerpt()`のデフォルトである110文字を参考に`55`を指定した。

### ショートタグでの出力

原則としてショートタグでの出力は`echo`や`print`を使わない方が良い。出力は結合して最後に`return`で返すのが標準的な手法のよう。

[php - Wordpress using echo vs return in shortcode function - Stack Overflow](https://stackoverflow.com/questions/21538180/wordpress-using-echo-vs-return-in-shortcode-function)

```php

/*
 * Enable short-tag
 * * * * * * * * * * * * * * * * * * * * * * */
function get_child_list($argv) {

  // 固定ページでない場合は終了
  if(!is_page()) {
    return "Error: Not supported type(only page).";
  }

  // クエリの組み立て
  $my_wp_query = new WP_Query();
  $all_wp_pages = $my_wp_query->query(array(
    'post_type' => 'page',
    'nopaging'  => 'true'
  ));

  // 子ページの取得
  $child_pages = get_page_children( get_the_ID(), $all_wp_pages );

  // 子ページが無い場合
  if(count($child_pages)<1){
    return;
  }

  // デバッグ用
  // echo "<pre>".var_dump($child_pages)."</pre>";

  // HTMLの組み立て
  $child_pages_html = '<ul class="childList">';

  // それぞれの子ページに対して処理を実行(ループ)
  foreach($child_pages as $child_page){

    // 子ページのデータを取得
    $child_page_id = $child_page->ID;
    $child_page_data = get_post($child_page_id);
    $child_page_title = $child_page_data->post_title;
    $child_page_raw_content = $child_page_data->post_content;

    // HTMLタグを除去して110文字(日本語は2バイト文字)を取得
    $child_page_content = mb_substr(wp_strip_all_tags($child_page_raw_content, true), 0, 55);
    $child_page_url = $child_page_data->guid;

    // HTMLの組み立て
    $child_pages_html .= <<< EOF
      <li><a href="$child_page_url">
        <span>$child_page_title</span>
        <div>$child_page_content</div>
      </a></li>
EOF;

  } // end of foreach

  // 組み立てたHTMLを返す
  return "$child_pages_html</ul>";

} // end of get_child_list()

add_shortcode('child_list', 'get_child_list');
```
このコードを`functions.php`へ書いて`[child_list]`を固定ページで書くと、サイトでは子ページ一覧が表示される。

---
Copyright (c) 2017 Tomoyuki KOYAMA
Released under the MIT license
http://opensource.org/licenses/mit-license.php
RSpecでファイルがダウンロードされるまで待つ

# 課題：ファイルのダウンロードが終わってたり終わってなかったり

Capybara(Chrome headless)のテストが不安定でした。

# 調査

ディレクトリの中が空じゃないかどうか見張ればいい。
なんでこんな単純なことに気づかなかったのか！！

# 実装

参考URLに載っているのとほぼ同じですが、PATHの指定を並列テストを考慮した作りにしています。

```rb
module WaitForDownload
  PATH = Rails.root.join("tmp/download#{ENV['TEST_ENV_NUMBER']}")

  def wait_for_download
    Timeout.timeout(Capybara.default_max_wait_time) do
      sleep(0.1) until downloaded?
    end
  end

  def downloads(pattern="*")
    Dir.glob(PATH.join(pattern))
  end

  def downloaded?
    !downloading? && downloads.any?
  end

  def downloading?
    downloads.grep(/\.crdownload\z/).any?
  end

  def clear_downloads
    FileUtils.rm_rf(downloads)
  end
end

RSpec.configure do |config|
  config.include WaitForDownload, type: :feature

  config.after :each, type: :feature do
    clear_downloads
  end
end
```

## 利用法

```rb
click_button 'Excelダウンロード'
wait_for_download
expect(downloads('*.xlsx').size).to eq 1
```

# 参考URL

- https://collectiveidea.com/blog/archives/2012/01/27/testing-file-downloads-with-capybara-and-chromedriver
プライバシーの確認を必要なやつだけ次々出す

「カメラロールを使用します」やらなんやらのプライバシーのアラートを一度に次々出す
毎回調べるの面倒だからまとめた
すでに出したことあるやつならスキップして次のアラートを出す


```swift
func checkAuth(_ completion:(()->())? = nil){
    //カメラロール
    func checkAuthCameraroll(_ completion:(()->())?){
      if PHPhotoLibrary.authorizationStatus() != .authorized {
        PHPhotoLibrary.requestAuthorization({ (status) in
          completion?()
        })
      }
      else{
        completion?()
      }
    }
    //ビデオ
    func checkAuthVideo(_ completion:(()->())?){
      if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) != .authorized {
        AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (isSuccess) in
          completion?()
        })
      }
      else{
        completion?()
      }
    }
    //オーディオ
    func checkAuthAudio(_ completion:(()->())?){
      if AVCaptureDevice.authorizationStatus(for: AVMediaType.audio) != .authorized {
        AVCaptureDevice.requestAccess(for: AVMediaType.audio, completionHandler: { (isSuccess) in
          completion?()
        })
      }
      else{
        completion?()
      }
    }

    checkAuthCameraroll {
      checkAuthVideo {
        checkAuthAudio {
          completion?()
        }
      }
    }
  }
```
Faust:soft clipperを作ってみた

ハードクリップしないようにするエフェクトです。shaperとかsaturatorとかの方が通りがいいのかな?
DAWを新しくしたら前使ってたのが使えなくなったので、作ってみました。

```Java:
declare name "SoftClipNoGui";

import("stdfaust.lib");

process = preGain : clipper : postGain  ;

preGain = preGainMono, preGainMono ; 
preGainMono = *( preSlider : ba.db2linear )  ;

clipper = clipperMono, clipperMono ;
clipperMono = ( clipSlider : ba.db2linear), _ : clip ; 
clip( a1, x ) = min( a0 , atan((a0 - a1) / a2 ) * a2 + a1 ) * a3
  with{
    a0 = abs(x);
    a2 = (1-a1) * 2 / ma.PI ;
    a3 = ma.signum(x) ;
  };

postGain = postGainMono, postGainMono ;
postGainMono = *( postSlider : ba.db2linear ) ;

preSlider = hslider("/v:Ctrl/1 pre[unit:dB]", 0, 0, 20, 1 ) ;
clipSlider = hslider("/v:Ctrl/2 clip", -1, -30, -1, 1 ) ;
postSlider = hslider("/v:Ctrl/3 post[unit:dB]", 0, -10, 10, 1 ) ;
```

```clip```が謎の数式になっていますが、```y = x``` から ```y = 1``` にうまく繋がる曲線はないかなあと試行錯誤した結果です。
```y = x``` の途中から ```atan(x)```を移動したものに乗り換えています。
![スクリーンショット 2017-12-13 16.40.23.png](https://qiita-image-store.s3.amazonaws.com/0/61597/f8b3a0c2-1d9f-8504-8b50-3908397cf504.png "スクリーンショット 2017-12-13 16.40.23.png")
もっと賢い方法があるんでしょうが思いつきませんでした。

このatanのつぶれ具合がよくてよく使っています。
(ma.)tanhを使うと若干ハード寄りなつぶれ具合になります。

※ FaustLiveだとsignumがundefinedになって読み込んでくれない。謎。
online compilerとPlayGroundでは問題なし。なぜ?
glslで良く作られるユーティリティ関数


# ランダム関数

恐らくもっとも使われている関数ですが、このオリジナルを使うとモバイル系がほぼ全滅するので、後述のものを使う。原因は精度不足。

```glsl
float rand(vec2 co){
   return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
```

```glsl
highp float rand(vec2 co){
    highp float a = 12.9898;
    highp float b = 78.233;
    highp float c = 43758.5453;
    highp float dt= dot(co.xy ,vec2(a,b));
    highp float sn= mod(dt,3.14);
    return fract(sin(sn) * c);
}
```

もしくはモバイルの場合は、すべて高精度にしてしまう方法がある。

```glsl
#ifdef GL_ES
precision highp float;
#endif
```

但し、この場合、高精度を指定したことによってシェーダーが動作しなくなってしまう端末があるらしい。※未確認

# saturate関数
```glsl
float saturate(float f){
   return clamp(f,0.,1.);
}
```

これは同名のhlslのシェーダー関数から、入力された値を0と1の間に限定する。フラグメントシェーダーでgl_FragColorで出力時0.より小さい数値は0.、1.より大きい数値は1.(saturateされて)として表示されるが、その前段で複数のシェイプ同士を+などで加算した場合は、特にsaturateされていないので、思わぬ不具合の元となる。
シェイプ同士の合成のあとは必ずと言って掛けるので、中級以上の場合、必ずと言っていいほど作っている。

```glsl
#define saturate(x) clamp(x,0.,1.)
```

saturate関数の場合はdefineで作ったほうがいい

# アフィン変換

## 回転(2D)
```glsl
mat2 rot(float r){float c=cos(r);float s=sin(r);return mat2(c,-s,s,c);}
```

## 拡大・縮小(2D)
```glsl
mat2 scale(vec2 s){
    return mat2(s.x,0.,0.,s.y);
}
```

拡大・縮小に関して言えばvec2(s.x,s.y)と同じなので使われることは少ないかもしれない。

```glsl
mat2(s.x,0.,0.,s.y) = vec2(s.x,s.y);
p*=mat2(s.x,0.,0.,s.y);
p*=vec2(s.x,s.y);
```

xとyが同じ拡大・縮小率の場合は単にnを掛けるだけである

```glsl
p*=n;
```

## シアー(せん断・スキュー) (2D)
```glsl
mat2 sheerX(float a){return mat2(1.,tan(a),0.,1.);}
mat2 sheerY(float a){return mat2(1.,0.,tan(a),1.);}
```

あまり、使われないが、任意の四角形変形が使えない時に使える

## ホモグラフィ homography (四角形変形) (2D)
* ホモグラフィについて
 * http://shogo82148.github.io/homepage/memo/geometry/homography/
 * http://yaju3d.hatenablog.jp/entry/2013/08/04/152524

ここで、難度がとても高くなる。
 * 実装例 https://www.shadertoy.com/view/MlGGz3

## 外積(二次元)

```glsl
//float cross(vec2 v1, vec2 v2) {return v1.x*v2.y - v1.y*v2.x;}
float cross(vec2 v1, vec2 v2) {return dot(v1,vec2(v2.y,-v2.x));}
```

3次元の外積は組み込み関数として用意されているが2次元は用意されていないので、作っておくと便利
外積の3次元ベクトルで返ってくるが、2次元はスカラー、ベクトルで返すこともできるが有効成分がスカラーなので、使われることはない。

公式通りとしてもいいが、組み込み関数がないので、内積(dot)にv2の逆行列を掛けてもいいのでこれで高速化している。

# pow(vec3対応)
トーンカーブ的に、コントラストを上げたい時に使う

```glsl
vec3 pow(vec3 c,float p){return vec3(pow(c.r,p),pow(c.g,p),pow(c.b,p));}
```
【鋭意更新】６歳児にも分かるプログラミング用語

## なんで書いたか
プログラミング初心者にとっては同じ日本語とは思えない、宇宙語みたいなのがネットにも書籍にも日常会話にもたくさん出て来る。読み進もうにも辞書がない。あってもその辞書が読めないことが多い。

## 方針
以下のルールで書く

1. なるべく簡単な言葉で説明する。
2. 例を書く
3. その用語を使う目的を明らかにする

## 【編集中】入れていく単語
DI Dagger プロパティ
Cognos でレポート実行時の送信データをFiddlerで確認する手順

#概要
この辺りの記事で、Cognosのレポートチューニング時に、Cognosサーバーからクライアントブラウザに送られてくる送信データを解析する事が必要な時があるというコメントをしました。

**Cognos BI ドリルスルー使用時のパフォーマンス上の注意点**
https://qiita.com/shinyama/items/2fa81dfd42689eb1b407

実際に他のプロジェクトで久しぶりにFiddlerを使ってみたところ、自分でやり方を結構忘れてしまっていたので、備忘録の意味も込めて手順を投稿しておきます。

#手順
使用するツールは、Fiddler2です。
フリーのツールなので、ダウンロードしてクライアントPCにインストールしてください。

スタートメニューから、Fiddler2を起動します。
初期画面はこんな感じです。
![001.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/70afea1c-67e8-d1a6-05ba-aa211519bf9c.png)

「Browse」の右側の矢印からプルダウンで「Internet Explorer」を選択します。
![002.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/cd2b5d6a-2d3c-762c-afeb-be67f2102d0d.png)

そのままCognos AnalyticsのURLを入力し、Cognosにログインします。
![003.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/9c0a9596-15ff-8ad6-52d7-dcd5f08721f5.png)

レポートを実行します。
![004.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/cbc2c06b-c5a3-27a4-571d-35a48151f649.png)

プロンプトに「ファックス」と「店頭」を選んで「終了」します。
![005.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/2e2e5db0-139d-be49-d940-502c7ec0dfc1.png)

Fiddler2に戻ってみると、下の方に /bi/v1/reports というURLで出力されているエントリーがあるので、クリックします。
![006.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/e0efe78c-df35-6325-69e4-6770fa1b6ca1.png)

右側のこの文言をクリックします。
![007.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/675283b8-d7f9-0bf9-b71c-ea7ecfdee257.png)

下側の「TextView」タブを選択します。
![008.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/f7d552cd-e5d8-b13e-06ea-729578c9da06.png)

「View in Note」をクリックすると、メモ帳で開きます。
![009.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/0849ced3-93c6-f774-e415-546ce92bf3bc.png)

SAKURAエディター等で検索してみると、「ファックス」が大量に繰り返して送信されて来ているのがわかります。
数をカウントしたい時は、「ファックス」を「ファックス」で置換してみると、置換件数が表示されるので便利です。
![010.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/ea0de5fc-f171-1a90-1bd7-7da0059457f0.png)
Fargateって秒速何センチメートルでスケールアウトするの？

2018年早々には、昨年の大ヒット作が地上波初登場！
この機会に同監督の過去作を見直してみるのはいかがでしょうか。


-------------


はい。
そんなわけでFargateです。


約1年ほどECSでサービスを運用してきました。
コンテナを起動した時の驚き。Vagrantとは次元が違う爆速感。

**これはDockerの時代くるわ〜**

と手元の開発環境をDocker化。勢い余ってサーバーサイドまでコンテナ化しました。
が、ふと我に返って足元を覗き込んで見ると、ECSはマネージドというにはあまりに急造に組んだ足場よろしくその土台にあるEC2がスケスケ。
定期的にEC2のAMIとコンテナのイメージ双方で、``yum update``やら``apt update``やら``apk update``しちゃったりしなかったりして、これって単に**お守りする層が二倍になってる**んちゃうん！？
と疑心暗鬼にとらわれておりました。
Lambda使ってAMIをアップデートする例なんかも公開されてますけど、なんかこう違うんですよ。


> AMI にパッチを適用し、Auto Scaling グループを更新する
http://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-asgroup.html

そんなとこにリソースを割きたくないんですよぉぉ。**箸より重いものを持ちたくないんですよぉぉぉぉ。**


そこに颯爽と登場したのが、我らが**Fargate**です。
実際チュートリアルに従ってFargate製クラスタをつくってみても、**EC2のページはもぬけの殻。**
これだ！
これを求めていたんだ！

気になるお値段に関しては既に素晴らしいポストが並んでおります。


> 俺はSSHをしたくない ~ Fargate vs ECS+SpotFleet のPrice比較 ~
http://tech-blog.abeja.asia/entry/fargate-ecs-spotfleet


> 新しいマネージドコンテナサービスAWS Fargateの価格は高いか安いか？ECS/Fargateのコスト最適化を考えてみよう
https://qiita.com/sudoyu/items/cde059bf98f3d32cfa61


**次はスケール速度だっ！**
ECS+EC2の時は、Cloudwatchのアラーム発報からオートスケール発動、EC2の起動完了まで約5分、そこからECSのAgentが最適な数にコンテナを増やすまでさらに5分で体感10分くらい待っていた感じでしたがはたして....。


# 前提

> AWS FargateでNginxを動かしてみる
https://qiita.com/riywo/items/b223bdad2b3ae3bebf55

恥ずかしげもなく2日目の記事の内容を完全トレースして環境を構築します。
その後、またまた本記事記載のスケールアウト方法を試してその結果をストップウォッチで計測。
せめて``ecs-cli``を``time``で計測しろや〜とはごもっともなご意見ですが、残念ながら秒速で起動！というほどには爆速ではないのはわかりきっているので省エネです。ご容赦を。

# 結果


回数|要した時間(分:秒)
-----|------
1    | 2:21
2    | 1:11
3    | 2:20
4    | 0:59
5    | 1:45
6    | 1:11
7    | 1:53
8    | 1:47
9    | 2:15
10   | 2:14


ばらつきはありますが、ざっくり2分程度待てばスケールする模様。アラート発報からの待ち時間を考えても5分もあればスケールしてくれるんではないでしょうか。ECS+EC2の時のざっくり半分くらいのイメージです。ざっくりいいすぎですみません。

sorryページを青ざめながら眺める時間が半減するのであれば、それだけでもFargateに乗り換える価値ありかもしれません！

**はよ東京リージョンにこい〜！**
ChatWork APIを叩いてみたらエラーになった話など

# ChatWorkのAPIを叩いてメッセージを投稿
chatworkのAPIをドキュメント(以下URL)を参考にすると
http://developer.chatwork.com/ja/endpoint_rooms.html#POST-rooms-room_id-messages
```
curl -X POST -H "X-ChatWorkToken: 自分のAPIトークン" -d "body=Hello+ChatWork%21" "https://api.chatwork.com/v2/rooms/{room_id}/messages"
```
とパラメータを指定して叩けばメッセージが登録されるらしいです。

room_id   : チャットワークのルームのURLの#!ridより後の値
APIトークン : アカウントごとに発行するごとにできるAPIトークン値


# Guzzleで叩いてみた
```php
// xxxxxは各自設定を行う
define('ROOM_ID', 'xxxxxxx');
define('API_TOKEN', 'xxxxxxxxxxxxxxxxxxxxxx');

try {
    $client = new GuzzleHttp\Client();
    $request_url = "https://api.chatwork.com/v2/rooms/". ROOM_ID ."/messages";
    $client->post($request_url, [
        'headers'     => ['X-ChatWorkToken' => API_TOKEN],
        'body' => ['body' => 'hogehoge']
    ]);
} catch (GuzzleHttp\Exception\ClientException $e) {
    echo $e->getResponse()->getStatusCode();
    exit;
}
```
これを実行したところ、

![FireShot Capture 16 - チャットワーク - test-room - https___www.chatwork.com_#!rid89667168.png](https://qiita-image-store.s3.amazonaws.com/0/129094/4637eaee-ccd4-b433-f7ff-877bcfa9898f.png)

と投稿されました！

#エラった体験談
## エラった１（ステータスコード：４００）
APIを叩くときのbodyの中身が空文字の場合に、400が返ってきます。
上ケースではエラーになりませんでしたが、
文字数があまりにも多い場合にも、400が返ってくる挙動っぽいです。この場合にエラリました。
これは調べても該当ドキュメントが見つからず、まだよくわかってないのですが、
bodyにバイト数制限もしくは文字数制限があるんじゃないかと思ってます。
ちなみに

```php

$hoge = '';
foreach (range(1,20000) as $value) {
  $hoge .= 'hoge';
}
try {
    $client = new GuzzleHttp\Client();
    $request_url = "https://api.chatwork.com/v2/rooms/". ROOM_ID ."/messages";
    $client->post($request_url, [
        'headers'     => ['X-ChatWorkToken' => API_TOKEN],
        'body' => ['body' => $hoge]
    ]);
} catch (GuzzleHttp\Exception\ClientException $e) {
    echo $e->getResponse()->getStatusCode();
    exit;
}
```
とした場合に400が返ってきました。
hoge * 10000なら200でしたので、このあたりに上限がありそうです。
私もこの文字数多すぎ問題でどうしようかと思ってるところです。。
心当たりがある人は確認してらいいかもしれません

## エラった例２（ステータスコード：４０１）
アクセストークンが失効している場合には、401が返ってきます。
間違ったAPIトークンを設定している場合に401が返ってきました。
正しいAPIトークンかどうか確認してください。



以上です。
【2019年1月版】Googleカレンダーで月表示の土日に色をつけるCSS

**** 2019年1月時点のGoogleカレンダーに合わせ更新しました ****

Googleカレンダーの月表示ではCSSで土日に色をつけて利用しています。

独自CSSの設定はChromeでは[Stylist](https://chrome.google.com/webstore/detail/stylist/pabfempgigicdjjlccdgnbmeggkbjdhd)という拡張機能で、Firefoxでは[Stylish](https://addons.mozilla.org/ja/firefox/addon/stylish/)というアドオンで行っています。
適宜設定でプレフィクスや正規表現でURL(https://calendar.google.com/calendar/r) を指定してください。
※月表示にのみ対応していています。週表示などには対応していません。
※現時点のGoolgeカレンダーに合わせて作成したCSSなので、Googleカレンダー側に変更が合った場合は適宜変更してください。（色なども好きなものに変えてください）

月曜開始

```CSS:
/** start monday **/

/* 
 * -----------
 * main 
 * ----------- 
 */
/*** week columnheader ***/
/* Saturday */
.PhLhOd.elYzab-cXXICe-Hjleke:nth-child(7) .wy3aMe {
    color: #6A6AFF !important;
}
/* Sunday */
.PhLhOd.elYzab-cXXICe-Hjleke:last-child .wy3aMe {
    color: #FF6A6B !important;
}

/*** month presentation ***/
/* Saturday */
.t8qpF.elYzab-cXXICe-Hjleke:nth-child(6) {
    background-color: #eaf4ff !important;
}
.t8qpF.elYzab-cXXICe-Hjleke.YK7obe:nth-child(6) .yzYBvd {
    color: #6A6AFF !important;
}
/* Sunday */
.t8qpF.elYzab-cXXICe-Hjleke:last-child {
    background-color: #ffeaea !important;
}
.t8qpF.elYzab-cXXICe-Hjleke.YK7obe:last-child .yzYBvd {
    color: #FF6A6B !important;
}



/* 
 * -----------
 * side 
 * ----------- 
 */
/*** week columnheader ***/
/* Saturday */
.SoBqBf:nth-child(6) :first-child {
    color: #22F !important;
}
/* Sunday */
.SoBqBf:last-child :first-child {
    color: #E22 !important;
}

/*** month presentation ***/
/* Saturday */
.iMprOe:nth-child(6) .r4nke {
    color: #88F !important;
}
/* Sunday */
.iMprOe:last-child .r4nke {
    color: #E88 !important;
}
```

　　
日曜開始

```CSS:
/** start sunday **/

/* 
 * -----------
 * main 
 * ----------- 
 */
/*** week columnheader ***/
/* Saturday */
.PhLhOd.elYzab-cXXICe-Hjleke:last-child .wy3aMe {
    color: #6A6AFF !important;
}
/* Sunday */
.PhLhOd.elYzab-cXXICe-Hjleke:nth-child(2) .wy3aMe {
    color: #FF6A6B !important;
}

/*** month presentation ***/
/* Saturday */
.t8qpF.elYzab-cXXICe-Hjleke:last-child {
    background-color: #eaf4ff !important;
}
.t8qpF.elYzab-cXXICe-Hjleke.YK7obe:last-child .yzYBvd {
    color: #6A6AFF !important;
}
/* Sunday */
.t8qpF.elYzab-cXXICe-Hjleke:first-child {
    background-color: #ffeaea !important;
}
.t8qpF.elYzab-cXXICe-Hjleke.YK7obe:first-child .yzYBvd {
    color: #FF6A6B !important;
}



/* 
 * -----------
 * side 
 * ----------- 
 */
/*** week columnheader ***/
/* Saturday */
.SoBqBf:last-child :first-child {
    color: #22F !important;
}
/* Sunday */
.SoBqBf:first-child :first-child {
    color: #E22 !important;
}

/*** month presentation ***/
/* Saturday */
.iMprOe:last-child .r4nke {
    color: #88F !important;
}
/* Sunday */
.iMprOe:first-child .r4nke {
    color: #E88 !important;
}


```
title属性　使い分け

マークアップ時にtitle属性の必要性に関して、数秒でも時間を費やすのが煩わしいので、整理して、投稿いたします。

## title属性とは
- グローバル属性なので、全ての要素（タグ）に追加することができる
- ツールチップに助言的な情報を表示するもの  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/192967/e72e2905-042c-20a5-e95a-ec8ac65ce836.png)
「Button1です」がツールチップ

## W3Cが定義しているtitle属性の使用用途

- リンク：　タイトルもしくは対象リソースの記述
- 画像：　タイトルもしくは説明
- 段落：　脚注もしくは解説
- 引用：　ソースの詳細情報
- インタラクティブコンテンツ：　用途に対する分類や指示など  
 インタラクティブコンテンツの例：　a, button, input, img, label, select, texture, video

## title属性の使い分け（本題）
アイコンや記号以外では使用しないのが適切かと思います。
※もちろんimgタグには、title属性を入れないことで統一するということです。

理由は、下記の２つの観点からです。

## SEOの観点から
- Imgタグは、alt属性が代替テキストの役割を担っている
- alt属性などのテキストコンテンツと重複させると、スパムとして捉えられる可能性がある
- スマホ、タブレットでは、ツールチップが表示されないので、PCとの差異が生まれる
- 有無がクローラの評価に影響しない可能性がある

## 見た目の観点から
- コンテンツの上に表示される
- 一律、シンプルなデザインのため、ページの世界観を壊す可能性がある

## 実例
ヤフーのホームページにて、検索窓直下に三角があります。
この三角をホバーして２秒待つと、「キーワード入力補助を開く」というツールチップが開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/192967/dd772240-5590-aa7e-b024-77cefd125a25.png)


## 例外
W3Cがtitle属性を推奨しているもの

- link
- abbr
- dfn
- menuitem
そのタグを使うかどうかは置いといて。

abbrは、略語を指す時に使用する
 `<p>最近、<abbr title=“ProgressiveWebApplication”>pwa</abbr>が気になっている。</p>` 
 pwaは略称であり、本当は、ProgressiveWebApplicationと言うことを伝えることができます。
伝えるのは、ユーザーだけでなくクローラに対してもだと思います。

## 所感
ツールチップが表示されるまで2くらいかかるので、むしろ、使わないくらいの感覚でいいと思います。
title属性は使わず、[ツールチップ自体の使い方は工夫できる](http://uxmilk.jp/60654)と思います。

参考：[w3c](https://momdo.github.io/html51/single-page.html#the-title-attribute)
Rの時系列ライブラリxtsでつまづいた処理をPythonで

[xtsでいろいろ混在したカラムをapproxしたい場合](https://qiita.com/Masutani/items/b235a1774a8ce64a2f09)

こちらで、ある種のバグに悩まされてできなかった処理をやむなくPythonでやりました。

# before (R) 

xts という時系列データフレームのうち、数値については、補完がうまくいきます。

```R
filled <- na.approx(object = xts$numeric, xout = grid, rule = 2)
filled <- na.locf(object = as.zoo(xts$numeric), xout = grid, rule = 2)
```

といってもlocfについては、なぜかダウンキャストしないと動かないんですが。

文字列については以下のように書いたら行けそうですが、仕様上はありなのに、動作しません。

```R
filled <- na.locf(object = xts$chr, xout = grid, rule = 2)
```

ワークアラウンドがいくつか書いて荒れましたが、文字列の場合とxoutを指定する場合には無理でした。


# after (Python)

Python Pandas版です。難なく動きました。

```Python
filled = xts['numric'].interpolate()
filled = xts['numric'].ffill()
```

```Python
filled = xts['chr'].ffill()
```

Rのライブラリは細分化しすぎていて、一個一個のくせが強すぎる。。。
この手のETL処理はPythonにするに限りますね。

## 追記
以下にU-SQLで同様の処理を行う場合を上げておきます。
[U-SQLでLOCF](https://qiita.com/Masutani/items/cf602ea9925d36902ed5)
Problem/Solution Fit を目指すための2種類のインタビュー

Problem/Solution Fitを目指すステージで何をするべきかを探し歩いた結果、[書籍 Running Lean](http://amzn.to/2AgMf6R) に舞い戻ってきました。
Lean Canvasだけじゃないぞ Running Lean! ということでメモ的な何か。

# Problem/Solution Fit を目指すステージでやること

やることは大きく3つある

- 解決するに値する課題かどうかを見極める
- ソリューションによって1の課題が解決できるか見極める
- ソリューションのMVPが何であるかを見極める

このステージでは大概の場合「動くモノ」が存在しない。そのためインタビューなどの定性調査によって上記3点を見極める必要がある。
3点の観点はバラバラなのにも関わらず、定性調査(インタビュー)という手段が一緒なため混同しやすく、例えば課題の無い人にソリューションについてインタビューをしてしまったり、その声をMVPに含めてしまったりといったことが起きてしまう恐れがある。

Running Leanではインタビューの目的を明確にし、分離することでこの辺の問題を避けようとしている（ように見える）。
それが「課題インタビュー」と「ソリューションインタビュー」。

# 課題インタビュー

課題インタビューでは「顧客」と「課題セグメント」の仮説を検証する。
例えば「最近の20代はコミュニケーション手段が複雑で困ってるんじゃないか？」といった仮説の検証に利用する。

課題インタビューは下記が明確になれば終了。

- アーリーアダプターとなる顧客、顧客セグメントが特定できた
- 「絶対に必要な課題」が見つかった
- 現在の顧客の解決方法（既存の代替品）がわかった

# ソリューションインタビュー

課題インタビューで明確になった顧客セグメントにいる顧客に対して、ソリューションインタビューをする。
例えば課題インタビューを繰り返した結果、「20代の中でも新社会人は学生時代の友人、社会人になってからの友人と2種がいて苦労している」ことがわかり、解決に値する課題だとするなら、新社会人にソリューションインタビューをする。
ソリューションの「デモ」を用意し、顧客の課題が解決できるかを検証する。

ソリューションインタビューは下記に確信を持てた時に終了する。

- アーリーアダプターの顧客情報が特定できた。
- 「絶対に必要」な課題がわかった。
- 課題を解決するのに必要な最小限の機能が定義できた。
- 顧客が支払ってくれる価格がわかった。
- (概算で)うまくいきそうなビジネスが構築できた。

ソリューションインタビューを繰り返し実施することで「ソリューションのデモ」をアップデートしていくため、必然的にMVPが何かも判ることになる。

ここまでできたら Problem/Solution Fit!

# とはいえ

こういう記事で判った気にならずに、ちゃんと[本を読みましょう](http://amzn.to/2AgMf6R)。
Franz Ver5でサービスをPluginする for Mac

## 概要
Slack、Chatwork、GitHub、Office365、GMail等のコミュニケーションツールを一元管理出来るElectron製のアプリ。
ブラグイン機能により個人で色々カスタマイズ出来る所が面白いと思う。

Franzがバージョン5になり個人で作ったPluginの追加方法が変更になり、今までの方法では出来なくなってしまった。。。
その為、5からのPlugin方法を下記に記載します。

※今回はEvernoteをプラグインしてみる

## 実際に使ってみる
### 準備
* [Franz](https://meetfranz.com/)をダウンロード、インストールする
* [plugins-legacy Repository](https://github.com/meetfranz/plugins-legacy)をダウンロードする

### プラグイン実施
* Franzに開発用ディレクトリを作成する

```
$ mkdir ~/Library/Application\ Support/Franz/recipes/dev
```

* Repository内のEvernoteを上記ディレクトリにコピーする

```
$ cp -ap ~/plugins-legacy/Evernote ~/Library/Application\ Support/Franz/recipes/dev
```

* packeage.jsonに追記する

```
$ vi ~/Library/Application\ Support/Franz/recipes/dev/Evernote/pacage.json
```

```json:package.json
{
  "id": "evernote", ← 追加
  ・・・
}
```

Franzを起動し、`利用可能なサービス`部分に`開発版`項目が出現し、Evernoteが表示される
![スクリーンショット 2017-12-13 16.02.11.png](https://qiita-image-store.s3.amazonaws.com/0/160596/7e2795dd-eea0-832e-98b4-ec65a525eaee.png)

後は、EvernoteをFranz上でログインすれば使用可能になります！
FranzはElectronで作成されているので個人で他にも色々カスタマイズ出来るので是非試してみてください。
【PlayCanvas】スマホからもconsoleを確認したい

スマホからだとconsole.logは見れません(工夫するとPCから見ることはできます)

PlayCanvas開発環境のデバッグコンソールはスマホからも表示されますが、あそこに直接出力するAPIはありません。
そんな時はconsole.errorを使うことをお勧めします。

```javascript
console.error("hogehoge");
```
階層構造にはなりませんが単純な出力なら十分使えます。
Redmine > 3.1→3.4へバージョンアップ


# Redmine > 3.1→3.4へバージョンアップ

## 環境：

Windows
Bitnami Redmine 3.4.1

基本的には2.x→3.4と同等作業
[Redmine > 1.4→3.4へバージョンアップ \- Qiita](https://qiita.com/sugasaki/items/ebd1d7d3fa2b4752deef)

## 新環境を構築する

Bitnamiのインストーラーで構築する

## ファイルの移行

添付ファイルデータ移行
旧環境の 以下フォルダ配下のデータを
\apps\redmine\htdocs\files
\apps\redmine\htdocs\plugins

新環境の同フォルダへコピーする
\apps\redmine\htdocs\files
\apps\redmine\htdocs\plugins



## Dumpファイルを作成する
ユーザー・パスワードは、
\apps\redmine\htdocs\config\database.ymlに設定がある。
port=3307はdatabase.ymlに設定ある番号に適宜置き換える。

```shell-session
mysqldump -u bitnami --password=xxxxxxx --all-databases  --default-character-set=binary --port=3307 > dump.sql
```


## 新環境にDBインポート
ユーザー・パスワードは、新環境の\apps\redmine\htdocs\config\database.ymlに設定がある。port=3307はdatabase.ymlに設定ある番号に適宜置き換える。
mysql -u bitnami -p bitnami_redmine --password=xxxxxxx --port=3307 < dump.sql


```shell-session
mysql -u bitnami -p bitnami_redmine --password=xxxxxxx --port=3307 < dump.sql
```


## 確認
この時点でサイトにアクセス可能かいちおう確認しておいた方がいい。
トップ画面は表示されるが、プロジェクトの詳細等は表示されない。
この後にマイグレーションを行う。

## マイグレーション

### ルビーの設定
rubyへのパスが通ってなければパスを通す
CMD.exeにて
`setx /M PATH "%PATH%;C:\BitNami\redmine-2.3.1-0\ruby\bin"`

一度CMD.exeを閉じて再度開く
`echo %path%`
でパスを確認

### ①マイグレーション
カレントフォルダをapps\redmine\htdocsへ移動して以下を実行

```shell-session
bundle exec rake db:migrate RAILS_ENV=production
```

ここで以下のようなエラーが出た場合、テーブルの削除を行う。
エラーがでなければ③へ行く

```shell-session
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Table 'imports' already exists: CREATE TABLE `imports` (`id` int(
11) auto_increment PRIMARY KEY, `type` varchar(255), `user_id` int(11) NOT NULL,
 `filename` varchar(255), `settings` text, `total_items` int(11), `finished` tin
yint(1) DEFAULT 0 NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetim
e NOT NULL) ENGINE=InnoDB
```


### ②テーブル削除
新しいコマンドプロンプトを開き、\mysql\binへカレントフォルダを移動する。

`mysql -u bitnami --password=xxxxx --port=3307`
でmysqlへ入り、テーブルを削除

```
USE bitnami_redmine
drop table queries_roles;
```

再度マイグレーションを行う
が、ここでもエラーが出る。

これをエラーがでなくなるまで①と②を繰り返す。
最終的に全てがmigratedされればOK

※環境により削除対象のテーブルが違うようなので、面倒だが１つずつ確かめながらやったほうがよい。

今回削除したテーブル一覧
* import_items
* import_items;
* custom_field_enumerations


### ③プラグインのマイグレーション
カレントフォルダをapps\redmine\htdocsへ移動して以下を実行
`bundle exec rake redmine:plugins:migrate RAILS_ENV=production`
特にエラーなく完了したら成功。


## 完了

旧環境のサービスを停止するか、アンインストールする。
これで完了


## 補足

SMTPの設定
デフォルトでgmailのSMTPが指定してある場合あるので、以下をチェック
redmine/htdocs/config/configuration.yml

適宜、SMTPを変更する。

[Redmine > Install > トラブルシュート > チケット作成・編集が遅い \- Qiita](https://qiita.com/sugasaki/items/2e3d292e8698ce5729d7)
OpenNLPをMacで使用する場合

[こちらのリンク](https://stackoverflow.com/questions/30738974/rjava-load-error-in-rstudio-r-after-upgrading-to-osx-yosemite)を参照すると、以下のコードが紹介されています。

これをターミナルで打ち込めば、library(OpenNLP)をRで打ち込んでも、問題なく作動します。

```r:rjava.r
sudo ln -f -s $(/usr/libexec/java_home)/jre/lib/server/libjvm.dylib /usr/local/lib
```

Reference:
https://stackoverflow.com/questions/30738974/rjava-load-error-in-rstudio-r-after-upgrading-to-osx-yosemite
【質問】四角形の中にダイヤを描写

初めまして。Java初心者です。
下記のように四角形の中にダイヤを描写したいと思っています。
□□□□■□□□□
□□□■■■□□□
□□■■■■■□□
□■■■■■■■□
■■■■■■■■■
□■■■■■■■□
□□■■■■■□□
□□□■■■□□□
□□□□■□□□□

■の出力の仕方まではなんとなく理解でき、
for文のみを使用して下記までコーディングしてみました。

-------------------------------------------------------
public class Study1_3 {
	public static void main(String[] args) {
		for (int i = 1; i <= 10; i += 2) {
			for (int n = 0; n < i; n++) {
				System.out.print("■");
			}
			System.out.println();
		}
		for (int i = 1; i <= 9; i += 2) {
			for (int n = 0; n < 8 - i; n++) {
				System.out.print("■");
			}
			System.out.println();
		}
	}
}

-------------------------------------------------------
あとはif文を使用して、□の部分をコーディングしていくと思うのですが、
なかなかうまくいかず困っています。
どなたかご教授いただけますと幸いです。

-------------------------------------------------------
【追加分】

とても長くなりましたが自分なりに地道にコーディングしてみました。
\\\\\\\\\\\\\\\\\\\\\\
public class Study {

	public static void main(String[] args) {
		// 四角形の中にダイヤ
		for (int i = 1; i <= 9; i++) {
			for (int j = 1; j <= 9; j++) {
				if (i == 1 && j == 5 || i == 2 && j == 4 ||
						i == 2 && j == 5 || i == 2 && j == 6 ||
						i == 3 && j == 3 || i == 3 && j == 4 ||
						i == 3 && j == 5 || i == 3 && j == 6 ||
						i == 3 && j == 7 || i == 4 && j == 2 ||
						i == 4 && j == 3 || i == 4 && j == 4 ||
						i == 4 && j == 5 || i == 4 && j == 6 ||
						i == 4 && j == 6 || i == 4 && j == 7 ||
						i == 4 && j == 8 ||	i == 5 && j == 1 ||
						i == 5 && j == 2 ||	i == 5 && j == 3 ||
						i == 5 && j == 4 ||	i == 5 && j == 5 ||
						i == 5 && j == 6 || i == 5 && j == 5 || 
						i == 5 && j == 7 ||	i == 5 && j == 5 ||
						i == 5 && j == 8 ||	i == 5 && j == 9 ||
						i == 6 && j == 2 || i == 6 && j == 3 || 
						i == 6 && j == 4 ||	i == 6 && j == 5 ||
						i == 6 && j == 6 ||	i == 6 && j == 7 ||
						i == 6 && j == 8 ||	i == 7 && j == 3 ||
						i == 7 && j == 4 ||	i == 7 && j == 5 || 
						i == 7 && j == 6 ||	i == 7 && j == 7 ||
						i == 8 && j == 4 || i == 8 && j == 5 ||
						i == 8 && j == 6 ||	i == 9 && j == 5) {
					System.out.print("■");
				} else {
					System.out.print("　");
				}
			}
			System.out.println();
		}
	}
}
\\\\\\\\\\\\\\\\\\\\\\
もっと簡略的に書く方法や、アドバイスがございましたらご教授ください。
都道府県選択したら連動して市区郡のチェックボックスが出るアレ作ってみた

[都道府県選択したら連動して市区郡が出てくるアレ作ってみた](https://qiita.com/next1ka2u/items/cbbcf1c71c78f5c1fa31)

↑のチェックボックス版。

[アレの動作](http://quiitaplace.php.xdomain.jp/pref_relation.php)
↑こんな感じで動きます。

全部書いてると長くなるのでスパッと書きます。
JSONの準備とか前準備は上の記事見て下さい。
この記事だけじゃ、動かないです。

```css:デザイン苦手だけど参考程度のcss
div#s2 {
    width: 640px;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
input[type="checkbox"] {
    display: none;
}
div.check-group label {
    cursor: pointer;
    padding: 5px 10px;
    float: left;
    border: solid 1px #aaa;
    margin: 4px;
    background: #eee;
    width: 128px;
    text-align: center;
}
div.check-group input:checked+label {
    color: #666;
    background: #99ff99;
}
```

```html:アレの変更、コピペでいいです。
<script>
/* 市区郡一覧のチェックボックスをリセットする関数 */
function cleardivbox() {
    $('#s2').empty();
}

/* 市区郡一覧のチェックボックスを表示するアレ */
$(function(){
        $('#s1').change((function(){
            cleardivbox();
            $.ajax({
                type: 'POST',
                url: 'json/pref.json',
                dataType: 'json',
                success:function(){
                    var selectPref = ('00' + $('#s1 option:selected').val()).slice( -2 );
                    $.getJSON("json/pref.json", function(Pref){
                        for(var i = 0; i < Pref[0][`${selectPref}`].city.length; i++){
                            $('#s2').append('<input id="' + Pref[0][`${selectPref}`].city[i].citycode
                            + '" name="s3[]" type="checkbox" value="'
                            + Pref[0][`${selectPref}`].city[i].citycode + '">'
                            + '<label for="' + Pref[0][`${selectPref}`].city[i].citycode + '">'
                            + Pref[0][`${selectPref}`].city[i].city + '</label>');
                        }
                    })
                },
                error:function(){
                    alert("市区郡の取得に失敗しました");
                }
            });
        }));
    });
</script>
```

JSONファイルにある`citycode`が`value`になっていますので市区郡の文字列を取得したい場合は`citycode`の`code`を取って頂ければ`渋谷区`とか市区郡の文字列で取得できます。

```html:表示領域
<div class="check-group">
    <div name="s2" id="s2"></div>
</div>
```

パーツでコードを載せてるのでもしかしたら動かないとかデザインがおかしいとかあると思いますが動いてるコードを載せてるのでおかしければデザインは自力でなんとかして下さいｗ

ちなみに市区郡一覧で一番長い文字列は「さいたま市」にある3文字の区で8文字が最長です。
「さいたま市大宮区」とかですね。
【PlayCanvas】PlayCanvas製アプリをWebページに組み込む

iframeで組み込み可能です

```html
<iframe src="https://playcanv.as/xxxxxx/" width="640" height="480"></iframe>
```

playcanv.asから呼び出してる場合は、パラメータで?overlay=falseを指定すると、フッターが表示されなくなります。

```html
<iframe src="https://playcanv.as/xxxxxx/?overlay=false" width="640" height="480"></iframe>
```

#余談
1タブで複数ウィンドウ広げるためのページ"quadiframe"を作りました。
https://playcanvas.utautattaro.com/quadiframe.html?tile_x=2&tile_y=2&url=https://utautattaro.com

quadiframe.html?以降のパラメータからiframeの数を調整できます。
tile_x : 横に何ウィンドウ並べるか
tile_y : 縦に何ウィンドウ並べるか
url    : 組み込むURL
RoRでseedファイルを指定して実行したい時。

いつも特定のファイルを指定して実行するときに忘れてしまうのとggってもrake task作ったりする記事が引っかかったりするので備忘録。

```
bundle exec rails r [実行したいseedファイルのpath]
```

とすると実行できる。

例えば以下のようなseedファイルを実行したい時。

```
db/seeds
└── user.rb
```

```
bundle exec rails r db/seeds/user.rb
```

と、するとdb/seeds/user.rbのみ実行することができる。
prependを使ってクラスメソッドをoverrideする

## Why

あるときだけクラスメソッドの挙動を変えたい。
（今回はCIで動かすときだけ挙動を変えるために使いました)

## How

まぁ、ほとんど以下の通りなんですが。
[How to prepend classmethods - Stack Overflow](https://stackoverflow.com/questions/18683750/how-to-prepend-classmethods)

```rb
class SomeClass
  class << self
    def some_classmethod
      "Hello"
    end
  end
end

SomeClass.some_classmethod
#=> Hello

SomeClass.singleton_class.prepend Module.new {
  def some_classmethod
    super + " world"
  end
}

SomeClass.some_classmethod
#=> "Hello world"

### 継承ツリーを確認
SomeClass.ancestors
#=> [SomeClass, Object, Kernel, BasicObject]
SomeClass.singleton_class.ancestors
#=> [#<Module:0x007fa1dd08acd8>, #<Class:SomeClass>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]

```

[#singleton_class](https://docs.ruby-lang.org/ja/latest/method/Object/i/singleton_class.html) に `prepend` するのがポイント。

「[メタプログラミングRuby第２版](https://www.amazon.co.jp/dp/4873117437/)」を読むとこの辺の理解が深まるらしいですよ(積読)

## おまけ

今回は値を渡したくて以下のように書いたんですが、もっと良い方法があったら教えてください。

```rb
# SomeClass の定義は上記の通り

user_name = "John"

SomeClass.singleton_class.prepend Module.new { |mod|
  # define_methodを使って外の変数を参照するメソッドを追加
  mod.send(:define_method, :user_name) do
    user_name
  end

  def some_classmethod
    super + " #{user_name}"
  end
}

SomeClass.some_classmethod
#=> "Hello John"
```
【PlayCanvas】keyやtoken等見せたくないものをpublicプロジェクトで使用するときの対処法

この記事は [PlayCanvas Advent Calendar 2017](https://qiita.com/advent-calendar/2017/playcanvas) の15日目の記事です。
#困る
PlayCanvasは基本オープン&シェアなサービスなので、パブリックプロジェクトは誰でも閲覧/複製できてしまうわけです。
外部ツール等と連携してコード内にAPI keyやtoken等を記載しなければいけないときは多々ありますが、平文で記載していると外部から閲覧されたり複製されて見えないところで再利用されてしまう恐れがあります。

#forumに投げてみた
これを解決するために、attributeにpassword属性を持たせてフォークした際に外れるような仕様にすればよいのでは？と思い投げてみたところそれは意味ないと返事がきました
https://forum.playcanvas.com/t/solved-attribute-password/4579/2

やるならURLに?pass=hogehoge
のようにつなげて使ってね、という回答。わかるけどいちいちめんどくさいですよね。

##ということで作ってみた。
attributeで宣言して、一度使うとwebStorageに格納され、次回以降はそこから参照されるような仕組みを書いてみました

```javascript:password.js
var Password = pc.createScript('password');
Password.attributes.add("pass",{type:"string"});

// initialize code called once per entity
Password.prototype.initialize = function() {
    if(this.pass){
        if(document.domain == "launch.playcanvas.com"){
            localStorage.setItem("pass",this.pass);
        }        
    }else
    {
        if(localStorage.getItem("pass")){
            this.pass = localStorage.getItem("pass");
        }
        else
        {
            window.open('about:blank','_self').close();
        }
        
    }
};
```

実行一度目はpasswordのattributeに入力しておく必要がありますが、以後はwebStorageから参照されるため空にしといてもよいです。誰かがフォークした後はwebStorageに格納されていないためウィンドウが強制終了するような仕組みになっています。
document.domainで開発環境のみ適用するようにしてあるので、デプロイする前はattributeにあらかじめ格納しておく必要があります。