OmniAICreator/Qiita-1.07M huggingface dataset:
Unityを触ってみた

Qiita初投稿です…。
Unityでちょっとしたゲーム作ってみて、それとなく形になってきたので投稿してみます。
半分趣味でしたが、プログラムの勉強にもなりやってみて良かったです。
今回の投稿はUnity使った事無い人向けです。キャラの動かし方程度のレベルの話です。

######「Unityでどうやってゲーム作るの？」「どうやってキャラが動いてるの？」
案外作るの難しくないですよーってのが伝われば良いかなと思います。

　

####■Unityとは？
具体的な話に入る前に簡単にUnityについてお話します。
ゲーム制作ツールUnityではプログラム言語はC#を使用します。
C#でコードを記述したことはありませんでしたが、Java等と基本の文法は同じなのでJava等扱った事のある方は問題ないかと思います。
Unityはゲーム制作のツールなので、よくあるHPバーを作ったり、オブジェクトに重力をかけたり等もできます。
ほんとに出来る事が多く自分もちゃんとツールを把握しきれていません。笑

####■ゲーム作るのって難しい？
ゲーム自体の難易度によりますが、オブジェクトの生成や移動方法が理解できれば、ある程度作れる気がします。
最初は紐づきが分からず苦戦しましたが、途中から想像通りに組み込めるようになってきました。


####■どうやってキャラとか動かすの？

下記の流れでキャラを動かします。
1. C#スクリプト(C#コード)側でUnityに登録している画像を呼び出す
2. 生成したオブジェクトを配置する
3. 配置したオブジェクトを移動させる
4. ゆっくり動かすためにUpdate()メソッドを使用する


#####1. C#スクリプト側でUnityに登録している画像を呼び出す
 
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594995/37e6db4d-d220-50a4-ad76-724479cdd8cc.png width=25% >
◎下記のコードでオブジェクトを生成できます。
　*GameObject original = (GameObject)Resources.Load("BlockPrefab") as GameObject;*
　*obj = Object.Instantiate(original) as GameObject;*
　これは、ツール内に登録した画像(BlockPrefab)を読み取ってオブジェクト化しているコードです。
#####2. 生成したオブジェクトを配置します
◎下記のコードでオブジェクトの配置ができます。
　*obj.transform.position = new Vector3(1, 1, 1);*
　Unityにおいて、Vectorクラスという概念は重要です。 Vectorとはベクトル(方向)のことです。
　ざっくり言えば上記のコードは中心(0,0,0)から見た座標(1,1,1)に配置するということです。
　※座標(x,y,z)です
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594995/694eb768-357a-1bc3-2017-7d82cbfdd7ac.png width=20%>


#####3. 配置したオブジェクトを移動させる
◎下記のコードでオブジェクトを移動させることができます。
　*obj.transform.Translate(0.1f, 0, 0);*
　Translateというメソッドがあるみたいです。
　配置したオブジェクトの位置から指定した値だけ移動します。
　※このコードは、配置のメソッドなので瞬間移動します。
　　キャラがゆっくり動く原理については後述します。

#####4. ゆっくり動かすためにUpdate()メソッドを使用する
<img width="300" alt="図5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594995/a40f1d35-4a4f-d27c-246b-dc88441992ec.png">

◎Update()メソッドについて
　実はUnityでスクリプトを生成した場合、Start(){}とUpdate(){}がデフォルトで付いています。
　***ツールでゲームを再生すると、一度Start(){}を読み込み、それからは常に繰り返しUpdate()の中の
　処理を読み込みんでいます***
◎使用例
　例えば、こうやって使えます。
　*Update(){*
　*obj.transform.Translate(0.1f, 0, 0); ←これが何回も読み込まれる*
　*}*
◎上記のコードの結果
　obj.transform.Translate(0.1f, 0, 0);では0.1fだけ右に配置されるのでこれをUpdate()が繰り返す
　ので、徐々に右に移動しているように見える、という仕組みです。
　「小さな瞬間移動を繰り返し行うことによってゆっくり動いているように見せる」ってカンジです。
　
　
何となく簡単に作れそうってイメージ付きそうですかね…？
まあ触ってみないと分からないこと多いですよね。笑
Terraformを使用してherokuにデプロイした際の備忘録

この記事ではTerraform初心者の私が、herokuにデプロイし際の備忘録を記載してます。

＜作成環境＞
■PC:MacBook (13-inch, Aluminum, Late 2008)
■macOS:10.11.6
◼Terrafom:v0.12.20
◼herokuk:v2.2.2

<参考URL>
https://blog.sshn.me/posts/using-terraform-to-build-heroku-app/

この記事は、基本的に、上記ページを参照しておりますが、上記私の作成環境でデプロイする際に修正した点を記載しております。

<前提作業>
◼__Terraformのインストール__
brew install terraform
◼__herokuの登録__
https://jp.heroku.com/

<私が記載したtfファイル>

```
provider "heroku" {
  email = "heroku登録時のメールアドレス"
  api_key = "heroku_api_key"
}

resource "heroku_app" "default" {
  name = "terraform-heroku-test"
  region = "us"
}

resource "heroku_addon" "database" {
  app = "${heroku_app.default.name}"
  plan = "heroku-postgresql:hobby-dev"
}
```

<修正した点>
◼__api_keyの記載方法__
修正前：api_key = "${var.heroku_api_key}"
修正後：api_key = "heroku_api_key"
上記のようにapi_keyを入力する際、修正前の記載だと正常に処理が完了しないため、
emailと同じように""の中にheroku_api_keyを入力すると処理が完了した。

◼__heroku_appのnameの使用文字__
修正前：terraform_heroku_test
修正後：terraform-heroku-test
_(アンダーバー)が使用できない。
参考URLの記載は正解です。私がappの名前を設定する際、他の名前を使用し、_(アンダーバー)を使用しました。
デプロイする際、エラーで_(アンダーバー)が使用できないことに気づきました。
参考ページ:https://stackoverflow.com/questions/41604716/heroku-errorname-must-start-with-a-letter-and-can-only-contain-lowercase-letter/41606980#41606980
ksnctf 7 Programming

#ksnctf 7 Programming

* 問題
    * http://ksnctf.sweetduet.info/problem/7
* .cppのコード
    * 実行<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/1de29956-34eb-e50c-5754-9b21b5f264e7.png)

* Whitespace
    * 空白、タブ、改行からなる難解プログラミング言語
    * それ以外の文字列はコメント扱いとして無視される

* ideoneでWhitespaceとして実行
    * https://ideone.com/<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/304fc176-9726-ede8-2e18-4c5ae019e0e8.png)
    * PINが必要そう
* コード中身を読む
    * .wsから.cへの変換コードがあったので、それを使わせてもらう
        * http://koturn.hatenablog.com/entry/2015/08/10/000000
    * 変換後<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/fd47b855-5647-ee54-3317-910e670a8d5c.png)
    * inputとして33355524を入れてもう一度ideone実行
Debianシステム全体にrbenvを導入する

