OmniAICreator/Qiita-1.07M huggingface dataset:
COTOHA で固有名詞の抽出 (PHP)

[COTOHA API Portal](https://api.ce-cotoha.com/contents/index.html) の使用例です。

```php:proper_noun.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	proper_noun.php
//
//						Feb/26/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');
require_once './vendor/autoload.php';

// ------------------------------------------------------------------
include "get_config.php";
include "get_token.php";

// ------------------------------------------------------------------
fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$config = get_config_proc();
$access_token = get_token_proc($config);

// print($access_token . "\n");

$sentence = "特急はくたかで富山に向かいます。それから、金沢に行って、兼六園に行きます。";

$headers = array();
$headers['Content-Type'] = 'application/json';
$headers['Authorization'] = 'Bearer ' . $access_token;

$data = array();
$data['sentence'] = $sentence;
$data['type'] = 'default';

$str_json = json_encode ($data);

$url_target = $config['url_base'] . 'v1/ne';
$request = Requests::post($url_target, $headers, $str_json);

var_dump($request->status_code);

$json_string = $request->body;
$dict_aa = json_decode ($json_string,true);

foreach ($dict_aa['result'] as $key => $unit_aa)
	{
	print($unit_aa['form'] . "\n");
	}

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------
?>
```

get_config.php get_token.php はこちら
[COTOHA API で構文解析 (PHP)](https://qiita.com/ekzemplaro/items/7afc653777e3785c6a02)

実行結果

```text
$ ./proper_noun.php
*** 開始 ***
int(200)
富山
金沢
兼六園
*** 終了 ***
```
COTOHA API で構文解析 (PHP)

[COTOHA API Portal](https://api.ce-cotoha.com/contents/index.html) の使用例です。

```php:parsing.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	parsing.php
//
//						Feb/26/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');
require_once './vendor/autoload.php';

// ------------------------------------------------------------------
include "get_config.php";
include "get_token.php";

// ------------------------------------------------------------------
fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$config = get_config_proc();
$access_token = get_token_proc($config);

// print($access_token . "\n");

$sentence = "特急はくたか";

$headers = array();
$headers['Content-Type'] = 'application/json';
$headers['Authorization'] = 'Bearer ' . $access_token;

$data = array();
$data['sentence'] = $sentence;
$data['type'] = 'default';

$str_json = json_encode ($data);

$url_target = $config['url_base'] . 'v1/parse';
$request = Requests::post($url_target, $headers, $str_json);

var_dump($request->status_code);

$json_string = $request->body;
$dict_aa = json_decode ($json_string,true);

foreach ($dict_aa['result'] as $key => $unit_aa)
	{
	foreach ($unit_aa['tokens'] as $key => $token)
		{
		$str_out = $token['form'] . "\t" . $token['pos'];
		print($str_out . "\n");
		}
	}

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------
?>
```

```php:get_config.php
<?php
// ------------------------------------------------------------------
//	get_config.php
//
//						Feb/26/2020
//
// ------------------------------------------------------------------
function get_config_proc()
{
	$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
	$dotenv->load();

	$config = array ();

	$config['grantType'] = 'client_credentials';
	$config['clientId'] = getenv("CLIENT_ID");
	$config['clientSecret'] = getenv("CLIENT_SECRET");
	$config['url_base'] = getenv("DEVELOPER_API_BASE_URL");
	$config['url_publish'] = getenv("ACCESS_TOKEN_PUBLISH_URL");

	return $config;
}

// ------------------------------------------------------------------
?>
```

```php:get_token.php
<?php
// ------------------------------------------------------------------
//	get_token.php
//
//						Feb/26/2020
//
// ------------------------------------------------------------------
function get_token_proc($config)
{
	$str_json = json_encode ($config);
	$headers = array('Content-Type' => 'application/json');

	$request = Requests::post($config['url_publish'], $headers, $str_json);

//	var_dump($request->status_code);

	$json_string = $request->body;
	$dict_aa = json_decode ($json_string,true);

	$access_token = $dict_aa["access_token"];

	return $access_token;
}

// ------------------------------------------------------------------
?>
```

実行結果

```text
$ ./parsing.php 
*** 開始 ***
int(200)
特急	名詞
は	動詞語幹
く	動詞接尾辞
たか	名詞
*** 終了 ***
```
gcloud app deployが10分でタイムアウトしてしまう問題の解決方法

cloudbuild.yaml に `timeout:1200s`を設定しているのにも関わらず、10分で必ずタイムアウトしてしまう...


原因はGoogle Cloud SDKの方にあったっぽい。。
`gcloud config list --all`で現在のアクティブな構成のCloud SDKプロパティ一覧を見ることができる

`cloud_build_timeout`の項目を見てみると

```
[app]
cloud_build_timeout = (unset)
```

unsetだとデフォルトの10分が適用される。
 
`gcloud config set app/cloud_build_timeout 1200`
などと設定すればOK

```
[app]
cloud_build_timeout = 1200
```

---
参考
[Google App Engine: Build Timed Out during Deployment](https://stackoverflow.com/questions/50046545/google-app-engine-build-timed-out-during-deployment)
[gcloud config list](https://cloud.google.com/sdk/gcloud/reference/config/list)
Cognos Analyticsのプロパティー設定とCase文を使う

[前回の手順](https://qiita.com/y_yasue/items/3b7663eb07597942d82c)でIBM Cloud上のDb2テーブルが扱えるようになったので、種類豊富なグラフがダッシュボードにサクサクと定義が出来た！・・・までは良かったのですが、以下のような事が私にはすぐに分からなかったので共有させてください。

1. 立て軸の範囲を変更したい
2. グラフ色を任意に変えたい
3. 範囲別の件数（個数）を数えたい



#1.立て軸の範囲を変更したい
例えば以下のようなグラフがあったとします。
これを見てパット思いつくのは値のない0V～30Vを表示しなければ、「もっと折れ線グラフの上下差が分かり易そうだ」です。
![img1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/070ea645-06b4-66a7-6b32-3e78e8ff04b4.png)

軸の範囲を変更するため「鉛筆」アイコン-->「変更したいグラフ」-->右上「プロパティー」アイコンの順にクリックします。（実はこの「プロパティー」アイコンの存在に全く気付きませんでした・・ハズカシイ・・）
![img1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/f1879749-1bcf-6e4c-7e0d-90e277b9a259.png)
表示された「視覚化のプロパティー」メニューから「グラフ」を選択します
![img1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/cecaf4bb-898a-990e-7f21-cc6d964b5715.png)
「値軸に原点ゼロを表示」を非選択（オフ）にします。
![img1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/35618f0a-fba4-29c2-ba6c-484e2c65af42.png)
そうすると指定どおり「原点ゼロを表示」しなくなり、下図のようにいい感じに値が見える範囲で調整してくれます。
![img1-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/98495f36-8eb0-870c-c617-c96e0f3002a1.png)
#2.グラフ色を任意に変えたい
見てくれを調整すると、色も変えたくなります。コレも最初「プロパティー」アイコンの存在を知らず時間を無駄にしました。先ほど同様に、「鉛筆」アイコン-->「変更したいグラフ」-->「プロパティー」アイコンの順にクリックします。
表示された「視覚化のプロパティー」メニューから「色」-->「プラス」アイコンの順にクリックします
![img2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/4496160c-389f-aa34-d18a-129d225e4ff0.png)
「パレット名」を指定し、任意の色を選択していきます。
![img2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/648de7fc-0f49-c76e-f9f3-92a57ccd98dd.png)
今回は4色あればよいので、余計な色は「ゴミ箱」アイコンで消した後「保存」しました。
![img2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/d4d845df-1af2-9009-e10b-5b0503c5baf6.png)
#3.範囲別の件数（個数）を数えたい
一番困ったのはコレです。例えば0以上45未満、45以上48V未満、48以上50.2V未満の範囲での電圧個数（件数）をカウントしたかったのです。IFとか ＝ ＜　＞記号とか使うとTrueとかFalseが返ってくるだけで「何か変！」。結局、I〇MのSEの方に以下のように教えて頂きました。（I〇Mの大先生様ありがとうございました。）

電圧を基に式で作ったカラムを追加するためデータモジュールでテーブルを右クリックし「計算」をクリックします。
![img3-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/9e34188e-da87-f3ff-1565-a3e3da55dd79.png)
カラム「電圧」を「式」欄へドラッグ＆ドロップします。
![img3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/12b33e32-62f0-4bc2-8558-baa12f77a819.png)

0Vから45Vまでの電圧個数（件数）をカウントするには

```
case when V between 0.0 and 45.0 then 1 else 0 end
```

のように書きます。
式が正しいか「検証」アイコンをクリックし「式は有効です」が表示されればOKです。
![img3-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188447/a420a866-7838-9e76-bdf3-ce9b363038d2.png)
カスタムフィールドの情報をWordPress REST APIで取得

# カスタムフィールド作成
カスタムフィールドを作成する方法は以下の3つ

 * 既存機能を使う
 * `functions.php`に書く
 * プラグインを使う

少し調べて試してみた結果、WordPress REST APIでカスタムフィールドを扱えてかつ難易度が低いものは「**プラグインを使う**」方法かなと思います。
というわけで今回は[Advanced Custom Fields](https://ja.wordpress.org/plugins/advanced-custom-fields/)というプラグインを使ってのカスタムフィールドの作り、その情報を[ACF to REST API](https://ja.wordpress.org/plugins/acf-to-rest-api/)というプラグインを使いAPIで取得できるようにしていきます。

# Advanced Custom Fields
デフォルトでもカスタムフィールドを作成できますが、Advanced Custom Fields（ACF）を使うと簡単にカスタムフィールドを作成することができるだけでなく、複雑な要件を満たすことも可能になるそうです。
![Advanced Custom Fields](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/aca23a05-4718-4268-b86c-32ed10eb6f2a.png)

## 使い方
プラグインをインストールすると左メニューに「カスタムフィールド」ができます。
ここから「新規追加」をクリックします。
![左メニュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/370297a5-8b87-bb41-f0ad-106315c21872.png)

そうすると「フィールドグループ」と言うものが作成できます。
上部の「タイトルを追加」部分にフィールドグループの名前を付けましょう。
そしてその下の「フィールドを追加」ボタンをクリックしフィールドを作成します。
![フィールドを追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/42ebfdb5-2ada-7248-abc3-f9aee4daca9c.png)

フィールドは色々設定がありますが、最低限「フィールドラベル」「フィールド名」「フィールドタイプ」を入力します。
フィールドを作成したら位置を設定します。これを設定することでどこでこのカスタムフィールドを表示するかを決定します。
![位置](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/35be15fb-3edd-0f73-4a70-aa68b37617fe.png)

設定できたら投稿画面を見てみましょう。
作成したカスタムフィールドが表示されているはずです。

![投稿](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/2c0bf2e8-a5a4-2209-8800-e4ddf80087aa.png)

# ACF to REST API
ACFで追加したカスタムフィールドはデフォルトでは取得出来ません。
（そもそもWordPress REST APIはデフォルトではカスタムフィールドのデータを取得できない。）
これを取得するために、[ACF to REST API](https://ja.wordpress.org/plugins/acf-to-rest-api/)というプラグインを導入します。
![ACF to REST API](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/22080a72-e289-d749-a1d0-d55acdbb0b66.png)

これを入れると投稿取得のAPIで

```json
  "acf": {
    "test1": "xxxx"
  }
```
`acf`という項目が追加されます。

# まとめ
Advanced Custom FieldsとACF to REST APIプラグインを導入して、カスタムフィールドの情報をWordPress REST APIで取得できるようにしました。
既存のWordPressソースをいじることなく簡単にできるのでおすすめです。
なぜオブジェクト指向は理解されないのか？転職エンジニア1000人と話してわかったこと（主に入門資料の違和感から）

仕事上JavaやC#といったオブジェクト指向の言語を使用したシステムの設計や実装の開発経験者と話をする機会が最近多くなって気づいたのですが、バリバリのオブジェクト指向言語をお仕事として書いている人でもかなり初歩の段階でつまづいている人が大多数だということです。
しかも一年未満の初心者ばかりではなく5年以上の実務経験があったり、簡単ではないプログラムの資格を持っていたり、月100万以上の単価だったりと、決して初心者と呼べないエンジニアがあれ？というほど初歩の段階でつまずいているということです。

また、Qiitaの記事でオブジェクト指向の解説の記事を見ても誤解が多いなと感じます。

そんなにも世間のオブジェクト指向の理解度が高くないのはなぜなのか？
その原因は様々だと思いますが、その原因一つ一つを考えるときりがありません。なので今回はその原因を、誰もが最初はお世話になるであろう入門者向け教材にあるとの仮定一つに絞って推察していきます。

## オブジェクト指向入門教材
オブジェクト指向「オブジェクト指向入門」と銘打っている本や動画を見ると、
オブジェクト指向3大要素(カプセル化、継承、ポリモーフィズム)について一通り解説されていて、学習する上で一見何も問題ないように思えます。
でも世間のオブジェクト指向の理解度はあまり高くないのはなぜなのか？　それを意識して見ているうちにある違和感に気づきました。

## <違和感>抽象化の解説が薄い
オブジェクト指向の入門教材でよく目にするのがCar（車）クラスです。
これにいろいろなフィールドやメソッドを定義し、それらを実装していく過程でオブジェクト指向の考えの一部を学習していくというものです。
その中で作られる車クラスの例が以下です。

### 車クラスの擬似コード

```
class Car
  private name     // フィールド
  public Car(name) // コンストラクタ
    name = name
  public go()      // パブリックメソッド
    print name+"が走っています" //標準出力
```

コンストラクタで機種名を定義し、goメソッドを実行すると標準出力に「走っています」的な文を出力するというクラスですが、これと似たようなものが入門教材では比較的よく見られます。
このクラスを色々ゴニョゴニョしてオブジェクト指向3大要素(カプセル化、継承、ポリモーフィズム)の学習をしていくのですが、この時点で違和感を感じました。

そもそも現実社会の車というものは、**走れメソッドを実行させると標準出力に"走っています"という文を出力する機械ではありません。**

主に鉄から出来た無数の精密な部品からできていて、それらが素人には到底組み立てることが出来ないほど複雑に組み合わされています。
そして、ガソリンを入れ、ブレーキを踏みながらキーを回し、ギアを入れてアクセルを踏むとガソリンと空気の混合物がエンジンで燃焼され、そのエネルギーがタイヤの回転力に上手く伝わって物理的に移動する機械です。

それをオブジェクト指向入門書では、車は現実世界の車ではなく、オブジェクト指向3大要素の学習のために適した概念としての「車」という存在になっています。
その過程が抽象化というオブジェクト指向において重要なプロセスなのですが、そのプロセスがすっぽりと抜け落ちているのです。（もしくは数行の簡単な解説で終わっている）

そしてそのままカプセル化やポリモーフィズムといったものの学習に移っていくのですが、その過程でJavaなどの言語仕様も同時に学習し、ある程度自分でコードが書けるようになっていきます。
そうするとJavaのコーディングができるという成功体験をオブジェクト指向を理解したという誤解を生み、その後の学習プランが言語仕様の理解やテクニック、資格の取得などに偏り、本質的なオブジェクト指向を理解しようとする学習の方向から遠ざかってしまうのでは？という解釈です。

実際、抽象化の誤解が一番多いように思えます。また、オブジェクト指向を全く理解していなくても表面上動くシステムは一応作ることは可能だということがオブジェクト指向の学習を妨げているさらなる要因なのかもしれません。

### まとめ

オブジェクト指向入門用の資料は抽象化の解説があまり丁寧にされていない資料が多い。
入門書も実務でも、オブジェクト指向の理解度の向上を必須としないという環境がエンジニアのオブジェクト指向の学習の優先度を下げている。
その結果が、オブジェクト指向の言語を扱っているエンジニアの理解度が高くない原因なのではという推察。
Jetbrains環境でNext.jsを書くと重くなるのでなんとかする

WebstormでNextの開発をしているのですが、lintなのかなんなんかわからないですが、とにかくめちゃくちゃ重い！

コード1行書いてフリーズ。
コード1行書いてフリーズ。

ってなってて、ストレスだったのですが、原因がわかったので対処法を書いてきます。


## 原因
`.next/`以下のhot reloadごとに生成されるファイルに対しても、なんらかの処理が走っていたようです。
![スクリーンショット 2020-02-26 14.42.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82779/15a02831-fb25-88bb-25f7-e4c8cb372396.png)

## 対処法
`.next` を監視対象から外します。

![スクリーンショット 2020-02-26 12.14.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82779/5b0801e7-f13a-e26f-48bd-6337e7f31f00.png)

ファイルツリーから、 `.next` を選択し右クリックで `Mark Directory as` => `Excluded` で直ると思います。

![スクリーンショット 2020-02-26 14.49.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82779/c654e4e2-7fc4-45db-e58b-18f8b60d335a.png)
UnityCollabrateで招待できてもプロジェクトがダウンロードできなかった場合

Unity Collabrateで共同制作者とプロジェクトファイルを共有した際に詰まったので共有します。
(プロジェクトファイルをUnity Collabrateで使用するためにはこちらを参考にしました
https://qiita.com/warapuri/items/bfb2a7cdbbcebaa172cc)

共同制作者にプロジェクトファイルの存在は伝わっているものの、ダウンロードができない状態でした。
結論、チームに招待すると解決しました。

https://id.unity.com/ja/account/edit
上記のURLからUnityIDページに飛び、左側の「組織」を選択します。
自分が作成したプロジェクトを開きます。
「メンバー＆グループ」をクリックします。
![erara.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/f22e886d-b63c-9c01-0917-e952d0d67926.png)
すると、右側に「メンバーを追加」があるのでクリック
![ｆｇｓｄｆｇｓTrt.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/b610ee02-96b7-4fdf-b407-33a40a4fc182.png)
メンバーのメールアドレスと組織の担当を割り当てて招待メールを送ります。
(ちなみに組織の役割ですがこちらを参考にしてください。
https://helpdesk.unity3d.co.jp/hc/ja/articles/115002023468-Unity-%E3%81%AE%E7%B5%84%E7%B9%94%E3%81%A7-%E3%82%AA%E3%83%BC%E3%83%8A%E3%83%BC-%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%83%BC-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AF%E4%BD%95%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%81%8B-%E3%81%A9%E3%82%93%E3%81%AA%E7%AE%A1%E7%90%86%E6%A8%A9%E9%99%90%E3%82%92%E6%8C%81%E3%81%A3%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%81%8B-)
Colfaxでデフォルトで表示されるメッセージが日本語でかえってわかりにくかったので英語に変えた(忘備録）

CourseraのFundamentals of Parallelism on Intel Architectureをやってます。
Intelの並列処理のお勉強をしてます。
使用できる開発環境がメッセージが日本語が出てきてむしろ使いにくいので、英語に変えました。
以下のコマンドを実行すればメッセージを英語に変えられます。

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

```
$ export LC_ALL=en_US.UTF-8
```

日本語に戻すには以下の通り

```
$ export LANG=ja_JP.UTF-8
```

か

```
$ export LC_ALL=ja_JP.UTF-8
```

てか、日本語のメッセージを英語に直したらエラーが治ったので、意外といろんなところで悪さしてるかもしれません。

参考文献

https://software.intel.com/en-us/articles/changing-language-setting-to-see-english-on-a-japanese-os-environment-or-vice-versa-on-linux
Pythonで島探し (paizaランク S 相当) を解く

# 初めに
paizaのレベルアップ問題集を解いていたのですが、模範解答がなかったので自分で作ってみました。
言語はPython3です。

# 問題
Paizaのスキルチェック見本問題「島探し (paizaランク S 相当)」
https://paiza.jp/works/mondai/skillcheck_sample/search-island?language_uid=python3
ログインしないと問題文が見れませんでした。
登録は無料ですぐにできるので、とりあえず登録してみることをおススメします。

# 解答コード
```python:find_lands.py
col, row = map(int, input().split())
map_list = [[0]* (col+2)]
for _ in range(row):
    map_list.append([0] + list(map(int, input().split())) + [0])
map_list.append(map_list[0])

def check(x, y):
    lands = [[x,y]]
    
    while lands:
        x, y = lands.pop()
        map_list[y][x] = 0
        # down 
        if map_list[y+1][x] == 1:
            lands.append([x, y+1])
        # right
        if map_list[y][x+1] == 1:
            lands.append([x+1, y])
        # up
        if map_list[y-1][x] == 1:
            lands.append([x, y-1])
        # left
        if map_list[y][x-1] == 1:
            lands.append([x-1, y])

count = 0
for r in range(1, row+1):
    for c in range(1, col+1):
        if map_list[r][c] == 1:
            check(c, r)
            count += 1

print(count)
```

# 参考
https://maro28.com/paiza-s-rank-mod7

# まとめ
初めでQiitaの記事を書いてみましたが、シンプルで使いやすくていいですね！
これからちょくちょく使っていけたらいいなと思います。
swift 誕生日から今日まで何日目か？

swiftのカレンダーアプリ作成でUICorectionViewで縦にスクロールしてカレンダーを表示する際に対応する開始日付から今日までの日数によって自動で当日へスクロールさせる時に下記の計算が必要だったので投稿します。他に良い方法があれば御伝授頂きたいとおもいます。よろしくお願いします。

```swift
let dateFormater = DateFormatter()
dateFormater.locale = Locale(identifier: "ja_JP")
dateFormater.dateFormat = "yyyy/MM/dd HH:mm:ss"
let date1 = dateFormater.date(from: "2015/10/01 12:12:12")
let date2 = Date()
let elapsedDays = Calendar.current.dateComponents([.day], from: date1!, to: date2).day
print(elapsedDays)
```
Dataikuで独自のPython環境を利用する

# Dataikuで独自のPython環境を利用する

## はじめに

Dataiku Data Science Platform（Dataiku DSS）を利用する方法として、[Dataiku DSSをVirtual Boxを使って利用する方法](https://qiita.com/goya1021/items/0b244ffec4a971b0f736)をご紹介しました。
Dataikuでは、pyenvやvirtualenvのような、Python環境を管理する仕組みが用意されています。今回は、Dataiku DSSで独自のPython環境を利用したいという場合に、その機能を利用して、独自のPython環境を作成する方法と、作成したPython環境をnotebookで使用する方法について紹介します。

## 独自のPython環境を作成する

#### 1. Code Envs画面を表示します

Dataikuにログインした後、画面右上のキューブアイコンをクリックして、［Administrator］メニューをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/f1c5f27e-fa12-0f83-e150-dac4f1cdcc45.png)
その後、画面右上にある［Code Envs］タブをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/9cccd13c-53b5-a373-4194-0d96bd85bb76.png)

#### 2. 独自のPython環境を作成します

画面右上にある、［NEW PYTHON ENV］をクリックします。その後、表示される［New Python env］画面で、次の設定を行います。
  
- Deployment type：Managed by DSS(recommended)
- Name：（英数字で適宜入力します）
- Python：必要なPythonバージョンを指定します。例えば、Python 3.6を用いる場合は、［Python 3.6 (from PATH)］を指定します。
- Conda：チェックなしで大丈夫です。Condaを使用したい場合はチェックします。
- Mandatory packages, Jupyter：いずれもチェックしたままとします。
  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/4300efa2-aaaa-6cae-325e-d8735d58f7c5.png)
  
設定が完了したら、［CREATE］ボタンをクリックします。独自のPython環境が作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/579b8bde-f8cb-d75c-cc75-7f3cd4a631e7.png)

**留意点**  

- Dataikuをインストールした環境において、［Python］で指定したバージョンのPythonはインストール済みで、かつそのバージョンの実行ファイルのパスが環境変数PATHに設定されている必要があります。Virtual Box版Dataikuアプライアンスを利用されている場合は、Python2.7とPython3.6がすでにインストールされていますので、そのバージョンは利用することができます。
- プロキシ環境で独自のPython環境を作成する場合は、あらかじめDataikuのAdministrator画面でプロキシ情報を設定してください。詳細は[こちら](https://qiita.com/goya1021/items/6eaa48080ed91099b70e)を参照してください。

## 独自のPython環境に新たなPythonライブラリをインストールする

#### 1. ライブラリをインストールするPython環境を選択し、ライブラリインストール画面を表示します
Code Envsタブで表示されるPython環境一覧の中で、ライブラリをインストールするPython環境に該当する［Name］のリンクをクリックします。クリックした後、画面左側の［Packages to install］をクリックします。

#### 2. インストールするライブラリを指定します
画面右下の［REQUESTED PACKAGES(PIP)］でインストールするライブラリを設定します。設定した後、［SAVE AND UPDATE］ボタンをクリックします。ライブラリがインストールされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/0da312d1-0823-d52e-290b-7e146922d052.png)

インストールされているか確認するには、画面左側の［Installed packages］をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/e545784a-cd58-d2a9-bb9e-4c29425bc947.png)

**補足**
［ADD SETS OF PACKAGES］ボタンをクリックすることで、機械学習で用いる標準的なライブラリを指定してインストールすることもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/aed36d28-c6dd-d0a0-ef14-92630dd584c1.png)

## 独自のPython環境をnotebookで利用する

Dataikuのnotebookで独自のPython環境を利用する場合は、次のようにします。

［New Python notebook］画面の［Code env］で独自のPython環境を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/a6c68a5f-17bf-574d-2b6a-78ebb48321ff.png)

あるいは、notebookのメニュー［Kernel］>［Change kernel］から独自のPython環境を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417992/c3c7112c-c4c5-f00b-0064-a954fc6272ff.png)

## さいごに

Dataiku DSSで独自のPython環境を作成し、notebookで利用する方法について紹介しました。
プロジェクトごとに独自のPython環境を利用したい場合に、よろしければご参考ください。
画像の回転(Exif Orientation)タグを削除する

iPhoneなどのカメラでカメラを傾けて撮影すると、Exif Orientationタグが記録され、MacのPreviewなどのアプリでは画像の向きを補正して再生される。 画像処理では時折邪魔になるため、Orientationタグを削除する。

動作環境： macOS Mojave (10.14.6)

## 準備

```bash
$ brew install exiftool
$ exiftool -ver
11.45
```

## コマンド
heicフォルダに画像(.heic)があり、その中にある画像全てのOrientationタグを削除する場合

```bash
exiftool -Orientation= ./heic/*
```
Visual Studio Codeでユーザースペニットで入力できない記号を入力する方法

エスケープ文字がわからなかったので、メモ
記号として入力したい記号の前に「\」を入力すると記号として認識されます。
これでダブルクオーテーションも入力できるよ！

```c.json
{
	"printf": {
		"prefix": "p",
		"body": [
			"printf(\"%d\\n\", $1);"
		]
	}
}
```


**参考文献**
Visual Studio Code for Mac ユーザー独自のスニペット定義(Emmet編) - Qiita
https://qiita.com/t_732_twit/items/6e37a6bdfe8ff3f8d76d
Gmailを無料で使わせていただいている限り手厚いサポートは受けられないという小話

現在の状況：通常の使い方ではないと機械判定されGoogleアカウントへのログインをブロックされた。
（unusually usageなんちゃらというメッセージが表示された気がする）

原因：短期間にメールマガジンを大量掃除

2010年春に作成したGmail由来のGoogleアカウントでしたが、

- 楽天市場から大量に送信された過去のメールマガジン
- タワーレコードから大量に送信された過去のメールマガジン

容量的には合計1GB程度を1日目夕方20分、翌日午前20分程度、検索→ゴミ箱→ゴミ箱全消去の作業を行っていたところ
Googleのセキュリティデーモンにより普通ではないと判定され以後ログインをブロックされました。

一応ブロック数分前に連携済みメールアドレスに「削除多すぎ～危ないよ。保護してください」
というメールが来ていたようでしたが作業中につき気づけませんでした。

たしかに不正ログインされているような行為と言われても仕方ないです。
不正ログイン・不正削除から一般市民を守るサービス提供側としての言い分も当然あるでしょう。

くれぐれも皆さんはGmailの短時間大量消去はおやめください。
さもないと不正ログインと勘違いされログインブロック、アカウント復元対応不可になります。

24時間経過しましたがアカウント復元はできていません。

グッバイ10年。

ずいぶん長いこと個人情報であるメールの閲覧権をGoogleに渡していましたが緊急電話サポート窓口もありません。

無料で使わせていただいていた限り諦めるしかないようです。

月末までに暇を見つけて件名やメールアドレスをクリックすると自動検索するChrome拡張機能を1KB以内で作成しようと思う。


↓アマチュアによるスクリプトなので改善希望。
from は予約語なのかもしれない。


```JavaScript:TamperMonkeyGmail.js
// ==UserScript==
// @name         Gmail クリック検索
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match   https://mail.google.com/mail/u/*
// @grant        none
// ==/UserScript==


//URLが変更されるたびにこのスクリプトが走り毎回3個イベントリスナが埋め込まれる
//ノートPCやタブレットなどバッテリーを使用したハードウェアには非常に不向き。浪費します。

//セレクターは適当です。GMAIL側の仕様変更があると機能しなくなります

window.addEventListener("hashchange", function () {

    var subject = document.querySelector('div[role="main"] h2');
    var from = document.querySelector('div[role="main"] h3 span[email]');
    var to = document.querySelectorAll('table > tbody > tr > td > table > tbody > tr > td > div > span')[1];
    var searchbox = document.querySelector('input[aria-label="メールを検索"]');
    var searchbutton = document.querySelector('button[aria-label="メールを検索"]');
    var search = function (string) {
        searchbox.value = string;
        searchbutton.click();
    };


    //全メールを対象にして検索したい場合はクリック
    //受信ボックスのみを対象にして検索したい場合は SHIFT KEY を押しながらクリック

    //件名
    //環境に合わせて正規表現で文字列整えてあげるといいかも
    subject.addEventListener('click', function (e) {
             if (e.shiftKey) {
            search(`label:inbox subject:("${this.textContent.trim()}")`);
        } else {
            search(`subject:("${this.textContent.trim()}")`);
        }
    }, false);

    //送信元
    from.addEventListener('click', function (e) {
        if (e.shiftKey) {
            search(`label:inbox from:("${this.textContent.trim(e)}")`);
        } else {
            search(`from:("${this.textContent.trim(e)}")`);
        }
    }, false);

    //送信先
    to.addEventListener('click', function (e) {
        if (e.shiftKey) {
            search(`label:inbox to:("${this.textContent.replace(/^To /g,'').trim()}")`);
        } else {
            search(`to:("${this.textContent.replace(/^To /g,'').trim()}")`);
        }
    }, false);


}, false);


```
transproxy 構築メモ

[前回の構築](https://qiita.com/kwi/items/b7c770d6b92c16c334fb)のリプレース。

Raspbian Buster Lite を balenaEtcher で書き込む

root に `ssh` という空ファイルを置く

Downstream 側用に USB ethernet dongle を追加する

`apt-get dist-upgrade -y`

`apt-get install` しておく

- `firmware-linux-free` : USB ethernet dongle のため
- `iptables-persistent` : nat rule を保存したい
- `dnsmasq` : Downstream 向け
- `screen` : 作業用

raspbian では最終的には dhcpcd の制御下にあるので、dhcpcd で eth1 を static 割り当てにする

```dhcpcd.conf
interface eth1
static ip_address=192.168.0.2/24
static routers=192.168.0.2
static domain_name_servers=192.168.0.2
```

ip routing を有効にする

```text:/etc/sysctl.d/98-nat.conf
net.ipv4.ip_forward=1
```

masquerade のルールを入れる。

```bash
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
```

`/etc/init.d/iptables-persistent save` で保存しておく。

再起動してここまでの設定が反映されることを確認する。

`golang-go` をインストールして、`github.com/wadahiro/go-transproxy` をビルドする

systemd unit を書いて enable する

```
[Unit]
Description=transproxy
After=network.target

[Install]
WantedBy=multi-user.target

[Service]
Environment=http_proxy=http://proxy.server:8080
Environment=https_proxy=http://proxy.server:8080
ExecStart=/home/pi/go/bin/transproxy -private-dns 192.168.0.2 -public-dns 8.8.8.8
KillMode=process
Restart=on-failure
```

-------
だめだった。IPv6->IPv4 fallback が待っていられない。DNS も透過 proxy したいという気持ちは理解した気がする。

どうしようかな。
WindowsでOpenSSHでSFTPサーバを立てる場合の設定

# 何？
WindowsServerでファイルをSFTPで連携したかったので、
OpenSSHでSFTPサーバを立ててみたので、その設定を記載する。

# 要件

- 公開鍵認証、パスワード認証不可
- SFTPで特定のディレクトリのみアクセス可 
- SSH接続不可　→　SFTPルートディレクトリ以外見せたくない
- SSH転送でアクセス可
- 特定ユーザでのみSFTPログイン可

# 設定手順

1. OpenSSH インストールし、サービス登録
手順は省略。

2. SFTPログイン用のグループとユーザを作成
アクセス制御はグループ指定で行う予定のため。

3. アクセスユーザの公開鍵登録
下記ファイルにアクセスユーザの公開鍵登録
C:\Users\(SFTPログイン用ユーザ)\.ssh\authorized_keys
SFTPログイン用ユーザのauthorized_keysにのみ公開鍵登録することでアクセス制御

4. OpenSSHの設定ファイルを修正
Windowsで、Web上でよく見る手順でOpenSSHをインストールしたならば「C:\ProgramData\ssh\sshd_config」に設定ファイルが作成されているはず。

sshd_configの設定
修正した差分部分のみ

```config
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# ファイルにINFOレベル以上のログ出力
# ログ出力先はC:\ProgramData\ssh\logs
SyslogFacility LOCAL0
LogLevel INFO

# Authentication:

#MaxSessions 10

#PubkeyAuthentication yes
# 公開鍵認証
PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# パスワード認証不可
PasswordAuthentication no

# GSSAPI options
#GSSAPIAuthentication no
#Banner none

# override default of no subsystems
#Subsystem sftp sftp-server.exe
# SFTPサーバはsshdのプロセスで動作
Subsystem sftp internal-sftp


# Example of overriding settings on a per-user basis
#Match User anoncvs
#	PermitTTY no
#	ForceCommand cvs server

# Administratorのアクセス許可する公開鍵登録ファイルの特別パス指定は無効
#Match Group administrators
#       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

# SFTPログイン用のグループの場合、sftpログをファイルへログ出力
# アクセス可能なルートディレクトリに「C:\SFTP_ROOT\」を設定
Match Group SftpGroup
	ForceCommand internal-sftp -f LOCAL0 -l INFO
	ChrootDirectory C:\SFTP_ROOT\
```

# うまく動作しない所
WindowsServer2016stdでSFTPサーバログがログ出力されない。

Windows10ならば、「C:\ProgramData\ssh\logs\sftp-server.log」にログ出力されるが、
WindowsServer2016stdではログ出力されない。調査中。

※2020/03/18追記
>WindowsServer2016stdではログ出力されない。調査中。

WindwosServer2016stdでログ出力されない件解決しました。
SFTPログインユーザにログ出力フォルダの権限が無いためでした。
Railsでdeviseを導入する

チラ裏レベルのなぐり書きを世に放って申し訳ない。

# 方法
```terminal
$ vim Gemfile　=> gem "devise" を追加
$ bundle install
$ bundle exec rails g devise:install

以下を設定する。
===============================================================================
Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views
===============================================================================

設定後、

$ bundle exec rails g devise:views
$ bundle exec rails g devise Account

# 必要ならここでmigrationファイルにフィールドを加える

$ bundle exec rails db:migrate
```
XCTest(Unit Test)で明示的に書かれていないいくつかの仕様

単体テストで画面遷移もやっちゃおう、と思って格闘したときの覚書です。

# アプリの起動はテスト実行時一回のみ行われる
テスト対象のアプリは、テストの実行時一回のみ行われます。

```swift
@testable import app
```

つまりAppDelegateは初回のテストケースで一度だけ走ります。
各テストケースでは走リません。

# デフォルトのテストケースの実行順序はクラス名順 -> テストケースメソッド名順
テストケースの実行順序は名前の順になります。
個人的にはクラスの中で、上から下に舐めていって欲しい気持ちがあったのですが、それは仕様みたいです。
テストケースの実行をランダムにするオプションはあるんですが、デフォルトは名前順。

基本テストケースの実行順序に依存するようなテストコードを書くな、というのはあるんでしょうけど、
何らか制約が生じてしまうときは、名前で縛るしかないのかなあという感じです。
たとえば`test_1_何かの確認`、`test_2_何かの確認`みたいな。

# あるテストケースでアプリに加えた変更は次のテストケースに引き継がれる
テストケースのたびにアプリの状態はイニシャルしてしまって構わないのですが、
多分パフォーマンスの問題だと思うんですが、イニシャルはされず、次に引き継がれます。
別にModelクラスならそんなに困ることはないんですが、UIが関わるクラスだと結構キツイです。

tearDown()でちゃんと後始末して、常にきれいな状態で次のテストケースに引き継げるように記述できれば良いんですが、
テストのことをあまり考えずにつくったアプリだとキツイときもあって、みんなどうしてんだろうなあって思いました。

# Class単位にsetup()/tearDown()ができる
これは明示的に書かれていないということはなく、
テストの本読むとXCTestのライフサイクルとしてちゃんと書かれていますが、
サンプルコートの中になくて、使わないので盲点になっていました。

XCTestCaseのclassメソッドsetup()/tearDown()はテストclassに対して一回。
通常のsetup()/tearDown()はテストケースに対して一回。
何を言っているのかというと、

```swift:XCTestCaseを継承したクラス
    class override func setUp() {
        <#code#>
    }
    
    override func setUp() {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }
    
    class override func tearDown() {
        <#code#>
    }
```
この一番上と一番下のクラスメソッドはクラス中で一回だけ、
二番目、三番目のメソッドは各テストケースごとに実行されます。

僕は画面遷移する前にアプリが持っている情報をテスト前に退避して、
テストでは仮のデータ突っ込んでめちゃくちゃにして、テスト後は退避したものをきれいに戻す、みたいな書き方をしようとしたんですが、
使ってみたらクラスメソッドだと子クラスの中に書いた変数が使えないので、退避先がなくて実現しませんでした。

本気であまり使い所ないかもしれませんね……

# UIテストだとアプリ自体の起動・終了が制御できる
アプリの状態をイニシャルできないというのは、UIテストだったら、アプリの起動・終了が制御できるので、多少は良いかなと思います。

```swift
XCUIApplication().launch()
```

画面遷移ならむしろUIテストで書くのが筋なんですかね？
【備忘録】PostgreSQLを導入してみたのでまとめてみた

## Introduction

ずっと`MySQL`ばかりしか使っておらず、初めて `PostgreSQL`を触りはじめてみたので
備忘録としてまとめを記載


## 環境
Date: 2020/02/25
OS  : macOS Catalina (10.15.3)

## インストール方法

### Homebrew

本手順は `Homebrew` を使ってインストールを行います。
※もしまだの方は参考文献をご参照ください

```terminal
$ brew install postgresql
```

### 初期化

```terminal
$ initdb /usr/local/var/postgres -E utf8
```

導入時にもし下記のような文がでるなら、`/usr/local/var/`配下にある`postgresql`ディレクトリを削除して、もう一度同じコマンドを入力してみましょう

```terminal
initdb: directory "/usr/local/var/postgres" exists but is not empty
If you want to create a new database system, either remove or empty
the directory "/usr/local/var/postgres" or run initdb
with an argument other than "/usr/local/var/postgres".
```

### バージョン

```terminal
$ postgres --version

postgres (PostgreSQL) 12.1
```

### 起動

```terminal
$ pg_ctl -D /usr/local/var/postgres -l logfile start
```

### 一覧

```terminal
$ psql -l

                             List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges
-----------+----------+----------+---------+-------+-----------------------
 postgres  | username | UTF8     | C       | C     |
 template0 | username | UTF8     | C       | C     | =c/username          +
           |          |          |         |       | username=CTc/username
 template1 | username | UTF8     | C       | C     | =c/username          +
           |          |          |         |       | username=CTc/username
(3 rows)
```

### 接続

```terminal
$ psql -U username postgres

psql (12.1)
Type "help" for help.

postgres=#
postgres=#
```

## 参考文献

- [macOSにPostgreSQLをインストール](https://kentama.hatenablog.com/entry/2017/04/23/222335)

- [MacにPostgreSQLをインストール](https://qiita.com/_daisuke/items/13996621cf51f835494b#db%E3%81%AE%E4%BD%9C%E6%88%90)
【Linux】teratermでDBに接続してSqlplusコマンドを打った後DB(oracle)にログインするまで

###【Linux】teratermでDBに接続してSqlplusコマンドを打った後DB(oracle)にログインするまで

####SQLDeveloperから応答が帰ってこない
SELECTもUPDATEも固まってしまって更新不可能。
直接DBに問い合わせてみることにする。


#####Teraterm
DBのいるip(XX.XX.XX.XX)
サーバーユーザ
サーバーパスワード
portはサーバ設定に合わせる

#####ログイン後
sqlplusを入力エンター
DBユーザ
DBパスワード
を順番に入力する

入れた！SQL打ってみることにする。To be continue...

######課題：sqlplusを入力エンター後めっちゃ文字化けするのなんで？
Teraterm設定は両方UTF-8だった
アプリにGoogleフォームを設置したら、本当にメッセージが来た

#はじめに
環境は以下の通り
Ionic4 + Angularで開発したアプリ

実際のアプリはこちら:point_down:
[Apple Store](https://apps.apple.com/jp/app/性活カレンダー/id1484151444?mt=8)

[Google Play](https://play.google.com/store/apps/details?id=com.hCalendar.app)

**アプリにお問い合わせフォームを設置したら、本当にユーザーさんからメッセージが来て驚いたお話である。**

#アプリに即席でお問い合わせフォームを設置するには
結論としては、**Googleフォームを使おう！**
本当はラインのトーク画面みたいなUIで、送信されたメッセージが全て開発者に届くって感じにしたかったが、、、結構めんどくさそうだったのでやめたww。

そこで何かいい方法は無いかと考えた結果、、、Googleフォームがあるじゃないか！！
っとなりました。。

<img width="302" alt="スクリーンショット 2020-02-26 17.00.49.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/a1c8f3fe-d292-8d98-4f02-c0b77f0e8e46.jpeg">

普通にリンクを貼っただけです。。。

<img width="287" alt="スクリーンショット 2020-02-26 17.27.15.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/7548963d-3e3f-897c-e9a8-ee8eebecf5c2.jpeg">

めっちゃシンプルにこれだけです。



#即席でもフォームを設置した方が良い理由
①レビュー欄にバグ報告をされない可能性が高い
:point_right:低評価につながるバグ報告を、レビュー欄以外にさせる

②ユーザーの声が届くのでアップデートの参考にできる
:point_right:100％ユーザーの望むものにする必要はないが、参考にはなる

③マジでメッセージが来ると面白い
:point_right:エェー本当に使ってる人いるんだ！！っと言う衝撃が、励みになったり

#ある日、本当にメッセージが来てた。。。
これはプッシュ通知の結果をFirebaseコンソールで確認した画像だが、だいたいユーザー数が２００人ぐらい。

<img width="957" alt="スクリーンショット 2020-02-26 17.44.29.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/41d7b3ae-66fd-1f6f-0a49-0db7481c5bab.jpeg">

で、実際に４人程のユーザーさんからメッセージが来て、応援メッセージとご意見（こんな機能欲しい！とか）が半々ぐらいでした。

けっこうやらかしたバグがある状態で、ストアから配信をしてしまった経験があるのだが。。
**早速応援メッセージをくれたユーザーさんから、けっこう詳細にバグの内容を教えてもらえました！！**

#最後に
ダサくてもGoogleフォーム付けとけば、いいことあるかもです。
each文とrender のcollectionオプション

#はじめに
掲示板アプリを作成しているのだが、
いいね機能実装時、

https://qiita.com/hayabusa3703/items/2b916e652a1dc85bb6e3

を参考に（ほぼ写して）、コードを書いていた。

機能自体の実装は成功したが、ビューでの表示が思うようにいかない。

各投稿一つ一つに、全ての投稿のイイねボタンがついてしまった。

これに対処するにあたって、
今までおざなりにしていた、renderとそのオプションについての理解がかなり深まったので、備忘録として残す。

##バージョンなど
ruby 2.5.1
rails 5.2.4.1
bootstrap 4.4.1
haml-rails 2.0.1
jquery-rails 4.3.5


##コード

```posts_controller.rb
def index
    @posts = Post.all.includes(:user).order('created_at DESC')
  end
```

```index.html.haml
.events__wrapper.row
        /# each文
      - @posts.each do |post|
        .events__content.col-sm-6.col-md-3.mb-3
          .card{id: post.id}
            %label.m-1
              - if post.image
                %img.card-img-top{src: "#{post.image}"}
              - else
                %img.card-img-top{src: "/public/noimage.jpeg"}
              .card-body.event
                %h5= link_to "#{post.title}", post_path(post.id), class: "event-title stretched-link text-decoration-none"
                .event__name 
                  #{post.user.name} さん
                .text-right
                  = l post.created_at, format: :long
                  = render partial: '/posts/posts', collection: @posts, as: :post  
```


each文の中に、renderとオプションでcollectionを使っている形になっている。

この書き方だと、先述の通り、一つのpostにイイねボタンがいくつもついてしまう。

原因を調べていると発見した、とてもrenderとオプションについてまとめてあるqiitaの記事があるので共有しておきます。

https://qiita.com/takeru56/items/299850d0f054ce107e21

この記事を読んで、collectionオプションは変数に自動でeachメソッドを使ってくれていることに気付き、renderの記述を修正。

```index.html.haml
= render partial: '/posts/posts', locals: {post: post}
/# これにより、元々あったeach文の中の変数postを部分テンプレートに渡せる。
```

##まとめ
イイね機能の実装を通じて、
collection, locals, object, as, などのオプションの理解が深まった。

エラーの数だけ成長がある！！！
Boto3を使って、S3のファイルリストから1000件以上のPrefixを取り出す

備忘録として

S3からのPrefixはデフォルトで1000件までしか取得できないので、1000件以上ある場合はpaginatorを利用する。

[Boto3 ドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html)

```python
import boto3

# Create a client
client = boto3.client('s3', region_name='us-west-2')

# Create a reusable Paginator
paginator = client.get_paginator('list_objects')

# Create a PageIterator from the Paginator
page_iterator = paginator.paginate(Bucket='my-bucket')

for page in page_iterator:
    print(page['Contents'])
```

ドキュメントのデフォルトでは以上の通りで、page_iteratorのリストの中に、1000件ずつのPrefixのリストが格納されています。
それらを扱いやすくするために、展開してしまいます。

```python
import boto3
import itertools

client = boto3.client('s3', region_name='us-west-2')
paginator = client.get_paginator('list_objects')
page_iterator = paginator.paginate(Bucket='my-bucket')
contents = list(itertools.chain.from_iterable(page_iterator))
```

これで、1000件以上のprefixを扱うことができます
「結局アクセスログってどれくらい保存しておけばいいの？」に答える関係法令

# これは何
アクセスログとかどれくらいの期間保存すればいいかな？というのを検討した資料。
結論でいうと以下のように解釈してます

* アクセスログは90日
* 監査ログやリリース履歴は1年

# この資料見ておけばOK
IPAの資料にまとまっていました。
https://www.ipa.go.jp/files/000052999.pdf

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/0e8a3850-729d-29d6-65d9-ad51f9852f47.png)


以下はそこからちょっとだけ掘ってみたものです。

# アクセスログについて

### 刑事訴訟法における記述
- 刑事訴訟法 第百九十七条 ３「通信履歴の電磁的記録のうち必要なものを特定し、三十日を超えない期間を定めて、これを消去しないよう、書面で求めることができる。」
    - もうちょっと詳しく原文を読む　http://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=323AC0000000131_20170713&openerCode=1#687
        - ○３　検察官、検察事務官又は司法警察員は、差押え又は記録命令付差押えをするため必要があるときは、電気通信を行うための設備を他人の通信の用に供する事業を営む者又は自己の業務のために不特定若しくは多数の者の通信を媒介することのできる電気通信を行うための設備を設置している者に対し、その業務上記録している電気通信の送信元、送信先、通信日時その他の通信履歴の電磁的記録のうち必要なものを特定し、三十日を超えない期間を定めて、これを消去しないよう、書面で求めることができる。この場合において、当該電磁的記録について差押え又は記録命令付差押えをする必要がないと認めるに至つたときは、当該求めを取り消さなければならない。
        - ○４　前項の規定により消去しないよう求める期間については、特に必要があるときは、三十日を超えない範囲内で延長することができる。ただし、消去しないよう求める期間は、通じて六十日を超えることができない。

**【要するに】**最大で６０日ログ保存しろや、と警察や検察に言われることがあるよってことと解釈

### サイバー犯罪に関する条約における記述
* サイバー犯罪に関する条約 第十六条 ２「必要な期間（九十日を限度とする。）、当該コンピュータ・データの完全性を保全し及び維持することを当該者に義務付けるため、必要な立法その他の措置をとる。」
    * もうちょっと詳しく原文を読む https://www.mofa.go.jp/mofaj/gaiko/treaty/pdfs/treaty159_4a.pdf
    * 締約国は、ある者が保有し又は管理している特定の蔵置されたコンピュータ・データを保全するよう当該者に命令することによって１の規定を実施する場合には、自国の権限のある当局が当該コンピュータ・データの開示を求めることを可能にするために必要な期間（九十日を限度とする。）、当該コンピュー
タ・データの完全性を保全し及び維持することを当該者に義務付けるため、必要な立法その他の措置をとる。締約国は、そのような命令を引き続き更新することができる旨定めることができる。

**【要するに】** 条約で最大で９０日保存してくれと権限のある当局（警察や検察？）がいってもよいとされているみたい

# 監査ログについて

監査ログとかリリース履歴とかのログは以下の記述に従えば良さそう。

* PCI DSS 監査証跡の履歴を少なくとも 1 年間保持する。少なくとも 3 か月はすぐに分析できる状態にしておく
* NISC「平成 23 年度政府機関における情報システムのログ取得・管理の在り方の検討に係る調査報告書」 政府機関においてログは１年間以上保存
* SANS「Successful SIEM and Log Management Strategies for Audit andCompliance」 1 年間のイベントを保持することができれば概ねコンプライアンス規制に適合する。

**【要するに】** 監査証跡は１年間保存必要だが、通常のアクセスログなどはこれに該当しなさそう。本番更新履歴とかはこれくらいは残していくことになりそう。

# 実際保存できるかも確認しておきましょう

保存設定を90日にしていても、ディスクフルとかで保存できていなかった、みたいなことがありえます。
ちゃんとディスクスペースがあるかとか、そういうところも確認しておきましょう！
【Atom】便利な検索機能紹介（一括検索、ファイル名検索）

## この記事は
コードエディタ・Atomユーザー向けに、便利な検索機能を紹介します。
これを読めば、**ファイル内検索、一括検索、ファイル名検索**ができるようになります。
使えるようになるとかなり便利なので、まだ知らないという方はぜひ読んでみてください。

## ファイル内検索
文字を検索したいファイルを開き、**Ctrl + F** を押します。
すると、下記のように検索欄が出てきます。
<img width="1098" alt="スクリーンショット_2020-02-26_13_01_05.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/580339b8-1af5-6ee5-d460-e4a5ed9f2718.jpeg">
ここに検索したい文字列を入れて検索すると、合致した箇所と数が表示されます。
<img width="1098" alt="スクリーンショット_2020-02-26_13_05_57.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/f3777ff8-fb82-648e-eac5-8e5270d4f16f.jpeg">
欄の右にある**「Find」**を押せば合致する文字列を1つずつ追うことができ、
**「Find All」**を押せば合致する文字列が全て目立って表示されます。

### 置換
余談ですが、検索欄の1つ下の欄も使うと、文字列の置換を行うことができます。
<img width="1098" alt="スクリーンショット_2020-02-26_13_08_52.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/7d47a845-bbef-70a2-a440-9ba76f0b0b44.jpeg">
※**「Replace」**で1つ置換、**「Replace All」**で全て置換

## 一括検索
1ファイルだけでなく、ディレクトリ全体に検索をかけたいときに使います。
Atom画面で、**Ctrl + Shift + F** を押します。
すると、2つだった欄が3つに増えます。 
<img width="1098" alt="スクリーンショット_2020-02-26_13_15_18.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/495995de-2912-82c5-31fe-450a89a1eae8.jpeg">
この状態で文字列を入力し、**「Find All」**を押すと、**Project Find Results**というタブが開いて該当ファイルと該当箇所を一覧で表示してくれます。
<img width="1098" alt="スクリーンショット 2020-02-26 13.18.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/1a59d3b7-e4b3-d277-7327-f72be634a4db.png">

### 検索範囲を絞る
ちなみにディレクトリ全体でなく、検索範囲（フォルダ）を絞りたいときもあると思います。
そんなときは、**3つ目の欄に検索したいフォルダを指定**して検索すればOKです。
<img width="1098" alt="スクリーンショット_2020-02-26_13_20_04.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/0d31d717-9963-ac39-4e6d-65fd45e6a9d1.jpeg">

#### 検索したファイルを開いたままにする方法
上の状態だと、検索にかかったファイルを1つまでしか開けません（1つ開いた後に別のを開くと、1つ目が閉じてしまう）。

これがどうにも不便に感じていたのですが、最近解決法がわかりました。
開いたままにしたいファイル名のところで右クリックし、**「Keep Pending Tab」**を選択します。
<img width="1171" alt="スクリーンショット_2020-02-26_13_25_12.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/04be219c-5aed-4718-7914-69fcc2cfc975.jpeg">

すると、斜体だったファイル名が正常になり、開いたままにすることができます！

## ファイル名検索
Atom画面で **Ctrl + P** を押します。
すると、こんな感じで検索枠が開きます。
<img width="1098" alt="スクリーンショット_2020-02-26_13_28_06.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/88811df2-a76a-b1cc-94df-e021e69b86f4.jpeg">
あとは探したいファイル名を入れて、下から選んで開くだけ。

以上です！
Spreadsheet.getRangeメソッドは行・列指定でRangeを取得できない。

IDやURI指定でスプレッドシートを開く場合、
　SpreadsheetApp.openById([IDまたはURI])
としますが、その戻り値はSpreadsheetオブジェクトです。

ただ、SpreadsheetオブジェクトのgetRangeメソッドには
A1形式指定かR1C1形式指定しか用意されていないので、
行列指定でRangeを取得したいときに困りました。

そこで。
SheetオブジェクトのgetRangeメソッドは
sheet.getRange("A1"); //A1形式
や
sheet.getRange(R[1]C[1]); //R1C1形式
や
sheet.getRange(1, 1) //行・列指定
とバリエーションに富んでいるので、これを利用しました。


```gas:例
  var ss = SpreadsheetApp.openById("spreadsheetnoidwoshitei");
  var sheet = ss.getSheets()[0];
  sheet.getRange(1, 1);
```

どうやら、SpreadsheetオブジェクトはExcelのワークブック相当で、
sheetオブジェクトがExcelのシート相当のようです。

...確かに、openByIdで指定するのはワークブック相当の方で、
ワークブック内の各シートには「gid」ってのが割り振られているねぇ。

手探りGAS道です。
AutoMLの先行事例

過去のHPO(Hyperparameter Optimization)に関する先行事例を[Automated Machine Learning](https://link.springer.com/book/10.1007/978-3-030-05318-5)から持ってきました。

- King, R., Feng, C., Sutherland, A.: Statlog: comparison of classification algorithms on large
real-world problems. Applied Artificial Intelligence an International Journal 9(3), 289–333
(1995)
- Lee, D., Sugiyama, M., von Luxburg, U., Guyon, I., Garnett, R. (eds.): Proceedings of
the 30th International Conference on Advances in Neural Information Processing Systems
(NeurIPS’16) (2016)
- Michie, D., Spiegelhalter, D., Taylor, C., Campbell, J. (eds.): Machine Learning, Neural and
Statistical Classification. Ellis Horwood (1994)
- Ripley, B.D.: Statistical aspects of neural networks. Networks and chaos—statistical and
probabilistic aspects 50, 40–123 (1993)
- Escalante, H., Montes, M., Sucar, E.: Particle Swarm Model Selection. Journal of Machine
Learning Research 10, 405–440 (2009)
- Mantovani, R., Horvath, T., Cerri, R., Vanschoren, J., Carvalho, A.: Hyper-Parameter Tuning
of a Decision Tree Induction Algorithm. In: 2016 5th Brazilian Conference on Intelligent
Systems (BRACIS). pp. 37–42. IEEE Computer Society Press (2016)
- Olson, R., La Cava, W.,Mustahsan, Z., Varik, A., Moore, J.: Data-driven advice for applying
machine learning to bioinformatics problems. In: Proceedings of the Pacific Symposium in
Biocomputing 2018. pp. 192–203 (2018)
- Sanders, S., Giraud-Carrier, C.: Informing the Use of Hyperparameter Optimization Through
Metalearning. In: Gottumukkala, R., Ning, X., Dong, G., Raghavan, V., Aluru, S., Karypis,
G., Miele, L., Wu, X. (eds.) 2017 IEEE International Conference on Big Data (Big Data).
IEEE Computer Society Press (2017)
- Thornton, C., Hutter, F., Hoos, H., Leyton-Brown, K.: Auto-WEKA: combined selection and
hyperparameter optimization of classification algorithms. In: Dhillon, I., Koren, Y., Ghani,
R., Senator, T., Bradley, P., Parekh, R., He, J., Grossman, R., Uthurusamy, R. (eds.) The
19th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining
(KDD’13). pp. 847–855. ACM Press (2013)
- 45. Golovin, D., Solnik, B., Moitra, S., Kochanski, G., Karro, J., Sculley, D.: Google Vizier: A
service for black-box optimization. In: Matwin, S., Yu, S., Farooq, F. (eds.) Proceedings of
the 23rd ACM SIGKDD International Conference on Knowledge Discovery and DataMining
(KDD). pp. 1487–1495. ACM Press (2017)

ここからはサービスの事例

- Amazon: Automatic model tuning (2018), https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning.html 
- Li, F.F., Li, J.: Cloud AutoML: Making AI accessible to every business (2018), https://www.blog.google/products/google-cloud/cloud-automl-making-ai-accessible-every-business/
- SIGOPT: Improve ML models 100x faster (2018), https://sigopt.com/

何か発表する時の裏取りに使おう。
無限スクロールを実現する自作JQueryライブラリ loop.jsのご案内

## はじめに

WebサイトのUXとして無限スクロールは既に一般的なUXとして採用されてきています。そこで制作してるサイトでもライブラリを用いて採用すると、思いのほか使い勝手が悪いことが判明し、ロジックを自作したものをライブラリとして公開するものです。このライブラリは下記の特徴（定義要件）の下で開発されたものです。

1. 再読み込み時にもこれまでに読み込んだページがリセットされない
2. 採用されたサイトにはフッターがあるためボタン操作で次のページが表示させる
3. 100行前後の軽量なライブラリである

## デモ・入手
このソースコードはGitHubから入手できます
https://github.com/emesh0620/jquery_loop_js


なお、デモは下記のページからご覧頂けます。
https://emesh0620.github.io/jquery_loop_js/


## 実装

#### html部

まずループさせたい箇所に次のコードを入力します。
なお、next_loop_btm_bodyとnext_loopを変更する際にはソースコードを変更する必要があります。

```
<div id = "next_loop"></div>
<span id = "next_loop_btm_body">
    <button id="next_loop_btm">もっと見る</button>
</span>

```

#### JS部
JavaScriptはたとえば次のコードになります。

```
<script type="text/javascript">
$(function() {
    //loop.jsの本体を呼び出す
    $('#next_loop_btm').loop_looping({
        name    : 'loop',
        url     : 'loop/$.html',
        allpage : 2,
    });

    //キャッシュをクリアしたい時に呼び出す
    $('#cache_clear').loop_looping_clear();
});
</script>
```
* name･･･HTMLのキャッシュ時に使う名前
* url･･･2ページ目以降のページを指示する注意点は下記の通りです。
    * かならず表示順の連番として、HTMLであれば全て同一のディレクトリ入れること。
    * 連番部分はJSに書き込む際には$で置換しておくこと。
    （例えば　loop/1.html loop/2.html...と続くなら　loop/$.htmlとする）
    * なお、HTMLを吐き出すことが出来れば動的サイトなどでも構わない。
* allpage･･･ループの総ページ数をかく。最初のページを入れた値を入れること。


キャッシュをクリアしたいときには適当な場所に、
```
$(任意のIDまたはClass).loop_looping_clear();
```
を挿入すればキャッシュはクリアされます。

### おわりに

このライブラリはMITライセンスにつき、ご利用の環境によってご自由に改変して頂いて結構です。例えば、キャッシュにはUNIXTimeを記録していますので一定の時間が経てばキャッシュをクリアするなどの使い方があります。
リモートワークが流行っているのでchromeのリモートデスクトップを使ってみた

# はじめに
MTGやワークショップはやはり対面だなーと思いつつ、コーディングメインの時は、リモートでもいいんじゃね？って思いつつ日々を過ごしてました。

最近、ウイルスやらオリンピックやらで騒がれているリモートワークをするにあたり、社内環境を家で実現できればよかったのに、、、、
と考えて、じゃあ、会社にいなくても会社のPCを触れたら解決するのではと、chromeのリモートデスクトップを利用してみました！

# 環境
**会社のPC** : Windows 10 Pro
**自宅** : iPad

# 準備
早速試すためにインストールしてみました。
5分かからずに準備できると思います。

1.　リモートで動かしたいPCのブラウザで下記のURLにアクセス
https://remotedesktop.google.com/access
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/3fe9a50e-a817-fbb1-bb23-45962b9c65c0.png)
※Googleアカウントにログインしていない場合は、ログイン画面に遷移します
※Googleアカウントがない場合は、取得してください

2. 「オンする」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/cb4e6dd9-c5b8-c6c5-b5f4-ae5bc0e22167.png)

3.　任意で判別しやすい名前を付ける（会社PCなど）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/85b54485-e38b-f039-368b-cd321cb8c1bf.png)

4.　接続認証用のPINを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/fc75ce32-18ef-f203-2f4f-8e0f49cbe537.png)
※ほかの端末から接続するときに使用します
※他人に推測されにくいものを推奨

起動をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/7278951d-bca8-4a8d-66e2-17f286da27ab.png)

5.　デバイスが追加される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/2b44aa58-b588-5ec5-dd98-8b385c24e991.png)

ここまでで、準備は完了
デバイスがオンラインになっている状態で、他の端末から接続すると簡単にリモートデスクトップができます。

# 会社のPCへ接続
今回はiPadで接続します。

1. App Storeで「chrome リモート」などで検索しアプリをインストールする
<img width="91" alt="4771.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/ac773c77-c1fd-53e3-d381-51aed57b408b.jpeg">

2. アプリを起動し、環境準備で設定したGoogleアカウントと同じアカウントでログインすると先ほど設定したリモートデバイスが表示される
<img width="1024" alt="58385.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/ee0715a9-93d4-d2dc-e522-1f60e2507577.jpeg">

3. デバイスを選択すると、環境準備で設定したPINを聞かれるので設定したPINを入力する
<img width="1024" alt="99283.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/2d9ace38-2190-6695-a600-cc900178c020.jpeg">

4. 簡単に接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19460/0a77966e-cc68-939f-489d-909f27713bd2.png)
※わかりにくいですけど、PCの画面をiPadで見ている写真です

5.　切断するときは右下の「三」メニューを開き「切断」をします

# 懸念点
・処理自体は会社のPCですが、描画部分が自宅のPCに依存するので、会社のPCの処理能力と自宅のPCの描画に依存してます（自宅のPCもある程度スペック必要）

・ネットワーク環境（当たり前ですが、ネットワークにつながっていないとダメで、自宅の回線がぜい弱だともう無理です。。簡単にテザリングで試しましたが、メールチェックなどは問題なかったです）

・会社のPCの電源を入れていないと始められない（対象のPCの電源が入っていないとダメ、、、）

・セキュリティ上の問題（会社のPCを外部から操作できてしまうので、こっそり使ったりせず、セキュリティ担当などに要確認）

以上