OmniAICreator/Qiita-1.07M huggingface dataset:
Rのデータ型

##本稿の目的・対象

以下のことを知りたい人・思い出したい人向けのメモ的postです。

- Rのデータ型の種類はどのようなものがあるの？
- typeってなに？
- modeってなに？
- classってなに？
- データ型はどうやって調べるの？
- データ型はどうやって変換するの？


##Rのデータ型

R のオブジェクトは、type、mode および class の 3 種類の型が存在する。



##type 

typeは、データを保存できる変数のオブジェクトに対する型であり、ベクトル型、リスト型などがある。

##mode 

modeは、オブジェクトに格納されている要素に対する型であり、理論型(logic)、実数型（numeric)、整数型（integer)、文字型(character)、日付と時間（Date/POSIXct）、関数型などがある。

##class
class は、オブジェクトの属性に対する型であり、行列型、因子型、データフレーム型などがある。
特にclass が定義されていない場合は、mode または type の型を継承する


##データ型の調べ方

typeを調べる時・・・typeof()
modeを調べる時・・・mode()
classを調べる時・・・class()


```R:R
x <- c(1.1, 2.2, 3.3, 4.4, 5.5)
typeof(x)
[1] "double"

mode(x)
[1] "numeric"

class(x)
[1] "numeric"
```


##データ型を変換する

Rのオブジェクト型は相互に変換可能である。変換の指定方法を表にまとめる（検査の仕方もついでにまとめる）

| | mode | numeric | integer | complex | character | logical ※bool |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|  変換 | mode()  | is.numeric()  | is.integer()  |  is.complex() | is.character()  | is.logical  |
|  検査 |  storage.mode() | as.numeric()   | as.integer()  | as.complex()  | as.character()  | as.logical()  |

ここで、ベクトルの型の間には以下の大小関係がある．

> character > complex > numeric > logical > NULL

ベクトルの要素は全て同じ型である必要があるので，異なった型のデータを集めてベクトルを作る時、上記の大小関係に従って「最も大きい」型に強制的に揃えられる．



##参考URL