# Debianシステム全体にrbenvを導入する
## 概要
Windows10のWSL2上に構築したDebianに`rbenv`を導入したときのメモ。
[インストールマニュアル](https://github.com/rbenv/rbenv)通りの手順を行うと、ホームディレクトリ配下にRubyバイナリが配置される。しかし個人的にホームディレクトリMac-Windows間でクラウド同期しているので、バイナリをホーム配下に配置したくなかった。
そこで`/usr/local/lib`配下に`rbenv`をインストールした。

## 環境
- OS: Debian(WSL2で構築)
- Shell: zsh

## 手順
- githubより`rbenv`を`clone`

```
sudo git clone https://github.com/rbenv/rbenv.git /usr/local/lib/rbenv
```
- またgithubより`ruby-build`を`clone`

```
sudo git clone https://github.com/rbenv/ruby-build.git /usr/local/lib/rbenv/plugins/ruby-build
```

- `.zshrc`に環境変数を設定する

```shell:.zshrc
export RBENV_ROOT=/usr/local/lib/rbenv
export PATH=${RBENV_ROOT}/bin:${PATH}
eval "$(rbenv init -)"
```
- `.zshrc`を再読み込み

*権限が無い旨のエラーが出るがここでは無視*

```
source ~/.zshrc
```

- Rubyをインストールする(執筆時点で最新の2.7.0の場合)

```
sudo -E /usr/local/lib/rbenv/bin/rbenv install -v 2.7.0
```
*インストールが完了すると*

```
Downloading ruby-2.7.0.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.bz2
Installing ruby-2.7.0...
Installed ruby-2.7.0 to /usr/local/lib/rbenv/versions/2.7.0
```
*しっかり`/usr/local/lib`配下にインストールされている*

- バージョン設定

```
 sudo -E /usr/local/lib/rbenv/bin/rbenv global 2.7.0
```

- 初期化する

```
 sudo -E /usr/local/lib/rbenv/bin/rbenv rehash
```
<!--
##さいごに
インストールマニュアルでは、`.zshrc`に`eval "$(rbenv init -)"`を追記するように記述があり、ログインごとに`rehash`する設定にしているが、この手順はインストール先がホームディレクトリ配下でないため`eval "$(rbenv init -)"`を実行するのに`sudo`が必要となる。このため`.zshrc`には記述しない。よって、新バージョンをインストールした際など必要に応じて手動で`rehash`する。
-->
【Laravel】フォームリクエストでバリデーションをしよう


入力フォームやクエリパラメータをフォームリクエストでバリデーションする方法について解説します。

#フォームリクエスト作成
まず、フォームリクエストを作成します
ターミナルから下記のコマンドで作成しましょう
下記のコマンドで`app/Http/Requests/`ディレクトリに`SampleRequest.php`という名前のRequestクラスを作成できます

```:ターミナル
php artisan make:request SampleRequest
```

#SampleRequestクラスについて
作成されたSampleRequestクラスで確認しましょう
`SampleRequest`クラス内に`authorize`メソッドと`rules`メソッドができていると思います

##rulesメソッドはバリデーションの規則を定義する
下記のように`rules `メソッドを定義すると、`title`、` body`それぞれに対して下記のような条件を設定しています。
`title` カラムには必須、`post`テーブル内での一意性、最大文字数を255に設定しています。
`body`カラムには必須条件を設定しています
他の条件については[公式ページのバリデーションのページ](https://readouble.com/laravel/5.5/ja/validation.html?header=%25E4%25BD%25BF%25E7%2594%25A8%25E5%258F%25AF%25E8%2583%25BD%25E3%2581%25AA%25E3%2583%2590%25E3%2583%25AA%25E3%2583%2587%25E3%2583%25BC%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%25B3%25E3%2583%25AB%25E3%2583%25BC%25E3%2583%25AB)を参考に設定してみてください

```php:app/Http/Requests/SampleRequest.php
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}
```

##authorizeメソッドはフォームリクエストの使用できる条件を定義
###ビューから送信されるURLの設定
保存処理を行うアクションへのURLを下記のように設定している場合を考えています

```php:
Route::post('comment/{comment}');
```

###`authorize`メソッドの説明
`authorize`メソッドはユーザーが、指定されたデータを更新する権限を持っているのかを確認します。
下記のコードでは、ユーザーが更新しようとしているブログコメントを所有しているかを確認します。

```php:app/Http/Requests/SampleRequest.php
public function authorize()
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}
```

###常に判定に成功する場合
もし、権限判定を他の場所でしている、または権限判定が不要な場合は、
下記のように返り値をtrueにして常に判定が通るようにしてください。

```php:app/Http/Requests/SampleRequest.php
public function authorize()
{
    return true;
}
```

上記の設定でリクエストでバリデーションを使用することができます！！

#フォームリクエストの使い方
フォームから送信された値、クエリパラメータを使用する時はコントローラーアクション引数にRequestクラスのインスタンスを設定すると思います。
そこのクラス名を今回独自で設定したSampleRequestを指定してください。
そうするとインスタンス`$request`を作成する時に自動でバリデーションをかけてくれます。

```php:コントローラー.php
public function store(SampleRequest $request)
{
    // 送信されたリクエストが正しい場合実行される
}
```

バリデーションに失敗すると、前のアドレスにユーザーを戻します。
その時に、エラーメッセージも表示できるように、フラッシュデーターとしてセッションに保存されます。

#エラーメッセージのカスタマイズ
上記の設定のままではエラーメッセージはデフォルトのままです。
英語で表示され、ユーザーに対して優しい設定とは言えません。
より具体的にエラー内容を設定しましょう
`messages`メソッドでメッセージの配列を設定しましょう。

```php:app/Http/Requests/SampleRequest.php
public function messages()
{
    return [
        'title.required' => 'タイトルは必須項目です',
        'body.required'  => '内容は必須項目です',
    ];
}
```


以上です！！！
**ここまで読んでいただきありがとうございました！！
疑問、気になるところがございましたら、質問、コメントよろしくお願いします！！！**
【Laravel】ルーティングを甘くみてたら痛い目にあった話

#web.php のルーティングは甘くみちゃいけない話
練習用で画像投稿機能つきの簡単なウェブアプリを制作しています。
PHP/Laravel学習歴３ヶ月ほどのプログラミング初学者の僕が個人的な備忘録として記述しました。

#とりあえず書いておけば良い！と思っていた自分

web.phpにはとりあず必要なものを記述しておけば良いと思っていた。
しかし、エラーが表示されたり、表示されなかったとしても、思い通りに関数が機能してくれないなど問題ばかり発生して、結果的に解決するのに数日を要した。

###初めに記述したルーティング（間違い）

```
---(略)---
Route::group(['middleweare' => 'auth'], function () {
    Route::get('/', 'StoriesController@index');
    Route::post('/stories/create', 'StoriesController@store');
    Route::post('/stories/create', 'StoriesController@upload');
    Route::get('/stories/create', 'StoriesController@upload');
    Route::get('/stories/create', 'StoriesController@add');
    Route::post('/stories/create', 'StoriesController@add');
});
---（略）---
```

`StoriesController`の`upload`に写真をアップロードするアクションにした。
しかしうまく機能してくれない。
ただ写真を表示したいページにリダイレクトするだけで写真は投稿できていない。

###修正後のルーティング（正しい）
```
---（略）---
Route::group(['middleweare' => 'auth'], function () {
    Route::get('/', 'StoriesController@index');
    Route::post('/', 'StoriesController@store');
    Route::get('/stories/create', 'StoriesController@add');
    Route::post('/stories/create', 'StoriesController@uplaod');
});
---（略）---
```

これで、写真を**投稿**、**保存**、の二つの機能を実装することができた。

##何がしたかったのか
ユーザーからのアクセスを`StoriesController`の`upload`アクションに渡して写真を投稿できるようにしたい。

##どんなエラーが起こっていたのか
`The POST method is not supported for this route. Supported methods:GET,HEAD. `
というエラー文が表示されるか、何も変化せず指定したページにリダイレクトする。

##何が問題だったのか


###POSTメソッドと/stories/createの組み合わせが複数存在する
最初の間違えている方のコードの3,4,7行目を実際見てみると、

`~::post('/stories/create',~`

の部分が共通していて、同じ組み合わせが存在していた。

###コードは上から書いた順に実行される（当たり前）
間違いの方のコードの最下行のコードをみてみると、最下行のコードが、

`Route::post('/stories/create', 'StoriesController@add');`

と記述されている。
今回実行したかった`StoriesController`の`upload`アクションを、この`add`アクションが上書きしていた。
それは`upload`アクションと`add`アクションの`~::post('/stories/create',~)`が共通していたからである。
コードは上から順に実行される（あたりまえ）。

###補足
`$php artisan route:list`
これを実行することによってどのルーティングが読み込まれているのか確認することができる。
Mac(US) -> Win(US) RDPの際のキーボード配列設定

# 問題

Mac（US配列) -> Win(US配列) にRDPで接続した際、

|Mac|Win|
|:--:|:--:|
|左Command|Windowsキー|
|右Command|カタカナひらがなローマ字キー|

に割り当てられているようだった。

自分はWin側のAutoHotKeyで、
左Alt単体 -> IME off, 右Alt単体 -> IME ON にしてるので、IMEの切り替えが全然スムーズにいかなくなって困った。

# やりたかったこと

できるだけMacの配列とWinの配列を近づけるため、以下のように設定したかった。

|Mac|Win|
|:--:|:--:|
|左Command|左Alt|
|右Command|右Alt|
|左Option|Windowsキー|
|左Control|左Ctrl|

設定後少し触った感じ、実現できたようなので、以下にやったことを書いていく。

# RDPクライアントアプリ
Microsoft Remote Desktopを使用する。

# やったこと

### 1. Microsoft Remote Desktopを導入
~~当初Microsoft Remote Desktopを使用していたので、これを利用した場合の設定方法を試してみたが、うまく行かなかった。その後、Paralles Clientを導入して試した結果、うまく行った。~~

Parallels Clientの仕様なのか、 右Optionが左Altとして送信されてしまう。
Microsoft Remote Desktopでは上記問題がなかったので、こちらを使用する。

### 2. Karabiner Elementsの導入・設定

以下のブログを参考にさせて頂いた。
[MacOS＋Windows（リモートデスクトップ）な人向けKarabiner-Elements設定をご紹介 - 蒲田ネット](https://blog.kamata-net.com/archives/9178.html)

この記事の設定対象を、 `Paralles Client` -> `Microsoft Remote Desktop`に変更する。
アプリ識別子 `"^com\\.2X\\.Client\\.Mac$"` を `"^com\\.microsoft\\.rdc\\.macos$"` に置換すれば良い。
                                
これにより、以下の2つの設定が有効になる。

##### Win側でのCtrl-○設定
以下引用
> コピー（Cmd-C）、切り取り（Cmd-X）、ペースト（Cmd-V）、検索（Cmd-F）、Undo（Cmd-Z）をWindowsでお馴染みのCtrl-○に割当
> Cmd-Enter（メール送信）もCtrl-Enterに割当
> ただし、TerminalとParallels Client（アプリ識別子は"com.2X.Client.Mac"）は除く

#### Microsoft Remote Desktop  アクティブ時の Commandキー と Optionキーの逆転

Commandキー -> Optionキー
Optionキー -> Commandキー

とすることで、Microsoft Remote Desktop 操作時に以下を実現する。

|Mac|Win|
|:--:|:--:|
|左Command|左Alt|
|右Command|右Alt|
|左Option|Windowsキー|

# 補足
Mac側でのIME ON/OFF に左/右Ctrlを用いている場合、この設定をWin側では無効にする必要がある。

これに関しては以下Qiita記事を参照
[USキーボードの左右Commandキーで仮想化Windowsの英数/かな入力を切り替える
](https://qiita.com/yukiri/items/6560e572dbe5eae4042f#windowsime%E3%81%AE%E8%A8%AD%E5%AE%9A)

こちらは、除外対象を `"^com\\.microsoft\\.rdc\\.macos$"` とすれば良い。

あとjsonファイルを変更した後にkarabiner側で一旦設定を `Remove` してから再度 `Add` しないと反映されない。

# 感想
かなりリモートワークがやりづらくなりそうだったので、先人の知恵に助けられた。
【Udemy Python3入門+応用】　14.文字の代入 15.f-strings

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**

##■文字の代入
#####◆`{}`と`.format()`
```
>>> 'A is {}.' .format('a')
'A is a.'

>>> 'A is {}.' .format('test')
'A is test.'
```
`{}`の部分に`.format()`で指定した文字列が代入される。


#####◆どこに代入するかを指定する
```
>>> 'My name is {} {}.' .format('Tony', 'Stark')
'My name is Tony Stark.'

>>> 'My name is {0} {1}.' .format('Tony', 'Stark')
'My name is Tony Stark.'

>>> 'My name is {0} {1}. Watashi ha {1} {0} desu.' .format('Tony', 'Stark')
'My name is Tony Stark. Watashi ha Stark Tony desu.'
```
`{}`が複数ある場合、前から順に代入される。
インデックスを指定してやると、そのインデックスに相当する文字列が代入される。


#####◆変数を用いて指定する
```
>>>Watashi ha {family} {name} desu.' .format(name = 'Tony', family = 'Stark')
Watashi ha Stark Tony desu.'
```


#####◆他の型のものはstr型に変換されて代入される
```
>>> type('1')
<class 'str'>

>>> type(1)
<class 'int'>
```

```
>>> '{}, {}, {}, Go!' .format('1', '2', '3')
'1, 2, 3, Go!'

>>> '{}, {}, {}, Go!' .format(1, 2, 3)
'1, 2, 3, Go!'
```
`1`はint型であるが、str型に変換されて代入される。

<br>

##■f-strings
Python 3.6から、f-stringsが以下のように使えるようになった。

```python:f-strings
a = 'a'
print(f'a is {a}')

x, y, z = 1, 2, 3
print(f'a is {x}, {y}, {z}')
print(f'a is {z}, {y}, {x}')

name = 'Tony'
family = 'Stark'
print(f'My name is {name} {family}. Watashi ha {family} {name} desu.')
```
```:result
a is a
a is 1, 2, 3
a is 3, 2, 1
My name is Tony Stark. Watashi ha Stark Tony desu.
```
Apache NifiでMongodbにCSVデータインポート

#はじめに
分散データをデータフローで整理できるApache Nifiを使う機会がありました。
RDBMSのデータをNoSQLのDatabaseに移行したいなどに使えます。

記事例：[Apache Nifi入門：RDBMSからMarkLogicへの移行](https://jp.marklogic.com/blog/getting-started-with-apache-nifi-migrating-from-relational-to-marklogic-jp/)

#Nifiとは
An easy to use, powerful, and reliable system to process and distribute data.

https://nifi.apache.org/index.html

#Nifiアーキテクチャ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/a74645b3-4043-5aa9-c5e9-2419f233511d.png)


出典：https://nifi.apache.org/docs.html


#CSVファイルをMongodbにインポートするサンプル
CSVデータをコーディングなしでMongoDBにインポートするのをやってみます。

##Nifiインストール（Windows）
①、ダウンロード：https://nifi.apache.org/download.html
②、解凍
③、管理者権限でrun-nifi.batを実行
④、http://localhost:8080/nifi　でアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/713a401a-f00e-337e-0892-22218ed70832.png)

##CSV Readerを追加
設定ボタンからいろいろ共有設定は可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/e6e9e451-ea75-9bae-131b-4d4749e77885.png)

##CSV Reader設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/4eece4a9-686e-38c3-4e8d-72e53da369b1.png)


##GetFileプロセッサー追加＆設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/f215d1a6-fc92-96e7-19e0-61073d19f398.png)

##PutMongoRecordプロセッサー追加＆設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/e85c16ab-e434-4347-0af6-0a2fb83d48bd.png)

##csvデータを設定したフォルダに配置
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/68b74878-6481-7333-8034-9591c2cfac3d.png)


##実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/e9632820-dc3f-8a79-0af9-43adc67d758e.png)

##実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/8d4bde49-1e34-b8be-04f1-83f29b20f79d.png)

GetFileのところ「Keep Source File」がfalseにした場合はデータ投入後元CSVファイルが削除できます。


Apache Avro: https://avro.apache.org/docs/current/


以上
[Rust] PartialOrd を Enum に derive

昨日の記事「[[Rust] 『Go言語でつくるインタプリタ』Rustで読了](https://qiita.com/osanshouo/items/d1b18c90e06670d602fa)」でも言及しましたが, enum に `PartialOrd` を derive することができます. 本記事ではその挙動についてまとめます.

# シンプルな例

enum を定義する際に `PartialOrd` を derive すると, variant を定義した順に大きくなるように不等号が定義されます. なお `PartialOrd` には `PartialEq` が必要なので, 普通はこれを同時に derive することになると思います.

```rust
/// 主系列星のスペクトル型のハーバード分類
#[derive(PartialEq, PartialOrd)]
enum MainSequenceStar { 
    M, K, G, F, A, B, O,
}

fn main() {
    assert!(MainSequenceStar::O > MainSequenceStar::B);
    assert!(MainSequenceStar::G == MainSequenceStar::G);
}
```

# variant がデータを持つ場合

variant がデータを持つ場合, それが `PartialOrd` であれば `PartialOrd` を derive することができます. 順番は, まず variant で比較した後に中のデータを比較することで決められます.

```rust
/// 4次元時空における定常ブラックホール解.
/// 値は質量を除いたパラメータ (a と Q).
#[derive(PartialEq, PartialOrd)]
enum BlackHole {
    Schwarzschild,
    Kerr{a: f32},
    ReissnerNordstrom{q: f32},
    KerrNewman{a: f32, q: f32},
}

fn main() {
    assert!( BlackHole::Schwarzschild < BlackHole::Kerr{a: 0.} );
    assert!( BlackHole::Kerr{a: 0.15} < BlackHole::Kerr{a: 0.99} );
    assert!( std::mem::discriminant(&BlackHole::Kerr{a: 0.15}) == std::mem::discriminant(&BlackHole::Kerr{a: 0.99}) );
    assert!( BlackHole::Kerr{a: 0.99} < BlackHole::KerrNewman{a: 0.2, q: 0.5} );
    assert!( BlackHole::KerrNewman{a: 0.1, q: 0.99} < BlackHole::KerrNewman{a: 0.2, q: 0.1} );
}
```

このようにフィールドが複数ある場合, 定義した際に先にあるものから順に比較されます. なおこの振る舞いは struct に `PartialOrd` を derive したときと同じです.

# 参考文献

* [std::cmp::PartialOrd - Rust](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html)
* [逆引き Rust 列挙体](https://qiita.com/nirasan/items/8eb1b449255f5d192d4b)
* [順序付き比較のためのPartialOrdとOrd - 付録C: 継承可能なトレイト - The Rust Programming Language](https://doc.rust-jp.rs/book/second-edition/appendix-03-derivable-traits.html#a%E9%A0%86%E5%BA%8F%E4%BB%98%E3%81%8D%E6%AF%94%E8%BC%83%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEpartialord%E3%81%A8ord)
ksnctf 30 Alpha Mixed Cipher

#ksnctf 30 Alpha Mixed Cipher
* 問題<br>http://ksnctf.sweetduet.info/problem/30

* alphenumeric shellcode
    * らしいので、調べる
    * 英数字のみからなるシェルコード
    * 英数字ではない文字を棄却するフィルタを通過させるのに使える
* 先頭の文字列を調べていく
    * VTX630VXH49HHHPhYAAQhZYYYYAAQQDDDd36FFFFTXVj0PPTUPPa301089
        * セグメントレジストFSを使ってSEHアドレスを取得し、新しいアドレスに書き換えて故意に例外処理を発生させ実行権を奪う、らしい。。
    * IIIIIIIIIIIIIIIII7QZ
        * ecxレジスタのこと。↑の実行権を奪うにあたって、ベースアドレス（実行させたいコードの先頭アドレス？）をどこかのレジスタに格納したくて、ecxレジスタを使ってるみたい。
    * jAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI
        * mixedcase_ascii_decoder_body
        * ここから先が、実行コードだよ。デコードしてね。実行コードはasciiで大文字小文字まざってるよ。の意味っぽい
* ここまでは、攻撃用。ここから先に、実際に実行したいシェルコードがalphanumeric化されて続いている。なので、攻撃用コードを全部省いてデコードしてみる。
    * ソース元：http://theloshackers.blogspot.com/2013/08/decode-shell-code-encoded-by-alpha2.html
* 得たシェルコードをexeに変換
    * 元：http://sandsprite.com/sc2exe/shellcode_2_exe.php


* 参考記事
    * http://inaz2.hatenablog.com/entry/2014/07/11/004655
    * http://shimenawa.hatenablog.com/entry/2016/08/19/011827
    * https://www.iwsec.org/mws/2010/presentation/2A3-3.pdf
    * https://securiteam.com/exploits/5JP0M2KBPE/
    * https://ja.wikibooks.org/wiki/X86%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9/x86%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
    * https://github.com/un4ckn0wl3z/Alpha2-encoder/blob/master/alpha2.c
    * http://theloshackers.blogspot.com/2013/08/decode-shell-code-encoded-by-alpha2.html
Macでターミナル分割コマンド（iterm2）

Macのターミナルのウィンドウを分割／統合する

分割：Command + D

統合：Command + Shift + D

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588101/31fd27a0-b314-8404-4bae-3657fd19af72.png)
Mac買ったら最初にすること

システム環境設定のキャプチャはmacOS Catalina 10.15.3のものです

#CapsLockをControlにする
システム環境設定>キーボード>修飾キー
から設定を変える

#USキーボードで日本語入力

##Google日本語入力をインストール

https://www.google.co.jp/ime/
こちらから

設定
キー設定をMS-IMEにします。これはお好みで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/4b1247c4-17f9-2ac6-88ab-124f0d0109db.png)


システム環境設定>キーボード>入力ソース
ひらがな(Google)を追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/2b46c05f-2724-7b09-b5a8-f635d63ba125.png)

##Commandキーで英数/かな変換

https://pqrs.org/osx/karabiner/

Karabiner-Elementsをインストール
設定画面でComplex Modificationsタブを選択
Add rule>Import more rules from the internet (open a web browser)をクリック
「japanese」などと検索して「For Japanese （日本語環境向けの設定） (rev 5)」をインポート

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/24403a7e-fc7a-0b61-4504-c83d9f085b75.png)

「コマンドキーを単体で押したときに、英数・かなキーを送信する。（左コマンドキーは英数、右コマンドキーはかな）」
を有効にする

##SafariでEscキーを押した時にフルスクリーンが解除されないようにする
「Safari」で検索
Escキーを多用するWebアプリケーションを使うので、誤作動防止用に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/5e831bdd-0d7a-2ea0-e600-2a285db2d83c.png)


