OmniAICreator/Qiita-1.07M huggingface dataset:
SSLアクセラレーションとは

## 勉強前のイメージ

LBやfirewallなどで、SSLの暗号化とか復号化とかすること

## 調査

### SSLアクセラレーション

SSL(/TLS)アクセラレーションとは、LBやfirewallなどでSSL通信を暗号化・復号化する処理のこと

### SSLアクセラレーター

`SSLアクセラレーション` と似ていますが、
LBやfirewallなどでSSL通信を暗号化・復号化することを専門に行う`機器`のことを指します。

### 図で解説

以下よくあるwebサーバの構成図になります。

#### 通信説明
- http通信
    - client から webサーバ までずっとhttp通信を行います

- https通信
    - client → LB : https通信
    - LB → webサーバ : http通信

#### SSLアクセラレーションをする理由

実は、以下の図からSSLアクセラレーション(暗号化・復号化)をする場所は
`LB(firewallでもよい)`と`webサーバ`の2つ選択肢があります。

- webサーバで行う場合
	- メリット
		- LBが必須ではないシステムでは、SSLアクセラレーションのためにLB導入をしなくて良い
	- デメリット
		- 大量アクセスが来た際にwebサーバでさばけるアクセス数が、SSLアクセラレーションしない場合と比べて劣る

- LB(firewallでもよい)で行う場合
	- メリット
		- SSLアクセラレーションをLBに任せることによってwebサーバでの負荷が軽減される
	- デメリット
		- SSLアクセラレーションを出来るLBを導入しないといけない


上記でメリデメを記述しましたが、多くの場合以下のLBでSSLアクセラレーションをしている理由としては
webサーバの負荷を下げる狙いがあります。

以下の図の場合のLBは上記に書いたように
`SSL通信を暗号化・復号化することを専門に行う機器` に属します。
webサーバで行うより高速にSSL暗号化・復号化を行うことが出来ます。



![プレゼンテーション1 - PowerPoint 2020-10-07 19.54.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/fb5dd594-2abe-058d-a7e7-34494fdbabb2.png)


## 勉強後のイメージ

イメージ合ってた。
感覚、webサーバの負荷が上がるのはわかるけど、どれだけ上がるのか気になるところ...

## 参考

