OmniAICreator/Qiita-1.07M huggingface dataset:
ransackを使ったプルダウン付き検索フォーム（アドバンストモード）

##やりたいこと
<img width="817" alt="スクリーンショット 2019-02-21 16.47.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/332184/91a9ba70-33ff-53aa-d309-8107f97c6fc9.png">

これ。
~~画像はいわずもがなa○azonです。~~

いちいち全データから検索しなくてもいいよって時に、
プルダウンで範囲を絞って（カラム指定）検索できたらいいのに・・・。
そんなにこだわらなくても、よほど膨大なデータでない限り問題はないことですが、

それ以外にも
ーーーーーーーーーーーーーーーー
（例）CD商品検索

「商品１」
歌手名:さかな
**CD名:にく**　

「商品２」
**歌手名:にく**
CD名:ふぃれ
ーーーーーーーーーーーーーーーー
上記のように歌手名で検索したつもりが同名のCDがヒットしたり、
CDを探していたのに歌手名でヒットした分お目当ての検索結果が埋もれたり。

かといって、チェックボックスを追加するのもデザイン的にすっきりしない・・・。
と思ったので、公式Gitなどを眺めながら以下やり方をまとめました。

##やりかた （プルダウン付きのフォームを表示させるまで）
```Gemfile.rb
gem 'ransack'
```
まずはransackを`Gemfile`に追記して`bundle install`

```検索フォームを出すcontroller.rb
def hoge
  @q = Post.ransack #試した当時はsearchメソッドでしたが恐らくransackでも動きます
  @q.build_condition if @q.conditions.empty? #これを書かないとformが表示されない
end
```
検索フォームを表示させるページのコントローラーに上記追記(必要に応じて以下変更要)
-`hoge`→フォームを表示させるアクション（indexとか）
-`Post`→検索するテーブル

```検索結果ページのcontroller.rb
def fuga
  @result = @q.result(distinct: true) #ここで実際に検索
end
```
ここまでは通常のransackの使い方とほぼ同じ。
違うのはparamsで検索条件を指定しないところです。(必要に応じて以下変更要)
-`fuga`→検索結果を表示させるアクション

```検索フォームを出す.html
<%= search_form_for @q, html: {class: 'hogehoge'} url: fuga_path do |f|%>

    <!-- ここで検索するカラムを指定-->
    <%= f.condition_fields do |c| %>
      <%= c.attribute_fields do |a| %>
        <%= a.attribute_select associations: [] %>
      <% end %>

      <!-- ここで曖昧検索(cont)を指定。これはc.hidden_field :p, value:を使って絞り込むことが可能-->
      <%= c.hidden_field :p, value: "cont" %>
      <%= c.value_fields do |v| %>
        <%= v.search_field :value, placeholder: '検索ワードを入力' %>
      <% end %>
    <% end %>
    <%= f.submit '検索' %>
<% end %>
```
viewに上記記載することでカラムを指定するためのプルダウンがついた検索フォームができます。(必要に応じて以下変更要)
-`hogehoge`→後で使うためクラス名を付与
-`fuga_path`→`検索結果ページのcontroller`の`fuga`へのpathを記載

```検索結果を出す.html
<% @result.each do |post| %>
(中略)
<%end%>
```
結果を表示。

##不要なカラムを非表示にする
ここまでで、この記事の最初の画像のようなフォームを作ることができました。
**しかしながら・・・、**
どうもこのままの記述だと、テーブル内の全カラムが表示されてしまうようです・・・。
（例）商品を登録したユーザーのID、登録した時間

```いずれかの.scss
.hogehoge {
$is: 1,3,5,6;
/*$isに何番目を指定するかいれる*/

@each $i in $is {
    option:nth-of-type(#{$i}) { display: none }
/*つまり上記の場合,1,3,5,6番目のカラムを非表示にしてる*/
}
}
```
試行錯誤した結果、上記記述で非表示にして対応しております。
.cssには書き込めないので注意してください。
（元からある.scssファイルにかくか、拡張子を変更する）
~~恐らくransackでカラムの指定のやり方もあると思うのですが・・・研究中~~

###参考ページ
http://nekorails.hatenablog.com/entry/2017/05/31/173925
Ransackで簡単に検索フォームを作る73のレシピ
プログラミング学習記録5〜Udemyに手を出す〜

##今日やったこと
- Progate Ruby4,5リセット復習
- Udemy「Web開発入門完全攻略コース - プログラミングをはじめて学び創れる人へ！未経験から現場で使える開発スキルを習得！」のセクション1から3の途中まで

Udemyの講座を受けてみることにしました。

実務未経験からITエンジニアに転職したい人やWebアプリを公開したい人向けの講座です。

若干Progateに飽きてきたので、一旦この講座でJavaScriptやBootstrapの復習もしつつ、Rubyやgitについて学んでいこうと思います。

まだちょっとしか進めてないですが、今のところ講師の中村祐太さんの声が聞きやすく、説明もわかりやすく、購入してよかったなと思います。

1.5倍速ぐらいで聞くとちょうどいい感じです。
倍速は動画の左下にある部分をいじると変えることができます

不満というかまだちょっとアレだな、、、と思ったのは動画の字幕です。

結構な割合で言ってることと若干違うことが字幕に書かれています。

僕は講師が話す日本語を聞くことができるので問題ないのですが、日本語がそんなに得意じゃない方が見ると混乱してしまうのではないかと思いました。

セクション１ではコース概要について
セクション２ではフロンドエンド開発概要について
セクション3ではHTMLについて

フロントエンド が何かということはなんとなく理解していたのですが、このセクションでより理解が深まりました。

講義中に出てくるフロントエンドとインターネットとバックエンドの関係を表した図がわかりやすかったです。

今まで学習したみた印象で言うと、、、

- フロントエンド→見た目を作る
- バックエンド→中身を作る（システムを作る）

という感じです。


そして、フロントエンドで用いる言語が

- HTML
- CSS
- JavaScript

という感じです。

バックエンドの言語はもっと色々あるみたいですね。

PHPやRuby、Pythonなども主に機能を作る言語です。

とまあ、まだこの程度の浅い知識しかないですが、徐々にフロントエンド、バックエンドの世界の理解を深めていきたいと思います。


明日からも引き続きプログラミングの勉強を頑張りたいと思います。

おわり
sshの設定が面倒だったのでschtasksからリモートプログラムを実行する。

# やりたかったこと
リモートサーバのプログラムを実行したい。
けどsshの初期設定面倒というか、windowsでのsshがよくわからなかったので・・・。

# 環境
リモート:WindowsServer 2008 R2(ワークグループ環境)

# server side
- 処理させたい命令文を書いたスクリプトを用意する。今回はpython
- タスクスケジューラに下記のように登録する

|項目|値|
|----:|----:|
|プログラム／スクリプト|python.exeのフルパス|
|引数の追加|.pyファイル名|
|開始|上記.pyファイルの格納フォルダ|

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/342467/7ed74b4c-bddd-47eb-c58c-ad44aa801b0e.png)

- Windowsファイアウォールの設定をする。「ｽｹｼﾞｭｰﾙされたリモートタスク管理」を「接続」に。






# client side

- コマンドプロンプトを管理者から実行する。
- schtasksを下記のように実行する。

```powershell:cmd
schtasks /run /tn mytaskname /s \\192.168.1.1 /u 192.168.1.1\administrator /p password
```
Vimium chromeにて

私はvim使いではないのだが、
少しでも手が早くなればいいなと、
Twitterでたまたま見つけたvimiumを入れてみた。

普段はchromeデフォルトのショートカットでなんとか、かんとか、やっているわけで、
開発者らしいこと一切やっていないのである。

それはさておき、ただの感想。

テキストボックスにフォーカスがあたってると、
単純にテキスト入力として扱われる。

simplenote
は特に仕事上手放せないのだが、
全面テキスト入力ばっちこいスタイルなので、
どうしても j k .....と打ってしまう

google calendar
などなどで使うと、便利なケースもある

けどなぁ

モード切替の仕方もあるみたいし
明日また探ってみるか
楕円曲線暗号のGPUによる解読プログラム

楕円暗号解読のGPU(GTX1080)プログラム(λ法)完成。
63ビット及び95ビットまでの暗号解読が可能。プログラムはCUDA。
60ビット暗号は平均1秒で、79ビット暗号(1997年解読)は
平均40分で解読。60ビット暗号は800倍、79ビット暗号は400倍
、それぞれPC(4Ghz,多倍長はgmp)より高速に解ける。
ASP.NET Core2.1 Identityのログイン画面をカスタマイズ