#(付録)キーボードショートカットについて

ctrl + f →
ctrl + b ←
ctrl + p ↑
ctrl + n ↓

ctrl + h 前を削除(deleteキーと同じ)
ctrl + d 後を削除(windowsのdeleteキーと同じ)
ctrl + a 行頭に移動
ctrl + e 行末に移動
ctrl + k 行末まで削除

日本語入力中のショートカット(前述のMS-IME設定の場合)
ctrl + t 半角英数変換
ctrl + i カナ変換

スクリーンショット(範囲指定)
command + shift + 4 画像はデスクトップに保存される
ctrl + command + shift + 4 クリップボードにコピー

その他はキーボード設定から確認。変更も可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/4d8451d1-ee3a-2566-3fda-596e5b5faa70.png)

#トラックパッドの設定

##タップでクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/3cff56f5-20ad-15ba-36e4-71466320afdd.png)

##3本指ドラッグ
アクセシビリティメニューから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/e7e17ad1-9bd8-e6c2-3ad5-fdf808a01bd8.png)

アプリケーションの切り替えが4本指になるという副作用があります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562849/b3350917-9eb3-54e1-e44f-3c5bd4758f1c.png)
【Udemy Python3入門+応用】　13.文字のメソッド

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**


##■文字のメソッド
#####◆`.startswith`
```python:.startswith
s = 'My name is Mike. Hi, Mike.'
print(s)

is_start = s.startswith('My')
print(is_start)

is_start = s.startswith('You')
print(is_start)
```
```:result
My name is Mike. Hi, Mike.
True
False
```
`.startswith`では「指定した文字(列)で始まっているかどうか？」を調べることができる。

