OmniAICreator/Qiita-1.07M huggingface dataset:
SpringBoot2.2+ThymeleafでHTTP PUT/DELETE メソッドを扱う

SpringMVCのControllerではHTTPメソッドとしてPUT/DELETEを扱うことが出来ますが、HTML5ではいまだにこれらのHTTPメソッドを扱うことができません。
このギャップを埋めるためにこれまでは、

- ControllerのマッピングではPUT/DELETEメソッドへのマッピングを定義する

```Controller.java
@Controller
@RequestMapping("/item")
public class ItemController {
    ...
    @DeleteMapping("{id}")
    public String delete(@PathVariable("id") Long id) {
        service.delete(id);
        return "redirect:/item";
    }
}
```

- thymeleaf側でput/deleteメソッドのフォームを定義するとpostに置き換えて_methodというhiddenパラメータを埋め込む

```template.html
<form th:action="@{/item/{id}(id=*{id})}" th:method="delete">
    <input type="submit" value="delete" />
</form>
```

```rendered.html
<form action="/item/1" method="post">
    <input type="hidden" name="_method" value="delete" />
    <input type="submit" value="delete" />
</form>
```

- HiddenHttpMethodFilterというフィルタでこのhiddenパラメータを検知するとリクエストメソッドを差し替える

というアプローチを取っていました。

SpringBoot 2.1 までは、この HiddenHttpMethodFilter がデフォルトの AutoConfiguration で有効化されていたため、特に意識することなく利用できていましたが、SpringBoot 2.2 からデフォルトの挙動が変わり、オフになったようです。