- [SSLアクセラレーターとは？特徴やサーバ証明書との関連性まとめ](https://t-tel.net/ssl/ssl030/)
- [常時HTTPS化の落とし穴＜解決編＞](https://www.tribeck.jp/column/opinion/technology/20171016/)
Laravel 6.xでのメール認証機能導入後のBladeテンプレートの分岐処理

## 背景

Laravel 6.x LTSを使っていて、以下の手順でメール認証機能を導入した。

* [認証 6\.x Laravel](https://readouble.com/laravel/6.x/ja/authentication.html)

導入した後、Bladeテンプレート側に書いてた `@auth` や `@guest` をメール確認済みかどうかで分岐させたいとき、どう書けばいいんだろうか？ となった。ドキュメントには特に何も書かれていなかったので自分で実験して調べてみた、という記録。

※なお執筆時点で最新のLaravel 8.xはまた全然違うものになってるようなので、これはあくまでもLaravel 6.x向けであることを最初に補足しておく。でも6.xはLTSなのでしばらくは有用なはず……。

## まず結論

元の記述
※`resources\views\layouts\app.blade.php` などにも最初からある記述

```php
@guest
  // 未ログイン状態の処理
@else
  // ログイン状態の処理
@endguest
```

修正後

```php
@if(!Auth::check())
  // 未ログイン状態の処理
@elseif(Auth::user() && !Auth::user()->hasVerifiedEmail())
  // ログイン状態の処理（メール確認が済んでいないがメアドとパスを入力した状態）
@else
  // ログイン状態の処理（メール確認済み）
@endif
```

## 解説

### 元の `@auth` や `@guest` は使えなくなるのか

修正前の記述も、これはこれで使用可能ではある。
しかし元の `@auth` や `@guest` ではメール確認が済んでいるかどうかの判別が出来ず、いっしょくたに「ログイン済みかどうか」だけで判断されてしまうのである。

```php
@guest
  // 未ログイン状態の処理
@else
  // ログイン状態の処理（★メール確認を済ませてない人を含む）
@endguest
```

※ `@auth` ～ `@endauth` の場合は上記の条件がひっくり返っただけ。

もちろん元の記述で問題ないならそれで良い。
でもメール確認が済んでいるかどうかも区別するには、結論に書いたような表現をする必要がある、ということの模様。

Laravelの用意してる認証機能は、内部的には「メール確認が済んでいなくてもログイン自体は出来る」という仕様のようですね。メール認証が済んでいないとログイン自体出来ないサービスが多い印象なので、つい勘違いしてしまいがちですが。

### ログアウトボタンを見せる条件

ではこのとき、ナビゲーションバーなどでログアウトボタンを見せるべき条件はどうなるかというと、これは従来の `@auth` の条件と変わっていない。メール確認が済んでいないユーザーであろうとログインはログインということのようなので。

結論に書いた条件文で言えば、ログイン/ログアウトボタンは以下のように用意してあげる必要がある。

```php
@if(!Auth::check())
  // 未ログイン状態なので、ログインボタンが欲しい
@elseif(Auth::user() && !Auth::user()->hasVerifiedEmail())
  // メール確認済んでないけどログイン済みなので、ログアウトボタンが欲しい
@else
  // メール確認済みでログイン済みなので、ログアウトボタンが欲しい
@endif
```

真ん中の場合が直感的に分かりづらいけど、まあそういうものなので。

## おまけ

認証機能で用意されているメールをカスタマイズしたい場合は、手前味噌だけど以下の記事を参照。

* [Laravel6\.xでパスワードリセットメールをカスタマイズする \- Qiita](https://qiita.com/daijin/items/8bc658c9b14cdd15260c)
Chrome 画面遷移してもconsole.logを残す

下記を参照して実施

[Google Chromeでコンソールのログを遷移しても残す](https://spphire9.wordpress.com/2012/08/28/google-chrome%E3%81%A7%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%92%E9%81%B7%E7%A7%BB%E3%81%97%E3%81%A6%E3%82%82%E6%AE%8B%E3%81%99/)

●デベロッパーツールを表示させる
●歯車のマークを押し"console"→"Preserve log upon navigation"にチェックを入れる
SeleniumによるWebスクレイピングで活躍するexecute_scriptメソッド

# はじめに
SeleniumでWebスクレイピングを行う際に活躍してくれるexecute_scriptメソッドについてまとめます。execute_scriptはJavaScriptで記述した動作をWebページに対して実行してくれるものです。

# 目次
1. execute_scriptを使わない場合はfind_element
2. execute_script
3. メソッドにして、より使いやすく
4. まとめ

#1. execute_scriptを使わない場合はfind_element、find_elements

SeleniumでWebスクレイピングを行う場合、通常はfind_element、find_elementsメソッドで要素を指定し、clickメソッドなどを実行することで、ページ処理を行います。

#####find_element、find_elementsを使った場合

```ruby
# クリック動作(例：submit_btnというクラス、"送信"というvalueを持つinput要素)
@driver.find_element(:class,'submit_btn').click # クラスで指定
@driver.find_element(:css,"input[value='送信']").click # CSSで指定

# 値の入力
@driver.find_element(:name,'favorite_food').send_keys('ramen')

# 要素の数を調べる
@driver.find_elements(:class, '.btn').size # ボタンの数を確認。
```

#2. execute_script

上のfind_element(s)であると、正確に要素を指定できているかを確認するのに毎回rubyを実行しなければならないため、少々面倒くさいです。そこで、以下のようにexecute_scriptで同じ動作を実装してみます。


#####execute_scriptを使った場合

```ruby
# クリック動作
@driver.execute_script(%{document.querySelector('.submit_btn').click();}) # クラスで指定
@driver.execute_script(%{document.querySelector("input[value='送信']").click();}) # CSSで指定

# 値の入力
@driver.execute_script(%{document.querySelector("[name='favorite_food']").value = 'ramen';})

# 要素の数を調べる
@driver.execute_script(%{return document.querySelectorAll('.btn').length;}) # ボタンの数を確認
```

execute_scriptの引数に直接実行したいJavaScriptコードを書きます。こうすることで、WebブラウザでJavascriptを実行しながら、開発を行うことができます。chromeの場合は、デベロッパーツールのConsoleタブにJavaScriptを打ち込むだけで、実行を行うことができます。これにより、エディタやターミナルを往復する回数が激減し、効率的な開発が可能となります。

#3. メソッドにして、より使いやすく

また、冗長性の削減や読みやすさを考えて、メソッド分割でリファクタリングするのが望ましいです。この場合、cssセレクタや送りたい値などを引数に渡してあげるようにします。

##### JavaScriptによる処理をメソッド定義した場合
```ruby

# クリック動作のメソッド
def query_click(css_selector)
  @driver.execute_script(%{document.querySelector("#{css_selector}").click();})
end

# 値の入力をするメソッド
def value_input(css_selector,value)
  @driver.execute_script(%{document.querySelector("#{css_selector}").value = "#{value}";})
end

# 要素の数を調べるメソッド
def query_count(css_selector)
  @driver.execute_script(%{return document.querySelectorAll("#{css_selector}").length;})
end

query_click('.submit_btn')         # クラスで指定してクリック
query_click("input[value='送信']") # cssで指定してクリック 

value_input("[name='favorite-food']",'ramen') # 値の入力

query_count('.btn') # ボタンの数を調べる
```

#4. まとめ
execute_scriptによってSeleniumにJavaScriptを実行させるやり方をまとめました。JavaScriptはページをまたいでの処理ができないため、ページ遷移させて繰り返し処理を実行したい場合などにはfind_elementを使用したほうがいいかもしれません。どちらも使えるようになっておくと、Webスクレイピングが捗ると思います。是非活用してみてください。
Git ローカルブランチの名前を変更する

# 目的

- ローカルリポジトリの名前を変更する方法をまとめる

# 詳細

- Git管理されているディレクトリに移動する。
- 下記コマンドを実行してブランチ名を変更する。

    ```terminal
    $ git branch -m 変更したい現在のブランチ名 変更後のブランチ名
    ```
neo4jでsandbox その13

#概要

neo4jでsandboxやってみた。
movielens、やってみた。
レコメンドしてみた。

#コサイン類似度で映画をお勧め。


```
MATCH (p1:User {id:21})-[x:RATING]->(m:Movie)<-[y:RATING]-(p2:User)
WITH COUNT(m) AS numbermovies, 
	SUM(x.rating * y.rating) AS xyDotProduct,
	SQRT(REDUCE(xDot = 0.0, a IN COLLECT(x.rating) | xDot + a ^ 2)) AS xLength,
	SQRT(REDUCE(yDot = 0.0, b IN COLLECT(y.rating) | yDot + b ^ 2)) AS yLength,
	p1, 
	p2 
WHERE numbermovies > 10
WITH p1, 
	p2, 
	xyDotProduct / (xLength * yLength) AS sim
ORDER BY sim DESC 
LIMIT 10
MATCH (p2)-[r:RATING]->(m:Movie) 
WHERE NOT EXISTS((p1)-[:RATING]->(m))
RETURN p1.name, 
	p2.name, 
	m.title, 
	SUM(sim * r.rating) AS score
ORDER BY score DESC 
LIMIT 5

```

#python実行結果

```
title   score
Shawshank Redemption, The (1994)  29.503255423721242
WALL揃E (2008)  26.663597071412074
Inglourious Basterds (2009)  25.151535146327763
Whiplash (2014)  17.84941121812618
Shutter Island (2010)  16.417668233642118


```

以上。
複数の整数で各々の差の条件で真偽判定


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

<b>2.どのようにプログラムするか</b>

<b>3.開発環境</b>



1.結論
----------------------------------------
<b>absメソッド、if</b>を使う！
<br>

2.どのようにプログラムするか
----------------------------------------

```ruby
def close_far(a,b,c) #---❶
  x_mar = (a-b).abs
  y_mar = (a-c).abs
  z_mar = (b-c).abs
 if (x_mar == 2 && z_mar >= 3) || (y_mar == 2 && z_mar >= 3) #---❷
   puts "True"
  else
   puts "False"
 end
end
```
今回は整数を3つにしました。

❶：absメソッドを使用し、正負関係なしに絶対値を返しそれぞれを変数に代入しています。
❷：今回は「"a"と"b”の差が2　または "a"と"b”の差が2
 かつ "b"と"c”の差が3」としています。下記のようにコーディングすることも可能ですが、上記のように「()と||(OR)と&&(AND)」で一つにまとめることも可能です。

```ruby
  if x_mar == 2 && z_mar >= 3
    puts "True"
  elsif y_mar == 2 && z_mar >= 3
    puts "True"
  else
    puts "False"
  end
```
<br>

3.開発環境
----------------------------------------
Ruby 2.6.5
Rails 6.0.3.3
Visual Studio Code 1.49.2
neo4jでsandbox その12

#概要

neo4jでsandboxやってみた。
movielens、やってみた。
レコメンドしてみた。

#jaccardで映画をお勧め。


```
MATCH (m:Movie {title:"Short Circuit (1986)"})-[:GENRE]->(g:Genre)<-[:GENRE]-(other:Movie)
WITH m,
	other,
	COUNT(g) AS intersection,
	COLLECT(g.name) AS i
MATCH (m)-[:GENRE]->(mg:Genre)
WITH m,
	other,
	intersection,
	i,
	COLLECT(mg.name) AS s1
MATCH (other)-[:GENRE]->(og:Genre)
WITH m,
	other,
	intersection,
	i,
	s1,
	COLLECT(og.name) AS s2
WITH m,
	other,
	intersection,
	s1,
	s2
WITH m,
	other,
	intersection,
	s1 + filter(x IN s2 WHERE NOT x IN s1) AS union,
	s1,
	s2
RETURN m.title,
	other.title,
	s1,
	s2,
	((1.0 * intersection) / SIZE(union)) AS jaccard
ORDER BY jaccard DESC
LIMIT 5

```

#python実行結果

```
title   jaccard
Cocoon: The Return (1988)  1.0
Evolution (2001)  1.0
Hot Tub Time Machine (2010)  1.0
Cocoon (1985)  1.0
Americathon (1979)  1.0

```

以上。
neo4jでsandbox その11

#概要

neo4jでsandboxやってみた。
movielens、やってみた。
レコメンドしてみた。

#ユーザーの評価してるジャンルの映画をお勧め。

```
MATCH (u:User {id:21})-[r:RATING]->(m:Movie)
WITH u,
	avg(r.rating) AS mean
MATCH (u)-[r:RATING]->(m:Movie)-[:GENRE]->(g:Genre)
WHERE r.rating > mean
WITH u,
	g,
	COUNT(*) AS score
MATCH (g)<-[:GENRE]-(rec:Movie)
WHERE NOT EXISTS((u)-[:RATING]->(rec))
RETURN rec.title AS recommendation,
	COLLECT(DISTINCT g.name) AS genres,
	SUM(score) AS sscore
ORDER BY sscore DESC
LIMIT 5

```

#python実行結果

```
title   genres  score
Confessions of a Dangerous Mind (2002)   ['COMEDY', 'CRIME', 'THRILLER', 'DRAMA', 'ROMANCE']  639
Maximum Ride (2016)   ['SCI-FI', 'COMEDY', 'ACTION', 'THRILLER', 'ADVENTURE', 'FANTASY']  637
Rubber (2010)   ['COMEDY', 'ACTION', 'CRIME', 'THRILLER', 'DRAMA', 'MYSTERY', 'ADVENTURE', 'WESTERN', 'HORROR', 'FILM-NOIR']  632
Mars Needs Moms (2011)   ['SCI-FI', 'COMEDY', 'ACTION', 'ADVENTURE', 'CHILDREN', 'ANIMATION', 'IMAX']  628
Dragonheart 2: A New Beginning (2000)   ['COMEDY', 'ACTION', 'THRILLER', 'DRAMA', 'ADVENTURE', 'FANTASY']  606


```

以上。
mixhost上でPHP Warning:  Cannot modify header informationが発生した場合の対処

【背景】レンタルサーバーmixhost上のphp環境で"twitteroauth"を使用しtwitter認証を実施

【問題】PHP Warning:  Cannot modify header information - headers already sent by(output started at /home/xxxxxx/public_html/xxxxx/twitter-login/login.php:8) が発生
※2箇所で発生し、いずれもheader()指定

【対応】下記サイトを参考に対応実施
[「Warning: Cannot modify header information…」エラーの解決方法[PHP]](https://kotori-blog.com/php/cmhi_error/)

●mixhostの"MultiPHP INI Editor"の"編集モード"で"output_buffering = 4096"を設定

![phpini.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596059/ff369d84-4176-db0e-a904-557a55e6335b.png)

以上で解決
neo4jでsandbox その10

#概要

neo4jでsandboxやってみた。
movielens、やってみた。
レコメンドしてみた。

#とりあえず、評価の良い映画をお勧め。

```
MATCH (u:User {id:21})
MATCH (u)-[r:RATING]->(m:Movie)
WITH u,
	avg(r.rating) AS average
MATCH (u)-[r:RATING]->(m:Movie)
WHERE r.rating > average
RETURN m.title, 
	r.rating
limit 5
```

#python実行結果

```
title        rating
Short Circuit (1986)   4.0
Rush Hour (1998)   3.5
Da Vinci Code, The (2006)   3.5
Never Say Never Again (1983)   5.0
Thunderball (1965)   4.5

```

以上。
webarenaでsshするまで

どハマりしたのでメモだけ残しておく。

# 基本的には

https://help.arena.ne.jp/hc/ja/articles/360039332013-SSH%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B5%E3%83%BC%E3%83%90%E7%AE%A1%E7%90%86

これに従えばいいんだけど

自分ちのwifiは定期的にfromのIPが変わるので、面倒だったので、0.0.0.0をhosts.allowに許可すればOKかなって思ってたけど

それがそもそも間違い。
ちゃんとIP指定しなきゃダメ。

それにどハマりした。

って話

```
ssh_exchange_identification: read: Connection reset by peer
```

これをぐぐることと、

```
/var/log/secure
```

をみることを怠った自分が愚かでした。
Ubuntu, Python, OpenCV な環境を Docker 上でつくった

Ubuntu をベースに Docker コンテナ生成して中に入る

ローカルでファイル共有したいのでボリュームをマウントしている
Jupyter を使いたいので port をつなげている

```
docker run -it -v $(pwd):/code -p 8888:8888 --name opencv ubuntu /bin/bash
```

恒例行事

```
apt-get -y update && apt-get -y upgrade
```

各種インストール

```
apt-get -y install python3-pip vim
pip3 install opencv-python jupyterlab pandas matplotlib scikit-learn seaborn
apt-get -y install libgl1-mesa-dev libgtk2.0-dev 
    # これらを入れないと import cv2 でエラーになる
```

# Jupyter 起動させたいとき

```
jupyter lab --ip=0.0.0.0 --allow-root --LabApp.token=''
```

これを実行してブラウザで localhost:8888 にアクセスする

# 課題点

このやり方だと `cv2.imshow()` が実行できないですよねぇ。。。
解決次第更新します。

解決方法わかる方いたら教えて下さい。。。

（メモ）
この辺が参考になりそう
https://qiita.com/oreyutarover/items/cca3511012b6ad97a1ce
https://kamino.hatenablog.com/entry/docker_gui

# 追記 2020/10/10

`cv2.imshow()` が動くバージョンを別記事で書きました!!
https://qiita.com/RyuGotoo/items/3e36622c52beb9d4e932
Vuex~Vue.jsとNuxt.jsで書き方がちょっと違う！？

#はじめに
勉強中の身です、そのため勘違い等あるかもしれません。
``Vue.js``での``Vuex``の書き方？はなんとなくわかっているつもりで
今回簡単なアプリを``Nuxt.js``で書こうと思いって``Vuex``の書き方でハマったのでメモとして残します。

#Vue.jsの場合

```javascript
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const state = {
  nowNumber: 0,
};

export const mutations = {
  increment(state) {
    state.nowNumber++;
  },
  decrement(state) {
    if (state.nowNumber <= 0) return;
    state.nowNumber--;
  },
  reset(state) {
    state.nowNumber = 0;
  },
};

export const actions = {
  increment({ commit }) {
    console.log('increment');
    commit('increment');
  },
  decrement({ commit }) {
    console.log('decrement');
    commit('decrement');
  },
  reset({ commit }) {
    console.log('reset');
    commit('reset');
  },
};

export default new Vuex.Store({
  state,
  mutations,
  actions,
});

```
コード自体は気にせずに
こんな感じですよね

これを分割して書くと

```javascript
export const state = {
  nowNumber: 0,
};
```
こんな感じでファイルをわけて

```javascript
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state.js'
import mutations from './mutations.js'
import actions from './actions.js'

Vue.use(Vuex);

export default new Vuex.Store({
  state,
  mutations,
  actions,
});
```

でそのファイルを``import``したら同じ用に使える。

#Nuxt.jsの場合

```javascript:store/index.js

export const state = () => ({
  nowNumber: 0,
});

export const mutations = {
  //省略
};

export const actions = {
  //省略
};

export default ({
  state,
  mutations,
  actions,
});
```

違いとして``Nuxt.js``の場合``Vuex``が組み込みになっているみたいなので
``import``の必要がないのと``state``が__関数に__なる
問題はここからで、これを分割する場合、上の``Vue.js``の時と同じ書き方をするとできない。。。
ちゃんと動くようにするには


```javascript:actions.js
import getters from './getters'

export default {
  postMessage({ commit }, message) {
    const postData = {
      id: getters.fetchId(),
      memo: message,
      date: getters.fetchDate(),
    }
    commit('messageBox', postData)
  },
}
```

```javascript:getters.js
export default {
 fetchId() {
    const id = //省略
    return id
  },

  fetchDate() {
    const d = new Date()
    const date = `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日`
    return date
  },
}
```

``export default``なんですね中身の書き方は同じ感じ
``actions``で``getters``使いたいとかの場合``import``する必要があるっぽい
後はこれを``index.js``で``import``

```javascript:store/index.js
import getters from './getters'
import actions from './actions'
export const state = () => ({
  messages: [],
  sample: 'test',
})

export const mutations = {
  messageBox(state, messageData) {
    state.messages.push(messageData)
  },
}

export default {
  state,
  mutations,
  actions,
  getters,
}
```


これで無事使えるようになった！
Pythonで文字列を比較する

#なんで必要なのか
Pythonエンジニア認定試験を勉強している時に、比較演算で文字列を比較しており理解できなかったものを、理解したためまとめておきます。

#どういったものか

```terminal
 >>> 'ABC'<'C'<'Pascal'<'Python'
True
```

上記の比較がなぜ`True`になるのか。
→`文字コード`を比較しているため

そもそも、文字コードポイントとはpythonがあらかじめ設定しているものです。`ord(文字列)`で簡単に確認できます。
例えば、`ord('a')`ならば97、`ord('A')`だと65といったようになっており、上記の文字列の比較はこの数値を比較しています。
ただし、文字列のコードポイントを比較するといっても、`ord('ABC')`はタイプエラーが返ってきます。

#実際に

```terminal
 >>> 'ABC'<'C'<'Pascal'<'Python'
True
```

注意点として、文字列の比較は最初の文字コードのポイントを比較しています。
`ord('A')=65` < `ord('C')=67`という風にです。
'Pascal'や'Python'は'P'始まりなので次も文字'a'と'y'を比較します。
`ord('a')=97` < `ord('y')=121`なので'Pascal'<'Python'は正しいことになります。
ファイルを一行ずつ読み込むVS一気に読み込む

ファイルの読み込みをするときに一気に読み込むのではなく1行ずつ読み込んだ方がメモリ的にいいとのこと
それが本当がどうかの実験をしてみようかと思います。

読み込み対象となるテキストは以下のものです。

    test.txt
    john	m	19
    micheal	m	28
    abbie	f	31
    dabid	m	17
    claire	f	26



#まず、一気に読み込んでみる
以下のコードでやってみる

    require 'objspace'

    start_time = Time.new

    puts File.read("test.txt")

    end_time = Time.new

    puts end_time - start_time
    puts "#{ObjectSpace.memsize_of_all * 0.001 * 0.001} MB"

読み込む部分をとても短く書きました。
そして、結果は

    $ ruby all_read.rb
    john	m	19
    micheal	m	28
    abbie	f	31
    dabid	m	17
    claire	f	26
    4.9e-05
    2.951902 MB


#次に1行ずつ読んでみる
以下のコードでやってみる

    require 'objspace'

    start_time = Time.new

    File.open("test.txt") do |text|
      text.each_line do |line|
         puts line
       end
    end

    end_time = Time.new

    puts end_time - start_time
    puts "#{ObjectSpace.memsize_of_all * 0.001 * 0.001} MB"

  

一気に読み込むのと対照的に少し行数が増えました。
そして、結果は

    $ ruby each_read.rb
    john	m	19
    micheal	m	28
    abbie	f	31
    dabid	m	17
    claire	f	26
    0.000112
    2.9598400000000002 MB

数回同じ操作をしたのですが、
行数が少ないと一気に読み込んだほうがメモリの使用量が少ないのかな？と思います。



では、もっと長いテキストでやってみたらどうなるかを考えます。

#もっと長いテキストで考えてみる

    test.txt
    john	m	19
    micheal	m	28
    abbie	f	31
    dabid	m	17
    claire	f	26
    (中略)
    john	m	19
    micheal	m	28
    abbie	f	31
    dabid	m	17
    claire	f	26　

と、とりあえず同じ行を増やしただけなのですが、
1000行,5000行,10000行で考えてみたいとおもます。

#1000行のテキストの読み込み
それぞれ5回測ってみました。

|    |  1  |  2  |  3  |  4  | 5  |
| ---- | ---- | ---- | ---- | ---- | ---- |
|  一気に読み込む  |  2.965176 MB  |2.963405 MB  |2.965656 MB  |2.965656 MB  |2.965656 MB  |
|  一行ずつ読む  |  3.002243 MB  |3.000736 MB  |2.999688 MB  |2.999808 MB |3.002083 MB  |
#5000行のテキストの読み込み

|    |  1  |  2  |  3  |  4  | 5  |
| ---- | ---- | ---- | ---- | ---- | ---- |
|  一気に読み込む  |  3.010936 MB  |3.011384 MB  |3.009285 MB  |3.008709 MB  |3.008349 MB  |
|  一行ずつ読む  |  2.542326 MB  |2.542286 MB  |2.542246 MB  |2.542286 MB  |2.54435 MB  |

#10000行のテキストの読み込み

|    |  1  |  2  |  3  |  4  | 5  |
| ---- | ---- | ---- | ---- | ---- | ---- |
|  一気に読み込む  |  3.065925 MB  |3.065341 MB  |3.065173 MB  |3.068216 MB  |3.067936 MB  |
|  一行ずつ読む  |  2.403886 MB |2.404046 MB  |2.404534 MB  |2.404366 MB  |2.403886 MB  |

#結論
明らかになりました。
行が増えるにつれて、
「一気に読み込む」が増えるのに対して、逆に「1行ずつ読み込む」が減っている。
多く読み込むのであれば「1行ずつ読み込む」方が良い。

けど、処理の時間的に「一気に読み込む」方が短かったです。それはそうか。


#参考文献

http://simplesandsamples.com/readlines.rb.html
https://techacademy.jp/magazine/7797
https://blog.freedom-man.com/measure-ruby-memory-usage
D8 compilerでdefined multiple timesエラー



*エラー文*
”com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives”  "is defined multiple times:"

*原因*
 Android Studio 4.2 canary 12 の D8 compilerのバグ

*エビデンス*
https://issuetracker.google.com/issues/169183194

*対応*
AndroidStudio 3.Xに戻した
AWS自動化の心得（IaC編）

インフラ、基盤の自動化が徐々に必須レベルに近い感じになってきていますので、下記の様な方に向けてAWS自動化の心得を書きます。

　①AWS利用しているが、自動化やIaCの知識はない
　②システムの自動化を頼まれたがちゃんと運用できるのか不安
　③AWS運用を効率化したい
　※①、②は2年前の私の心境。今はAWSを効率よく運用できていると感じてます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311339/8fc93585-2efc-d1be-16fe-7564f0189a8a.png)



まず言っておきたいですが、自動化（IaC）は便利です。
AWSで初めて自動化担当となった方の不安を低減できれば良いなと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311339/25d7ed75-bacb-25c5-7247-0843386997ed.png)

なぜ自動化するのかという点については下記も参考にしてみてください。
（クラウドのベストプラクティス集に自動化必須の旨が記載されています）
[AWS Well-Architected 5本の柱を要約する（運用上の優秀性）](https://qiita.com/toma_shohei/items/3e8338ddfa6aca344c29)

## AWSをIaCで構築する際の心得３つ

### ①Bestは難しい、Betterを目指すので良い
エンジニアとして完璧なものを作りたいというマインドは大事ですが、IaCの手法はまだ発展途上です。完璧を目指し過ぎて納期に遅れることが無いようにしましょう。

### ②まずはIaCをやってみる
部分的（例えばサービス影響のない箇所など）にIaCを導入していくのもありです。
とりあえず自分一人で始めてみるくらいの気持ちでも大丈夫です。
（そしてノウハウたまったらチームに公開）
上手く管理できなかったら途中でリスクなく止めることもできます。

### ③設計書なくせるかどうかは微妙
IaCのメリットで設計書を無くせるというものがありますが、これは微妙です。
設計書と実機の値が乖離するという問題はどこでも起きがちですので、
当時私はこのメリットが大きいなと思っていました。


しかしプロジェクトメンバー全員がコードを読めるわけではないこと、
一覧性（サーバ何台あるかなどがすぐにわからない）にかける部分もあります。
※パラメータからコードと設計書を自動作成する仕組みがあることが
理想かなと思います。


## ※始め方：CDK(Python)で始める
AWSをIaCで管理するツールは多数（CloudFormation、CDK、Terraformなど）あります。
それぞれ特徴がありますが、まずやってみるというところではCDK（Python）で良いのではないかと思っています。
[WindowsにCDK環境構築する手順（Python）](https://qiita.com/toma_shohei/items/985916e1a95ec4c38121)

CDK（Python）の良い所はPythonの勉強も兼ねられるというところです。
※各ツールの比較をしたい場合は「Terraform CDK」などでググってみると機能比較を纏めているサイトが見つかりました。

## 最後に
運用工数削減のためにもどんどん自動化（IaC）が広まってほしいと思います。
私はインフラエンジニアなので、シェル以外のプログラミングをほぼやってこなかったのですが、時間忘れて作業してしまうほどにPythonは楽しいです。
周りの人に自動化肯定派が多かったので、運が良かったかもしれません。（人に恵まれてないと中々踏み出せないかも）
createアクション失敗時にエラーメッセージが表示されない

# 問題発生の経緯
経緯としてはタイトルの通りです。
保存は問題なくできているが、保存が失敗した時にエラー文が表示されず苦戦しておりました。
(コード一部抜粋)

```ruby:laundries_controller.rb
def create
  @laundry = Laundry.new(laundry_params)
  if @laundry.save
    redirect_to root_path
  else
      render :new
  end
end
```

```ruby:new.html.erb
<%= form_with model:@laundry, url: laundries_path, locals: true do |f| %>
  <%= render 'error_messages', model: f.object %>
```

# 結論
ビューファイルの記述に誤りがありました。
正

```ruby
local: true
```

誤

```ruby
locals: true
```

正しい記述に修正したことで無事エラー文が表示されました。
記述ミスによって非同期通信になっていたため、エラーメッセージが正しく表示されていなかったという訳です。
ちなみに```locals```は```render```メソッドのオプションで部分テンプレートで使用する変数の定義ができます。
1文字だけの違いではありますが、その違いで挙動が変わるため、気をつけなければと痛感しました。

# 余談
記事を作成するにあたりコードを表示させたいがなかなかうまくいかず苦戦...
コードを表示させるときはバッククォートの前後は空行にしないといけないのですね
実際に手を動かしながら覚えていくことが大切だと感じました。
Unicodeの文字をサクッと UTF-8 に変換する


uni2ascii というライブラリを使って CLI 上で変換処理をおこないます

```
brew install uni2ascii
```

以下のような感じで簡単に変換ができます。
オンライン上で変換できるサービスはありますが、外部に出したくない機密情報などを扱うときとかに便利です。

```
$ echo '\u7533\u3057\u8fbc\u307f'  | ascii2uni -a U -q
申し込み
```
Twilio Flex Pluginでのデプロイ時のエラー

##バージョン
twilio-cli / 2.10.3
flex-plugin / 4.0.2-beta.0

#Twilioコマンドでデプロイ時に謎のエラーが発生した…
まだ何もデプロイしてない状態で初デプロイしたら何故かエラーが出た。

###デプロイコマンド
```
twilio flex:plugins:deploy --changelog='deploy'
```

###エラー内容
※IDはマスクしてます
>Error code 20404 from Twilio: The requested resource /Services/ZSXXXXXXX/Environments was not found. 
See https://www.twilio.com/docs/errors/20404 for more info.

上記のリソースが無いと言われてるのはわかるけど、何のIDですかそれ:angel:


##心当たりは…？

プラグインのデプロイより前に、serverlessの方(functionsとassetsの方)で
デプロイした時後に、defaultのServiceを手動で削除したけど
それのSIDをプラグインが参照してた…？？

**追記**
**やはりここでdefaultのサービスを削除してしまっていたからというのが原因でした**

defaultサービスのSIDなんて覚えてない～:ghost:

##もうね、サポートに聞いちゃいます！

ほんとに、にっちもさっちも状態だったのでサポートに問い合わせて見ました。
返信あるのか不安でしたが、翌日には返信が…！:joy:

####英語ですが全文載せときます
長いので折りたたんでます

<details><summary>返信内容:envelope:</summary><div>
Thank you for reaching out about about this!

I'm sorry to hear that you are receiving an error 20404 when attempting to deploy your plugin.
This is most likely occurring because the the Plugin Builder is looking for a field called "serverless_service_sids" in your account's configuration and it sounds like that SID was deleted.

This can be fixed by resetting the value in your account's configuration and running twilio flex:plugins:deploy again.
The command to reset the value is shown below. You need to replace the ACCOUNT_SID and AUTH_TOKEN fields with the account information on your Twilio console home page.

```
curl  https://flex-api.twilio.com/v1/Configuration \
    -H "Content-Type: application/json" \
    -d '{"account_sid":"ACCOUNT_SID", "serverless_service_sids": []}' \
    -u ACCOUNT_SID:AUTH_TOKEN
```

After running this command, the next time you run twilio flex:plugins:deploy the configuration field should be set to the correct value.
</div></details>

ざっくりいうと、serverless_service_sidsというのを参照してるけど、削除されてるような感じなので
リセットしてください。
コマンドはこれです。実行したら再度デプロイしてね。

って感じでしょうか？？

とりあえずこのコマンドをやってみます

##serverless_service_sidsリセットコマンド？
```
curl  https://flex-api.twilio.com/v1/Configuration \
    -H "Content-Type: application/json" \
    -d '{"account_sid":"ACCOUNT_SID", "serverless_service_sids": []}' \
    -u ACCOUNT_SID:AUTH_TOKEN
```

serverless_service_sidsを空にしますって感じ？
  
curlコマンド打てないので（Windowsで入れてないので…）
ChromeのAPI Testerを使って叩いてみました。

**すると、何か色々入ったJsonが返ってきましたが、serverless_service_sidsは空になってました。**

これでリセットされたってことなんかな？？

##再度デプロイしてみる

ていっ

```
twilio flex:plugins:deploy --changelog='deploy'
```

```
√ Validating deployment of plugin plugin-XXXXX
√ Compiling a production build of plugin-XXXXX
√ Uploading plugin-XXXXX
√ Registering plugin plugin-XXXXX with Plugins API
√ Registering version v0.0.1 with Plugins API

� Plugin (private) plugin-XXXXX@0.0.1 was successfully deployed using Plugins API
```

**成功した！！:dancer_tone1:**


##まとめ

結局何が原因でこうなったかはわかりませんが（サポートに原因も聞いてみてるので返信あれば追記します）
とりあえず同じ現象が起こったら、このリセットコマンドがあるということで。

##追記
現在設定されている、serverless_service_sidsがわかるコマンドを教えてもらいました。

```
curl -X GET 'https://flex-api.twilio.com/v1/Configuration' \
-u your_account_SID:your_auth_token
```

実行結果のserverless_service_sidsに、↑でデプロイした時に出来たdefault servicesのSIDが入っていました。
なので、defaultのserviceを消すと、このエラーが発生してしまうようです。
Three.jsのShaderMaterialにFogを適用する

Three.jsはWebGL表現を簡単に実現できるライブラリ。それでもやはり自前でシェーダを記述すると表現の幅が広がる。Three.jsには自作シェーダを適用可能なRawShaderMaterialとShaderMaterialのクラスがあり、前者は完全に全てのシェーダを自前で記述、後者はシェーダに送られてくる変数等の記述を補間してくれる機能を持つ。
SceneにFogを適用すると距離に応じて遠方をぼかし、Three.js標準機能で作成したMeshも遠ざかれば自動的にFogの適用を受ける。しかし自作シェーダを適用したMeshには、必要な記述を加えないとFogが適用されない。
この記事ではShaderMaterialを使用してMeshを作成したときに、そのMeshに対してFogを適用するための記述がわかったのでメモとして残す。

#SceneにFogを適用する

作成済みのSceneにFogを適用する。Fogは色指定が必須。

```JavaScript:JavaScriptの記述
const scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x000000 );
```

#Uniform変数にFogパラメータを組み込む

Three.jsが保持するFogの情報をUniform変数に組み込む。

```JavaScript:JavaScriptの記述
const uniforms	= THREE.UniformsUtils.merge([
	THREE.UniformsLib.fog,
	{
		//ここには自前で追加するUniform変数を記述
	}
]);
```

#ShaderMaterialを作る

Fogを有効にする

```JavaScript:JavaScriptの記述
const material	= new THREE.ShaderMaterial({
	'vertexShader'		: vShader,	//頂点シェーダの文字列
	'fragmentShader'	: fShader,	//フラグメントシェーダの文字列
	'uniforms'			: uniforms,	//前項で作成したUniform変数
	'fog'				: true		//Fogを適用することを伝える
});
```

#頂点シェーダに記述を追加する

\#includeはThree.jsのための記述（GLSL標準でない）

```GLSL:頂点シェーダの記述
#include <fog_pars_vertex>	//main関数の外に記述
void main () {
	//自前の記述

	//以下の2行を追加
	//positionを変更している場合は変更した値を割り当てる
	vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
	#include <fog_vertex>
}
```

#フラグメントシェーダに記述を追加する

gl_FragColorで出力色決定後にFogを適用する

```GLSL:フラグメントシェーダの記述
#include <fog_pars_fragment>	//main関数の外に記述
void main () {
	//自前の記述（最後にgl_FragColorで出力色が決まるはず）

	//以下の1行を追加（gl_FragColorの後）
	#include <fog_fragment>
}
```

#最後に

人によって記述方法が違う（いろいろな記述があった）。これが一番Three.jsのお作法に則っているような気がした。
4P vs 4C


応用情報技術者平成28年春期 午前68 

売り手側でのマーケティング要素4Pは，買い手側での要素4Cに対応するという考え方がある。4Pの一つであるプロモーションに対応する4Cの構成要素はどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/b1cea7fa-3ff7-a11e-19d1-9b3bef3d6b2a.png)


１、4Pとは
売り手側でのマーケティング要素4Pとは、
Product（製品、サービス、品質）
Price（価格、割引、コスパ）
Place（流通、立地、流通範囲、品揃え）
Promotion（販売促進、宣伝、広告）
のことです。

２、
4Pとは逆に買い手側の視点である4Cとは、
Customer value（顧客価値）
Customer cost（顧客コスト）
Convenience（利便性）
Communication（コミュニケーション・対話）
の4つです。

4Pと4Cの対応関係は：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/84332e2c-9aed-8df5-2f51-2b3d59b5fba2.png)


参照：
https://www.ap-siken.com/kakomon/28_haru/q68.html
mixhostでffftpを使ってファイルをアップロードする

#【前提】
初期で与えられたftpパスワードでログインできなかった為、ftpアカウント作成含めて記述する

#【実施したこと】
1. cPanelのFTPアカウントでアカウントを作成する  
　●ログインにユーザ名を設定する  
　※"ログイン+ドメイン"が接続時のユーザ名となる  
　●ドメインを設定する。今回はメインドメインを設定。  
　※他のドメインでは未確認  
　●パスワードを設定する  
　●ディレクトリを設定する。今回は入力なしとする。  
1. ffftpの設定をする  
　mixhostのsupport [FTPソフトの設定方法](https://help.mixhost.jp/hc/ja/articles/115003735291-FTP%E3%82%BD%E3%83%95%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95) を参考に実施  
　●ホストの設定名(T)：適当に設定する  
　●ホスト名(アドレス)(N)：(1)で作成したアカウントのFTPクラインアントの構成の"FTP サーバー"を設定する  
　●ユーザ名(U)：(1)で作成したアカウントのFTPクラインアントの構成の"FTP ユーザー名"を設定する  
　●パスワード/パスフレーズ(P)：(1)で設定したパスワードを設定する  
　●ローカルの初期フォルダ(L)：今回はmampのドキュメントフォルダ"C:\MAMP\htdocs"を設定  
　●ホストの初期フォルダ(R)："/"を設定  

以上で正しくレンタルサーバーに接続できました
JavaScript var let const の違い

#はじめに
この記事はプログラミングをはじめたばかりの素人が、メモするのに利用しています。
内容には誤りがあるかもしれません。

#var let const の違い
変数を宣言する際のvar let const の違いを簡単にまとめてみました。

|変数の種類|読み方|有効範囲|値の変更|
|:---|:---|:---|:---:|
|let|レット|狭い(ブロックスコープ)|○|
|const|コンスト|狭い(ブロックスコープ)|×|
|var|バー|普通(関数スコープ)|○|

オンラインスクールでは、varで習いましたが、letを標準的には使うようです。

#ブロックスコープとは
例えばletは{ }の中で宣言すると、有効範囲が{ }内に制限されます。
この有効範囲のことをブロックスコープといいます。

例

```JAVASCRIPT
let hello = 'こんにちは';

if (true) {
  console.log(hello);  // A

  let evening = 'こんばんは';
}

console.log(evening);  // B
```

この場合Aは表示されるが、Bはエラーが出て表示されない。

#constについて
constは、letと同じ有効範囲だが、一度値を代入すると変更ができない。
このような変数のことを、「定数」という。

例

```JAVASCRIPT
const MAN = '男';
```

定数には大文字を使用するのが慣習になっている。
Pythonで四択問題アプリを作ってみた

## 概要

G検定の勉強をしようと思い、
ローカルで動く四択問題アプアリを作りました。
問題集としては、一般社団法人日本ディープラーニング協会が実施しているG検定を題材としました。
[G検定について](https://www.jdla.org/certificate/general/)

Python入門者にとってはちょうどいい教材になると思います。

## 処理内容
ざっくりと次のようなステップです。
1. csvから問題を読み込む（No, 問題文, 回答　の３列）
2. 読み込んだ問題から1行目のヘッダ部分をのぞいてリストに入れる
3. 問題文をランダム出力する
4. 回答選択肢を４つ出す。一つは正解、残り３つは他の問題の正解からランダムに選択する
5. ユーザーから回答を受け付ける。回答番号(1~4)以外はやり直しさせる
6. 回答の都度、正解、不正解を出力する
7. 最後の問題が終わったら、最終的な正答率を出力する


## 開発環境
- ローカルマシン(Mac)にて、Dockerを使ってLinux環境を構築
- エディタはVS Code。
- Python:3.8.5



## 問題集となるCSV

エクセルなどで、1行目をヘッダ行として、
１列目はNo、２列目は問題文、３列目は回答とするファイルを作り、csvで保存します。
保存する場所はプログラムと同じディレクトリとしています。
別の場所に保存する場合は、プログラムの方を修正する必要がありますのでご注意ください。

![スクリーンショット 2020-10-07 16.54.21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206150/46ca07bd-9bdb-a492-b058-853747be3490.jpeg)


## コード
```python

# 必要なライブラリの読み込み
import csv
import random


# 問題集ファイル（csv）の読み込み。1行目はヘッダなので読み込まない。
test_file = open('gkentei.csv')
test_data = csv.reader(test_file)
questions = []
for row in test_data:
    if test_data.line_num == 1:
        continue
    questions.append(row)
test_file.close()


# 純不同に出題するためにシャッフル
random.shuffle(questions)


# 正答率を計算するために、初期値として正答数に0をセット
correct_count = 0


# ループを回してランダムに出題しながら都度回答を表示
for quiz, question in enumerate(questions):
    # 選択肢を作る　（１）誤りの３つをいれる
    answers = []
    while len(answers) < 3:
        choice = random.randint(1, len(questions))
        if (choice != quiz + 1) and (questions[choice-1][2] not in answers): # 正解ではない、かつ既に含まれていない
            answers.append(questions[choice-1][2])
            
    # 選択肢を作る　（２）正解を入れる
    correct_ans = questions[quiz][2]
    answers.append(correct_ans)
    
    # 選択肢を作る　（３）シャッフルする
    random.shuffle(answers)
        
    # 問題文を出力
    print('\n問題{}'.format(quiz + 1))
    print(questions[quiz][1])
    
    # 回答選択肢を出力
    print('\n---- 回答選択肢 -----')

    for i, ans in enumerate(answers):
        print('{}: {}'.format(i+1, ans))

    # 回答の受付と入力された値のチェック
    while True:
        user_ans = input('\n回答選択肢を入力してください。\n')
        if user_ans in ['1', '2', '3', '4']:
            break
        else:
            continue

    # 正解の表示
    print('\n----- 正解は -----')
    correct_num = answers.index(questions[quiz][2]) + 1
    print('{}: {}'.format(correct_num, questions[quiz][2]))
    
    # 結果
    if correct_num == int(user_ans):
        print('😀😀😀正解😀😀😀')
        correct_count += 1
    else:
        print('☠️☠️☠️残念☠️☠️☠️')
    print('\n\n■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ')

# 最終結果を出力
correct_rate = int(correct_count / len(questions) * 100)
print('\n⭐️⭐️⭐️最終結果⭐️⭐️⭐️')
print('正答率は {}％です。{}問中 {}問正解'.format(correct_rate, len(questions), correct_count))


```

何かの参考になれば幸いです。
【けんちょん本 to Python】-第２章-「問題解決力を鍛える！ アルゴリズムとデータ構造」掲載コードをPythonに書き直してみた！

#はじめに
この記事は、競技プログラミングの解説を多数書かれているけんちょんさんの書籍、**[問題解決力を鍛える！ アルゴリズムとデータ構造](
https://www.amazon.co.jp/%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA%E5%8A%9B%E3%82%92%E9%8D%9B%E3%81%88%E3%82%8B-%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E5%A4%A7%E6%A7%BB-%E5%85%BC%E8%B3%87/dp/4065128447/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E5%A4%A7%E6%A7%BB+%E5%85%BC%E8%B3%87&qid=1602096326&s=books&sr=1-1)（けんちょんさん本）**について、掲載コードをPythonに翻訳したものを、備忘のためまとめたものです。

このページでは、第２章掲載分について紹介します！
バグ等ありましたらご容赦ください。

他の章へのリンクは以下のページをご覧ください。
【目次ページ】
https://qiita.com/KevinST/items/002676619a583754bf76

#code2.1　一重for文の計算量
一重for文の計算量について示す問題ですね。
出力もつけてみました。

```python:code2-1.py
#Nを入力から受け取り
N = int(input())
count = 0

for i in range(N):
    count += 1

#結果を出力
print(count)
```
>【入力例】
>100
>【出力例】
>100

いわゆる$O(N)$ですね！

#code2.2　二重for文の計算量
今度は二重for文の計算量です

```python:code2-2.py
N = int(input())
count = 0
for i in range(N):
    for j in range(N):
        count += 1
print(count)
```
>【入力例】
>100
>【出力例】
>10000

いわゆる計算量$O(N^2$)ですね！

#code2.3　偶数の列挙
```python:code2-3.py
N = int(input())
for i in range(N, 1, -2):
    print(i)
```
>【入力例】
>10
>【出力例】
>10
>8
>6
>4
>2

計算量は$O(N)$です。

#code2.4　最近点対に対する全列挙
```python:code2-4.py
def calc_dist(x1, y1, x2, y2):
    return ((x1 - x2)**2 + (y1 - y2)**2)**0.5

#入力データを受け取る
N = int(input())
x = [0] * N
y = [0] * N
for i in range(N):
    x[i], y[i] = map(int, input().split())

#求める値を十分大きい値で初期化しておく
minimum_dist = 10000000.0

#探索開始
for i in range(N):
    for j in range(i+1, N):
        dist_i_j = calc_dist(x[i], y[i], x[j], y[j])
        if dist_i_j < minimum_dist:
            minimum_dist = dist_i_j

print(minimum_dist)
```

>【入力例】
>4
>1 1
>2 2
>12 66
>18 31
>【出力例】
>1.4142135623730951

上記の例だと、
- 最近点対は、(1,1) (2,2)
- 距離は$\sqrt2$
- 計算量は$O(N^2)$
です。

第３章はこちら
https://qiita.com/KevinST/items/4d04dc7369880670a63b
【けんちょん本 to Python】「問題解決力を鍛える！ アルゴリズムとデータ構造」掲載コードをPythonに書き直してみた！ -目次-


#はじめに
Qiitaでアルゴリズムや競技プログラミングについて、わかりやすく面白い記事を多数投稿されている[けんちょんさん](https://qiita.com/drken/ "Qiitaのページ")が、本を出版されました！　おめでとうございます！！！！

**問題解決力を鍛える！ アルゴリズムとデータ構造**
![けんちょん本画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764923/c9c5c63b-4a95-a62b-536e-2a39b6a54775.png)
[けんちょん本　Amazonサイト](
https://www.amazon.co.jp/%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA%E5%8A%9B%E3%82%92%E9%8D%9B%E3%81%88%E3%82%8B-%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E5%A4%A7%E6%A7%BB-%E5%85%BC%E8%B3%87/dp/4065128447/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E5%A4%A7%E6%A7%BB+%E5%85%BC%E8%B3%87&qid=1602096326&s=books&sr=1-1)

アルゴリズム・データ構造について、図や説明、例示が豊富で、理解しやすく、読んで楽しめる本です。
近年難化傾向が止まらないAtCoderに参加している伸び悩み競プロerとして、この本のアルゴリズムをぜひ身に着けたい！　そう思いましたが、普通に写経や流し読みするだけではもったいない。
そこで、掲載コードを、普段使っているPythonに書き換えてみることにしました。
備忘とモチベーションの維持を兼ねて公開させていただきます。少しでも皆様の参考になれば幸いです！

初Qiita記事ですので、読みづらい点などありましたらご容赦ください。
バグご指摘・ご意見・アドバイスなど（できれば優しく）いただけますと嬉しいです！

#目次
###第１章
コードの記載なし
###第２章
https://qiita.com/KevinST/items/cb926022777d2b0f3cfd
###第３章
https://qiita.com/KevinST/items/4d04dc7369880670a63b
###第４章
https://qiita.com/KevinST/items/f846d57e56242c6e1293

以下記事未作成です。
進捗に伴い、随時アップデートしていきます！

###第５章

###第６章

###第７章

###第８章


#その他備考
- 基本的に、**けんちょんさん本を見ながらお読みいただく**ことを前提にしています
- 章末問題については記載していません（またご要望があれば、記事作成するかもです）
- 以下の環境で作成しています：Python3.7.4(Anaconda), Windows10, Pycharm
- テストケースについては基本的にけんちょん本から取っていますが、一部記載のないもの等については自作しています
- たまに補足を載せています。よかったら参考にしていただけると嬉しいです
さくらのレンタルサーバーでデータベースのバックアップを自動化。

手動保存するのが面倒になるほど、バックアップする案件が増えたので、google先生にデータベースのアックアップの自動化を聞いてみました。
その答えとして、古い記事ですが「[さくらインターネット環境でDBデータをcronで自動バックアップする](https://nodoame.net/archives/1482)」を参考にさせて頂きました。

#記事のプログラムを動かしてみる
参考記事の最終更新日が2016年ですが、問題なくバックアップファイルが作成されました。

ただ、以下のWarningが表示されました。

```
mysqldump: [Warning] Using a password on the command line interface can be insecure.
```

コマンドラインにパスワードを入力したら安全でない場合があるよ！との事なので、ユーザーID・パスワード・ホストを別ファイルに記入して、読み込むように変更しました。


##ユーザーID・パスワード・ホストを別ファイルに移動

```sh:db_dump.sh
#!/bin/sh

# ----- 設定 -----
DBCONF=/home/ユーザー名/scripts/mydb.cnf
DBNAME=データベース名

PATH=/bin:/usr/bin:/usr/local/bin

# 保存する日数
bk_days=7

# ---------- ファイル名を設定 ----------
# タイムスタンプを取得
TSNOW=`date +%Y%m%d`
TSOLD=`date -v -"${bk_days}"d +%Y%m%d`

# バックアップ先のディレクトリ・ファイル
bk_dir=/home/ユーザー名/db_backup/

# ファイル名を設定
file_temp=${DBNAME}_${TSNOW}.sql
file_backup=${DBNAME}_${TSNOW}.tar.gz
file_remove=${DBNAME}_${TSOLD}.tar.gz

# ---------- バックアップ処理 ----------
# バックアップ先のディレクトリに移動
cd ${bk_dir}
if [ $? != 0 ]; then
echo "Backup directory does not exist."
exit 1
fi

# データベースをダンプ
mysqldump --defaults-extra-file=${DBCONF} ${DBNAME} > ${file_temp}
if [ $? != 0 -o ! -e ${file_temp} ]; then
echo "Cannot dump database."
exit 1
fi

# アーカイブを作成
tar cfz ${file_backup} ${file_temp}
if [ $? != 0 -o ! -e ${file_backup} ]; then
echo "Cannot archive files."
exit 1
fi

# テンポラリファイルを削除
rm -f ${file_temp}

# ローテーション処理
if [ -e ${file_remove} ]; then
rm -f ${file_remove}
fi

exit 0
```

```mydb.cnf
[mysqldump]
user=データベースユーザー名
password=データベースパスワード
host=データベースホスト
```

上記のように、mydb.cnfにデータベース情報を記入し、mysqldumpのオプション--defaults-extra-fileにmydb.cnfの絶対パスを設定しています。

##利用するには

「/home/ユーザー名/」に「scripts」「db_backup」フォルダを作成。
scriptsフォルダに上記プログラムを設置。

設置が完了したら下記コマンドでバックアップ。

```
/home/ユーザー名/scripts/db_dump.sh 1> /dev/null
```
サーバー管理画面から上記コマンドをcronに設定してやれば、データベースのバックアップ自動化の完成です。
超簡単Local by Flywheel で Visual Studio Code + xdebug 環境を add-on で作る

## TL;DR (too long, don't read)

あまりにも簡単になって感動。タイトルの通り

1. Local by Flywheel（以下、LxF） で Add-on で VS Code + xdebug をインストール、有効化
2. LxF で WordPress を作成
3. Utilitys で 有効化（再起動）
4. Visual Studio Code で公開フォルダを開く
5. デバッグテスト（完了）

環境は以下の通り。

- Local by Flywheel ver 5.7.5+4909（多分、5.6.1以上が必要）
- xDebug +  VS Code Add-on ver 1.0.4
- VS Code 1.49.2
- Mac環境
- WordPress (Customで作成 **重要**）

## 背景

本職のプログラマではなく、時々、仕方なくプログラムを書くので、環境設定は忘れてしまう。特に、xdebug の設定は、ややこしい。phpStorm はドキュメントのリンクを行ったり来たりして、設定に四苦八苦。やり方をメモするも、次回やってみると、ブレークポイントをスルーされる。

クッキー？セッション？ポート番号指定で開始？など、いつも不安定。とにかく、さくっと簡単なコードを、大したテストはしないけど、動作をしっかりチェックしてリリースたいだけなのに、その前の作業が大変で本末転倒。

・・・

Local by Flywheelのおかげで、WordPress環境の立ち上げはものすごく簡単に。さらに、phpStormのAdd-onのおかげで、デバッグ環境もかなり簡単になりました。

しかし、**たまにしか開発しないし、大それたコードも書かないのに、phpStormはもったいない。情報も少ないので、vs code に鞍替え** したのですが、デバッグ環境を作るのに苦労してました。

それが、Add-on がリリースされて一発解決です。

## スクリーンショット

Add-ons から Xdebug + VS Code をインストール。Enable Launch をしないと使えません。
![スクリーンショット 2020-10-08 4.39.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193970/f8eb623d-485b-70e5-314f-05fbc95295d0.png)

WordPress環境は念のため「カスタム」で作成。確か、Customでないとデバッグ環境が作れないとか、書いていた気がする（試してません）
![スクリーンショット 2020-10-08 5.03.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193970/e2f2afcc-b6f9-5190-38c8-6a60560143b1.png)

ADD RUN CONFIGURATION TO VS CODE を実行する
![スクリーンショット 2020-10-08 4.41.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193970/92d2e4e4-e35b-b16b-5077-125bf403c526.png)

VS Codeで「Local Sites > name > app > public」を開いて、デバッグモード。適当なところにブレークポイントをつけてテストしてみる
![スクリーンショット 2020-10-08 4.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193970/e09a7e52-9969-dbcc-972c-55c09d154e0a.png)
Laravel簡単ログイン機能に関する記事が少なかったので投稿してみた。

# はじめに
Laravelのポートフォリオ制作の過程において簡単ログイン機能の記事が少なく、（Railsの簡単ログイン機能の記事は山ほどあった。。笑）
個人的には参考にできる記事がなかったので、もしLaravelでポートフォリオ制作に おいてこの機能についてお役に立てたら幸いです。
# ※注意点 
ポートフォリオを見て頂く方のストレスを軽減する事を優先ているため、セキュリティに関しては一切考慮していないので予めご了承ください。
 
# 開発環境
Laravel 6.18.40
PHP     7.3.11
Mysql
MacOS

# ゲストユーザーデータをDBに登録する
Laravelのインストール時にデフォルトで用意されているDatabaseSeederクラスを変更。

※insertする値は自分で設定してください※

（例） 
'name' => 'ゲストユーザー',
'email' => 'aaabbbccc@',
'password' => 'aaabbbccc',


```
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class DatabaseSeeder extends Seeder
{
    /**
     * データベース初期値設定の実行
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'password' => Hash::make('password'),
        ]);
    }
}
```

# views
hidden属性値を使って簡単ログインボタンをサブミットします。

```
<form method="post" action="{{ route('login.guest') }}">
      @csrf
      <input type="hidden"  name="email" value="登録したデータ">
      <input type="hidden"  name="password" value="登録したデータ">
      <button type="submit" class="btn btn-primary">ユーザー簡単ログイン</button>
</form>
```
# ルーティング

名前付きルートを指定
->name('login.guest')

```
Route::post('login/guest', 'Auth\LoginController@guestLogin')->name('login.guest');
```
# コントローラー

attempt関数でviewファイルのhiddenで受け取った値を認証して、認証した場合はtrueを返します。今回であれば一般ユーザーのログイン後と同じ操作を可能としています。もし不正の値の場合はリダイレクトして元の画面に戻るようにしてあります。

```
<?php

namespace App\Http\Controllers\Auth;

use Auth;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
   
    use AuthenticatesUsers;

    protected $redirectTo = '/';

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    public function guestLogin(Request $request)
    {
        
        if(Auth::attempt(['email' => $request->input('email'), 'password' => $request->input('password')])){

            $articles = Article::latest()->paginate(5);
            return view('articles.index', ['articles' => $articles]);

        }
            return redirect()->back();
            
    }

}

```

# 最後に
冒頭でも書きましたが、セキュリティに関しては目を瞑ってください。
この実装内容は本番環境では到底で使用きませんが、柔軟に機能実装できるエンジニア脳を鍛えていきたいですね。
Firebaseでfunctions/node_modules/uuid' do not define a valid '.' targetでエラー

そのままなのだけど

Firebaseでgoogleapisのライブラリを使おうとしたら以下のようなエラーが．

```
Error: Error parsing triggers: Package exports for '/Users/rium/Repositories/hogehoge/functions/node_modules/uuid' do not define a valid '.' target
```

いろいろやってダメだったのだけど，理由はnodeのバージョンで，

自分が13を使っていたのがダメっぽい．

12.x.xの12系のnodeであればOKっぽい．

誰かの参考になれば
Node.jsのインストール方法（Windows）

# はじめに
今回はNode.jsのバージョン管理ツールNodistを用いてのインストール方法を書いていきます！
後々@angular/cliを入れるのでNode.jsのバージョンを12.18.2で指定しています。
（Node.js公式サイトの現在の推奨版12.19.0だと@angular/cliのインストールに失敗したため）

# 目次
1. Nodistのインストール
2. Nodistを用いてのNode.jsのインストール

# 1.Nodistのインストール
* 下記サイトで「NodistSetup-v0.x.x.exe」をダウンロード
 
[Nodistのインストールサイト](https://github.com/nullivex/nodist/releases)
![nodistinstall2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748651/9058942d-d732-010f-ed53-5e2ff4d1644a.png)

* インストーラーを起動

![nodistinstall3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748651/7d65e795-ed83-7fa9-a1b7-6564f555e159.png)

* 「Next>」をクリック！

![nodistinstall4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748651/99a03274-7e2f-4e23-e819-56e18e5efbed.png)



* 「I Agree」をクリック！

![nodistinstall5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748651/62cfc9c1-9337-bde1-a328-6a4e071c8b10.png)

* Destination Folderを「C:\Program Files\Nodist\」にし「Install」をクリック！

![nodistinstall6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748651/5095f7fc-7120-0a9a-8b73-c2dc39ffd458.png)

これでNodistのインストールは完了！
# 2.Nodistを用いてのNode.jsのインストール
* コマンドプロンプトを起動

![nodistinstall7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748651/aaa09691-c2d0-3092-0e5b-167e3b49f004.png)

* Nodistのバージョン情報を確認

```
$ nodist -v
0.9.1
```

* Nodistで使用できるNode.jsのバージョンを確認

```
$ nodist dist
.
.
14.12.0
14.13.0
```

* 使用するNode.jsを取得

```
$ nodist use 12.18.2
 12.18.2 [===============] xxxxx/xxxxx KiB 100% 0.0s
12.18.2
```

* 取得したNode.jsがあるか確認

```
$ nodist
  (x64)
> 11.13.0 (global: 11.13.0)
  12.18.2
```

* 使用するNode.jsのバージョンを指定

```
$ nodist global 12.18.2
12.18.2
12.18.2 (global)
```

* Node.jsとnpmが正しくインストールされているかのバージョン確認

```
$ node -v
v12.18.2

$ npm -v
6.9.0
```

これでNode.jsのインストールは完了！
Dcokerfile メモ

Dockerfile で使用できる命令（instruction）　
大文字小文字の区別をしない。慣習として大文字を使用する。

- FROM  
必ずこれから始める。FROMより前に置けるのはARGのみ。ARGはFROMの引数宣言。  

```
FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]
```  

- ESCAPE　
エスケープ文字の指定。デフォルトで「’’」が設定されている。

- ENV
環境変数の置換。以下の命令に置いてサポートされる。<br>
  - ADD
  - COPY
  - ENV
  - EXPOSE
  - LABEL
  - USER
  - WORKDIR
  - VOLUME
  - STOPSIGNAL

- RUN  

```
RUN <command> シェル形式
RUN ["executable", "param1", "param2"]　exec形式
```
- CMD<br>

```
CMD ["executable","param1","param2"] (exec 形式、この形式が推奨される)
CMD ["param1","param2"] ( ENTRYPOINT のデフォルト・パラメータとして)
CMD command param1 param2 (シェル形式)
```

- LABEL<br>

```
LABEL <key>=<value> <key>=<value> <key>=<value> ...
```

- EXPOSE  
コンテナの実行時に、どのポートをリッスンさせるかの指定

```
EXPOSE <port> [<port>...]
```

- ENV  
環境変数の設定

```
ENV <key> <value>       一つの変数に一つの値を設定
ENV <key>=<value> ...　 一度に複数の変数の値を設定
```
- ADD  
`<src>`に示されるファイル、ディレクトリ、リモートファイルURLを<dst>にコピーする。

```
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] <dest> は絶対パスか、あるいは WORKDIR からの相対パスにより指定
```

- COPY

```
COPY <src>... <dest>
COPY ["<src>",... "<dest>"] 絶対パスか、あるいは WORKDIR からの相対パスにより指定
```

- ENTRYPOINT  
複数記述されていても、最後の命令しか実行されない

```
ENTRYPOINT ["executable", "param1", "param2"] （exec 形式、推奨）
ENTRYPOINT command param1 param2 （シェル形式）
```

- VOLUME

```
VOLUME ["/data"]
VOLUME /data
```

- USER

```
USER <user>[:<group>]
USER <UID>[:<GID>]
```

- WORKDIR  
ワークディレクトリの指定。WORKDIR が存在しないときは生成される。  
その後に続く RUN、CMD、ENTRYPOINT、COPY、ADD の各命令において利用可能。

```
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd  ⇒ この結果は 「/a/b/c」
```

- ARG  
変数を定義して、ビルド時にその値を受け渡す。

```
ARG <name>[=<default value>]
```

以下のARG変数は定義済み。
- HTTP_PROXY
- http_proxy
- HTTPS_PROXY
- https_proxy
- FTP_PROXY
- ftp_proxy
- NO_PROXY
- no_proxy

- ONBUILD
イメージに対して取りが命令を追加する。そのイメージが他のビルドにおけるベースイメージとして用いられたときに実行される。

- STOPSIGNAL

```
STOPSIGNAL signal
```

- HEALTHCHECK
コンテナ内でヘルスチェックを行うコマンドを指定

- SHELL　デフォルトシェルの上書き設定

```
SHELL ["executable", "parameters"]
```

デフォルトのシェルは、 
Linux 上では `["/bin/sh", "-c"]`
Windows 上では`["cmd", "/S", "/C"]`
rails routesコマンドについて

#rails routesコマンド説明
アプリケーションのディレクトリでrails routesコマンドを実行すると、
そのアプリケーションで設定されているルーティングを確認できます。
要は、rails routesコマンドをターミナルに入力すると自分の知りたい
ルーティングを確認できるってことです。

####例

```例:ターミナル
# 作成したアプリケーションのディレクトリか確認（アプリ名「sample_app」の場合）
% pwd
/Users/ユーザー名/projects/sample_app

# 設定されているルーティングを確認
/Users/ユーザ名　sample_app　% rails routes
```

確認の際には、ルーティングがターミナルを画面幅いっぱいに表示されるので画面を広げて見やすくして表示を確認しましょう。

下記の例のようにターミナルに表示されます。
また、以下のような表示がされていれば正しくルーティングが
設定できています。

```例:ターミナル
Prefix  Verb  URI Pattern       Controller#Action
posts   GET   /posts(.:format)  posts#index
（以下省略）
```

rails routesの実行結果を見てもよくわからない方は
下記の画像を参考にして、内容を読んで下さい。


![rails routes.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762918/68a0c5d4-cbae-2a0d-9377-8da5f101441b.png)

ここは、基礎中の基礎のためよく理解する必要がありますね。


#まとめ
**rails routesコマンドは、アプリケーションに設定されているルーティングを一覧表示するためのコマンドのこと。**

**基本的にコマンドは数多くあるため、覚えきれないと思います。
てか、実際覚えきれないです。w
ですが、何かを確認する場合のコマンド等は覚えておくと作業する上で
効率良く進めることができるのでこういうコマンドは覚えておくとよいでしょう！！**
コンテナにIBM Cloud CLIをインストールする

# 概要
Dockerコンテナ内にIBM Cloud CLIをインストールし、ローカル環境を汚さないCLI開発環境を構築する。
今回は最新のCentOSのイメージを使用してコンテナを作成します。
前提条件として、Docker Desktop がインストールされていることとします。

# 手順
## コンテナの準備

### CentOS8のイメージを取得
```
docker pull centos:latest
```

### 取得したイメージからコンテナの作成と起動
```
docker run -it -d --name ibmcloud centos:latest
```

### 起動しているコンテナの確認
```
docker ps
```

### コンテナ内に接続
```
docker exec -it <CONTAINER ID> bash
```

### yumの最新化
```
yum check-update
```

## IBM Cloud CLIのインストール
公式のCLIインストール方法はここ(https://cloud.ibm.com/docs/cli?topic=cli-getting-started)

### `which` コマンドのインストール
```
yum which
```
whichをインストールする理由は、こちら(https://qiita.com/Masayuki-M/items/6e7d541b1627f55df221) を見てください。

### CLIのインストール
```
curl -sL https://ibm.biz/idt-installer | bash
```

### CLIインストールの確認
```
ibmcloud -v
```

## コンテナの保存
コンテナをイメージにする

```
docker commit <CONTAINER ID> ibmcloud 
```

## まとめ
以上の手順でibmcloudコマンドを実行できるコンテナが作成できた。
最後のイメージ保存で、再起動後もCLIの再インストールが不要となる。
Kindle Unlimitedの本を検索するクエリ



こんちゃっす、やぐちです。
Kindle Unlimited無料期間入っていろいろと読み漁ろうとしています。
ただKindle Unlimitedの検索性が死ぬほど悪くて困ったので
URLの後ろにKindle Unlimitedだけをフィルタリングするクエリくっつけます。

#けつろん

これをURLの後ろにつけてくれ。

```:query
&rh=p_n_feature_nineteen_browse-bin%3A3169286051
```

#たとえば
たとえば、普通にgitの本を検索すると以下のようなURLになります。

https://www.amazon.co.jp/s?k=git&i=digital-text&dc&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&qid=1602091260&rnid=3169285051&ref=sr_nr_p_n_feature_nineteen_browse-bin_1

このURLの後ろに上記のクエリをくっつけてあげるとUnlimitedだけの表示になります。

https://www.amazon.co.jp/s?k=git&i=digital-text&dc&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&qid=1602091260&rnid=3169285051&ref=sr_nr_p_n_feature_nineteen_browse-bin_1&rh=p_n_feature_nineteen_browse-bin%3A3169286051



#せんじん

先に似たようなことやって、検索画面作ってる人いたので見てみてください。

[kindle unlimited検索を作ってみた](https://qiita.com/muranet/items/4bb0c89f6c2da44185a9 "kindle unlimited検索を作ってみた")

#以上です
なんか間違いとかあったらコメントください。
よかったらお勧めの本とか教えてください。
【next.js】LGTM数 + ストック数ランキング【毎日自動更新】

# はじめに
LGTM数 + ストック数の合計値が高い記事こそが真に価値のある記事ではないだろうか⭐︎
という思いからLGTM数 + ストック数の合計でランキングをつけ自動で投稿できようにしました。
自分の気になるタグの有益な記事が埋もれるのを防げたら最高です。
# 集計タグ
**タグ名：**`next.js`
**フォロワー数：**494
**記事数：**993
# 集計概要
**集計方法：**毎日7時に Qiita API v2をcronにて定期実行し集計
**集計期間：**2021/09/02 ~ 2021/09/09
**集計内容：**LGTM数 + ストック数合計値
**集計対象：**LGTM数3件以上
# 1位：[表情を鍛えることができるアプリを作った](https://qiita.com/yuikoito/items/a0c588e19999e50f5a0b)(33P)
**LGTM数：17**  **ストック数：16**
`TypeScript`  `next.js`  `face-api.js`
[@yuikoito](http://qiita.com/yuikoito)さんの投稿（2021/09/06/1:30 PM）
# 2位：[【個人開発】CtoCのコードレビューサービス Kanon Code](https://qiita.com/art_porokyu/items/b53c18c1b250996b9aaf)(18P)
**LGTM数：13**  **ストック数：5**
`lambda`  `コードレビュー`  `個人開発`  `next.js`
[@art_porokyu](http://qiita.com/art_porokyu)さんの投稿（2021/09/05/2:45 AM）
# 3位：[【始め方】Next.js + TypeScript + ESLint + Prettier + Material UI + Emotion + dependabot + Vercel で快適開発](https://qiita.com/hasehiro0828/items/ef1736e871b85b039212)(6P)
**LGTM数：3**  **ストック数：3**
`TypeScript`  `material-ui`  `next.js`  `emotion`  `Vercel`
[@hasehiro0828](http://qiita.com/hasehiro0828)さんの投稿（2021/09/05/7:10 AM）