#####◆`.find`と`.rfind`
```python:.find_and_.rfind 
s = 'My name is Mike. Hi, Mike.'
print(s)
print(s.find('Mike'))
print(s.rfind('Mike'))
```
```:result
My name is Mike. Hi, Mike.
11
21
```
`.find`で、「指定した文字(列)が何番目か？」を調べることができる。
今回 'Mike' は文中に2回登場しているが、`.find`では最初に登場した 'Mike' の位置を調べている。
`.rfind`では後ろから探すことなる。
今回では2回目に登場した 'Mike' の位置を調べている。

```
M y   n a m e   i s    M  i  k  e  .     H  i  ,     M  i  k  e  . 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25      
```
インデックスを書いてみるとこんな感じ。

#####◆`.count`
```python:.count
s = 'My name is Mike. Hi, Mike.'
print(s)
print(s.count('Mike'))
```
```:result
My name is Mike. Hi, Mike.
2
```
`.count`で、文中に 'Mike' が登場した回数を調べている。


#####◆`.capitalize`と`.title`
```python:.capitalize
s = 'My name is Mike. Hi, Mike.'
print(s)
print(s.capitalize())
print(s.title())
print(s.upper())
print(s.lower())
```
```:result
My name is Mike. Hi, Mike.
My name is mike. hi, mike.
My Name Is Mike. Hi, Mike.
MY NAME IS MIKE. HI, MIKE.
my name is mike. hi, mike.
```
`.capitalize`を使うと、文の先頭の文字だけ大文字となり、残りはすべて小文字となる。
`.title`を使うと、各単語の頭文字が大文字になる。
`.upper`では全ての文字が大文字になる。
`.lower`では全ての文字が小文字になる。


#####◆`.replace`
```python:.replace
s = 'My name is Mike. Hi, Mike.'
print(s)
print(s.replace('Mike', 'Nancy'))
```
```:result
My name is Mike. Hi, Mike.
My name is Nancy. Hi, Nancy.
```
`.replace`で、指定した文字列を任意の文字列に入れ替えることができる。
FlaskでPostgreSQLと連携した読書記録簿を作った

##はじめに
土日で勉強がてら、ちょっとした読書記録簿を作りました。
画面はこちら。
<img width="670" alt="画面.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389437/c0f45ea0-9f50-4b66-8cd7-22d34a83710d.png">

機能としては、読んだ本を登録することと、登録された本のリストを見ることくらいです。
##ソースコード
ソースコードは以下の通りです。htmlは見たままなので割愛します。

```python:app.py
from flask import Flask, render_template,url_for,request,redirect
from sqlalchemy import create_engine
import pandas
import psycopg2

'''
参考にしたサイト
https://tanuhack.com/pandas-postgres-readto/

'''

# PostgreSQLの接続情報
connection_config = {
    'user': 'user',
    'password': 'password',
    'host': 'localhost',
    'port': '5432',
    'database': 'mydb'
}

# psycopg2を使ったDB接続
connection = psycopg2.connect(**connection_config)

# dfの作成
df = pandas.read_sql(sql='SELECT * FROM books;', con=connection) 
header = ['id','書籍名','著者','読了日','評価']
record = df.values.tolist() # DataFrameのインデックスを含まない全レコードの2次元配列のリスト

app = Flask(__name__)

@app.route('/')
def index():
    #indexを読み込むたびにDBからのSELECT文更新
    df = pandas.read_sql(sql='SELECT * FROM books;', con=connection) 
    record = df.values.tolist()
    return render_template('index.html',  header=header, record=record)

@app.route('/result', methods=['GET','POST'])
def addition():
    if request.method == "POST":
        # レコード数再取得が必要
        df = pandas.read_sql(sql='SELECT * FROM books;', con=connection) 
        record = df.values.tolist() 

        # POSTの内容を元にINSERT文の値取得、idは現在のレコード数+1
        book_id = len(record)+1
        res1 = request.form['書籍名']
        res2 = request.form['著者']
        res3 = request.form['読了日']
        res4 = request.form['評価']
        dict1={'id':[book_id],'name':[res1],'writer':[res2],'read_day':[res3],'rank':[res4]}

        # DBに飛ばすにはSQLAlchemy必要
        engine = create_engine('postgresql://{user}:{password}@{host}:{port}/{database}'.format(**connection_config))
        df = pandas.DataFrame(data=dict1)
        df.to_sql('books', con=engine, if_exists='append', index=False)
        return redirect(url_for('index'))

## おまじない
if __name__ == "__main__":
    app.run(debug=True)
```
概要としては、PostgreSQLに読んだ本のテーブルがあり、SELECT文でDataFrameとして取得した内容をリスト化し、render_templateでindex.htmlに送って「あなたが読んだ本」として表示させます。
そして、読んだ本の登録は入力フォームに情報を入力し、登録ボタンを押すことでPOSTメソッドとして処理されます。idは最新の番号を自動で割り振り、他は入力フォームから取得し、1行の辞書型のデータを作ります。
最後に、辞書型のデータをDataFrameに変換し、df.to_sqlでDBにINSERT文を飛ばせばデータが追加されます。

##課題
・デプロイできなかった
　herokuを使おうとしたんですが、デプロイしたものがうまく起動せずに断念しました。
　原因ははっきりしていないのですが、生の環境でやったのが影響していそうだったので、virtualenvを使うべきだったと思います。

・機能不足
　ご覧の通り、データを追加する機能しかありません。登録情報を修正したり、消したかったらコマンドプロンプトで直接DBを見に行かなければいけません。

