OmniAICreator/Qiita-1.07M huggingface dataset:
Luaをサクッと


Luaという拡張プログラミング言語を知ったので、とりあえずどんな書き方するのかなと思い
まずサクッとLuaを動く環境を作成。
※本当にただ動かすだけですww


# Luaとは
> オブジェクト指向プログラミング、関数型プログラミング、データ駆動型プログラミングもサポートしている。
>拡張言語であるため、Luaは「メイン」プログラムを持たない。 ホストクライアント (エンベッディングプログラム、あるいは単にホスト とも呼ぶ) に 組み込まれて 動くだけである。

ふむふむ。軽量で高速でC言語のホストプログラムに組み込まれる目的なわけか〜。
文法的で面白いのは、関数を変数として扱えるのか〜、ふむふむ。

まあとりあえずで、

環境: macOS


## Luaをインストール&ヴァージョン確認

```bash
$ brew install lua
$ lua -v
Lua 5.3.4  Copyright (C) 1994-2017 Lua.org, PUC-Rio
```

## LuaRocksをインストール
LuaRocksは、パッケージマネージャの1つ。
インストールした後、ホームディレクトリにモジュール等がインストールされるディレクトリを作成。

```bash 
$ brew install luarocks
$ mkdir ~/.luarocks
```


## ライブラリをインストール
CJSON: JSONを扱うライブラリである
LuaFileSystem: ファイルシステムを扱う

```bash
$ luarocks install --local lua-cjson
$ luarocks install --local luafilesystem
```


## test.luaを作成

```lua
local json = require 'cjson'
local lfs = require 'lfs'
local doc_path = "./"
local result
local file
local text
local val
for filename in lfs.dir(doc_path) do
    result =  string.find(filename,"^.*json$")
    if result ~= nill then
        file = io.open(filename,"r");
        io.input(file);
        text = io.read()
        val = json.decode(text)
        io.close(file)
    end
end

print("from JSON File...." ..val.sample)
```

## helloworld.jsonを作成

```json
{ "sample":"Hello World!!!!"}
```

## 実行

```bash
$ lua ./test.lua
```

構成はこんなかんじになった(当たり前だけどw)

```
├── bin
│   ├── json2lua
│   └── lua2json
├── helloworld.json
├── lib
│   ├── lua
│   │   └── 5.3
│   └── luarocks
│       └── rocks-5.3
├── share
│   └── lua
│       └── 5.3
└── test.lua
```

## 出力

```
from JSON File....Hello World!!!!
```





参考:
http://milkpot.sakura.ne.jp/lua/lua51_manual_ja.html#1
https://dev.classmethod.jp/server-side/language/installation_of_lua/
webpack-dev-serverでおれおれSSL証明書を使う方法

webpack-dev-serverで自己署名(独自)SSL証明書を使う場合は、`--cert`にサーバ証明書、`--key`にその秘密鍵を渡す。

```
webpack-dev-server \
  --config webpack.development.js \
  --hot \
  --host 0.0.0.0 \
  --https \
  --cert=localhost.crt \
  --key=localhost.key
```