[R-source 25](http://cse.naro.affrc.go.jp/takezawa/r-tips/r/25.html)
<input type="hidden">の使い方について

# ＜input type= "hidden"＞の使用例

##idをブラウザ上に見えないようにして値を変更する

```php

<form method ="post">

<input type="text" name="price" value="">
<input type="submit" name="change" value="変更">
<input type="hidden" name="id" value="<?php $value['id'];">

```
値段を変更するのに、どの商品するかを特定し、表記しないように隠している。
表に出したくないときに使用するが、パスワードなどはセキュリティーの観点から
使うべきではない。

##送信ボタンに値を入れたいとき

非公開→公開ボタンのstatus_chgが送った値を付与する入れ物として
＜input type="hidden" name="open_status"＞を挿入しています。

```php

        <select name="open_status">
            <option value= "0">非公開</option>
            <option value="1">公開</option>
        </select>
 <form method="post">        
　　　　　<td><?php print htmlspecialchars($value['open_status'],ENT_QUOTES,
            'UTF-8'); ?>
        <input type="hidden" name="open_status" value="<?php echo 
        $value['open_status']; ?>">
        <input type="hidden" name="drink_id" value="<?php echo $value['id']; ?>">
        <input type="submit" name="status_chg" value="
        <?php if((int)$value['open_status'] === 0) { ?>
            <?php echo "非公開→公開"; ?>
        <?php } else if ((int)$value['open_status'] === 1) {  ?>
            <?php echo "公開→非公開"; ?>
        <?php } ?>">

        </td>
  </form>
```
１　フォームを入力をする画面
２　入力内容を確認する画面

２のときに画面に表記していない値を１に含ませることで、プログラムを送信できるようにする
Python 内包表記

##経緯

ATcoderのサンプル問題を解いていた時にどうしても処理制限時間が超えられず、
内包表記を使うと解決できたので、忘れないようにまとめておく

##構文

```
[リストに組み込みたい文字列 for 変数 in 範囲やリスト]
```

範囲の後に条件式を記載することで条件式に当てはまったものだけリスト化することもできる

例）

```
//期待する結果=>[0,2,4,6,8,10]
l = [i for i in range(11) if i%2 == 0]
print(l)
//[0,2,4,6,8,10]
```

条件式はfor文の中に入れることもできれば、for文の中で取り出した値を条件式に掛けることもできる

```
//期待する結果=>['リンゴ','ブドウ','リンゴ','ブドウ','リンゴ','ブドウ']
l = ['リンゴ' if i%2 == 1 else 'ブドウ' for i in range(11)]
print(l)
//['リンゴ', 'ブドウ', 'リンゴ', 'ブドウ', 'リンゴ', 'ブドウ']
```

##利用するシチュエーション
基本的にはリストを作成するときに、appendで利用するより処理速度を速めたいときに利用する。

リストだけではなく、辞書や二元配列の作成にも対応できるので、lengthの長い配列を処理する際にはコードの簡易化にも使えるので利用するべきだと思われる
【WordPress】え、、ローカル環境と本番環境でのカルチャーショック

#経緯
WordPressでのサイト制作を行う際の最終関門が、この本番環境へのアップロードではないでしょうか？
私自身、これまで何度かサイトを作成してきましたが、本番環境へのアップロードが一番緊張しますね。
最後の最後につまらないことでつまづくのは勿体無いのでしっかり解消していきたいものです。
今回は、自分自身がローカル環境では通常どおり表示されていた固定ページの画像が本番環境にあげた途端表示できなくなってしまったことから、同じような境遇の方もいるのではないだろうかということで共有していきたいと思います。

#注意
サーバー、ドメイン、FTPのお話はこちらではしません。
すでにサイト自体はアップロードされた状態から、発生する問題の解決について解決していきたいと思います。

#参考
[ブログの画像が表示されない9つ＋αの原因！リンク切れの対処法](https://bibabosi-rizumu.com/image-broken/)

#実践
すいません。参考で共有した記事を読めば解決する話なのですが、私自身が直面した事例でより詳細にお伝えできればといった所存でございます。
一言で言えば、相対パスの問題です。

ローカル環境であれば、以下のように画像フォルダまでのパスを表示していました。

```
<img src="/directory/wp-content/themes/theme-name/img/img.jpg" />
```

しかし、本番環境にアップロードした場合はこんな感じで記入する必要があります。

```
<img src="https://domein.com/wp-content/themes/theme-name/img/img.jpg" />
```

冷静に考えるとそれはそうですよね。
FTPからのパスをよく見ればわかりそうなものですよね。
気をつけましょう！

余談ですが、私の場合には以下のようなテンプレートを入るとページ全体のCSSが崩れてしまい焦りました、、

```
<?php echo get_template_directory_uri(); ?>
```
通常のfront-page.php等のテーマ直下に直接存在するファイルには必要になりますが、WordPressの固定ページから表示される際には問題児になってしまうものなんですね。



#最後に
ローカル環境でうまくいって、本番環境にやっとの思いであげられたと思いいたらこの仕打ち。。
とつまづくことは案外多いかもしれませんが、冷静に見直してみれば気づくこともあるかと思います。
まずは、ローカルと本番とのパスの違いから見てみてはいかがでしょうか？
PHPでスクレイピングその2

# 前回のおさらい

前回Goutteを使って簡単なスクレイピングを行いました。
https://qiita.com/shioharu_/items/d5cca03c9bba16e0bf0b

なので今回は自分の取得したい情報を実際に取ってこようかと思います！

## 取得したい情報

今回取得したい情報はこちら。
beatmaniaIIDXのWeeklyRankingです。
1週間ごとに課題曲があり、プレイヤーがだしたスコアを高い順にランキング化したものとなります。

![WR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290284/a31bb6ef-79cb-13af-7f27-540239bf7544.png)

## さっそく取得

```
<?php

require_once 'goutte.phar';
use Goutte\Client;

$client = new Client();
$crawler = $client->request('GET', 'https://p.eagate.573.jp/game/2dx/27/ranking/weekly.html?class_id=3');
```
よし、これで前回同様ページ情報を取得できるぞ

## 立ちはだかる壁

しかしながらランキング情報は取得できませんでした。
なぜならこのページは**ログインが必要**だったからです

![hilogin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290284/214ee7df-989a-c577-33bc-307786d259d6.png)

## それならば

Goutteはログインを行うことも可能です。
これならログイン後に目的のページ情報が取得できますし、勝ったも同然です。

```
$client = new Client();
$crawler = $client->request('GET', 'https://p.eagate.573.jp/gate/p/login.html?path=/index.html');
$loginForm = $crawler ->filter('form')->form();
$loginForm['nm_login_id'] = 'hoge@example.com';
$loginForm['password'] = 'PASSSWOOOORDDD';
$cli->submit($loginForm);
```

## 立ちはだかる壁その2

しかしながらログインができませんでした。
なぜならこのページは**画像認証**があるからです。

![screencapture-p-eagate-573-jp-gate-p-login-html-2020-04-12-15_02_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290284/ea1662fa-4916-8621-9116-95e0e16cffb2.png)


詰みました。

～完～

## 総評

- Goutteで画像認証する(または待機処理をして手動でログインを行う)方法がわからなかったため、急遽今回でPHPでスクレイピングシリーズは打ち切りとなりました。
- 次回、**Selenium＋Pythonでスクレイピング**へ続きます
gitで自分のローカル環境ファイルだけ無視したい

## やりたいこと

- gitで自分のローカル環境ファイルだけ無視したい。
- 共通の`.gitignore`は編集したくない。

色々参考にして、`.git/info/exclude`ファイルに追記すればOKということがわかった。
ただ自分の場合は.gitディレクトリ内にinfoディレクトリもなければexcludeファイルも無かったのでそこからの適用方法。

まずはターミナルでプロジェクトディレクトリに入ったあと、

## プロジェクトフォルダから.gitディレクトリに移動


```
$ cd .git
```

## infoディレクトリ作成
```
$ mkdir info
```

## excludeファイル作成
### ディレクトリ移動
```
$ cd info
```

## excludeファイル作成
```
$ touch exclude
```

`.git/info/`にexcludeファイルが作成されていることを確認。

テキストエディタでexcludeファイルを開き、`.gitignore`と同じ要領で除外ファイルを適用。
RPA AutoMate

##ハンズオン
[AutoMate - ハンズオン1 Excel処理の自動化](https://www.youtube.com/watch?v=vhVWUdjbb64)
[AutoMate - ハンズオン2 アプリケーション操作の自動化](https://www.youtube.com/watch?v=_IKeWIsPe7Y)
[AutoMate - ハンズオン3 Webブラウザ操作の自動化](https://www.youtube.com/watch?v=msHGzuqpVho)
[AutoMate - ハンズオン4 マウス・キーボード操作の自動化](https://www.youtube.com/watch?v=YzWLDsFn9mU)
[AutoMate - ハンズオン5 IBM i操作](https://www.youtube.com/watch?v=kNo90t2N_IA)
##デモ
[AutoMate 定型OCRオプション with AI inside 紹介デモ - YouTube](https://www.youtube.com/watch?v=SzMF-zlSZSo)
[AutoMate PDFデータをIBM i に入力するデモ - YouTube](https://www.youtube.com/watch?v=ZDJYkRMBeR0)
[AutoMate - LINE WORKS, SPALO 連携デモ動画](https://www.youtube.com/watch?v=b9NAhK1SGn4)
[AutoMate - TwitterおよびWatson連携デモ](https://www.youtube.com/watch?v=l2kf5NeCpWE)
[AutoMate IBMi(AS400) 操作の自動化 デモ - YouTube](https://www.youtube.com/watch?v=Nb44POGZNaE)
[AutoMate 経費精算システムデモ](https://www.youtube.com/watch?v=GxXnW6gnEyM)
##その他
[AI inside × UiPath RPA Platform - YouTube](https://www.youtube.com/watch?v=DjV3-fuEKUc)
[AutoMate　伝票セパレート - YouTube](https://www.youtube.com/watch?v=_ZtNh1nqZqs)
[D3.js] たのしいスケール 尺の変換

# はじめに

D3.jsにおけるスケール(Scale)とは、どんなものなのかまとめてみようと思います。
難しいことはわからないので、動く例を貼っていきます。


## サンプルについて

サンプルコードはD3.js本体と同じく[Observable.com](https://observablehq.com/)に置きました。

Observable.comの画面の見方はこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/16f3cac1-a0a0-e5e7-b090-7acf265ee0ac.png)





# スケール(Scale)とは

ある入力（ドメインといいます）から、ある出力（レンジといいます）への写像（マッピング）を提供します。

ドメインからレンジへどのように対応させるかによって、いろいろなスケールがあります。

* 連続スケール - Continuous Scape
* シーケンシャルスケール - Sequential Scale
* 発散スケール - Diverging Scale
* 量子化スケール - Quantize Scale
* 順序スケール - Ordinal Scale


とりあえず最初の3つについて書いてみました。
量子化スケールと順序スケールはまた調べます。


# 連続スケール - Continuous Scale

連続量$x$を連続量$y$へマッピングします。

連続スケールには線形(Linear)、ぺき乗(Power)、対数(Log)、同一値(Identity)、日時(Time)があります。

## 線形スケール - Linear Scale

ドメインとレンジをそのまま対応させます。

数式で書くとこんなんです。

```math
y = mx + c
```

$m$と$c$は、ドメインとレンジの値により自動的に決まります。


サンプルです → https://observablehq.com/@sengokyu/d3-js-linear-scale

## べき乗スケール - Power Scale

数式で書くとこんなんです。

```math
y = mx^k + c
```

$m$と$c$は、ドメインとレンジの値により自動的に決まります。

$k$は、別途`expornent`メソッドで指定します。指定しないときは1になります

サンプルです → https://observablehq.com/@sengokyu/d3-js-power-scale

## 対数スケール - Log Scale

数式で書くとこんなんです。

```math
y = m \log{_n} x + c
```

$m$と$c$は、ドメインとレンジの値により自動的に決まります。

底$n$は、`base`メソッドで指定します。デフォルトは10です。

$\log(0)$は $-\infty$ になるので、ドメインに0を含む範囲は指定できません。 

サンプルです → https://observablehq.com/@sengokyu/d3-js-log-scale

## 同一値スケール - Identity Scale

ドメインとレンジが同じ値になるスケールです。

## 日時スケール - Time Scale

ドメインが日時になっているスケールです。
日時の書式を指定できたります。

# シーケンシャルスケール -  Sequential Scale

連続スケールと同様に、連続量$x$を連続量$y$へマッピングします。
連続スケールと異なるのは、マッピングのための関数を別途指定できることです。

サンプルです → https://observablehq.com/@sengokyu/d3-js-sequential-scale

# 発散スケール - Diverging Scale

連続スケールと同様に、連続量$x$を連続量$y$へマッピングします。
また、シーケンシャルスケールと同様に、マッピングのための関数を別途指定できます。
シーケンシャルスケールと異なるのは、ドメインに3つの値を取ることと、それを0〜0.5〜1へマッピングすることです。

サンプルです → https://observablehq.com/@sengokyu/d3-js-diverging-scale



# リンク

* [d3-scale Githubレポジトリ](https://github.com/d3/d3-scale/tree/master)
【Laravel】フォームリクエストクラスについてまとめ

#フォームリクエストクラス

ユーザーがフォーム入力をして送信した HTTP リクエストの情報に対してバリデーションをかける事ができる。

##以下のコマンドで作成できる
```terminal
$ php artisan make:request #[クラス名]
```


```php:SumpleRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SumpleRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize(): bool
    {
        // ユーザーがこのリクエストの権限を持っているか否かをbooleanで返す。
        // 例 Route::post('comment/{comment}');のパラメータを取得、
        //    commentsテーブルにidカラムが$commentIdで、
        //    user_idカラムがログイン中のidであるデータが存在するか否かをチェック。
        $commentId = $this->route('comment');
        return Comment::where('id', $commentId)
                  ->where('user_id', Auth::id())->exists();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return [
            // ココにバリデーションを記述する。
            'title' => 'required|unique|max:255',
            'body' => 'required',
            'image' => 'required|file|mime::jpg,jpeg,png,gif',
        ];
    }
}
```

##authorize()メソッド
　　権限に関する判定を行うメソッド、権限に対する true,false を設定する。
　　アプリケーションの他の場所に別の認証ロジックがあれば、trueを返すだけで良い。

##rules()メソッド
　　この中にバリデーションのルールを書く。

##バリデーションルールの書き方(抜粋)
　　rules()メソッドの戻り値に連想配列で渡す。

```php:
    /**
     * @return array
     */
    public function rules(): array
    {
        return [
            // 必須、指定されたDBテーブルに無い(uniqueな)、255文字までの文字列
            'title' => 'required|unique|string|max:255',
            // 必須、
            'subtitle' => 'required',
            // 必須、10MBまでのjpg,jpeg,png,gifファイル
            'image' => 'required|file|mimes:jpg,jpeg,png,gif|max:10000',
            // 必須、255文字までの文字列
            'address' => 'required|string|max:255',
            // 必須、10〜11桁の数値
            'phone_number' => 'required|digits_between:10,11',
            // 必須、数値のみ
            'article_id' => 'required|numeric',
            // 必須、21845文字までの文字列
            // TEXT型(max:65535バイト、UTF-8(1文字3バイト)だと21845文字入る)
            'article' => 'required|string|max:21845',
        ];
    }
```

##使い方
バリデーションを掛けたいコントローラーのメソッドの引数にタイプヒント[^1]で渡す。  
渡されたフォームリクエストは、コントローラーメソッドが呼び出される前に確認される。

```php:SumpleController.php
/**
 * @param  SumpleRequest  $request
 * @return Response
 */
public function index(SumpleRequest $request): Response
{
    // controllerの処理
}
```


バリデーションに成功すると、コントローラーの処理に進むが、`失敗すると`、エラーメッセージと入力値がフラッシュデータ[^2]として保存され、`リダイレクトレスポンス`が返される。  
`Ajax リクエストの場合、バリデーションエラーを表現する JSON を含んだ、422 ステータスコードの HTTP レスポンスが返される。`


##参考文献
[Laravel6.xドキュメント/基礎/バリデーション](https://readouble.com/laravel/6.x/ja/validation.html)


[^1]: `タイプヒント/タイプヒンティング（型宣言）`<br>関数およびメソッドが受け取る引数に対して、特定の型であることを指定できる機能。  
[^2]: `フラッシュデータ`<br>特殊な種類のセッション・データで、あるリクエストの中で設定されると、次のリクエストの間においてのみ読み出すことができて、その後は自動的に削除される。
Flutterで動的にWidgetを作成する時の方法

# はじめに

ListViewやPageViewerなどの要素数が動的な場合のUIを作る場合のコーディング方法についてまとめた記事です。

# for文を使う方法

引数だけ変えたWidgetを複数個指定する場合にはfor文 (for-each含む) を利用した方が便利です。もちろん、if文も同様に利用可能です。

```Dart:
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        for (int i = 0; i < 10; i++)
          if (i == hogehoge) ...[MyCircleAvatar(true, i)] else CircleAvatar(false, i),
      ],
    );
  }
```

# Listを使う方法

例えば以下のサンプルのように、List型で管理し、必要なWidgetを動的にaddしていけば良いです。

```Dart:
  @override
  Widget build(BuildContext context) {
    var contentWidgets = _makeWidgets();
    return Column(
        mainAxisAlignment: MainAxisAlignment.center, children: contentWidgets);
  }

  List<Widget> _makeWidgets() {
    var contentWidgets = List<Widget>();

    contentWidgets.add(Text('Hello'));
    if (hoge) {
      contentWidgets.add(Padding(
        padding: EdgeInsets.only(top: 10, right: 20, bottom: 30, left: 40),
        child: Text('world'),
      ));
    }

    return contentWidgets;
  }
```
'web3.currentProvider.selectedAddress' is null with MetaMask

## 問題
署名付きトランザクションを発行したいが、秘密鍵をコード側に記述したくない。
そこで、MetaMaskのweb3を使いたいが、なぜか使えない。
`web3.currentProvider.selectedAddress` の返り値が`null`になってしまう。
当然、`web3.eth.accounts[0]` の返り値も`undefined` になる。

## 解決策
`ethereum.enable()` を実行して、Webサイトからのアクセスを許可する。
## 原因
バージョン4.18以降のMetaMaskでは、PrivacyModeというオプションが追加されたみたいです。
そして、7.0以降では全てのユーザにおいて、PrivacyModeがデフォルトの設定になっています。
そのため、従来の初期化方法では、MetaMaskのアカウントにアクセスができなくなっているようです。

許可前の`ethereum`では`selectedAddress`が`null`ですが、許可後は値が入っています。
![スクリーンショット 2020-04-13 22.01.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131659/2091cbfb-9872-2592-258f-9a0770209447.png)
`ethereum.enable()`の実行後にポップアップで、許可するか聞かれます。許可すれば、アカウントアドレスを取得することができます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131659/7caddfef-ea2b-c67c-c752-6ab5b3c2bc2c.png" width="200px"/>

## 余談
これまでは ` window.web3 = new Web3(web3.currentProvider);` のようにプロバイダを使ってWeb3を初期化していましたが、
これからは `window.web3 = new Web3(ethereum);` のように初期化するのが、いいみたいです。詳しくは、公式DocやMediumを参照してください。

ちなみに[MetaMask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn)は2020年3月14日時点でバージョン7.7.8のようです。

## 参考
* [Privacy Mode is now enabled by default - MetaMask - Medium](https://medium.com/metamask/privacy-mode-is-now-enabled-by-default-1c1c957f4d57)
* [Getting Started | MetaMask Docs](https://docs.metamask.io/guide/getting-started.html#basic-considerations)
* [MetaMaskプライバシーモードとDapps側の対応 - Yuya Sugano - Medium](https://medium.com/@yuyasugano/metamask%E3%83%97%E3%83%A9%E3%82%A4%E3%83%90%E3%82%B7%E3%83%BC%E3%83%A2%E3%83%BC%E3%83%89%E3%81%A8dapps%E5%81%B4%E3%81%AE%E5%AF%BE%E5%BF%9C-d8a8f717fda9)
* [Example provider enablement code for EIP-1102](https://gist.github.com/bitpshr/076b164843f0414077164fe7fe3278d9#file-provider-enable-js)
PythonのEnumを関数と紐付け、Callableにする

いくつかの選択肢からアルゴリズムを選ばせるような時、列挙型の各値に関数を紐づけたいことがある。

Javaなら列挙型の各値にメソッドを設定できるのだが、Pythonではできない。Enum自体をCallableにする方向性で、なんとかキレイな書き方がないか考えてみる。

## 値はどうでもいい場合

PythonのEnumは値を自由に設定できる。だから値そのものを関数にしてしまえばいい。

だがEnumを継承したクラスの中で定義された関数はメソッドと判断され、列挙される値に含まれなくなってしまう。

```python
class Dame(Enum):
    # 値を定義したことにならず、メソッドを定義したことになる
    A = lambda: print("A")

list(Dame)
# 空リスト
```

そこで、[このstackoverflowのアイデア](https://stackoverflow.com/questions/31907060/python-3-enums-with-function-values)を借りて、関数が含まれるタプルを値に使うことにする。

```python
from enum import Enum

class CallableEnum(Enum):
    """
    このクラスを継承してCallableなEnumを作る
    """
    def __call__(self, *args, **kwargs):
        return self.value[0](*args, **kwargs)

def register(func):
    """
    関数が含まれるタプルを簡単に定義するためのデコレータ
    """
    return func,
```

使い方はこう。

```python
class Test(CallableEnum):
    @register
    def A():
        print("A")
    
    @register
    def B():
        print("B")

Test.A()
# A
```

## 値を自由に設定したい場合

Enumを継承したクラス`T`に、`T`から関数への辞書を持たせて、`__call__`の中で参照する。

ただし「`T`から関数への辞書」をクラス定義中に`T`の属性として持たせてしまうと、それも列挙型の値の一つになってしまう。`T`がクラスとして出来上がった後で付け加えないといけない。

したがって、クラス定義が終わった後に関数を付け加える書き方になる。

```python
from enum import Enum

class Dnum(Enum):
    """
    Dispatching Enum。こいつを継承する
    """
    @classmethod
    def register(cls, key):
        if not hasattr(cls, "table"):
            cls.table = {}
        def registration(func):
            cls.table[key] = func
        return registration
    
    def __call__(self, *args, **kwargs):
        return self.__class__.table[self](*args, **kwargs)


def register(enum):
    def ret(func):
        enum.__class__.register(enum)(func)
    return ret
```

こんな感じで使う。

```python
from enum import auto

class Test(Dnum):
    A = "A"
    B = "B"

@register(Test.A)
def _A():
    print("A")

@register(Test.B)
def _B():
    print("B")

Test.A()
# A
```

値を自由に設定しつつ、関数をクラス定義の中に書く裏技ないかな……
いろいろなコードの書き方

##return 〇〇　if n == 0(処理はn==0の条件を満たすまで継続）
####return 〇〇　if n == 0
```
def factorial(n)
    return 1 if n == 0
    n * factorial(n - 1) # 関数の中で自身を呼び出している
end
p factorial(5) # => 120
```

####別の書き方
```
def factorial(n)
  if n == 0
    return 1
  else
    n * factorial(n - 1)
  end
end
p factorial(5)
```


##attr_accessorメソッド
####attr_accessor
```
class School
  attr_accessor :name
end
```

####別の書き方
```
class School
  def name=(value)
    @name = value
  end
  def name
    @name
  end
end
```
Kaminariで、controllerでメソッドチェインできない時

## Kaminariで、メソッドチェインができない...

Kaminariを使って無限スクロールを実装していたところ、


```controller.rb
  def index
    # コイツは普通に取得できるけど
      @posts = current_user.posts.where(created_at: Date.today).page(params[:page]).per(8)

    # sort_by, sort_by!, reverse!でつなげた時はエラーになる
      @posts = current_user.posts.where(created_at: Date.today).sort_by {|f| f[:updated_at]}.reverse!.page(params[:page]).per(8)
  end
```
##解決策

上は、メソッドチェインで取得したのはインスタンスオブジェクトなのに対し、
下は、sortメソッドなどは、`Enumerable#sort`というRuby標準のメソッドで配列を返す。

###そもそも

Kaminariのpageは、配列に対して使えなかったらしい。知らなかった。
>もともと、kaminari が扱う page は scope だったかと思います。なので、配列（Array）に対しては使えませんでした。
http://hamasyou.com/blog/2011/06/14/kaminari-paginate-array/


そして、あらかじめKaminariに用意されている`paginate_array`というメソッドがあることを発見。
引数に配列を渡せばオブジェクトに変換してくれる。

##1. インスタンスオブジェクトに配列を格納　2.paginate_arrayの引数に渡す

```controller.rb
  def index
      @posts = current_user.posts.where(created_at: Date.today).sort_by {|f| f[:updated_at]}.reverse!
      
      # paginate_arrayの引数に、格納した配列を渡す。
      @posts = Kaminari.paginate_array(@posts).page(params[:page]).per(8)
  end
```


カミナリについて少し詳しくなれました。（ホッ


こちらの記事を参考
https://stackoverflow.com/questions/16326855/rails-kaminari-how-to-order-a-paginated-array
https://teratail.com/questions/226802
ownCloudインストールとエラー回避設定

# インストール
https://qiita.com/RubiLeah-com/items/53006eedce5e48dba7ea
このサイトを見てもらえればもんだいなかった（ありがとうございました！）。

# 不要なファイル
https://doc.owncloud.org/server/10.4/admin_manual/configuration/general_topics/code_signing.html

フォルダにダウンロードしたZipファイルがあったためエラーが発生した。サーバで削除することで解決。

#「メモリベースによるロック」のエラー

トランザクションによるファイルのロックは、既定の低速データベースによるロックではなく、メモリベースによるロックを使用するように構成する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274506/683497ed-35d1-76d5-3ff8-96e9d40fa989.png)

下記URLを参考に解決する。
https://thinkit.co.jp/article/9772

と思ったが、DBサーバの設定を変更する必要があるようで、借りているサーバだと不可のため、このまま。

# cronの設定
https://doc.owncloud.org/server/10.4/admin_manual/configuration/server/background_jobs_configuration.html#webcron

借りているサーバが、シェルスクリプトしかCRONに設定できない管理画面のため、下記を作成し、CRON設定した。

```
#!/bin/sh
/usr/local/bin/php /path/to/install/dir/occ
```
ハッシュについて（Ruby)

##ハッシュのイメージ

```
{キー1: 値1, キー2: 値2, キー3: 値3}
member = {name: "Ryohei", age: 24}
```

##ハッシュの要素を取り出す

```
member[:name]
=> Ryohei
```

##ハッシュの追加方法
```
member[:place] = "Okayama"
=> {name: "Ryohei", age: 24, place: Okayama}
```

##配列の中にハッシュがあり、取り出す場合

```
blog = [{title: "今日は暑いな", content: "でも頑張るぞ"},{title: "今日の仕事が終われば", content: "明日から旅行だ"},{title: "明日から", content: "プログラミングするぞ"}]
puts blog[0][:title]
=>明日から
```
WSL (ZSH)でGolang 環境を作ろうとしてハマりかけた罠

# ~~sammary~~ summary
WSL でGolang環境を作ろうとしたらgoenvインストール後ディレクトリ名がおかしくなっていました。

``` ~/.
.goenv~ (ファイル名)
etc...
```

## やったこと
参考:https://qiita.com/10380r/items/37d0bf71b0e19a49ce53

* golang のバージョン管理ツールgoenvを入れる  

```
git clone https://github.com/syndbg/goenv.git ~/.goenv
```

* 環境変数設定

``` ~/.zshrc
export GOENV_ROOT=$HOME/.goenv
export PATH=$GOENV_ROOT/bin:$PATH
eval "$(goenv init -)"
```

この後 ```source .zshrc```をしてもcommand not found: goenvになってしまうし
```which goenv```をしてもgoenv not foundになってしまうしで頭を抱えていた所、
ディレクトリをls -aで見てみると冒頭で述べたように".goenvのはずのものが"."goenv~"になっていました。

これを正しいファイル名に直した所goenvは正常に動作しました。
文字コードなのかなんなのか原因はさっぱり分かりません。
javascriptの注意点まとめ

##配列とハッシュの組み合わせを追加したい時
ハッシュを作り、変数に入れた後に配列に追加する。

```js
let test = [
    { subject: 'math', points: 70 },
    { subject: 'english', points: 50 },
    { subject: 'society', points: 80 }
  ];
let science = { subject: 'science', points: 100 };
test.push(science);
```
AtCoder Beginner Contest 162の復習, E問まで(Python)

競プロ初心者の復習用記事です。

ここで書く解は解説や他の人の提出を見ながら書いたものです。自分が実際に提出したものとは限りません。

# [A - Lucky 7](https://atcoder.jp/contests/abc162/tasks/abc162_a)

与えられた3桁の数字が７のつく数字か答える問題です。

どう書いても通ると思いますが。文字列のまま扱い、`in`で存在チェックするのが一番きれいでしょうか。

```python
S = input()
if '7' in S:
    print('Yes')
else:
  print('No')
```

# [B - FizzBuzz Sum](https://atcoder.jp/contests/abc162/tasks/abc162_b)

与えられた数字KまでFizzだったりBuzzだったりしない数字だけを数え、合計するといくつになるか答える問題です。

そのまま書いたら通りました。$N=10^6$での$O(n)$なら特別に効率化する必要はないですね。

```python
count = 0
n = int(input())
for i in range(1, n+1):
  if i%3 and i%5:
    count += i
print(count)
```

# [C - Sum of gcd of Tuples (Easy)](https://atcoder.jp/contests/abc162/tasks/abc162_c)

K以下の三つの数字全てについて最大公約数を合計するといくつになるかを答える問題です。

全ての組み合わせを`itertools.combinations_with_replacement`で作成して最大公約数を求め、$a\neq b\neq c$ならその6倍、$a\neq b=c$とかならその3倍を足していく。一度計算した公約数は保存していって高速化しようとしました。
あんまりきれいな感じはしませんが、これで一応通りました。

```python
import itertools
import math
K = int(input())
g = [[0] * (K+1) for _ in range(K+1)]
out = 0
for a, b, c in itertools.combinations_with_replacement(range(1, K+1), 3):
  if g[a][b] == 0:
    g[a][b] = math.gcd(a, b)
  d = g[a][b]
  if g[d][c] == 0:
    g[d][c] = math.gcd(d, c)
  if a == b and b == c:
    out += g[d][c]
  elif a != b and b != c:
    out += g[d][c] * 6
  else:
    out += g[d][c] * 3
print(out)
```
# [D - RGB Triplets](https://atcoder.jp/contests/abc162/tasks/abc162_d)

RGBの三種類の組み合わせが何通り作れるか考える問題です。ただし一定条件下で組み合わせは弾かれます。

RGB全ての組み合わせは$Rの個数\times Gの個数\times Bの個数$だけあります。ここから条件にひっかかる組み合わせの数を引いていきます。

除外の条件である「一定距離ずつ離れた組み合わせ」というのは離れる距離と開始地点の二つをforで回して$O(n^2)$で取得できます。このインデックスがR, G, Bの三つを埋めているなら除外対象として含まれることになります。

というわけで、以下のようなコードを書きました。これで通りました。

```python
import itertools
N = int(input())
S = input()
out = S.count('R') * S.count('G') * S.count('B')

RGBs = list(itertools.permutations(['R', 'G', 'B'], 3))

for i in range(1, N):
  for j in range(N-i*2):
    if (S[j], S[j+i], S[j+i*2]) in RGBs:
      out -= 1
print(out)
```
# [E - Sum of gcd of Tuples (Hard)](https://atcoder.jp/contests/abc162/tasks/abc162_e)

再び最大公約数の問題ですが、先ほどの解き方では絶対に間に合わないほど値が増えています。

諦めました。解説を見ます。

$\gcd(a, b, c, ...)=X$を求める上で$a, b, c, ...$の全部の組み合わせを求める時間はないので、特定の$X$を満たす$a, b, c, ...$の組み合わせの数を数えていきます。

$a, b, c, ...$の最大公約数が$X$になるということは、「$a, b, c, ...$の全てが$X$で割れる」「$a, b, c, ...$の全てが$n\times X$(ただし$n>1$)では割れない」という二つの条件を満たしていることになります。

まず「$a, b, c, ...$の全てが$X$で割れる」の条件を考えてみましょう。Kから1までの数字の中で、Xの倍数であるものは$K\over X$個存在します。それがN個だけ並んでいるので、$a, b, c, ...$の組み合わせは$({K\over X})^N$個存在します。

さらに「$a, b, c, ...$の全てが$n\times X$(ただし$n>1$)では割れない」という条件は、Xの探索を高い順に行い、$2X, 3X, ...$の倍数であるものの組み合わせの数を順番に引いていけばよいです。

こうしてXとなる組み合わせの数がそれぞれ求まったので、それぞれの組み合わせの数×Xの値を合計すれば求まります。

というわけで、実装したものが以下になります。

```python
N, K = map(int, input().split())
li = [0]*(K+1)

out = 0
mod = 10**9+7

for i in range(K, 0, -1):
  li[i] = pow(K//i, N, mod) 
  for j in range(i*2, K+1, i):
    li[i] -= li[j]
  out += li[i] * i
print(out%mod)
```

この記事はここまでとします。
快適リモートワーク環境を構築する方法

## 概要
個人的な話になりますが、新型コロナウィルス感染症 （COVID-19)の感染拡大を防ぐため、一時的にリモートワークという働き方になりました。それに伴い、自宅から社内システムにアクセスする環境を急遽用意することになりました。

感染症や自然災害などを原因とする不測の事態により、これまでの働き方では対応できない局面が増えているからこそ、今後も働き方改革の一環として、リモートワークを導入や検討する企業が増えていくと予想されます。

しかし、スタートアップやWebアプリを開発しているベンチャーなどは、リモートワークを容易に導入できるかもしれませんが、大手企業の場合、リモートワークを導入しても、自宅PCから社内システムにアクセスすることを許可していないところも多い状態かと思います。

リモートワークできる環境をどうつくるか。
インフラの知識が乏しい私が、最低限知っておく必要があった技術・知識と、リモートワークを楽しく快適にする方法を備忘録としてまとめます。

### おすすめの本
* [Google式10Xリモート仕事術](https://amzn.to/38ITxEo)
* [強いチームはオフィスを捨てる](https://amzn.to/2KiEGqO)
* [小さなチーム、大きな仕事　働き方の新しいスタンダード](https://amzn.to/38Gg190)

## 要件と戦略
- リモート環境でもオフィスと同様の開発ができること
    - リモートワークを始めるために必要なものを把握する
    - VPN（Virtual Private Network）を理解する
- リモート環境でのミーティングをオフィスと同様にできること
    - リモート環境を考慮したミーティングを準備する
    - リモート環境を考慮したミーティングを進行する

作業を行う上で、リモート環境でもオフィスと同様のパフォーマンスが出せる状況を作る必要があります。

## 事前準備
### リモートワークを始めるために必要なもの
- PC
- ネット回線
- 長時間作業しやすい机と椅子
- ヘッドセットマイク

低スペックのPCは作業効率がかなり落ちます。また、円滑なリモートワークには、各家庭に安定したネット回線が敷かれていることが必須です。
チャットツール等でビデオ通話をするのであれば、ヘッドセットマイクはあったほうが便利です。
作業用の机や椅子がなく、ローテーブルで長時間の作業が必要となると、首や腰を痛めます。また、家族と同居していて、一人になれる空間がないのであれば、貸し個室など検討しなくてはいけません。

今後も働き方改革の一環として、リモートワークを導入や検討する機会があるかと思います。
不足しているものがあれば、購入や準備などの検討が必要かもしれません。

### 自宅PCから社内システムにアクセスする
#### VPN（Virtual Private Network）を理解
VPNとは、Virtual Private Networkの略で、離れた場所の間を仮想的な専用線でつないで安全なデータ通信を実現する仕組みです。

VPNは大きく2種類のサービスがあります。

> **インターネットVPN**
インターネットVPNとは、一般的なインターネット回線を利用して離れた拠点同士のLANをつなぐ仮想技術です。VPN接続ルータを拠点に設置することで社内ネットワークを構築でき、スマートデバイスにVPN接続ソフトウェアを導入することで、外にいても社内ネットワークに入ることができるリモートアクセスVPNも利用出来ます。構築認証セキュリティの強さとコストの安さは大きなメリットです。

> **IP-VPN**
IP-VPNとは、通信事業者が提供する閉域網を利用して離れた拠点のLANをつなぎます。通信事業者の閉域網は、その通信事業者と契約した企業のみが利用できる閉ざされたネットワークで構築され、抜群の安全性を誇っています。データの暗号化がないためレスポンス速度が早く、回線品質も安定しています。暗号化してほしい場合は事業者によって対応してくれるケースもあります。IP-VPNはインターネットVPNと違い、通信事業者との契約が必要になります。そのため、業者選びもVPNの品質を保つ重要な検討事項に入ります。


### リモート環境でのミーティング
毎日顔を合わせて仕事をすることが出来なくなるので、メンバーとWeb会議ツールに関して話し合っておく必要があります。また、Web会議ツールは、事前に必ず接続テストしておくとスムーズに会議が出来ます。
Web会議ツールを使用する上で、周りの音が入りやすい環境なら、聞くときはミュートにすると良いです。キーボードの音が入りやすいので、ミュートにしておくと安心です。

#### Web会議システムの例
- [Zoom](https://zoom.us/)
- [Google Hangouts Meet](https://hangouts.google.com/)
- [Skype](https://www.skype.com/ja/)
- [Microsoft Teams](https://products.office.com/ja-jp/microsoft-teams/group-chat-software)

[Snap Camera](https://snapcamera.snapchat.com/)を使用するとWeb会議に、加工した映像で参加できるようになります。

## リモートワークを導入して感じたメリット・デメリット
### メリット
コロナウイルスなどの感染症の流行や、災害による交通網の麻痺など、災害時にもリモートワークは対応しやすくなります。もちろん身に危険が及ぶ状況では、仕事どころではないですが、事態が落ち着いてくれば働かなくては生活していくことはできません。
あらかじめリモート対応の準備を進めておくことで、多少の災害時にも事業をストップせずに稼働させることができます。
また通勤時間がなくなる事で、通勤で体力を消耗する事なく作業に集中できます。

### デメリット
企業にとってリモートワークで最も危惧するのが、「本当に自宅で仕事ができるのか」という点です。
そのため普段の仕事から社員の仕事量を明確にし、リモートでも変わりなく業務が行えることを証明しなければなりません。
また、判断に困ったときどこに質問すればいいのか明確にする必要があります。リモートワークで自分が対応できない業務などは、柔軟な対応も必要になります。

## まとめ
現在、実際にリモートワークで稼働してみてPDCAを回しています。
念入りに準備をすることで快適に業務ができる反面、どれだけ準備をしても、必ずどこかで不備は発生します。
多少の災害時にも事業をストップせずに稼働させる為に、更に経験と準備が必要です。
初心者のKubernetes入門（書籍 Kubernetes 実践入門の写経から学ぶ）Secret 編

# 背景
個人的にインフラの知識以上にこれからのアプリケーションが動く環境を作ってデプロイしたりしてこれからの知識を身に着けたい。そしてより一層、自分の知識のアップデートをしたいと思いました。

その中でこの本に出会い、これから少しずつやったことを残し、未来の自分への手紙としてもあり、見つめ直せればと思いました。

# 引用や参考と今回の自分の勉強用の書籍の紹介
[技術評論社『Kubernetes実践入門』のサンプルコード](https://github.com/kubernetes-practical-guide/examples)
[Kubernetes実践入門 プロダクションレディなコンテナ＆アプリケーションの作り方](https://gihyo.jp/book/2019/978-4-297-10438-2)
![](http://image.gihyo.co.jp/assets/images/cover/2019/9784297104382.jpg)


## 実際の学びについて

書籍を読みながら、章ごとに少しずつ進めていきたいと思います。
GitHub のソースコードも使いながら学んで行きたいと思います。

# 勉強開始

- https://github.com/kubernetes-practical-guide/examples/tree/master/ch1.3.8

# コマンド郡

secret で mysecret を作成する

```text:username
my-username
```

```
$ kubectl create secret generic mysecret --from-file=username --from-literal=password=mypassword
secret/mysecret created
```


## 実行結果

- `username` ファイルの中身が 実行結果の `username=my-username` として設定されてるのを確認できます。
- コマンドラインの `--from-literal=password=mypassword` が`password=mypassword` として設定されているのを確認できます。


<img width="1140" alt="スクリーンショット 2020-04-12 13.03.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174596/be3cce65-db67-72f8-8758-718d3011e484.png">

## 実行結果(コマンド)

- 確認して値がBase64で表示されているのを確認できます。

```
$ kubectl get secrets mysecret -o yaml
apiVersion: v1
data:
  password: bXlwYXNzd29yZA==
  username: bXktdXNlcm5hbWU=
kind: Secret
metadata:
  creationTimestamp: "2020-04-12T03:58:21Z"
  name: mysecret
  namespace: default
  resourceVersion: "64003"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: 0fe6f11b-74b9-4f86-895b-f62da6bda371
type: Opaque
```


## Secret をボリュームとしてマウントする場合

```yaml:secret-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-volume
spec:
  containers:
  - name: nginx
    image: k8spracticalguide/nginx:1.15.5
    ports:
    - containerPort: 80
    volumeMounts:
    - name: mysecret-volume # 下記の Volume 名と一致しなければならない
      readOnly: true
      mountPath: /secrets/mysecret
  volumes:
    - name: mysecret-volume
      secret: # Volumeとして投入するSecretの設定 (1)
        secretName: mysecret # Secret 名と一致しなければならない
```

## マニュフェストを適用する

```
$ kubectl apply -f secret-volume.yaml
pod/secret-volume created
```

## 実行後(コマンド)

- key は表示され Value は非表示でした。これでよいのかな？

```
$ kubectl exec secret-volume -- ls /secrets/mysecret
password
username
```

## Secret を環境変数として扱う場合

```yaml:secret-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-env
spec:
  containers:
  - name: nginx
    image: k8spracticalguide/nginx:1.15.5
    ports:
    - containerPort: 80
    env:
    - name: SECRET_PASSWORD # 設定する環境変数名
      valueFrom:
        secretKeyRef: # 環境変数の値として利用するSecretのキーの参照 (2)
          name: mysecret # Secret名を指定する
          key: password # Secretのキー名を指定
```



## マニュフェストを適用する

```
$ kubectl apply -f secret-env.yaml
pod/secret-env created
```

## 実行後(コマンド)

- Secret で設定したパスワードが環境変数に設定されているのを確認できました。

```
$ kubectl exec secret-env -- sh -c "env | grep SECRET_PASSWORD"
SECRET_PASSWORD=mypassword
```

## アプリケーションの管理方法（３章）〜

今までが一応、コマンドの使い方や、`Namespace`/`Pod`/`ReplicaSet`/`Deployment`/`Service`/`Secret` 等の概要からだと思ってやっていきます。

# 最後に

１章ずつ、ちょっとずつ、 `ちょっとちょうどいい` を勉強のベースにやっていきます。
golang multi-stage build でscratchを使う際にタイムゾーンを設定する方法

## 追記
Go 1.15から、タイムゾーンデータベースをバイナリに埋め込むことができるようになりました。
`-tags timetzdata`
https://go.dev/doc/go1.15#time/tzdata

```dockerfile
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -tags timetzdata -ldflags="-w -s" -o /go/bin/myapp
```

## Dockerfile example :whale:

```dockerfile
FROM golang:1.14.2-alpine3.11 AS builder
RUN apk --update-cache add tzdata
WORKDIR $GOPATH/src/mypackage/myapp/
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/myapp

FROM scratch
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip
COPY --from=builder /go/bin/myapp /go/bin/myapp
ENV TZ=Asia/Tokyo
ENTRYPOINT ["/go/bin/myapp"]
```


ルートCA証明書が必要な場合は上記に加えて以下をCOPYする

```dockerfile
COPY --from=build-stage /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
```

### `-ldflags="-w -s"`

`-w` DWARFシンボルテーブルを省く
DWARF生成を無効にし、ビルドプロセス中にDWARFシンボルテーブルを省く

`-s` シンボルテーブルとデバッグ情報を省く
実行ファイルをビルドするときに、シンボルテーブルとデバッグ情報を省く

今回はバイナリをダイエットさせるために上記のオプションを指定した
参考：
[The Go Programming Language Command link](https://golang.org/cmd/link/)

参考になった記事:star:
[GoとDockerでscratchを使うときに気をつけること](https://qiita.com/Tsuzu/items/774073bccaff32e9ee8d)
【reactnavigation-v5】ヘッダーを消す方法

#方法

探したら解決していました。
https://stackoverflow.com/questions/44701245/hide-header-in-stack-navigator-react-navigation

一部抜粋

``` js
<Stack.Navigator
  screenOptions={{
    headerShown: false
  }}
>
  <Stack.Screen name="route-name" component={ScreenComponent} />
</Stack.Navigator>
```

**headerShown: false**を利用するだけで解決できます。

#まとめ
今まで：header:null
V5：**headerShown: false**
React学習記録2日目

##Progateで作ったアプリをローカルで作成→記事にまとめる
[Progate終了レベル+αの知識でReactアプリを実装](https://qiita.com/d0ne1s/items/4249d3525fe1da097875)

記事を作った後に、記事をなるべく見ないようにしながらもう一度構築。
いい感じに理解が深まりました。

###学んだこと
- `create-react-app`の使い方

##公式チュートリアル
https://ja.reactjs.org/tutorial/tutorial.html
###学んだこと
- オブジェクトを直接変更するより、オブジェクトのコピーを作ってそれを変更する方が良い
    - 複雑な機能が簡単に実装できる
    - 変更の検出
    - React の再レンダータイミングの決定
- renderをするだけのコンポーネントは関数コンポーネントにした方が良い
    - その方がシンプルに書ける
- `map`を使って繰り返し出力する時には`key`を指定することが推奨されている
    - コンポーネントとその兄弟の間で一意なkeyを指定する

##明日やること
公式チュートリアルの後半があんまり理解できてないから、処理の流れを整理して、もう一度作ってみる
注記の分類（地理院地図 Vector タイル）

[toki](https://github.com/unvt/toki) の注記を色分けするために、地理院地図 Vector タイルの [dataspec.pdf](https://maps.gsi.go.jp/help/pdf/vector/dataspec.pdf) をみながら注記を分類して色を割り当てます。

# 注記の分類
annoCtg をみながら、注記を分類します。

|色|対象|4..7|8..10|11..13|14..16|17|
|---|---|---|---|---|---|---|
|Black|人工地物（建物、道路）||411|411,412,413,431,1431,2431,432,441,1441,2441,511,521,522,523,531,1531,2531,532,534,1534,2534,611,612,613,614,615,623,631,632,633,641,642,651,652,653,671,672,673,681,730|411,412,413,431,432,441,511,521,522,523,531,532,533,534,611,612,613,615,631,632,633,634,651,653,654,671,672,673,681,999|511,412,413,432,441,830,831,842,843,850,860,870,880,881,883,884,886,882,887,889,888,885,899|
|Gray|行政地名|150,140|110,140,212|110,120,130,210,220,621|110,120,210,220,621|800|
|Red|人工地物（文化系、鉄道）||421,361|421,422,423,661,662|421,422,423,661,662|421,422,423|
|Blue|水関係|344,345,348,321,322|321,322,344,348,345|321,1321,2321,322,1322,2322,344,1344,2344,345,1345,2345|321,322,341|820,822,840,841|
|Green|植生・陸上の自然地名|351,352,346,343|331,346,347,343,351,352|323,1323,2323,331,1331,2331,346,1346,2346,347,1347,2347,343,1343,2343,351,1351,2351,352,1352,2352,353,1353,2353|323,331,343,351,352,353||
|Brown|地形・山名・平野・盆地|311,333|311,314,315,316,333,334,332|311,1311,2311,312,1312,2312,333,1333,2333,334,1334,2334,332,1332,2332|311,312,313,332,342,720|810,832,833|

色の分類は、[MAP READING AND LAND NAVIGATION](https://fas.org/irp/doddir/army/fm3-25-26.pdf) 3-5.節にいう、15世紀からの地図の伝統を参考にしています。ただし、このマニュアルによれば、全ての注記は Black でなければならないことになるので、あくまで色ボキャブラリを参考にしているという程度になります。

# 割り当てる色の設計
Material Design color を参考にしながら、割り当てる色を設計します。

## Black
Gray 900 #212121 つまり (33, 33, 33) を使用することにします。

## Gray
Gray 500 #9e9e9e つまり (158, 158, 158) を使用することにします。

## Red
Red 800 #c62828 つまり (198, 40, 40) を使用することにします。

## Blue
Blue 900 #0d47a1 つまり (13, 71, 161) を使用することにします。

## Green
Green 800 #2e7d32 つまり (46, 125, 50) を使用することにします。

## Brown
等高線色つまり (200, 160, 60) を使用することにします。

## Purple
不良設定によるデフォルトがわかるための色として、Purple 600 #8e24ee つまり (142, 36, 238) を使用することにします。

# TODO
これらを、https://github.com/optgeo/toki/blob/master/hocon/label.conf で実装していきます。
俺でもわかるElastiCache Redis Clusterのシャードメンバーが消せなくてRedis警察に怒られるイベントメッセージ

俺です。

Redis ClusterのShardメンバーが冗長すぎるなって思ったときに、ノードメンバーを削除してRedis Clusterの利用料金抑えたいときがあります。
Shard内のPrimary Nodeを消そうとするとMasterノード消そうとしたからRedis警察が守ったで(ﾆｶｯ
というイベントが発生します。

```
Decrease Replica count operation failed because the request included deletion of one or more masters: orenorediscluster-001-001 for replication group orenorediscluster
```

このイベントを見かけたときはReplica扱いのノードを消しましょう。

Primaryはダメだ。
Djangoのテストサーバーに他のPCから接続する時の設定

Djangoのテストサーバーに他のPCから接続する時の設定
====

Djangoをインストールして、/home/userid/（~/）で

```django-admin startproject mysite```

でジェネレート。

```cd mysite
python manage.py runserver```

でテスト用にhttpサーバーを起動する所までは公式ドキュメント読みながらすぐに出来ると思います。
けど、サーバーを別のマシンや仮想環境で立ち上げると、他のPCからはアクセス出来ません。
そこで公式ドキュメント
　https://docs.djangoproject.com/ja/3.0/intro/tutorial01
を見ると
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136856/6dc6e6b8-e84b-1c17-7a4f-251732dc2177.jpeg" width=95% />
のように書いてあります。

```python manage.py runserver 0:8000```

その通りに立ち上げて他のPCからアクセスすると、ALLOWED_HOSTSにIPを追加しろと怒られます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136856/75c38fe3-2d14-5098-fe8f-1c3d2845a61f.jpeg" width=80% />


ここでその通りに ~/mysite/mysite/settings.py に追加すると、ちゃんと空のページが表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136856/6074bd20-8b7a-2459-a5c6-aa30e11fba81.jpeg" width=50% />

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136856/791d40fa-989d-48dd-b437-5815f6afb725.jpeg" width=80% />

公式ドキュメントの説明が間違っているのでこうなります。
正解はALLOWED_HOSTSにサーバー(HOST)のIPを登録して

```python manage.py runserver 192.168.29.218:8000```

のように登録したIPで起動する、です。

なぜ？
----
公式ドキュメントの「すべてのIPから」が間違い。
正しくは「サーバーのすべてのIPで」待ち受ける、です。この時IPに0を指定します。
でないと、サーバーのローカルIP（127.0.0.1）でしかリクエストを受け付けられなくなります。
他のPCからつなぐ時はサーバーのIPを指定しますから、サーバー側も待ちうけIPを指定して、リクエストを通してあげる必要があります。
Quill で「Shit + Enterで改行」する方法

エディタライブラリのQuillで「Shit + Enterで改行」する方法。
https://github.com/quilljs/quill

なお、Quill標準の動作で、改行はpタグの段落となります。

# 解決方法
いくつか対応するコードが見つかりますが、こちらの実装が最もスマートな方法だと思います。
https://codepen.io/mackermedia/pen/gmNwZP

```js
var Delta = Quill.import('delta');
let Break = Quill.import('blots/break');
let Embed = Quill.import('blots/embed');

function lineBreakMatcher() {
  var newDelta = new Delta();
  newDelta.insert({'break': ''});
  return newDelta;
}

class SmartBreak extends Break {
  length () {
    return 1
  }
  value () {
    return '\n'
  }
  
  insertInto(parent, ref) {
    Embed.prototype.insertInto.call(this, parent, ref)
  }
}

SmartBreak.blotName = 'break';
SmartBreak.tagName = 'BR'

Quill.register(SmartBreak)

var options = {
  theme: 'bubble',
  modules: {
    clipboard: {
      matchers: [
        ['BR', lineBreakMatcher] 
      ]
    },
    keyboard: {
      bindings: {
        linebreak: {
          key: 13,
          shiftKey: true,
          handler: function (range) {
            let currentLeaf = this.quill.getLeaf(range.index)[0]
            let nextLeaf = this.quill.getLeaf(range.index + 1)[0]

            this.quill.insertEmbed(range.index, 'break', true, 'user');

            // Insert a second break if:
            // At the end of the editor, OR next leaf has a different parent (<p>)
            if (nextLeaf === null || (currentLeaf.parent !== nextLeaf.parent)) {
              this.quill.insertEmbed(range.index, 'break', true, 'user');
            }

            // Now that we've inserted a line break, move the cursor forward
            this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
          }
        }
      }
    }
  }
};

var quill = new Quill('.editor', options);  

var length = quill.getLength()
var text = quill.getText(length - 2, 2)

// Remove extraneous new lines
if (text === '\n\n') {
  quill.deleteText(quill.getLength() - 2, 2)
}
```

# 議論
どうも、Smart Break (Shift+Enter改行)のニーズはあるものの、本家では標準機能化することに乗り気では無い様子です。
QuillはHTMLエディタではなく、リッチテキストエディタだから、というのが理由のようですね。
https://github.com/quilljs/quill/issues/252
https://github.com/quilljs/quill/issues/1187

段落と改行の差を意識しなくて良いような、エディタの設計にする方が正しいかもしれません。
[Unity初級]転がる球にカメラを追従させる

#概要
キャラクターにカメラを追従させるには
![スクリーンショット (66).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/a0bec40e-a91f-57c9-9773-1be1b092adc1.png)
カメラを対象の子オブジェクトにすると簡単に実現できます。
  
でも、ころがる球にこの方法で追従させようとすると、カメラも一緒にクルクル回ってしまいます。



#本文
```cs

    public GameObject ball;//キャラクター
    private Vector3 offset;//カメラとの距離

    void Start()
    {
        offset = transform.position - ball.transform.position;
    }

    void LateUpdate()
    {
        transform.position = ball.transform.position + offset;
    }

```

このようなコードを書いてカメラにAddComponentするとクルクル回ることなく追従させられます。
  

プログラム開始時にカメラと球の位置関係を覚えさせて、適宜その位置関係に調整する仕組み。
![スクリーンショット (68).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/4e143e7b-5213-a290-141e-adeba4c0d880.png)
【ruby】『ruby入門(メモ4)』恐竜配列を作ってみよう(windows10+ruby2.3.3)


####１．配列の追加
__　配列名.push(配列の要素名)__
__　配列名 << 配列の要素名__

####２．配列の逆順ソート
__　配列名.reverse__

####３．配列の重複削除
__　配列名.uniq__

####４．配列に特定の要素が含まれているか
__　配列名.include?(要素名)__

####５．配列が空かを確認する(空の場合はtrue)
__　配列名.empty?__

####６.メソッド!
メソッドの結果を元の配列に反映する。


####６．コード例
```ruby:array_dinosor.rb
=begin
Tyrannosaurus:ティラノサウルス
Velociraptor:ヴェロキラプトル
Stegosaurus：ステゴサウルス
Triceratops：トリケラトプス
Brachiosaurus：ブラキオサウルス
=end

arr_dinosor=['Tyrannosaurus','Velociraptor','Stegosaurus']

puts arr_dinosor[0]
puts arr_dinosor[1]
puts 'all'
#全ての要素
p arr_dinosor
#配列arr_dinororは空か(空の場合はtrue)
puts arr_dinosor.empty?
#配列arr_dinosorにトリケラトプスは含まれているか？
puts 'Triceratops include?='+arr_dinosor.include?('Triceratops').to_s
#逆順に並べ替え
p "***array reverse"
puts arr_dinosor.reverse
p "***arr_dinosor"
puts arr_dinosor
#逆順に並び替えを反映
p "***array reverse!"
p arr_dinosor.reverse!
p "***arr_dinosor"
p arr_dinosor
#入力した要素の追加
p "***input dinosor"
dino_name1=gets.to_s.chomp
p arr_dinosor.push(dino_name1)
#入力した要素の追加2
p "***input dinosor<< "
dino_name2=gets.to_s.chomp
arr_dinosor << dino_name2
##前に入力した2つの恐竜が追加
arr_dinosor << dino_name1
arr_dinosor << dino_name2
p "***arr_dinosor"
p arr_dinosor
#重複を削除したarr_dinosorをarr_dinosor_uniqとする
arr_dinosor_uniq=arr_dinosor.uniq
p "***arr_dinosor_uniq"
p arr_dinosor_uniq

```

####７．実行結果
```

c:\ruby_pg>ruby array_dinosor.rb
Tyrannosaurus
Velociraptor
all
["Tyrannosaurus", "Velociraptor", "Stegosaurus"]
false
Triceratops include?=false
"***array reverse"
Stegosaurus
Velociraptor
Tyrannosaurus
"***arr_dinosor"
Tyrannosaurus
Velociraptor
Stegosaurus
"***array reverse!"
["Stegosaurus", "Velociraptor", "Tyrannosaurus"]
"***arr_dinosor"
["Stegosaurus", "Velociraptor", "Tyrannosaurus"]
"***input dinosor"
IndominusRex
["Stegosaurus", "Velociraptor", "Tyrannosaurus", "IndominusRex"]
"***input dinosor<< "
Indoraptor
"***arr_dinosor"
["Stegosaurus", "Velociraptor", "Tyrannosaurus", "IndominusRex", "Indoraptor", "IndominusRex", "Indoraptor"]
"***arr_dinosor_uniq"
["Stegosaurus", "Velociraptor", "Tyrannosaurus", "IndominusRex", "Indoraptor"]

c:\ruby_pg>
```
Hangfire でタスクをクラスで実装する


## はじめに

[いままでの記事](https://qiita.com/yoh1496/items/b8c65243af214ad0e83d) で実装してきた
タスクのバックグラウンド実行環境、実行周りだけ整えてきましたが、、、
（ソースは下記）

https://github.com/yoh1496/hangfire-dotnet3.1/tree/filter

タスクの実行が式だけ、となかなかにイケていません。

```csharp
BackgroundJob.Enqueue(() => Console.WriteLine($"task #{i}"));
```

これをいい感じに外部クラスに定義して実行できるようにしていきます。

## 実装

### NGな例

こういった形式で app (スケジューラにジョブをキューするプロジェクト)にタスククラスを定義して
キューに入れるとします。一見リッチなタスクが実装できるような気がします。

```csharp
namespace app {
    class AwesomeTask {
        public void Execute(string strText) {
            Console.WriteLine("Super heavy task");
            Thread.Sleep(3000); // wait 3 sec
            Console.WriteLine($"Done: {strText}");
        }
    }
    class Program {
        static void Main(string args[]) {
            // 中略
            int Cnt = 10;
            for (int i = 0; i < Cnt; i++) {
                BackgroundJob.Enqueue<AwesomeTask>(x => x.Execute($"task #{i}"));
                Console.WriteLine($"Enqueued task#{i}");
            }
            // 中略
        }
    }
}
```

が、当然 server (キューされたジョブを実行するプロジェクト)側でエラーになります。

```
System.IO.FileNotFoundException
Could not load file or assembly 'app, Culture=neutral, PublicKeyToken=null'. 指定さ
れたファイルが見つかりません。
```

まぁ当然ですね。server側にappへのリファレンスを追加する必要があります。（追加すれば動きます）
ドキュメントではキューする側と実行する側が同じバイナリになることを想定して書かれているため、
この問題は発生しません。

### 共通クラスライブラリを作成する

server側にタスククラスへの参照を設定する必要があるので、
タスククラスを共通クラスライブラリに定義して、それを参照します。

```sh
$ dotnet new classlib -o common
$ cd server
$ dotnet add reference ../common/common.csproj
$ cd ../app
$ dotnet add reference ../common/common.csproj
```

### 共通クラスライブラリを実装する

本体を実装して、

```csharp
// common/AwesomeTask.cs
using System;
using System.Threading;

namespace common.Tasks {
    public class AwesomeTask {
        public void Execute(string strText) {
            Console.WriteLine("Super heavy task");
            Thread.Sleep(3000); // wait 3 sec
            Console.WriteLine($"Done: {strText}");
        }
    }
}
```

`common.Tasks` namespaceをappから使えるようにします。

```csharp
// app/Program.cs
using common.Tasks;
```

で、実行するとちゃんと実行できました。

```
# サーバーの出力
Super heavy task
Super heavy task
Done: task #9
Done: task #8
2020-04-13 04:51:10 [INFO]  (server.Filters.ReportPerformanceFilter) {"latency":6440,"duration":3009}
2020-04-13 04:51:10 [INFO]  (server.Filters.ReportPerformanceFilter) {"latency":6448,"duration":3016}
```

今回のタスクでは3秒の待機処理を入れているので duration が 3秒近くになっています。

## 終わりに

今回は内容が少ないですが、ちょっとリッチな処理が記述できるようになりました。ということで。
次回はDependencyInjectionでより高度な実装をできるように書こうかな。

今回のコードは↓
https://github.com/yoh1496/hangfire-dotnet3.1/tree/tasklib
SSHコマンドを使って踏み台サーバ経由でリモートログインする(Mac/Linux版)

## 前提環境
- クライアント Mac
- サーバ Linux

## SSHとは
サーバへの安全なリモートログインを提供する仕組み
認証の方法としてパスワード方式と鍵方式の2つがあるが今回扱うのは後者
詳しい仕組みが知りたい場合は以下の記事がオススメ

- [SSHについて理解できたとこまでまとめてみた](https://qiita.com/chonma57/items/5192525ebc3de9ac63e5)
- [SSHの公開鍵認証における良くある誤解の話](https://qiita.com/angel_p_57/items/2e3f3f8661de32a0d432)

## SSHで実行サーバに初回ログインするまでの手順(ざっくり)

1. ローカルマシンで公開鍵・秘密鍵の作成
2. 作成したファイルのパーミッションを正しく設定する
3. 公開鍵`id_rsa.pub`をサーバ管理者に渡し、サーバ管理者はそれぞれのサーバの認証済み鍵リストにその公開鍵を追加する
7. SSHコマンドで踏み台サーバ経由で実行サーバにログインする

## 秘密鍵・公開鍵の作り方

`ssh-keygen`コマンドを用いて作成する

```bash
$ mkdir -p ~/.ssh && cd ~/.ssh
$ ssh-keygen -t rsa
$ ls # 確認
id_rsa id_rsa.pub
```


## ファイルやディレクトリのパーミッションの設定

秘密鍵ファイルと`~/.ssh`ディレクトリのパーミッションを正しく設定する

~~~bash
$ chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_rsa
~~~


## 踏み台サーバ経由でSSH接続

`~/.ssh/config`を以下のように編集する(VScodeで編集する場合は、`code ~/.ssh/config`で可能)


```~/.ssh/config
Host ProxyServerHoge # 好きな名前で
    Hostname      123.456.789.0 # 踏み台サーバのIPアドレス
    Port          1001 # 踏み台サーバのポート番号
    User          taro # ログインユーザ名
    IdentityFile  ~/.ssh/id_rsa
Host TargetServer # 好きな名前で
    HostName      987.654.321.0 # 目標サーバのIPアドレス
    Port          1002 # 目標サーバのポート番号
    User          taro # ログインユーザ名
    ProxyCommand  ssh -CW %h:%p -4 ProxyServerHoge
```

シェル上で以下のコマンドを実行し、接続

~~~
$ ssh TargetServer
~~~

初回はホスト認証で以下のように聞かれるので

```
Are you sure you want to continue connecting (yes/no)?
```

`yes`と入力してEnter

## ローカルマシンのVSCodeからリモートのファイルを編集する
Microsoft製の`Remote - SSH`というパッケージを使用する
内部的にやってることはSSHポートフォワーディング
具体的な手順は以下のよう

1. パッケージ一覧から`Remote - SSH`をインストール
 <img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181667/c2aacaeb-a3d6-d5aa-ccea-08650913ebf7.png">

2. `F1`でコマンドパレットを開き、「Remote-SSH: Connect to Host...」というコマンドを選択する
 <img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181667/4bda6f81-6c76-0601-70a4-63957b3e7907.png">

3. 先ほど`~/.ssh/config`に保存した接続先ホスト一覧が表示されるので、接続したいホストを選択する
4. 接続に成功するまで待ってから、 「フォルダーを開く」をクリックし、自分が開きたいフォルダーを選択する
6. あとはローカルファイルを編集するのと同様



## SSHログインしてコマンドを実行する(余興)

~~~
ssh TargetServer '実行したいコマンド'
# 例
ssh TargetServer 'ls'
~~~

ローカルのシェルスクリプトをサーバ上で実行するなら

~~~
ssh TargetServer　'sh -s' < sample.sh
~~~

という方法もある

##参考文献

[インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識](https://qiita.com/tag1216/items/5d06bad7468f731f590e)
position: stickey;が効かない理由

##やりたいこと

親要素→ `display:flex;`
子要素→ 左右に分けて、片方は記事内容、もう片方はサイドバー

→サイドバーの方をスクロールと一緒に、下に追従するようにしたい

##方法

```style.css
.side-menu {
  position: sticky;
  top: 150px;
}
```

サイドバーの要素にこちらのstyleを当てるだけ。
スクロールしても、上部から150pxの場所に固定されます。

ただ、`position: sticky;`が反映されなかったので、私が試した方法が以下の通りです。


###overflow属性の存在を確認

ほとんどの原因がこれかと思います。

position: stickyの祖先に、`overflow属性`(overflow、overflow-X、overflow-Y)が`visible以外`で指定されてる事です。

祖先は、「対象要素の親、そのまた親、…」など、`全ての親要素`を含みます。


###①jsを使用して確かめる

効かない理由がoverflow属性であるかどうかを、`JavaScript(jQuery)`を使用して確かめます。

以下のコードでoverflow属性値をvisibleに変更しています。実行後にstickyが正しい挙動になる場合、`overflow属性が原因`である事が分かります。

```script.js
$(".side-menu").parents().css("overflow", "visible")
```


###②サイドバーの高さを確認

`サイドバーの高さがメインコンテンツの高さと同じ`だと、スクロール時にサイドバーが追従しません。

今回、サイドバーに背景色があったので、高さが同じでは無い事は理解してましたが、一応試しました。

(ここの確認でデベロッパーツールを使用しましょう)


・`align-items: baseline;`を`Flex-boxの親要素`に設定
・position:stickyを指定している要素にcss`align-self: baseline;`を指定して元の要素の高さになるようにする


こちらを試しましたが、ダメでした。

##原因

結果的に何が原因だったかというと

`"reset.css"`のせいでした！！！

reset.cssにはhtml要素(全体)に

```
overflow-y: scroll; /* All browsers without overlaying scrollbars */
```

がかかってしまっているので、position: stickey;が効かなかった。

私は普段`sanitize.css`を使用していて、`ローカル環境ではposition: sticky; が反映されいて`たのに対し、

`他の人が作成したサイトのページ改修`で、同じコードを挿入したら反映されなかったので原因が不明で苦戦しました。

`reset.css`は便利ですが、予想もしてないstyleが当たっている時があるので注意してください。


position: sticky; はIE11に対応してないらしいです。。。
早くIEがなくなりますように。。。


###参考リンク
https://termina.io/posts/position-sticky-and-overflow-property
https://cheat.co.jp/blog/archives/1896
Linuxでdockerコマンドの補完

Mac利用の場合や、docker-composeはめっちゃ記事ある。Linux + dockerコマンドはなかったのでメモ

```
curl https://raw.githubusercontent.com/docker/docker-ce/master/components/cli/contrib/completion/bash/docker -o /etc/bash_completion.d/docker.sh
```