##今後に向けて
とりあえず、最低限やりたかったDBとウェブページの連携（DBからの取得とDBへの追記)はできたので及第点にしちゃいます。
次は読書記録簿をリメイクするのか別のものを作るか決めていませんが、virtualenvをつかい、少しずつherokuにデプロイする、という作成スタイルでやりたいと思います。
paiza cloudを使って、ipad(スマホでも)だけでクラウド上でNodeの環境を構築し、ssh接続して好きなように動かす

## paiza cloudとは
paiza cloudという「ブラウザを開くだけでエディタ、Webサーバ、DB等の開発環境が整う クラウド開発環境」ができる超絶便利なやつ。

本格的な開発ではazureとかawsが使われるとは思うが、
これらはある程度勉強が必要で、しかもインスタンス起動しっぱなしで止め忘れたら料金が「えぐいてぇ！(某ユーチューバー)」になるので個人でやる分にはいろいろ面倒。

paiza cloudを使うとブラウザを開くだけでスマホでもipadでもPCでもすぐにターミナルを開いて好きなようにプログラムが動かせるのが便利。

なので、電車の中でちょっとライブラリの挙動を試してみたいときに超絶便利。

今回はNodeだが、PHP、Tomcat、Ruby、Django、Laravel、Go、MySQL、PostgreSQLなどがワンクリックの選択で構築可能。

## ipadだけで環境構築
アカウント作って、新規サーバー作成画面では、このようにNodeからPHPなど好きなように選択するだけで、環境構築ができてしまう。

![IMG_0244.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/3b0bb333-1f90-da1e-bbf3-e9b29316aef1.png)


好きなものを選択して「新規サーバー作成」クリックすると。。。

![IMG_0245.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/ec785be2-d01c-4d2b-7a39-51b38ef804b0.png)

たったこれだけで、構築終了。もうNodeJS使えます。。。(驚き)

ちなみに、gitもデフォルトで入ってました。

何よりすごいのが、これをスマホ、ipadがブラウザ開くだけで出来ちゃうところ。
しかもこの画面でエディタも開けて完全にパソコン触ってる感覚になります。

つまり、スマホで「npm install ～」って電車の中で片手で入力して実行できてしまう。

## paiza cloudにssh接続して、もっと便利に扱う
僕がこのサービスを利用する理由は、電車の中とかで
ちょっとnodeのモジュールを試してみたい程度のものなので、
コピペがしたい。
paiza cloudは超絶便利なのですが、スマホやタブレットからだとコピペができないため、
スマホやipadで一文字一文字入力するのはつらい。

なので、sshクライアントで接続して、コピペできるようにする。
今回は「termius」というアプリを使う。
https://apps.apple.com/jp/app/termius-ssh-client/id549039908


ホスト名やポートは、paiza cloudの左上のメニューから「SSH設定」を見れば書いてある。

paiza cloud上でターミナルを開いて、
パブリックキーとプライベートキーを生成して、
クラウド側とsshクラインとでキーの設定するだけ。

## ipadでssh接続した結果
いや、もうパソコンやん(至言)
![IMG_0247.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/ea7425b5-8db6-868d-5b47-d72d6ac6ef4f.png)

## 注意
実はプランによっては急にSSH接続できなくなります。


無料プラン、ライトプラン、ベーシックプラン、
の３つのうち、無料プラン、ライトプランはちょっと時間経ったらコンテナが自動停止します。

しかも、ブラウザで開いている間しかsshできないという罠も。
なのでブラウザ開くのとsshクライアント開くのを頻繁に交互に繰り返してなんとか逃れてるけど非常にだるい。

でも僕がpaiza cloudに対してsshする理由はコピペしたいだけなので正直やらなくてもよい。

●無料プラン・・・1日でサーバー自体削除、時間が少し経つとコンテナ自動停止
●ライトプラン・・・時間が少し経つとコンテナ自動停止されるが、データは残ったまま
●ベーシックプラン・・・上記のデメリットがなくなる。
*「時間が少し経つと」は約480分。つまり8時間。

こんな感じで、停止してるンゴって言われる。
![IMG_0248.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/a12099c4-77f5-c02b-4921-783582822a76.png)


なので、ベーシックプラン以外の場合は、
まずはPaiza cloudにログインして「停止してるので再起動する？」みたいなダイアログが出たら再起動ボタン押す。
そこからsshクライアント使えばよい。

また、クラウド側のパブリックキーは、最初にサーバー作成の際に指定したものから変更できない。
厳密には変更できるが、再起動するたびに最初に設定したパブリックキーにリセットされてしまう。
設定画面から編集しても直接viで編集してもコンテナを再起動してしまうとまたリセットされてしまう。それはまあ仕方ない。

なので、最初に正しいパブリックキーを指定すればいいが後回しにするとコンテナが再起動するたびに設定し直すことになるので注意(この仕様どうにかしてほしい)

このサービスを使う人は、ちょっと動かしてみたいぐらいの気持ちなはずなので、別にこの手間は気にしていません。満足してます。

無料プランだと1日経てばサーバー自体が消えてしまうので、毎回キー生成してsshの設定するのは面倒なので、ライトプランにしました。

でも僕、実は学生時代から利用しているレンタルサーバーがあるのでそこからキー生成してsshしたら金払わなくて済むけどpaiza cloudだとブラウザでターミナル操作やエディタ開けたり編集がすぐできるのが良いからなぁ。。。(そういうの無料で出来るアプリあったら知りたい)

試しにpaizaに対してsshした状態で自分が既に持っていたレンタルサーバーに対してSSHしてみたらレンタルサーバーをあの編集画面で操作できるようになるのか？って思ってやってみたら、当然ファイル一覧に表示されるのはpaiza cloudにあるファイルなので意味なかった。

まあ実家暮らしで飲みに行くことも無く余裕あるので、月1000円ぐらい払いますよ。払えばいいんでしょう！？(王者の風格)(ツンデレ)

## 感想
パソコンでガッツリ使うなら他のレンタルサーバー使うべき(大容量かつ高速かつコンテナが落ちることはない)、スマホやタブレットで手軽に便利に試してみたいときはPaizaがよい。でも僕は自分のサーバ持ってるしあまりPaizaを使うことはなさそう(てのひらくるっくる)
【Udemy Python3入門+応用】　12.文字列のインデックスとスライス

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**

##■インデックス
#####◆インデックスの使い方
```python:index
word = 'python'

print(word[0])
print(word[1])
print(word[2])
print(word[3])
print(word[4])
print(word[5])
```
```:result
p
y
t
h
o
n
```
変数に文字列を代入したとき、その文字列の任意の文字を指定できる。
Pythonにおいて、**「1番目の文字」のインデックスは「0」**であることに注意。

#####◆インデックスのエラー
```python:index
word = 'python'

print(word[100])
```
```:result
    print(word[100])
IndexError: string index out of range
```
このとき、文字列の範囲を超えたインデックスを指定するとエラーとなる。

#####◆インデックスの「ー」
```python:index
word = 'python'

print(word[-1])
print(word[-2])
print(word[-3])
```
```:result
n
o
h
```
`[-1]`などは先頭の文字(`[0]`)から更に左にいき、最後の文字に回るようにカウントされる。
よって、`[-1]`は最後の文字を表すインデックスとなる。

<br>

##■スライス
#####◆スライスの使い方
```python:slice
word = 'python'

print(word[0:2])
```
```:result
py
```
`[:]`により、始点と終点を指定し、その間の数を指定することができる。

```
｜p｜y｜t｜h｜o｜n｜
0　1　2　3　4　5　6
```
インデックスは実際は文字と文字の間を表しており、このように考えるとわかりやすい。
(0と2の間は「py」となる。)

#####◆省略
```python:slice
word = 'python'

print(word[:2])
print(word[2:])
print(word[:])
```
```:result
py
thon
python
```
始点を省略すると「最初から」になり、
終点を省略すると「最後まで」になる。
始点も終点も省略した場合は、文字列全体を指定することになる。

<br>

##■文字列の任意の文字だけを入れ替える
#####◆「python」→「jython」
```python:change_letter
word = 'python'
word = 'j' + word[1:]
print(word)
```
```:result
jython
```

<br>

##■文字数をカウントする
```python:count_letters
word = 'python'

n = len(word)
print(n)
```
```:result
6
```
文字列の"length"を`len()`を用いてカウントすることができる。
素人によるビット全探索