独自SSL証明書自体の発行については『[おれおれ認証局になっておれおれSSL証明書を発行してやる方法 - Qiita](https://qiita.com/suin/items/37313aee4543c5d01285)』を参照。
Project Euler Q69 【トーティエント関数の最大値】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
オイラーのトーティエント関数, $φ(n)$ [時々ファイ関数とも呼ばれる]は, $n$ と互いに素な $n$ 未満の数の数を定める. たとえば, $1, 2, 4, 5, 7,$ そして$8$はみな$9$未満で$9$と互いに素であり, $φ(9)=6.$

|$n$|互いに素な数|$φ(n)$|$n/φ(n)$|
|:---|:---|:---|:---|
|$2$|$1$|$1$|$2$|
|$3$|$1,2$|$2$|$1.5$|
|$4$|$1,3$|$2$|$2$|
|$5$|$1,2,3,4$|$4$|$1.25$|
|$6$|$1,5$|$2$|$3$|
|$7$|$1,2,3,4,5,6$|$6$|$1.1666...$|
|$8$|$1,3,5,7$|$4$|$2$|
|$9$|$1,2,4,5,7,8$|$6$|$1.5$|
|$10$|$1,3,7,9$|$4$|$2.5$|

$n ≤ 10$ では $n/φ(n)$ の最大値は $n=6$ であることがわかる.

$n ≤ 1,000,000$で $n/φ(n)$ が最大となる値を見つけよ.

## アプローチ
全て計算しようとするとものすごい時間がかかる。
どうにかして計算する量や対象を減らす必要がある。

$n≤1000$や$n≤10000$で実際にやってみると、求めるべき$n$は
「素因数分解したときにより多くの因数を持つ」ことが予想される。
※あくまで予想であり、特に根拠はない。

よって、まず素因数分解をおこない、因数の数が最大である値にだけ互いに素である値の数をカウントする。

$n≤10$のとき、$n=6$　因数の種類：$2(2,3)$
$n≤100$のとき、$n=30$ or $60$ or $90$　因数の種類：$3(2,3,5)$
$n≤1000$のとき、$n=210$ or $420$ or $630$ or $840$　因数の種類：$4(2,3,5,7)$
・・・

## 解答

```bash
time seq 2 1000000 |
factor |
awk '{delete a;printf $1*1" ";for(i=2;i<=NF;i++){a[$i]=1};for(k in a){printf k" "};print ""}' |
awk '{print $1,NF-1}' |
sort -k2,2nr |
awk 'NR==1{max=$2} $2==max{print}' |
awk '{for(i=1;i<$1;i++){print $1,i}}' |
awk '{a=$1;b=$2;r=a%b;while(r!=0){a=b;b=r;r=a%b};if(b==1){c[$1]++};print $2,c[$1],$1}' |
sort -k3,3n -k1,1nr |
uniq -f2 |
awk '{print $3,$3/$2}' |
sort -k2,2n -k1,1nr |
tail -1 |
awk '$0=$1'
510510

real    1m44.113s
user    2m11.793s
sys     0m1.152s
```

解き終わって調べてみると、素数をかけたものが答えになるようす。
それをふまえると、

```bash
time seq 20 |
factor |
awk 'NF==2{print $2}' |
head -7 |
awk 'BEGIN{a=1} {a*=$1} END{print a}'
510510

real    0m0.006s
user    0m0.001s
sys     0m0.009s
```

## 答え合わせ
こちらのサイト様と一致していればOKとした。
[Project Euler 69 _ nとφ(n)の比 - PEをMathematicaで](http://variee.hatenadiary.com/entry/2017/03/16/011552)

## 参考にさせて頂いたサイト様
[Project Euler 69 - maple0705のブログ](http://maple0705.hatenablog.jp/entry/2017/08/11/230611)
Firebase storageでのグループ認証

最近Firebaseを使うことが多くなったのですが，グループ認証に悩んだのでメモしときます．


##グループ認証の方法
Firebase databaseのデータを直接Storageが参照できればいいのですが，それはできません．
なので，仲介役としてAuthのCustomClaimを使います.

CustomClaimは本来，有料会員のフラグを保存したりするものらしいので，チョット使い方が違うような気もしますが，Storageから参照できるものが他にないのでこれを使います．

（一応，[公式ドキュメント](https://firebase.google.com/docs/storage/security/user-security?hl=ja)にもこの手法で書いてありました）

##作り方

###前提
Firestore databaseにユーザー情報があったとします．

```
{ 
  users:{
    userA :  {
      groups : {
        groupA : true
        groupB : true
      }  
    }，
    userB :  {
      groups : {
        groupB : true
        groupC : true
      }  
    }
  }
}
```



この情報をuserAはuserAのCustomClaimに，userBはuserBのCustomClaimにいれます．
CustomClaimはadmin権限がないといじれないので， Cloud Functionsで実行します．


### cloud functionの設定
```javascript:index.js

exports.updateUserGroupGrant = functions.database.ref('/users/{userId}/groups')
    .onWrite(event => {
      return refreshCustomClaims(event.params.userId);
    });

function refreshCustomClaims(userId){
  return admin.database().ref('/users/' + userId + "/groups").once('value').then((snapshot) => {
    var claim = {};
    for (var key in snapshot.val()){
      claim[key] = true;
    }
    return admin.auth().setCustomUserClaims(userId, claim);
  });
}
    
```

databaseを監視し，`/users/{userId}/groups`が何か変化あったら｀`refreshCustomClaims`を呼びます

`refreshCustomClaims`では引数で渡された`userId`のclaimを作成し，`admin.auth().setCustomUserClaims`で保存しています


### strageの設定
Strageのルールでは`request.auth.token`でclaimが取れるので，そこの値を使って認証します．
`request.auth.token[groupId]`と言う書き方で変数を組み込むことができます
※ドキュメントの記載を見つけられていないので，動作保証はされないかもしれません

```text:strage.rules
service firebase.storage {
  match /b/{bucket}/o {
    match /groups/{groupId} {
       match /{path=**} {
          allow read, write: if request.auth!=null
                            && request.auth.token[groupId] == true;
       }
    }
  }
}

```

これでdatabaseを使ってstrageでの認証ができました．

##注意点
claimは認証以外に使わないでください（データは入れないでください）と公式ドキュメントに書いてあります．
今回のは認証に使っているので違反しているわけではないのですが，データに対応していない＝たくさん情報を詰め込むことを想定していない　ということだと思うので，
大量のグループがある場合，この方法はちょっと見直さないといけないかもしれません．
AndroidStudio3.0の新機能を使ってSQliteの中身を見る

Android Studio3.0から端末内部を簡単見ることができるようになりました。

そこで今回はsqliteで作成されたローカルDBを見てみます。


## Device File Explorer

右下の「Device File Explorer」を開くとデバイスの中身を見ることができます

![スクリーンショット 2018-01-29 16.40.54.png](https://qiita-image-store.s3.amazonaws.com/0/139360/94d95e01-6eb5-2e8a-8d8e-67522fb4b7b6.png)

↑のアイコンを開くと下記のようなタブが開きます。(念のため中身を隠しておきます)

![スクリーンショット 2018-01-29 16.41.21.png](https://qiita-image-store.s3.amazonaws.com/0/139360/ac74a8ee-6143-6ade-246c-80c7656fc35b.png)


そこから中からアプリを探します

`/data/data/<みたいアプリのパッケージ名>/databases/<DB名>` 

だいたいのアプリは↑のパスにあります。

データベースを右クリックからローカルにコピーしてSQLiteの中をいい感じに見れるソフトを使って開くと中身がみれます。
自分は下記を使いました。

http://sqlitebrowser.org/
FragmentからSQLiteDatabaseを使う

quick memo
結論: `getActivity()`を使う

```java:MyDbhelper.java
public class MyDbHelper extends SQLiteOpenHelper {

public MyDbHelper(Context context) {
    super(context, DBNAME, null, VERSION);
}

// 以下略
```

```java:MyFragment.java
MyDbHelper helper = new MyDbHelper(getActivity()); 
```
Google Cloud Speech API を使って音声ファイルをバッチ処理で文字化する

# 概要

16khz16bitのPCM音声ファイルをGoogle Cloud Speech APIで文字化する方法です。
Google Cloud Speech APIは以下の利用方法があるようです。
① Google Cloud Storage の音声を文字化する方法
② HTTPSでPOSTした音声を文字化する方法
今回はお手軽に利用できるように「②HTTPSでPOSTした音声を文字化する方法」でやってみます

# API key の取得とサービスのアクティブ化

https://codelabs.developers.google.com/codelabs/cloud-speech-intro-ja/index.html?index=..%2F..%2Fsc16#0

上記資料を参考にCloud Speech APIの有効化とAPI keyの取得を行う

※上記資料ではGoogle Cloud Storageの音声を文字化していますが、request.jsonのaudio->url を利用せずにaudio->contentにbase64エンコードした音声データを入れることで、Google Cloud Storage を利用しなくても音声文字化が可能です

# サンプルソース

フォルダ内の音声ファイルをBase64エンコードしてGoogle Cloud Speech APIを実行するPHP

```
<?php
$audioFileFolder = $argv[1];
$audioFiles = array();
foreach(glob($audioFileFolder . '/*') as $file){
    if(is_file($file)){
        $audioFiles[] = htmlspecialchars($file);
    }
}

$jsonArray = array();
$jsonArray["config"]["encoding"] = "LINEAR16";
$jsonArray["config"]["sampleRateHertz"] = 16000;
$jsonArray["config"]["languageCode"] = "ja-JP";
$jsonArray["config"]["enableWordTimeOffsets"] = false;

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://speech.googleapis.com/v1/speech:recognize?key=<取得したKey>");
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);

foreach($audioFiles as $audioFile){
	$jsonArray["audio"]["content"] = base64_encode(file_get_contents($audioFile));
	curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($jsonArray));
	$response = curl_exec($curl);
	$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); 
	$header = substr($response, 0, $headerSize);
	$body = substr($response, $headerSize);
	$result = json_decode($body, true); 
	
	echo $audioFile . "\t" . $result["results"][0]["alternatives"][0]["transcript"] . "\n";
}
```

上記のPHPを実行するsh

```
#!/bin/bash
php googleCloudSpeechApi.php audio
```

# [おまけ]Google Speech API とGoogle Cloud Speech API

Google Speech APIとGoogle Cloud Speech APIは別物のようです。

## Google Speech API

+ 研究目的、個人用途
+ 利用回数制限あり（1日数百回？）
    + 制限に引っかかったらしばらくほっとけば復活（12時間～1日くらい？）
 
## Google Cloud Speech API

+ 従量課金
+ cloud storage の音声や、HTTPSでPOSTした音声を文字化する
SQLの実行計画を確認する際に使うSQL諸々


##indexの確認
```
MySQL [xxx]> show index in t_table;
+---------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table         | Non_unique | Key_name         | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t_table |          0 | PRIMARY          |            1 | id      | A         |       20048 |     NULL | NULL   |      | BTREE      |         |               |
| t_table |          1 | index |            1 | id2  | A         |       20048 |     NULL | NULL   | YES  | BTREE      |         |               |
+---------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
```
##indexの追加
###単一index
```
ALTER TABLE t_table ADD INDEX index(created);
```
###複合index
単一の際と構文変わらず。

```
ALTER TABLE t_table ADD INDEX index_multi(created_at, updated_at);
```
##indexの削除
```
DROP INDEX  index_name ON tbl_name
```
https://dev.mysql.com/doc/refman/5.6/ja/drop-index.html
##queryの確認
実行クエリの確認

```
MySQL [xxx]> select * from INFORMATION_SCHEMA.PROCESSLIST order by id desc limit 10\G;
*************************** 1. row ***************************
     ID: 599155
   USER: admin
   HOST: 127.0.0.1:54267
     DB: xxx
COMMAND: Query
   TIME: 0
  STATE: executing
   INFO: select * from INFORMATION_SCHEMA.PROCESSLIST order by id desc limit 10
```

##実行計画の確認
この辺見ればいい感じかなー。
主にtypeを見ていたり。
あとはpossible_keysとkeyの差異とか。ここを絶対に合わせたい場合はヒント句とか使えばいいんだけど、そもそもの話、実行計画を取得する元データがおかしいとか、indexの考え方が誤ってるとかそういう場合のほうが多いように思う。
https://qiita.com/kzbandai/items/ea02727f4bb539fcedb5
http://woshidan.hatenablog.com/entry/2015/06/20/165817
https://dev.mysql.com/doc/refman/5.6/ja/explain-output.html
linux > link > kill -0 ... > if ! kill -0 $(cat /path/to/file.pid); then

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
gcc version 4.4.7 (とgfortran)
NCAR Command Language Version 6.3.0
WRF v3.9を使用。
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

RTOS付きの組込みプログラムでタスク周りの不具合を見つけた。

関連してlinuxのkillを調べたところ、以下を見つけた。

[What does `kill -0` do?](https://unix.stackexchange.com/questions/169898/what-does-kill-0-do)
> answered Nov 25 '14 at 17:50
slm

`kill -0`とすることで以下のようにすることができる、とのこと。

> So signal 0 will not actually in fact send anything to your process's PID, but will in fact check whether you have permissions to do so.

許可がなければ`bash: kill: (15693) - Operation not permitted`になるという例が紹介されている。
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

# SSHでログインできない　Permission denied (publickey,gssapi-keyex,gssapi-with-mic).


SSHでログインできなくなりました。

下記でログインできなくなった場合

ログを確認します。

```
tail /var/log/secure
```

```
Jan 31 19:53:43 ik1-316-18051 sshd[28579]: Authentication refused: bad ownership or modes for directory /home/user_name/.ssh
```

権限的な何かが巻き起こってます。

まきおこりです。

なので、

下記実行します。

```
chmod 0700 ~/.ssh
chmod 0600 ~/.ssh/authorized_keys
```

これでいけるはずとクライアント側から再度実行

```
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

⚠️　FUCK!　⚠️

そんな気持ちです、、、

悩んで、、、

んっ！

home のディレクトリーの権限を確認してみました。

```
pwd /home/user_name/
drwxrwxrwx 8 user_name user_name 4096 Jan 29 15:34 user_name
```

なにっ！

７７７だ！

まずいのでは、

正確には0700ではと思い、変更、

```
chmod 700 user_name
ls -ll 
drwx------ 8 user_name user_name 4096 Jan 29 15:34 user_name
```

これで再度実行

```
->> ssh vps
Last login: Mon Jan 29 15:34:42 2018 from shichimitoucarashi.com

 _____ _   _ _____  _____  _____ _____ _____                             
/  ___| | | /  __ \/  __ \|  ___/  ___/  ___|                            
\ `--.| | | | /  \/| /  \/| |__ \ `--.\ `--.
 `--. \ | | | |    | |    |  __| `--. \`--. \
/\__/ / |_| | \__/\| \__/\| |___/\__/ /\__/ /
\____/ \___/ \____/ \____/\____/\____/\____/ 

```

成功です。

悲願達成になりました。

おめでとう
ASP.NET Web APIのOData v4でつまづいたところ

基本的には[ASP.NET Web API の OData v4 のサポート](https://docs.microsoft.com/ja-jp/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/)を参考にしていたが、詰まったところがあったので、メモ。

#クエリオプションを付けるとエラーになる

初期設定とContoller側の設定を両方やらないと効かない場合がある。
初期設定で全般的な使用許可を与えて、個別に設定するイメージかな？

## 初期設定
追加したいクエリオプションが\$count、\$filter、\$orderby、\$expand、\$selectの場合には、WebApiConfig.csで、各種オプションを有効にする。

```c#:WebApiConfig.cs
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            ODataModelBuilder builder = new ODataConventionModelBuilder();
            // エンティティを追加
            builder.EntitySet<Customer>("Customers");
            // オプションを有効化 ↓この行を追加（必要なものだけでOK）
            config.Count().Filter().OrderBy().Expand().Select().MaxTop(null); 
            // 
            config.MapODataServiceRoute(
                routeName: "ODataRoute",
                routePrefix: null,
                model: builder.GetEdmModel());

        }
    }
```

各オプションは[System.Web.OData.Extensions.HttpConfigurationExtensions](https://github.com/OData/WebApi/blob/master/src/System.Web.OData/Extensions/HttpConfigurationExtensions.cs)で定義されている。

## Contoller側の設定
GetメソッドにEnebleQuery属性を追加し、許可したいクエリオプションをAllowedQueryOptionsで指定。
各オプションは「|」で結合

```c#:Contoller
        [EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Count | AllowedQueryOptions.Skip)]
        public IQueryable<Customer> Get()
        {
            return db.Customer;
        }
```
Angularによるフロントエンド開発とAPI開発を同時に行う

Angularでフロントエンド開発する際に"ng serve"コマンドを使うと便利なのは周知の事実。
バックエンドAPIを代替する手段は用意されているとはいえ、実際のバックエンドを使いたい(バックエンドも同時にデバッグしたい)場合、nginxのリバースプロキシを使って開発環境を作るとうまくいく。

せっかくnginxを使うので、https化(Webカメラにアクセスする場合などは必須)やjavascript,jsonなどのgzip圧縮にも対応させておくことにする。

###想定するアプリケーション
https://{hostname}/{application-path}/  　　      … いわゆるindex.htmlが呼び出されるURL
https://{hostname}/{application-path}/rest/  　　 … バックエンドのAPIへのURL
 ※JavaEEアプリケーションだと上段がWebContent配下になり、下段がJAX-RSのベースURLになる

###フロントエンド/バックエンドそれぞれのサーバを立ち上げる
バックエンドサーバのAPI: `http://127.0.0.1:8080/{application-path}/rest/*`
フロントエンドサーバは "ng serve --base-href=/{application-path}/"で立ち上げる
 ※--base-hrefでフロントエンドサーバ側とURLを合わせる

###オレオレ証明書(笑)の作成
`$ openssl genrsa 2048 >server.key`
`$ openssl req -new -key server.key >server.csr`
`$ openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt`
作成した３つのファイルはnginxのconfディレクトリに置いておく

###nginxの設定
ここでは{application-path}として"operation"としている

```nginx.conf
worker_processes            1;

events {
    worker_connections      1024;
}

http {
    include                 mime.types;
    default_type            application/octet-stream;

    sendfile                on;
    tcp_nopush              on;
    keepalive_timeout       0;

    gzip                    on;
    gzip_http_version       1.1;
    gzip_types              text/css application/javascript application/json;
    gzip_proxied            any;

    server {
        listen              443;
        server_name         127.0.0.1;
        ssl                 on;
        ssl_certificate     server.crt;
        ssl_certificate_key server.key;

        charset utf8;

        proxy_set_header    Host                  $host;
        proxy_set_header    X-Real-IP             $remote_addr;
        proxy_set_header    X-Forwarded-Host      $host;
        proxy_set_header    X-Forwarded-Server    $host;
        proxy_set_header    X-Forwarded-For       $proxy_add_x_forwarded_for;
        proxy_http_version  1.1;
        proxy_set_header    Upgrade               $http_upgrade;
        proxy_set_header    Connection            "upgrade";
        proxy_force_ranges  on;

#APIへのアクセスはAPサーバ(port:8080)へ
        location /operation/rest/ {
            proxy_pass    http://127.0.0.1:8080/operation/rest/;
        }
        
#index.htmlやjavascriptへのアクセスはwebpack-dev-server(port:4200)へ
        location /operation/ {
            proxy_pass    http://127.0.0.1:4200/operation/;
        }
#websocketの通信はwebpack-dev-server(port:4200)へ
        location / {
            proxy_pass    http://127.0.0.1:4200/;
        }
    }
}
```
上記、windows版のnginxのconfファイル。
Linux版の場合には証明書ファイルのパスをフルパスで書く。(/etc/nginx/conf.d/***)

###nginxを立ち上げてアクセスしてみる
`"https://127.0.0.l/{application-path}/"`にアクセスしてみる。
main.bundle.jsなどのjavascriptファイルやAPIからのJSONファイルのResponseHeaderを見た時、
"Content-Encoding:gzip"となっていればgzip圧縮されている。

###アプリケーションのデプロイ
ng serveと同様に、"ng build --base-href=/{application-path}/"としてフロントエンドをビルド。
ターゲットパス(デフォルトだとdistというディレクトリ)に出力されたファイル一式を、バックエンド側の"WebContent"配下にコピー。
バックエンドのアプリケーションをwarとしてexportし、本番サーバにDeploy!
【Redux】ストアの状態をリセットする

会員サイトでログアウトした場合などに、Reduxのstoreをリセットしたい。
リセットしないと、そのまま違うアカウントでログインしたときにいろいろ困る。

## reducer単位でクリアするパターン

```store.js

import { createStore, combineReducers } from "redux";

import a from "./reducers/a";
import b from "./reducers/b";

const rootReducer = combineReducers({
    a,
    b
});

export default createStore(rootreducer);
```

```reducer/a.js

export const registerName = name => {
	return {
		type: "INSERT_NAME",
		name: name
	}
}

export const registerAge = age => {
	return {
		type: "INSERT_AGE",
		age: age
	}
}

// ここにクリアアクションを追加
export const clearState = () => {
	return {
		type: "CLEAR_STATE"
	}
}

const initialState = { name: "", age: ""}

export default reducer(state = initialState, action) {

	switch(action.type) {
		case "INSERT_NAME": 
			return {
				...state,
				name: action.name
			}
		case "INSERT_AGE": 
			return {
				...state,
				age: action.age
			}
		case "CLEAR_STATE": 
			return initialState
		default:
			return state
	}
}

```

reducer/b.jsでも同じことをする

## stackoverflowにあったイケてるやつを参考にしたパターン

参考：[stackoverflow](https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store)

```store.js
import { createStore, combineReducers } from "redux";

import a from "./reducers/a";
import b from "./reducers/b";

const appReducer = combineReducers({
    a,
    b
});

const rootReducer = (state, action) => {
    if (action.type === "CLEAR_STATE") {
        state = undefined;
    }
    return appReducer(state, action);
};

export default createStore(rootreducer);
```

素晴らしいね！！
captionの書式を変更せずにsubcaptionを使用する

## はじめに

LaTeXでsubcaptionパッケージを使用したときにcaptionの書式まで変わってしまう、という問題に対する解決策を調べた。
日本語で調べても答えが見つからなかったので、忘れないうちにここにメモしておく。

## 問題

とある学会に提出する論文を書いていた時のこと。
figure環境内に図を並べようと思いプリアンブルに`\usepackage{subcaption}`と書いたところコンパイルエラーを吐いた。じゃあこれならどうだと試したところ……

```LaTeX
\usepackage{subcaption}
\captionsetup{compatibility=false}
```

今度はコンパイルはできたものの、キャプション内のフォントや書式が指定されたスタイルファイルとは異なって出力されてしまう。どうやらsubcaptionパッケージを読み込む際に、既存のキャプションの挙動が変わってしまうらしい。

subcaptionではなくsubfigパッケージを使って`\usepackage[caption=false]{subfig}`とすれば、キャプションに影響を与えずに使用できるらしい(?)。しかしsubfigは今や非推奨とされている[^使ってはいけない]ようで、できればsubcaptionでなんとかしたい。

## 解決策

参考: https://tex.stackexchange.com/questions/154435/ieee-template-and-caption-false-option-for-subcaption-package/288401

`\usepackage{subcaption}`を実行する際に、キャプション関連の既存のコマンドが上書きされないように一時退避させておけばいいらしい。

```LaTeX
\makeatletter
\let\MYcaption\@makecaption
\makeatother

\usepackage{subcaption}
\captionsetup{compatibility=false}		% 必要に応じて

\makeatletter
\let\@makecaption\MYcaption
\makeatother
```

これで指定された書式に従いつつサブキャプションを使用できる。

[^使ってはいけない]: [使ってはいけない LaTeX のコマンド・パッケージ・作法](http://ichiro-maruta.blogspot.jp/2013/03/latex.html)
NodeREDからのHTTPリクエストにStaticaを利用する


#はじめに
###Staticaとは？
IBM Cloud(旧Bluemix)で提供されているサードパーティ制のプロキシサーバーです。
IBM Cloudではアプリケーションの再起動などでIPアドレスがその都度変わるため、
ホワイトリストが設定されているようなAPIやシステムを利用するにはひと工夫いります。
そこで便利なのがStaticaです。

#手順
###Staticaの準備
IBM Cloudのカタログから、Staticaのサービスを作成する
![カタログ_-_IBM_Cloud.png](https://qiita-image-store.s3.amazonaws.com/0/143517/30bf5de5-0096-0e33-921e-3b4488f6f0a7.png)

ダッシュボードからプロキシサーバーのアドレスをメモする
![Statica.png](https://qiita-image-store.s3.amazonaws.com/0/143517/7c71159d-c992-e4de-f1e3-aa10f76b552a.png)

###NodeREDの準備
右上のハンバーガーメニューからパレットの管理をクリック
![Node-RED___uchino-nodered_mybluemix_net 5.png](https://qiita-image-store.s3.amazonaws.com/0/143517/fb906bd3-973b-f972-b801-133c3197ecc7.png)

"node-red-contrib-http-request"ノードを追加する
![Node-RED___uchino-nodered_mybluemix_net 6.png](https://qiita-image-store.s3.amazonaws.com/0/143517/6027f09f-74a9-4f0d-0909-8b5adda631e1.png)

この追加ノードの說明にはこうあります。
>Note: If you need to configure a proxy please add http_proxy=... to your environment variables and restart Node-RED.

つまり、NodeRED Starterの環境変数に"http_proxy=<Staticaのアドレス>"を設定すればOKです。
ちなみに追加したノードは、`www request`という名前で「機能」カテゴリにあります。

###環境変数の設定
NodeREDのアプリケーションの`ランタイム`から`環境変数`タブをクリックする
![アプリケーションの詳細_-_IBM_Cloud.png](https://qiita-image-store.s3.amazonaws.com/0/143517/aaa5c4bb-2716-38dd-b8d4-3b0efafed9a0.png)

下にスクロールしていくと`ユーザー定義`で環境変数を独自に定義できます。
下図のように設定しましょう。
![アプリケーションの詳細_-_IBM_Cloud 2.png](https://qiita-image-store.s3.amazonaws.com/0/143517/365ae1c4-ff29-ff5b-441f-e104940d597c.png)

###動作確認
`www request`を使用してHTTPリクエストを送信するとStaticaのダッシュボードで正常にStaticaを経由してリクエストがされているかが確認できます。
![スクリーンショット_2018_01_29_15_06.png](https://qiita-image-store.s3.amazonaws.com/0/143517/2509e123-6d17-f0fd-57de-18008d91950c.png)

###おわりに
最近だと、LINEのチャットボットを作る際に使用しました。
ホワイトリストの設定が必須のため、Staticaを使用しなければアプリの再起動のたびにIPアドレスを取得してホワイトリストを上書きするという手間がありました。
Spring boot の i18n 対応で message.properties をデフォルトとするには spring.messages.fallback-to-system-locale: false が必要

Spring Boot のアプリで多言語対応をしていて、 `message.properties`の値が使われず`jp`の値が使われなくて困ったのでメモ。
デフォルトの設定だと、言語ファイルが存在しない場合サーバのシステム言語がデフォルトとして使われる。

この挙動は`spring.messages.fallback-to-system-locale`がデフォルトで`true`になっているため。
これを`false`にすると、言語ファイルが存在しないlocaleの場合は`message.properties`の値が使われる。
wrkでのhttp ベンチマーク測定時のbasic 認証をluaスクリプトで行う.

[wrk](https://github.com/wg/wrk) を使って、httpベンチマークを測定する場合に、測定先にbasic認証を必要とする場合、以下のようなluaスクリプトを指定し、認証させます。
利用した [wrk](https://github.com/wg/wrk) のバージョンは、 `4.1.0` です。 

* Basic認証用 luaスクリプト

```lua
wrk.headers["Authorization"] = "Basic {base64文字列}"
```

* 実行方法

`-s` オプションでluaスクリプトのパスを指定します.
上のBasic認証用luaスクリプトを、 `BasicAuth.lua` として保存しておきます。


```
wrk --latency -t2 -c40 -d3s -s ./BasicAuth.lua 'https://domain/xxxxx'

```

luaスクリプトに記載する `base64文字列` は、 `username:password` を `base64` 化した値です。

```
 echo -n 'username:password' | base64 -w 0
```

通常であれは、urlに埋め込んで、認証させますが、認証を通過できなかったので、luaスクリプトで回避しました。

curlなら、これでhttpステータス 200が返ってくる。

```
curl 'https://username:password@domain/xxxxx'
```

wrkで同様の指定をしても、200応答にならず..

```
# NG
wrk --latency -t1 -c1 -d1s 'https://username:password@domain/xxxxx'

# NG
wrk --latency -t1 -c1 -d1s -H"Authorization:Basic ${base64文字列}" 
 'https://domain/xxxxx'
```

また、wrkでの測定結果でのhttpステータスは、200とそれ以外で丸められてしまう為、200以外の何番で応答しているのか細かく知ることができません。200番以外の値を確認する場合は、以下のようなluaスクリプトを記載して、細かく出力する必要があります。

* httpステータスを出力するluaスクリプト

```
function response(status, headers, body)
   local msg = "status: %d"
   print(msg:format(status))
end
```

上のスクリプトは、標準出力に1アクセスごとのhttpステータスが出力するので、httpステータスの応答結果を分析する場合は、shell等で分析.

```
wrk --latency -t1 -c1 -d1s -s ./httpResponse.lua 'https://domain/xxxxx' |  tee out.log | grep 'status:' | cut -d':' -f2 | sort | uniq -c
```
Elasticsearchのpainless scriptをElasticsearchに保存する。


AWSのAmazon Elasticsearch Serviceでは、ファイルに保存したscriptの呼び出し等対応していませんでしたが、version5.5以上では、scriptのstoreに対応しています。これにより毎回queryに記載していたscriptを簡素化して呼び出すことができます。

この機能を使って、Elasticsearchの painless  script をElasticsearch側に保存し、検索時には、idで呼び出せるようにします。

保存するscriptは、以前記載した [Elasticsearchに登録した生年月日から現在の年齢を算出する.](https://qiita.com/stoneriverheart/items/62d592fae662ffc607ed) を使います。

### scriptの保存

scriptの保存は、 `_script/{id}` で行います。

```
POST _scripts/script-age
{
  "script": {
    "lang": "painless",
    "code": "Date n = new Date(); Date b = new Date(doc['birthday'].value); DateFormat f = new SimpleDateFormat('yyyy-MM-dd'); return Period.between(LocalDate.parse(f.format(b)), LocalDate.parse(f.format(n))).getYears();"
  }
}
```

`_script` の後ろに指定した値が `id` として扱われる為、 `id` の管理は、利用する側で行う必要があります。

### 保存したscriptを使った検索

保存したscriptを利用する場合は、 scriptで `stored` : `id` を指定します。

```
GET {index}/{type}/_search
{
  "script_fields": {
     "age": {
       "script": {
         "stored": "script-age"
       }
     }
   }
}
```

### scriptの参照

保存した script を参照する場合は、 `GET` で `_script` を呼び出します。

```
GET _scripts/script-age
```

### scriptの削除

script を削除する場合は、 `DELETE` で `_script` を呼び出します。

```
DELETE _scripts/script-age
```

queryに直接記載されたscriptを分離することで、search queryの記述を簡素でき、script単独で管理できるようになります。

本家マニュアル
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/modules-scripting-using.html#modules-scripting-stored-scripts

あとは、保存したscriptの一覧取得が欲しいところですが、バージョン5.5では、対応するapiはなさそうです。。
Webアノテーション活用法

## Web Annotationって何？
[Web Annotation Data Model](https://www.w3.org/TR/annotation-model/)
1.Webサイトや画像に注釈やタグをつけるためのW3Cによって定義された規格
2.異なるハードウェアやソフトウェアプラットフォーム上で共有や再利用をする事を可能にする為のデータ構造モデルを表している

## Web Annotationで何ができるの？
オンラインで作業する遠隔チームと迅速に効率的なフィードバックを共有可能
従来メールやチャットチケットなどでやり取りしていた問題を効率化

## Web Annotationツールを使おう！
[こちら](https://www.hongkiat.com/blog/top-web-annotation-and-markup-tools/)のURLを参考にWebAnnotationツールを紹介したいと思います。

個人的にはチケット管理でQAをするのに機能要件意外のチケット(デザインや誤字脱字関連)に関する項目が多いのでそこの効率化の為に導入できないかなと思います。

### [Scribe](https://www.scrible.com/)
PDFにそのまま注釈づけをしてチームで共有できるので非常に便利です。
W3Cで定義された事でPDFの資料が全部WEBになればいいのにと思います。

### [Pundit Annotator](https://www.hongkiat.com/blog/top-web-annotation-and-markup-tools/)
ChromeExtentionをインストールして使います。
記事の校正とかには使えそうですね。あんまり機能は多くないかも・・・・

![スクリーンショット 2018-01-29 14.38.05.png](https://qiita-image-store.s3.amazonaws.com/0/89997/fa0a12c2-d983-496b-8319-c875e7a74433.png)

### [Notable Extension](https://notableapp.com/)
ChromeExtentionをインストールして使います。30日無料ですがその後有料です。

1.URLから画像を一括キャプチャしたり、Image/PDFのアップロードツールがある
2.チームで使える
3.キャプチャ画像ベースでコメント記述できるのでデザイン修正などには最適
4.iPhoneアップローダーがあるのだが日本のiTunesストアで使えない(残念すぎ)

![スクリーンショット 2018-01-29 14.51.32.png](https://qiita-image-store.s3.amazonaws.com/0/89997/6f47abce-b21c-d873-07a8-27808040cb3c.png)

有料だけどNotable Extensionが良かったかな。
少しでも無駄なチェック作業とかを楽にしたいものです。

### おまけ
[Medium](https://itunes.apple.com/us/app/medium/id828256236?mt=8)というウェブアノテーションを利用した記事共有アプリがあるのですがこちらが記事の品質も高く

<img width="414" alt="IMG_4140.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/89997/59d82c6c-194d-ca69-9303-a6c0fa82cc92.png">
記事にハイライトをつけてコメントをしていく事ができます。
FBでシェアしてディスカッションしたりできます。
ハイライトのガイドラインは[下記](https://help.medium.com/hc/en-us/articles/214406358-Highlight)に記載の通り自分のフォロワーにのみハイライトが見られる様になっています。
[Android][Kotlin]JavaScriptと相互通信

WebViewでJavascriptとKotlinの双方向通信を行う方法です。

# JavascriptからKotlinのメソッドを実行する
## 基本的な使い方
### Kotlin
`webChromeClient`の `onJsAlert`を使用してJavascriptのalertに渡された文字列を受け取ります。
戻り値のBooleanでAlertViewの表示を制御します。
true: 表示しない, false: 表示する
※AlertViewを表示しない場合、見た目上は表示されていないのですが、透明なAlertViewが表示された状態となっているようでそのままだと操作不能になってしまうため、 `result.cancel()`でAlertのキャンセルを実行してAlertViewを閉じる必要があります。
Javascriptのalertに渡した文字列はmessageで受け取っています。

```kotlin
webView = findViewById(R.id.webView) as WebView
webView.setWebChromeClient(object : WebChromeClient() {
  override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean {
    if (message == 'hoge') {
      // do something
    }
    result.cancel()
    return true
  }
})
```

### Javascript
通常のalertと同じように実行します。

```Javascript
alert("hoge");
```

## 値を受け渡したい場合
受け渡せるのは文字列のみなので、値を渡したい場合は少し工夫が必要です。
私の場合は「:」をセパレータにして `メソッド名:変数1:変数2:...` のようにして渡しています。

### Kotlin
```Kotlin
webView = findViewById(R.id.webView) as WebView
webView.setWebChromeClient(object : WebChromeClient() {
  override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean {
    val components = message.split(":")
    if (components[0] == 'hoge') {
      val number = components[1]
    }
    result.cancel()
    return true
  }
})
```

### Javascript
```Javascript
var number = 123;
alert("hoge:" + number);
```

# KotlinからJavaScriptのメソッドを実行する
## 基本的な使い方
### Kotlin
`evaluateJavascript` を使用してJavascript側で拡張したwindowオブジェクトを呼び出します。

```Kotlin
webView.evaluateJavascript("window.hoge()", null)
```

### Javascript
windowオブジェクトを拡張することでKotlin側からの呼び出しを受け付けます。

```Javascript
window.hoge = function() {
  // do something
}
```

## 値を受け渡したい場合
通常のメソッドを呼び出すのと同じように引数を渡して呼びます。
※呼び出すメソッド自体を文字列にする必要があるので、「$」もしくは「+」で連結します。

### Kotlin
```Kotlin
webView.evaluateJavascript("window.hoge($number)", null)
```

### Javascript
```Javascript
window.hoge = function(number) {
  // do something
}
```
【iOS】Basic認証

#SwiftでBasic認証2種

##外部ライブラリ使わない版
```swift
// 認証情報
let username = "name"
let password = "pass"
// リクエスト準備
let session = URLSession.shared
guard let url = URL(string: "https://hogehoge.com") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
guard let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8) else { return }
let credential = credentialData.base64EncodedString(options: [])
let basicData = "Basic \(credential)"
request.setValue(basicData, forHTTPHeaderField: "Authorization")
// リクエスト実行
session.dataTask(with: request) { data, urlresponse, error in
  // レスポンス処理
}.resume()
```

##Alamofire版
```swift
// 認証情報
let username = "name"
let password = "pass"
// リクエスト準備
guard let url = URL(string: "https://hogehoge.com") else { return }
guard let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8) else { return }
let credential = credentialData.base64EncodedString(options: [])
let headers = ["Authorization": "Basic \(credential)"]
request(url, method: .post, parameters: nil, headers: headers).response(completionHandler: { defaultDataResponse in 
    // レスポンス処理
}
```
Android 初心者による実装時のメモ

プログラミング経験がある人が、 Android で Hello World! するアプリまではやってみて、さて次に何か作りものをしたりしたいけどどうしよう？という時用のメモです。

Java は少しは書いたことあるのと、一度既存アプリの簡単な機能追加をしたことはあるので Activity　やら Fragment の概念はうっすらと知っているのですが、きちんと説明とかはできないので省略しています。用語が適当だったらコメント欄や編集リクエスト等でご指摘いただければ幸いです。

# 実装

## 地図を入れたい

### 地図だけを表示するアプリを作ってしまう

* 地図の表示
* 中心の指定
* Pin を打つ

とりあえずここまでを理解しましょう。

まずは例として作ってしまえ、ということで、 New Project のダイアログを進み、Activity の追加で「 Google Maps Activity 」を選択。

<img width="899" alt="Google　Maps Activity を選択" src="https://qiita-image-store.s3.amazonaws.com/0/117087/da7c57da-2f05-c18d-a90d-52442dfae699.png">

ここでエミュレータでアプリを実行すると、アプリの起動はできますが地図は表示されません。

google_maps_api.xml を開くと、「Google Map を表示するのに使う API　キーを取得しろ」的なことが TODO としてコメントに書かれています。指示通りに取得して XML の所定の場所に貼り付ければ、とりあえず地図表示するアプリを作ることができます。

MapsActivity.java を見れば、下記のことがなんとなく推測できたりします。

* Activity で OnMapReadyCallback のインターフェースを実装すること（onMapReady　メソッド）
* 地点は LatLng クラス
* addMarker で Pin を打つ
* moveCamera　で表示範囲やズームを設定


### Developer's Guide とサンプルコード
開発者用のドキュメントはこちらにあります。ズーム用の UI を追加したい、というようなときはここから探せば見つかります。
https://developers.google.com/maps/documentation/android-api/start

また、それぞれの API の実装例が GitHub で公開されています。

https://github.com/googlemaps/android-samples/tree/master/ApiDemos/app/src/main/java/com/example/mapdemo

# エミュレータ
## エミュレータの設定どこじゃ

メニューの Tools -> Android -> AVD Manager
iOS位置情報まとめ



【使う記述】
##■ 位置情報の精度

```
// バックグラウンドからの位置情報取得
locationManager.allowsBackgroundLocationUpdates = true
```

```
// 更新頻度（didUpdateLocations:に渡す位置情報）、mの値を設定
locationManager.distanceFilter = 2.0
```

```
// 精度を指定。最高精度
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
```

<br>

##■ バッテリー消費削減

```
// 位置情報を新たに取得する必要がない場合、取得をポーズしてくれる
// 一度ポーズになった際はアプリがフォアグラウンドにくるときしか位置情報取得は再開されない。
locationManager.pausesLocationUpdatesAutomatically = true
```

```
// 位置情報更新を自動的にポーズするための判断基準
locationManager.activityType = .fitness
```

 
 
 
##■
Vagrant 上の CentOS6.7 で mailcatcher を使う

## 環境
- vagrant
- CentOS 6.7
- ruby 2.4.3 
- （CakePHP2.10）

## やりたいこと
ローカルの環境からメールのテスト送信をしたい。mailcatcher だと便利だよ！と言われたので入れてみます。

## 手順

### 1. インストール
ruby は既に入ってます。

```
$ gem install mailcatcher
```

途中で一回怒られました。

```
.
.
Building native extensions.  This could take a while...
ERROR:  Error installing mailcatcher:
	ERROR: Failed to build gem native extension.
.
.
.
checking for sqlite3.h... no
sqlite3.h is missing. Try 'brew install sqlite3',
'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
.
.
```

なんか足りないっぽいので、言われたとおりに不足してるのを入れてあげる。

```
$ sudo yum install sqlite-devel
```
すると、今度は成功。

```
Done installing documentation for sqlite3, daemons, thin, skinny, mailcatcher after 2 seconds
5 gems installed
```

### 2. 起動

```
$ mailcatcher
Starting MailCatcher
==> smtp://127.0.0.1:1025
/home/vagrant/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/thin-1.5.1/lib/thin/server.rb:104: warning: constant ::Fixnum is deprecated
==> http://127.0.0.1:1080
*** MailCatcher runs as a daemon by default. Go to the web interface to quit.
```

### 3. ブラウザで確認
んで、メール受信画面をブラウザで見ようと思って、はたと気がついた。
これ……Vagrant上じゃん……？
http://127.0.0.1:1080
って書いてあるけど、このURLで見られるわけないじゃん……？

ためしにvagrantに割り振ってある 192.168.33.40:1080 にアクセスしてみるも、見られない。
調べて見ると、ポートを指定して mailcatcher を起動するやり方があるらしい。ので、それをやろうと思ったら。

```
$ mailcatcher --http-ip 192.168.33.40
Starting MailCatcher
~~> ERROR: Something's using port 1025. Are you already running MailCatcher?
==> smtp://127.0.0.1:1025
==> http://192.168.33.40:1080
```

既に1025ポート使われてるんですけど、って怒られた。うん、知ってた。
一回 mailcatcher 落とそうと思ったら、どうやらPID調べて kill しないといけないらしい……？

ので、とりあえずPID調べてkillする。

```
$ netstat -tulpn | grep :1025
$ kill -9 6253
```

そして、今度はIPアドレスを指定して起動。

```
$ mailcatcher --http-ip=192.168.33.40
```

ブラウザでアクセスしてみます。
http://192.168.33.40:1080

![スクリーンショット 2018-01-29 14.05.36.png](https://qiita-image-store.s3.amazonaws.com/0/152333/5359d082-3056-502f-2131-9eeaaac00bbd.png)


出来たー！

## ついで：メール送信の設定
CekePHP2.10の場合、メール設定はこんな感じ。
ポートを1025に指定したら良いようです。

```
class EmailConfig
{
  public $mailcatcher = array(
        'transport' => 'Smtp',
        'from' => 'example@hoge.com',
        'host' => '127.0.0.1',
        'port' => 1025,
        'timeout' => 30,
        'client' => null,
        'log' => true,
        'charset' => 'utf-8',
        'headerCharset' => 'utf-8',
        'template' => 'default',
        'layout' => 'default',
    );  
}
```



## 参考
https://qiita.com/nanasess/items/8194ae76c1b94c9a7bb9
phpの配列の仕様、癖、指定方法

phpの配列で仕様というか癖というか、バグの元になり得る
指定方法を本で読んだので自分なりにまとめてみます。

#まずはシンプルな配列
ソースを見てから整理していったほうがわかりやすいと思うので
まずは通常のシンプルな配列

```php
$first_array = ["a", "b", "c"];
echo "first_array[2]は" . $first_array[2] . "\n";
```

```php:結果
first_array[2]はc
```
first_arrayの3番目の値を表示していますね。
これは配列に自動的に添字と呼ばれる連番が登録され
その添字をつかって値にアクセスしているという状態になります。

#配列に値を追加する際に数字でkeyを指定して追加すると・・・

以下は一見、通常の配列に添字で追加していると思いがちです

```php
$test_array = [0, 1];
$test_array["a"] = "えい";
$test_array[5] = 5;
$test_array[4] = 4;
$test_array[2] = 2;
$test_array[3] = 3;
```

これを以下のように様々な形でアクセスしてみると・・・

```php
echo print_r($test_array)."\n";
echo "---for文---\n";

for ($i = 0; $i < count($test_array); $i++) {
	echo $test_array[$i]."\n";
}
echo "---foreach文---\n";

foreach ($test_array as $e) {
	echo $e."\n";
}
echo "---\n";
echo $test_array["a"] . "\n";
echo $test_array[3] . "\n";
```

```php:結果
Array
(
    [0] => 0
    [1] => 1
    [a] => えい
    [5] => 5
    [4] => 4
    [2] => 2
    [3] => 3
)
1
---for文---
0
1
2
3
4
5
PHP Notice:  Undefined offset: 6 in /var/www/html/array-order.php on line 18

---foreach文---
0
1
えい
5
4
2
3
---
えい
3

```

となります。

まず結果の最初を見てみると配列がどのような順番で格納されているかがわかります。

次にfor文を見てみましょう。
このfor文だけを見ると一見、以下のようなイメージで配列に格納されていると考えがちです。

```php:これは認識違い
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
    [a] => えい
)

```

しかしこれは認識違いです。
正しくは上記print_rの部分で表示している。

```php

Array
(
    [0] => 0
    [1] => 1
    [a] => えい
    [5] => 5
    [4] => 4
    [2] => 2
    [3] => 3
)
1
```

上記のような形で格納されています。

このことはfor文で表示されたNoticeとforeachの結果を見みても解ります。
noticeの意味は6番目の要素はないということではなく
keyが6の値はありませんという意味になります。

まとめると
配列に値を追加する際に、keyを数字で指定して値を追加し
$array[数字]のような形で値を呼び出すと
**添え字の数字を指定したのではなくkeyの数字を指定したと解釈されることになります。**

phpの配列は基本的に連想配列（マップ）で実装されているということのようです。

#バグを生まないために
・配列のkeyを数字で指定するのは避けたほうがよさそう。
Xamarin.FormsでImageをボタンっぽくする

##Buttonコントロール
Xamarin.FormsにはちゃんとButtonというコントロールがあって、それのImageプロパティに画像パスを指定することで画像をボタンにすることができます。

```a.xaml
<Button Image="image.png" Clicked="Clicked"/>
```

しかし、これを使うといろいろめんどくさい（具体的には画像のサイズ変更など）のでImageコントロールをボタンぽくしてみようと思いコントロールを作成しました。

##ボタンっぽいImageコントロール

```ImageButton.cs
public class ImageButton: Image
{
    public event EventHandler Tapped;

    /// <summary>
    /// アニメーション時間を取得または設定します。
    /// (デフォルト100ms)
    /// </summary>
    /// <value>アニメーション時間</value>
    public uint? AnimationTime { get; set; }

    /// <summary>
    /// アニメーションの際のスケールを取得または設定します。
    /// (デフォルト0.5)
    /// </summary>
    /// <value>アニメーションの際のスケール</value>
    public double? UnevennessScale { get; set; }

    public ImageButton(): base()
    {
        var tgr = new TapGestureRecognizer();
        tgr.Tapped +=  (sender, e) =>  OnClicked(sender, e);
        this.GestureRecognizers.Add(tgr);
    }

    private async void OnClicked(object sender, EventArgs e)
    {
        var btn = sender as ImageButton;

        if (btn != null)
        {
            uint _animationTime;
            double _unevennessScale;

            // アニメーション時間の指定がなければデフォルト(100ms)
            if (AnimationTime is null)
            {
                _animationTime = 100;
            }
            else
            {
                _animationTime = (uint)AnimationTime;
            }

            //凹凸スケールの指定がなければデフォルト値(0.5)
            if (UnevennessScale is null)
            {
                _unevennessScale = 0.5;
            }
            else
            {
                _unevennessScale = (double)UnevennessScale;
            }

            await btn.ScaleTo(_unevennessScale, _animationTime);
            await btn.ScaleTo(1, _animationTime);
        }

        // アニメーション後に指定されたメソッドを実行
        if (Tapped != null)
        {
            Tapped(this, e);
        }
    }
}
```

ポイントはImageコントロールにしてしまうと**Buttonコントロールのような「押された感」がなくなってしまう**ので、アニメーションをつけており、そのパラメータはカスタム可能です。（デフォルトでは押すと0.5倍の大きさになって「押された感」を演出）

XAML側では以下のように使えます。

```デフォルト.xaml
<control:ImageButton Source="image.png"　Tapped="Clicked" />
```

```カスタム.xaml
<control:ImageButton Source="image.png" Tapped="Clicked" AnimationTime="500" UnevennessScale="0.5" />
```

##さいごに
とりあえず作ってみましたが、もっとこうするといいなどアドバイスいただけると嬉しいです。
ArchLinuxにmingw gccをインストールする

どうも。Archでexeを作らねばいけなくなりました。
gccのmingw版をインストールします。

今回は、自力でビルドするのは面倒だったので、非公式リポジトリを利用しました。

## リポジトリを追加します。

以下を`/etc/pacman.conf`に追記。

```ini:/etc/pacman.conf
[ownstuff]
SigLevel = PackageOptional
Server = http://martchus.no-ip.biz/repo/arch/$repo/os/$arch
```


アップデートしとく

```bash
$ sudo pacman -Sy
```

# インストール

```
$ sudo pacman -S mingw-w64-gcc
```
macOS でデスクトップアイコンの後ろにウィンドウを表示する方法

NSWindow のサブクラスを作り、以下のように実装するとデスクトップアイコンの後ろに鎮座するウィンドウが作れます。

```swift
class BackgroundWindow : NSWindow {
    override func awakeFromNib() {
        putBackground()
    }

    private func putBackground() {
        let windowLevel = Int(CGWindowLevelForKey(CGWindowLevelKey.desktopWindow) + 1)
        self.level = NSWindow.Level(rawValue: windowLevel)
    }
}
```

デスクトップアイコンの後ろにウィンドウを配置するとマウスでは操作できなくなります。
ご注意ください。
Ruby2.5にバージョンアップしたらdeviseがエラった

# Ruby2.5だとdeviceがシンタックスエラー
```
SyntaxError (/usr/local/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/devise-4.3.0/app/controllers/devise/sessions_controller.rb:5: syntax error, unexpected '{', expecting keyword_end
...ion only: [:create, :destroy] { request.env["devise.skip_tim...
...                              ^
/usr/local/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/devise-4.3.0/app/controllers/devise/sessions_controller.rb:5: syntax error, unexpected '}', expecting keyword_end
..."devise.skip_timeout"] = true }
...                              ^):

app/controllers/front/users/sessions_controller.rb:1:in `<top (required)>'
```


# 解決策
以下のisuueをご確認ください。

> Devise syntax error (Possibly ruby-2.5 related?) 
> https://github.com/plataformatec/devise/issues/4630


この記事はほぼ個人メモです。
Railsで複数案件の開発をしていて、「あれ？ 前もこんなエラー出たなー」って思ったのでメモ。
intentの中身をvar_dumpしたい

## やりたいこと
他所のアプリとかから結果を受け取ったりすることがある。QRやNFCを読んだ結果とか。

そういう場合、多くは`onNewIntent(Intent intent)`に処理を書く。

ところで、このIntentの中身を確認したい、という状況が起きた。

PHPなら`var_dump`で出せるのに、と思いつつ頑張ることになった。

## 解答
```java
public var_dump(Intent intent) {
    Bundle extras = intent.getExtras();
    if (extras != null && !extras.isEmpty()) {
        System.out.println("+ Bundle.toString: " + extras.toString() + "");

        for (final String key : extras.keySet()) {
            System.out.println("+ Key Name: " + key + "");
            System.out.println("+ toString: " + extras.get(key).toString() + "");
        }
    }
}
```
Redashで同じクエリを複数人で編集したい

# こんな事があります
前の担当者が作ったクエリを編集したくてソースコードを表示したら、FORKだけでSAVEボタンが表示されないぞ！

# 解決方法
現状、Redashはデフォルトでは他の人が作ったクエリを編集することが出来ません。
REDASH_FEATURE_SHOW_PERMISSIONS_CONTROLの設定を変えることで、他人にクエリの編集を許可することが出来ます。
※ これをTRUEにするとダッシュボードにも権限設定メニューが表示されます

# 手順概要
1. 環境変数の追加
1. サービスリスタート
1. 共同編集していクエリの権限編集

# 手順
## 1.環境変数の追加
```export REDASH_FEATURE_SHOW_PERMISSIONS_CONTROL=true```

## 2.サービスリスタート
```$ sudo supervisorctl restart redash_server```

## 3.共同編集していクエリの権限編集
### まずはクエリのソースコードを表示して、コンテキストメニューを選択
![manage_permissions.PNG](https://qiita-image-store.s3.amazonaws.com/0/66855/3249191f-1711-c627-3e98-b826c33174e7.png)


### 次に出るウィンドウでユーザーを追加
![manage_permissions_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/66855/14ff585d-413c-c6df-70b3-3291f1a6d2bf.png)


これにて完了です。

これで、許可したユーザーにもSAVEボタンが表示されるようになります。

# 参考
- [Ability to contribute to someone else’s query](https://discuss.redash.io/t/ability-to-contribute-to-someone-elses-query/14/7)
- [Redash パラメータ一覧 \- Qiita](https://qiita.com/kyoshidajp/items/3528e3cd470eafef6edf#redash_feature_show_permissions_control)
【iOS】ハンバーガーメニューの作り方

#簡単にハンバーガーメニューを作る(Swift)


###Storyboard設定

(1)ビューコントローラをsegueで「Present Modally」を選択して結ぶ。
(2)segueの「Identifier」をshowMenuに設定する。
(3)segueの「Transition」をCross Dissolveに設定する。
(4)メニュー画面のグレー部分(View)のBackgroundを「Opacity」50%程度に設定する。
(5)グレー部分(View)の「tag」を1に設定
![hamburgerUI.png](https://qiita-image-store.s3.amazonaws.com/0/59015/1db26dd5-203b-8b3e-48fb-80d2cf5fd0f2.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/59015/74a82bbb-716c-3e42-334c-691a8a815973.png)

###コード

```swift:呼び出し元
import UIKit

class BaseViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    // ハンバーガーメニューボタンタップ処理
    @IBAction func tapMenu(_ sender: UIBarButtonItem) {
        self.performSegue(withIdentifier: "showMenu", sender: nil)
    }

}
```

```swift:ハンバーガーメニュー
import UIKit

class MenuViewController: UIViewController {

    @IBOutlet weak var menuView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // メニュー画面の位置
        let menuPosition = self.menuView.layer.position
        // 初期位置設定
        self.menuView.layer.position.x = -self.menuView.frame.width
        // 表示アニメーション
        UIView.animate(
            withDuration: 0.1,
            delay: 0,
            options: .curveEaseOut,
            animations: {
                self.menuView.layer.position.x = menuPosition.x
        },
            completion: { bool in
        })

    }

    // メニュー外をタップした場合に非表示にする
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        for touch in touches {
            if touch.view?.tag == 1 {
                UIView.animate(
                    withDuration: 0.2,
                    delay: 0,
                    options: .curveEaseIn,
                    animations: {
                        self.menuView.layer.position.x = -self.menuView.frame.width
                },
                    completion: { bool in
                        self.dismiss(animated: true, completion: nil)
                }
                )
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}
```
巨大素数を見つけるアルゴリズムについて（リュカ=レーマー・テスト）

#概要
<a href="https://wired.jp/2016/01/22/discover-your-own-prime-number/">史上最大の素数が更新されたというニュース</a>が最近話題になっていました。

見つかった素数は 2<sup>74207281</sup> - 1 です。

この数のように、2<sup>n</sup>-1 の形で書ける数を「メルセンヌ数」と呼ぶのですが、
実は現在見つかっている巨大素数のほとんどがこのメルセンヌ数です。

これは何故かというと、メルセンヌ数だけに特別に使える優れた素数判定法が存在するからです。

その一つが「リュカ=レーマー判定法」です。
今回はそれをpython3で簡単に実装してみたいと思います。

#判定法
（※実装だけ知りたい人は飛ばしてください）

p を 3以上の素数,
M<sub>p</sub> を p 番目のメルセンヌ数（つまり 2<sup>p</sup>-1）,
S<sub>0</sub> = 4,
k=1, 2, 3,... に対して S<sub>k</sub> = S<sub>k-1</sub><sup>2</sup> - 2. 
とするとき、

S<sub>p-2</sub> が M<sub>p</sub> で割り切れるなら、
M<sub>p</sub> は素数である。

ここで入力 p を素数に限っているのは、p が合成数なら M<sub>p</sub> も合成数になると知られているからです（証明は因数分解を使ったもので初等的）。

#実装の考え方
（※実装そのものだけ知りたい人は飛ばしてください）

まず、上のアルゴリズムを素直に実装すると、S<sub>p-2</sub> が大きくなり過ぎてしまいます。

最終的に知りたいのは S<sub>p-2</sub> の値そのものではなく、それが M<sub>p</sub>
 で割り切れるかどうかなので、
最初から M<sub>p</sub> で割った余りの世界（合同式の世界）で考えます。

つまり実装では、S<sub>k</sub> = S<sub>k-1</sub><sup>2</sup> - 2 の計算をするたびに M<sub>p</sub> で割った余りを取り、あつかう数を小さくしていきます。

そして、それを p-2 回繰り返して最終的に 0 になれば、余りも 0、すなわち割り切れたということになります。

#実装

```python3
def Lucas_Lehmer_Test(p):
    s = 4 #S_0の定義
    M = (1 << p) - 1 #左シフトで2^pを作る

    for n in range(2, p):
        s = (s**2 - 2) % M
    return s == 0
```

（入力が 3 以上の整数であることを前提としています）

試しに range(3, 3000, 2) でメルセンヌ素数を探してみたところ、
おんぼろノートPCで 50 秒ほどかかって 17 番目までのメルセンヌ素数が見つかりました。
![メルセンヌ.png](https://qiita-image-store.s3.amazonaws.com/0/123809/242ac800-5027-9099-789a-d2e56777cec3.png)

その中で最大の 2<sup>2281</sup>-1 は 687 桁の数なので、
普通に素数判定をしようとするとかなり難しい大きさです。
（例えば 2048bit の RSA暗号で使われるような素数で 617桁）

それだけメルセンヌ数は恵まれているということですね。

ちなみに上記のプログラムでは、単純化のため入力 p が合成数の時も実行しています。
p に対する素数判定も入れて、合成数の時はすぐにFalseを返すようにするとより早くなると思います。
Macで学ぶNode.js　初心者メモ１

※疑問が多いながらも、動かしながら少しずつ解剖できたら良いなと思う。
※随時、追記更新していく予定。
※ブラックボックスにする部分は多いと思う。
※node.jsはインストール済みの前提

---
# node.jp
node.jsとは
>node.jsはJavaScriptのランタイム環境です。
<details><summary>ランタイム環境</summary>プログラムを実行するための環境</details>


# node.jpを使ってみよう
まずは、ディレクトリ（フォルダ）を準備する。
>プロジェクトを保存するフォルダを任意の場所に作成します
今回はtestAAAというフォルダを作成しました。


npmの初期化を行う
>ターミナルで、作成したディレクトリに移動し、以下のコマンドを入力

    【入力するコマンド】
    npm init
>色々質問されるので答えていく
npmの初期化を行うと、package.jsonというファイルが作成される。
ここには、必要なパッージなどの情報がまとめられている。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147613/c0469d16-4417-983f-9a51-9b02a51059d5.png)



>答え終わると、フォルダにpackage.jasonというファイルが出来ている。
ここには、今回作成したプロジェクトの説明が書かれている。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147613/f8c377f2-5735-1699-cbfb-5d55c861ff74.png)


htmlファイルを用意する
>publicフォルダを作成し、index.htmlのファイルをその中に作成した。
コードは以下の通り。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147613/e6a42d10-3e32-3be6-6d2c-21b952d5ca45.png)


jsファイルを用意する。
>app.jsのファイルを作成し、以下のように記述した。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147613/870f0f34-966b-a98d-bb87-c2e17ff31ad8.png)

サーバーを待ち受け状態にする。
>ターミナルで。現在のプロジェクトのディレクトリであることを確認して、以下のコードを入力する。

    node app.js
>うまくいけば、console.logがコンソールに表示される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147613/20971612-d038-d22e-02d4-983474b1082d.png)

ブラウザからアクセスを行う。
>ブラウザで以下のURLにアクセスを行う。
http://localhost:3000/

>![image.png](https://qiita-image-store.s3.amazonaws.com/0/147613/9a00f2f1-79d3-f5b0-211c-8e077c67da6b.png)
無事に表示することが出来た。

---
メモ１はここまで。