OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu Desktop on the Intel® NUC で職場からノートPC排除して自宅のディスプレイも減らしててすごい

# はじめに

ITのおじさんからITじゃないおじさんになったので記事も雑です。
細かいことはこっちに書いてあります。 [メモ: nucとubuntuを職場のノートPC代わりにしてみた](http://km-d.blogspot.com/2019/04/nucubuntupc.html)

# やりたいこと

家でも使いたい。でも家はディスプレイ増やしたくないのでリモートデスクトップ的な使い方をしたい。

```
職場（自席・会議室）┃　自宅
┏━━━━━━┓　　┃　┏━━━━━━┓
┃ディスプレイ┃　　┃　┃ディスプレイ┣┓
┗━━┳━━━┛　　┃　┗━━━━━━┛┃
┏━━┻━━━┓　　┃　┏━━━━━━┓┃
┃　新マシン　┃　　┃　┃　新マシン　┃┃
┗━━┳━━━┛　　┃　┗━━┳━━━┛┃
┏━━┻━━━┓　　┃　┏━━┻━━━┓┃
┃　　人　　　┃　　┃　┃ＷｉｎＰＣ　┣┛
┗━━━━━━┛　　┃　┗━━┳━━━┛
　　　　　　　　　　┃　┏━━┻━━━┓
　　　　　　　　　　┃　┃　　人　　　┃
　　　　　　　　　　┃　┗━━━━━━┛
```

# 前提というか経緯というか

雑に列挙

- 勤務先が変わったので
- 新しいPCが必要だけど
- お金を稼がない系ジョブにチェンジして
- 高いPCをオネダリしづらくて
- **節約マシン** にするしかないが
- **打ち合わせに持ち込め** ないといけないから
- ボロいノートPCみたいなのが必要
- でも **エクセルはなくても** よくて
- ブラウザだけ動けばいい

# 選んだもの

chromebookあたりでいいと思ったけど会社のおじさんに言われてコレ

- Intel® NUC
 - 持ち運べる
 - 仕事で使える性能
 - 安い
- Ubuntu
 - 0円
 - 仕事で使える(?)

# やったこと

こんな挙動を自動でしてくれないといけない。

- ディスプレイがあるときはディスプレイ最優先
- 無い時はWindowsのリモートデスクトップみたいにする

下記の設定やっとけば期待したとおりの動きをしてくれます。大体。

## vinoでvncする設定

- 職場と同じ構成で接続
- vinoを有効にする
  - `設定 > 共有` で有効にすればいいだけ
  - vinoはubuntu18.04に最初から入ってるリモデっぽいやつなのでちゃんと動いた

## ダミーな画面領域作成

- これやっとかないとディスプレイつないでない時にvncで接続しても変
- 画面がプルプルしちゃってログインできても使えない
- 表示する領域確保されないから

### ダミーなデヴァイスを追加

自宅でvncするだけなのでVirtualHeadsは1つで十分ですよ!

```bash:/usr/share/X11/xorg.conf.d/20-intel.conf
Section "Device"
    Identifier "intelgpu0"
    Driver "intel"
    Option "VirtualHeads" "1"
EndSection
```

### OS起動時にダミーを有効にする

```bash:/etc/X11/Xsession.d/45custom_xrandr-settings
#!/bin/bash
xrandr --newmode "1920x1080_60.00"  172.80  1920 2040 2248 2576  1080 1081 1084 1118  -HSync +Vsync # フルHDサイズの設定を作成
xrandr --addmode VIRTUAL1 1920x1080_60.00 # ダミーっぽい出力先に反映させる
xrandr --output DP2 --pos 0x0 --primary # 実際の出力先(USB-C/Thunderbolt)を優先させて左上に設定
```

# だめだったこと

- vnc server はubuntu18.04だとグレーな画面になっちゃう人も
- xserver-xorg-video-dummy を使ってもダミーな領域は作れるけど本物のディスプレイつないでも認識されなくなる

# まとめ

- 自宅に持って変えるのめんどくさくなったので
- 今はもうやってない
- でもnucは小さくていいなあ
- 金があるならwindows使ったほうがいいなあ
PHPからaws-sdkで実行したLambda関数の戻り値を取得するには

# はじめに
AWS SDK for PHPを利用してLambda関数を実行(invoke)した際の戻り値をどのように取得すればよいのかという情報を探してみたのですが、なかなか情報が見つかりませんでした。

※API Gatewayを利用してLambda関数を実行して戻り値を取得するという方法に関する情報はそれなりにありますが、SDKからLambda関数を実行して戻り値を取得する方法に関する情報がPHPに限らずほとんどありませんでした、あるいは探しづらい状況でした。

PHPの場合、以下のようなコードを実行することでLambda関数からの戻り値を取得することができます。（下記コード内の ```$invoke->get('Payload')->__toString()``` でLambda関数からの戻り値を取得することができます）

# コード

```
<?php
$lambda = new \Aws\Lambda\LambdaClient([
			'region' => 'ap-northeast-1',
			'version' => 'latest',
			'profile' => 'default'
		]);

$invoke = $lambda->invoke([
	'FunctionName' => 'hoge',
	'InvocationType' => 'RequestResponse',
	//"LogType" => "Tail"
]);

$result = json_decode($invoke->get('Payload')->__toString());

// Lambda関数からの戻り値が表示される
var_dump($result);

```

# 参考
- https://stackoverflow.com/questions/36451925/cannot-get-aws-lambda-function-response-in-php-client
EC-CUBE4系でプラグインインストール時にエラーが出た時の対処法

*[プラグインインストール時のエラーを防止する方法](https://qiita.com/nanasess/items/791c9ec98f69ada93ea0) も書きましたので、合わせてご覧ください*

EC-CUBE4 になって、プラグインの管理方法が大きく変わりました。
これに伴い、共有レンタルサーバーなど、リソースの少ない環境では以下のような問題が発生する場合があります。

> プラグインのインストール時に高負荷な状態が発生し、OOM Killerでhttpdのプロセスが殺される。そのため、プラグインのインストールが完了しない。
> 
> https://github.com/EC-CUBE/ec-cube/issues/4142

インストール時以外に、有効化/無効化時、アンインストール時にも発生します。
これらの処理が完了しない場合、以下のような状態となります

- 「インストール完了」の表示になっても、「有効/設定」ボタンが表示されない
- システムエラーになる
- PHPエラー画面が表示される
- レスポンスが十数分返ってこない

## 対処法

対処方法はケースバイケースになりますが、以下の順で試してみることをおすすめします

### Symfony のキャッシュクリア

管理画面→コンテンツ管理→キャッシュ管理からキャッシュクリアする

管理画面が開かない場合は、以下のいずれかをお試しください。
(キャッシュの強制削除は自己責任で...)


```shell
## Symfony コマンドでのキャッシュクリア
bin/console cache:clear --no-warmup
```

```shell
## キャッシュの強制削除
rm -rf /path/to/ec-cube/var/cache/*
```

### Composer クラスマップの再生成

[こちら](https://getcomposer.org/download/) を参考に、 Composer コマンドをインストールしておいてください

```shell
php composer.phar dumpautoload
```

上記コマンド終了後、 Symfony のキャッシュクリアを実施してください

### Composer install コマンドの再実行

```shell
php composer.phar install
```

### コマンドラインでのプラグインの再インストール

管理画面からインストールに失敗しても、コマンドラインからインストールできる場合があります。

```shell
## クラスマップが壊れている場合は再生成(オプション)
php composer.phar dumpautoload

## エラーになっているプラグインを一旦削除
bin/console eccube:composer:remove ec-cube/<PluginCode>

## 再インストール
bin/console eccube:composer:require ec-cube/<PluginCode>

## 有効化
bin/console eccube:plugin:enable --code <PluginCode>
```

既に運用中の場合は、プラグインをアンインストールすることによりデータが削除されてしまう恐れがあります。必ずデータベースのバックアップを取得したあと、上記コマンドの実行をお願い致します。

### 何度か繰り返す

プラグインインストール/有効化/無効化 時のエラーは、確実に再現性のあるものではなく、うまくいく場合もあります。
何度か繰替えしてみることをおすすめします。



これらを実行しても解消しない場合は、エラーログやエラー画面のスクリーンショットとともにコメント覧にてお知らせください。
mruby でリアルタイムで映像分類する

@akuroda さんが [mruby-gdを使って画素にアクセスする方法](https://qiita.com/akuroda/items/e3d509f75713a55ae22e)を教えてくれたので @kjunichi さんの mruby-webcam を使ってリアルタイムに映像分類する様にしてみました。

導入の方法は akuroda さんの記事を読んで下さい。

```ruby
model = TfLite::Model.from_file 'mobilenet_v1_1.0_224_quant.tflite'
interpreter = TfLite::Interpreter.new(model)
interpreter.allocate_tensors
input = interpreter.input_tensor(0)
output = interpreter.output_tensor(0)
wanted_width = input.dim(1)
wanted_height = input.dim(2)
wanted_channel = input.dim(3)
data = Array.new(wanted_height * wanted_width * wanted_channel, 0)
labels = File.read('labels.txt').lines.map {|x| x.strip} 

cam = Webcam.new(ARGV[0]||0)
cam.set_size(wanted_width, wanted_height)
cam.each(true) {|img|
  decoded = GD::Image.new_from_jpeg_data(img)
  (0...wanted_width).each do |x|
    (0...wanted_height).each do |y|
      pixel = decoded.get_pixel(x, y)
      offset = (y * wanted_width + x) * wanted_channel
      data[offset+0] = decoded.red(pixel)
      data[offset+1] = decoded.green(pixel)
      data[offset+2] = decoded.blue(pixel)
    end
  end
  decoded.destroy
  input.data = data
  interpreter.invoke
  output.data.each_with_index do |v, i|
    puts "#{i} #{v} #{labels[i]}" if v > 50
  end 
  puts "---"
}
```

![](https://i.imgur.com/o9MPXRO.gif)

`cam.each` はまだマージされてないので今しばらくお待ちください。

https://github.com/kjunichi/mruby-webcam/pull/15
ActiveRecord::StatementInvalid in Tasks#index

#ActiveRecord::StatementInvalid in Tasks#index

「現場で使える Ruby on Rails 5速習実践ガイド」
の７章をやっていて以下のエラーが出た。

```
Showing /home/ubuntu/rql/taskleaf/app/views/tasks/index.html.slim where line #21 raised:

PG::UndefinedColumn: ERROR:  column "craeted_at" does not exist
LINE 1: ...ROM "tasks" WHERE "tasks"."user_id" = $1 ORDER BY "craeted_a...
                                                             ^
HINT:  Perhaps you meant to reference the column "tasks.created_at".
: SELECT DISTINCT "tasks".* FROM "tasks" WHERE "tasks"."user_id" = $1 ORDER BY "craeted_at" DESC
```

というエラーが出た。
データベースがおかしい（上記のcraeted_atという打ち間違い）のかと思い、コンソールでテーブル、カラムを出力しても打ち間違いは見当たらない。。。



結果どこが間違っているのかと言うとモデルのscopeだった

```md:task.rb
scope :recent, -> { order(craeted_at: desc)}
```

ここを修正すると問題なく動作。
エラー画面からここまでたどり着くのに結構時間かかった。。。。
応用数学レポート

# 第1章：線形代数

### 固有値分解、特異値分解
ある行列Aにおいて、Aが正方行列の場合は固有値分解、それ以外は特異値分解が可能

### 固有値分解、特異値分解の目的
固有値、特異値から特徴の似ているものを分類するために使う
（例）
・音声データを固有値分解し、同一人物の音声を見つける
・画像圧縮のため、小さい特異値を切ってうまくぼやかす

# 第2章：確率・統計

### ベイズ則
ある事象Xが与えられた元でYとなる確率とYとなる確率をかけたものは、ある事象Yが与えられた元でXとなる確率とXとなる確率をかけたものと同じ
→ 
・つまり、どちらかの条件付き確率がわかれば調査しないでももう片方の確率がわかる。
・主観確率、頻度確率どちらにも使える。

### 確率分布
事象の発生する確率の分布


#### 期待値
その分布で、施行したとき期待される値（ありえそうな値）
連続値の場合は積分で求められる

#### 分散
データの散らばり具合（同じもの同士の掛け算）
機械学習において値をどうしたいか（近づけたい、散らばせたい）によって分散の値を調節する。

#### 共分散
2つのデータの散らばり方（違うもの同士の掛け算）
平均値との差の積をとるので、負の相関があると負の値をとる

#### 確率分布の種類
事前に確率分布を知って、計算しやすくする。

ベルヌーイ分布：2通りの事象、1回の施行
・2通りより多い事象が出る場合 → マルチヌーイ分布
・1回より多い施行の場合 → 二項分布

ガウス分布：連続値の分布　


# 第3章：情報理論

### 自己情報量
・珍しさを示す数
・複雑さがどれだけふえたのかをあらわしている。

### シャノンエントロピー
自己情報量の期待値を表したもの

### KLダイバージェンス,交差エントロピー
同じ事象の確率分布が変わったときにどれだけ自己情報量が変わるかを表した値
homebrew-caskでJava8をインストールする

homebrew-caskについては以下記事を読んでセットアップしてください。

[MacのBrewで複数バージョンのJavaを利用する - Qiita](https://qiita.com/seijikohara/items/56cc4ac83ef9d686fab2)

この手順通りに `brew cask install java8` するとエラーが出ます。

```
$ brew cask install java8
Error: Cask 'java8' is unavailable: No Cask with this name exists.
```

[Java有償化問題とJava8のサポート終了](https://qiita.com/machidadada/items/8137d3c079490f764524)の影響で、java8が消えてなくなっています。

> Oracle has deleted their Java 8 builds from their public website. There’s no way for Homebrew to download them for you any longer. If you want Oracle’s Java 8, you’re going to have to log into Oracle’s website with your personal Oracle account, and download and install it manually.
[Delete java8.rb · Homebrew/homebrew-cask-versions@2f7c1d5](https://github.com/Homebrew/homebrew-cask-versions/commit/2f7c1d5d1582a1fd465991fea8087b94cdbbd088#diff-554be5da105125afa6aa1270ad76723d)

代わりに `adoptopenjdk8` がリリースされていますので、それをインストールすることでJava8を使うことができます。

```
$ brew tap AdoptOpenJDK/openjdk
$ brew cask install adoptopenjdk8
```

切り替えはjava8のときと同様で問題なさそうです。

```
$ export JAVA_HOME=`/usr/libexec/java_home -v "1.8"`
$ PATH=${JAVA_HOME}/bin:${PATH}
```
画像を読み込めた場合のみ、ドラッグできるように制御

## はじめに
JSでドラッグ＆ドロップを実装する際に、「画像が読み込まれない場合は、ドラッグできないようにする」にはどうするかです。


画像を読み込めないというのは、以下のようなエラーがコンソールで吐かれ、
`Failed to load resource: the server responded with a status of 404 (Not Found)`

ブラウザ上では、例えばこのように描画されます。
<img width="119" alt="スクリーンショット 2019-04-22 13.31.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/7ef9dfee-c1f1-0807-cf1b-e2a812a9980e.png">

何もしなかったら、これもドラッグできてしまうので、この制御を行いたいですね。

## 実装前

実装前は、このように`Not Found`でもドラッグできてしまいます。
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/50400e04-333e-1d1d-405c-2727238a236b.gif)
(ここでは描画されない場合は、`Not Found`と表示させるようにしています)


そこで以下のようにしましょう。

## 方法
### 1.`:draggable="imageDraggable(item)"`を追加

Template内の対象のimgタグに`draggable`でtrue/falseを持たせることで、ドラッグ判定制御ができます。ロジックの部分はcomputedに用意した、`imageDraggable`で判定させるようにします。(itemのキーにimage_urlとして画像パスを持たしています。)

### 2.new Image()を利用し、widthで判定させtrue/falseを返す

```js

imageDraggable: () => item => {
   const newImage = new Image()
   newImage.src = item.image_url
   // 画像がない場合は、widthが0になることを利用
   return newImage.width > 0 ? true : false
},
```

ここでは、imgタグを生成し、そのパスに先ほどの渡した`item.image_url`をセットししています。
そしてポイントが、そのwidthを見ること。

画像が読み込めていれば、widthがきちんと取れているはずです。
逆に404で読み込めていない場合は、`0`になるので、falseが返ります。

## 実装後

これで無事に、読み込めない画像のドラッグはできなくなりました！

![test1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/402820b6-6faf-f0e1-7d1f-f3f8f1a9ecdd.gif)

めでたしめでたし:tada:

## 補足
* 他にも、メソッドの中で`onload`と`onerror`を使ってやる方法がありますが。算出プロパティで使う場合は、そちらは`undefined`が返ってきます。どこで判定させたいかで使い分けましょう。

* ここではVue.jsを使った例で書いていますが、jQueryや他のフレームワークをお使いの際は、それぞれの書き方に置き換えて下さい
Kotlin1.3.30に上げるとktlintでPROPERTY_DELEGATEエラーが出る

# バージョン
Kotlin 1.3.30
kotlinter-gradle 1.23.1

# 現象

```
> Task :app:lintKotlinAndroidTest FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:lintKotlinAndroidTest'.
> There was a failure while executing work items
   > A failure occurred while executing org.jmailen.gradle.kotlinter.tasks.lint.LintWorkerRunnable
      > PROPERTY_DELEGATE

```

# 原因

ktlint 0.31.0 が Kotlin 1.3.30 に対応できてないのが問題のようです。

> This does happen from time to time since ktlint depends on internal compiler details of kotlin which this plugin get transitively.
[Upgrading to Kotlin 1.3.30 causes "A failure occurred while executing org.jmailen.gradle.kotlinter.tasks.lint.LintWorkerRunnable > PROPERTY_DELEGATE" · Issue #93 · jeremymailen/kotlinter-gradle](https://github.com/jeremymailen/kotlinter-gradle/issues/93)


# 解決方法

2019年4月22日現在、解決方法はなさそうです。素直にKotlinを1.3.21に戻しましょう。

ただ、ktlintの方には対応PRがマージされていて（[Upgrade to kotlin 1.3.30 by jeremymailen · Pull Request #376 · pinterest/ktlint](https://github.com/pinterest/ktlint/pull/376)）リリース待ちのステータスのようなので、すぐに解決しそうです。

## [2019年5月24日追記]

ktlint0.32.0がリリースされ、kotlinter-gradleも1.24.0で内部のktlintバージョンが上がったので、直ったようです。
direnv/dotenvを使ってnpm run-scriptからS3にDeployする

## 使うもの

- s3-deploy-dotenv
  `$ npm install —-save-dev s3-deploy-dotenv`
- direnv、dotenv
  Macなら `$ brew install direnv dotenv`

## 手順

### 1. プロジェクトルートに `.env` つくる

   ```
   # S3 リージョン
   S3_REGION=ap-northeast-1
   # S3 アクセスキー ID
   S3_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXX 
   # S3 シークレット アクセスキー
   S3_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXX
   # バケット名
   S3_BUCKET={{S3バケット名}}
   
   # デプロイするルートディレクトリ ex) dist
   S3_LOCAL_DIR={{ディレクトリパス}}
   # デバッグモード 任意
   S3_DEBUG_MODE=true
   ```

### 2. npm scriptsに追加

   ```JSON
   ...
   "deploy": "s3-deploy-dotenv",
   ...
   ```   

### 3. 実行
`$ npm run deploy`



## 環境ごとにわけたい

プロダクション環境を分ける場合...

### 1. プロジェクトルートに `.env.production` をつくる

   ```
   S3_BUCKET={{プロダクションバケット名}}
   ```

   上書きしたい値のみ記入でOK.

### 2. npm scriptsに追加

   ```JSON
   ...
   "prod:deploy": "source .env.production && s3-deploy-dotenv && direnv reload",
   ...
   ```

   やってること

   - sourceコマンドで.env.productionを読み込みグローバル変数が上書きされる
   - S3 デプロイの実行
   - .envの環境変数に戻す

### 3. 実行
   `$ npm run prod:deploy`
そのアプリケーションに Bot の技術が本当に必要か?

# きっかけ

とある方向けに、プログラミングの初歩を教えておりまして、C にしたかったのですが、C# から始めてみました。

# 発見 - Step.1 Console App

まずは、`Console アプリケーション` から始めてみました。Console.WriteLine() からですね。

コンピューターに自分の事を呼んでもらいたいだろうから、名前と生年月日を入力してもらって、年齢を当てる、というアプリケーションを作りました。

幾つかのプログラミングの基本を盛り込むためです。

- ユーザーとの情報のやり取り
- 逐次実行
- データ型の存在 - 日付の計算
- 条件分岐 -> 繰り返し

以下、今、私が30分くらいで作ったサンプルコード。コード自体に大した価値はないので...

```C#
using System;

namespace ConsoleAppLikeBot
{
	class Program
	{
		static void Main(string[] args)
		{
			// 1. あいさつ文作成
			var greetingMessage = MakeGreetingMessage(DateTime.Now.Hour);
			Console.WriteLine($"{greetingMessage}!");

			var customeName = "";
			while (customeName.Trim().Length==0)
			{
				Console.WriteLine($"お名前を教えてください");
				customeName = Console.ReadLine();
			}


			// 2. 誕生日を聞く
			DateTime? birthDate = null;
			while (birthDate == null)
			{
				Console.WriteLine($"誕生日はいつですか?");
				var inputDate = Console.ReadLine().Trim();
				try
				{
					birthDate = DateTime.Parse(inputDate);
				} catch (Exception e)
				{
					Console.WriteLine("入力したデータが日付の形式として処理できないか、存在していない日付の様です。");
					birthDate = null;
				}
			}

			Console.WriteLine($"{customeName}さん、ようこそ!");
			Console.WriteLine($"現在 { getAge(birthDate)} 歳ですね?");

			Console.WriteLine("ご利用ありがとうございました");
		}

		static string MakeGreetingMessage(int Time)
		{
			string message = "";
			if (Time < 3) {
				message = "深夜までご苦労さまです";
			}
			else if (Time < 11)
			{
				message = "おはようございます";
			}
			else if (Time > 15)
			{
				message = "こんにちは";
			}
			else
			{
				message = "こんばんわ";
			}

			return message;


		}

		static int getAge(DateTime? birthDay)
		{
			if (birthDay == null) return 0;
			int age = DateTime.Now.Year - birthDay.Value.Year;
			if (birthDay > DateTime.Now.AddYears(-age))
			{
				age--;
			}
			return age;
		}

	}
}

```

動かすと、こんな感じ。

```cmd
こんばんわ!
お名前を教えてください
わたくし
誕生日はいつですか?
2000/1/1
わたくしさん、ようこそ!
現在 19 歳ですね?
ご利用ありがとうございました
```

で、気づいたのですが。

*これって、Botのアプリと同じじゃない*

という事なんです。

- ユーザーの入力を待つ
- 入力結果で、条件分岐をする
- どこかで終了する

ま、LUIS も呼び出し出来ますしね。なんなら、喋らせる事も出来ますね。

# 発見 - Step 2. WindowsForm を作ってみた

画面があった方が楽しいので、同じ処理を WindowForms で実装してみました。コードは割愛します。

<img width="626" alt="SimpleUI.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/6e50c9e2-85cf-d5ed-fbb5-a6295531f38c.jpeg">

で、画面にコントロールを置いて、気づいたのですが...

*シーケンシャルでしか処理の書けない、Console Application と比較して、圧倒的にユーザーにも、プログラマーにも優しいじゃない!*

- ユーザーが入力状況を常に確認できる
- 日付専用のコントロール。容易な入力値のチェック
- 完結なプログラミングモデル

という事なんです。

プログラミングの進化をなぞっただけなのですが、改めて実感したわけです。

# 発見 - 自分の身の回りをみて

何でも、Bot という風潮が強いと思います。スマートスピーカーでもいいのですが、ぶっちゃけ、複雑な入力を処理できるわけじゃないです。

Chat Bot の弱点:

- Bot とのやり取りが 5回 程度を超えると大多数の方が離脱する...
- スマートフォンに話しかける人は、ほぼ不在
- 一覧性が悪い。項目数が増えると、ユーザーが過去何を言ったのか、忘れやすい

で、やっぱり、スマートフォンなら:

- ボタンで選ばせる。何なら画像で説明。
- Q&Aは所詮*検索*なので、素直に検索に最適な画面構成にする

方がいいかな、と改めて思った次第です。

# まとめ

私は以前から、Bot のアプリについて、こう考えています。

*Bot は単なるWebアプリ*

そして、その User Experience のデザインや、プロトタイプに、実は単純な Console Application が役に立つのではないでしょうか?

本当に Bot のアプリが必要なのか? 複雑なアプリ+インフラにする価値が本当にあるのか?

良く考えてみてもいいかと思います。

ボット設計の原則:
https://docs.microsoft.com/ja-jp/azure/bot-service/bot-service-design-principles?view=azure-bot-service-4.0
CentOSにphpMyAdminを入れる。php5.6版


#phpMyAdminのインストール

### 前提条件
CentOS
Apache
php5.6
mysql
あたりがインストールされていること。

---

###phpMyAdminのインストール
`$ sudo yum --enablerepo=remi,remi-php56 install phpMyAdmin php-mcrypt php-mysqlnd`

設定ファイルの追記。
`$ sudo vi /etc/httpd/conf.d/phpMyAdmin.conf`

```phpMyAdmin.conf
<Directory /usr/share/phpMyAdmin/>
   AddDefaultCharset UTF-8

   <IfModule mod_authz_core.c>
     # Apache 2.4
     #Require local

     # すべてのアクセスを許可---
     AllowOverride all
     Require all granted
     # ---ここまで

   </IfModule>
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Deny from All
     Allow from 127.0.0.1
     Allow from ::1
   </IfModule>
</Directory>
```

Apacheの再起動
`$ sudo systemctl restart httpd`


これで、http://[サーバ名]/phpMyAdminでphpMyAdminが開ける。
本当に楽チン!! Custom Vision Serviceで画像判別サービスを作ろう。

#Custom Vision Service とは
Microsoft Azule が提供している画像認識のサービスです。教師データとなる元の画像を勉強し、
新たな画像に対して、Aである可能性 XX%、Bである可能性 YY% と画像を判別してくれるサービスです。（今回は、A: きのこの山、B:たけのこの里）
そして、難しいプログラミングなど一切不要であるということです。本当に一切不要。

公式サイト→ https://azure.microsoft.com/ja-jp/services/cognitive-services/custom-vision-service/

#知ったきっかけ
ちょまどさん（@chomado）がTwitterでCustom Vision Service を用いて、
松屋、吉野家、すき家の牛丼を判別するというしょうもないことをやっていて興味を持ちました。
（なんか俺にもできそうだなと。笑）
![スクリーンショット 2018-11-16 10.33.19.png](https://qiita-image-store.s3.amazonaws.com/0/274029/a18eb9d0-54f5-c42c-393a-0be448bc07b2.png)

#きのことたけのこを判別
Custom Vision Service を使ってみたいけど、画像を用意するなどがめんどくさいという方も多々おられると思います。
以下の記事の最後の方に、きのこの山、たけのこの里の画像もダウンロードできるようになっております。
ナレッジコミュニケーションの大柳(@oyngtmhr)さん、ありがとう。
「Azure Custom Vision Serviceで「きのこの山」と「たけのこの里」を判別させてみる」
https://azure-recipe.kc-cloud.jp/2017/12/custom_vision_2017adcal/


#手順

###イメージのアップロード
![illustration-1.png](https://qiita-image-store.s3.amazonaws.com/0/274029/6b2132ad-237e-c775-db41-b649e99859b5.png)

ラベル付けした画像をアップロードするか、ラベル付けしていない画像に Custom Vision Service を使ってすばやくタグ付けします。

たけのこの写真をアップロードしている様子です。
![スクリーンショット 2018-11-16 9.18.51.png](https://qiita-image-store.s3.amazonaws.com/0/274029/7ba7beaa-d527-504b-08f7-da7cbe14ad5a.png)

###トレーニング
![illustration-2.png](https://qiita-image-store.s3.amazonaws.com/0/274029/1268915f-c927-f783-cc77-aa22ee1db394.png)

ラベル付けした画像を使って Custom Vision Service に学習させたいコンセプトを伝えます。

![training.PNG](https://qiita-image-store.s3.amazonaws.com/0/274029/b2a50218-4784-a47c-3940-bae1c09bbafd.png)


###評価
![illustration-3.png](https://qiita-image-store.s3.amazonaws.com/0/274029/6b76ca14-7190-2816-6e58-13289ca5129d.png)

シンプルな REST API 呼び出しを使用して、新しいカスタム コンピューター ビジョン モデルで画像をすばやくタグ付けできます。また、リアルタイムの画像解釈を実行するデバイスにモデルをエクスポートすることもできます。


![コアラのマーチ.PNG](https://qiita-image-store.s3.amazonaws.com/0/274029/7bd3306b-95fa-edc9-05c0-a3896d6dcde5.png)

![コロン.PNG](https://qiita-image-store.s3.amazonaws.com/0/274029/3a3e7be4-7447-52d9-2ad8-05c07ef03032.png)

![フォード.PNG](https://qiita-image-store.s3.amazonaws.com/0/274029/583a9acf-cddc-f79f-b33b-5bdbccccbd73.png)


###アクティブな学習
![illustration-4.png](https://qiita-image-store.s3.amazonaws.com/0/274029/23fc478a-7f78-c585-b6f8-7f98adf6fc9c.png)

カスタム ビジョン モデルを通して評価された画像が、分類方法を改善し続けていくためのフィードバック サイクルの一部になります。


##まとめ
簡単すぎてびっくりしました．きのことたけのこくらい判別し易いものであれば，かなりの確率でキレイに判別してくれますね．
ちなみに，これを飛行機の画像（Boeing737, 767, 777, 787）で判別させた際には，うまくいきませんでした．
Blackwidow Elite 英語配列を Windows で MacOS っぽく使いたい


## 状況
 - ゲーム開発用にゲーミングキーボードが必要
 - コーディングもするので英語配列が欲しい
 - 普段は Mac なので Windows でも操作系統を合わせたい
  - Ctrl + FBPN でのカーソル移動が好き

## 選択したキーボード
 - Razer Blackwidow Elite (黄軸) 英語配列
  - 職場でも使うのでうるさくない黄軸を選択
  - HHK 程ではないがスコスコ系でタイピングは心地よい

## 設定の変更
### Ctrl + FBPN でキーカーソルの移動
 - キーボードの公式アプリ「Razer Synapse 3」のハイパーシフトを利用
  - ハイパーシフトキーを押している間だけ他のキーの役割を変えることができる
  - 例えばHS(ハイパーシフト)中「P」を「↑(Up)」に割り当てると、[Ctrl + P]で上移動しているように動作する
 - Aキーの左にある[CapsLock]に[ハイパーシフト]を割り当てることで、Ctrl 操作”風”にできる

| コマンド | 動作 |
|:----|:----|
| HS + F | → |
| HS + B | ← |
| HS + P | ↑ |
| HS + N | ↓ |
| HS + A | Home (行頭へ移動) |
| HS + E | End (行末へ移動) |
| HS + K | カーソルから後ろを切り取りマクロ（Shift + End > Ctrl + X) |
| HS + H | Back Spase |
| HS + D | Delete |
| HS + W | Ctrl + W |
| HS + Q | Alt + F4 |
| HS + Z | Ctrl + Z (Undo) |
| HS + X | Ctrl + X (切り取り) |
| HS + C | Ctrl + C (コピー) |
| HS + V | Ctrl + V (貼り付け) |

### Command + S で保存みたいなことしたい（できるけどおすすめしない）
 - Razer Synapse で「左Alt」を「Ctrl」に割り当てる
 - かなり MacOS っぽい操作になります
 - ただ Alt の置き場所に困ります。他の操作に支障がでます(Alt + Tab をよく使うので)
  - Ctrl の位置に持ってくると押しづらい
  - Windows キーを Alt に変更できればいいのだけれども

### IME のオンオフ
 - 左右の Alt にそれぞれ IMEオン、オフを割り当てる
 - フリーソフト[alt-ime-ahk](URL:https://www.karakaram.com/alt-ime-on-off)を利用

## 所感
 - 文字列操作周りは大分快適
 - まったく同じではないけど妥協点ってところじゃないでしょうか

## おまけ：Blackwiodw Elite は MacOS で動くの？
 - 動きます。普通にキーボードと認識しますし、光ります。
 - ただし、Razer Synapse 3 が MacOS 非対応なのでキー設定やライティングの設定ができません。
Android Studio 3.4の更新内容

いろいろと追加/更新されたようなので雑にまとめる。

## 公式情報

### ブログ
https://android-developers.googleblog.com/2019/04/android-studio-34.html
### リリースノート
スクショがたくさんあり分かりやすい
https://developer.android.com/studio/releases/
### youtube
https://www.youtube.com/watch?v=3lDO5uFkJoQ

## 更新内容
### リソースマネージャが追加
Drawableのリソースをプレビュー、管理するツール
起動は `View > Tool Windows > Resource Manager`
アプリプロジェクト全体のドロアブル、色、およびレイアウトを統合ビューで視覚化
一括アセットのドラッグアンドドロップ
一括SVGからVectorDrawableへの変換がサポート
https://developer.android.com/studio/write/resource-manager

### Import Intentionsでコードからdependencyにライブラリ追加
コードから必要なライブラリをプロジェクトに追加することを提案してくれる。
たとえばWorkManagerとタイプすると、Gradleのdependencyにライブラリ追加するダイアログがでる
サポートはJetpackおよびFirebaseのみ？

### レイアウトエディタの改善
Attributesパネルが強化された。
Layout Editorの右側に出るやつ
各プロパティが便利にアクセスできるぽい？
カラーピッカーがついた？

### Android Gradle pluginが3.4.0に更新された
新しいプロジェクトは3.4.0を使おう

### Product Structureダイアログがパワーアップして
プロジェクトへの依存関係を表示/追加/更新できる、つまり便利になった。
ライブラリの管理できるようになり、新しいVersionなどが選べる。
ビルドファイル構成を改善するための提案などが表示
詳しくはここ
https://developer.android.com/studio/releases#psd

### R8がデフォルトになった
ProguardよりR8が高性能らしい

### Navigation Editorはすべての引数タイプをサポート
サポートされているタイプ https://developer.android.com/guide/navigation/navigation-pass-data

### Android Qベースエミュレータ追加
Google Pixel 3とGoogle Pixel 3 XLのデバイススキンも使える
（エミュレータでノッチが使える？）

## 感想
リソースマネージャが便利そうで良さげ。
Product Structureでライブラリのバージョン管理も嬉しい。

Android Studio 3.4 いいじゃん！
[JavaScript]setIntervalとsetTimeout

# setIntervalとsetTimeoutについて

今回はこの二つの基本的な使い方について解説したいと思います。
これらのメソッドは自動更新などに使うことができ、引数に時間を指定して関数を一定間隔で呼び出すことができます。


## setInterval();
まずsetIntervalについて説明します。
setIntervalメソッドは第一引数に指定した関数を第二引数に指定した時間の間隔でなんども呼び出します。
サンプルコードを下記に記します。

```setInterval.js
$(function(){
  setInterval('sample', 1000);
});
function sample() {
　//処理を記入
  };
```
これで定義できました。上記に処理は1000ミリ秒つまり、1秒ごとにsampleを実行するという意味になります。
条件分岐などを使って処理を止めたりしないと常に1秒ごとに呼び出されてしまいますので、気をつけましょう。

## setTimeout();
setTimeoutはsetIntervalと違い、指定した時間後に関数を一度しか呼び出しません。


```setTimeout.js
$(function(){
  sample();
});
function sample() {
　//処理を記入
  };
setTimeout(sample, 5000);
```

上記の意味は関数sampleを5秒後に呼び出すという意味になります。
関数sampleを繰り返さないのがポイントです。

ただし以下のように記述することによりsetIntervalのように繰り返すこともできます。

```setTimeout.js
$(function(){
  sample();
});
function sample() {
　//処理を記入
　setTimeout(sample, 5000);
  };
```

このようにsetTimeoutを関数内に定義することによりsetInterval同様5秒ごとに関数sampleを呼び出すという意味になります。
Cassandra のタイムスタンプ型は文字列で指定する

自分がデータベースでよく使う型で一番手が止まるのは、タイムスタンプ型です。
例えば Oracle だと to_date で日時を指定してみたり、それでも上手く指定できずに between を使って select 文を書いたりしています。

一方 Cassandra に関しては、タイムスタンプ型の指定がとても大らかで助かったので、まとめてみました。
※ cqlsh は 3.4.4 を使っています。

### Cassandra のタイムスタンプ型は文字列で指定する
以下のパターンは、全て Cassandra のタイムスタンプ型として成立します。

- ```2019-04-15``` （その日の0時0分として利用ができる）
- ```2019-04-15 00:00```　(分単位)
- ```2019-04-15 00:00:00```　（秒単位）
- ```2019-04-15 00:00:00+0000```　（4桁のタイムゾーンを指定。例は GMT）
- ```2019-04-15 00:00:00Z```　（cqlsh や環境変数で指定された時差を使用）

便利ですね。

※ 他にも Cassandra は時刻に関する表現として timeuuid 関数を持っています。
こちらは必ずユニークな値で保存でき、データの一意性を保ちたい場合に便利です。
webpacker で stylus-loader を使う

webpacker で stylusを使おうとして軽くハマってしまったのでメモ。

sass に特に不満はないんだけど、ディレクトリが深くなったときにいちいち index.sass 作らないと import できなくって嫌だったので stylus にしようかなってなった（stylus だと `import "directory/*"` ができる）んだけど、css 関連のloader の設定が webpacker の中にあってちょっと面倒だった。

もちろん、webpack ちゃんとわかってる人だったら簡単なんだろうけど、そんな人はきっと webpacker すでに剥がしてると思うのでこの記事は読まなくていい。前提として webpacker を使っていて、今後もしばらく剥がす予定がなくて、でも stylus 使いたい人（いるのか？）向け。

結論としては組み込みのsass-loaderをcloneして必要なところを書き換えてるだけ。

```js
// config/webpack/environment.js
const _ = require('lodash')
const webpack = require('webpack')
const { environemnt } = require('@rails/webpacker')

const sassLoader = environment.loaders.get('sass')
stylusLoader = _.cloneDeep(sassLoader)
stylusLoader.test = /.styl$/i
stylusLoader.use.slice(-1)[0].loader = 'stylus-loader'
environment.loaders.prepend('stylus', stylusLoader)

// ...
```

lodash に依存してるけど、それが嫌な人は自分でがんばってディープコピーして欲しい。ていうか、 ES が標準でディープコピーする手段提供して欲しい。
OpenAMのポータル画面へログインせずにAWSへSAML認証で接続する

前回、[OpenAMのSAML認証でAWSへログインするまでの設定](https://qiita.com/ot-nemoto/items/50b259bb53a5d41ad657)で、OpenAMの設定とAWSへSAML認証で接続する手順を書きました。

ブラウザ経由でOpenAMへログインすることで、AWSへそのOpenAMユーザでログインしていましたが、今回はOpenAMのAPIを使い、OpenAMへログインせずにAWSへ接続させる方法です。

※コマンド内で `jq` コマンドを使っています。インストールしていない方は使えるようにしてください。

# 管理者（Adminユーザ）

### ユーザ追加

ユーザは管理者アカウントで作成しても可能ですが、以下はAPIで作成する方法です。

**管理者のトークンIDを取得**

```sh
# 自身のOpenAM環境に合わせる
OPENAM_URI=http://openam.example.com/openam
REALM=/
ADMIN_USER=amAdmin
ADMIN_PASS=password

# AdminのTokenIdを取得
TOKEN_ID=$(curl -s -X POST \
  -H "X-OpenAM-Username: ${ADMIN_USER}" \
  -H "X-OpenAM-Password: ${ADMIN_PASS}" \
  -H "Content-Type: application/json" \
  ${OPENAM_URI}/json/authenticate?realm=${REALM} | jq -r '.tokenId')
echo ${TOKEN_ID}
  #
```

**ユーザの確認**

```sh
USER="ot-nemoto@example.com"
PASS=password

# 以下のARNは前回AWSに作成したロールのARNとSAMLプロバイダのARNです
AWS_ROLE_ARN=arn:aws:iam::012345678901:role/openam-user-role
AWS_SAML_PROVIDER_ARN=arn:aws:iam::012345678901:saml-provider/OpenAM
EMPLOYEE_NUMBER=${AWS_ROLE_ARN},${AWS_SAML_PROVIDER_ARN}

# ユーザ確認
curl -s -X GET \
  -H "iplanetDirectoryPro: ${TOKEN_ID}" \
  -H "Content-Type: application/json" \
  "${OPENAM_URI}/json/users?realm=/&_queryId=${USER}" | jq

# ユーザ作成
curl -s -X POST \
  -H "iplanetDirectoryPro: ${TOKEN_ID}" \
  -H "Content-Type: application/json" \
  -d "{
    \"username\": \"${USER}\",
    \"userpassword\": \"${PASS}\",
    \"mail\": \"${USER}\",
    \"employeeNumber\": \"${EMPLOYEE_NUMBER}\"
  }" \
  ${OPENAM_URI}/json/users/?_action=create | jq
```

### パスワード更新

作成したOpenAMのユーザのパスワードを変更するAPI。

```sh
curl -s -X PUT \
  -H "iplanetDirectoryPro: ${TOKEN_ID}" \
  -H "Content-Type: application/json" \
  -d "{
    \"username\": \"${USER}\",
    \"userpassword\": \"${PASS}\"
  }" \
  ${OPENAM_URI}/json/users/${USER} | jq
```

### 削除

OpenAMのユーザを削除するAPI。

```sh
curl -s -X DELETE \
  -H "iplanetDirectoryPro: ${TOKEN_ID}" \
  -H "Content-Type: application/json" \
  ${OPENAM_URI}/json/users/${USER} | jq
```

# 一般ユーザ

### AWSへログイン

**一般ユーザのトークンIDを取得**

管理者と同様に、操作するユーザのトークンIDを発行します。

```sh
USER="ot-nemoto@example.com"
PASS=password

# 一般ユーザのTokenIdを取得
TOKEN_ID=$(curl -s -X POST \
  -H "X-OpenAM-Username: ${USER}" \
  -H "X-OpenAM-Password: ${PASS}" \
  -H "Content-Type: application/json" \
  ${OPENAM_URI}/json/authenticate?realm=${REALM} | jq -r '.tokenId')
echo ${TOKEN_ID}
  #
```

**AWSへリダイレクトするHTMLを取得**

```sh
curl -s -XGET \
  -H "Cookie: iPlanetDirectoryPro=${TOKEN_ID}" \
  "${OPENAM_URI}/saml2/jsp/idpSSOInit.jsp?metaAlias=/idp&spEntityID=urn:amazon:webservices"
```

ここで得られるのはAWSへリダイレクトするURLです。
以下のようなHTMLが返ってきます

```html
<html>
<head>
    <title>Access rights validated</title>
</head>
<body onload="document.forms[0].submit()">
<form method="post" action="https&#x3a;&#x2f;&#x2f;signin.aws.amazon.com&#x2f;saml">

    <input type="hidden" name="SAMLResponse" value="PHNhbWxwOlJlc3BvbnNl..." />

    <noscript>
        <input type="submit" value="Submit SAMLResponse data " />
    </noscript>
</form>
</body>
```

これをブラウザ経由で開くと、onloadイベントで submit するので、AWSへ接続することが出来ます。

以上
ロケール環境設定を理解して使う


ロケール環境は全部で8種類あります。
それぞれに意味や優先順位、グループが存在します。

- LANG
- LC_COLLATE
- LC_CTYPE
- LC_MESSAGES
- LC_MONETARY
- LC_NUMERIC
- LC_TIME
- LC_ALL

## 設定の仕方

それぞれの環境変数は以下のように設定をします。

```
export LANG=en_US.UTF-8
```

## ロケール環境の意味

#### LANG
LANGは少々特殊な役割をしています。

LANGを設定するとロケール環境の大半がLANGと同じ内容で設定されます。
例えば`export LANG=en_US.UTF-8`を設定したとすれば、

<img width="518" alt="スクリーンショット 2019-04-22 11.12.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191025/ffa4b6e2-12a2-04bd-5856-1f4e88830dc1.png">

このように設定されます。(LC_CTYPEとLC_ALLは変更されていません)

LANGの優先順位は一番低いため、その他のロケール設定で部分的に上書きして使うことができます。

#### LC_COLLATE
文字のソート順に使用します。

#### LC_CTYPE
文字数の計算や判定に使用します。

#### LC_MESSAGES
通知・診断メッセージや対話式応答のフォーマットに使用します。

#### LC_MONETARY
通貨のフォーマットに使用します。

#### LC_NUMERIC
通貨ではない数値のフォーマットに使用します。

#### LC_TIME
日時フォーマットに使用します。

#### LC_ALL
LC_ALLは全てのロケール環境設定を一括で設定するためのものです。
LC_ALLの設定は最優先のため、その他のロケール設定を全て上書きします。

#### その他
その他にもいくつかロケール環境がありますが、`locale`コマンドで出力される有名な環境はこれだけです。


## 参考

- https://www.ibm.com/support/knowledgecenter/ja/SSMKHH_9.0.0/com.ibm.etools.mft.doc/ae19494_.htm
起動時のカーネルモジュールのロード

忘れないように。

起動時のカーネルモジュールのロードは、

- systemd-modules-load.service
- /etc/modprobe.d/
- /etc/modules-load.d/
- /etc/modules

に関係している。

## systemd-modules-load.service
statusの確認は次のように行う。

```bash
systemctl status systemd-modules-load.service
```

## /etc/modprobe.d/
ディレクトリ下にconfファイルを作成して、

- alias
- options

を記載する。alias/optionsは、コマンドでmodprobeする際にも使用される。

```
alias mod1 module_name
options mod1 param1=1 param2=2
```

## /etc/modules-load.d/
ディレクトリ下にconfファイルを作成して、起動時に読み込みたいモジュール名または、alias名のみを記載する。
modprobe.d以下でのalias/optionsが使用される。

```
mod1
```

## /etc/modules
ファイルがあればここに記載してもよい。ただし、/etd/modules-load.dにシンボリックリンクがはられているか確認する。

```
root@debian-armhf:~# ls -ltr /etc/modules-load.d/                                                                                                                                             
total 0
lrwxrwxrwx 1 root root 10 Jan 15  2019 modules.conf -> ../modules

```
App Store Reviewガイドライン、2.3.1に抵触しリジェクトされた

#まずはじめに
[AppStoreReviewガイドライン2.3 正確なメタデータ](https://developer.apple.com/jp/app-store/review/guidelines/#accurate-metadata)
この中で、2.3.1とは、

> Appに隠し機能または提示していない機能を含めないでください

これにつきます。

自分が作成している、[Animix](https://itunes.apple.com/us/app/animix-%E3%82%A2%E3%83%8B%E3%83%A1%E5%B0%82%E9%96%80%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%97%E3%83%AA/id1448653072?l=ja&ls=1&mt=8)というアプリでbugfixをした申請がこれに抵触しリジェクトされてしまいました。

#リジェクト内容
おそらくコードを自動でチェックする機能に引っかかったんでしょう。
件のアプリでは、サーバー側から表示・非表示・表示内容をコントロールできる動画広告の機能が入っています。
ですが現状、表示する広告がないため、ユーザーから見えない状態となっています。
どこが抵触してるか教えてくれてないから、完全に推測となります。

以下、内容は同じなので、別アプリのリジェクト文言を転載させていただきました。
今後レビューが遅くなることを覚悟せい、だの、アカウント消すだの、結構過激なこと書いてます。

>From Apple 2. 3 Performance: Accurate Metadata Guideline 2.3.1 - Performance

>We discovered that your app contains hidden features. Specifically, It would be appropriate to remove all code obfuscation and selector mangling from this app before resubmitting for review.

>The next submission of this app may require a longer review time.

>Next Steps

>Review the Performance section of the App Store Review Guidelines.
Ensure your app is compliant with all sections of the App Store Review Guidelines and the Terms & Conditions of the Apple Developer Program.
Once your app is fully compliant, resubmit your app for review.
Submitting apps designed to mislead or harm customers or evade the review process may result in the termination of your Apple Developer Program account. Review the Terms & Conditions of the Apple Developer Program to learn more about our policies regarding termination.

>If you believe your app is compliant with the App Store Review Guidelines, you may submit an appeal. Alternatively, you may provide additional details about your app by replying directly to this message.

#対応・解決
当然、ユーザーに危害を加える気もないし、そもそもどこが抵触したかもわからないので、その旨を送信してみました。
すると、上述の脅しのような文言が嘘のようにあっさり審査通りました。
今までも色々なリジェクトをいただきましたが、誠意ある対応が正解というどうしようもない結論に至りました。

実際に送った文言
>Thank you for your review.

>We have no intention of misleading or harm customers or evade the review process. And if our app include a problem, we want to modify it to be compliant with the App Store Review Guidelines.

>Therefor, please tell us additional details information about this reject.

>Best regards,
Gitサービスをssh鍵で利用する[決定版]

鍵の作り方毎回忘れるので覚えているうちに書き残します。

## 鍵生成
コマンドは、以下の感じで使えばいいと思います。
`ssh-keygen -o -t rsa -C"[name]@mail.com" -f"[name]_rsa"`

## `.ssh/config`に登録
```config
Host sample-gitlab
  User git
  HostName gitlab.com
  identityFile ~/.ssh/[name]_rsa
```
登録されたものがちゃんと動くかテスト
`ssh -T [host name]`

## Gitサービスに登録
pubキーをクリップボードにコピー

```MacOS
pbcopy < ~/.ssh/[name]_rsa.pub
```

```Windows
clip < ~/.ssh/[name]_rsa.pub
```

## remote add
`~/.ssh/config`で書いたHost名をgit@の後に入れてremoteを登録する

```bash
git remote add origin git@[host name]:[user name]/[repository name].git
```

## ひとこと
Happy Hacking!
[バイオインフォ向け]俺のDocker & Singularity環境メモ

強い人の助言大歓迎です。
遺伝研のページだけだと自前で開発したDocker imageをSingularityで使う方法がイマイチ分かり辛かったのでメモしておきます。

# バイオインフォの人がDocker学ぶ動機

- とりあえず他人の作ったDockerファイル使ってソフトウェアを動かす、ぐらいは今後やらざるを得ない
- どうせある程度覚えなきゃいけないのなら自前でDocker環境で解析環境作れた方がhappy、ソフトウェアインストールバトルでの勝率がグッと上がる
- 遺伝研スパコンで使えるようになったので覚えるにはいい時期

# 参考

[bio分野向けのDockerコンテナをつくる on MacOSX
](https://qiita.com/hiromasaono/items/5b0af4a03357fd38c098)
[Install singularity on Mac](https://qiita.com/daikumatan/private/775e3cea91bac6147974)

# DockerFileの雛形

[Docker上のCentOSにPython3と、関連ライブラリpip, virtualenvとフレームワークDjango, bottle, Flaskのインストール！これらをまとめたDockerfile付き！
](https://qiita.com/RyosukeKamei/items/eca9687162b7fe122094)
これが良さそうだったのでコピペしたが、諸々進めていく中でubuntuの方がいいなとなったのでubuntuに変更した。

現状のメタゲノム解析用に作っているDocker環境は以下のような感じ。

https://github.com/kmooog/metagenome-pipeline/blob/master/Dockerfile

# 環境

<img width="631" alt="スクリーンショット 2019-04-22 10.43.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175646/98c99fd9-5527-c2be-3f9c-661c78f9a1c7.png">

- 遺伝研スパコンで使えるのは権限の関係でDockerではなくSingularity。
- Singularity imageはDocker fileからもビルドできるが、ビルドの権限は遺伝研スパコンでは与えられていないのでlocalでやる必要がある。

- gitHubとDockerHubを連動させるとgitにpushするだけでclが走りDocker imageが作られるので、それをlocalのvagrant box内でsingularity pullしsingularity imageをビルド。singularityではDockerと違い、ビルドしたイメージがカレントディレクトリに作られるので、それをそのままscpで遺伝研スパコンに送る。

# 所感

- ソフトウェア開発じゃなくて解析の場合はDocker Imageをどの粒度で作るかとか、並列化はどのレイヤでやるかとか、色々考える余地が多くBest practiceにたどり着く道のりはまぁまぁ長そう。Docker fileを最終的に公開するのかどうかとかでも変わってくると思うので、プロダクトマネジメント力が問われてくる。
- それでもソフトウェアの依存関係の悩みから解放されるメリットは大きいと思う
- また基本的に性格が雑で環境構築/依存関係とか言葉聞くだけでジンマシン出ちゃうよ、というタイプなので、コンテナ環境はその辺の苦しみの仕組みでの対処として最適
- しかしsingularity対応のスパコンまだまだ少ないので、現状ではソフトの悩みから解放される代わりにハード選びに制約受けることにはなりそう
疑似攻撃シート

## はじめに
`WAF`や`AntiVirus`などのセキュリティソフトをインストールした際、本当に正しくインストールされているか?攻撃をちゃんと防いでくれるのか?ということを確認したいために、簡単に疑似攻撃する手法をまとめようと思います。

## WAF
### SQL Injection
```
https://${FQDN}/?id=%27+or+1%3D1--%27&Submit=Submit#
```
よくある`SQLInjection`の攻撃パターンです。このURLをブラウザから叩くだけで擬似攻撃となります。
ちなみに僕は AWS WAF のマネージドルール`Cyber Security Cloud Managed Rules for AWS WAF -HighSecurity OWASP Set-`に対して実施しましたが、ちゃんと攻撃とみなしてくれて、想定通りブロックされることがわかりました。


## AntiVirus
(途中)
AndroidのカメラLibraryをピックアップ

カメラを使うAndroidアプリを作るとき、どう実装するのが楽なのか？
`android.hardware.camera2`を使ってスクラッチで実装するのもいいが、かなーり大変。
もっと楽に実装できないか？と思い、カメラライブラリを調べてみた。

※ star数は2019/04/22時点の数値です。

## google/cameraview
https://github.com/google/cameraview

### star数
4341

### 感想
google公式のライブラリだが、Latest commit が 2017年で、放置されてる。
コードが古いのか、今のアーキテクチャに対応した便利そうなメソッドはなさそう。
（ライフサイクルを検知して自動で色々やってほしい）

スター数は多いが、放置＆時代遅れっぽいので理由がない限り使わないだろう。

## CameraKit-Android
https://github.com/CameraKit/camerakit-android
### star数
4049
### 感想
Java以外にCやC++コードもあるようで、ネイティブなのか？
パーミッション処理を自動ハンドリングしてくれるぽい、素晴らしい
プレビューのスケールサイズを指定できるらしい、低スペ端末にはありがたいかも

色々な機能が揃っていて便利そう、カスタマイズ性も高い
スター数も多いし安心
使ってみたい

## RedApparat/Fotoappara
https://github.com/RedApparat/Fotoapparat
### star数
3264
### 感想
ほぼKotlinで作られているせいか、精錬された実装になっている
GitHubのサンプル見ると分かるが、カメラ撮影の実装コード量が超少ない
この記事で紹介しているライブラリ内で一番シンプルに書ける

自分は使ったことないが、いつか使ってみたい

## natario1/CameraView
https://github.com/natario1/CameraView
### star数
1855
### 感想
このライブラリは使用したことがあるが、普通に良い
Activity/Fragmentのライフサイクルに合わせてカメラをコントロールしてくれるのが便利
こんな感じでライフサイクルを渡せる`cameraView.setLifecycleOwner(viewLifecycleOwner)`
`FrameProcessor`でリアルタイムな画像キャプチャも対応しているので、バーコード読み取りに使えた。
なによりカメラに対するコード量がかなり少なくできたので、良いライブラリである

## もっと他のライブラリを知りたい
ここにたくさん載ってますぜ

Android Store | Camera
https://mindorks.com/android/store/Camera
AWS AssumeRole手順書(S3バケットへのファイルアップロード)

## やりたい事
AアカウントからBアカウントへAssumeRoleして、Bアカウントが持つS3バケットへファイルのアップロードを行う。

## なぜAssumeRoleが必要なのか
アクセスを許可すればAアカウントからBアカウントのもつS3バケットへのアップロードは可能だが、オブジェクトのオーナーがAアカウントになってしまう。
こうなると、Bアカウントが持つS3バケットに設定するバケットポリシーが無視されたり、オブジェクトのアクセスができなくなるなど、不都合なことが起こる。
なので、AssumeRoleしてBアカウントとしてファイルをアップロードすることで、S3バケットの管理者とオブジェクトの管理者を統一しておく。
これでアクセス権限などの予期せぬ問題を起こしにくくする。

## 手順
- Aアカウント管理者はA-Roleを作る。例としてLambdaの実行ロールとかBatchのタスクロールとか。これのARNをコピーしてBアカウント管理者に送る。
- Bアカウント管理者はB-Roleを作る。これはBアカウントが持つS3バケットへの書き込み権限を付与する。
- B-Roleの信頼エンティティにA-RoleのARNを入れ、A-RoleからのAssumeRoleリクエストを承認できるようにしておく。「信頼関係の編集」より、`Principal`にKeyをAWS,Valueに信頼するIAMロールのARNを入力します。`Action`には`sts:AssumeRole`を入力する。これでA-RoleからのAssumeRoleリクエストを承認する事ができる。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxx:role/A-Role"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

- B-RoleのARNをコピーしてAアカウント管理者に送る。
- A-RoleにAssumeRoleする為のポリシーを設定する。インラインポリシーで大丈夫。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::yyy:role/B-Role"
    }
  ]
}
```

これで作業は完了。A-Roleを使ってB-RoleをAssumeする為のサンプルコードは以下

```python
    # A-Roleの権限を使って、B-RoleのAssumeリクエストを送信。この時にA-RoleにAssumeRoleのポリシーがないと権限不足でエラーとなる。
    sts_default_provider_chain = boto3.client('sts')
    creds = sts_default_provider_chain.assume_role(
        RoleArn="arn:aws:iam::yyy:role/B-Role",
        RoleSessionName="session-test",
        DurationSeconds=900
    )

    # 受け取ったB-Roleのクレデンシャル情報を使って、Sessionを作る。
    session = Session(aws_access_key_id=creds['Credentials']['AccessKeyId'],
                      aws_secret_access_key=creds['Credentials']['SecretAccessKey'],
                      aws_session_token=creds['Credentials']['SessionToken'],
                      region_name='ap-northeast-1')

    # 作成したSessionで新たにリソースを作る。S3へのアクセスがしたいのでS3を指定。
    s3 = session.resource('s3')

    # ファイルをアップロード。ここで出来なければB-RoleにS3関連の権限がないので確認する。
    s3.meta.client.upload_file('A.png', "B-bucket", 'A.png')
```
Google選択された各結果を新しいブラウザ ウィンドウで開く(ブラウザ:IE)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381112/3aef1d4d-2e24-3458-e9a4-91e661812b06.png)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381112/3bfbd633-86e8-7ed0-5ced-cb41c6cf016e.png)
railsで開発環境のＤＢをPostgreSQLにするときにroleがローカルユーザー名になっててはまった話

デフォルトのユーザー「postgres」でPostgreSQLにログインしたときにroleがローカルのユーザー名になっていて、修正に時間がとられたのでここにまとめておきます。結構強引に解決したので、扱いには注意が必要だと思います。

# 開発環境
- windows7
- ruby 2.4.5p335 (2018-10-18 revision 65137) [x64-mingw32]
- Rails 5.2.3
- psql (PostgreSQL) 10.7

# 事前準備

```
$ rails new YOUR_APP -d postgresql
$ rails g scaffold YOUR_MODEL_NAME
$ rails db:create db:migrate
```

# エラー内容
該当コマンド：rails db:create db:migrate

```
$ rails db:create db:migrate
Created database '<app_name>'
FATAL:  role "<user_name>" does not exist
Couldn't create '<app_name>' database. Please check your configuration
rails aborted!
ActiveRecord::NoDatabaseError: FATAL:  role "<user_name>" does not exist.
```

# 解決法
PostgreSQLに管理者権限を持つ"postgres"でログインする。

```
psql --username=postgres
```

<user_name>に管理者権限(ついでにログイン権限)を付加して、PostgreSQLから抜ける。

```
postgres=# CREATE ROLE <user_name> SUPERUSER;
postgres=# ALTER ROLE <user_name> LOGIN;
postgres=# \n
```

これで正常に動作するはずです。


#参考サイト
エンジニアの入り口|【初心者向け】PostgreSQLのロールについて分かり易く解説
https://eng-entrance.com/postgresql-role
atomでgithubにpush

# 手順
１．atomでファイルを作成し保存する。
２．ファイルがUnstaged Changesに表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396969/34a566e2-46ee-b109-80fd-6f888a7b04fc.png)
３．Qiita￥a.mdをダブルクリックするとStaged Chagesに移動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396969/ca8bb949-1877-d645-e9cd-d69f9ae155a6.png)
４．Commit messageを書いてCommit to masterをクリックすると右下にPush1と表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396969/5c4793fc-fd78-c5ad-d720-e7f61fca3d18.png)
５．Pushを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396969/cf562e53-916a-1f8a-bd33-bb3026b808c2.png)
６．githubに反映されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396969/fc43d352-d954-ac2b-bc73-45383ff2f319.png)
【CraftCMS】出力値を翻訳する

下準備
=================
翻訳する値を格納するディレクトリを作る

```sh
mkdir craft/translations
```

とりあえず英語でやるとして

```sh
# cd translations
mkdir en
touch site.php
```

site.phpで英語対応する文字を定義する

```php:site.php
return [
           "必須"  => "req",
    	   "お名前" => "name",
       ];
```

コンパネ→設定→サイトで英語版サイトのURLを定義する

<img width="669" alt="スクリーンショット 2019-04-22 11.03.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/a06eeca5-9958-cf23-0cc1-21cfabfa2eb8.png">

実装
=================
あとはtwigでtranslateフィルタを掛けるだけ

```twig
{{お名前|t}}
{{必須|t}}
```

確認
=============


### 日本語版 (mentaicoo.jp)
![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/5a69a888-7384-a62b-4f40-f1e1cbe18f2a.png)

<hr />
### 英語版 (mentaicoo.jp/en)
<img width="463" alt="スクリーンショット 2019-04-22 11.10.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/4444c580-8e12-ad31-d576-08d4f58ffbcc.png">

結論
==========
ということでCMSで管理しない固定値も楽々多言語対応が可能
という話でした。

**おわり。**
Ruby と JavaScript の Template literal (文字列展開、式展開)

### Ruby

`Double quotes + #{} ` で展開できる。

```ruby
era_name = '令和'
puts "次の元号は...#{era_name}です！" # 次の元号は...令和です！
```

Single quotes で囲むと展開されない。

```ruby
era_name = '令和'
puts '次の元号は...#{era_name}です！' # 次の元号は...#{era_name}です！
```

Back quotes で囲むとコマンドとして実行されるのでエラーになる。

```ruby
era_name = '令和'
puts `次の元号は...#{era_name}です！` # No such file or directory - 次の元号は...令和です！ (Errno::ENOENT)
```

### JavaScript

`Back quotes + ${}` で展開できる。

```javascript
const eraName = '令和';
console.log(`次の元号は...${eraName}です！`); // 次の元号は...令和です！
```

Single quotes, Double quotes で囲むと展開されない。

```javascript
const eraName = '令和';
console.log('次の元号は...${eraName}です！'); // 次の元号は...${era_name}です！
console.log("次の元号は...${eraName}です！"); // 次の元号は...${era_name}です！
```

### まとめ

- Ruby で文字列展開したい時は、`Double quotes + #{}`
- JavaScript で文字列展開したい時は、`Back quotes + ${}`
Node.jsのTypeScriptにおけるエラーの定義はinterfaceだった

# 概要(TL;DR)
typeScriptではエラーオブジェクトはインターフェースとして定義されていました。

# 使っているTypeScriptのバージョン
typescript 3.2.2

# 実際の定義
```typescript:lib.es5.d.ts
interface Error {
    name: string;
    message: string;
    stack?: string;
}
```

つまりこのinterfaceをimplementsで実装してやればネイティブのエラーを侵食することなくオリジナルのエラーを実装できるってことですね。

# 実際にエラークラスを実装してみた
Rest APIエラー処理に利用したかったので、ネイティブのErrorインターフェースをimplementsした、各エラーの基底となる抽象クラスを作り、そのクラスを継承して各エラークラスを実装する形にしました。

```typescript:CommonError.ts
export abstract class CommonError implements Error {
  name: string;
  code: number;
  message: string;
  body?: any;
  // 最終的にjsonでレスポンスするのでそのための変換関数
  public toJson(): any {
    return {
      name: this.name,
      code: this.code,
      message: this.message,
      body: this.body
    }
  }
}
```

```typescript:MyError.ts
import { CommonError } from 'path/to/commonError';

export class MyError extends CommonError {
  constructor (){
    super();
    this.name = 'MyError';
    this.code = 500;
    this.message = 'MyError is occurred.'
  }
}
```

# まとめ
- ネイティブのエラーの定義はinterface
- なのでそれをimplementsする
- 各エラーの基底となるクラスを作り、それを継承して各エラークラスを作ろう
Pythonでハノイの塔を再現

## ハノイの塔とは

ハノイの塔（ハノイのとう、Tower of Hanoi）はパズルの一種。
![500px-Tower_of_Hanoi.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168441/56c956a5-2fe3-4da3-f5d1-8192465590b2.jpeg)

### ルール
以下のルールに従ってすべての円盤を右端の杭に移動させられれば完成。

- 3本の杭と、中央に穴の開いた大きさの異なる複数の円盤から構成される。
- 最初はすべての円盤が左端の杭に小さいものが上になるように順に積み重ねられている。
- 円盤を一回に一枚ずつどれかの杭に移動させることができるが、小さな円盤の上に大きな円盤を乗せることはできない。

![Tower_of_Hanoi_4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168441/b7cd2f36-25aa-be3a-8899-807c3e5445f1.gif)

### 数学的な見地
上記のルールに沿って、整理された状態からだと、n枚の円盤すべてを移動させるにかかる手数は、(2n − 1)の式で計算可能である。

### 参考
[https://ja.wikipedia.org/wiki/ハノイの塔](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%8E%E3%82%A4%E3%81%AE%E5%A1%94)

## 思いついた経緯
もともと、最近ハマっていたパズルゲームでもあり、
所持していた書籍でも解説されていたが、殆どが、手数の計算についてであったので、
視覚的に、ハノイ盤の動きを再現できるか？、実際に計算結果と同じになるか？を目で確認したく、着手しました。

## github
[github.com/biz-nakashima001/python_hanoi](https://github.com/biz-nakashima001/python_hanoi)

### 実行方法

pythonスクリプト　hanoi.pyを起動後、
hanoiの数を聞かれるので、希望の段数を入力して下さい。

その後、予測手数の計算結果が出力されるので、
確認後、スリープ時間を入力して下さい。
１秒単位で設定でき、スリープ不要なら０秒を設定して下さい。

```
python3 hanoi.py 
hanoiの数＜: 6
予想手数: ２^n -1 ->  63
スリープ(秒)＜: 1
```

### 実行イメージ
<img width="690" alt="スクリーンショット 2019-04-22 10.07.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168441/0dc599df-ac2b-c650-1017-7ff7aca8f794.png">

<img width="629" alt="スクリーンショット 2019-04-22 13.10.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168441/8ec00eaa-b90f-994a-3c42-e365916ed8c5.png">



##  やり残し

- numpyをもっと駆使して、縦方向で表示したい。 
- 他のアルゴリズム、パズルも視覚的(webページ等)に表現してみたい。

## 参考書籍
- [プログラマの数学 (結城 浩[著])](https://www.hyuki.com/math/)
- [プログラミング言語図鑑 (増井敏克[著])](http://www.socym.co.jp/book/1108)
お前らのコミットメッセージは間違っている！！ (JavaScriptでGit Hooks)

# TL;DR
コミットメッセージにプレフィックスをつけるとログの検索効率が上がる、レビュアーが見た時わかりやすい、プレフィックス単位でコミットの粒度を揃えられるなど利点多数。
⬇️
でも形式がその時でまちまち、忘れたりタイポしてしまう。（個人開発ではめんどくさがってやらない）
⬇️
<b>「Git Hooks」</b>という仕組みを利用すれば、コミットメッセージのフォーマットチェックを行い、強制させることができる。
⬇️
ネット上のGit Hooksのサンプルコードはシェルスクリプトばかり😇めんどい、わからない、シェル職人芸が必要（！？）。
⬇️
<b>「husky」</b>を使えば(Node)JSでも簡単にいけるぞ〜

そんなお話！！

## プレフィックス
プレフィックスのルールについては、以下の方の記事が参考になります。
[ 【今日からできる】コミットメッセージに 「プレフィックス」 をつけるだけで、開発効率が上がった話 ](https://qiita.com/numanomanu/items/45dd285b286a1f7280ed)


##Git Hooksについて
コミットやプッシュなどをトリガーに任意のスクリプトを実行することができる仕組み。
今回紹介するコミットメッセージのチェックや、プッシュ直前にテストを実行、ソースにデバック用コード（console.log）などの消し忘れチェックなどにも使える。

詳しくは以下を参照
[ Git公式「Git のカスタマイズ - Git フック」 ](https://git-scm.com/book/ja/v1/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%95%E3%83%83%E3%82%AF)

<b>ここで一つ問題なのが、フック本体は.gitディレクトリ配下にあるので、プロジェクトメンバー間で共有できないのである！！</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57833/f9572751-a0f4-4da0-9063-0a2e1d879e48.png)

## husky
前述の問題は、Node.jsプロジェクトであれば<b>「husky」</b>を導入することで簡単に解決できる。

```
npm install husky --save-dev 
```
#### package.jsonに追記
```json

{
  "husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }
}
```

## 実践
任意のディレクトリにソースファイルを配置して呼び出すだけ
コミットメッセージをチェックしたければ、「commit-msg」にフックさせる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57833/848f73aa-fe96-187d-d818-13f5d9cda61a.png)
コミットメッセージは.git/COMMIT_EDITMSGファイルの記載内容をチェックするばおk

```js

/* git hoooks commit-msg */
/* コミットメッセージのprefix確認 例： hoge: */
const boxen = require('boxen');
const fs = require('fs');
// プレフィックス一覧
const prefix = ['fix', 'add', 'feat', 'refactor', 'perf', 'style'];

//コミットメッセージ取得、チェック
let git_message = fs.readFileSync('./.git/COMMIT_EDITMSG', 'utf8').trim();
let isMissmatch = !prefix.some(str => {
   let pattern = new RegExp(String.raw`^${str}:\s.*`, 'i');
   return git_message.match(pattern);
});

if(isMissmatch){
   console.error(boxen('☠⚠️コミットメッセージにプレフィックスをつけてね @delmontz  prefix:半角スペース ⚠️️☠', {
      borderStyle: 'double',
      align: 'center'
   }));
   //異常終了 コミット中止
   process.exit(1);
}else{
   //正常終了
   process.exit(0);
}
```
ちなみに
<b>「boxen」</b>を導入するとこんな感じでターミナルに表示させることができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57833/95c5e186-fc97-8ce3-a058-c1898b635621.png)

## おまけ
よくある「マスターブランチにプッシュしちゃった☆いっけねー　てへぺろ☠️」など
任意のブランチへのプッシュを防止するには「pre-push」にフックさせる

```js
const execSync = require('child_process').execSync;
const boxen = require('boxen');

const branch_name = execSync(`git branch --contains`).toString().match(/\* (?:\(no branch, rebasing )?([^)\n]+)/)[1];

if (branch_name === 'master' || branch_name === 'release') {
   console.error(boxen(`☠⚠️⚠️⚠️${branch_name}ブランチにpushしないで！！ @delmontz⚠️⚠️⚠️️☠`, {
      borderStyle: 'double',
      align: 'center'
   }));
   //異常終了 push中止
   process.exit(1);
}else{
   //正常終了
   process.exit(0);
}
```
Windowsでキーボードの言語設定が誤認識されたときの応急処置【メモ】

# 応急処置

- とりあえず再起動（いちばん簡単）
- タスクバーからIMEをトグルする
- [Capslock/英数]+[Shift]をがちゃがちゃしてトグル（New!）
- USキーボードに慣れる
    - cf. [USキーボードと日本のキーボードの違い](http://www.nagasaki-gaigo.ac.jp/toguchi/pc/multilingual/keyboard_us_jis.htm)
- 英語ネイティブになる

# 再起動＠日本語WindowsでUSのIMEを載せている場合

できるだけ早めにWin+Space等で，IMEの言語を日本語に切り替えておくと，バグらない．

# その他

- [PCのキーボードがおかしくなった。半角/全角キーが効かなくなった場合の対処法 - ぼくんちのTV 別館](https://freesoft.tvbok.com/tips/windows/keyboard.html)