# ページを上書きする
ASP.NET Core Identityには、ログイン画面もライブラリ内に保持されており、デフォルトのまま利用するのであれば、ライブラリを取得するだけで利用することが可能です。
もし、デザインを変更したい場合には、Areas/Identity/Pages/Account/Login.cshtmlファイルを追加すれば、そちらが利用されるようになります。

```csharp:Login.cshtml
@page
@model Identity.ExternalClaims.Pages.Account.LoginModel
@{ ViewData["Title"] = "LoginTest"; }

<div class="row">
    <div class="col-md-4">
        <section>
            <form name="loginForm" method="post">
                <div asp-validation-summary="All" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="Input.Email"></label>
                    <input asp-for="Input.Email" class="form-control" id="inputEmail" />
                    <span asp-validation-for="Input.Email" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Input.Password"></label>
                    <input asp-for="Input.Password" class="form-control" id="inputPassword" />
                    <span asp-validation-for="Input.Password" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <div class="checkbox">
                        <label asp-for="Input.RememberMe">
                            <input asp-for="Input.RememberMe" />
                            @Html.DisplayNameFor(m => m.Input.RememberMe)
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-default" id="submitButton">Log in</button>
                </div>
            </form>
        </section>
    </div>
</div>
```

認証まわりのカスタマイズ方法を調べるのは、資料よりもマイクロソフトが提供しているサンプルコードをあたった方が理解が早いです。

# 追記
スキャフォールディングというコマンドラインのツールを使うと簡単に、必要なコードを生成してくれます。
カスタマイズしたいページのコードは、ツールを使って生成しましょう。

```
> dotnet aspnet-codegenerator identity -dc Vue2Spa.Data.ApplicationDbContext --files "Account.Register;Account.Login"
```
Excel からのコピペで Markdown Table を作る

# Excel からのコピペ = タブ区切り文字列

要はタブ区切りの複数行ある文字列を、
**Markdown Table**に変換したいというお話です。

**正規表現**でやってもいいですが、
エディタが限られるのでWebサービスが理想です。

## 実はツールが色々あります。