[Spring Boot 2.2 Release Notes: HttpHiddenMethodFilter disabled by default](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#httphiddenmethodfilter-disabled-by-default)

リリースノートによると、
> it causes early consumption of a request body if the body may contain parameters.

ということで、early consumption が何を指すのかは理解できなかったのですが、やりたいことに対してフィルタを噛ませるオーバーヘッドのデメリットの方が大きいという感じなのでしょうか。
HTMLでPUT/DELETEがサポートされる気配はないですし、REST APIでもないHTMLなWebサイトから無理にPUT/DELETEメソッド使う必要もないでしょうみたいな話なのかもしれません。

HttpHiddenMethodFilterを使いたい場合は、Configurationで有効にしてあげれば良いとのこと。

```application.yml
spring.mvc.hiddenmethod.filter.enabled: true
```

これでこれまで通りHTMLからPUT/DELETEメソッドを利用することができます。
ですが、SpringBootのデフォルトでdisabledになったということはあまり使わないほうがいいのでしょうかね。

### 追記

なぜデフォルトから外されたのか。という点について。
以下のIssueあたりで議論されていました。

https://github.com/spring-projects/spring-boot/issues/16953
https://github.com/spring-projects/spring-boot/issues/18088

ざっくりまとめると

- テンプレートエンジンを使用せずAPIとして利用するなら不要
- MultipartFileがリクエストパラメータに含まれていた場合にフィルタの処理に時間がかかっている
- MaxUploadSizeを超えるエラーが起きた場合にFilterでエラーを投げてしまうためMVCでハンドリングできない

というあたりが理由のようです。
このあたりを踏まえて問題ない場合に有効にするのがよさそう。
AWS LambdaのNode.jsのランタイム更新時確認手順書

なかったんで用意しておきました。まだ本番環境でサポート期限間近のランタイムを使っている人は参考にしてください。
※当時はNode.js 8.10系が対象でした。

## TL;DR
- AWS Lambdaのランタイムの更新はダウンタイムがないので本番環境への適用もサービス稼働中でOK
- ランタイム更新時の動作確認は推奨
- 更新はAWSがランタイムサポートポリシーで定めている日付より前に実施する

## 手順
1. 本番環境以外の環境で本番環境にデプロイされている資源と同じものをデプロイする
2. デプロイした環境のLambdaのランタイムを上げる
3. 動作確認を実施
4. 問題なければ本番環境(ST環境　→　本番環境の順番でも)のLambdaのランタイムを更新する

## 気になるところ

#### 廃止(更新)をすぎても更新可能なのか
これについてAWSサポートに問い合わせてみました。
AWSサポート内の過去事例として、廃止(更新)以降でもランタイムの移行(サポート対象バージョンへの移行)が可能だった例があったそうですが、ドキュメントにも明記がないように、それが必ずしも可能というわけでもないので、AWS的には非推奨という意見をもらいました。
そのためランタイムの更新は必ずAWSの[ランタイムサポートポリシー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtime-support-policy.html)が掲げる日付よりも前に行いましょう。

また、ランタイムの更新時には **ダウンタイムが発生することはない** という意見も同時にいただいているので、本番環境で利用中の関数でもサービスを停止させることなく更新することが可能です。

#### ランタイム更新時の動作確認は必須なのか
こちらAWS SAに口頭で確認をしてみました。結論からいうと **すべき** です
>Node.jsのRuntimeをあげる時は、syntax errorやnode_modulesにおける依存関係の中でエラーが発生する可能性があるので動作確認は必須。

以下別途いただいた懸念すべき点
>・Node.js 12 と互換性のないコードが含まれていないか。
・Lambda の実行環境の OS には Amazon Linux と Amazon Linux 2 があるが、 OS に依存したコード (コードから特定のシェルコマンドを呼んでいる等) が含まれていないか。

Node.jsのライフサイクルは約2年なので、その検証に時間を取られることを嫌いNode.jsそのものを選択肢から外すケースもあるそうです。

検証ちゃんとやろうね。


### 最後に
え？まだ本番環境でNode.js 8.10系を使ってる？
じゃあランタイムの更新しますか。
Node.js の Rest で Cloud Firestore のデータを削除 (Delete)

```js:firestore_delete_rest.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	firestore_delete_rest.js
//
//					Feb/01/2020
//
// ---------------------------------------------------------------
var fs = require("fs")
var get_token = require('./get_token.js')

// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const key_in=process.argv[2]
console.log (key_in)

const env = process.env
const json_str = fs.readFileSync (env.GOOGLE_APPLICATION_CREDENTIALS,'utf8')
const dict_aa = JSON.parse (json_str)
const project_id = dict_aa['project_id']
console.log(project_id)

const token = get_token.get_token_proc()

const project = 'project-jan25-2020'
const url="https://firestore.googleapis.com/v1/projects/" + project_id + "/databases/(default)/documents/cities/" + key_in

var Client = require('node-rest-client').Client

var client = new Client()

var args = {
    headers: { "Authorization": "Bearer " + token}
	}

try
	{
	client.delete(url, args, function (data, response) {
//			console.log(response)
			})
	console.error ("*** 終了 ***")
	}
	catch (error)
	{
	console.error ("*** error *** from client.get ***")
	console.error (error)
	}

// ---------------------------------------------------------------
```

get_token.js はこちら
[Node.js の Rest で Cloud Firestore のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/154aba68cb00e77c2a0a)

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_delete_rest.js t0921
```
Node.js の Rest で Cloud Firestore のデータを更新 (Update)

```js:firestore_update_rest.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	firestore_update_rest.js
//
//					Feb/01/2020
//
// ---------------------------------------------------------------
var fs = require("fs")
var get_token = require('./get_token.js')

// ---------------------------------------------------------------
function patch_proc(token,url,str_json)
{
	const args = {
		data: str_json,
		headers: { "Authorization": "Bearer " + token}
		}

	try
	{
	client.patch(url, args, function (data, response) {
		console.log(data)
			})
	console.error ("*** 終了 ***")
	}
	catch (error)
	{
	console.error ("*** error *** from client.get ***")
	console.error (error)
	}
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const key_in=process.argv[2]
const population_in=process.argv[3]

console.log (key_in + "\t" + population_in)
const today = new Date ()
var ddx = (1900 + today.getYear ()) + "-" + (today.getMonth () +1)
ddx += "-" + today.getDate ()
console.log(ddx)

const env = process.env
const json_str = fs.readFileSync (env.GOOGLE_APPLICATION_CREDENTIALS,'utf8')
const dict_aa = JSON.parse (json_str)
const project_id = dict_aa['project_id']
console.log(project_id)

const token = get_token.get_token_proc()

const url="https://firestore.googleapis.com/v1/projects/" + project_id + "/databases/(default)/documents/cities/" + key_in

var Client = require('node-rest-client').Client

var client = new Client()

var args = {
    headers: { "Authorization": "Bearer " + token}
	}

client.get(url, args, function (data, response) {
	console.log(data.fields)

	data.fields.population.integerValue = population_in
	data.fields.date_mod.stringValue = ddx
	const str_json =  JSON.stringify(data)

	patch_proc(token,url,str_json)
	})

// ---------------------------------------------------------------
```

get_token.js はこちら
[Node.js の Rest で Cloud Firestore のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/154aba68cb00e77c2a0a)

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_update_rest.js t0921 8942700
```
Node.js の Rest で Cloud Firestore のデータを読む (Read)

```js:firestore_read_rest.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	firestore_read_rest.js
//
//					Feb/01/2020
//
// ---------------------------------------------------------------
var fs = require("fs")
var get_token = require('./get_token.js')

// ---------------------------------------------------------------
function row_parser(doc)
{
//	console.log(doc)
	const array_aa = doc.name.split("/")
	const llx = array_aa.length
	const key = array_aa[llx - 1]
	const name = doc.fields.name.stringValue
	const population = doc.fields.population.integerValue
	const date_mod = doc.fields.date_mod.timestampValue
	const str_out = key + "\t" + name + "\t" + population + "\t" + date_mod
	console.log(str_out) 
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
const env = process.env
// console.log(env.GOOGLE_APPLICATION_CREDENTIALS)
const json_str = fs.readFileSync (env.GOOGLE_APPLICATION_CREDENTIALS,'utf8')
const dict_aa = JSON.parse (json_str)
const project_id = dict_aa['project_id']
console.log(project_id)

const token = get_token.get_token_proc()

const url="https://firestore.googleapis.com/v1/projects/" + project_id + "/databases/(default)/documents/cities"

var Client = require('node-rest-client').Client

var client = new Client()

var args = {
    headers: { "Authorization": "Bearer " + token}
}

try
	{
	client.get(url, args, function (data, response) {
		try
		{
		data['documents'].forEach((doc) => {
			row_parser(doc)
			})
		}
		catch (error)
		{
		console.error ("*** error *** from forEach ***")
		console.error (error)
		}

		console.error ("*** 終了 ***")
		})
	}
	catch (error)
	{
	console.error ("*** error *** from client.get ***")
	console.error (error)
	}

// ---------------------------------------------------------------
```

get_token.js はこちら
[Node.js の Rest で Cloud Firestore のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/154aba68cb00e77c2a0a)

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_read_rest.js
```
Android  + cmake で ASAN(Address Sanitizer)を使う

https://developer.android.com/ndk/guides/asan

API level 27 から Android でも ASAN(Address Sanitizer)が使えるようになりました.
(APL level 24 くらいから使えたような気もしますが, セットアップのしかたが変わったようです)

## ビルド

ドキュメント通りにすればいけます.
特段, gradle や CMake での ASAN 専用設定オプションはありません.
CFLAGS/LDFLAGS に直接 `-fsanitize=address` あたりを指定します.

## APK の作成

`libclang_rt.asan-*-android.so` ファイルは NDK のパッケージにあります. `jniLibs/<arch>` に入れます.

wrap.sh ファイルは, `resources/lib/<arch>` フォルダに入れます(`res` でもいいかもしれません)
(`jniLibs/<arch>` に置いても, .so ファイルしか APK にコピーされないため)

APK にパッケージングされたら, `lib/<arch>/` に .so と wrap.sh が置かれるはずです.

## 実行時

asan エラーがでると, logcat に

```
ERROR: AddressSanitizer: SEGV ...
```

などとエラーとスタックトレースを出してくれます.
ただ, debug ビルドしてもソースコードなどの行は出してくれません.

## symbolize

How to Get meaningful stack trace in Android
https://github.com/google/sanitizers/issues/984

スタックのファイル名や行番号を出すには, logcat の結果を, host 側で llvm-symbolizer 走らせて取得する必要があります.

https://llvm.org/docs/CommandGuide/llvm-symbolizer.html

https://source.android.com/devices/tech/debug/asan#symbolization

実機で `/system/bin/` などに `llvm-symbolizer` を入れて動かしたいところですが, 現状ではこれを行うには rooted or ASOP が必要なので, Vulkan/GLES を使うなどグラフィックスメインのアプリ開発では選択肢にはなり得ません.
 
一応 NDK のパッケージに実デバイスで動く `llvm-symbolizer` のリクエストは上がっています.

Add device llvm-symbolizer to NDK
https://github.com/android/ndk/issues/753

## TODO

* [x] logcat で ASAN スタックトレースでソースコードが表示されるようにできないか調べる.
  * host で llvm-symbolizer を動かす  
* [ ] `wrap.sh` で他の .so も有効にする方法を試す(Vulkan validation layers, tsan, msan, etc)
Node.js  の Rest で Cloud Firestore のデータを作成 (Create)

```js:firestore_create_rest.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	firestore_create_rest.js
//
//					Feb/01/2020
//
// ---------------------------------------------------------------
var fs = require("fs")
var get_token = require('./get_token.js')

// ---------------------------------------------------------------
function patch_proc(client,token,url,str_json)
{
	const args = {
		data: str_json,
		headers: { "Authorization": "Bearer " + token}
		}

	try
	{
	client.patch(url, args, function (data, response) {
		console.log(data)
			})
	}
	catch (error)
	{
	console.error ("*** error *** from client.get ***")
	console.error (error)
	}
}

// ---------------------------------------------------------------
function add_data_proc(client,token,url_base,key,name,population,date_mod)
{
var data = {}
unit_aa = {}
unit_aa['name'] = {"stringValue": ""}
unit_aa['population'] = {"integerValue": 0}
unit_aa['date_mod'] = {"stringValue": ""}
data['fields'] = unit_aa

data.fields.name.stringValue = name
data.fields.population.integerValue = population
data.fields.date_mod.stringValue = date_mod
const str_json =  JSON.stringify(data)

const url = url_base + key
patch_proc(client,token,url,str_json)
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
const env = process.env
const json_str = fs.readFileSync (env.GOOGLE_APPLICATION_CREDENTIALS,'utf8')
const dict_aa = JSON.parse (json_str)
const project_id = dict_aa['project_id']
console.log(project_id)

const token = get_token.get_token_proc()

const project = 'project-jan25-2020'
const url_base="https://firestore.googleapis.com/v1/projects/" + project_id + "/databases/(default)/documents/cities/"

var Client = require('node-rest-client').Client

var client = new Client()

add_data_proc(client,token,url_base,'t0921','宇都宮',81236,'1954-9-24')
add_data_proc(client,token,url_base,'t0922','小山',94247,'1954-2-15')
add_data_proc(client,token,url_base,'t0923','佐野',71393,'1954-5-28')
add_data_proc(client,token,url_base,'t0924','足利',35441,'1954-7-8')
add_data_proc(client,token,url_base,'t0925','日光',61923,'1954-1-11')

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

```js:get_token.js
// ---------------------------------------------------------------
//	get_token.js
//
//					Feb/01/2020
//
// ---------------------------------------------------------------
exports.get_token_proc = function()
{
	const execSync = require('child_process').execSync
	const command = 'gcloud auth application-default print-access-token'
	const result =  execSync(command).toString().trim()

	return result
}

// ---------------------------------------------------------------
```

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_create_rest.js
```
shellscript rootユーザ確認スクリプト

# 概要
- bashで今のユーザがrootかどうか判定するスクリプトです。

# スクリプト
- スクリプト名：check_user_root.sh

```

#!/bin/bash

#----------------------------------------
# code by Taki_Naka
#
# version
# 2020/02/01 new
#
# note
#
#----------------------------------------

# global variable
user_name=$(whoami)

# chock user name
function check_user_name(){
  if [[ "$user_name" = "root" ]]; then
    echo "user is "$user_name"."
    exit 0
  else
    echo "user is "$user_name"."
    echo "Please execute as root user"
    exit 255
  fi
}


# main
check_user_name
```

# 経緯
- お名前.comのVPNで遊んでいます。
- 構築を楽にしたくて、スクリプト化しています。
- まずは、手動構築 ⇒ スクリプト化（主にbash）⇒ 自動構築OSS って感じでレベルアップしていければと思います。

# note
- Log関数を作って連携させたい。

# 参考
[シェルスクリプト（bash）のif文やwhile文で使う演算子について](https://qiita.com/egawa_kun/items/196cd354c0d8e4e0fefc)
[bashスクリプティング研修の資料を公開します](https://www.m3tech.blog/entry/2018/08/21/bash-scripting)
[シェルで現在のユーザー名を取得する方法](https://linuxfan.info/post-1586)
初心者によるプログラミング学習ログ 226日目

#100日チャレンジの226日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

226日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>226日目<br>・youtubeみながらjavascriptでおみくじアプリ作成<br>・htmlとcssで、skillbar作成<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1223333387378683904?ref_src=twsrc%5Etfw">January 31, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
JavaScript: 配列とオブジェクトの使い方の基本

配列は、複数の値を同じ名前の定数で扱う方法です。

```js

'use strict';

const scores = [10, 20, 30, 40, 50];
scores.push(60, 70); // 配列の値を後ろにどんどん追加する。

for (let i = 0; i < scores.length; i++){ //配列の数だけ繰り返す。

    console.log(`Score ${i}: ${scores[i]}`);

}

```


別の配列の値を、配列に追加する。

```js

'use strict';


const tempScores = [10, 20];
const scores = [10, 20, 30, 40, 50, ...tempScores];

console.log(scores);

```

配列の値をレイアウトし直す。あるいは文字列を分割して個別に配列に入れる。


```js

'use strict';

const d = ['2020', '01', '30'];
const date = d.join('/');
console.log(date);

const t = '11:23:00';
const [hour, min, sec] = t.split(':');
console.log(hour);
console.log(min);
console.log(sec);

```



オブジェクト記法。

```js

'use strict';


const point = {
    x: 50,
    y: 80,
};

console.log(point);

point.x = 60;
point['y'] = 70;

console.log(point);

point.z = 30; // さらにプロパティーを追加。

console.log(point);

delete point.z;// プロパティーを消す。

console.log(point);
```

オブジェクトからキーやバリューを自由に取り出したい。

```js

'use strict';


const point = {
    x: 50,
    y: 80,
};

console.log(point);

const keys = Object.keys(point); // オブジェクト定数「point」のキー情報（xとかyとか）をkeysに取り込む。
console.log(keys);

keys.forEach(key => { // key は引数名。定数「point」のキーだけを取り出した「keys」の中からキーがある限り取ってくる。
    console.log(`Key: ${key} Value: ${point[key]}`); // キー名と、その値を表示。
});

```
[DOS]バッチファイルで、シャットダウンタイマーを作ってみた

# はじめに
筆者は、寝付きがあまり良くないので、音楽をかけたり、動画サイトを見たりしながら、寝ております。
（それが原因で、寝付きが良くないのかもしれないですが）
そのため、すごい昔（たぶんWindows98の頃）にダウンロードしたシャットダウンタイマーを使って、いつ寝てしまっても自動的に、PCをシャットダウンするようにしていました。

流石に、そんな古いツールを使い続けるのもどうかな、と思って自分で作ることにしました。
会社でも、帰宅直前に大きすぎる圧縮ファイルの解凍完了を待つ、のような状況に使えます。
（そんな状況、そうそうないですが）

今回は、以下を参考にさせていただきました。
[コマンドプロンプトで sleep するためのテクニック - Qiita](https://qiita.com/Targityen/items/8d9fcae5a86dbc713517)

# 成果物
今どき、誰もDOSコマンドを覚えたい、ということはないだろうと思うので、
まずは作ったバッチファイルの内容を載せます。
ファイル名は好きに変えてください。（拡張子は除く）

まずは、タイトル通りにシャットダウンタイマーから。
後半の`taskkill`コマンドは、シャットダウン時にひっかかる（強制終了するか聞かれる）ようなプロセスがありそうな方だけ、実行すればいいです。

```bash:ShutDownTimer.bat
@echo off
set /p in=シャットダウンまで何分？：

for /f %%f in ('time /t') do set tm=%%f

set /a hr = %tm:~0,1% * 10 + %tm:~1,1%
set /a mn = %tm:~3,1% * 10 + %tm:~4,1% + in

set /a hr = hr + (mn / 60)
set /a mn = mn %% 60
set /a hr = hr %% 24

set mn=0%mn%
set mn=%mn:~-2,2%

for /l %%n in (%in%, -1, 1) do (
	echo. %%n 分
	title シャットダウン %hr%:%mn% [残り %%n 分]
	ping -n 61 localhost >nul
)

taskkill /f /im "chrome.exe"

shutdown -f -s -t 0
```

一応、ログオフ（サインアウト）タイマーも。
表示文言と、`shutdown`コマンドのオプション以外は同じです。

```bash:LogOffTimer.bat
@echo off
set /p in=ログオフまで何分？：

for /f %%f in ('time /t') do set tm=%%f

set /a hr = %tm:~0,1% * 10 + %tm:~1,1%
set /a mn = %tm:~3,1% * 10 + %tm:~4,1% + in

set /a hr = hr + (mn / 60)
set /a mn = mn %% 60
set /a hr = hr %% 24

set mn=0%mn%
set mn=%mn:~-2,2%

for /l %%n in (%in%, -1, 1) do (
	echo. %%n 分
	title ログオフ %hr%:%mn% [残り %%n 分]
	ping -n 61 localhost >nul
)

taskkill /f /im "chrome.exe"

shutdown -f -l
```

# DOSコマンド詳細

- set
    - /pオプションで、ユーザー入力を変数に代入。
    - /aオプションで、数式の計算結果を変数に代入。
    - /aオプションでの数式内では、変数を`%`や`!`で囲まなくても、変数の値になる模様。
- for
    - /fオプションで、コマンド実行結果の各行を使ったループ。今回は`time /t`の出力が、`hh:mm`の1行であるため、1回しかループしない。
- title
    - DOS窓自体のキャプション変更。DOS窓をいちいち開かなくても、いつシャットダウン／ログオフするか分かるようにするため、使用。
- ping
    - 詳細は [コマンドプロンプトで sleep するためのテクニック - Qiita](https://qiita.com/Targityen/items/8d9fcae5a86dbc713517) を参照してください。
- taskkill
    - /fオプションで、強制終了。
    - /imオプションで、イメージ名（≒exeファイル名）を指定。

# 終わりに
筆者は、ソースコードの「縦」を揃えるのが大好きです。
そのため、変数名の文字数もなるべく統一するのですが、日付や時刻に関する変数名には絶望します。。。
application_controllerの存在。

カリキュラムに沿って学習して来たが、個人アプリの制作に入って改めてapplication_controllerの存在意義調べてみた。

コントローラー全体に共有するメソッドを与えるのが、application_controllerの役割。
各コントローラーは全て、application_controllerを継承しているので、コントローラー全体に共有のメソッドを与えることが出来ます。

例
ログイン情報などを判別する情報を記載しましょう。
YoloV3を使ってカスタムモデルを作った

####やったこと
Yolov3 を使って、自分のカスタムモデルを作った。

ここのYoloの公式サイトに書かれている手順を参考にして簡単に作成できた。
https://pjreddie.com/darknet/yolo/

###darknet のソースコードのdownloadとmake

~~~
git clone https://github.com/pjreddie/darknet
cd darknet
make
~~~

###事前に準備するファイル
* train.txt  
学習したい画像のファイルの場所の一覧が書かれたファイル  
**images フォルダの下にjpegを置くこと**

```train.txt   
/home/guest/work/train_data/images/train_00000.jpg
/home/guest/work/train_data/images/train_00001.jpg
/home/guest/work/train_data/images/train_00002.jpg
/home/guest/work/train_data/images/train_00003.jpg
/home/guest/work/train_data/images/train_00004.jpg
/home/guest/work/train_data/images/train_00005.jpg
/home/guest/work/train_data/images/train_00006.jpg
/home/guest/work/train_data/images/train_00007.jpg
/home/guest/work/train_data/images/train_00008.jpg
/home/guest/work/train_data/images/train_00009.jpg
/home/guest/work/train_data/images/train_00010.jpg
/home/guest/work/train_data/images/train_00011.jpg
/home/guest/work/train_data/images/train_00012.jpg
```
* valid.txt  
  評価用の画像のファイルの場所の一覧が書かれたファイル  

```valid.txt
/home/guest/work/train_data/images/train_20003.jpg
/home/guest/work/train_data/images/train_20004.jpg
/home/guest/work/train_data/images/train_20005.jpg
/home/guest/work/train_data/images/train_20006.jpg
/home/guest/work/train_data/images/train_20007.jpg
/home/guest/work/train_data/images/train_20008.jpg
/home/guest/work/train_data/images/train_20009.jpg
/home/guest/work/train_data/images/train_20010.jpg
```
* custom.names  
物体認識で検出させたいクラスの一覧が書かれたファイル

```custom.names
Motorbike
Bicycle
Car
Signal
SVehicle
Truck
Bus
Pedestrian
Signs
Train
```
* custom.data  
class数の定義や、↑で作ったファイル(train.txt, valid.txt, custom.names)の場所を指定する。  
ここは自分の環境に合わせてパス等を修正する。

```custom.data
classes= 10
train  = /home/guest/work/train_data/train.txt
valid = /home/guest/work/train_data/valid.txt
names = cfg/custom.names
backup = /home/guest/work/darknet/backup
```


#### label ファイルを作成する。
学習させたい画像のアノテーション情報を書き込んだファイルを画像分用意する。
フォーマットは↓ 

```
  < Class index > < x_center > < y_center > < width > < height >
```
***ここで注意したいのが***
train_00000.txtは学習したいJPEG名と合わせる事と、JPEGが置かれているフォルダ名のimagesをlabelsに変更したフォルダに置くこと。

JPEGの置き場所:      /home/guest/work/train_data/images/train_00000.jpg
label情報の置き場所: /home/guest/work/train_data/**lables**/train_00000.txt

```train_00000.txt
2 0.495868 0.493832 0.036157 0.045230
5 0.452738 0.535773 0.287707 0.277138
```

####モデルの作成

以下のコマンドで作成。
cfgフォルダ以下にある、cfgファイルによって作成できるモデルを切り替えられる。

yolov3 版

```
darknet detector train cfg/custom.data cfg/yolov3.cfg
```

yolov3-tiny版

```
darknet detector train cfg/custom.data cfg/yolov3-tiny.cfg
```
　　　
本当は検出したいクラス数に応じて、cfgファイル内に書かれているclasses=80をclasses=10にしたりする必要があるが、検出自体は問題なく動くのでここでは修正していない。

#### PyTorch 版でも動かせた
こちらを参考にした。
https://github.com/eriklindernoren/PyTorch-YOLOv3
【JQuery】 ボタンを押したら、指定の場所にスクロール

# jQueryのoffset() で表示位置の取得と移動

offset()では、ドキュメントの左上の起点と、指定要素の左上の距離を取得します。

要するに、指定要素の場所を特定できる。

span はどこにあるとoffsetで聞いたら

```
Object {top: 150, left: 50}
```
と場所の位置を取得できる。
その場所にスクロールさせればいい。

[参考](https://www.flatflag.nir87.com/offset-1167)


スクロールさせたい要素の場所を下記で定義しましょう

```javascript

var position = $("任意の要素").offset().top;
```
topにしているのは、topから閲覧してほしいからです。

## ボタンを押したら、下にanimateでスクロール

場所を取得したら、animateで移動させます。

```javascript

$("html,body").animate({
    scrollTop : position
}, {
    queue : false
});
```
これで指定した場所にスクロールされます。

## Clickイベントで作動
ボタンを押したら作動させたいので、下記のようにclickイベントつける

```javascript

$(任意のボタン).click(function(){
    $("html,body").animate({
        scrollTop : position
    }, {
        queue : false
    });
});
```

## まとめ

これらの一連の処理をまとめると

```javascript

// スクロールさせたい場所を定義
var position = $("任意の要素").offset().top;

// 指定のボタンを押したら、スクロールさせる。
$(任意のボタン).click(function(){
    $("html,body").animate({
        scrollTop : position
    }, {
        queue : false
    });
});
```

## functionで使い回す

jQueryのfunctionは処理を定義すれば使い回しが可能。

例えば、下記のように使い回すことができる。

```javascript

function sample(name, age) {
 
    console.log(name + 'さんの年齢は' + age + 'です！');
 
}
 
//引数に値を渡す
sample('太郎', 32);
```

このようにスクロールアニメーションもfunctionで定義して、引数を利用して使い回しましょう

# 完成（コピペで使い回せる）

```javascript

$(function(){
      function ScrollButton(button, place){
        // スクロールさせたい場所を定義
        var position = $(place).offset().top;  
        // 指定のボタンを押したら、スクロールさせる。
        $(button).click(function(){
          $("html,body").animate({
              scrollTop : position
          }, {
              queue : false
          });
        });
      }

      // 使う場合、下記のようにする。ScrollButton(ボタン, スクロールさせたい場所)
      ScrollButton(".team-button", ".team");
    });
};
AtomのEmmetでTab補完を共存させたい！

# Emmetは便利だけどtab補完が使えないんじゃ〜〜〜！という人へ

こんにちは。最近LaravelとかVueの勉強をを始めたのでHTMLファイルをいじることが増えました。
HTMLやCSSを触る時にEmmmetのプラグインはとても便利です(自分はあまり使いこなせてないですが...)

しかし、こんな現象で困っている人もいるのではないでしょうか？

----

**「text」って入れて欲しいな〜〜** → tabキーぽち
<img width="679" alt="スクリーンショット 2020-02-01 19.24.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392018/281f7304-f7ec-4c5f-8b9c-c8284a89e199.png">

**あああぁぁぁぁ「\<te>\</te>」になってる！！！**
<img width="592" alt="スクリーンショット 2020-02-01 19.16.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392018/5a738331-d5fc-e80b-0b1c-0184d955be48.png">

普段からtabキーでコードの補完に慣れているとEmmetのプラグインのせいでタグが生成されるのは困りものです。
そこでEmmetのtabキーの割り当てを「shift-tab」に変更しました。

# 自分ではうまくいかなかったやり方
[こちらの記事](https://iwb.jp/atom-emmet-package-shortcut-tab-shift/)によると、Atomの設定ファイルの`keymap.cson`を書き加えると良いというのを見つけました。

↓設定ファイルは左下の「設定フォルダを開く」を押します。(キーバインドを調べるときは右の「キーバインド」で検索できます)
<img width="1000" alt="スクリーンショット 2020-02-01 19.40.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392018/ac15b9b0-4dae-928d-20b3-96099cd982f0.png">

しかし記事の通りに`keymap.cson` に以下のコードを貼り付けて、tabをtab-shiftに変更してもうまくいきませんでした。

```keymap.cson
'atom-text-editor[data-grammar="text html basic"]:not([mini]), atom-text-editor[data-grammar~="erb"]:not([mini]), atom-text-editor[data-grammar~="jade"]:not([mini]), atom-text-editor[data-grammar~="css"]:not([mini]), atom-text-editor[data-grammar~="stylus"]:not([mini]), atom-text-editor[data-grammar~="sass"]:not([mini]), atom-text-editor[data-grammar~="scss"]:not([mini])':
  'shift-tab': 'editor:indent'
```
(どうなったかというと「shift-tab」でも「tab」でも\<tag>の補完が自動でされるようになった)
どうやら`keymap.cson`ではショートカットを加えることはできても変更することはできないようです。

# emmetの設定ファイルを書き換える

[こちらの記事](https://blog.nainaism.com/atom-html-rails-emmet/)を参考にして、Atomの設定ファイルの
`packages > emmet > keymaps > emmet.cson` を開きます。

そして以下の画像のようにtabキーのショートカットについて書かれている部分がある(画像だと37行目)ので、
<img width="894" alt="スクリーンショット 2020-02-01 19.52.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392018/6acad30a-87d4-60a0-8b7a-c37407325dec.png">

```emmet.cson
    'tab': 'emmet:expand-abbreviation-with-tab'
```

となっているのを

```emmet.cson
    'shift-tab': 'emmet:expand-abbreviation-with-tab'
```

と書き換えます。そして設定を反映させるためにAtomを再起動しましょう！

すると


> * 「shift-tab」で\<tag>の補完
> * 「tab」でautocompleteやTabNineでの補完

の使い分けが共存できるようになります！
自分と同じ現象で困っている人は参考にしてください！
Docker Machineめも




環境 Windows10

※ コマンド入力は管理者権限で行う

# 仮想スイッチを追加して、外部と接続する

停止

```
docker-machine stop create-test
```

追加したい仮想マシンを右クリック > 設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/4ca54af6-d41f-be90-ece4-8772d71db213.png)

ハードウェアの追加 > ネットワークアダプタ > 追加ボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/229e20fb-0a2d-69d4-e893-ad516d90da2d.png)

すでに作成済みの仮想スイッチマネージャーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/f8d4c56b-6154-db22-2646-afecabbc576e.png)


## 外部と接続するための仮想スイッチを作成

Hyper-Vマネージャー > 仮想スイッチマネージャー

Hyper-Vマネージャー > 仮想スイッチマネージャー

名前は適当につけてあとはデフォルト設定でおｋ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/da40ae1c-f420-c1cf-ff86-d0107bb25eae.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/7fc9b2be-223b-189d-2fdf-e1b8d9c371eb.png)

