OmniAICreator/Qiita-1.07M huggingface dataset:
GCPのDataFlowを簡単に触ってみた記録

# Intro
Google Cloud Dataflowを触ることがあったので、備忘も兼ねてどんな感じだったか記録を残す。

# Google Cloud Dataflowって？
簡単に言うと、ストリーミングデータやらの操作・管理を取り持ってくれる[GCPのサービス](https://cloud.google.com/dataflow)です。
今回はPubSubで受けたデータをDataFlowを介してCloudStrageに配置しようと思います。
ログやトラッキングデータのような物が不特定多数postされ、それを保持したり後の分析に利用するようなケースを想定しています。

# 1.Pub/Subにトピックを作成
Pub/Subってまたストレートな名前ですが、こちらもGCPのサービスです。所謂メッセージングというかキューというか。
今回のデータの始点、ある意味トリガーとなります。
とりあえず普通にGUIのコンソールから名前をつけるだけです。

# 2.CloudStorageにバケット用意
今回の終点となる場所を用意しておきます。
新たにバケットを作るか、既存であれば任意のフォルダを用意してください。
一時ファイルを配置するフォルダも合わせて用意しておきましょう（後述）。

# 3.DataFlowをテンプレートから作成
ここまで準備できると、あとは画面からポチポチしていくだけでできてしまいます。
というのも、DataFlowには利用頻度の高いユースケースに合わせて、テンプレートが用意されているので、
適宜選んで、必要な設定をするだけである程度動くものができてしまいます。

「テンプレートからジョブを作成」リンクから作成画面にいったら、ジョブ名、リージョンを選択します。
そしてテンプレートを選択。
今回は「Pub/Sub to Text Files on Cloud Strage」（そのまま！）を選びます。
その他必須パラメータを設定する上でのポイントとしては、

* Pub/SubのTopic名は"projects〜"から始まるものにすること（トピックの詳細ページでコピーできるもの）。
* Output Directoryは日付フォーマットが使える。"gs://foo-bucket/bar-folder/YYYY/MM/DD"とかしておくとYMDのところは日付に応じて自動でフォルダを割り振ってくれる。
* "一時的なロケーション"を指定する必要あり。（まぁ、任意のバケットに適当に/tmpとか作っておけば取りえあず大丈夫かと）

![スクリーンショット 2020-09-23 13.30.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531310/9b170630-c0b5-c626-9c6b-016a56184e1b.png)

# 4.TopicにPublishしてみる
以上までで、一通りの設定は完了。
ジョブを実行して、PubSubからメッセージをパブリッシュしてしばらくすると、CloudStorageにファイルができています。
中身にはパブリッシュしたメッセージが！
因みに、デフォルトは５分間でたまったメッセージが、それぞれ改行された上で１ファイルとしてCloudStorageに吐かれる模様。

# 備考・感想
* そういえばsubscriptionを作っていません。通常、Topicに対してSubscriptionがあってPubSubが構成されるのですが、今回はジョブを作成した時点で自動でsubscriptionが作られていたようです。
* 既存テンプレート以外の構成は、適宜テンプレートの実装を行う必要があります。ただし、[githubにテンプレートのリポジトリ](https://github.com/GoogleCloudPlatform/DataflowTemplates)があるので、それをベースにカスタマイズすることが可能（ソースはJavaかPython）。
* 最終的にはBigQueryも絡めてやってみたいが、今回の感触でそれも難しくなさそうな感じ。
OpenVINO の名付け有り顔認識デモを Docker でそのまま使うだけ

[前は interactive_face_detection_demo を動かしましたが](https://qiita.com/tset-tset-tset/items/cfdb35f65c13d73ccf4a)、同様に [face_recognition_demo](https://docs.openvinotoolkit.org/2020.3/_demos_python_demos_face_recognition_demo_README.html) を動かします。OpenVINO 2020.3 にはあったデモですが、OpenVINO 2020.4 には入ってなさそうでした。なので 2020.3 で実行します。

![output-palette.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693216/1a526a21-8d58-28d7-1dbb-d3eeb4ebd3ba.gif)

# Docker で実行

2020.4 にしたり 2020.3 にしたりが便利なので Docker で実行します。(GUI を操作するのが大変そうなため、Google Colab では試していません。)

## X11 サーバのインストール

このデモは不明な顔が出た時、名前を入力するとその場で顔画像と共に保存される機能があります。GUI から入力するため、Docker から窓を立ち上げられるよう設定します。

今回はホスト OS (Windows 10) 側で X11 サーバを立ち上げ、コンテナ (Ubuntu 18) の窓を Windows 10 上に飛ばせるようにしました。Windows 10 なので、[VcXsrv](https://sourceforge.net/projects/vcxsrv/) の 1.20.8.1 をインストール・起動し、Windows ファイアウォールの設定でプライベートネットワークを許可しておきました。docker コンテナからホスト OS への接続アドレスは `localhost` ではないので、`ipconfig` で確認しておきます。

```bash
ipconfig
～～～
イーサネット アダプター vEthernet (WSL):

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::6ca1:e659:80eb:a804%18
   IPv4 アドレス . . . . . . . . . . . .: 172.25.64.1 (ココが DISPLAY 接続先)
   サブネット マスク . . . . . . . . . .: 255.255.240.0
   デフォルト ゲートウェイ . . . . . . .:
```

上記の例だと `172.25.64.1` が DISPLAY 接続先になります。

## Docker 起動・デモの実行

```bash
docker run \
  -v /c/Users/${USER}/Downloads:/Downloads \
  -u root \
  -it \
  --rm \
  -e DISPLAY=172.25.64.1:0.0 \
  openvino/ubuntu18_dev:2020.3
```

`172.25.64.1` の部分は↑↑で確認したアドレスです。ライブラリの追加やビルドは不要なため、root じゃなくても動くかもですが、モデルパス等を[前回同様](https://qiita.com/tset-tset-tset/items/cfdb35f65c13d73ccf4a)にしたかったので root になっています。2020.4 にないデモなので 2020.3 を立ち上げています。

### 以下コンテナ内で作業

```bash
${INTEL_CVSDK_DIR}/deployment_tools/tools/model_downloader/downloader.py \
  --name face-detection-retail-0004,landmarks-regression-retail-0009,face-reidentification-retail-0095 \
  --output_dir /content/model/ \
  --precisions FP32
```

[face_recognition_demo](https://docs.openvinotoolkit.org/2020.3/_demos_python_demos_face_recognition_demo_README.html) で使いたい学習済モデルを、[付属のダウンローダー](https://docs.openvinotoolkit.org/2020.3/_tools_downloader_README.html)で落としてきます。

```bash
mkdir -p /Downloads/face_gallery/
cd ${INTEL_CVSDK_DIR}/inference_engine/demos/python_demos/face_recognition_demo/
python3 ./face_recognition_demo.py \
  -m_fd /content/model/intel/face-detection-retail-0004/FP32/face-detection-retail-0004.xml \
  -m_lm /content/model/intel/landmarks-regression-retail-0009/FP32/landmarks-regression-retail-0009.xml \
  -m_reid /content/model/intel/face-reidentification-retail-0095/FP32/face-reidentification-retail-0095.xml \
  --input /Downloads/input.mp4 \
  --output /Downloads/output.mp4 \
  -fg /Downloads/face_gallery/ \
  --allow_grow
```

Python なのでビルドは不要です。また、マニュアルに `pip3 install -r requirements.txt` の記載がありますが、依存モジュールも既に入っているので不要でした。起動後、`--allow_grow` をつけているので、不明な顔があれば適宜訊かれるようになります。その際、顔画像は `face_gallery` に保存されます。
【自分用メモ】BufferedWriterを使用したファイルの書き込み

FileWriterは一文字ずつ書き込むメソッド。
これをBufferingFilterを使用して、処理効率を上げよう！

```java

package practice1;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Write {

	public static void main(String[] args) {

		FileWriter fw=null;
		BufferedWriter bw=null;

		try {
			
			//cドライブには事前にworkファイル作成しておく

			fw=new FileWriter("c:\\work\\filetest.txt",true); 
			//workフォルダにfiletestファイルを生成。もしあればそれを使用する
			
			bw=new BufferedWriter(fw); 
			/*行ごとに書き込むために、「ため込んで一定量ずつ放出する」Bufferedメソッドをつくり、
			 FileWriter（書き込むメソッド）と組み合わせる*/
			
			bw.write("abcdefg"); //書き込み。行単位で書き込めるのはBufferedメソッドのおかげ。
			bw.newLine(); //改行処理
			bw.write("1234567890");
			bw.newLine();
			bw.write("1 2 3 4 5 6 7 8 9 0");
			bw.flush(); //強制的に「今書き込め！」と命令するメソッド
			


		}catch(IOException e){
			e.printStackTrace();  //エラーの詳細を、コンソールに赤文字で表示させるメソッド
			//System.out.println("ファイル書き込みエラーです");
			
			/* try-catch間でエラーが起こっても起きなくても
			 * fileをcloseできるようにfiallyメソッド使う↓*/
		}finally {
			if(bw!=null) {
				try {
					bw.close();
				}catch(IOException e) {}//中身はカラでもいいし、なんらかのエラーメッセージを出力してもok

			}
			if(fw!=null) {
				try {
					fw.close();
				}catch(IOException e) {}
			}
		}
	}
}

```
BitbucketからGitHubへとpush先を変更するときの手順（備忘録）

#push先を変更したきっかけ
転職活動時、GitHubのURLを求められることがあった（おそらくBitbucketでも良いと思うが、GitHubと指定されるケースがあった）ため、push先を変更する方法を覚えておくことに。

#前提
・以前はBitbucketを使用しており、BitbucketにSSHキー設定済。
・GitHubアカウント作成済＋リポジトリ作成済。

#SSH鍵確認
Bitbucketログイン
→左下のアイコンから、[Personal settings]に遷移
→セキュリティ欄の[SSHキー]を選択し、自身のSSHキーを確認

または、

ターミナル上で以下のコマンドを入力し、確認

```
cat ~/.ssh/id_rsa.pub
```
すると

```
ssh-rsa XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX= 
hogehoge@hogehoge
```
と表示されるので、ssh-rsaから=までをコピー。

#GitHubでSSHキー設定
GitHub右上のアイコンから[Settings]を選択
→[SSH and GPG keys]を押下し、SSHキーを設定。

#pushしたいリポジトリ（GitHub）のURLを確認
GitHub右上のアイコンから[Your repositories]に遷移
→該当リポジトリに遷移
→[Code]という緑色のボタンをクリックすると、SSHのURLが出るので、それをコピー

#push先URLの変更
まず、現在のpush先URLを確認する

```
git remote -v
```
まだ変更していないので、BitbuckerのリポジトリURLが登録されていた
push先を変更する以下のコマンドを入力

```
git remote set-url origin [GitHubリポジトリのURL]
```
#pushする

```
git push origin master
```
GitHubにｐushできた！
気軽な.countに気をつけよう（N+1問題）

## はじめに
Ruby on Railsを使っているとサクサクコードが書けて楽しいですね。
文法さえいくつか覚えてしまえばまるでプログラミングを意識せずに書きたいことをサクサク書いていけます。
Databaseに対してどういう命令を出しているかも意識せずに・・・

この代表的な問題点がいわゆるN+1問題です。

N＋1問題の解決策などは[このあたり](https://qiita.com/hirotakasasaki/items/e0be0b3fd7b0eb350327)に詳しく書いてありますが、今回はcountメソッドを使った場合に起きる問題に焦点を当てて解説します。

## 問題点: Array?ActiveRecord::Associations?
配列の数を数えるメソッドとして、

```ruby
.length
.size
.count
```

などがあります。
これらを使うことで、簡単に要素の数を返してくれます。

今回の問題点は `.count` を使った際にせっかく `includes` などを利用してもN+1問題が発生してしまうことの詳細です。

例えば、記事に対するコメント数を出す場合に

```ruby:app/models/article.rb
class Article < ActiveRecord::Base
  has_many :comments
end
```

```ruby:app/models/comment.rb
class Comment < ActiveRecord::Base
  belongs_to :article
end
```

というモデルがあったとします。

とある一覧画面に記事の一覧とコメントの数を列挙しようとした際に、何も考えずに書くと

```ruby:app/controllers/articles_controller.rb
~~略

  def index
    @articles = Article.all
  end

~~略
```
※ページングも何も考慮してません

```html:app/views/articles/index.html.erb
~~略

<%= @articles.each do |article| %>
<div class="article_panel">
  <div class="article_title"><%= article.title %></div>
  <div class="comment_count"><%= article.comments.count %></div>
</div>
<% end %>

~~略
```

おめでとうございます。コレであなたもN+1問題へ無事突入しました。

一般的な解決策としては `app/controllers/articles_controller.rb` で `includes` をすることなのですが、

```ruby:app/controllers/articles_controller.rb
~~略

  def index
    @articles = Article.includes(:comments).all
  end

~~略
```

これだけだと `app/views/articles/index.html.erb` で `.count` メソッドを使っているため、解決しません。

`.count` メソッドは [ActiveRecord::Associations::CollectionProxy](https://apidock.com/rails/v6.0.0/ActiveRecord/Associations/CollectionProxy/count) にも定義されており、対象のテーブルに `COUNT(*)` 句のクエリを発行してしまいます。

残念ながらここまででは、N+1は未解決です。

### 解決策

```ruby:app/controllers/articles_controller.rb
~~略

  def index
    @articles = Article.includes(:comments).all
  end

~~略
```

includes に加えて、

```html:app/views/articles/index.html.erb
~~略

<%= @articles.each do |article| %>
<div class="article_panel">
  <div class="article_title"><%= article.title %></div>
  <div class="comment_count"><%= article.comments.size %></div>
</div>
<% end %>

~~略
```

`.count` を `.size` （もしくは `.length` ）に書き換えることで、N＋1問題は解決します。


## 結論
せっかくincludeしたActiveRecord::Associationsに対しての数を数えるときは、 `.size` もしくは `.length` を使いましょう。
そうすることで `COUNT(*)` 句のクエリは発行されず、要素の数だけを数えて返してくれます。

※ちなみにですが、 `comments.sum(:like)` などを使った際にも `SUM(comments.like)` などでクエリが発行されますので注意が必要です。

## おわりに
Ruby on Rails は本当に気軽にかける素晴らしいフレームワークです。
我々の会社でも数多くのプロダクトでこのフレームワークを使うことによる開発速度の恩恵を受けてきました。

正しく理解し、正しく使うことが非常に重要です。

何に対してどんな命令を出すことで、どこのリソースに対してどんな負荷がかかるのかを意識し、この記事がN＋1退治に役立てれば幸いです。
【Ruby on Rails】トップに戻るボタン

# 目標
![arrow.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/cdbce6f2-f475-f9d8-cc66-66a80bcf09d4.gif)

# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

# 前提
※　▶◯◯　を選択すると、説明等が出てきますので、
　　よくわからない場合の参考にしていただければと思います。

- [deviseでログイン環境構築](https://qiita.com/japwork/items/275110b810965fbdf72f)
- [ログインユーザーのみができる投稿機能](https://qiita.com/japwork/items/8dfb52121036791ac4fb)
- [投稿の編集機能（更新、削除）](https://qiita.com/japwork/items/e258ccbbe4f48ea5a3b5)

上記機能はなくても大丈夫です。

# 流れ
1 写真の用意
2 viewの編集
3 cssの編集
4 jsファイルの編集（ページスクロールにアニメーションを追加する場合)

# 写真の用意
このような画像を用意してください。
ちなみにこの画像はipadで作成しましたので、ご自由にお使いください。
<img width="100px" alt="arrow.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/bf2a9a8f-9c67-c9c9-7380-67abeb0b51eb.jpeg">

画像ファイルをapp/assets/images配下に格納してください。


# viewの編集
今回は全てのページで表示したいため、下記場所に記載。

```erb:app/views/layouts/application.html.erb
<body>
  <%= yield %>
  <span id="back">
    <a href="">
      <%= image_tag asset_path('arrow.jpg'), data: {"turbolinks"=>false}, class: "arrow" %>
    </a>
  </span>
</body>
```
<details><summary>補足【image_tag asset_path(　)】</summary>
app/assets/images配下の画像を読み込むことが出来ます。</details>

<details><summary>補足【data: {"turbolinks"=>false}】</summary>
turbolinksの誤作動を防ぎます。</details>

# cssの編集

```css:app/application.css
#back {
  position: fixed;
  right: 20px;
  bottom: 20px;
}
.arrow{
  width:      50px;
  height:     50px;
}
```
<details><summary>補足【position: fixed;】</summary>
position: fixed;により表示する場所を固定しています。</details>

# jsファイルの編集
gem 'jquery-rails'を導入しておいてください。
マウスでクリックするとアニメーションを動作させます。

```js:app/assets/javascripts/application.js
$(function() {
  $('#back a').on('click',function(event){
    $('body, html').animate({
      scrollTop:0
    }, 800);
    event.preventDefault();
  });
});

```
<details><summary>補足【$('#back a').on('click',function(event)】</summary>
$('.セレクタ名').on('click',function(event) {　　
  イベント発生時に行われる処理
});
</details>

<details><summary>補足【$('body, html').animate】</summary>
$('セレクタ名').animate({　　　
  変化対象のプロパティ名:変化値　　
}, アニメーションの動作時間);　
</details>
Amazon LinuxにLightFMをインストールしようとしてハマった話

タイトルそのままなんですが、備忘録として。

結論から言うと「Amazon LinuxのgccにはOpenMPの実行環境が入っていないので手動再インストールが必要」ということ。

LightFMに関してはこの辺を確認してみてください

- 教師あり機械学習で映画を推薦するモデルを作成する【LightFM】  
https://sja-analysis.org/python-lightfm/
- LightFMをMovielensに適用してみた  
https://qiita.com/guglilac/items/757fc665510c9b68f385

さて、ひとまずLightFMのインストールは

```
pip install lightfm
```

でOKなのですが、これをAmazon Linux上で普通に実施すると
```omp.h: そのようなファイルやディレクトリはありません```
というエラーが出てきます。

で、[ここ](https://qiita.com/takebozu/items/c521f3937190fe8d3102)の記事を参考にすると以下の通り
>原因ですが、yumでインストールされるgcc7.2には、Qulacsが使っているOpenMPのヘッダーファイルomp.hが含まれていない様子。

で、どうするかというと

>```
>sudo yum erase gcc72 gcc72-c++ libgcc72
>```
>で一旦gcc7.2を削除します。その上で、あらためてgcc 7.4.0を手作業でインストールします。

お～そういうことですか。

というわけで、gccをソースからビルド/インストールしないといけないわけですが、そのまんまな記事が。大変参考になりました。

- gccをソースからビルド／インストールする  
https://qiita.com/liveralmask/items/6ed4a98ebb3bf6b7f707

ほぼこちらに書いてあることそのまんまですが、バージョンに関しては2020/9/23現在は10.2.0が最新ということでそこだけ変えて。実行コマンドは以下の通り。

```
wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-10.2.0/gcc-10.2.0.tar.gz
tar zxvf gcc-10.2.0.tar.gz 
cd gcc-10.2.0
./contrib/download_prerequisites 
mkdir build
cd build
../configure --enable-languages=c,c++ --prefix=/usr/local --disable-bootstrap --disable-multilib
make > /dev/null
sudo make install all
```

make実施時に結構時間かかりますので、気長に待ちましょう。

で、上記実施後再度

```
pip install lightfm
```

を実行するとすんなりインストール出来ます。
vhと%の違い

※主に自分の振り返り用です。

クレジットカード登録画面の下部に空白が生じるのをなんとかしたい。
写真ではわかりにくいですが、黄色で囲んだところに生じている空白を
無くしたいと思い奮闘しました。

![スクリーンショット 2020-09-23 10.21.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659091/ecbe19ea-6f5d-2c6b-0c92-4f175e5796ca.png)

いろいろ調べて、htmlやbodyに
```
height: 100%;
```
を当てる方法を試したところ、他のページのビューにも影響が出てしまい
この方法は断念。。。

このあと2時間ほど奮闘しましたが、
card_addクラスに
```
height: 100vh;
```
これであっさり解決。

要素の高さ指定で%とvhの違いがよく理解できていなかったので
ここにたどり着くのに時間がかかったようです。

#vhと%の違い

【vh】
ページの表示領域に依存する。

```
height: 100vh;
```

と指定すれば、高さがページの表示領域いっぱいに表示される


【％】
親要素に依存する。

```
height: 100%;
```
と指定すれば親要素の大きさまで表示される。
KintoneのREST API用スニペット(APIトークン認証用ヘッダーの書き方、ログイン名パスワード用認証ヘッダーの書き方、クエリの書き方)

# 一通り使ってみたのでよく使うものに関しての備忘録

インターン先でKintoneから一部のデータを利用するためにREST APIを初めてしっかり勉強しました。そのうえでKintone特有の書き方っぽいものだけまとめました。

基本的にKintoneのドキュメントにはJavaScriptのスニペットしか置いていないので、どこまでがREST APIの仕様でどこからがKintone REST APIの仕様なのかわからない部分が多かったのでKintone REST APIの仕様の部分だけをピックアップした感じです。

下記URLの一部をpythonように書き下しました。
https://developer.cybozu.io/hc/ja/articles/201941754

APIトークン利用時のヘッダー

```python
headers = {"X-Cybozu-API-Token": api_token}
```

IDとパスワードで認証するときのヘッダー

```python

import base64
str_ = str(id_) +':' + str(password)#'id:password'
encoded = base64.b64encode(str_.encode('utf-8'))  
header = {
    "X-Cybozu-Authorization":encoded
}
```

レコードをとるときにクエリを書いて一括取得するときのURLの書き方
参考URL
https://developer.cybozu.io/hc/ja/articles/202331474

```python
import urllib
url = 'https://{ドメイン名}.cybozu.com/k/v1/records.json?app={}&query={}'.format('アプリ番',urllib.parse.quote('クエリを記入'))
```
fortran 導入手順　備忘録

環境: macOS Catalina
エディタ: Visual Studio Code　バージョン: 1.44.2
manaba配布テキストの手順より
(https://home.hiroshima-u.ac.jp/rgdlab/rgdl_html/programming/gfortran_install_macOS.htm)
1.Xcodeでcommand line toolsをインストール
2.GitHubからgfortran-8.2-Mojave.dmgをインストール
(https://github.com/fxcoudert/gfortran-for-macOS/releases)

エディタにVisual Studio Codeを使用
1.Japanese Language Pack for Visual Studio Code
2.Modern Fortran 
の拡張機能をインストール

動作確認済。
【新入社員】「システムと圧縮メモリ」がメモリやCPUを大量に使用してしまう問題と解決法

https://i-bitzedge.com/tips/how-to-fix-system-and-compressed-memory
「システムと圧縮メモリ」がメモリやCPUを大量に使用してしまう問題と解決法

今日はいそいそなので、リンク貼っときます
PHP Laravel 6 おすすめ映画投稿サイト作成過程 1:準備編

# 備忘録としての制作過程を記録

##Laravel を実装（バージョン６）

```
composer create-project --prefer-dist laravel/laravel recommend "6.*"
```

##一部内容の修正
###.env
DBはsqliteを使用する。

```recommend/.env
DB_CONNECTION=sqlite
```

###app.php
ロケーション等の変更。

```recommend/config/app.php
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
'faker_locale' => 'ja_JP',
```

##DB作成

```
touch database/database.sqlite
```

##DB関連の資料作成
###必要なファイルを一括生成

```
$ php artisan make:model Models/Recommend -a
```

###テーブル内容を設定
今回は、以下の６項目

| カラム |
|:-----------|
| ID |
| 映画タイトル    |
| 映画の画像       |
| 映画イメージの名前       |
| 映画URL       |
| 映画概要（空投稿可）      |
| 感想（空投稿可）　|


```recommend/database/migrations/2020_09_23_105017_create_recommends_table.php
public function up()
    {
        Schema::create('recommends', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->string('image_file_name', 100)->nullable();
            $table->string('image_title',100)->nullable();
            $table->string('url');
            $table->string('description')->nullable();
            $table->string('Impressions')->nullable();
            $table->timestamps();
        });
    }
```

###マイグレーション
マイグレーションファイルがデータベースに反映されます。

```
$ php artisan migrate
```

##autuの実装
以下の作業で、認証に必要なすべてのビューがresources/views/authディレクトリに生成されます。
###ルート定義
```
composer require laravel/ui "^1.0" --dev
```
```
php artisan ui vue --auth
```
No Method Errorについて

自分用のエラー解決録です。

フリマアプリ作成のチーム実装もいよいよ終盤。
各メンバーが開発したものをマスターにマージし、
自分のローカルにプルすると度々エラーが発生します。

今回のエラーはこちら
![NoMethodError.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659091/6cf20005-5873-0b2b-0c84-10535f76574b.png)

マイページからログアウトページ遷移しようとしたところ発生。

```
undefined method `each' for nil:NilClass
```

という記述です。
場所はどこか？というと
user#showです。

早速コントローラーを確認すると

```
class UsersController < ApplicationController
  def index
    @parents = Category.where(ancestry: nil)
  end

  def show
    
  end
  
end

```
showの中身が空、、、
こちらに記述を追加

```
class UsersController < ApplicationController
  def index
    @parents = Category.where(ancestry: nil)
  end

  def show
    @parents = Category.where(ancestry: nil)
  end
  
end
```

するときちんと表示が戻りました。
![スクリーンショット 2020-09-23 12.27.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659091/17e25523-4cb0-058d-52a1-d68930150290.png)

エラーを重ねることによって、エラー文から原因を自分で推測して
解決できるようになってきました。
自走力が少し身についてきたのかな？

まだまだこれからですが、引き続き頑張ります！
jsでもifやswitchを式として扱いたい

忘れない内にメモ
こうすれば行ける

```javascript
const result = ((some) => {
    if(some === 1) {
        return 1;
    } else {
        return 2;
    }
})(some);
```

```javascript
const result = ((some) => {
    switch(some) {
        case 1:
            return 1;
        case 2:
            return 2;
        default:
            return 3;
    }
})(some);
```

ifじゃなくて三項演算子使うのもアリか
【Java】JSON 通信 with jackson

# java で json の通信を行う (jackson を利用)
### 環境
- windows10
- eclipse：2020-06 (4.16.0)
- jackson
- java 1.8

例によって忘備録です・・・

## 順序
1. Dto 生成
2. jackson を使って Dto -> json に変換
3. HttpURLConnection を使って通信
4. 結果取得

## Dto 生成
```java
public class SampleDto implements Serializable {
    private static final long serialVersionUID = 1L;　 // ちゃんと生成した方が良さげ

    private int id;
    private String mail;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getMail() {
		return mail;
	}
	public void setMail(String mail) {
		this.mail = mail;
	}
}
```

## Dto -> json 変換
```java
	protected String createJson4Sample(SampleDto dto) {

		ObjectMapper mapper = new ObjectMapper();
		try {
			return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dto);
		} catch (JsonProcessingException e) {
			StringWriter sw = new StringWriter();
			e.printStackTrace(new PrintWriter(sw));
			log.error(sw.toString());
			return null;
		}
	}
```

## 通信
```java
	protected String requestJson(String method, String json, String urlPath, String charset,
			String bearer) {

		HttpURLConnection con = null;
		if (StringUtils.isEmpty(charset)) {
			charset = StringUtils.lowerCase(StandardCharsets.UTF_8.name());
		}
		String body = "";
		try {
			URL url = new URL(urlPath);
			con = (HttpURLConnection)url.openConnection();
			con.setRequestMethod(method);
			con.setUseCaches(false);
			con.setDoOutput(true);
			con.setRequestProperty("Content-Type", "application/json; charset=" + charset);
			if (StringUtils.isNotEmpty(bearer)) {
				con.setRequestProperty("Authorization", "Bearer "+bearer);
			}

			OutputStreamWriter out = new OutputStreamWriter(new BufferedOutputStream(con.getOutputStream()));
			out.write(json);
			out.close();

			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
			String line = in.readLine();
			while (line != null) {
				body = body + line;
				line = in.readLine();
			}
		}
		catch (Exception e) {
			StringWriter sw = new StringWriter();
			e.printStackTrace(new PrintWriter(sw));
			log.error(sw.toString());
			return null;
		}
		finally {
			if (con != null) {
				con.disconnect();
			}
		}
		return body;
	}
```

## 結果取得
```java
	protected boolean checkResponseJson(String response) {

		ObjectMapper mapper = new ObjectMapper();
		try {
			if (StringUtils.isEmpty(response)) { return false; }
			JsonNode root = mapper.readTree(response);

			String success = root.get("success").asText();
			String id = root.get("id").asText();
			log.info("Response:" + id + ":" + success);
			if (!"OK".equalsIgnoreCase(success)) {
				return false;
			}
		} catch (Exception e) {
			StringWriter sw = new StringWriter();
			e.printStackTrace(new PrintWriter(sw));
			log.error(sw.toString());
			return false;
		}
		return true;
	}
```

以上、お疲れさまでした！
Python（スライス表記）

今回はPython のスライス表記について書いていきます。

スライスは単純なルールで表記されますが、初学者に方にとっては
何回か使用していると、ややこしくなってしまう瞬間があるかと思います。

その際、意識しておくべき2つのルールについてお話していきます。

## ■ スライスを読むときの、2つのルール

①データの順番は0番目から始まる（リストの基本）
②スライスの終わりは、1つ手前の $n-1$ となる

実際に例をあげて説明していきます。

下記のようなデータを用意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725082/dc7ec17c-6566-7b94-1e05-300a9e66a1de.png)
ルール①では単純に、先頭データから0番目、1番目、2番目・・・と順番が決められているので
それをもとに、数字を抽出していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725082/8fd71cb1-4d01-4096-791f-16d381652531.png)
上記のように、インデックス番号（0から始まる順位付け）をもとに数字の抽出ができました。
このルールだけならば、まだ簡単だとは思います。

次に、②のルールについて説明していきます。
ここで、ややこしい問題が発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725082/52920d2a-16b2-1c3d-a955-405f806426db.png)
今回のリストでは、0から数えて5番目のデータが10でしたが
スライスで5番目までを指定して抽出しても、9までしか出力されていません。

このようにスライスでは、インデックス番号の範囲を指定する際に
終わりの番号の一歩手前、 $n-1$ までの順番までしか抽出されません。（今回は $n=5$）
実際に他の数字も入れて確かめてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725082/71d528da-e170-0f16-06af-c6d8172778a3.png)
初学者の方は、学習中にルール①は意識して写経などをされるかと思いますが
いきなり上記のようなスライスの表記が出てくると、複雑に考えてしまうことがあるかと思います。

その際には、最初にお伝えした2つのルールをもとに考えてみてください。

【スライスを読むときのルール】
①データの順番は0番目から始まる
②スライスの終わりは $n-1$ となる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725082/cd87e4bd-54f9-a8af-1469-1181f7e7be87.png)
MVCについて（自分なりにアウトプット）

#そもそも何ってことから振り返ってみます！
 MVCとは、モデル（Model）・ビュー（View）・コントローラー（Controller）の頭文字をとったもです。で、それ自体は何かと問われると、【Webフレームワークで一般的に取り入れられるアプリケーション設定を整理するための概念の一つ】とある記事で書かれていましたが、要は、railsなどのアプリケーションの処理を行うシステムの構造のことを言うと覚えておけば良いのかと思います。

#では、なんでそれを使用するのかを調べました。
MVCの概念がない場合、あるプログラムを書いたディレクトリをどこで対応しているかなどがわからなくなります。そのディレクトリで記述したコードの破綻等が起き不具合やバグの原因にも繋がります。そのため、役割ごとに意味のある単位で機能を実装すると管理しやすくなるので、MVCに分割して実装することでそれらを防ぎ円滑にアプリケーションを構築できるので便利であると言う理由から使用されたとのことです。
要は、それらを機能している箱に、コードを書くだけでアプリケーションが動きますよ的なことだと認識してます😄

#【MVC】のそれぞれの役割を調べていきます！
まずは、MVCの　**M**　から見ていきます！
Mとは、モデルのことを指します。
モデルは何の機能をもったところかと言うと、データベースとデータのやり取りを行う機能を実装したり、データベースからデータをプログラムで扱いやすい形式でデータを変換する役割を担っています。
データベースに、新規のデータを入れたい時や、データの更新を行いたい時、削除したい時などに機能の実装を行う箇所です。

次にMVCの　**V**　を見ていきます！
Vとは、ビューのことを指します。
ビューは、データを文字上でレスポンスを行う機能をいい、HTMLを動的に生成する部分です。
要は、リクエストされた情報を、HTMLなどを利用し、可視化してコントローラーに渡す役割を持った箇所を指します。
※HTMLとは、webページ上で表示されている文字などを表示させるマークアップ言語です。

ラストにMVCの　**C**　を見ていきます！
Cとは、コントローラーを指します。
コントローラーは、ルーティングから来たリクエストをモデルを介して情報の取得及び保存を行いビューからもらった（見た目が整った）ものをレスポンスとしてクライアントに返す役割を持った箇所です。
要は、モデルとの橋渡し・ビュートの橋渡し・クライアントの橋渡しの部分がコントローラーに当たります。
※ルーティングとは、クライアントからくる情報をコントローラに道筋を決めて渡す箇所を言います。

これを画像にするとこうです（鬼の手書きなのでわかりにくいと思います🙇‍♂️）↓
![47964874-E251-4A59-B0C4-3C792284CF36_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670418/49c5ef8f-3955-6728-aca7-9856b6aa856c.jpeg)


#まとめ
MVCの概念はアプリケーションを作る上では必須と言っても過言ではないもので、それらを理解するとスムーズにアプリケーションを作成することができるものだと言った認識でいます！
共有サーバから閉め出されたときのコマンドの使い方（資格情報とかについて）

# 症状
権限が限られてるタイプの共有サーバにアクセスしたい
→ユーザ名とパスワードを入力してアクセスしようとする
→使用したユーザにアクセス権限がなのでアクセスできない
→再度アクセスしようとしても、認証情報が残ってしまい、ポップアップが出るだけで認証情報入力し直せない
→認証情報消したいんだけどGUIの資格情報マネージャに何も表示されない
→コマンドプロンプトでやるっきゃねえ

# やり方
`net use [\\ネットワーク名] /delete`
のあとに
`klist purge`

`cmdkey /delete:ネットワーク名`
とかもある

# ダメだったら
再起動しかないのかもしれない……
cronでGithubにPushするプロセスを自動化する

#やったこと

Pythonとcrontabを使って、データファイル(pklフォーマット)を一週間に一回（土曜日の午後7時）に更新されるようにしました。

毎週更新されるデータをGithubに自動的にPushしたく、同じくcrontabを使ってやってみた。

#環境

- Linux Mint 19
- Python 3.6.9
- git 2.17.1

#GithubでSSH接続する
ssh接続する方法はたくさんネットに上がっているので割愛します。
(参考: [GitHubにssh接続できるようにする](https://qiita.com/0ta2/items/25c27d447378b13a1ac3))


#GITコマンドでプッシュしてみる
ssh接続が出来たら、gitコマンドでPushしてみる。

アップしたいデータファイルはplayers_data.pklというpythonのpickleというモジュールを使用したフォーマットです。

```bash
git add players_data.pkl
git commit -m "最初のコミット"
git remote add origin git@github.com:<ユーザー名>/＜レポジトリ名＞
git push origin master
```


#自動化のPythonコードを作成

この一連の作業を自動化するPythonのコードを書きます。

使用するのはsubprocessというModuleで、bashコマンドをPythonで実行することが出来ます。（参考：[Python の subprocess](https://qiita.com/tanabe13f/items/8d5e4e5350d217dec8f5)）

```python:new_data.py
import os
import datetime
import subprocess as cmd

#input values
new_date = datetime.datetime.now().strftime('%Y%m%d')
current_dir = os.getcwd()

#Subprocessで自動化
cp = cmd.run(f"git -C {current_dir} add players_score.pkl", check=True, shell=True)
cp = cmd.run(f"git -C {current_dir} commit -m 'scoresheet updated on {new_date}'", check=True, shell=True)
cp = cmd.run(f"git -C {current_dir} push origin master", check=True, shell=True)
print('Githubへのアップ成功!')
```

この段階で`python3 new_data.py` をbashで実行し、ちゃんとGithubにアップされているか確認してもよいでしょう。

#SSH のラッパースクリプト(git-ssh.sh)を作成
ここが今回引っかかったところなのですが、crontabでgit push origin masterを実行しようとすると、以下のようなエラーがでます。
>Command 'git -C /path/to/folder/ push origin master' returned non-zero exit status 128.

[cron から自動で git push する](http://tm.root-n.com/unix:command:git:cron_git_push)を参考にすると、
>cron から自動で git push したい時、ssh の秘密鍵を明示的に指定して git push する必要があります。

というわけで以下のSHファイルを.sshのあるフォルダーに置いてやることが必要です。

```shell:/path/to/.ssh/git-ssh.sh
#!/bin/sh
exec ssh -oIdentityFile=/path/to/.ssh/id_rsa "$@"
```

このSHファイルに実行権限を与えることも必要。

```bash
cd /path/to/.ssh
chmod +x git-ssh.sh
```

#SHファイルでPythonを動かす
直接Crontabでやってもいいのですが、今回はSHファイルを作成してPythonを動かすようにします。

```shell:scripts.sh
#!/bin/sh
cd /path/to/folder
export GIT_SSH=/path/to/.ssh/git-ssh.sh
python3 new_data.py > output_newdata.txt
```

#crontabでSHファイルを定期的に実行する
最後にcrontabで定期実行の方法です。

まず`crontab -e`をbashで実行し、crontabを開けます。

Cronの設定の仕方は割愛しますが、毎週土曜日の午後7：00にscripts.shを定期実行したいときは下記のようにします。（参考：[crontabのガイドライン](https://qiita.com/onomame/items/71646c5517a39bcd01cc)）

```
00 19 * * 6 bash /path/to/folder/scripts.sh
```

これでうまく定期実行のできるようになりました。


#参考サイトまとめ
- [GitHubにssh接続できるようにする](https://qiita.com/0ta2/items/25c27d447378b13a1ac3)
- [Python の subprocess](https://qiita.com/tanabe13f/items/8d5e4e5350d217dec8f5)
- [cron から自動で git push する](http://tm.root-n.com/unix:command:git:cron_git_push)
- [cronを使いGitlabリポジトリをWEBサーバ側に反映させる](https://qiita.com/redamoon/items/cf806971b278775bd5b7)
- [crontabのガイドライン](https://qiita.com/onomame/items/71646c5517a39bcd01cc)
Denite + Defx で複数プロジェクトを渡り歩く

## 目的

複数のプロジェクトで作業をしないといけない場合、プロジェクトを切り替えながら渡り歩くのが結構めんどくさかったりします。
そういった場合に`Denite`の`denite#custom#var`を使うとプロジェクト間の行き来が少し楽になります。

## 環境

`NVIM v0.5.0-94b7ff730`
[Denite](https://github.com/Shougo/denite.nvim)と[Defx](https://github.com/Shougo/defx.nvim)が使えることが前提です。

## 詳細

`:help denite#custom#var`

## 設定

以下のように設定すると`<Leader>p`でプロジェクトの選択肢が表示され、Enterでプロジェクトルートが開きます。

```vim
let s:menus = {}
let s:menus.projects = { 'description': 'switch projects' }
let s:menus.projects.command_candidates = [
      \   ['project A', 'Defx ~/path/to/projectARoot'],
      \   ['project B', 'Defx ~/path/to/projectBRoot'],
      \   ['project C', 'Defx ~/path/to/projectCRoot'],
      \ ]
call denite#custom#var('menu', 'menus', s:menus)

nnoremap <silent> <Leader>p :<C-u>Denite menu:projects<CR>

```

`Defx`以外のコマンドでも、`command_candidates`に追加すれば選択式で使えるので結構便利そう。
依存パッケージをアップグレードしたい(yarn)

## 問題
GitHubのdependabotから、`node-forge`のバージョンを`0.10.0`以上に上げろと怒られる
↓
`package.json`内に`node-forge`は無いから、`yarn upgrade node-forge`では対応できない

## 解決法
依存元のパッケージを特定して、そのパッケージをアップグレードして対応。

```zsh
$ yarn why node-forge # 依存元のパッケージを確認
=> Found "node-forge@0.9.0"
info Reasons this module exists
   - "webpack-dev-server#selfsigned" depends on it
   - Hoisted from "webpack-dev-server#selfsigned#node-forge"
$ yarn upgrade webpack-dev-server # 依存元のパッケージをアップグレード
```

## その他
日頃からテストをしっかり書いていると、パッケージをどんどんアップデートできて、セキュリティ的にもパフォーマンス的にも良いサービスを保てることを実感。

## 参考
[yarn upgrade で更新できない間接的な依存パッケージだけをアップグレードするには - Qiita](https://qiita.com/uasi/items/ca440a750a77ca62321b)
[Oracle]暗黙の型変換が存在するとインデックスが効かない

このようなインデックスがあったとして

```
# id varchar(16) に対してのindex

CREATE INDEX test ON user(id);
```

これは `varchar(16)` で宣言されています。ですが、実態として中身が数値しか入っていなかったとします

```
mysql> select id from user;
+----------+
| id       |
+----------+
| 11111111 |
| 22222222 |
| 33333333 |
| 44444444 |
| 55555555 |
| 66666666 |
+----------+
```

これに対して、数値で検索をかけてしまうとインデックスは効きません。

```
select * from user where id in (22222222, 66666666);
```

文字列で定義されているため、暗黙の型変換が入りインデックスが外れます。文字列で指定してあげましょう。

```
select * from user where id in ('22222222', '66666666');
```

インデックスきいているはずなのに遅いなと思ったら要注意。
任意の場所から文字を取り出せるメソッド作成

【概要】
----------------------------------------
<b>1.結論</b>

<b>2.どのように記載するか</b>

<b>3.ここから学んだこと</b>



1.結論
----------------------------------------
<b>lengthメソッドとsliceメソッド</b>を使用する！

<br>
2.どのように記載するか
----------------------------------------

```ruby
def srt_search(strings)
  character_number = strings.length #---❶
  character_reslut = strings.slice(character_number - 3, 3) #---❷
end
```
上記のように記述しました！

❶lengthで、文字列を数に変更しました。
>ex)"Goodjob"➡︎"8"文字に変換

❷今回は最後から3番目までの数字が欲しいので❶の文字数からslice(character_number - 3, 3)することでcharacter_numberからの文字数から"-3"した番目の"3"文字分を取得できます。
>ex)"Goodjob"の8文字から"-3"すると最初から"5"番目(=最後から3番目まで)の"3"文字を抜き取る。



参考にしたURL:
<a href="https://web-camp.io/magazine/archives/16198#slice">【Ruby入門説明書】ruby sliceについて解説</a>
<br>
3.ここから学んだこと
----------------------------------------
slice(character_number - 3, 3)の部分は、
slice(-3,3)とすれば、最後から3番目の3文字を常にとることができるなと思いました。ただ、文章の構成(ex:Hi, John! Nice to meet you!)になると単語区分でsliceが判断してしまい、"to meet you!"が抜き出される点は注意しないといけません。
<br>
TypeScriptでArray<T>から重複要素を排除してユニークにする

[JavaScriptでArray<Object>をuniqにする]
(https://qiita.com/oubakiou/items/b848434e65d0644e1dfc)を元に

```typescript
const defaultComparator = <T>(a: T, b: T): boolean => a === b

export const distinctBy = <T>(
  array: Array<T>,
  comparator: (a: T, b: T) => boolean = defaultComparator
): Array<T> =>
  array.filter(
    (elem, index, self) => self.findIndex(e => comparator(elem, e)) === index
  )
```

で

```typescript
type Dog = {
  id: string
  name: string
}
const comparator = (a: Dog, b: Dog) => a.id === b.id
const dogsDistinct = (dogs: Array<Dog>) => distinctBy(dogs, comparator)

```

みたいな。


ところでJavascriptには[ビルトインの等価性アルゴリズムが4種類ある](https://developer.mozilla.org/ja/docs/Web/JavaScript/Equality_comparisons_and_sameness)(演算子としては3種類ある)のでcomparatorを実装する時はどれに合わせるのか気をつけたほうが良いと思います。

```javascript
[1, 2] == '1,2' //true
[1, 2] === '1,2' //false
Object.is([1, 2], '1,2') //false

NaN == NaN //false
NaN === NaN //false
Object.is(NaN, NaN) //true

+0 == -0 //true
+0 === -0 //true
Object.is(+0, -0) //false
```

TypeScriptを使っていると型の上でも馴染みが深い、構造が一致するかどうかという比較はビルトインでは提供されていないため、必要であれば[deep-equal](https://www.npmjs.com/package/deep-equal)のような外部パッケージを利用すると便利です。

# see also

- [等価性の比較と同一性 - JavaScript | MDN]
(https://developer.mozilla.org/ja/docs/Web/JavaScript/Equality_comparisons_and_sameness)
- [等価演算子の同一性 構造の等価性(Structural Equality) - TypeScript Deep Dive 日本語版]
(https://typescript-jp.gitbook.io/deep-dive/recap/equality)
- [JavaScriptの等値比較を全部理解する]
(https://qiita.com/uhyo/items/d99f536332e03442c432#%E7%AD%89%E5%80%A4%E6%AF%94%E8%BC%83%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%99%E3%82%8B%E5%A0%B4%E9%9D%A2)
- [deep-equal  -  npm]
(https://www.npmjs.com/package/deep-equal)
組み合わせツール『PICT』の使用メモ

## PICTについて
PICTは2因子間で網羅する組み合わせ技法"ペアワイズ法"を生成できるツールです。

### インストール
PICT (Microsoft)
https://github.com/microsoft/pict/releases/download/release/pict.exe
・コマンドプロンプトを起動し、pict.exeのパスを入力すると使用できる
・PICT MASTERで使用する場合は、pict.exeを適当なフォルダに格納し、環境変数 > ユーザー環境変数 > pathを編集して格納先のパスを追加しておく

>pict
Options:
/o:N - Order of combinations (default: 2) ⇒　因子間網羅数
/d:C - Separator for values (default: ,)
/a:C - Separator for aliases (default: |)
/n:C - Negative value prefix (default: ~)
/e:file - File with seeding rows
/r[:N] - Randomize generation, N - seed
/c - Case-sensitive model evaluation
/s - Show model statistics　⇒　ケース数の表示(下記の"Generated tests")

※オプションo,sの実行例
`C:\>pict model.txt /s /o:3
Combinations:    1701
Generated tests: 201
Generation time: 0:00:00`


PICT MASTER (PICTと併せExcelで使用できる)
https://ja.osdn.net/projects/pictmaster/
※PICTの格納先に、PICT MASTERを解凍先にあるnkf.exeとcit.jarのファイルを移動しておくこと。

### モデルファイルの書き方
<b>因子・水準の書き方</b>
メモ帳などテキストファイルで因子・水準を書く。
下記例ではアルファベットが因子、数値が水準。水準はカンマで区切ること
>OS: Windows7,Windows8.1,Windows10,Linux Ubuntu20.04,Linux Ubuntu19.10
CPU: Core i7,Core i5,Core i3,Celeron,AMD Ryzen7,AMD Ryzen5,AMD Ryzen3
メモリ: 2GB,4GB,8GB,16GB
Office: あり,なし
HDD: SSD 128GB,SSD 256GB,HDD 500GB,HDD 1TB
価格: 40K,50K,60K,80K,100K以上

<b>制約条件</b>
・演算：水準の比較　=,<>, >, >=, <, <=
・複数の水準の指定　in {"水準1","水準2}
・論理演算　NOT, AND, OR
・LIKE ワイルドカード(*または?)で複数の値を指定

条件式
` if [OS] = "Linux Ubuntu19.10"
　then [メモリ] = "2GB"
　else [メモリ] <> "2GB"; `
 
else省略可能
` if [OS] = "Windows10"
　then [CPU] in {"Core i7", "Core i5", "AMD Ryzen7" , "AMD Ryzen5"}; ` 

分岐
` if [Office] = "あり"
　then [価格] = "60k" or [価格] = "80k" or [価格] = "100k以上"; `

固定則
` if [CPU] = "Core i7"
then [HDD] LIKE "SSD*"; `

### コマンド実行
Cドライブ直下にモデルファイルを置き、コマンドプロンプトにてコマンド実行
Cドライブ直下に組み合わせた結果がファイル出力される
> pict モデルファイル.txt > 結果.txt
Spring Bootでのページ遷移をざっくり理解する

#Spring Bootでのページ遷移
Servletアプリを例えばEclipseの「動的プロジェクトの作成」からスターターファイルを作ってやる場合、WebContent以下のディレクトリに以下のように静的ファイルを格納すれば割と簡単にページ遷移の設定ができました。

```
WebContent
┠META-INF
┠WEB-INF
    ┗login
        ┗login.jsp　//ここに格納したファイルは直接URIからはリクエスト不可
┗index.jsp //ここに置いたファイルがデフォルト(http://localhost:8080など)で表示される
```

ですがServletの勉強をしたとき、デフォルトディレクトリはどこなのか、ページ遷移はどうやってするのかがあまり体系的にまとまっているサイトや本がなかったので、自分メモとして書いておきます。

Spring Initializerでスターターファイルを作成すると、上のようなWebContentなどのディレクトリは作成されていません。

代わりに以下の構成になっているresourcesフォルダに格納します。

```
src/main/resources
┠static
┗templates
```

Servletの時のような構成にしたい場合は以下のようにファイルを格納します。

```
src/main/resources
┠static
　　┗index.html // ここにあるファイルがデフォルト(http://localhost:8080など)で表示される
┗templates // ここはURIから直接参照不可
   ┗hello.html
　　┗login
      ┗login.html 
```

Servletのときは、直接参照不可にしたいページに遷移させる場合は、以下のようにサーブレット側で管理しました。formのactionなどから下記のサーブレットクラスを呼び出して遷移できます。

```Java:sampleServlet.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    RequestDispatcher dispatcher = request.gerRequestDispatcher("WEB-INF/login/login.jsp");
	    dispatcher.forward(request,response);
	}
```

Spring Bootで同様のことを実現したい場合はControllerクラスなどからreturnで遷移させます。こちらの場合は`/login`でURIを叩くと以下の`getLogin()`メソッドが呼ばれて`templates`以下の静的ファイルにアクセスしにいきます。templates以下に格納したファイルはURI指定で呼び出すことはできないので、`Controller`クラスなどで調整します。

```Java:LoginController.java
@Controller
public class LoginController
{
	@GetMapping("/login")
	public string getLogin() {
	    return "/login/login"; 
//「http://localhost:8080/login」でアクセスすると、templates以下loginファイルのlogin.htmlが呼び出される
	}
　　　　　
　　　　@GetMapping("/hello")
	public string getHello() {
	    return "/hello"; 
//「http://localhost:8080/hello」でアクセスすると、templates以下hello.htmlが呼び出される
	}
}
```

一応自分で調べた限りですが、もし他に良い方法などあればぜひコメントください。
[備忘録] Tensorflowに関して

#はじめに
これまでTensorflow(Keras)を使ってみて、わかったことを整理しておきたいとと思います。

#1. 仮想環境でのTensorflowの設置
Tensorflowを仮想環境に設置する時、Anacondaのconda命令とPythonのpip命令を使うケースに分けられます。それぞれの特徴について、下記の表に整理します。


| 項目| conda | pip |
|:-----------|:------------|:------------|
| 設置コマンド       | conda install -c anaconda tensorflow-gpu    |pip install --upgrade tensorflow|
| メリット     | CUDA, cuDNNも一緒に自動的に設置される。超便利！  | 2020.09時点でTensorflow 2.3<br> pip install -r requirement.txtが大変便利       |
| デメリット    | 2020.09時点でTensorflow 2.1が最新Version. <br> tensorflow-estimatorのVerisonが2.3になっているケースがある。[2] その時は、conda install tensorflow-estimator==2.1.0で、tensorflow-estimator version 2.1を手動で設置  | CUDA, CuDNNを自分で設置する必要がある。<br>pip設置のTensorflowのPerformaceがconda設置より悪いと言われている [1]        |

#2. Tensorflow 2.0 with Keras
Tensorflow 2.0になったとき、変更点がいくつありました。

| 項目| Tensorflow 1.X | Tensorflow 2.X |
|:-----------|:------------|:------------|
|設置|TensorflowとKerasを別々設置|Tensorflowだけ設置|
|import 部分|```import tensorflow as tf``` <br>```import  keras```|```import tensorflow as tf```　<br> ```import tf.keras``` |

#3. Google Colabで、TensorflowのVersionを変更する方法
2020年9月の時点で、Google ColabでのTensorflowのVersionは2.3です。しかし、ローカルマシンのTensoflowのVersionが2.1だとしましょう。その時、Google ColabのTensorflowのVersionを2.3から2.1に変更する必要があります。

```python
#Google Colabに入力
#Downgrade tensorflow

!pip install tensorflow-gpu==2.1
import tensorflow as tf
print(tf.__version__)
```

#4.参考資料
1. [Stop Installing Tensorflow using pip for performance sake!](https://towardsdatascience.com/stop-installing-tensorflow-using-pip-for-performance-sake-5854f9d9eb0c)
2. [AttributeError: module 'tensorflow' has no attribute 'compat'](https://github.com/tensorflow/tensorflow/issues/40422)
[mac] Rstudioで日本語入力時に入力文字が表示されない

# 概要
MacにてRstudioを使ってスクリプトを書いているときに、確定する前の日本語が画面に表示されない現象が起こっていた。
ググってみたが解決策がなく、色々試しているとある程度安定して解決できるようになったのでそれを記す。

# 忙しい人のための解決策
プロジェクト起動後にダミーのRscriptなどをSourceペインに開き、新たにScriptファイルを開いて編集すると入力中の日本語が表示できる！

# 環境
- Mac OS Catalina 10.15.6
- R version 4.0.2
- Rstudio version 1.3.1073
    - R, RstudioはHomebrew経由でインストール

# 現象

1. 新規プロジェクトを作成
2. 新規R Scriptを作成
3. 日本語入力中に以下のような現象になった。(日本語入力をONにして「てすと」と入力している)
![スクリーンショット 2020-09-17 17.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265129/4da2e862-94db-7e0e-0876-455e2c9c43c6.png)

- 変換中も文字は表示されず、確定したときには問題なく日本語で表示される。
- 画像はGoogle日本語入力を使っているときの結果だが、Macデフォルトの日本語入力を使っても同じ現象になった。
- R Notebook形式で作成した場合も同じ現象になった。

# 解決方法

1. 新規プロジェクトを作成
2. 新規R Script（もしくはその他ファイル形式）を作成
3. 更に新規のR Scriptを作成
4. 日本語入力をするとしっかりと文字が表示されるようになった！！！
![スクリーンショット 2020-09-17 17.41.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265129/daf4a046-cb65-c5e2-8cdc-89c9031b123a.png)

# まとめ
スマートな解決方法では無いですが、個人的には満足です。
先日作成したテキストをカラフルにするエクスプレッションを貼っておく。

動画はこちら
![コンポ-1-(0-03-03-23).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178061/0f3b9f91-5ac9-0c19-baa0-f1d14f3779ef.jpeg)

https://youtu.be/T37XV15MbE8

#エクスプレッションセレクター量
```jsx
//indexの指定
const colorLength = thisComp.layer("ColorController001").effect("カラー制御")("カラー").propertyGroup(2).numProperties;
let targetTextIndex = textIndex % colorLength;
targetTextIndex = (targetTextIndex == 0)? colorLength : targetTextIndex;
//targetの指定
const setNum = Math.floor(time*5);
const offsetInd = thisProperty.propertyGroup(3).propertyIndex;
const setNumMod = setNum%thisComp.layer("マイラマイライ").text.sourceText.length+offsetInd;
let result = setNumMod%colorLength;
result = (result == 0)? colorLength : result;

if ( targetTextIndex == result ){
	100
}else{
	0
}
```

#カラーのエクスプレッション
```jsx
colorLength = thisComp.layer("ColorController001").effect("カラー制御")("カラー").propertyGroup(2).numProperties;
myProp = (thisProperty.propertyGroup(2).propertyIndex) % colorLength;
//ゼロ処理
myProp = (myProp == 0)? colorLength :myProp;
thisComp.layer("ColorController001").effect(myProp)("カラー");
```

#ついでにエクスプレッションセレクターの基準を変更出来るスクリプトも貼っておく。
最後のsetValue(n)この中の数値を1～4で変更すれば、変更出来る
例えばsetValue(4)であれば基準を行に変更出来ます。

```jsx
var myComp = app.project.activeItem;
var selLay = myComp.selectedLayers;
//$.writeln( selLay )
for (var i = 0 ;  i <selLay.length; i++ ){
   //$.writeln( selLay[i].property("ADBE Text Properties").numProperties )
   numProp = selLay[i].property("ADBE Text Properties").numProperties;
   for ( var j= 1; j < numProp+1 ; j++){
       //プロパティの名前にcolorが入っているかチェック
       var myProp = selLay[i].property("ADBE Text Properties").property("ADBE Text Animators").property(j);
        var regExp = /color/;
        if ( regExp.test( myProp.name ) == true ){
            //$.writeln(myProp.property("ADBE Text Selectors").property(2).property("ADBE Text Range Type2").value)
            myProp.property("ADBE Text Selectors").property(2).property("ADBE Text Range Type2").setValue(1)
        } 
   }
}
```

#ちなみに
今リリックビデオ作成中でその作業で必要なものをメモしていきます。
[Blade]@includeWhenを使えば@if @include @endif と書くよりシンプルだった

# はじめに

`@includeWhen`というBladeディレクティブはご存知ですか？ 私は知りませんでした。

# @includeWhen

これを

```php
@if($bool)
    @include('view.name')
@endif
```

こう書けます。

```php
@includeWhen($bool, 'view.name')
```

ただ、以下のような落とし穴もあるようなので、使い所は限られそうです。

[LaravelのincludeWhenはfalseでも右辺の評価が行われてしまう。](
https://qiita.com/rorensu2236/items/09305bc8ea27aae68bba)


`@if @include @endif`と書く方が逆にシンプルかもしれない。

# 他の便利なディレクティブ

公式のドキュメントを読むと`＠includeIf`や`@auth`など、知ってると便利かもしれないディレクティブが色々載っています。
時間があるときに目を通して見ると、スマートな記述方法を見つけられるかもしれません。
Blade拡張を使えば、独自のディレクティブも定義できるようです。

https://readouble.com/laravel/7.x/ja/blade.html

# 参考
- https://readouble.com/laravel/7.x/ja/blade.html
- https://qiita.com/yumaeda/items/75eb84f19dba787b298d
- https://qiita.com/rorensu2236/items/09305bc8ea27aae68bba
ECSでEC2インスタンスを使う

FargateでのECSの方が上手くいったので、今度はEC2インスタンスを用意しようとおもった。
けど、なぜか情報が少なくて一筋縄ではいかなかったのでまとめて見る


# Amazon ECS Container Instance IAM Role

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html

* コンテナインスタンスを起動して、ECSクラスターに登録する前にサービスを起動するためのIAMロールを作る必要がある
* Amazon ECS-optimized AMI でコンテナが作られている前提
* ecsInstsanceRole がIAMロールに見つからなければそれを作る！
    * ロールを作成
    * AWSサービスロールタイプを選択し、 Elastic Container Service をさらに選択
    * ユースケースの選択から「EC2 Role for Elastic Container Service」を選択して、次のステップへ
        * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/8b4bdb7b-9815-7dc0-c7b3-7d9ec9eb404b.png)
    * 「AmazonEC2ContainerServiceforEC2Role」を選択して、次のステップへ
    * ロール名を ecsInstanceRole としてロールの作成を完了させる
    * S3のフルアクセスが必要なので、ecsInstanceRoleを選択し、ポリシーの追加で「AmazonS3FullAccess」をアタッチする

# ECSコンテナを作成

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html
PHP: 連想配列とDB操作（初心者向け）

初心者向けに***DB接続***の記事を書いたのですが、初心者の方に`わからない`と言われました笑
PHP: らくらくPDOクラス

ヒアリングをしてみると間に配列を挟んでるところがごちゃつくようです。

***DB -> PDOでDBからデータGet -> なんかわからんけどforeach？？***

正解は「連想配列に一旦、格納する！！」です。

***DB -> PDOでDBからデータGet -> `連想配列に格納` -> foreachで展開***

###配列変数 -> １つの変数で複数の値を格納できるスグレモノ。
```php:変数と配列変数の比較
普通の変数   //入る場所は一つ
$b = 1;
echo $b;    //-> 1

配列変数（連想配列） //入る場所が複数, 添字キーで格納 key: value

//連想配列を１つつくってみます（生成）: key => value
$bar = ['id' => 1, 'name' => 'CakePHP', 'birthday' => '2005-04-01'];

var_dump($bar);         //一度確認しましょう！

//呼び出し方
echo $bar['id'];        //-> 1
echo $bar['birthday'];  //-> 2000-02-03

//foreachで呼び出す
foreach ($bar as $val) {
    echo $val . ',';
}                       //-> 1,CakePHP,2000-02-03
```
###多次元配列（配列の中に配列が入ります。）

```php:多次元配列（連想配列）
データベースと連動してよく使われます。
-> DBテーブル名 -> key
-> DBデータ   -> value

//多次元配列を生成してみます: key => value
$bars = [['id' => 1, 'name' => 'CakePHP', 'birthday' => '2005-04-01'],       //0
         ['id' => 2, 'name' => 'Laravel', 'birthday' => '2011-06-01'],       //1
         ['id' => 3, 'name' => 'Ruby on Rails', 'birthday' => '2004-07-01'], //2
];

var_dump($bars);             //必ず確認します！

呼び出し方
echo $bars[0]['birthday'];   //-> 2005-04-01
echo $bars[1]['name'];       //-> Laravel
echo $bars[2]['id'];         //-> 3

foreachで呼び出す: 
//1ループ目: $bar <- ['id' => 1, 'name' => 'CakePHP', 'birthday' => '2005-04-01']
//2ループ目: $bar <- ['id' => 2, 'name' => 'Laravel', 'birthday' => '2011-06-01']
//3ループ目: $bar <- ['id' => 3, 'name' => 'Ruby on Rails', 'birthday' => '2004-07-01']
foreach ($bars as $bar) {
    echo $bar['id'] . ':';
    echo $bar['name'] . ',';
}  //-> 1:CakePHP,2:Laravel,3:Ruby on Rails,

多重ループで全て呼び出す。
//$bars -> [id, name, birthday] -> $bar 以下繰り返し
foreach ($bars as $bar) {
    foreach ($bar as $val) {
        echo $val . ',';
    }
    echo '<br>';
}  //-> 1,CakePHP,2005-04-01,
   //   2,Laravel,2011-06-01,
   //   3,Ruby on Rails,2004-07-01,
```

####foreachでキーと値の取得
```php
$values = [
    1 => 'CakePHP',
    2 => 'Laravel',
    3 => 'Ruby on Rails',
];
foreach ($values as $key => $value) {
    echo $key . ': ' . $value . '<br>';
}
// 1: CakePHP
// 2: Laravel
// 3: Ruby on Rails
```

###PDOとの連携
例の中で連想配列・多次元配列を生成している部分をPDOがやってくれます。
その後は`foreach`でデータをブン回して処理しましょ！

LGTMお願いします！
モチベーションがあがります！
MacでGNUブランドのsed & awkを利用する時の備忘録

Macのsed & awkはBSD UNIXの物が標準でインストールされています。ひょんな事からsed & awkを勉強しようと思い立った矢先、書籍やWebの情報はGNUブランドのsed & awkの情報が圧倒的に多いことが分かりました。MacでもGNUブランドのsed & awkを利用するための設定を備忘録にまとめておこうと思います。

:warning: 2023/5/17 最新のGNU Sed, GNU AWKに対応した情報に更新しました．

# sed
参考記事より、まずHomebrewでgsedをインストールします。

```bash
brew install gnu-sed
```

`.bash_profile`に`PATH`を書き込み、有効化します。

```bash
echo 'export PATH="(brew --prefix)/opt/gnu-sed/libexec/gnubin/:$PATH"' >> ~/.bash_profiile
source ~/.bash_profile
```

```bash
$ sed --version
sed (GNU sed) 4.8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
Paolo Bonzini, Jim Meyering, and Assaf Gordon.

This sed program was built without SELinux support.

GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.
E-mail bug reports to: <bug-sed@gnu.org>.
```

* [参考: macOS標準sedをGNU sedに置き換える](https://qiita.com/yohhoy/items/f026173bfb70cad52f8a)

# awk
sedと同様の方法で設定出来ます。

```bash
brew install gawk
```


`.bash_profile`に`PATH`を書き込み、有効化します。

```bash
echo 'export PATH=(brew --prefix)/opt/gawk/libexec/gnubin:$PATH' >> ~/.bash_profile
source ~/.bash_profile
```


```bash
$ awk --version
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
Copyright (C) 1989, 1991-2021 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
```
ASTERIA Warpで在庫一覧をNest Hubに表示してみる

[ASTERIA Warpでも十分いけそうな感じがする](https://qiita.com/zrock/items/45a9867a9b7f8593d8d5)ので、ASTERIA Warpならではのエンタープライズ向けに仕立て上げてみる。

# 使用環境
* Windows 10 1909 (18363.1049)
* ASTERIA Warp 1912 Standard Edition
* Python 3.8.5
* CATT v0.11.3
* MySQL 8.0.21

# CATT、ASTERIA Warpの準備
CATTの準備はこちら。
* GravioでChromecastに動画を流す: Windows編
* GravioでChromecastに動画を流す: ラズパイ/Linux編
* CATTを使ってラズパイからChromecastやNest Hubに動画やWebサイトをキャストしてみる

ASTERIA Warpは普通にインストールしてください。EXEコンポーネントを使うのでStandard以上で。

# ASTERIA Warpで在庫一覧をできるようにしておく
今回、ASTERIA Warpで簡単に作っちゃいます。MySQLにこんなテーブルを作成しておきます。
![inventory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/278c4dff-f5d9-6dec-e4aa-90a7ca01785e.png)

在庫一覧はテンプレート「テーブル検索」を使います。

![tablesearch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/63a2603b-a587-e262-c4b4-5422dd614477.png)

ウィザードでコネクションとテーブルを選択するだけ。

![select_table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/df70c6d4-bf59-073f-4b86-55e482ce08f4.png)

するとフローやファイルが作成されます。
![intentoryflows.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/26c81e94-1108-5670-60e4-597945e726eb.png)

できたプロジェクトふたつを開いて保存し、「在庫管理.html」を右クリックして「ブラウザから開く」を選ぶとブラウザでテーブル一覧が表示できます。パチパチパチ
![inventorysite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/b137f726-8da3-a3b2-a58f-369a9b3c9f94.png)

# Nest Hubに表示する
ここまでできたらあとはCATTを呼び出すだけ。[前回](https://qiita.com/zrock/items/45a9867a9b7f8593d8d5)と同じく、EXEコンポーネントを置いて、`catt`コマンドと引数を渡します。
今回は静的サイトなので`cast`コマンドではなく`cast_site`を使います。引数のURLには先程作ったHTMLのURLをコピーすればよいですが、localhostではなく、Warpサーバーの入っているPCのIPアドレスを指定します。
![inventoryflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/3a3c0e62-f2e1-372a-803b-53beff2797a2.png)

|プロパティ|値|
|----:|:--|
|ファイルパス|catt|
|引数|-d <デバイス名> cast_site  http://＜IPアドレス＞:21380/ktamura/%E5%9C%A8%E5%BA%AB%E7%AE%A1%E7%90%86.html |

あとは実行するだけです。
![inventry.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/a61d65e0-15d9-99c3-6d56-278e0582b49b.gif)

あとはこれをスケジューラーで定期実行して、Chromecastで大画面ディスプレイに表示すれば、お手軽在庫確認サイネージが出来上がりですね！