## はじめに
　ビットの扱いが不慣れでビット全探索をするときは毎回コピペすることでやり過ごしていました。しかし、以下の記事で水色コーダーになるためには`bitset`やビット全探索は知っておきたいと紹介されていたので、この機会にちゃんと理解しようと思いました。
[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編：目指せ水色コーダー！】](https://qiita.com/e869120/items/eb50fdaece12be418faa)

　今回の記事の内容は自分が詰まっていたところです。ビット演算に関しては以下の記事が詳しいです。
[ビット演算 (bit 演算) の使い方を総特集！ 〜 マスクビットから bit DP まで 〜](https://qiita.com/drken/items/7c6ff2aa4d8fce1c9361)

## 詰まっていたところ
　全ての元凶はシフト演算子`>>`でした。シフト演算子はビットを左右にずらすものだと思っていました(その通りなんですが)。例えば、

```cpp
for (int bits = 0; bits < (1 << n); bits ++)
```

ビット全探索では上のような部分をよく見かけます。このとき、「`(1 << n)`の部分は1のビットをn桁左にずらすだけなのに、なぜこれが終了条件になるの？」と疑問に思っていました(この疑問わかってもらえますか？)。しかし実際は「数値１を２進数で表したものをn桁左シフトしたものの値」だったんですね。

　実際に手元で試してみると、

```cpp
cout << (1 << 5) << endl; // 32
cout << (1 << 10) << endl; // 1024
```

と値が返ってきています。どうやらシフトするという処理とその結果を混同していたようです。

## さらに詰まっていたところ
　シフト演算子の左右の位置って重要なんですね。いつも左側が`1`だったので順番を意識していませんでした。`x << y`なら`xの２進数表現の値をy桁分左にシフト`、`x >> y`なら`xの２進数表現の値をy桁分右にシフト`となるんですね。目が開かれる思いでした。

## いざビット全探索！
　では、ビット全探索でよく出てくる部分を読み解いていきます。まずはこちら。

```cpp
for (int bits = 0; bits < (1 << 5); bits ++)
```

`bits < (1 << 5)`の部分は1(`0b000001`)を５桁分左シフトしたもの(`0b100000`)なので`32`を終了条件とするということですね。仕組みがわかれば楽チンです。

　次はこちら。

```cpp
if (bits & (1 << 5))

// bits == 33 (0b100001)のとき
if (0b100001 & (0b100000)) // -> if (0b100000) -> if (32) -> true

// bits == 31 (0b011111)のとき
if (0b011111 & (0b100000)) // -> if (0b000000) -> if (0) -> false
```

　分解すれば上のようになり、このif文も理解できました。`bits & (1 << n)`でやりたいことは、`bitsのn桁目のフラグが立っているかどうか`のチェックとなります。`1 << n`のフラグはn桁目の１つしか立っておらず、それとの論理積で`0`が返ってきた時は、bitのn桁目のフラグが立っていないことになるというわけですね。

## おわり
　書いてて思ったんですが、２進数のまま考えた方が分かりやすい気がしましたし、その方がビット全探索でやりたいことにも適していると思います。ビット演算子に慣れないために２進数の世界と１０進数の世界を行ったり来たりして頭がこんがらがっていました。今後はビット演算子を使うときは２進数の世界に常駐していようと思います。

## 編集履歴
2020/03/03 22:08
`0`から始まるリテラルは８進数とのご指摘を受け、２進数であることを明確にするためリテラル`0b`を追記しました。

2020/03/03 22:12
`bit`を複数形の`bits`に修正しました。
ROS講座 109 逆運動学を解く

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 16.04 |
| ROS | Kinetic |

インストールについては[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参照してください。
またこの記事のプログラムはgithubにアップロードされています。[ROS講座11 gitリポジトリ](https://qiita.com/srs/items/25a56a6abda41dcf396e)を参照してください。

# 概要

ロボットアームの制御ではアームの先端をある地点に移動させるという制御が良く行われます。しかしロボットアームへの入力として、各軸の角度を渡します。この2つを変換するのがアームの制御の基本になります。

* 「各軸の角度」->「先端の位置」に変換するのを「運動学」
* 「先端の位置」->「各軸の角度」に変換するのを「逆運動学」

と呼びます。これらをプログラムしていきます。

# 対象となるアーム
特に逆運動学はアームが複雑になると、そもそも解析解がなく反復法で解く必要がありますし、そこまで複雑にならなくてもベアで書くのには限界があります。ここではよくつかわれる4軸のアームを例にとります。
下の図のように根元から、yaw回転をする軸が1つ、pitch回転をする軸が3つあります。この構成だと先端の角度を水平などに指定したまま、先端のxyzの位置を指定できるために簡易的なロボットアームでよく使われる形式です。

![arm_link図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/fd162c28-1bf2-e6bf-bc27-b57814222c1c.png)


# 計算の原理

## 運動学
たいそうな名前がついていますが、ただ三角関数の計算をするだけです。
x,y,zの座標系に、第1関節の向いているほうの向きにL軸を取ります。

![arm_link図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/531a9284-1905-16c6-0063-a2c9e910eede.png)

```math
L軸: L3sin(a2) + L4sin(a2+a3) + L5sin(a2+a3+a4)\\
Z軸: L1 + L2 + L3cos(a2) + L4cos(a2+a3) + L5cos(a1+a2+a3)\\

\left(
  \begin{array}{ccc}
    x \\
    y \\
    z 
  \end{array}
\right)
=
\left(
  \begin{array}{ccc}
    L軸 cos(a1) \\
    L軸 sin(a1) \\
    Z軸 
  \end{array}
\right)
```

## 逆運動学
こちらは少々複雑です。最終的に2軸で余弦定理を使うところまで追い込みます。
出力は(a1,a2,a3,a4)の4変数になるので一意な入力を得るには先端の(x,y,z)位置と選択の角度(φ)を入力とします。φ=0は先端が真上を向いている。φ=π/2は真横を向いているを表します。

![arm_link図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/8d86643e-574d-f22d-4511-bfb6fb4be02a.png)

問題設定から第1リンクの先と第3リンクの先の(L,Z)面での座標が求まります。

![arm_link図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/0b45a9bb-59c6-4cb4-b0b0-ab1c0292dc48.png)

ここで第3、第4リンクだけを切り抜くと以下のようになります。ここでできる三角形の3辺の長さが分かるので、余弦定理から角度を求められます。
![arm_link図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/a8b54e11-fdbc-5833-fe99-4d0aa7d16ea3.png)

# ソースコード

逆運動学を解くプログラムは[arm_lecture/src/arm_ik.h](https://github.com/project-srs/ros_lecture/blob/master/arm_lecture/src/arm_ik.h#L84)にあります。
[arm_ik_node](https://github.com/project-srs/ros_lecture/blob/master/arm_lecture/src/arm_ik_node.cpp)でこれを使って動かします。

# ビルド
```shell
cd ~/catkin_ws
catkin_make
```

# 実行

```shell
 roslaunch arm_lecture arm4d_ik.launch 
```

逆運動学の入力となる入力のx,y,z位置を赤の球で表示します。その場所に移動するアームの角度を算出して移動します。

![arm_ik.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/94755f47-a861-4fd1-eda3-3ea872377b03.gif)

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)
GoLandデフォルトで使用可能なLive Templates一覧

## Live Templatesとは
JetBrains IDEにおけるコードテンプレート機能です。よく使うコードの構造を登録することで、コードをかんたんに挿入することができます。

挿入方法は、`err` などとキーワードを入力して、そのままTabキーを押すだけです。

以下の表はデフォルトで登録してあるLive Templatesをまとめましたが、もちろん自分でLive Templatesを登録することも可能です。

参考:[ライブ・テンプレート - 公式ヘルプ | IntelliJ IDEA](https://pleiades.io/help/idea/using-live-templates.html)

## GoLandデフォルトで使用可能なLive Templates一覧

|name|value|description|
|---|---|---|
|`:`|`$NAME$ := $VALUE$ `|`Variable declaration :=`|
|`bench`|`func Benchmark$NAME$(b *testing.B) {&#10; for i := 0; i &lt; b.N; i++ {&#10; $END$&#10; }&#10;} `|`Benchmark`|
|`con`|`const $NAME$ $TYPE$ = $VALUE$ `|`Constant declaration`|
|`err`|`if $ERR$ != nil {&#10; $END$&#10;} `|`If error`|
|`for`|`for $VAR0$; $VAR1$; $VAR2$ {&#10; $END$&#10;} `|`For loop`|
|`forr`|`for $KEY$, $VALUE$ := range $COLLECTION$ {&#10; $END$&#10;} `|`For range loop`|
|`imp`|`import (&#10; &quot;$END$&quot;&#10;)&#10; `|`Import declaration`|
|`init`|`func init() {&#10; $END$&#10;} `|`Init function`|
|`iota`|`const $NAME$ $TYPE$ = iota `|`Iota constant declaration`|
|`json`|`json:&quot;$FIELD_NAME$&quot; `|`json:&quot;&quot;`|
|`main`|`func main() {&#10; $END$&#10;} `|`Main function`|
|`map`|`map[$KEY_TYPE$]$VALUE_TYPE$ `|`Map type`|
|`meth`|`func ($RECEIVER$ $TYPE_1$) $NAME$($PARAMS$) $TYPE_2$ {   &#10; $END$&#10;} `|`Method`|
|`p`|`package $NAME$ `|`Package declaration`|
|`printf`|`fmt.Printf(&quot;$END$&quot;,$VAR$) `|`printf`|
|`test`|`func Test$NAME$(t *testing.T) {&#10; $END$&#10;} `|`Test`|
|`xml`|`xml:&quot;$FIELD_NAME$&quot; `|`xml:&quot;&quot;`|`

### Go Struct Tags
|name|value|description|
|---|---|---|
|`json`|`json:&quot;$FIELD_NAME$&quot;$END$`|`json:&quot;&quot;`|
|`xml`|`xml:&quot;$FIELD_NAME$&quot;$END$`|`xml:&quot;&quot;`|
[Xcode]ディレクトリをターミナル にドラッグ&ドロップすれば絶対パスが表示される

Project Navigatorのgroupからターミナル にドラッグ&ドロップすればgroupまでの絶対パスが表示されます。

<img width="841" alt="スクリーンショット_2020-03-01_11_15_51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/f84eb546-bb50-084f-4551-fa68213f5011.png">

## こういう時に便利
- Xcodeを開いていてさくっとルートディレクトリにファイルを作りたいとき。
  - `Podfile`や`Cartfile`など

このままではルートディレクトリでは無いので先頭のパスを消す必要があります。

```
$ cd /Users/[UserName]/iOS/[Project Name]/[Project Name]⬅︎先頭のパスが不要
```
【AWS】【SAA対策】DynamoDB

# DynamoDB
## サービス概要
高速で予測可能なパフォーマンスとシームレスなスケーラビリティのフルマネージド型の NoSQL データベースサービス。

## 特徴
- 分散データベースの運用とスケーリングに伴う管理作業（ハードウェアのプロビジョニング、設定と構成、レプリケーション、ソフトウェアのパッチ適用、クラスタースケーリングなど）を自分で行う必要がなくなる。
- 十分な数のサーバー間でデータとトラフィックを自動的に分散し、一貫した高速なパフォーマンスを維持。
- 保管時の暗号化。
- 任意の量のデータを保存および取得できるデータベーステーブルを作成し、任意のレベルのリクエストトラフィックを処理。
- ポイントインタイムリカバリを使用すれば、過去 35 日間の任意の時点にテーブルを復元可能。
- Key-Valueストア＝「値」とそれを取得するための「キー」だけを格納するというシンプルな構造。
- DynamoDB Acceleration
 - 可用性が高くフルマネージドなDynamoDB用 インメモリキャッシ。1秒あたり100万回単位のリクエストに数ミリ秒の応答時間で処理が可能。DynamoDBに格納されたデータの読み込み回数を減らすことができるため、読み込みスループットが向上。

## 類似サービスとの比較
|                  |   RDS       |    DynamoDB       |Redshift|ElastiCache|
|:-----------------|:------------------|:-------------------|:-------------------|:-------------------|
| 概要             | ・リレーショナルデータベース。<br>・主なDBエンジンをサポート、ツールがそのまま使えるため、オンプレからの移行に便利。<br>・データベースソフトウェアのパッチは自動パッチが可能。|  ・NoSQL データベースサービス。<br>・結果整合性<br>・write直後のreadでは整合性が取れない場合あり。<br>・「強い整合性」オプションを指定すると性能は落ちる。<br>・レコードのサイズに上限あり。<br>・リージョンサービスでありプライベートネットワークからはNAT経由でアクセスする必要あり。    |・データウェアハウスタイプ<br>・スケーラブル<br>・高パフォーマンス|・メモリーキャッシュタイプ<br>・Memcached：Key-Value Store形式のメインメモリキャッシュ。マルチノートのキャッシュクラスタ。<br>・Redis：Memcached：Key-Value Store形式のメインメモリキャッシュ。|
| 場所          |   AZ サービス（VPC内に配置） |      リージョン      |	AZ サービス|	AZ サービス（VPC内に配置）|
| バックアップ             |  スケージュールで1日1回取得可能(手動可)※ただし、バックアップ中はI/O停止、止めたくない場合はマルチAZ利用する必要あり |       -      |-|(memcached)バックアップ機能はなし(Redis)Snapshotによる永続化|
| ユースケース             |  OS以下レイヤの管理不要、高可用性な、既存データベースの利用など |  大量のオンライントランザクション処理など|大容量データの分析など|DBの負荷低減用のメモリキャッシュ|



★NoSQLとRDBMS

|                  | NoSQL       |  RDBMS      |
|:-----------------|:------------------|:-------------------|
| 特性            |      ・**B**asically **A**vailable(基本利用可能)<br>・**S**oft-state(柔軟な状態)<br>・**E**ventual Consistency(結果整合性) |    ・**A**tomicity(原子性)<br>・**C**onsistency(一貫性)<br>・**I**solation(独立性)<br>・**D**urability(永続性)     |
|   処理  |  トランザクション処理にあたり、データの更新においては、古いデータが存在する時間を許容。 |  トランザクション処理にあたり、即時に一貫したデータの整合性を保証し、処理が途中で失敗した場合は、ロールバックし、処理がなかったことになる。       |
| スケールアウト            |     スキーマを固定しないシンプル構造のため、水平的に分散スケールアウトが可能 |    整合性をもってデータを更新するため、水平的に分散スケールアウトするのが困難。      |


## ベストプラクティス
- DynamoDBストリームを有効にすると、作成したLambda関数にストリームARNを関連させることができる。Lambdaがストリームをポーリングすることで、新しいレコードを検出し、Lambda関数を呼び出す。
- DynamoDBのテーブルは、パーティションキー全体でアクティビティが均一になるアプリケーション設計をする。テーブルはスキーマを持たないため、開発の自由度があがる。また、キーバリューの構造はキーをもとにして、データを分散格納できるため、水平にスケールが可能。
- DynamoDBでThlottlingExceptionとLimitExceedExceptionのエラーが返されたときは、アプリケーションでリクエストを再試行することで解決できる。
- フルマネージドによる高い拡張性、データへの1桁ミリ秒のレイテンシー、マルチリージョン/マルチマスターの高い信頼性を実現するNoSQLDBはDynamoDB。
- DynamoDBは、データベースとして、JSONドキュメントの保存、インデックスの可用性、Auto Scalingが必要な場合にも適している。
- DynamoDBでは結果整合性に基づく処理をするため、多くのトラフィックを処理可能だが、一方それらの読み込みを可能にするため、古いデータの読み込みが発生してしまう。DynamoDBの読み込みオペレーションのオプションのConsistReadパラメータをTrueにすることで強力な整合性のある読み込みを可能とし、回避できる。
- DynamoDBに一時的なアクセス集中がある場合、以下の手段により、対応が可能。
 - SQSメッセージからDynamoDBに書き込みをするように連携
 - DynamoDBに対してAutoScalingを適用
- 新規テーブル作成の際、Read,Writeに対して、プロビジョニングスループットを指定する。
- クロスリージョンレプリケーションが可能なテーブルを作成することにより、グローバルユーザー向けにスケールしたアプリケーションの構築やDR対策に利用できる。
- キャパシティユニットを適切に設定することでコストを抑えることができる。
はじめてのDjango起動

#■環境
　windows10
　Pycharm　Community　2019.3
　Python3.7

#■前提条件

　Djangoプロジェクト、アプリケーション作成していることを前提。以下参照
　![ターミナルでDjangoアプリケーション作成まで](https://qiita.com/oporimaster/items/4ec4809284cddd8b4ba0)


#■Djangoの起動


プロジェクトのディレクトリに移動して、runserver

```
C:\python_project\venv_python_dev\Private_Diary_project>python manage.py runserver
```

ブラウザで　http://127.0.0.1:8000/
つながりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547159/64af55f8-0ac2-4854-431c-3989126d209c.png)

ターミナルで、「　CTL+C　」　でWebサーバ停止

以上
Unity SceneViewのカメラ操作感変更

Unity2018?系からSceneViewのToolbarからカメラ操作感を変えられるようになりました。
プロジェクトごとに最適なSceneカメラのスピードは違うので適宜変更すると良きです。

![スクリーンショット 2020-03-01 18.28.21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/d64781c4-b9a0-1fc6-bb7a-614e28107166.jpeg)
【AWS】【SAA対策】Route53

# Route53
## サービス概要
可用性と拡張性に優れたDNSウェブサービス。
ドメイン登録、DNSルーティング、ヘルスチェックの3つの主要な機能を任意の組み合わせで実行可能。

## 特徴
- ドメイン名の登録
 - 新しいドメイン名（URL が http://example.com であれば、example.com という部分）を取得する場合は、ドメイン名を Amazon Route 53 に登録可能。既存のドメインの登録を他のレジストラから Route 53 に移管することも、逆に、Route 53 に登録したドメインの登録を別のレジストラに移管することも可能。
- ドメインのリソースへのインターネットトラフィックのルーティング
 - ホストゾーンの作成(パブリックホスト/プライベートホスト)
- リソースの正常性のチェック
 - Route 53 ヘルスチェックでは、ウェブサーバーや E メールサーバーなどのリソースの正常性を監視します。必要に応じて、リソースが使用不可になったら通知を受け取るように、ヘルスチェックに対して Amazon CloudWatch アラームを設定可能
- A,CNAME,MX,NS等の代表的なレコードタイプはサポート。
- エイリアスレコード：Amazon CloudFront ディストリビューションやAmazon S3バケットなどの AWSリソースにトラフィックをルーティングするためにAmazon Route 53で作成できるレコードタイプ。CNAMEと同様な扱いを受ける。実態はAレコード。
 - CNAMEは他のレコードとの共存ができないため、Zone Apexに設定できないが、エイリアスレコードの実態はAレコードのため、Zone Apexに設定できる。
- エイリアスレコードはAWS内で利用する限られたDNS名に対してのみ指定可能。(CloudFront distribution, ELB, static website設定をしたS3バケット, 他のRoute 53リソースレコードセット)

## 種類やタイプ
#### ルーティングポリシー
|                  |   ルーティング        |
|:-----------------|:------------------|
| シンプルルーティングポリシー             |   ドメインで特定の機能を実行する単一のリソース (example.com ウェブサイトにコンテンツを提供するウェブサーバーなど) にインターネットトラフィックをルーティング |        This        |
| フェイルオーバールーティングポリシー           |    アクティブ/パッシブフェイルオーバーを構成する場合に使用 |       column       |
| 位置情報ルーティングポリシー             |    ユーザーの場所に基づいてインターネットトラフィックをリソースにルーティング |        will        |
| 地理的近接性ルーティングポリシー             |  リソースの場所に基づいてトラフィックをルーティングし、必要に応じてトラフィックをある場所のリソースから別の場所のリソースに移動する |        will        |
| レイテンシールーティングポリシー             |    複数の場所にリソースがあり、レイテンシーが最も小さいリソースにトラフィックをルーティングする |        will        |
| 複数値回答ルーティングポリシー             |       ランダムに選ばれた最大 8 つの正常なレコードを使用して Route 53 が DNS クエリに応答する場合に使用 |        will        |
| 加重ルーティングポリシー            |   指定した比率で複数のリソースにトラフィックをルーティング |        will        |

#### レコードタイプ
|      |  CNAMEレコード |  ALIESレコード |
|:-----------------|:------------------|:-------------------|
|リダイレクト先|DNSクエリを任意の DNSレコードにリダイレクト。<br>A や AAAA などのレコードタイプに関係なく、レコード名に対する DNS クエリをリダイレクト|選択したAWSリソースにのみクエリをリダイレクト。<br>エイリアスレコードの名前 (acme.example.com など) とエイリアスレコードのタイプ (A や AAAA など) が DNS クエリの名前とタイプと一致した場合にだけ DNS クエリに応答。|
| ドメイン名そのものへのマッピング  |  不可 |  可能(Zone Apexを利用)    |
|Zone Apex           |   不可(Zone ApexにはNSレコードが必要なため。) |     可能(AWS リソースにトラフィックをルーティング) |
| パフォーマンス     |   良い |  CNAMEより良い     |

## ベストプラクティス
- ブルーグリーンデプロイメントは、稼働システムと準備システムで本番系のトラフィックを切り替える方法で、重み付けで段階的移行が可能になる加重ルーティングが適切。
- 複数リソースにDNSクエリのレスポンスを分散して返答する場合は複数値回答ルーティングを利用し、正常なリソースの値のみを戻すことができる。
- Route53のヘルスチェックはインターネット経由でアクセスできるエンドポイントに使用可能なため、オンプレミスからクラウド環境へのDNSフェイルオーバーとして、利用可能。
- エイリアスレコードを利用すると、DNSクエリに対して、AWSサービスのエンドポイントのIPアドレスを直接返すため、レスポンスがはやくなる。
- サーバーごとに性能の偏りがある場合は、加重ルーティングで性能ごとに分配して振り分けができる。
- 自動フェールオーバーのルーティングではCNAMEを利用する。
【AWS】【SAA対策】Redshift

# Redshift
## サービス概要
エンタープライズレベル、ペタバイト規模、フルマネージド型のデータウェアハウスサービス。
超並列処理、列指向データストレージ、および非常に効率的で対象を限定したデータ圧縮エンコードスキームの組み合わせによって、効率的なストレージと最善のクエリパフォーマンスを実現。
シンプルで費用対効果の高いサービスを実現し、既存のビジネスインテリジェンスツールを使用して、すべてのデータを効率的に分析可能。

## 特徴
- ビジネスインテリジェンス (BI)、レポート、データ、分析ツールなど、多くの種類のアプリケーションとのクライアント接続をサポート。

## 類似サービスとの比較
*比較対象としてDynamoDBも記載されることが多いが、NoSQLDBのため、今回は省きます。

|                  |   Redshift        |    RDS       |
|:-----------------|:------------------|:-------------------|
| 概要             | ・データウェアハウスタイプ/スケーラブル/高パフォーマンス。<br>・OLAP(複雑で分析的な問い合わせに回答) | ・インスタンスでありVPC内に配置可能。<br>・MySQL、Oracle、Microsoft SQL Server、PostgreSQL、MariaDB、Amazon Auroraをサポート。現行のツールがそのまま使えるため、オンプレからの移行が比較的容易。<br>・データベースソフトウェアのパッチは自動パッチが可能。   |
| ユースケース          |  大容量データ分析。列指向DB。リレーショナルデータベース | リレーショナルデータベース。メタデータ分析。比較的、汎用的に利用可能      |

## ベストプラクティス
- 列指向データベースは水平スケーリングが可能なため、低コストの分散クラスターを使用し、スケールアウトすることで、高い費用対効果でスループットを向上できる。ペタバイトクラスの構造化データウェアハウスとしてビッグデータ分析処理に最適。
- Redshiftは暗号化されたSSL接続を使用して、スナップショットをS3に保存可能。EBS同様、増分スナップショットを自動作成し、このスナップショットからクラスターを復元可能。このバックアップは残ってしまうため、保持期間を指定または削除が推奨される。
- プライマリクラスターがダウンした場合、すぐに利用できるようにするにはクロスリージョンスナップショットを利用する。（自動的に他リージョンへコピーされるよう設定）
- S3に蓄積したデータをRedshiftと連携する場合で、VPCのプライベートサブネット内でのデータ利用に限定したいという要件がある場合、
 - Redshift拡張VPCルーティングの設定する
 - S3にVPCエンドポイントからアクセスする
Windows10上のSpacemacsでHelm Git Grepが頻繁に固まる

# 概要
Windows10でSpacemacsを使っている時、Helm Git Grep ( `Space g /`)で文字の高速タイピングをすると高確率でフリーズする。

1文字打つ度に反応速度が凄い (デフォルトは0.01秒っぽい)ので、高速タイプによって処理が衝突したりしているのかもしれない。

1文字ずつ反応を確かめながら打たねばならずストレスが凄い。







# ひとまずの対処
Spacemacsの設定ファイル `.spacemacs` ( `Space f e d`)の `dotspacemacs/user-config ()`内で、Helmの入力に対する反応速度を操作する。

具体的には以下をやる。

- Helmのミニバッファ ( `Space f f`など)が開いたら追加の判定を始める
- もしHelm Git Grepのバッファなら、入力から反応までの遅延時間 `helm-input-idle-delay`を0.5秒に遅らせる
- それ以外のバッファなら、 `helm-input-idle-delay`を0.01秒に戻す

以下のように追記する。

```emacs-lisp
(defun dotspacemacs/user-config ()

  ;;; Helm

  ;; 入力への反応時間を `Git Grep`のときだけ遅らせ、それ以外では戻す
  (add-hook 'helm-minibuffer-set-up-hook
            (function (lambda ()
                        (if (equal (helm-buffer-get) "*helm git grep*")
                            ;; (message "Helm Git Grepですねぇ！")
                            (setq helm-input-idle-delay 0.5)
                          (setq helm-input-idle-delay 0.01)))))

)
```

毎回書き換えが起こるのはつらいな、と思い、こういう方法もあるかも。
（バッファ名がhelmじゃないなら書き換え自体しない）

```emacs-lisp
(add-hook 'helm-minibuffer-set-up-hook
            (function
             (lambda ()
               (let ((buffer-name (helm-buffer-get)))
                 (if (string-match "*helm.*" buffer-name)
                     (if (equal buffer-name "*helm git grep*")
                         ;; (message "Helm Git Grepですねぇ！")
                         (setq helm-input-idle-delay 0.5)
                       (setq helm-input-idle-delay 0.01))
                   nil)))))
```





# 場当たり的に対処するなら
helmの設定に `helm-input-idle-delay`を追加すれば、以下のように遅延時間を (全体的に)0.2秒遅らせることもできる。

```emacs-lisp
dotspacemacs-configuration-layers
'(
  ;; ここ
  (helm :variables
        helm-input-idle-delay 0.2)

  )
```


ただし、これだと `Ctrl + l`でのディレクトリ移動など、通常のHelm操作までラグる。





# 解決までの経緯
## `dotspacemacs-which-key-delay`ではダメ
最初にSpacemacs自体の設定で解決することを考えたが、 `dotspacemacs-which-key-delay`では対象範囲が広すぎた。

しかもSpacemacs全体の反応速度は落ちるくせに、Helm Git Grepは元気に反応してしまう。


## `helm-input-idle-delay`は有効
次に、各レイヤーの設定を見た。幸いHelm layerには `helm-input-idle-delay`の存在を確認できた。

定義ジャンプすると、初期値は0.01秒っぽい。

これで急場はしのげたが、Helm全体の反応速度を落としてしまうので良くない。


## `helm-grep-input-idle-delay`が使えない
巷でやり玉に挙げられていたのは `helm-grep-input-idle-delay`だった。

cf. [Emacs helm grep flickering](https://github.com/emacs-helm/helm/issues/2106#issuecomment-441373203)

定義を見るとこんな感じで、grepのときだけ別途に遅延させてくれるらしい。

```emacs-lisp
(defcustom helm-grep-input-idle-delay 0.6
  "Same as `helm-input-idle-delay' but for grep commands.
It have a higher value than `helm-input-idle-delay' to avoid
flickering when updating."
  :group 'helm-grep
  :type 'float)
```

……が、Spacemacsではどうやら機能していなかった :innocent: 


## `helm-input-idle-delay`を動的に変えることに
どうしようもないので、バッファがHelm Git Grepのときだけ一時的に遅延時間を変えられないか、と考えていた。その結果、生まれたのが冒頭のアレ。

バッファ判定はどのタイミングでフックすればできるのか、そのバッファ名をどうやれば取得できるのか、自力で調べるのがとてもつらかった。

もっと良い方法もあるだろうが、これ以上は頑張れない。。。