[**Markdown Tables Generator**](http://www.tablesgenerator.com/markdown_tables)
HTMLテーブルにも出せるので高機能。
ただ、高機能故に3クリックくらい必要です。

[**CopyToMarkdownAddIn**](http://www.nuits.jp/entry/2016/10/20/144241)
**.NET Framework 4.5.2**を使用されているようなので、
おそらくWindows限定ですが、
**Markdown Table**を**Excel**にコピペする操作も行えるのが素晴らしいです。

[**Copy Table in Excel and Paste as a Markdown Table**](https://thisdavej.com/copy-table-in-excel-and-paste-as-a-markdown-table/)
コピペした瞬間にもう変換済みの**Markdown Table**が表示されてるシンプルさがいいですね。

[**Excel to Markdown table**](https://marketplace.visualstudio.com/items?itemName=csholmq.excel-to-markdown-table)
こちらは**Visual Studio Code**の**Extension**ですが、
私の環境では実行すると `command 'extension.excelToMarkdown' not found` となって実行できずでした。
インストールは完了しているのになー。。。

## 簡単そうだったので自前で作ってみました。

[**Convert tab delimited string to MarkDown table**](https://codepen.io/yuu510/full/VXQbqG)
結構簡単でした。
**CodePen**で実装したので、
お好みで**Fork**してカスタマイズしちゃってください。

### Code

必要な部分だけ抜き出しで書いてます。

#### HTML(pug)

```:pug
    textarea#request
    span ↓
    textarea#response
```

#### CSS(sass)

別になんでもいいので割愛

#### JavaScript(Babel)

```javascript:javascript
$(document).ready(()=>{
  const INPUT = $('#request');
  const TARGET = $('#response');
  INPUT.on('keydown', (e)=>{
    let el, current, end, start, val;
    if (e.keyCode === 9) {
      if (e.preventDefault) {
        e.preventDefault();
      }
      el = e.target;
      current = el.selectionStart;
      start   = el.value.substr( 0, current );
      end     = el.value.substr( current, el.value.length );
      el.value = start + "\t" + end;
      el.selectionEnd = current + 1;
      return false;
    }
  });
  INPUT.on('keyup', (e)=>{
    TARGET.val('');
    let str = INPUT.val();
    const FIRST = str.split(/[\r\n]+/)[0];
    const COUNT = FIRST.split(/\t/).length - 1;
    let arr = [];
    if(str.length > 0){
      str = str.replace(/\t/g, ' | ');
      str = str.replace(/([\r\n]+)/g, ' |$1');
      str = str.replace(/(^)/gm, '| $1');
      str = str + ' |';
      arr = str.split(/[\r\n]+/g);
      for(let [i,v] of arr.entries()){
        if(i === 0){
          str = v + "\n";
        } else if(i === 1){
          str = str + generateHeader(COUNT) + v + "\n";
        } else {
          str = str + v + "\n";
        }
      }
    }
    TARGET.val(str);
  });
  const generateHeader = (cnt) => {
    let str = '';
    str = str + '| ---';
    for(let i=0; i<cnt; i++){
      str = str + ' | ---';
    }
    str = str + ' |\n';
    return str;
  }
});
```

結構な雑コードですみません（＞人＜）
Swift：CGPoint・CGSize用の演算子定義&Extension

# CGPoint編
CGPoint（NSPointでも可）の演算を円滑にするための便利な演算子と拡張の定義

```swift
//オリジナルの演算子ではないためinfix operatorはいらない

func + (left: CGPoint, right: CGPoint) -> CGPoint {
    return CGPoint(x: left.x + right.x, y: left.y + right.y)
}

func += (left: inout CGPoint, right: CGPoint) {
    left = left + right
}

func - (left: CGPoint, right: CGPoint) -> CGPoint {
    return CGPoint(x: left.x - right.x, y: left.y - right.y)
}

func -= (left: inout CGPoint, right: CGPoint) {
    left = left - right
}

func * (left: CGFloat, right: CGPoint) -> CGPoint {
    return CGPoint(x: left * right.x, y: left * right.y)
}

func * (left: CGPoint, right: CGFloat) -> CGPoint {
    return CGPoint(x: right * left.x, y: right * left.y)
}

func *= (left: inout CGPoint, right: CGFloat) {
    left = left * right
}

func / (left: CGPoint, right: CGFloat) -> CGPoint {
    assert(right != 0, "divide by zero")
    return CGPoint(x: left.x / right, y: left.y / right)
}

func /= (left: inout CGPoint, right: CGFloat) {
    assert(right != 0, "divide by zero")
    left = left / right
}

extension CGPoint {
    // xとyが同じ時の初期化
    init(_ scalar: CGFloat) {
        self.init(x: scalar, y: scalar)
    }
    // 二点間の距離を返す
    func length(from: CGPoint) -> CGFloat {
        return sqrt(pow(self.x - from.x, 2.0) + pow(self.y - from.y, 2.0))
    }
    // 二点を結んだ線分の角度（ラジアン）を返す
    func radian(from: CGPoint) -> CGFloat {
        return atan2(self.y - from.y, self.x - from.x)
    }
    // 二点を結んだ線分の角度（度）を返す    
    func degree(from: CGPoint) -> CGFloat {
        return atan2(self.y - from.y, self.x - from.x) * 180 / CGFloat.pi
    }
}
```
演算子の評価順序は基本的なものと変わらない．

取得できる角度はx軸を基準にした反時計回り(macOSの場合y軸が上向きなのでそれにあわせた）
![degree.png](https://qiita-image-store.s3.amazonaws.com/0/67153/d2848f04-a43d-d58e-354d-2c832c36a90a.png)

#CGSize編
CGSize（NSSizeでも可）の演算を円滑にするための便利な演算子と拡張の定義

```swift
func + (left: CGSize, right: CGSize) -> CGSize {
    return CGSize(width: left.width + right.width, height: left.height + right.height)
}

func += (left: inout CGSize, right: CGSize) {
    left = left + right
}

func - (left: CGSize, right: CGSize) -> CGSize {
    return CGSize(width: left.width - right.width, height: left.height - right.height)
}

func -= (left: inout CGSize, right: CGSize) {
    left = left - right
}

func * (left: CGFloat, right: CGSize) -> CGSize {
    return CGSize(width: left * right.width, height: left * right.height)
}

func * (left: CGSize, right: CGFloat) -> CGSize {
    return CGSize(width: right * left.width, height: right * left.height)
}

func *= (left: inout CGSize, right: CGFloat) {
    left = left * right
}

func / (left: CGSize, right: CGFloat) -> CGSize {
    assert(right != 0, "divide by zero")
    return CGSize(width: left.width / right, height: left.height / right)
}

func /= (left: inout CGSize, right: CGFloat) {
    assert(right != 0, "divide by zero")
    left = left / right
}

extension CGSize {
    // widthとheightの大きさが同じ時の初期化
    init(_ side: CGFloat) {
        self.init(width: side, height: side)
    }
}
```

だいたいは`CGPoint`と同じ

## 蛇足
`NSPoint`，`NSSize`，`NSRect`はそれぞれ`CGPoint`，`CGSize`，`CGRect`のエイリアス．
Herokuってなんなの？

#### 使ったことはあるものの、よく知らなかったので調べてみました
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322577/49e17d16-b5ab-490a-56b7-ee6f4a32d9bd.png)
# Herokuとは？
##### 開発したWEBアプリケーションを10分程度で全世界に公開することができ、そのままサービスを本格的に運用することも可能なホスティングサービス

- Python/Java/Go/PHP/Node.JS/Ruby on Railsに対応可能
- salesforceが買収したサービス


## ホスティングサービスとは？

![fukidasi.png](https://qiita-image-store.s3.amazonaws.com/0/322577/5cdcf347-7c8b-e935-f261-c7ee9d02382e.png)

レンタルサーバ、共有サーバのこと
その中でSaaS、PaaS、IaaS、DaaSと呼ばれるものがあり、違いはどこまでクラウドとして用意してくれているか
##### SaaS→PaaS→IaaSの順でシンプル⇄自由度が高い

## SaaS
Software as a Serviceの略
利用者はインターネット上で利用するだけでいい
##### メリット：サービスが整っているので手間なく使える
無料ブログサービスなどがこれに当たる

## PaaS
Platform as a Serviceの略
##### Herokuはこの中のひとつ

・ネットワークなどのインフラ
・OSなどのプラットフォーム

2つがすでに整った状態で利用できるのでアプリケーションの構築に集中できる
##### メリット：Ruby on Rails、Django、Spring、Node.jsなどで制約なくアプリを作成ができる
コンシューマ向けの凝ったアプリを作るのに向いている

## IaaS
Infrastructure as a Serviceの略
##### AWSのEC2はこの中のひとつ
仮想サーバ、ハードディスク、ファイアーウォールを用意
サーバのスペックやOS等を選択することが出来る

##### メリット：自由に開発できる

Xサーバーなどのレンタルサーバー
無料CMSのWordPressを利用するために使われることもある

##### VPSとの違い
IaaS：料金は使った分だけ　多機能で色々凝りたいならこっち
VPS：料金は一定　機能がシンプルなので扱いやすい

## DaaS
Desktop as a Serviceの略
クラウド上にデスクトップ環境を作って利用する
##### メリット：デスクトップ環境が低コストで簡単に利用できる
##### デメリット：アプリとの互換性がなかったり、大容量データの転送が遅い

#数あるPaaSの中のHerokuの特徴

#### デプロイが簡単
- gitのリモートリポジトリに追加してgit pushするだけでデプロイできる

#### アドオン追加
- 現在約150種あるアドオン（いろんな会社から提供されているHerokuで使える追加機能）をコマンドで簡単に追加出来る

https://jp.heroku.com/elements/addons

###### アドオンの代表的なもの
- DBのPostgres
- メール配信サービスのSendGridなど

## 利用時の注意
　一番安い$5のプランならdyno 1,000時間/月利用可能
- 必要な RAM は 1 dyno あたり 512 MB

#### 512MBを超えるとスワップが発生しR14エラーに
スワップとは・・
ハードディスクなど補助記憶装置を利用して使用可能なメモリ容量を増やすOSの機能のこと


#### 一時的に立ち上がっているDynoの利用時間も換算される
Dynoがクラッシュしてもアプリに影響が出ないようにしている
→Dynoに直接コマンドを実行しても直接アクセスせずに、一時的に別のDynoを立ち上げてそこにアクセスしているので
そのサーバ利用時間もカウントされている

#### ~~30分アクセスがないとスリープしてしまう~~
~~次にアクセスがあったときに Dyno を起動するのでレスポンスが遅くなる（アプリケーションの内容によっては30秒待たさせることも）~~
##### ~~UptimeRobot（無料のネットワーク監視サービス）を使い5分ごとにアクセスすることでスリープを回避出来る~~
~~https://uptimerobot.com/~~
↑全てのプランが有料化されたかわりに解消
ASP.NET Core2.1 Identityのユーザー登録機能を潰す

# 概要
VisualStudioのASP.NET Core2.1 Identityテンプレートを極力流用しつつサービスを作成したとします。
テンプレートには、Register(ユーザー登録)のサンプルも付属しておりDBの中に、どのような情報が登録されるのか確認することができます。
しかし、インターネットに公開されているページで、自由にアカウント登録させるのは、困るサービスもあると思います。
本記事は、アカウントの新規登録を制限する方法についての記事です。
私が独自に見つけた方法なので、もっとスマートな方法があるかも知れません。
コメントで、ご指摘頂けますと助かります。

# ASP.NET Core Identityとは
ASP.NET Core Identityは、読んで字のごとく、ASP.NET Coreで、ユーザーのアカウント情報を管理するライブラリです。
かなり多機能なライブラリで、使いこなす事ができれば、世の中のたいていのパターンの認証方法は実現できそうです。
ただ、ASP.NET Core自体が、未成熟なためかバージョンによって、記述方法が変わります。
私は、2.1が、LTSなこともあって、2.2へは移行していません。

# ヘッダーのリンクを削除する
テンプレートを見て、まず思いついたのは、_LoginPartial.cshtmlのリンクを削除することです。

```csharp:_LoginPartial.cshtml
@using Microsoft.AspNetCore.Identity

@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

@if (SignInManager.IsSignedIn(User))
{
    <form asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })" method="post" id="logoutForm" class="navbar-right">
        <ul class="nav navbar-nav navbar-right">
            <li>
                <a asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
            </li>
            <li>
                <button type="submit" class="btn btn-link navbar-btn navbar-link">Logout</button>
            </li>
        </ul>
    </form>
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li><a asp-area="Identity" asp-page="/Account/Register">Register</a></li>
        <li><a asp-area="Identity" asp-page="/Account/Login">Login</a></li>
    </ul>
}
```

ログイン中かを判断して、RegisterとLoginへのページリンクが、表示される仕組みになっています。
リンクを削除すれば、とりあえずアカウント登録画面を表示することは、できなくはなります。
しかし、リンクのURLを知っていたらどうでしょうか？
https://localhost:44326/Identity/Account/Register
リンクを直接入力すれば、いとも簡単に、アカウント登録画面は表示されてしまいます。

# ページを上書きする
ソリューションに、Areas/Identity/Pagesというフォルダがあると思います。
フォルダの中に、Accountというフォルダを作成して、Register.cshtmlというページを作成します。

```csharp:Register.cshtml
@page
@model UserRegist.Areas.Identity.Pages.Account.RegisterModel
@{
}
```
```csharp:Register.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace UserRegist.Areas.Identity.Pages.Account
{
    public class RegisterModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}
```

ページの中身は、空っぽです。
この意味のないページを作成しておくことで、直リンクで開かれてもアカウント作成機能を無効化することができます。
今回は、機能の無効化目的で、ページを作成しましたが、アカウント登録画面のカスタマイズ目的で、利用することも可能です。

# スキャフォールディングを使ってコードを生成
この記事を書いたときには、サンプルコードとソースコードを見て、上書きするページを作成したのですが、スキャフォールディングという機能を使えば、コードを自動生成してくれる事が分かったので、追記します。
ASP.NET Core scaffolderをインストールします。

```
> dotnet tool install -g dotnet-aspnet-codegenerator
```
ログインページを生成します。
コマンドラインは、スタートアッププロジェクトのカレントディレクトリで実行してください。
エラーで止まる場合には、binとobjフォルダを削除してから実行すると動くこともあるようです。

```
> dotnet aspnet-codegenerator identity -dc Vue2Spa.Data.ApplicationDbContext --files "Account.Register"
```
生成されたコード(ページ)を編集すれば、登録画面をカスタマイズすることができます。
Ruby 学習　基本　（クラス）

#はじめに
  Rubyの学習を始めました。学んだことを忘れないように備忘録として残しています。


##クラス
   プログラミンで「もの」を生成するには、まずその「設計図」を用意する必要がある。
 　 設計図のことをクラス
 「 もの」のことをインスタンスを呼ぶ。

 　インスタンス生成手順
 　　1　クラスを用意する
 　　2　クラスからインスタンスを生成する。
 　　3　インスタンスに情報を追加する

  1　クラスの定義

```ruby

  Class Menu　　         #クラス名は大文字で始める
    attr_accessor :name  # nameをインスタンス変数と呼ぶ
    attr_accessor :price
  end

```

  2　インスタンスの生成 クラス名.new

```ruby

  menu1 = Menu.new # Menuクラスからインスタンスを生成
                   # 変数menu1に代入

```

  3　インスタンスに情報を追加

```ruby

  menu1.name = "Sushi"  # 値を代入
  puts menu1.name  # sushi  

```    

## クラスの中でメソッドを定義し呼び出す（インスタンスメソッド）

```ruby

Class Menu　　
  attr_accessor :name
  attr_accessor :price

  def show　#　クラスの中でメソッドを定義
   puts "This is a menu!"
  end
end
  menu1 = Menu.new
  menu1.show  #  クラスの中で定義したメソッドを呼び出す
```

## インスタンスメソッドの中でインスタンス変数を扱う
　　インスタンスメソッドの中では特殊な変数「self」を用いて
　　「self.変数名」とすることでインスタンス変数を扱うことができる。

```ruby

Class Menu　　
  attr_accessor :name
  attr_accessor :price

  def show_name
   puts "This is #{self.name}!"
  end
end
  menu1 = Menu.new
  menu1.name = "sushi"
  menu1.show_name   #　This is sushi!

```
ECSでサービスのスケジューリングを行う方法

# 概要
ある特定の時間のみに利用するwebアプリを、出来るだけ低コストで提供したいという背景があり、ECS(Fargate) + Aurora Serverless で構築していた。

Aurora Serverless は、アクセスがなくなると自動で停止されるが、ECSでも同様のことがやりたかったので考えてみた。

# 前提
ECS のタスク実行には二種類ある。

- タスクのスケジューリング
- サービス


タスクのスケジューリングでは、タスク（アプリ）のみが管理される。
サービスでは、LBやtarget groupの設定も管理される。

# 方法
今回の対象アプリは、バッチアプリではなくwebアプリであり、target groupへの追加部分なども要件に含まれている。
そのため、タスクのスケジューリングは利用できず、自前でlambdaを作ることにした。

serverless frameworkを利用して、lambda + CloudWatch Eventsの構成。


### handler.js

タスク数`desiredCount`を変更し、起動/停止を行う。

```js
const AWS = require('aws-sdk');
const ecs = new AWS.ECS({apiVersion:'2014-11-13',region:'us-east-1'});

module.exports.start = (event, context) => {
  const params = {
      cluster: "CLUSTER_NAME",
      desiredCount: 1,
      service: 'SERVICE_NAME'
  };
  
  ecs.updateService(params, (err, data) => {
     if (err) console.log(err);
     else console.log(data);
  });
};

module.exports.stop = (event, context) => {
  const params = {
      cluster: "CLUSTER_NAME",
      desiredCount: 0,
      service: 'SERVICE_NAME'
  };
  
  ecs.updateService(params, (err, data) => {
     if (err) console.log(err);
     else console.log(data);
  });
};
```

### serverless.yml
月曜から金曜の午前9 - 10時のみ稼働させるCloudWatch Eventsの設定

```yml 
...

functions:
  startEcsService:
    handler: handler.start
    events:
    	- schedule: cron(0 0 ? * MON-FRI *)
  stopEcsService:
    handler: handler.stop
    events:
    	- schedule: cron(0 1 ? * MON-FRI *)

...
```

# まとめ
LBの設定（target groupへの登録）なども行う場合は、タスクスケジューリングは要件にあわなさそう。
lambdaからAWS SDKで、ECSの操作ができるのでそれを活用した。
TCP で送受信


## ソケット送受信クラス

System.Net.Sockets.TcpClient クラスをラップして扱いやすいように TcpCommunicator クラスを作成

```C#
public class TcpCommunicator : IDisposable
{
	public TcpCommunicator(TcpClient tcpClient)
	{
		if (tcpClient == null) throw new ArgumentNullException(nameof(tcpClient));
		this.TcpClient = tcpClient;
		this.Name = $"[{this.Socket.RemoteEndPoint}]";
	}

	public TcpCommunicator(string host, int port) : this(new TcpClient(host, port)) { }

	private TcpClient TcpClient { get; }

	protected Socket Socket => this.TcpClient?.Client;

	public string Name { get; }

	public bool IsConnecting
	{
		get
		{
			try
			{
				if ((this.TcpClient == null) || !this.TcpClient.Connected) return false;
				if (this.Socket == null) return false;
				return !(this.Socket.Poll(1, SelectMode.SelectRead) && (this.Socket.Available <= 0));
			}
			catch
			{
				return false; // 強制で切断した場合に Socket が null になるため、例外を無視
			}
		}
	}

	public void Dispose()
	{
		if (this.TcpClient != null)
		{
			this.TcpClient.Close();
			(this.TcpClient as IDisposable).Dispose();
		}
	}

	static string ToHexString(byte[] data)
	{
		if (data == null) throw new ArgumentNullException(nameof(data));
		var sb = new StringBuilder(data.Length * 2);
		foreach (var item in data) sb.Append($"{item:X2}");
		return sb.ToString();
	}

	public void Send(byte[] data)
	{
		if (data == null) throw new ArgumentNullException(nameof(data));
		if (!this.IsConnecting) throw new InvalidOperationException();
		try
		{
			Console.WriteLine($"{this.Name} << " + ToHexString(data));
			var stream = this.TcpClient.GetStream();
			stream.Write(data, 0, data.Length);
		}
		catch (Exception ex)
		{
			throw new ApplicationException("Attempt to send failed.", ex);
		}
	}

	public byte[] Receive()
	{
		if (!this.IsConnecting) throw new InvalidOperationException();
		try
		{
			using (var memory = new MemoryStream())
			{
				var stream = this.TcpClient.GetStream();
				while (stream.DataAvailable)
				{
					var buffer = new byte[8192];
					var count = stream.Read(buffer, 0, buffer.Length);
					if (count > 0)
					{
						var data = new byte[count];
						Array.Copy(buffer, 0, data, 0, count);
						Console.WriteLine($"{this.Name} >> " + ToHexString(data));
						memory.Write(data, 0, data.Length);
					}
				}
				return memory.ToArray();
			}
		}
		catch (Exception ex)
		{
			throw new ApplicationException("Attempt to receive failed.", ex);
		}
	}
}
```
ASP.NET Core アプリケーションの開発時 IIS サポート

※ [Development time IIS support for ASP.NET Core Applications][] を和訳したものです。

---

最近の Visual Studio 2017 のアップデートにより、IIS に対して ASP.NET Core アプリケーションをデバッグするためのサポートが追加されました。
この記事では、この機能を有効にしてこの機能を使用するようにプロジェクトを設定する方法について説明します。

## 準備

- あなたはVisual Studio 2017（version 15.3）Preview をインストールする必要があります。(Visual Studio の以前のバージョンでは動作しません)
- [ASP.NET と Web 開発]、または [.NET Core クロスプラットフォームの開発] がインストールされている必要があります。

## IIS を有効にする
Visual Studio で [開発時の IIS サポート] を有効にする前に、IIS を有効にする必要があります。

1. [コントロールパネル] > [プログラムと機能]
2. [Windows の機能の有効化または無効化] を選択<img src="https://www.infraexpert.com/studygif/win7-iis02.gif" width="400">
3. [インターネットインフォメーションサービス] チェックボックスをオンにします。<img src="https://www.infraexpert.com/studygif/win7-iis03.gif" width="400">


IIS のインストールで再起動が必要な場合は、次の手順に進む前に必ず完了してください。

# 開発時のIISサポート
IIS をインストールしたら、Visual Studio インストーラを起動して既存の Visual Studio インストールを変更できます。
インストーラ で、[ASP.NET と Web 開発] ワークロードの下でオプションコンポーネントとしてリストされている
[開発時 IIS サポート] コンポーネントを選択します。
これにより、IIS 上で ASP.NET Core アプリケーションを実行するために必要なネイティブ IIS モジュールである ASP.NET Core Module がインストールされます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/111975/645174cb-72a9-bf18-bdb3-e5522345956e.jpeg" width="200">

# 既存プロジェクトへのサポートの追加
開発時の IIS サポートを追加するための新しい起動プロファイルを作成できます。
既存の ASP.NET Core アプリケーションの [プロジェクト] プロパティの [デバッグ] タブにある [起動]ドロップダウン から [IIS] を選択してください。

この時点で、プロジェクトはすべて開発時のIISサポート用に設定されています。
※管理者として実行されていない場合は、Visual Studio を再起動するように求められることがあります。

## 参考サイト
- [Development time IIS support for ASP.NET Core Applications][]
- [Windows 7 - IISをインストールしよう][]

[Development time IIS support for ASP.NET Core Applications]: <https://devblogs.microsoft.com/aspnet/development-time-iis-support-for-asp-net-core-applications/>
[Windows 7 - IISをインストールしよう]: <https://www.infraexpert.com/study/loadbalancer9.html>
monacaでnpmを使う

[Monaca](https://ja.monaca.io/)の試用版（書籍についていたクーポン券）を使って、アプリを作ってみました。
一通り使ってみて、スマホアプリを作るなら、とてもお手軽なIDEだなーと思います。
この手のIDEのなかで一番スッと使えました。学習コストって低ければ低いほどいいですよね。
高校や大学の先生が教材に使ってるのも頷けます。

しかし、npmからインストールできる様々なライブラリが（試用版だからなのか）権限がなくて-gオプションでインストールできなかったので、その場合どうするのかシェアします。

# package.jsonの中身
プロジェクトのトップレベルには、`package.json`というファイルがあります。
そのファイルには、"scripts"という項目があります。

```json:package.json
{
    "name": "monaca-template-minimum",
    "displayName": "Monaca Template Minimum",
    "dependencies": {
        "@mapbox/polyline": "^1.0.0",
        "browserify": "^16.2.3",
        "cordova-custom-config": "5.0.2",
        "cordova-plugin-dialogs": "2.0.1",
        "cordova-plugin-splashscreen": "5.0.1",
        "cordova-plugin-vibration": "2.1.6",
        "cordova-plugin-whitelist": "1.3.3",
        "gtfs-realtime-bindings": "0.0.4",
        "monaca-lib": "^3.1.0",
        "monaca-plugin-backend": "2.0.1",
        "monaca-plugin-monaca-core": "3.2.1",
        "pg": "^7.7.1",
        "request": "^2.88.0"
    },
    "scripts": {
        "monaca:preview": "npm run dev",
        "dev": "browser-sync start -s www/ --watch --port 8080 --ui-port 8081",
        "build1": "browserify www/js/getVehicle.js > www/js/vehicle.js",
        "build2": "browserify www/js/git-polyline.js > www/js/polyline.js",
        "build3": "browserify www/js/getRouteInfo.js > www/js/route.js",
        "build4": "browserify www/js/getAlert.js > www/js/alert.js"
    },
    "cordova": {
        "plugins": {
            "cordova-plugin-whitelist": {},
            "cordova-plugin-splashscreen": {},
            "cordova-custom-config": {},
            "monaca-plugin-monaca-core": {},
            "cordova-plugin-dialogs": {},
            "cordova-plugin-vibration": {},
            "monaca-plugin-backend": {}
        }
    },
    "devDependencies": {
        "browser-sync": "^2.26.3",
        "cordova": "^7.1.0"
    }
}
```

"scripts"にはbuild1などのコマンドが入っています。
build1など、エイリアスを作り、対応するコマンドを登録します。

```shell
"build1": "browserify www/js/getVehicle.js > www/js/vehicle.js"
```

# Terminalを起動
monacaのブラウザ版IDE画面には、Preview Log、Debuggerタブの他に、Terminalというタブがあります。

```shell
Welcome to Monaca Terminal Console!
/project $ npm run build1
```

通常、

```shell
npm install -g browserify
browserify www/js/getVehicle.js -o www/js/vehicle.js
```
などとダイレクトにコマンドを使うところで
`npm run {上記コマンド} `を使うと、グローバルにコマンドをインストールしたり実行する権限なくても動きます。
おためしgdb

基本的に自分用のメモですが、これからgdbを触ってみようと思っている方も参考になるかと思います。

## gdbとは
C言語やC++等のプログラムをLinux上でデバッグするデバッガです


## 準備
デバッグ対象のソースを`-g3`オプションを付けてビルドする

- オプションを付けずともgdbは使用可能ですが、付けないとデバッグ情報がほとんどないので付けるのをオススメします

## 使い方
以下のように準備した実行ファイルをgdbに読み込ませます。
今回は例として実行ファイル名は`a.out`としています。

```
$ gdb a.out
```

## コマンド

### run [引数]
- gdbで読み込んだプログラムを実行します
- 省略形は`r`

```
(gdb) r
```

### quit [引数]
- gdbを終了します
- 省略形は`q`

```
(gdb) q
```

### break ファイル名:行数
- 指定のファイル/行にブレイクポイントを設定します
- 省略形は`b`

``` 
(gdb) b hoge.cpp:10
```

### next
- ステップ実行をします(関数の中には入りません)
- 省略形は`n`

``` 
(gdb) n
```

### step
- ステップ実行をします(関数の中に入ります)
- 省略形は`s`

``` 
(gdb) s
```

### continue
- ブレイクポイントなどで停止したプログラムを次のブレイクポイントまで再開します
- 省略形は`c`

``` 
(gdb) b hoge.cpp:10
```

### print
- 変数や式などを評価し表示します
- 省略形は`p`

``` 
(gdb) p hoge
```

### backtrace
- 直前までの関数呼び出しの履歴を表示します
- 省略形は`bt`

```
(gdb) bt
```
Laravel標準に認証にusers以外のテーブルを使う

Laravelで利用者サイトと管理者(複数)サイトを作って同一のデータベースを共有したい場合などに
片方(管理者)用の認証用のテーブルをusers以外にしたい場合などの話

##構成
サブドメインなどでドキュメントルートを切り分けてそれぞれ別のプロジェクトを作り同一DBを参照する
今回管理者認証用のテーブル名はmanagersとする

##手順

###認証機構を生成

```terminal
$ php artisan make:auth
```

###テーブルの生成
デフォルト配備されているでcreate_users_tableからcreate_managers_tableを作りテーブル名部分を書き換える

```diff:database/migrations/XXXX_XX_XX_XXXXXX_create_managers_table.php
-class CreateUsersTable extends Migration
+class CreateManagersTable extends Migration
{
    public function up()
    {
-        Schema::create('users', function (Blueprint $table) {
+        Schema::create('managers', function (Blueprint $table) {
            …
        });
    }

    public function down()
    {
-        Schema::dropIfExists('users');
+        Schema::dropIfExists('managers');
    }
}

```
###マイグレート
基本的に同盟のマイグレーションファイルは読み込まれないのでそのまま実行してもよいがDB周りは片方のプロジェクトで一括管理した方がいいかもしれない

```terminal
$ php artisan migrate
```

User.phpがvendor内のライブラリで呼ばれているようなのでこのファイルはそのまま流用した方がよさそう

```diff:app/User.php
    use Notifiable;
    // これで参照先のテーブルを変更
+    protected $table = 'managers';

    protected $fillable = [
        'name', 'email', 'password',
    ];
```

登録時にユニークチェックする対象がusersになっているので
app/Http/Controllers/Auth/RegisterController.phpも変更

```diff:app/Http/Controllers/Auth/RegisterController.php
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
-            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
+            'email' => ['required', 'string', 'email', 'max:255', 'unique:managers'],
            'password' => ['required', 'string', 'min:6', 'confirmed'],
        ]);
    }
```

あとホーム画面やトップ画面からRegisterメニューの削除などは任意に
scpコマンド久しぶりに使ってハマった

#Permission deniedが出る
プロダクトをサーバーにscpコマンドで移動させようとしてたら、何度やってもPermission deniedが出る。

```
scp: /product/name: Permission denied
```

権限周りねと、いつものようにchmodとかchownとか試してみても、エラーが変わることなくPermission denied。

# 解決
送信先のパス指定が悪かった。

```
scp -i hogehoge.pem ../product_name ec2-user@**.***.***.***:/
```
上記のものを、下記のようにしてあげるとうまくいった

```
$ scp -i hogehoge.pem ../product_name ec2-user@**.***.***.***:~/
```

#まとめ
なんか以前にも.zshrcをgit管理するためにシンボリックリンクを貼る時もこの~で解決したことがある。

```
$ ln -s ~/set_zsh/.zshrc .zshrc
```
これを私は厳密指定と勝手に呼んでいますが、絶対パスなら大丈夫と思っていて、~を抜いて書いていたことが原因です。ホームディレクトリを参照させるのには~が必要であると言うことらしい。ここはもう少し言語化したいです。

それにしてもPermission deniedとは・・・エラー内容と原因が食い違ってて時間食ってしまった。食い違ってただけに！食い違ってただけに！
Elasticsearch サービス比較表

|サービス|過去1年のダウンタイム|費用|その他|
|:---|:---|:---|:---|:---|
|[Searchly](http://www.searchly.com/)|[0.044%(thorin-us-east-1)](http://status.searchly.com/)|[9ドル/月〜799ドル/月](http://www.searchly.com/#pricing)  |Heroku に秒で導入できる|
|[Amazon Elasticsearch Service](https://aws.amazon.com/jp/elasticsearch-service/)|[0%](https://status.aws.amazon.com/)|[0.028ドル/時〜(およそ20ドル/月〜)](https://aws.amazon.com/jp/elasticsearch-service/pricing/?nc=sn&loc=3)。使用量(計算量)によって料金が変わる。|素の Elasticsearch を運用することになりそう|
|[Elastic Cloud](https://www.elastic.co/cloud)|[不明](https://cloud-status.elastic.co/)|[Storage 2GB, Tokyo リージョンで16.64ドル/月〜](https://cloud.elastic.co/pricing)|Elasticの公式サービス|
|[Bonsai](https://bonsai.io/)|[0%(tokyoリージョン)](https://status.bonsai.io/uptime/sbf0nq2703tm)|[0ドル/月から2,500ドル/月](https://bonsai.io/pricing)。Heroku用のプランも[ある](https://elements.heroku.com/addons/bonsai)|Heroku に秒で導入できる|

## 参考サイト

- [Bonsai vs Searchly - Slant](https://www.slant.co/versus/567/568/~bonsai_vs_searchly)
- [Searchly vs Elastic Cloud - Slant](https://www.slant.co/versus/569/568/~elastic-cloud_vs_searchly)
- [ElasticSearchのSaaSサービス比較 - Data Scientistになりたかったアプリエンジニアのブログ](http://tsubasa2307.hatenablog.com/entry/2017/12/03/155417)
- [AWSで怯えず作るEC2 + Amazon Elasticsearch Serviceでハマったところ - リブの開発者のブログ ](https://tech.libinc.co.jp/entry/2018/11/02/100751)

## 所感

- ダウンタイム 0.04%(3時間/年, 15分/月)を考えるとクリティカルな業務でなければ Searchly で十分かな
- ちょっと高くなるけど Bonsai 入れるのもよさそう
- 今後 Elasticsearch の運用のノウハウを貯めることを考えているのであれば、AWS や Elastic Cloud。
    - ちょっとした検索で使うだけならメンテコストの方が高くなるかも。
SourceTreeで変更にpackage-lock.jsonが入っているとすごく重いのでDiffを無視する

[SourceTree](https://ja.atlassian.com/software/sourcetree)すごく良いですね。
コマンドラインのGitも必要ですが、GUI操作すごく良いです。

JS系の開発をしているとnpmを利用することが多いです。
npmを利用して開発していると`package-lock.json`が変更に入ります。
このファイルにはパッケージのバージョン情報などが入っているためすごく重いです。

<img width="861" alt="Screen Shot 2019-02-21 at 16.41.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/b255c4df-6e1d-4c58-1153-95813165f05e.png">

これを回避します。

`Preferences > Diff`を開きます。
<img width="684" alt="Screen Shot 2019-02-21 at 16.40.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/fce0b0cb-c9ee-0bef-55d3-af31c2bdaf00.png">


`Ignore pattern list`に`package-lock.json`を記述します。

これでSourceTreeで`package-lock.json`を選択しても重くないです。

<img width="1194" alt="Screen Shot 2019-02-21 at 16.41.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/b0e67953-37d3-7693-90df-352bbf96b594.png">


よいGitライフを！
VSCode の JSON 形式での設定画面の左側にデフォルト設定を表示させるのを復活させる

version 1.13 以降、設定画面を開くと自分が過去に書いたjsonの設定ファイルが開くだけになってしまって困った。
今までは左にデフォルト設定、右にその自分のファイルが表示されて、
どのような設定項目があるのか、デフォルトでは何に設定されているのか確認できていたが無くなってしまった。
GUI の設定画面を使えということだろうか。
困っていたら、issueがあった

https://github.com/Microsoft/vscode/issues/68119

というわけで、

## デフォルト設定と自分の設定を並べて表示する

```
workbench.settings.useSplitJSON: true
```

を追加すると、デフォルト設定と自身の設定が並ぶ従来の表示に戻った。

GUI設定画面からでも `ワークベンチ > 設定エディター` の `Workbench > Setting: Use Split JSON` にチェックすると、同じ設定ができる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/100313/3e586864-ca32-347b-2291-6776d18eb172.png)

## 設定を開いたときにJSON形式の設定画面が開くようにする

また、別件ではあるが、設定を開いたときにGUIではなくJSONが開くようにするには、

```
"workbench.settings.editor": "json"
```

を追加するか、GUI設定画面で、 `ワークベンチ > 設定エディター` にある `Workbench > Setting: Editor` を `json` にすれば良い。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/100313/b3579a51-2629-6972-60c9-a372c5f022ce.png)

## GUIの設定画面とJSONの設定画面をその場で切り替える

エディター右上のボタンで切り替えられます

<img width="157" alt="スクリーンショット 2019-02-21 16.37.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/100313/60fd6f07-58a0-ed60-8918-a7753d779710.png">
<img width="115" alt="スクリーンショット 2019-02-21 16.39.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/100313/9e8ae53f-a3e9-b55e-af8b-e7c2888e8575.png">
PHPで対象となる文章（文字列）の偶数番目の「。」だけを置換する方法

PHPで指定した文章の偶数番目の「。」だけを置換する方法はあるでしょうか。
全ての「。」を置換するのはstr_replaceなどで可能ですが、2つに1つのスパンで改行コードを入れたく、そのような指定方法があればご教示いただけると幸いです。
どうぞよろしくお願いいたします。

置換前）
親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。

置換後）
親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。
なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。
brew caskでのエラー

# brew caskでのエラー

macの環境下で，tex環境を削除しようと以下のコマンドを走らせたら...

```terminal
$ brew cask list | grep basictex
Warning: Unexpected method 'gpg' called on Cask torbrowser.
Follow the instructions here:
  https://github.com/Homebrew/homebrew-cask#reporting-bugs
```

torbrowserのｇｐｇが悪さしてるらしい...
でも最近，torbrowser更新した記憶もない...

なにやともあれ，ちょこちょこ検索して..


```terminal
$ rm -rf "$(brew --prefix)/Caskroom/torbrowser" && brew cask install tor-browser
```

これで完了．

原因調査は後日します．

## 参考
- [https://github.com/Homebrew/homebrew-cask#reporting-bugs](https://github.com/Homebrew/homebrew-cask#reporting-bugs)
- [https://github.com/Homebrew/homebrew-cask/issues/58567](https://github.com/Homebrew/homebrew-cask/issues/58567)
SikuliX 1.1.4 日本語PATH入りエクセルファイルを開く

##Excelを開く際に日本語PATHが入ったxlsxを指定したい

###2019/2月時点の失敗例
```python:当初の目論見
excel_path = r"バージョンによって異なる\EXCEL.EXE"
file_path = r"c:\集計\本日の集計.xlsx"
proc = App(path +" "+ excel_path)
proc.open()
#RPA処理
proc.close()
```

いけると信じていた。
エラーにはならず、
sikulix.jarがあるフォルダをExplorerで開く
という挙動が行われる。

###成功例
```python:打開策_サブプロセスを使う
import subprocess
excel_path = r"バージョンによって異なる\EXCEL.EXE"
file_path = r"c:\集計\本日の集計.xlsx"
proc = subprocess.Popen([excel_path , file_path])
#RPA処理
proc.terminate()
```
致し方なくサブプロセスを使用することにした。

一応日本語をあきらめればいけることは確認した

```python:補足_英語のみ
excel_path = r"c:program\EXCEL.EXE"
file_path = r"c:\aggregate\today.xlsx"
proc = App(path +" "+ excel_path)
proc.open()
#RPA処理
proc.close()
```

日本語使えないのはRDP的には負けかなと思うのでサブプロセスで行くことにした。
問題が出たらまた考える
jQueryでワイプ切り替えのスライダーを実装する

※機能を追加してプラグイン化しました。[こちらの記事](https://qiita.com/Kackie/items/8ef48f9af1bf524dd9fe)へどうぞ。
下記の旧バージョンもシンプル版として一応残しておきます。

## サンプル
https://kackie.github.io/wipeSlider/test.html

## 使い方
ほぼサンプルのコピペでOKで、設定が必要なのはアニメーション時間、スライド表示時間のところくらいです。

## コードの解説
簡単なコードしか書いてないので、JS全部載せちゃいます。

```js
$(window).on('load', function(){
	var	slides = $('.js_wiper'),
		slide = slides.find('.slide'),
		slideW = slide.outerWidth(true),
		slideH = slide.outerHeight(true),
		length = slide.length - 1,
		transition = 1000, //アニメーション時間
		duration = 4000; //スライド表示時間
	slide.eq(0).addClass('active');
	
	//スライド用のクラス切り替え
	var num = 0;
	var wiper = function(){
		if(num < length){
			num++;
		} else {
			num = 0;
		}
		slide.removeClass('active');
		slide.eq(num).addClass('active').css({
			clip: 'rect(0px,'+ slideW +'px,'+ slideH +'px,0)',
			'z-index':'2'
		});
		setTimeout(function(){
			slide.filter('.active').css({
				'z-index':'1'
			});
			slide.not('.active').css({
				clip: 'rect(0,0,' + slideH +'px,0)',
				'z-index':''
			});
		},transition);
	};
	setInterval(wiper, duration);
	
	//スライドのアニメーション作成
	slide.css({
		width:slideW,
		height:slideH,
		transition:'clip ' + transition/1000 + 's'
	});
	slide.filter(':nth-child(n+2)').css({
		clip: 'rect(0,0,' + slideH +'px,0)',
	});
});
```

まず最初のvarでスライドのサイズと枚数を取得、表示時間とアニメーション時間の設定をします。
setIntervalの設定をします。スライド1枚目から順番にactiveクラスを付け替えるという動作を表示時間の間隔で行います。
activeクラス付きは他のスライドより手前に来るように、z-indexで調整します。

アニメーションはCSSのtransitionとclipで作りました。
最初に取得したスライドの幅、高さをもとに作ったマスクを操作し、ワイプ表示を再現しています。

## 注意点
- レスポンシブ、リキッド対応はしていないです。スライドのサイズの取得は一回きりだけ。
- CSSのtransitionを使っている関係で、変数のtransitionとdurationに同じ値は設定できません（わざわざしないと思うけど）。
- 画像ではなくスライド内にHTMLを書くこともできますが、各スライドに背景を指定or画像で覆う必要があるのと、全スライドのサイズを揃えておくのが前提です。<br>CSSでwidth,heightを指定しておくか、画像スライドならimgにwidth,height属性を指定しておいたほうがいいかも。<br>
サンプルでは画像読み込み後に動いてほしいので`$(window).on('load', function(){`としています。

## 感想
プラグインのスライダーって押し出し式の切り替えばっかりですよね。今回作ったようなタイプをずっと探していたのですがなかなか見つけられず..。
作ってみて一番迷ったのは、スライドの中身を崩さずアニメーションさせる方法でした。
画像をbackgroundで指定してbackground-positionを操作するやり方もありますが、これだと画像スライドにしか対応できないのと、JSのためにHTMLを寄せて書かなきゃいけないのがちょっと嫌でした。
clipは設定が少し面倒くさいですが、一筆書きっぽいインタラクションを簡単に作りたいときなんかにも使えそうでなかなかよいですね。

今後はもうちょっと機能を増やしてスクリプトのプラグイン化にも挑戦してみたいです。
Amazon WorkDocs iPhone アプリを試してみる

# 概要

事前に設定しておいた WorkDocs に、モバイルアプリをインストールして iPhone からアクセスしてみます。

WorkDocs の設定については以下をご参照ください。  

* [導入](https://stangler.hatenablog.com/entry/2019/02/12/124148)
* [Admin 設定](https://stangler.hatenablog.com/entry/2019/02/13/113050)
* [ドライブアプリ](https://stangler.hatenablog.com/entry/2019/02/19/154518) 

# 参考サイト
  
*  [Amazon WorkDocs ドキュメント](https://docs.aws.amazon.com/workdocs/index.html#lang/ja_jp)


# iPhone アプリ
  
AppStore で Amazon WorkDocs を検索すると以下のように出てきますので、インストールしましょう。  
  
![20190129_WorkDocs_01_AppStore01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/ffc57395-1b72-d589-89a3-32118f5463a6.png)


# アプリ設定
  
まずは「サインイン」ボタンをクリック。  
  
![20190129_WorkDocs_02_サインイン01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/d2adade7-cbfd-61c0-4048-c32be5c597ce.png)

次に「サイト URL 」と「メールアドレス」を入力します。  
  
![20190129_WorkDocs_03_組織01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/f82416ce-f7c6-428d-40cb-bbdbbeed1d0d.png)

  
次の画面では、ご自分のアカウントのログイン情報を入力します。  
  
![20190129_WorkDocs_04_認証01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/3e8f563f-41f1-e676-772e-87977930c869.png)


  
# ドキュメント閲覧
  
マイドキュメントが開いて以下のようにファイルが表示されます。  
  
![20190129_WorkDocs_05_マイドキュメント01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/1e173958-a794-f04d-b90e-b71aecac4a0d.png)

  
ファイルをクリックして中を覗いてみて見ましょう。きちんと表示されていますね。  
  
![20190129_WorkDocs_06_テストテキスト01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/6a138fdf-a212-21c6-85ed-baea0087dea6.png)


次に、メニューをクリックすると以下のように、ファイルの情報を見ることができます。また、いろいろな操作をすることができます。  
  
![20190129_WorkDocs_07_情報01.PNG](https://qiita-image-store.s3.amazonaws.com/0/344724/552687a8-c91b-0900-2a02-2fd9ce3a8fcf.png)

  
以上です。
vimのプラグイン管理

#dein.vimを始めよう
今までVimをバニラのまま使って来たけど、そろそろプラグインなどが欲しくなって来たのでdein.vimを導入することを決意。
何をやったかのメモ。

##dein.vimのインストール
このページを参考に
https://qiita.com/Coolucky/items/0a96910f13586d635dc0


```bash
#まずディレクトリを作る。慣例的に~/.cache/dein に作るらしい。（公式でもここに作ってる）
$ mkdir -p ~/.cache/dein
#ディレクトリ移動
$ cd ~/.cache/dein
#gitにあるdein.vimのinstaller.shを取ってくる
$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
#インストーラ実行
$ sh ./installer.sh ~/.cache/dein
```

インストーラ実行時に設定用のコードとして下のようなコードが出てくるので、コピーして.vimrcに貼り付けておく。
最後の"if you want ~~"の所にはコメントアウトがあるのでこれは外しておく。

```
"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=$HOME/.cache/dein/repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('$HOME/.cache/dein')
  call dein#begin('$HOME/.cache/dein')

  " Let dein manage dein
  " Required:
  call dein#add('$HOME/.cache/dein/repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here:
  call dein#add('Shougo/neosnippet.vim')
  call dein#add('Shougo/neosnippet-snippets')

  " You can specify revision/branch/tag.
  call dein#add('Shougo/deol.nvim', { 'rev': '01203d4c9' })

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif

"End dein Scripts-------------------------

```

そこでvimを実行すればインストールできるはずだったのだが、ここでエラーが発生。

```
Error detected while processing function dein#begin[1]..dein#util#_begin[6]..dein#util#_error[1]..<SNR>5_msg2list:
line    1:
E121: Undefined variable: v:t_list
E15: Invalid expression: type(a:expr) ==# v:t_list ? a:expr : split(a:expr, '\n')
Error detected while processing function dein#begin[1]..dein#util#_begin[6]..dein#util#_error:
line    1:
E714: List required

```
エラーメッセージでググったらvimのバージョンが7.4だと最新のdein.vimは動かないらしい。

##vimの最新版のインストール
ということで急遽vimのアップデートをする。ついでに、vimのバージョン管理をHomebrewに任せることにする。

Macには標準でver7.4が入っていたため、brewで最新版のvimをインストールした後、パスを通して終わり。
Homebrewのオプションで--with-override-system-viを追加するとパス設定を省略できるらしい。

```bash
$ brew　install vim --with-override-system-vi 
```

しかし、ここでもエラーが発生。どうやら僕のbrewのvimにはオプションが存在しないらしい。なので手動でパスを変更。

```bash
$ brew install vim
```
の実行後に、~/.bashrcに以下のコードを追加。

```
export PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin
```
~/.bashrcを読み込んで

```bash
$ source ~/.bashrc
```
これで最新版のvimが使えるようになった。

```bash
$ vim --version
#VIM - Vi IMproved 8.1 (2018 May 18, compiled Feb 19 2019 11:57:32)
#~~~
```

最新版のvimだとエラーが発生しなかったので上手い事いったらしい。
これでdein.vimが入った。

#まとめ

- dein.vimをインストールした。
- 古いバージョンのvimだと動かなかったので最新版にアップデートした。

ここに来て、シェルの知識の無さがつらくなって来た。シェルの勉強をしようと思った。
【自分用メモ】Git

## 特定のコミットまで戻る
```
$ git log //コミットidを探す
commit 5e76a65935a652f88f5280ad2ad10d7f3
Author: hoge <hoge@gmail.com>
Date:   Thu Feb 21 13:17:29 2019 +0900

    install redux

commit b1a50e1f2cd788e2960ec2c341f372110d2
Author: hoge <hoge@gmail.com>
Date:   Thu Feb 21 13:08:56 2019 +0900

    create application by create-react-app

commit e13b05391d054a72307bbe74183dcf02fc
Author: hoge <hoge@gmail.com>
Date:   Thu Feb 21 12:59:33 2019 +0900

    first commit

$ git reset --hard コミットid
```

## ブランチ名変更
```
$ git branch -m 対象ブランチの名前 新しい名前

//現在いるブランチ名の変更
$ git branch -m 新しい名前
```

## コンフリクトの解消
```
$ git fetch
$ git rebase -i origin/master
```
Laravel チートシート 多言語 編

### Blade @langディレクティブ
```
@lang('label.title')
```
### PHP __ヘルパ関数
```php5
__('label.title')
```

### ロケール取得
```php5
if (Config::get('app.locale') == 'en') {
}

if (\App::getLocale() == 'en') {
}

```
Monaca 環境構築はじめるよー 

# 私の環境だよ
macOS mojave 10.14.3
 
# マニュアル読むよ

## Monaca Localkit編

### 概要
https://docs.monaca.io/ja/products_guide/monaca_localkit/overview/
ふむふむ

### ペアリングとデバッグ
https://docs.monaca.io/ja/products_guide/monaca_localkit/pairing_debugging/
LANの設定が厳しいみたで繋がらない。まあいいや。

＃＃＃ ファイル・フォルダー構成
https://docs.monaca.io/ja/products_guide/monaca_localkit/dependencies/file_dir/
ふむふむ

### チュートリアル
https://docs.monaca.io/ja/products_guide/monaca_localkit/tutorial/
ふむふむ

＃＃＃＃　パート 1 : プロジェクトの作成
https://docs.monaca.io/ja/tutorials/monaca_localkit/starting_project/
ふむふむ

#### パート 2 : Monaca Localkit と Monaca デバッガーとの連携
https://docs.monaca.io/ja/tutorials/monaca_localkit/testing_debugging/
ふむふむ

* * *
 とりあえずここまで読んだ。

## Monaca CLI編

### 概要
https://docs.monaca.io/ja/products_guide/monaca_cli/overview/
ふむふむ

### チュートリアル
https://docs.monaca.io/ja/products_guide/monaca_cli/tutorial/
ふむふむ

#### パート 1 : プロジェクトの作成
https://docs.monaca.io/ja/tutorials/monaca_cli/starting_project/

$ monaca create PROJECT_DIRECTORY

「PROJECT_DIRECTORY」このまま打って無事「PROJECT_DIRECTORY」フォルダができた。
まあいいや。次。

### パート 2 : Monaca CLI と Monaca デバッガーとの連携
https://docs.monaca.io/ja/tutorials/monaca_cli/testing_debugging/
ペアリングに失敗した。

> ローカル PC 側のファイアーウォールを無効化していること。

とあったので、オフにした結果、繋がった。
ちなみにマカフィーが有効にしていた。

`Please run "npm install nw@0.26.6" and restart the debug.`
と言われるけど、とりあえず無視。

* * *
 とりあえずここまで読んだ。
today's python error

```
# python train.py
../common/trainer.py:7: UserWarning: 
This call to matplotlib.use() has no effect because the backend has already
been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.

The backend was *originally* set to 'Qt5Agg' by the following code:
  File "train.py", line 5, in <module>
    import matplotlib.pyplot as plt
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/pyplot.py", line 71, in <module>
    from matplotlib.backends import pylab_setup
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/backends/__init__.py", line 16, in <module>
    line for line in traceback.format_stack()


  mpl.use('Agg')
Traceback (most recent call last):
  File "train.py", line 12, in <module>
    from ch07.peeky_seq2seq import PeekySeq2seq
  File "../ch07/peeky_seq2seq.py", line 5, in <module>
    from seq2seq import Seq2seq, Encoder
ModuleNotFoundError: No module named 'seq2seq'
```

```
# python visualize_attention.py 
Traceback (most recent call last):
  File "visualize_attention.py", line 60, in <module>
    visualize(attention_map, row_labels, column_labels)
  File "visualize_attention.py", line 26, in visualize
    fig, ax = plt.subplots()
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/pyplot.py", line 1198, in subplots
    fig = figure(**fig_kw)
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/pyplot.py", line 548, in figure
    **kwargs)
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/backend_bases.py", line 161, in new_figure_manager
    return cls.new_figure_manager_given_figure(num, fig)
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/backend_bases.py", line 167, in new_figure_manager_given_figure
    canvas = cls.FigureCanvas(figure)
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/backends/backend_qt5agg.py", line 24, in __init__
    super(FigureCanvasQTAgg, self).__init__(figure=figure)
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/backends/backend_qt5.py", line 234, in __init__
    _create_qApp()
  File "/opt/conda/lib/python3.6/site-packages/matplotlib/backends/backend_qt5.py", line 125, in _create_qApp
    raise RuntimeError('Invalid DISPLAY variable')
RuntimeError: Invalid DISPLAY variable
```
UEFI HTTP Boot + Kickstart で OSの自動プロビジョニング

最近のサーバはHTTP Bootなるものができるので調査した。IPV6も試したがいくつか問題があり、今回は断念。次回のチャレンジする。

## 事前準備

* 192.168.1.1 にプロビジョニング用サーバを用意（hddが10GBあれば十分）
* httpdと、dhcpdをインストールしておく
* /media にインストール用DVDをマウントしておく

## DHCPサーバの設定

PXEではnext-serverを指定するが、HTTP BOOT では、HTTPClientと、efiのbootイメージのファイル名を指定する。

```
subnet 192.168.1.0 netmask 255.255.255.0 {
  range 192.168.1.2 192.168.1.100;
  option subnet-mask 255.255.255.0;
  default-lease-time 3600;
  max-lease-time 7200;

  class "httpclients" {
    match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";
    option vendor-class-identifier "HTTPClient";
    filename "http://192.168.1.1/boot/bootx64.efi";
  }

}
```

## WEB サーバ側の設定

最低限必要なものは以下の通り

```
/var/www/html/ks/rhel7.cfg        ... Kickstart のファイル、urlにはhttpでアクセスできる場所を指定する（今回なら、/rhel7/）
/var/www/html/boot/bootx64.efi    ... DVDから抽出したものに、netとhttp モジュールを組み込む必要がある。後述。
/var/www/html/boot/initrd.img     ... DVDから抽出(/media/isolinux/initrd.img)
/var/www/html/boot/vmlinuz        ... DVDから抽出(/media/isolinux/vmlinuz)
/var/www/html/boot/grub.cfg       ... 後述
/var/www/html/rhel7 -> /media     ... DVDのルートにlinkを張っておく
```

## EFI用bootイメージの作成

メディアからコピーしてきたrpmを展開し、モジュールを組み込んだイメージを作成する

```
rpm2cpio /media/Packages/grub2-efi-x64-modules-xxxxxxxxx.el7.noarch.rpm | cpio -id
grub2-mkimage -d ./usr/lib/grub/x86_64-efi -O x86_64-efi \
    -o bootx64.efi -p '' normal linux http net echo linuxefi
```

## grub.cfgの設定

netとhttpモジュールの有効化と、場所の指定をする

```
set timeout=10
menuentry 'RHEL 7' {
  insmod net
  insmod http
  linuxefi (http,192.168.1.1)/boot/vmlinuz ip=dhcp inst.repo=http://192.168.1.1/rhel7/ inst.ks=http://192.168.1.1/ks/rhel7.cfg
  initrdefi (http,192.168.1.1)/boot/initrd.img
}
```

以上