私の環境では、Realtekを選ぶとうまくいった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/6cecc009-db44-7132-ce55-052f906afe52.png)

# 作成エラー　no External vswitch found. A valid vswitch must be available for this command to run

```
docker-machine create --driver hyperv create-test
```

```bash:エラー内容
Error with pre-create check: "no External vswitch found. A valid vswitch must be available for this command to run. 
```

[外部と接続するための仮想スイッチを作成](https://qiita.com/zakki/items/6c29c8a3f83a3635ae71#%E5%A4%96%E9%83%A8%E3%81%A8%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E4%BB%AE%E6%83%B3%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81%E3%82%92%E4%BD%9C%E6%88%90)する
ある日、「Faster-RCNNを作ってくれ」と言われても困らないように備える

# 初めに
みなさん、Faster-RCNNは好きですか。
もしかしたら、あなたの上司はFaster-RCNNが大好きで、「Faster-RCNNを作ってくれ」と言ってくるかもしれません。

幸いにもFaster-RCNNの原理についての解説はQiitaやそのほかのサイトにも多くあります。
しかし、それでもわからないことがあります。
それは、**画像ごとに検出する物体の個数が違うのをどう扱うか**。

上司に「入力の前処理と出力の後は別の人にやらせるから仕様を教えてくれ」と言われても困ってしまいます。
そうならないように皆さんも今のうちに備えましょう。

# 論文
Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks ([arxiv](https://arxiv.org/abs/1506.01497))

![Screenshot_2020-02-01 1506 01497 pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36371/259df33e-adfb-0b9e-7a96-501bd52f8e23.png)
図は上記論文より。

# 疑問
- 物体の個数は画像ごとに異なっていて、また不明だがそれをどういった形式で出力するか

# 答え
入力のバッチサイズは1。
なので、出力のサイズは単純にbounding boxでは[RPNが提案した画像の枚数、4]、物体のクラスは[RPNが提案した画像の枚数、クラス数+1]。
(RPNはRegion Proposal Networkの略。クラス数+1となっているのは背景の場合があるため)

言われてしまえば、なんということはない。
論文の著者らが公開しているソースコードの[設定ファイル](https://github.com/rbgirshick/py-faster-rcnn/blob/master/experiments/cfgs/faster_rcnn_end2end.yml)に

```yaml
IMS_PER_BATCH: 1
```

という項目がある。

# 余談
Faster R-CNNはend2endで学習できるのが売りだが、いきなりend2endで学習するのはRPNが変な領域ばかり提案して効率が悪い。
そのため、先にRPNを学習すると論文に書いてある。

その際、学習データが負例ばかりになるのを避けるために正例と負例を128個ずつサンプリングするが、正例が128個以下の場合は負例で埋めるので、合計サイズは256で一定。
この場合は画像ごとにサイズが異なる心配はしなくてもいいが、入力画像は1枚みたいなのであまり関係ない。

# 最後に
思い込みって怖いですね。
ミニバッチで複数の画像を入力するものとばかり思っていて、その中で可変長に対応する方法を探していたが、1枚ずつ入力するとは思いもしなかった。

これで、入出力の仕様が定まってよかったですね。
上司に無事に報告できます。

それでは、良き物体検出ライフを。
クラスの継承とsuper関数

```py:
class Car(object):
    def __init__(self, model=None):
        self.model = model
    def run(self):
        print('run')

class ToyotaCar(Car):
    def run(self):
        print('run fast')

class TeslaCar(Car):
    def __init__(self, model='Model A', enable_auto_run=False):
        super().__init__(model)
        self.enable_auto_run = enable_auto_run
    def run(self):
        print('run very fast')
    def auto_run(self):
        print('auto run')

car = Car()
car.run()

print('############')

toyota_car = ToyotaCar('Lexus')
print(toyota_car.model)
toyota_car.run()

print('############')

tesla_car = TeslaCar('Model S')
print(tesla_car.model)
tesla_car.run()
tesla_car.auto_run()
```

```:実行結果
run
############
Lexus
run fast
############
Model S
run very fast
auto run
```

TeslaCarクラスのコンストラクターは、
本来、

```py:
def __init__(self, model='S Model', enable_auto_run=False):
        self.model = model
        self.enable_auto_run = enable_auto_run
```
と書くところであるが、
スーパークラスのコンストラクターと同じ処理をするので、
super関数を使って書く事ができる。
JavaScript: 関数の書き方の基本



関数宣言の例（引数にはデフォルト値も入れてます）：

```js

function showAd(message = 'Ignored'){ //default value
    console.log(`--- ${message} -----`);
}

showAd(); //Run with default value
showAd('Morning!'); 
```

また、returnで値を返すだけにとどめることも可能。


```js

function sumA(a, b, c){
    console.log(a + b + c); //実際に処理をする
}

function sumB(a, b, c) {
    return a + b + c; //処理する。結果は値として返すだけ。
}

sumA(1, 2, 3); //実行する。表示処理までお任せする
console.log(sumB(2, 2, 4)); //実行する。値を取得した後の処理も自分でやりたい。
```


関数式の例：

```js

const sum = function (a, b, c) {
    return a + b + c; //処理する。値を返すだけ。
};

console.log(sum(1, 2, 3) + sum(3, 4, 5)); //実行する。値を取得する。最後の処理も自分でやりたい。
```

アロー関数での書き方：

const 定数名 = (引数) => 処理した返り値

```js


const sum = (a, b, c) => a + b + c; // アロー関数で書いたもの
console.log(sum(1, 2, 3));

```
【Salesforce】VS Code開発環境構築

#目次
1. VS CodeとSalesforce間のやり取り流れの説明
2. VS Code開発環境構築

##　VS CodeとSalesforce間のやり取り流れの説明
　　VS CodeとSalesforceは直接通信できない、SalesforceクライアントとしてのSalesforce CLI、とVS Codeのプラグイン「Salesforce Extension Pack」を経由しなければならない。
　　VS Code、VS Codeのプラグイン「Salesforce Extension Pack」とSalesforce CLI、及びSalesforce間のやり取り流れは下図の流れ通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480807/923350c5-0e37-b331-3941-f22a1f916bb7.png)

##　VS Code開発環境構築
　　開発環境環境の構築手順はネット上にたくさんあります。下記の記事をご参照ください。こちらは割愛します。

　　[Visual Studio CodeでSalesforceの開発環境を構築する](https://qiita.com/shunkosa/items/e6248520bff90f397158)
EC2にzsh及びoh-my-zshを入れた

EC2にZshとoh-my-zsh入れたので、あったら便利な設定。

```shell:.zshrc

# 個人的にzsh-autosuggestionsあると便利なので入れる。
plugins=(
        git,
        zsh-autosuggestions
)

autoload -U compinit
compinit

# 補完で小文字も大文字にマッチ
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# 重複したディレクトリを追加しない
setopt pushd_ignore_dups

# ヒストリに保存するときに余分なスペースを削除する
setopt hist_reduce_blanks

# cdしたあとで、自動的に ls する
function chpwd() { ls }

# hostnameを表示させる
PROMPT="%{$fg[white]%}%n@%{$fg[green]%}%m%{$reset_color%} ${PROMPT}"

alias sz='source ~/.zshrc'
```
themeはこの場合なんでもよい。自分ちはmuseなので、EC2内はデフォルトにしたまま。ただ、それだとhostnameとかでなくて誰で動かしてるんや、どこのEC2や！？とかなると不便なので`PROMPT="%{$fg[white]%}%n@%{$fg[green]%}%m%{$reset_color%} ${PROMPT}"`こいつを搭載すると捗る雰囲気があります。

`echo $SHELL`したり`sudo chsh ec2-user`したり、色々したり、EC2内使いやすくなってよかった。
でも、まじで、AWS難しすぎて病む。
体力と時間と効率の話(あとアウトプットめんどくさい

<h1>プログラミング学習を始めて感じたこと</h1>
<p>プログラミングの学習を始めて40日ちょっと?程度になったので、</p>
<p>実際にやってみて個人的に感じた感想を述べたいと思います。</p>
<ul>
<li>体力が持たない</li>
<li>時間が足らない</li>
<li>結局効率upを考え始める</li>
<li>アウトプットは面倒くさい(滅茶苦茶大変)</li>
</ul>
<h4>体力が持たない</h4>
<p>毎日平日はフルタイム8時間で働き、家に帰って4~5時間学習、土日は大体10~12時間程度学習していますが、正直きついです...ショートスリーパーとかの人は、3~4時間睡眠でいいのかもしれませんが、僕は最低6時間程度は寝ないと反動で潰れます＼(^^)／<p>
<p>実際学習を始めてから6~7回ぐらい寝落ちしました。(起きたら「へ？なんで部屋の電気消えてパソコンも落ちてんの？∑(ﾟДﾟ)なんてことがありました、単純に自分で消しただけなんですが、記憶が吹っ飛んでるんですね...)やっぱ何事にも体力ある人が強いですね。</p>
<h4>時間が足らない</h4>
個人的には毎日10~12時間ぐらい学習したいところですが、仕事&体力の関係で全然時間が足りませんね。
正確には家事、洗濯、風呂、職場への移動など色々あってどんどん短縮化されてはいってるんですが、それでも毎日4~5時間ぐらいしか取れないですね。仕事やめてしまいたいけど、やめてしまったら就職先の選択肢などが減る、精神的に余裕がなくなるなど、それはそれできついので今のままでいこうと思います。趣味とか自分の時間を結構切り詰めているつもりですが、もっとプログラミングに魂売らないとダメですね( ；∀；)
<h4>結局効率upを考え始める</h4>
<p>以上の理由で、結局時間に制限があるから効率UPを考え始めるんですが、これに時間をかけすぎても学習時間が減ってしまうのでバランス取りながら、うまくタスク管理していかないといけないと思っています。まぁ普段の仕事柄タスク管理は、結構得意(好き)だからここらへんはあまり苦ではないかもしれません。(タスク管理に夢中にならないよう気をつけないといけませんが...</p>
<h4>アウトプットは面倒くさい(滅茶苦茶大変)</h4>
<p>こんな短い文章を書くだけでも、こんな大変で面倒くさいとは思っていませんでした( ；∀；)</p>
<p>加えて表現力もないので、中々文字がでてきませんね...アウトプットをしない、継続できない人が多いとは聞いていましたが、これは体感してみてマジでよくわかります。ホントしんどい；；</p>
<p>とはいえ自分の表現力、考えをまとめるとかそういう能力UPのためには欠かせませんのでこれからも継続して頑張っていきたいと思います。(ツイッターは毎日一言、ブログは一週間に一度投稿ペースで)</p>

<h4>まとめ</h4>
<p>まとめとしては、色々大変ですがプログラミング自体は個人的にゲーム感覚で結構楽しいのでなんとかやっていけそうです。(今のところは)才能とか云々よりも体力、精神力、継続力とかが大事なんだと身をもって体感していますという記事でした。</p>
Tabmanのつまずきポイント

#完成予想図
![tabman.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490120/b2ab3ce2-94c2-fccf-6963-30d0010ca153.gif)



#Tabman参考記事
公式HPを参照するとわかりやすいです！
https://github.com/uias/Tabman/blob/master/Cartfilehttps://github.com/uias/Tabman/blob/master/Cartfile

https://teratail.com/questions/202790

#つまずきやすいところ
親コントローラーと子コントローラーを作ります！
この時、コントローラー同士をsegueでつなぐ必要はありません！
<img width="221" alt="スクリーンショット 2020-02-01 9.56.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490120/fcae6187-b549-2c3f-f08a-bcc479cad9c4.png">

###注意点①
segueで繋げていない代わりに、storyboardで、Moduleを指定してあげる必要があります！
ファイル名で指定してあげましょう！
<img width="262" alt="スクリーンショット 2020-02-01 10.10.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490120/b05a71f9-2527-8231-42c4-0b1c6a7b3ea3.png">

###注意点②
タブの名前が複数の時は、for文を使って一つずついれて返しましょう！（以下コード参照）

```swift
 let titilename = ["名前１","名前２"]
        var items = [TMBarItem]()
        
        for i in titilename {
            let title = TMBarItem(title: i)
            items.append(title)
        }
```




#親コントローラーのコード
①ライブラリTabmanをいれる
②subclassをUIViewControllerで指定した後に、TabmanViewControllerに変える
③子コントローラーの名前をstoryboardに登録
④storyboardでModuleの設定（上の注意点参照）


```swift

import UIKit
import Tabman
import Pageboy

class BigCalendarViewController: TabmanViewController {
    private var viewControllers = [UIViewController]()


    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = self

        //tabmanの宣言
        let bar = TMBar.ButtonBar()
        bar.layout.transitionStyle = .snap
        addBar(bar, dataSource: self, at: .top)        
    }

    private func setTabsControllers() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let ViewController1 = storyboard.instantiateViewController(withIdentifier: "子コントローラーの名前")
        let ViewController2 = storyboard.instantiateViewController(withIdentifier: "子コントローラーの名前2")
     
        viewControllers = [
            ViewController1,
            ViewController2
        ]
    }
}
extension BigCalendarViewController: PageboyViewControllerDataSource, TMBarDataSource{
    func barItem(for bar: TMBar, at index: Int) -> TMBarItemable {
          
        let titilename = ["名前１","名前２"]
        var items = [TMBarItem]()
        
        for i in titilename {
            let title = TMBarItem(title: i)
            items.append(title)
        }
        return items[index]
    }
  
    func numberOfViewControllers(in pageboyViewController: PageboyViewController) -> Int {
        setTabsControllers()
        return viewControllers.count
    }

    func viewController(for pageboyViewController: PageboyViewController,
                        at index: PageboyViewController.PageIndex) -> UIViewController? {
        return viewControllers[index]
    }

    func defaultPage(for pageboyViewController: PageboyViewController) -> PageboyViewController.Page? {
        return nil
    }

    func barItem(for tabViewController: TabmanViewController, at index: Int) -> TMBarItemable {
        let title = "Page \(index)"
        return TMBarItem(title: title)
    }

    
}

```
DroidKaigi 2020 の Repository に Contribute した話

表題そのままですが、初めてオープンソース開発に Contribute しました。
そのままの勢いで書いてしまいました。


## DroidKaigi ??

> DroidKaigiはエンジニアが主役のAndroidカンファレンスです。
> Android技術情報の共有とコミュニケーションを目的に、2020年2月20日(木)、21日(金)の2日間開催します。

[DroidKaigi 2020](https://droidkaigi.jp/2020/)


そしてこのカンファレンス用のモバイルアプリは有志によって作成されています。

[GitHub - DroidKaigi/conference-app-2020: The Official Conference App for DroidKaigi 2020 Tokyo](https://github.com/DroidKaigi/conference-app-2020)


前々から Android アプリ開発のバイブルとして (勝手に) 参考にさせていただいていました。
このプロジェクトに参加できたら Android アプリエンジニアとして成長できるだろうなと思っていたのです。

その思いを爆発させるのは今しかない...!!


## Contribute

`Welcome contribute` のラベルがついたものは比較的参加しやすいものだそうです。

ただ自分でもできそうな Issue が上がっていても爆速で Assigne されてました。。。😭
その中でやっと実装した内容はこちらになります。🙋

やった事としてはセッションのリストをグルーピングする前に他のリストの項目を除外するだけです。
(1行追加しただけ。。。)


### Issue

- [Exclude event sessions from day sessions · Issue #669 · DroidKaigi/conference-app-2020 · GitHub](https://github.com/DroidKaigi/conference-app-2020/issues/669)


### PR

- [Exclude event sessions from day sessions by tick-taku · Pull Request #675 · DroidKaigi/conference-app-2020 · GitHub](https://github.com/DroidKaigi/conference-app-2020/pull/675)

👏


### Accident

ハマった...と言う程でもありませんが、Push の方法で手間取りました。。。

fetch できるのに push できないなぁ〜〜〜😱
と思っていたらまず Repository を fork してからそこで作業をするのですね。。。
確かに、不特定多数が触れると悪意があればいくらでも改竄できてしまいますからね。

詳しい Contribute の仕方を纏めてくださっていました。


[DroidKaigi 2020のアプリをGitHubで公開しました - DroidKaigi - Medium](https://medium.com/droidkaigi/droidkaigi-2020%E3%82%92github%E3%81%A7%E5%85%AC%E9%96%8B%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-18abe68d1f6e)


## Conclusion

いつか DroidKaigi に参加(登壇)してみたいです。
東京の会社に転職すれば可能性が。。。

最近英語の勉強に力を入れているので、アプリ開発スキルも合わせて自信に繋がりました。

(これまた勝手に)フォローしている takahirom さんからリアクションがもらえるのは嬉しかったですね。
これからも Android アプリ開発盛り上がっていきましょう😁
Google Text To Speakでテキスト読み上げ機能で音声ファイルを作って３分間スピーチの目安の文章を確かめる

Google Text To Speakでテキスト読み上げ
て大まかなスピーチ時間を測る方法。
最近３分間スピーチをしなくてはいけなくて原稿が大まかにどの位の読み上げ時間をかかるか調べる必要があったので記事を書きました。
まずターミナルで
```pip install gtts
```
で音声読み上げのパッケージを入れて文章を記載したhello.txtを読み上げ機能でmp3ファイルを作ります。
ファイルは全体の時間情報を持っているので（音楽アプリで何分って表示されますよね）
3分スピーチの原稿の大まかな読み上げ時間を確認出来ます。

```python

from gtts import gTTS

f = open('hello.txt','r',encoding="utf-8")
data1 = f.read()  # ファイル終端まで全て読んだデータを返す
f.close()
tts = gTTS(text=data1, lang='ja')
tts.save("good.mp3")
Herokuのbuildpackエラー対応

#エラー内容

bundler 2.x 系を使えるように
`$ heroku buildpacks:set https://github.com/bundler/heroku-buildpack-bundler2.git`
を実施したが、現在は2.x系が対応しているので不要とのこと、以下エラー内容

```terminal
remote: ###### WARNING:
remote: 
remote:        This buildpack was created as a stop-gap measure to allow running applications with Bundler 2 on Heroku.
remote:        Heroku now supports Bundler 2 directly: https://devcenter.heroku.com/changelog-items/1563
remote:        
remote:        Please discontinue use of this buildpack and instead directly use the `heroku/ruby` buildpack.
remote:        
remote:        To remove this buildpack use the `heroku buildpacks` command to list your existing buildpacks.
remote:        
remote:        If you only have one buildpack listed you can run:
remote:        
remote:        ```
remote:        heroku buildpacks:set heroku/ruby
remote:        ```
remote:        
remote:        If you have multiple buildpacks, you'll need to add the buildpack to the correct location using
remote:        `heroku buildpacks:add heroku/ruby -i <correct index>` and then remove this buildpack via:
remote:        
remote:        ```
remote:        heroku buildpacks:remove https://github.com/bundler/heroku-buildpack-bundler2

```

#対応方法
いろいろbuildpackのコマンドを分からずに実行し、buildpack内が

```
=== Buildpack URLs
1. https://github.com/bundler/heroku-buildpack-bundler2.git
2. heroku/ruby
```
の状況に。
buildpackの削除コマンド`heroku buildpacks:remove`を試みたが削除できず。
2つの全てのbuildpackを削除（`heroku buildpacks:clear`）し、再度`heroku buildpacks:set heroku/ruby`を実行、解決！

#buildpackコマンド例（heroku）

- 使用中の buildpack を表示
`heroku buildpacks`

- buildpackのインストール
`heroku buildpacks:set "ビルドパック名 or URL"`

- buildpackの追加
`heroku buildpacks:add "ビルドパック名 or URL"`

- buildpackの削除
`heroku buildpacks:remove "ビルドパック名またはURL"`

- 全てのbuildpackを削除
`heroku buildpacks:clear`
勾配を用いた法線の算出

# はじめに
勾配を計算することで法線ベクトルを計算するケースはいくつか存在します．自分が使用するケースとしてはレイマーチングでのライティングや、拡散方程式などの数値解析の境界条件で使用されるノイマン境界条件などでも使用されたりします．
そこでこの記事ではなぜスカラー場の勾配をとると法線ベクトルが求められるのかを記述していきます．

#勾配と法線の関係

${f(x, y)}$で与えられている平面スカラー場Dについて考える．${P{\_0}(x{\_0}, y{\_0})}$を通る等位曲線を$C$とし、$x = x(s), y = y(t)$をする．↓ピンクで塗られている曲線が等位曲線

![20200201_184216.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184790/43e36aad-6628-83a7-ec83-4896fb6cfe32.jpeg)


ここで等位曲線Cの方程式について考える.(Cはどの点に置いても同じ値、$f(x{\_0}, y{\_0})$という**定数**をとる)
$$
P(t) = f(x(t), y(t)) = f(x{\_0}, y{\_0}) \tag{1.1}
$$

(1.1)の両辺を変数$t$で微分を行うと

$$
\frac {\partial f}{\partial x} {\cdot} \frac{dx}{dt} + \frac {\partial f}{\partial y} {\cdot} \frac{dy}{dt} = 0 \tag{1.2}
$$

(1.2)は２つのベクトル$ [ \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}] $と$ [\frac{dx}{dt} , \frac{dy}{dt}] $の内積を表現している．$ [\frac{dx}{dt} , \frac{dy}{dt}] $は等位曲線上の接線を示しており,この
またベクトルとの内積の値が0になっていることから２つのベクトルが直行していることがわかる．故に、勾配を示す$ [ \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}] $は法線を示していると言える

# サンプルソース
参考までにですが、コンピュータ上では正確な微分演算は出来ないので以下のように微少区間ずらした値との差分で計算を行います．


```glsl
vec3 normal(vec3 p) {
 	float EPSILON = 0.0001;
 	return normalize(vec3(
 		phi(vec3(p.x + EPSILON, p.y, p.z)) - phi(vec3(p.x - EPSILON, p.y, p.z)),
 		phi(vec3(p.x, p.y + EPSILON, p.z)) - phi(vec3(p.x, p.y - EPSILON, p.z)),
 		phi(vec3(p.x, p.y, p.z  + EPSILON)) - phi(vec3(p.x, p.y, p.z - EPSILON))
 	));
 }
 

```
form外からpost、form内から複数のpostを送る方法

### 記事を書いた経緯

とある申し込み画面を作成していた際、内容確認画面で「戻る」「登録」ボタンと、
さらにパンくずリスト（前画面に戻る）動作が必要な場面に遭遇したため、備忘録用に。

## form外からpost送信
上記の私の経験でいうと、パンくずリスト（前画面遷移の際に値を持っていく必要がある場合）でこの方法を使いました。jQueryで実現してます。

早速ソースコードです。

```ruby:jQuery
    $('#listback').click(function() {
      var form = document.forms["form"];
      var url = $('#listback').attr('name');
      form.action = url;
      form.submit();
      return false;
    });
```
下はviewの抜粋です。
Laravelを使っているため、遷移先urlをrouteで指定してあります。


```ruby:view
    <li class="breadcrumb-item"><a href="" name="{{ route('Back')}}" id="listback">新規登録</a></li>
```

まぁ、上記見ればおわかりかと思いますが、簡単に説明します。
aタグのname属性に、遷移先urlを指定してしまいます。ついでにユニークのidも振っておきます。
そのidでjQueryを呼び出し、name属性で指定したurlを取得しform.actionに指定します。

## form内から複数のpost送信
私の経験だと内容確認画面の「戻る」「登録」ボタンに当たります。

```ruby:jQuery
    //戻るボタン押下
    $("#back").click(function(){
      var url = $('#back').attr('name');
      $('form').attr('action', url);
      $('form').submit();
    });

    //登録ボタン押下
    $("#signup").click(function(){
      var url = $('#signup').attr('name');
      $('form').attr('action', url);
      $('form').submit();
    });
    
```
```ruby:view
<input id='back' type="submit" class="btn btn-primary" name="{{ route('Back')}}" style="margin-right: 10px" value="戻る">
<input id='signup' type="submit" class="btn btn-primary" name="{{ route('Insert')}}" value="登録">
```

上記はすでにform内に入っているボタンです。
このときinput要素のtype属性をsubmitに設定します。
あとはform外postと同じようにname属性に遷移先urlを指定し、idを振ります。
jQueryでは、attr()で既存のformを調整し、送信先を設定します。
rootで実行されたかどうか確認する

[Golang Geteuid Examples, os\.Geteuid Golang Examples \- HotExamples](https://golang.hotexamples.com/examples/os/-/Geteuid/golang-geteuid-function-examples.html)


rootで動かすバッチの動作チェックなどに。
[whoamiコマンド](https://ja.wikipedia.org/wiki/Whoami)と等価

```go:whoami.go
package main

import (
        "fmt"
        "os"
)

func main() {
        if os.Geteuid() != 0 {
                fmt.Println("Must be run as root")
                os.Exit(1)
        }
        os.Exit(0)
}
```

```
// 一般ユーザー実行
$ go run whoami.go
Must be run as root
exit status 1
// root実行
# go run whoami.go
# echo $?
0
```
mkdirから公開鍵認証方式でgithubにpushするまで

mkdirからってのは嘘です。ディレクトリは適当に作ってください。
# git init から git commitまで
おなじみ[サルでもわかるgit](https://backlog.com/ja/git-tutorial/)を見れば、とりあえずここまでは楽勝です。

```bash
$:git init
$:git add .
$:git commit -m "first commit"
```
1. `git init`でリポジトリの新規作成
2. `git add .`でファイル全部をインデックスに追加
3. `git commit -m`でコミット

commitは-mでコメントを付けるのはほとんどおまじないです、頭を空っぽにして唱えましょう。ちなみにmをFにしたらファイルの内容をコメントにできたりする。

# githubにリポジトリを作る
1. [github](https://github.com/)にアクセス。
2. 左の`Repositories`にある緑色のNEWってやつをクリック
3. ディレクトリ名決めるノリでリポジトリ名を決める
4. create repositoriyをクリック

# ssh-keygen で鍵を作る
まずは`~/.ssh`に移動。そしてまず公開鍵のペアを作成。

```bash
$:ssh-keygen -C githubのメアド -t rsa
$:ls
id_rsa id_rsa.pub
```
パスワードは適当に付けたほうがいい(ってgithub公式が言ってる)


# githubに公開鍵を登録
1. `cat ~/.ssh/id_rsa.pub`の出力結果をマウス操作でコピー
2. [githubの設定にある鍵登録ページ](https://github.com/settings/keys)にアクセス
3. 右上にある緑色の`NEW SSH key`ってつをクリック
4. 適当にtitleいれて、keyのところに全部貼り付け
5. 下のAllowなんたらにチェック(必須)

鍵の登録画面にはリポジトリからじゃなくユーザーのホームから行かないと、登録したリポジトリ専用になってしまうので注意
# configの設定をして最後に接続テスト
次にconfigの設定ですな、`.ssh`内に`config`ってファイルを作って、`config`に以下を記述。

```bash
Host 好きな名前(僕はgithub.com.XXX)
   HostName github.com
   User git
   Port 22
   IdentityFile ~/.ssh/id_rsa
   TCPKeepAlive yes
   IdentitiesOnly yes
```
そして接続テストは以下みたいな感じになったら成功

```
$:ssh -T configで決めたHost
Hi XXXXXX! You've successfully authenticated, but GitHub does not provide shell access.
```

# ちょっと設定してpushする
ここでgithubのユーザー名とリポジトリ名を使います。
- ユーザー名 -> [github](https://github.com/)の右上にある自分のアイコンをクリックすると、`Signed in as ○○`ってでるその○○
- リポジトリ名 ->さっきディレクトリ名決めるノリで作ったリポジトリの名前

```bash
$:git remote add origin configできめたHost:ユーザー名/リポジトリ名.git
```
これで設定は終了。設定を確認したり変更したいときは`git remote -オプション`でいろいろできる。あとは

```bash
$:git push -u origin master
```
これで次からはgit pushで簡単にpushできます。


多分...