OmniAICreator/Qiita-1.07M huggingface dataset:
Java sessionスコープ

趣味でプログラミングを勉強しています。
古本販売サイトを作成したいと思って勉強を始めたのですが、サーバ上でウェブページなどを動的に生成したりデータ処理を行うためには、Java Servlet（ジャバ サーブレット）の知識が必要ということで勉強を始めました...（^_^;）
古本サイトを例に考えた場合にお客さんがカートに入れた情報を保持する、session(セッション)の概念がいまいちわかりにくかったので、今回記事にしてみました!! ヾ ^_^♪

- セッション
    - ユーザーごとの状態を保持する仕組み

- サーブレットでは`javax.servlet.http.HttpSession`インターフェースを使って扱う

```　CounterServlet.java
package session;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class CounterServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{

		//1.セッションの取得
		HttpSession session = request.getSession();

		//2.セッションからのオブジェクトの取得
		Integer count = (Integer)session.getAttribute("count");

		//3.カウンタを+1
		if(count == null){
			count = new Integer(0);
		}
		count = new Integer(count.intValue() + 1);

		//4.セッションにオブジェクトを格納
		session.setAttribute("count", count);

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<html><body>");

		//セッションIDの表示
		out.println("<p>sessionId=" + session.getId());

		//セッションIDの表示
		out.print("<p>count=" + count);

		//このサーブレットへのリンクの表示
		String linkurl = request.getRequestURI();
		out.println("<p><a href=\"" + linkurl + "\">RELOAD</a>");
		out.println("</body></html>");
	}

}
```

1. HttpSessionオブジェクト生成時には、アプリケーションサーバから一意の識別子「セッションID」が割り当てられます。セッションの同一性は、このセッションIDによって担保されているようです。
2. セッション属性から"count"という名前のオブジェクトを取得、Integer型にキャストしています。
最初のリクエストはセッション属性にcountという名前のオブジェクトは登録されていないので、countの値はnullになります。
3. カウントアップ
最初の段階でnullなので0を代入します。
4. setAttributeメソッドで、1を足した後の値をセッション属性に登録します。

セッションスコープにおけるデータの受け渡し
リクエストスコープに登録されたデータは、リクエストをまたいで受け渡すことができませんでしたが、セッションスコープに登録されたデータは受け渡すことが可能です。

- requestスコープ
    - 1回のHTTPプロトコルで実行される、サーブレットとforwardされたJSP間で有効なオブジェクト
    - リクエストの処理が終わると破棄  
    - HttpServletRequest属性として設定
   
- sessionスコープ
    - 同一のセッションで実行される、サーブレットやJSPで有効なオブジェクト
    - 一定時間経過でsession終了ともに破棄
    - HttpSessionの属性として設定

```
セッションスコープのオブジェクトを操作するメソッド

Object getAttribute(java.lang.String name)
引数で指定したオブジェクトを取得します。存在しない場合はnullを返します。
返ってくる型はObject型ですので、適切にキャストして利用することが多いようです。

void setAttribute(java.lang.String name, java.lang.Object value)
引数valueで指定したオブジェクトをnameという名前で登録します。

void removeAttribute(java.lang.String name)
引数nameで指定したオブジェクトを削除します。

java.util.Enumeration getAttributeNames()
登録されているnameの一覧を返します。
```

セッションタイムアウト
セッションデータを削除していかなければ、使われないデータがサーバー上に残ってしまいます。
回避策として、クライアントが最後にアクセスしてからの経過時間をチェックして、削除する仕組みがアプリケーションサーバーに搭載されています。

```  web.xml
<session-config>
        <session-timeout>3</session-timeout>
</session-config>
```
PHPフレームワーク Laravel

趣味でプログラミングを勉強しています。
古本販売サイトを作成したいと思って勉強を始めたのですが、コワーキングスペースにいるプログラミングに詳しいTさんに「スクラッチ開発するより、フレームワークを使ってサイトを作成するほうがいいよ」とアドバイスをいただき、おすすめPHPフレームワーク「Laravel」を今回記事にしてみました!! (^-^)

### PHPフレームワーク「Laravel」

- スクラッチ開発した場合の問題点 
    - セキュリティの問題 
    - メンテナンスの問題
    - 拡張性の問題<br>
     →スクラッチ開発する場合、セキュリティやメンテナンス性、拡張性などは全て自分で実現しないといけない 

##### フレームワークとライブラリ比較

- フレームワーク
    - 機能　＋　機能を使う仕組み
    - セキュリティやメンテナンス性、拡張性が考慮されたシステム
    - 開発で多用される様々な機能や仕組みを持ったソフトウェア 

- ライブラリ 
    - 開発に役立つ便利な機能を備えたソフトウェア 
     
#### Laravelって？
2012年リリース 

#### 特徴 
- Model-View-Controllerフレームワーク、各機能のパーツを作ることで開発を行う 
- 低い学習コスト 
- 非常にわかりやすいコード 
- 土台にSymphony ※MVCフレームワーク　2007年リリース
- インストールやソフトウェアのインストールなどは、すべて「Composer」というパッケージ管理ツールでOK
- Webサーバー機能内臓(PHP5.4以降ビルトインサーバー機能を利用) 
- データベースアクセスにORM(Object-Relational-Mapping)技術を導入 
- 画面の表示は「Blade」と呼ばれるテンプレートエンジンを搭載

##### Laravelスタート準備 
「Composer」のパスを通す<br>
`composer global require "laravel/installer=1.1" `

#### Laravelを使うには
 
プロジェクト作成コマンド 
`laravel new プロジェクト名 `
サーバー起動コマンド 
`php artisan serve` 
動作確認 
`http://localhost:8000/ `

####ルーティングとコントローラー 

#####ルーティング 
指定アドレスにアクセスしたとき、その処理を呼び出して実行管理 

```
Laravelファイル
.env / 動作環境に関する設定情報 
.gitigonore / git利用情報 
artisan / artisanコマンド 
composer.json / composer利用に関するもの 
package.json / JavaScriptのパッケージツール(npm)で利用するもの 
phpunit.xml / PHPUnitに関するもの 
server.php / サーバ起動時に利用されるプログラム 
webpack.mix.js / webpackというJavaScriptのパッケージツールで利用するもの 
yarn.lock / yarnというパッケージマネージャが使うファイル（自動生成） 
```

```
Laravelフォルダ 
app / アプリケーションプログラム （よく使う）
bootstrap / 実行時に行われる処理 
config / 設定 
database / データベース関連 （まぁまぁ使う）
public / 公開フォルダ 
resources / テンプレートファイルなどのリソース （よく使う）
※「views」フォルダあり、welcome.blade.phpがある
routes / ルート情報 （よく使う）
storage / ログファイルなど 
tests / ユニットテスト関連のファイル 
vender / フレームワーク本体
```

#####「app」フォルダについて
アプリケーション部分のプログラム を配置

```
vender / Laravelフレームワーク部分
Console / コンソールプログラムを配置する
Exception / 例外処理を配置
Http / Webアプリケーションにアクセスした時の処理（重要）
Providors / プロバイダと呼ばれるプログラムを配置
User.php / ユーザー認証に関するスクリプト
```

#####ルーティングと「routes」フォルダ
ルーティングは、アクセスを設定している情報（ルート）を管理している機能
→特定のアドレスにアクセスすると、それに対応する処理が呼び出される。関連付けをおこなっているのがルーティング

#####「routes」フォルダについて
```
api.php / APIのルーティング プログラム内から利用するAPIの機能を特定のアドレスに割り当てるのに利用
channels.php / ブロードキャストチャンネルのためのルーティング
console.php / コンソールプログラムのためのルーティング
web.php / Webページにアクセスするためのルーティング
```

```
//トップページにアクセスした時
Route::get('/', function () {
return view('welcome');
});
```

#####ルート情報の基本（GETアクセス）

```
Route::get(アドレス, 関数など);

第1引数 アドレス
第2引数 処理（関数,コントローラー）
※関数ではviewを使うことで「views」フォルダのテンプレートを利用できる
```

#####ルートパラメーターの利用

```
Route::get('/〇〇/｛パラメーター｝', function($受け取る引数) {...});
第1引数 パラメータに指定した部分がパラメータとして取り出せる
第2引数 パラメータの値を受け取る変数
```

#####コントローラー

- コントローラーの作成は、artisan(アーティザン)コマンドで作成する
`php artisan make:controller コントローラ名`
- コントローラーに用意される処理を「アクション」と呼び、メソッドの形で用意される
- アクションメソッド 引数を持たないメソッドと呼ぶ
 `例）index`


#####ルート情報の用意
- 「routes」フォルダのweb.phpに記載する

```
Route::get(アクセス先, 'コントローラー名@アクション名')
第1引数にアクセスされると、第2引数に指定されたコントローラーが実行される
```
Cloud Buildから、デフォルトのkubectlコンテナ1 stepでGKEにデプロイ


GCPは、アップデートが早いので、簡単にまとめてみる。
基本的な内容については、記載しない。


# 要約
- `gcr.io/cloud-builders/kubectl`コンテナで、kustomizeは使える
- `gcr.io/cloud-builders/kubectl`コンテナにクラスター名、ゾーン or リージョンを設定してデプロイ
- `gcloud container clusters get-credentials`は自動でやってくれる

# ディレクトリ構成

```
.
├── deployments
│   └── kustomize
│       ├── kustomization.yaml
│       └── test-batch.yaml
└──  cloudbuild.yaml
```

# kustomize

非常にシンプルなYAML管理ツール

現状でも、`gcr.io/cloud-builders/kubectl`は、v1.14なので、[kustomize](https://github.com/kubernetes-sigs/kustomize)は組み込まれている。

```
kubectl -k
```

## kustomization.yaml

```yaml
resources:
- test-batch.yaml
```

## test-batch.yaml

```yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: test
spec:
  schedule: "1/* * * * *"
  jobTemplate:
    spec:
      backoffLimit: 3
      completions: 1
      parallelism: 1
      template:
        spec:
          containers:
          - name: busybox
            image: busybox
            command: "/bin/sh -c echo 'hello!!'"
          restartPolicy: OnFailure
```

# cloud build

## cloudbuild.yaml

`gcr.io/cloud-builders/kubectl`イメージを使用して、環境変数を正しく設定すると自動で認証情報を取得してくれる。

```yaml
step:
  - name: "gcr.io/cloud-builders/kubectl"
    args:
      - "apply"
      - "-k"
      - "./deployments/kustomize"
    env:
      - "CLOUDSDK_COMPUTE_REGION=<cluster region> (regional clusters)"
      - "CLOUDSDK_COMPUTE_ZONE=<cluster zone>"
      - "CLOUDSDK_CONTAINER_CLUSTER=<cluster name>"
```

環境変数を設定しないと、下記のように怒られる。

```
Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/kubectl
Step #1:   No cluster is set. To set the cluster (and the region/zone where it is found), set the environment variables
Step #1:   CLOUDSDK_COMPUTE_REGION=<cluster region> (regional clusters)
Step #1:   CLOUDSDK_COMPUTE_ZONE=<cluster zone>
Step #1:   CLOUDSDK_CONTAINER_CLUSTER=<cluster name>
Finished Step #1
```

# 実行ログ

クラスター名： test-cluster
テストバッチ名： test

```
Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/kubectl
Step #1: Running: gcloud container clusters get-credentials --project="test-ci-gke" --region="asia-northeast1-a" "test-cluster"
Step #1: Fetching cluster endpoint and auth data.
Step #1: kubeconfig entry generated for test-cluster.
Step #1: Running: kubectl apply -k ./deployments/kustomize
Step #1: cronjob.batch/test created
Finished Step #1
```
2重デコレータ

動いたのでメモ。12345と出力される。

```python
class a():

    def deco1(func):
        def in_deco1(self):
            print(1)
            func(self)
            print(5)
        return in_deco1

class b(a):

    def deco2(func):
        @a.deco1
        def in_deco2(self):
            print(2)
            func(self)
            print(4)
        return in_deco2

    @deco2
    def fun(self):
        print(3)

b().fun()
```

# 追記

こっちでも動いた。

```python
class a():

    def deco1(func):
        def in_deco1(self):
            print(1)
            func(self)
            print(5)
        return in_deco1

class b(a):

    def deco2(func):
        def in_deco2(self):
            print(2)
            func(self)
            print(4)
        return in_deco2

    @a.deco1
    @deco2
    def fun(self):
        print(3)

b().fun()
```

deco2に直に@a.deco1とつけるのならハナから1つのデコレータにすればいいとちょっと思ったが、
よくよく考えてみると分割させたい処理次第ではそうとも言い切れない。
まぁシステム次第だが出来る限りアトミックにすることを意識したい。

# さらに追記

2重じゃないけどデコレータが普通の関数と同じように値を返戻できたので一応メモ。
これで121と出力される。

```python
class a(object):

    def b(func):
        def in_b(self):
            print(1)
            if func(self):
                print(2)
        return in_b
    
    @b
    def c(self):
        return True
        
    @b
    def d(self):
        return False
        
e = a()
e.c()
e.d()
```
Effective C++ 第３版 第５章 26項 読書メモ

# はじめに
私はC/C++を学び始めて一年にも満たない専門学生です。
読書メモをQiitaに投稿するという課題が出されたので現在読書中であるEffective C++第3版 第5章26項の読書メモを投稿します。

## 変数の定義は可能な限り先延ばしにする
コンストラクタ・デストラクタを持つ型の変数を定義すると変数が生成・破棄されるときにコストがかかるので、使われない変数による無駄なコストがかからないように注意が必要。

```ruby
void Swap(int* a,int* b){
   // a が bよりも大きかった時、使用されない
   int tmp
   if(a < b){
      tmp = *a;
      *a = *b;
      *b = tmp;
   }
}
```

## 変数は初期化する値が決まるまで定義しない方がよい。
「デフォルトコンストラクタで生成したオブジェクトに代入し、値を与える」 よりも 「最初に必要な値を与えてオブジェクトを生成する」
の方が効率が良いので、定義を可能な限り先延ばしにすることによって不要なオブジェクトの生成・破棄、不要なデフォルトコンストラクタの使用を避けることができ、プログラムが明快になり効率的になる。

## 変数の定義はループの内か外か
変数がループの中だけで使われる場合以下の2種類の方法が考えられる。

```ruby:方法A
//ループの外で定義
//クラスでも構造体でも良い
App a;
for (int i = 0; i < 10; ++i){
   a = i に依存する値;
   …
}
```

```ruby:方法B
//ループ内で定義
for (int i = 0; i < 10; ++i){
   App a(iに依存する値);
   …
}
```
上記の2つの方法でかかるコストは

 * 方法A : 生成１回、破棄１回、代入10回
 * 方法B : 生成10回、破棄10回

コストが 1回の代入 < 一組の生成、破棄 の場合
一般的に方法Aが効率的
しかし、aを必要以上に大きなスコープで有効にしているため分かりにくい。

それ以外の場合
方法Bの方が効率的

つまり、1回の代入が1組の生成と破棄よりコストがかからず、その部分では効率が重要な時以外は方法Bを使うべき。

## 結論
変数の定義を可能な限り先延ばしにすることでプログラムは明快になり効率的にもなる。

## 参考文献
[https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0](https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0)
DAG間の依存関係を設定したDAGをつくる

# 追記(2020/06/16)
こちらに最新版のまとめを書きました↓

#### [AirflowでDAG間の依存関係の作成方法のまとめ](https://qiita.com/munaita_/items/5b6444880722df74ac61)

==追記ここまで==

# 背景
DAG_A と DAG_B がある場合に、DAG_A が正常終了した後に、DAG_Bが実行されるような依存関係のあるDAGを作成したい。



# サンプルコード

[TriggerDagRunOperator](https://github.com/apache/airflow/blob/master/airflow/example_dags/example_trigger_controller_dag.py) を使う。

```py:triggering.py

from datetime import timedelta
from airflow import DAG
from airflow.contrib.operators.bigquery_operator import BigQueryOperator
from airflow.operators.dagrun_operator import TriggerDagRunOperator

default_args = {
    "owner": "airflow",
    "depends_on_past": False,
    "start_date": airflow.utils.dates.days_ago(1),
    "retry_delay": timedelta(minutes=5)
}
dag = DAG("first_dag", default_args=default_args, catchup=False, schedule_interval="0 17 * * *")
task1 = BigQueryOperator(
    task_id="task1",
    sql="./sql/task1.sql",
    use_legacy_sql=False,
    destination_dataset_table="pj.dataset.table_name",
    write_disposition="WRITE_TRUNCATE",
    allow_large_results=True,
    dag=dag
)

trigger = TriggerDagRunOperator(
    task_id="trigger",
    trigger_dag_id="second_dag", 
    dag=dag,
)

task1 >> trigger
```

```py:triggered.py

from airflow.models import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.operators.python_operator import PythonOperator
from airflow.utils.dates import days_ago

default_args = {
    "owner": "airflow",
    "depends_on_past": False,
    "start_date": airflow.utils.dates.days_ago(1),
    "retries": 3,
    "retry_delay": timedelta(minutes=5),
}

dag = DAG( "second_dag", default_args=default_args, schedule_interval=None)

bash_task = BashOperator(
    task_id="bash_task",
    bash_command='echo "success trigger"',
    schedule_interval=None,
    dag=dag,
)
```

`trigger.py` の `task1` 実行後、`trigger` タスクで `triggered.py` の `second_dag` を実行している。
DAGをトリガーするには [TriggerDagRunOperator](https://github.com/apache/airflow/blob/master/airflow/example_dags/example_trigger_controller_dag.py) を使う。

# 参考

#### [github: airflow/airflow/example_dags/example_trigger_controller_dag.py ](https://github.com/apache/airflow/blob/55853c3c23fe177bcf4ca19697f1e664325c69ea/airflow/operators/dagrun_operator.py)
MacBook Pro (OS : Catalina) にてZIPアイコンがおかしくなった件

仕事でずっと使っていたMacBook Pro (2017) の調子がいきなり悪くなり、急遽買い替えた。

手元に届き、移行したときのこと。
「最新のOSは…そうだ…Mojaveさんじゃないんだ…」と冷や汗をかいた記憶がある。

32bitのアプリが使えなかったり、仲良くなるには何かと苦労の多いCatalinaさん。
色々厄介なこともあったが、一番頭を悩ませたのは**ZIPのデフォルトアイコンがおかしくなったこと**。
見慣れていたアイコンが変わるだけで意外と気が散ったので、頑張って直してみた。

これはCatalinaさんだからなのかは不明だが、とりあえず備忘録的にここに書いておこうと思う。


## 環境
MacBook Pro (2019) / Catalina 10.15.2


## 経緯
Catalinaさんでは、(特定の条件下) ZIPファイルがアーカイブユーティリティでは解凍できなくなるバグが発生中。
とりあえず`The Unarchiver`をインストールして難を逃れたが、うっかり`このアプリケーションで開く`を`The Unarchiver`に`すべてを変更`してしまった。
デフォルトである`アーカイブユーティリティ`に戻したが、ZIPアイコンが見慣れないものに………

![スクリーンショット-2020-01-28-16.56.22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316493/18cd68ba-6016-0582-caac-be74461c5266.jpeg)

**…おいこら………これはなんぞ？？？**

あの、見慣れた愛しいZIPアイコンは何処へ…？


## 解決方法
色々調べてみたところ、以下の方法で愛しいデフォルトアイコンに戻すことができた。

1. `The Unarchiver以外の代替アプリ`をインストール
2. `このアプリケーションで開く`を`新規でインストールしたアプリ`に`すべてを変更`
3. `新規でインストールしたアプリ`を削除
4. `Finder`を再度開く （optionキーを押しながらFinderのアイコンを長押し、ポップアップメニューに再度開くが表示される）

![スクリーンショット-2020-01-28-17.09.16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316493/f6b8496b-2432-653d-d069-22facaf37ded.jpeg)

今回は`The Unarchiver`を引き続き使いたかったため代替アプリに犠牲になっていただいたが、もう使わないから消すという場合は`The Unarchiver`をデフォルトにして削除すればよい。


## まとめ
Mojaveさんが恋しい。
Laravel mixで環境変数を.env以外のファイルから読み込む

ステージング、本番サーバーにElasticbeanstalkを使っていて、ハマったのでメモ。

## 結論

https://laravel-mix.com/extensions/env-file
を使う。

``` 
// package.json
"scripts": {
        "local": "npm run development", // localは.envを読めばいいので上記使う必要なし
        "dev": "NODE_ENV=development ENV_FILE=./env/.env.staging node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", // デフォルトから変更。
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production ENV_FILE=./env/.env.production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
```

```
// webpack.mix.js
let mix = require('laravel-mix');
require('mix-env-file');

if(process.env.ENV_FILE) {
    mix.env(process.env.ENV_FILE);
}}
```
初学者によるプログラミングMemo　#20 素数判定

#はじめに
今回は素数のお話です
難しかったので、間違えないように順をおって書きたいと思います
Rails関係なくても書いている下記はすでに決まり文句ともなりました
なお、本記述はMacにおいて、Railsでの開発を前提としています
また、まだまだひよっこですので、不備等ございましたらご指摘いただけると幸いです
＊例によって、コメントにてありがたいご指摘をいただいております
そちらの方が、コーディングも短くなっているので、是非ご覧ください！！

#目次
- 素数の話
- 素数を見つける
- 問題

##素数の話
意外と素数を知らない人が結構いるので、まずは素数とはなんぞやと言う話をしたいです
素数の定義は

**1より大きい自然数で、正の約数が1と自分自身のみであるもののこと。つまり、正の約数の個数が2である自然数のこと。**

さっぱりですかね、そうですね
小学生にもわかるように言いますと、

「２以上の小数点が付かない数（これをxとします）で、その数（x）を余りの無いように割り算しようとすると、その数(x)と１以外では割り算できない数のこと」

でしょうか
私にとってはすごくわかりにくい文章になりましたが、理解していただけるならこれでいいでしょう
素数は"2,3,5,7,11,13,17,19..."と続きます

##素数を見つける

さて、素数を求めるプログラミングを考えたいと思います
[公式リファレンス](https://docs.ruby-lang.org/ja/latest/class/Prime.html)を参照します
いやー難しい…何書いてるのかさっぱりです
こう言う時はひたすらコードを書きましょう

たどり着いたのはこのメソッド

"prime?"

これで素数かどうか判定できるようです

```.rb
require 'prime' # これ必須です

p Prime.prime?(3)
# => true

p Prime.prime?(4)
# => false
# 返り値は"true","false"です
```
できました
3は素数なので"true"を返してくれています
4は素数では無いので、"false"が帰ってきます

いやー、便利なメソッドですね、本当に
考えなくても素数を返してくれるんですから

さて、ではこれを使って素数判定のプログラムを組んでみましょう
素数だけ教えてくれるプログラムです

```.rb
require 'prime'

p "どの数字までの素数が知りたいんや？うちが教えたるで"

i = gets.to_i

if i >= 2
  pri = []
  (1..i).each do |p|
    if Prime.prime?(p) == true
      pri << p
    end
  end
  p pri
else
  p "その数はエラー起きてまうわ、ごめんな"
end

# => 20
# => [2, 3, 5, 7, 11, 13, 17, 19]
```
できました
いやぁ、しかしこの辺のメソッド使えば数学余裕じゃね？ってくらい使えそうなのが転がってますね
まだまだ勉強の余地がありそうです
次は素因数分解でも書きたいと思います
pythonは"ぴぃちょん"と読むので"ぴぃちょん"で実行できるようにする(ネタです)

## TL;DR
python の読み方は"ぱいそん"らしいのですが、[ぴぃちょんとと誤解している方がいました](https://twitter.com/sana_natori/status/1222062850484473856)。
そこで、"ぴぃちょん"コマンドを作りました。

## コマンド
```bash:.bashprofile
# bashの場合 ~/.bashprofileに追記
alias ぴぃちょん="python"
```

```zsh:.zprofile
# zshの場合 ~/.zprofileに追記
alias ぴぃちょん="python"
```

```fish:fish
# fishの場合 以下のコマンドを実行
alias ぴぃちょん="python"
funcsave ぴぃちょん
```
標準入力まとめ


AtCorderで標準入力に困ったのでメモ。

#### a, b = list( map( int, input().split() ) )

* 一言で言うと
inputした文字列をsplitを使いスペースの時点で分割
→mapを使い全ての値をint型に
→値をリスト化

* list()
文字列をリスト化
**例**
list('python')  →['p', 'y', 't', 'h', 'o', 'n']  
* map(function, iterable, ...)
 関数とイテラブルオブジェクトを引数で受け取る。
イテラブルオブジェクトの各要素を関数に渡し、渡した各要素について関数実行後の戻り値を要素にもつイテレータ
**参照サイト**
[mapの使い方](https://python.atelierkobato.com/map/)
[イテレータとは](https://www.sejuku.net/blog/23570)
[mapはイテレータを返す](https://note.nkmk.me/python-map-list-iterator/)

* input()
取得できるのは常に文字列
**参照サイト**
[Pythonのinput関数でキーボードからの入力を取得](https://note.nkmk.me/python-map-list-iterator/)　　
  
* .split()
split()をデフォルトで適用すると改行文字だけでなくスペースでも分割される。 
**参照サイト**
[Pythonで文字列を分割（区切り文字、改行、正規表現、文字数）](https://note.nkmk.me/python-split-rsplit-splitlines-re/)
SQL Server:プロダクション環境で現在使われていないテーブルを探す方法

#背景
長年プロダクション環境で稼働しているシステムでは、現在では（機能廃止等に伴い）使われなくなったテーブルが存在することがよくあると思います。

アプリ観点でアクセスログ等から調査する方法もあるかと思いますが、DB観点でも割とシンプルに未使用テーブルを探すことが可能なため、方法についてまとめてみました。

#SQL Serverのテーブルの概念
方法について説明する前に、SQL Serverのテーブルについても簡単にまとめておきます。
SQL Serverの実データは「クラスタ化インデックス」または「ヒープ」というデータ構造で格納されます。1テーブルごとに必ずどちらか一つだけで、クラスタ化インデックスもヒープも存在するテーブルというのは存在しません。
また、SQL Serverではヒープも「インデックスの一種」と捉えられます。（この方が説明がいろいろしやすいです）

実データ以外にも、特定のカラムだけから成るインデックスを任意で複数作成することも可能です。こちらは「非クラスタ化インデックス」と呼ばれています。

以上をまとめると、SQL Serverにおいて、各テーブルは必ず以下の4パターンのいずれかに該当します。

1.クラスタ化インデックスのみ
2.クラスタ化インデックス＋1つ以上の非クラスタ化インデックス
3.ヒープのみ
4.ヒープ＋1つ以上の非クラスタ化インデックス

###留意事項
正確には、XMLインデックス、空間インデックス、カラムストアインデックス、メモリ最適化テーブルにおける非クラスター化ハッシュインデックス等、別のインデックスも存在しますが、大多数のテーブルは上記4パターンのいずれかに当てはまると思います。

###テーブルの概念についてのまとめ
SQL Serverでは、各テーブルは1つ以上のインデックスの集合として定義されると捉えることができます。

#アイデア
次に、使っていないテーブルをどうやって探していくかについて説明します。
SQL Serverでは、DMV(Dynamic Management View / 動的管理ビュー)を使って各インデックスの最終アクセス時間を確認できます。

SQL Serverにおいて、テーブルはインデックスの集合である、ということを踏まえると、「1つのテーブルの全インデックスの最終アクセス日時が古ければ、現在使われていない」と判断することができます。

どのくらい古ければいいか、という判断は難しいところではありますが、例えば最終アクセス日時が3か月以上前であれば、かなり高い確率で未使用といえると思います。

インデックスへの最終アクセス時刻は、以下の4種類に分類されるため、4種類すべてを考慮するようにクエリを組めばOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148310/45ddfe37-c404-ef67-bac6-464e0848ff6d.png)
[出典](https://docs.microsoft.com/ja-jp/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-usage-stats-transact-sql?view=sql-server-ver15)

#方法
[こちら](https://github.com/masaki-hirose/SQLServer-Info/blob/master/%E6%9C%AA%E4%BD%BF%E7%94%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E8%AA%BF%E6%9F%BB/%E6%9C%AA%E4%BD%BF%E7%94%A8%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E8%AA%BF%E6%9F%BB/%E8%AA%BF%E6%9F%BB%E3%82%AF%E3%82%A8%E3%83%AA.sql)で検出用のクエリを公開しました。
※実行にはVIEW_SERVER_STATE権限が必要です。

使い方について説明します。
####1. @threasholdDateの値を設定
デフォルトでは3か月前の日付となるように作っています。
直接 '2020/01/28'など設定していただいてOKです。
各テーブルごとに、全インデックスへの最終アクセス日時が@threasholdDateを上回らないようなテーブルを検出します。

####2. クエリを実行
取得できたテーブルたちが、未使用と判断できるテーブルです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148310/0ce848f3-059c-e574-d5ef-5bced577b4db.png)
こんな感じで取得できます。

TableName：未使用と判断したテーブル名
latest_last_user_seek：そのテーブルの全インデックスにおける最新のuser_seek日時
latest_last_user_scan：そのテーブルの全インデックスにおける最新のuser_scan日時
latest_last_user_lookup：そのテーブルの全インデックスにおける最新のuser_lookup日時
latest_last_user_update：そのテーブルの全インデックスにおける最新のuser_update日時
※NULLの場合は全インデックスで一切アクセスが無かったとの解釈でOKです。

#注意事項
テーブルがレプリケーションされている場合、サブスクライバ側（スレーブ側）では、レプリの配布コマンドによってもuser_seeksカラムがカウントアップされることがあります。
SQL Server2017で検証したところ、クラスタ化インデックスと非クラスタ化インデックスでそれぞれ以下の挙動となりました。
※ヒープはレプリできないため検証対象外です。

■ 非クラスタ化インデックス
insert/update/deleteしたとき：user_updatesが1カウントアップ

■ クラスタ化インデックス
insertしたとき：user_updatesが1カウントアップ
update/deleteしたとき：userseeks/user_updatesが1カウントアップ

そのため、アプリケーションから一切アクセスが無い状態でも、もしパブリッシャ側（マスタ側）でデータ更新が日次バッチ等で行われている場合は、「本当は使われていないけどuser_seeksがカウントアップされ続けているため、使われているテーブルのようにみえる」といった状態になってしまう可能性があります。

基本的には、未使用のテーブルであればマスタ側のデータ更新も停止しているはずなので問題ないかと思いますが、「使われていないけどデータ更新だけはバッチ等で定期的に実行されている場合」は今回紹介した方法では未使用と判断ができないため、別途調査の必要がありそうです。
今更ながらJavaScriptを勉強し直す 1. 基本情報

# はじめに
某プログラミングスクールでJavaScriptを学びましたが、あまり理解できないまま卒業してしまいました。
今更ですが、もう一度勉強し直した事をまとめていきます。

# JavaScriptとは
非常に汎用的な言語であり、様々な場面で使用される。
特にブラウザ上での操作において有益であることが多く、アプリ開発においては必要不可欠である

## 使用例
#### 1. ウェブサイトで操作して表示を変化させたい時
ある箇所にマウスを乗せるとプルダウンが展開されるなどの挙動
[メルカリ](https://www.mercari.com/jp/?gclid=CjwKCAiA1L_xBRA2EiwAgcLKA6JfrqoteLnSS-aE1KdNc0LTVHJfLkqUpsz0jWVVvEK1BXal6GqmUBoCvgEQAvD_BwE)等のサイトで使用されている。

#### 2. 画面を更新せずにサーバと通信をしたい時
例えば、[Twitter](https://twitter.com/home?lang=ja)や[Instagram](https://www.instagram.com/)で、いいねボタンを押すとブラウザ全体がリロードされることはなく、ボタンの表記だけ変わり、「自分がいいね登録をした」という情報はデータベースに保管される。
再度同じ場所をクリックすると、「自分がいいね登録をした」という情報はデータベースから取り除かれる。
都度画面が再読み込みされないので、非常に操作がしやすい。

# JavaとJavaScriptの違い
名前が似ているこの2つ、実は全く異なる言語で親戚でもない。

Java       ... サーバーサイド（サイトの裏側）を作成する目的で使用される。
JavaScript ... フロントサイド（サイトの見た目）を作成する目的で使用される。

くりぃむしちゅーの上田さん的にいうと「阿藤快と加藤あいくらい違うよ」というまとめ。

# 今回はここまで！

[次回](https://qiita.com/myktmht/items/53a45b5e8015152ebcca)に続く
Apple サポートで「403 Forbidden」と表示される場合

Apple の公式サポートサイトで「403 Forbidden」と表示された場合の対処法です。
![403](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155587/18150af5-7603-00b1-0e8f-685997f43992.png)

# 1. 4G を利用 / ルーターの再起動
何らかの理由でIPアドレスでの制限を受けてしまった場合、Wi-FiをOFFにして4Gにすると接続できます。
またダイナミックIPの場合ルーターの再起動によってもIPアドレスが変更されます。

# 2. Safari を使用する
Chrome など他ブラウザではこの現象が起こることがあります。

# 3. 別のデバイスを使用する

# 4. Cookieを削除する
Mac のトラブルで Apple サポートに連絡する前にすべきこと

基本的なトラブルシューティングを行う前にサポートに連絡してもそれらを行うように指示されるだけなので、ある程度自分で試したあとで連絡したほうが時間の節約になります。

# まず
- エラーメッセージや症状の検索
- アクティビティモニタ、コンソールでプロセス・エラーの確認
- 再起動
- OS、アプリのアップデート
- 周辺機器の取り外し
- ウイルス対策ソフトのアンインストール→再起動
- その他常駐ソフトの見直し

Mac OS X で問題を特定する方法 https://support.apple.com/ja-jp/HT203161
トラブルシューティング for Mac (ソフトウェア編) https://discussionsjapan.apple.com/docs/DOC-1032
トラブルシューティング for Mac (ハードウェア編) https://discussionsjapan.apple.com/docs/DOC-1073

無償修理の対象：
交換／リペアエクステンションプログラム　https://support.apple.com/ja-jp/exchange_repair

# 数時間おきなどに起こる場合

- 発生時刻のメモ (秒単位) → サポートにログの提出を要求されたときのために必要
- 発生状況のメモ (使用していたアプリ等)

# それでも直らない場合

- セーフモード(起動時`Shift`) https://support.apple.com/ja-jp/HT201262
- リカバリーモード(起動時`⌘Command+R`) https://support.apple.com/ja-jp/HT201314
- Apple Diagnostics https://support.apple.com/ja-jp/HT202731
- 新規ユーザ(管理者権限)作成 https://support.apple.com/ja-jp/guide/mac-help/mtusr001/mac
- NVRAMリセット https://support.apple.com/ja-jp/HT204063
- SMCリセット https://support.apple.com/ja-jp/HT201295
- Verbose モード(起動時`⌘Command+V`)：CUIで起動 https://support.apple.com/ja-jp/HT201573

# 最終手段 (バックアップ必須)

- OS の再/クリーンインストール https://support.apple.com/ja-jp/HT204904

# サポートの流れ

電話またはチャット、店舗が選択できます。
Twitter の DM でも受け付けています(おそらく英語のみ)：https://twitter.com/applesupport
**電話**
長所：タイピングしなくてよいので楽
短所：メールアドレスやシリアル番号などを伝えるのに時間がかかる
**チャット**
長所：メールアドレスやシリアル番号などをコピーするだけで伝えられる
短所：時間がかかる、問題が解決できない場合は結局電話でスペシャリストと話すことになる
**店舗**
長所：直接製品を見せられる、修理の場合はその場でできることもある
短所：店舗の近くに住んでいない場合面倒

1. まず最初にアドバイザーに繋がり、問題の説明を求められる。ここで上記で試したことを伝えるとスムーズ。
2. 問題が解決できない場合は、電話でスペシャリストと話すことになる。
3. 解決 or 修理

修理の場合には持ち込み修理と配達修理があります。配送修理では早ければ Apple に到着してから1〜2日で発送されます。MacBook の場合は梱包材は宅配業者が持ってくるのでその中に何もつけずに本体を入れるだけです。
マストドン構築3日目 on AWS

# 経緯

前回書いた [マストドン構築2日目 on AWS](https://qiita.com/suwa3/items/eb4fe8303b1b720737fa) の続きです。

半年ほど前に AWS ＆ Docker ド素人の状態から
なんとかインスタンスをたてて運用していました。

EC2の上にDockerで本番運用していましたが、だんだん辛くなってきたのでDockerから降ろすことにしました。
その作業ログです。

# 環境 / ツール
macOS Mojavi 10.14.6
AWS

# 参考にしたもの
マストドンGitHub
https://github.com/tootsuite/mastodon
公式ドキュメント
https://docs.joinmastodon.org/admin/install/

# サーバー内での作業

まずサーバーにsshログインします。

```
$ ssh ubuntu@3.112.***.*** -i ~/.ssh/hoge.pem
```

作業に入る前に、とりあえずrootユーザーになります。

```
sudo su -
```

## Nginxのセットアップ

マストドンにあるサンプルをコピーします。

```
$ cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
```

シンボリックリンクを書き換えます。

```
$ ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon
$ vi /etc/nginx/sites-available/mastodon
```

server_nameなどを編集し、ファイル名を自身のドメイン名にします。

```
$ mv mastodon don.suwa3.me
```

nginxをリロードしたら、エラーが出ました。

```
$ service nginx reload
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
```

serviceコマンドで`config test`をしてみます。

```
$ service nginx configtest
 * Testing nginx configuration                                                                                       [fail] 
```

nginxコマンドで原因究明です。
`No such file or directory`とのことです。

```
$ nginx -t
nginx: [emerg] open() "/etc/nginx/sites-enabled/mastodon" failed (2: No such file or directory) in /etc/nginx/nginx.conf:62
nginx: configuration file /etc/nginx/nginx.conf test failed
```

移動して

```
$ cd ../sites-enabled/
```

シンボリックリンクの向き先を確認します。

```
$ ls -l
total 0
lrwxrwxrwx 1 root root 34 Jan 13 10:03 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 35 Jan 28 05:22 mastodon -> /etc/nginx/sites-available/mastodon
```

`mastodon`部分を`don.suwa3.me`に書き換えます。

```
$ ln -sf /etc/nginx/sites-available/don.suwa3.me mastodon
```

リロードできました。

```
$ service nginx reload
```

念の為ステータスの確認をします。
`Active: active (running) `になっているのでOKです。

```
$ service nginx status
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) (Result: exit-code) since Tue 2020-01-28 05:16:57 CET; 31min ago
(略)
```

## SSL証明書の取得

Let's Encryptを使用して、無料のSSL証明書を取得します。
`example.com`は自身のドメイン名に書き換えます。

```
$ certbot --nginx -d example.com
```

## systemdサービスのセットアップ

systemdサービステンプレートをMastodonディレクトリからコピーします。

```
$ cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/
```

念の為、ユーザー名とパスが正しいことを確認します。

- `/etc/systemd/system/mastodon-web.service`
- `/etc/systemd/system/mastodon-sidekiq.service`
- `/etc/systemd/system/mastodon-streaming.service`

新しいsystemdサービスを開始して有効にします。

```
$ systemctl daemon-reload
$ systemctl start mastodon-web mastodon-sidekiq mastodon-streaming
$ systemctl enable mastodon-*
```

# 次回予告

4日目はDBの引っ越しやメディアサーバーなどの接続です。
作業が進み次第、Qiitaに作業ログを残したいと思います。
【Nuxt.js】dayjs導入編：リアルタイムな日時を表示してみよう

# 前置き

dayjsについて🗓🕰
日付と時刻を表示・操作できるライブラリ🎈🧸

今回は簡単に表示のみ。
時間の足し引きなどは
TypeScriptで設定が必要なため、
TypeScriptの応用編をやってからですね！

公式
https://www.npmjs.com/package/dayjs
日本語
https://github.com/iamkun/dayjs/blob/master/docs/ja/README-ja.md


# 使用ファイル

```bash:file
pages/
--| index.vue

plugins/
--| day.js

nuxt.config.js
```


# Step1: インストール

```bash:ターミナル
npm i dayjs
```

# Step2:  /pluginsにjsファイルを追加

plugins/day.jsを作成
Nuxt.jsにおけるプラグインの書き方
https://ja.nuxtjs.org/guide/plugins/

```plugins/day.js
import dayjs from 'dayjs'

export default ({ app }, inject) => {
   inject('dayjs', ((string) => dayjs(string)))
}
```

# Step3: nuxt.config.jsのpluginsに記載

これでグローバル登録

```nuxt.config.js
plugins: [
 '~plugins/day.js'
],
```

# step4: 表示


1番シンプルなdayjs().format()で表示🍒
<img width="620" alt="スクリーンショット 2020-01-27 17.09.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/d3a004be-8bf6-c32c-985b-2dac693af6e1.png">


**◾️パターン1**

```index.vue
<template>
 <div class="page">
   <p v-text="$dayjs().format('YYYY-MM-DD')" />
 </div>
</template>

<script>
</script>
```

**◾️パターン2**

```index.vue
<template>
 <div class="page">
   <p>
     {{ now }}
   </p>
 </div>
</template>
<script>
export default {
 data () {
   return {
     now: '',
   }
 },
 mounted(){
   this.now = this.$dayjs().format('YYYY-MM-DD')
 },
}
</script>
```

# 表示パターン色々

**◾️曜日、時刻も表示**

デフォルトは英語(US)ロケール。
後ほど日本語に変更していきます🌟
<img width="620" alt="スクリーンショット 2020-01-27 17.33.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/7c359a4f-84d6-426b-7d0a-765bca00c233.png">

```index.vue
<template>
 <div class="page">
   <p v-text="$dayjs().format('dddd, MMMM D, YYYY h:mm A')" />
 </div>
</template>

<script>
</script>
```

長いのでFormatを使います🍒
plugins/day.jsを編集

```plugins/day.js
import LocalizedFormat from 'dayjs/plugin/localizedFormat'

dayjs.extend(LocalizedFormat)

dayjs().format('L LT')
```

書き換え

```index.vue
<template>
 <div class="page">
   <p v-text="$dayjs().format('LLLL')" />
 </div>
</template>

<script>
</script>
```

表示は変わりません🌟
<img width="620" alt="スクリーンショット 2020-01-27 17.33.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/f19f0167-ae9c-1ee6-2483-c4a1a670ed73.png">




◾️日本語で表示
<img width="620" alt="スクリーンショット 2020-01-27 17.39.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/8eddc738-cb6d-5fda-8783-412f0ad1a862.png">

plugins/day.jsを編集

```plugins/day.js
import dayjs from 'dayjs'

// 日本語表示にするためlocaleを追加
import 'dayjs/locale/ja'
dayjs.locale('ja')

export default ({ app }, inject) => {
   inject('dayjs', ((string) => dayjs(string)))
}
```

templateを編集

```index.vue
<template>
 <div class="page">
   <p v-text="$dayjs().locale('ja').format('LLLL')" />
 </div>
</template>

<script>
</script>
```

jaを他のロケールに変えれば
簡単に表示が変わります♪



記事が公開したときにわかる様に、
Qiita・Twitterフォローをお願いします😀
https://twitter.com/aLizlab
Visual Studioでwebフォームを実行するとボタン配置がずれる問題の解決方法

#はじめに
Visual Studioを利用して、webフォームを作成していたのですが、きれいにボタンやラベルの配置を行ったつもりが、実行してみると、想定とは違う場所に配置されていて困ったのですが、解決できたので書いておきます。

#解決方法
すごい簡単なことだったのですが、位置の設定が相対になっていたのが原因でした。これを絶対に変えると想定通りに配置されるようになりました。


設定の変更は「書式」→「位置の設定」から変更できます。
[Android] AlertDialogにListViewを表示する（未完）

##前提
ListViewの使い方がわからない方はこちらを参考にしていただきたい。
https://qiita.com/QiitaD/items/6123bb53d358c51beb97

##参考URL
こちらを参考にした。この方の記事で紹介されているサンプルではうまくいった。
https://qiita.com/ueno-yuhei/items/ef6d835e143592e7a3f0

##使い方（未完）
まずListViewを作り、それを以下のようにしてAlertDialogにセットした。

~~~java
        //ListView作成
        listView.setAdapter(adapter);

        //AlertDialogにセット
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("タイトル")
                .setView(listView)
                .setPositiveButton("OK", null)
                .create();
        dialog.show();
~~~

しかし
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
というエラーが発生した。
まだ解決できていないが、この方の記事が参考になりそうである。
http://www.sumahodays.sblo.jp/article/105586834.html

##感想
ListViewをAlertDialogにセットするのみの簡単な実装だと思っていたが、うまくいかなかった。早く使えるようにしたい。
CORS（Cross-Origin Resource Sharing）とは

例えば、https://example.com から、APIなどで別のサイト( https://sample.com )にアクセスしてデータを持ってこようとするとエラーになる仕組みのことを**同一オリジンポリシー（Same-Origin Policy）**といいます。
> コンテンツがブラウザに来る源泉（origin）に基づいて整理して、外部からの干渉を防ごうとする。
by ウィキペディア（Wikipedia）

しかし、データのアクセスをしてもいい信頼できるサイトには制限をかけずに、originを越えてアクセスを可能にするために、**CORS**という仕組みが存在します。

ブラウザ「オリジンA( https://example.com )からリクエストきたけどどうする？」
オリジンB「オリジンA( https://example.com )から？それならOK:ok_hand:」

ブラウザから送られるHTTPリクエストヘッダと、サーバから返されるHTTPレスポンスヘッダでこのようなやりとりがされます。
docker初心者によるコマンドメモ

たーみなる…？という状態からdockerを触ってみました。
なのでフワッとしか理解してませんが、コマンド系を自分用にメモしていきます。

##コンテナ関連

###起動中のコンテナ一覧を表示する
```
docker ps
```
停止中のコンテナを表示させたい場合は```docker ps -a```。
起動中も停止中も含めた全てのコンテナを表示させたい場合は```docker container ls -a```


###コンテナを止める
```
docker container stop コンテナ名
```
全てのコンテナを止める場合は```docker stop $(docker ps -q)```


###コンテナを消す
```
docker container rm コンテナ名
```
全てのコンテナを消す場合は```docker rm $(docker ps -q -a)```


###コンテナ内に移動
```
sudo docker exec -i -t コンテナ名 bash
```

---

###vimコマンド
dockerコマンドとは別ですが、コンテナに入ったときvimコマンドをよく使うのでついでにメモ。


####ファイルを編集
```
vi ファイル名
```
lsやcdで対象のディレクトリまで移動してファイル名を確認。

####そもそもviが使えないと言われたら
```
apt-get update
apt-get install vim
```
コンテナから一旦出てから上記コマンドを打って、パッケージリストを更新した後vimをインストール。

ファイル編集後、終了コマンドは次の通り

```
:q （書き込まず終了）
:q! （書き込まず強制終了）
:wq （書き込みを保存して終了）
:wq! （書き込みを保存して強制終了）
```
詳しくは「vi」と検索すれば他にも色んなコマンドのまとめが出てくるので参考にしてください。
当たり前すぎるのかもしれませんが、**まずescキーを押さないと上記のコマンドは打てません**。
viと検索してもあまりそこは書かれてない気がして、初心者には不親切だなと思いました。いまだによく忘れるのでメモ。



---

###エラーログを確認
思ったように動かないときエラーログを見てみましょう。
これもコンテナに入って使うコマンドなのでついでにメモ。
nginxのコンテナを例にしています。

####エラーログやアクセスログが見られるディレクトリに移動
```
cd /var/log/nginx/
```
nginxならここ。

####エラーログの最新の10件を表示
```
tail -f error.log
```

``tail``が最新の10件を表示させていて、``-f``はログを日本時間でリアルタイムに監視し表示してくれる。




##イメージ関連


####イメージ一覧を表示
```
docker images
```

####イメージを削除
基本的に、イメージを消すには**紐づけられたコンテナを削除してある必要**があります。

```
docker rmi イメージID
```
全てのイメージを消す場合は```docker rmi $(docker images -q)```

####イメージを強制的に消す
```
docker rmi イメージID -f
``` 
-f（force）を使うとコンテナを消さずに強制削除できます。その際はコンテナは消されずに残ります。


##その他メモ
###コンテナ名は指定しておくと楽
コンテナ名は、docker container ls -aなどでコンテナ一覧を表示した際に表示されるIDの頭2文字でも代用できる（重複した場合はフルで記入する）ため、しばらくその方法を採用していたのですが毎度一覧表示させるのが面倒でした。
そこでDocker-Compose.ymlでcontainer_name:を指定してしまえば履歴を辿れるし、チームで開発する際README.mdなんかにも書きやすくなります。
@nuxtjs/vuetify v2.0 での変更点

# @nuxtjs/vuetify とは

---

## @nuxtjs/vuetify とは

* Nuxt.js のモジュールの1つ
* Vuetify を自動で読み込む
* `nuxt.config.js` でテーマの設定ができる

**Nuxt.js + Vuetify に必須のビルドモジュール**

---

## `nuxt.config.js` の書き方

v1.x までの場合

```javascript:nuxt.config.js
export default {
  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [
    '@nuxtjs/vuetify'
  ],
  /*
  ** vuetify module configuration
  ** https://github.com/nuxt-community/vuetify-module
  */
  vuetify: {
    customVariables: [
      '~/assets/variables.sass'
    ],
    theme: {
      options: {
        customProperties: true
      },
      dark: true,
      themes: {
        dark: {
          ...
        }
      }
    }
  }
}
```

---

## インストール方法

1. `npx create-nuxt-app`  
  して、  
  `? Choose UI Framework: Vuetify.js`  
  を選ぶと自動でセットアップ
2. 後からインストールする場合は

```shell:shell
$ npm i -D @nuxtjs/vuetify
```

---

# v2.0 へのバージョンアップ

---

## v2.0 での変更点

* 記事公開時点では、 `v2.0.0-alpha.4`
* Tree shaking が常時 ON に
    * `nuxt build` したときだけでなく、  
      `nuxt` でも Tree shaking するようになった
* SASS/SCSS の変数がインジェクトされるタイミングが変わった
* `fibers` ライブラリが optional dependency に
    * `node-gyp` でのビルドが不要に

詳しくは GitHub の [v2.0@alpha - Module revamp #177](https://github.com/nuxt-community/vuetify-module/pull/177)

---

## 今までの @nuxtjs/vuetify

* `nuxt` 時 → ビルド済みバンドル
    * `~vuetify/dist/vuetify.js`
    * `~vuetify/dist/vuetify/css`
        * SASS/SCSS 変数が**無視される**
* `nuxt build` 時 → ソースからビルド
    * `~vuetify/lib/index.js`
    * `~vuetify/src/styles/main.sass`
        * SASS/SCSS 変数が**有効になる**

---

## v2.0 以降の @nuxt/vuetify

* `nuxt`, `nuxt build` どちらもソースから
* SASS/SCSS 変数の変更がちゃんと反映される
* ただ、常に Tree shaking されるので、ディレクティブ、トランジション、 lazy ローディングするコンポーネントは自分で指定が必要

---

## Tree shaking は何が嬉しいの？

* Vuetify はコンポーネント数が多い
    * すべてバンドルすると、ファイルサイズが大きくなる
* Webpackでは、実際に使うソースファイルだけビルドに含める機能がある
    * Tree shaking という
    * 必要最低限だから、コンパクトになる

---

## バージョンアップ時の注意

* `nuxt.config.js` での書き方が変わった
* `fibers` がオプショナルになった
    * よく分からないが、自分の場合  
      `Cannot find module './build'`  
      エラーが出て実行できなくなった
    * `fibers` のビルドの問題だと思われる
    * `rm -rf node_modules` した後、  
      `npm i` し直したら治った
    * `npm rebuild` でも治るかもしれない

---

## v2.0 以降の `nuxt.config.js` の書き方

```javascript:nuxt.config.js
export default {
  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [
    '@nuxtjs/vuetify'
  ],
  /*
  ** vuetify module configuration
  ** https://github.com/nuxt-community/vuetify-module
  */
  vuetify: {
    customVariables: [
      '~/assets/variables.sass'
    ],
    frameworkOptions: {
      theme: {
        options: {
          customProperties: true
        },
        dark: true,
        themes: {
          dark: {
            ...
          }
        }
      }
    }
  }
}
```

---

# まとめ

---

## まとめ

* @nuxtjs/vuetify 使うべき
* v2.0 に上げてしまおう
    * `npm i -D @nuxtjs/vuetify@next`
* Nuxt.js + Vuetify でハッピーコーディングライフを！
Nuxt.jsのnuxt.config.js内で、cross-envで設定した環境変数を使用する

Nuxt.jsのプロジェクトを作成する際、開発環境や本番環境毎に環境変数を設定したい場合があります。

この環境変数を設定する方法として、 [cross-envというパッケージが公式でも紹介されている](https://ja.nuxtjs.org/api/configuration-dev/) ため、利用している方も多いかと思います。

しかし、cross-envで設定した環境変数を `nuxt.config.js` で使用できなかったため、解決方法をまとめておきます。

cross-envの設定方法などは、下記の記事などがわかりやすかったため、まだ導入していない方は参考にしてください。
[参考] [Nuxtでcross-envを使い環境ごとに環境変数を分ける](https://qiita.com/TakahiRoyte/items/c152ad8baa191ed1f8ae)

# 環境変数用のファイルを作成

今回は例として、開発環境(development)と本番環境(production)の２つの環境を用意するものとします。
まずは、環境変数用のファイルを作成します。
`config` というディレクトリを用意し、その中に作成しました。

```config/env.development.js
module.exports = {
  API_BASE_URL: 'http://localhost:3003/'
};
```

```config/env.production.js
module.exports = {
  API_BASE_URL: 'https://api.hogehoge/'
};
```

# `nuxt.config.js` 内で環境変数を設定

環境変数を設定します。

この設定を行うことで、 コード内では `process.env.API_BASE_URL` のように呼び出すことができますが、 `nuxt.config.js` 内ではまだ呼び出すための設定が完了していないため `process.env.API_BASE_URL` を使用することはできません。

例として、axiosのbaseURLに環境変数を設定してみます。

```nuxt.config.js
const envSet = require(`./config/env.${process.env.NODE_ENV || 'development'}.js`);
module.exports = {

  ...

  axios: {
    baseURL: process.env.API_BASE_URL  // 環境変数を正しく読み取れない
  },

  ...

  env: envSet

  ...

}
```
# `nuxt.config.js` 内での環境変数の使用方法

`envSet` をrequireしているので、ここから直接環境変数を読み込むことができます。

```nuxt.config.js
const envSet = require(`./config/env.${process.env.NODE_ENV || 'development'}.js`);
module.exports = {

  ...

  axios: {
    baseURL: envSet.API_BASE_URL  // 環境変数を読み込み
  },

  ...

  env: envSet

  ...

}
```

以上！
ABC 153: F - Silver Fox vs Monster

#### 問題
$N$ 体のモンスターがいる。$i$ 番目のモンスターは座標 $X_i$ にいて、体力は $H_i$ である。座標 $a$ で爆弾を使うと、$a-D \leq x \leq a+D$ の範囲のモンスターの体力を $A$ 減らすことができる。すべてのモンスターの体力を $0$ 以下にするために必要な爆弾の使用回数の最小値を求める。

#### 解法
モンスターたちをあらかじめ座標でソートしておき、座標の小さいモンスターから順に倒していくことにします。
爆弾の効果を最大限利用するため、座標 $X_1$ のモンスターを倒すには、爆弾を $X_1+D$ で使用します。すると、座標 $X_1+2D$ までのモンスターが標的になります。座標 $X_1$ のモンスターの体力が $0$ 以下になったら、この位置で爆弾を使用するのをやめます。以下、同じように爆弾を使用していけば最小回数で全モンスターを倒せます。

これを素朴に実装すればいいのですが、ネックになるのは $X_1 \leq x \leq X_1 + 2D$ の範囲の全モンスターの体力を更新する操作です。愚直に更新していると時間計算量が $O(N^2)$ になりTLEします。この部分の工夫の仕方は何通りかあります。

##### キューで管理する
キューにどの位置で何回爆弾を使用したかを入れていき、$i$ 番目のモンスターを処理する前にキューの先頭を確認して、爆弾の効果範囲から外れていたら削除するというやり方。
詳しくは[すぬけさんの解答](https://atcoder.jp/contests/abc153/submissions/9769976)や[解説](https://www.youtube.com/watch?v=pKOPnK1JPLE)を見てください。

##### いもす法で管理する
いもす法とは、imosさんが考案した累積和のアルゴリズムの改良版です。[ご本人による解説](https://imoz.jp/algorithms/imos_method.html)も参考にしてください。

各モンスターへのダメージを記録するテーブルを用意します（空間計算量は $O(N)$）。それぞれのモンスターの処理の概要は次のようになります。
1. 前のモンスターのダメージを引き継ぐ。
2. いま見ているモンスターの体力を $0$ 以下にするまで爆弾を使う。
3. 使った爆弾が影響しない最初のモンスターのダメージから、いま使った爆弾のダメージを引いておく。

たとえば、$1$ 番目のモンスターに対して爆弾を $C_1$ 回使用したとすると、テーブルに $C_1*A$ と記録します。これと同時に、この爆弾が影響しない最初のモンスター（$k$ 番目とおく）のテーブルに $-C_1*A$ と記録しておきます。すると、1. の操作を行うので、この爆弾が与える $k$ 番目のモンスターへのダメージは相殺されて $0$ になります。

それぞれのモンスターに対して $k$ 番目のモンスターを探す操作に $O(\log N)$ かかるので、全体で $O(N\log N)$ で解けました。

実装例: https://atcoder.jp/contests/abc153/submissions/9771219

#### 感想
終わってすぐ風呂に入っている間に気づいたので、あと20分早ければACしてたかもしれない。
同一のstatic変数（プロパティgetのみ経由でさえ）が違うオブジェクトを指し示す例

#実際の参照先とは
```c#
        static private char[] __TEST = null;
        static public char[] __TEST_GET
        {
            get
            {
                if (__TEST != null)
                    return __TEST;

                __TEST = new char[] { 'B', 'C', 'D' };
                return __TEST;
            }
        }
```

```c#
            char[] test_chars1 = Cfun.__TEST_GET;
            test_chars1[0] = 'R';
            char tc_1 = test_chars1[0];

            char[] test_chars2 = Cfun.__TEST_GET;
            char tc_2 = test_chars2[0];
```
このとき、
test_chars1はstatic private char[] __TESTの参照先（ア）
test_chars2もstatic private char[] __TESTの参照先（ア）
なので、tc_1もtc_2も'R'になります。
同じ参照先がtest_chars1[0] = 'R';で'R'に書き換えられてしまいます。


一方で、

```c#
        static private char[] __TEST = null;
        static public char[] __TEST_GET_B
        {
            get
            {
                /* ここだけコメントアウトします。
                if (__TEST != null)
                    return __TEST;
                */
                __TEST = new char[] { 'B', 'C', 'D' };
                return __TEST;
            }
        }
```
とすると、まるで動作が変わります。

test_chars1はstatic private char[] __TESTの参照先（カ）
とすると、
test_chars2はstatic private char[] __TESTの参照先（キ）
のようになります。
同じ【__TEST】を利用するのですが、newする都度、
（カ）を新規作成して返す、
（キ）を新規作成して返す、
という動作が.Netで行われます。

プロパティにGet{}しか実装していないのに、
同じ static private char[] __TEST なのに、
実際の参照先が異なる、というケースは普通にありえます。

#実際は何を操作しているのか把握する必要がある
結局は、アセンブラのように実際は何を（どのオブジェクトを）操作しているのか、
意識して把握する必要があります。

このサンプルだけだと、書き方の問題というレベルですが、趣旨をわかって頂けると幸いです。
electron-storeがパッケージ化したら動かねぇ！

# 解決方法はとっても単純でした．

package.jsonの`dependencies`に`electron-store`を追加するだけ．

```json
{
  (省略)
  "devDependencies": {
    "electron": "^7.1.10",
    "electron-builder": "^22.3.2",
    "electron-store": "^5.1.0"
  },
  "dependencies": {
    "electron-store": "^5.1.0"
  }
}

```

※ `dependencies`がない場合は作ってください．
自動テストのブラウザ起動までを効率的に実施する方法

Seleniumを利用したウェブの自動テストを実行するうえで、ブラウザ起動までに行わなければならない諸々の処理を簡単に行う方法をご紹介します。
Selenideの利用を前提とした説明となっています。

#まえがき
Seleniumを利用したテストを行うための事前作業として、当然ですがブラウザを起動する必要があります。
ただ、ブラウザを起動してテストを開始するまでの間に以下の手続きを踏むことが必要です。
* ブラウザ毎にドライバの更新有無を確認
* (ドライバの更新があれば)
* ブラウザに対する設定の実施

手動で頑張ってもできないことはないですが、テストを実行する端末が複数ある場合には一つ一つドライバの更新作業するのは煩わしいですし、そもそも定期的かつ安定的なテスト実行の妨げとなるので、今回はこれらを効率的に実施する方法を記載します。

#ブラウザ指定方法
Webのテストを行う上ではテスト対象のブラウザを指定する必要があります。
その方法はコード上で指定する方法と実行時のパラメータで指定する方法の2種類があります。
##コード上で指定する場合
Selenideでは設定をConfigurationクラスで保持しており、ソースコード上でブラウザを指定する場合には以下のように記載します。

```java
Configuration.browser = WebDriverRunner.CHROME
```
と書けばブラウザを切り替えることができます。

##実行時パラメータで指定する場合
ただ、通常は同一のテストを複数のブラウザで実行するというニーズが前提にあるはず。
なので、テスト対象のブラウザはコード上で直接指定するのではなく、実行時のパラメータで切り替えるのが普通です。

selenide.browserを利用して以下のように記述することで実行ブラウザを指定できます。
*java -Dselenide.browser=Chrome*

とはいえ、ブラウザを指定する際にはそのブラウザ固有の設定もしたいもの。
かつ、いちいちテストコードにはブラウザの設定は書きたくない。
そのような場合への対処方法を以下にご紹介します。

#ブラウザ別の設定方法
ブラウザの起動処理の前にパラメータ設定を行うコードを呼び出すことで解決ができます。
以下、サンプルコードです。

```java:IEWebDriverProvider.java
package com.driver;


public class IEWebDriverProvider implements WebDriverProvider {
  @Override
  public WebDriver createDriver(final DesiredCapabilities desiredCapabilities) {
    InternetExplorerDriverManager.iedriver().arch32().setup();
    desiredCapabilities.setCapability("ignoreProtectedModeSettings", true);
    InternetExplorerOptions opt = new InternetExplorerOptions(desiredCapabilities)
        .destructivelyEnsureCleanSession().withAttachTimeout(10, TimeUnit.SECONDS);
    opt.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);

    return new InternetExplorerDriver(opt);
  }
}
```

WebDriverProviderを実装したクラスを用意し、加えて実行時にパラメータとして以下のようにコードのパスを与えます。
*-Dselenide.browser=com.driver.IEWebDriverProvider*

そうすることでブラウザを起動させるタイミング、具体的には
*WebDriverRunner.getAndCheckWebDriver();*
が実行される中でブラウザに対する設定を行う上記コードもあわせて実行されます。

今回はIEを起動する例を記載していますが、各ブラウザに対してあらかじめ設定用のclassを用意しておくことが可能です。
この方法のメリットはブラウザに対して必要な事前設定を個別のテストに記述することを避けることで、テストコードの見通しが良くなる点を複数のテストで設定コードを使い回せる点にあります。

#ドライバの自動更新
テスト実行時にはテストを実行する端末にインストールされているドライバのバージョンが古いためにテストが失敗することがあります。

しかし、Selenideには[WebdriverManager](https://github.com/bonigarcia/webdrivermanager)を内包しており、自動的にブラウザを更新する処理が組み込まれているので、特に意識することなくテストを実行する端末のドライバが最新のドライバか否かをチェックして、最新でない場合には自動でダウンロードしてくれます。

Selenideを利用していない場合にもWebdriverManagerを利用することで同様の効果を得られると思われます。

##ドライバのバージョンを指定する場合
最新ドライバのバージョンとテスト実行端末のブラウザのバージョンが適合しない場合、そのままではテストが実行できないのでドライバのバージョンを個別に指定する必要があります。

その場合には以下のようにドライバのバージョンを指定することも可能です。
*java -Dwdm.chromeDriverVersion=1.99*

また、ドライバが最新であることが明確かつ、テスト件数が膨大で少しでもテストにかかる時間を短縮したい等の理由により自動更新処理を止めたい場合もあります。
そのような場合にも以下のように設定することで、更新処理を止めることができます。
*java -Dselenide.driverManagerEnabled=false*

#おわりに
以上、テスト開始の前提となるブラウザに関連する諸々の面倒を解消する方法をご紹介しました。
こちらを参考に快適なテスト自動化ライフをお過ごしいただければと思います。
[Mac][Catalina] ESET で SSH 接続を許可する

## はじめに

多くのセキュリティソフトにはファイヤウォールの機能があります．
そのため，Mac をサーバとして使用する際には，アプリケーションごとにセキュリティソフトの追加を変えなければなりません．

[ESET Cyber Security Pro V6.8](https://eset-info.canon-its.jp/support/setup/howto_setup2_ecsp.html) がインストールされた macOS Catalina を SSH サーバとして使用する際の設定を書いていきます．


## 手順

[ホーム] -> [パーソナルファイヤウォール] -> [設定] と遷移していきます．

<img width="1550" alt="スクリーンショット 2020-01-28 13.03.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131552/0b7c5c55-b95d-c686-c776-3a0783da3e7c.png">

左下の「追加」を選択すると，新たなルールを追加することができます．
ここでは「システムの通信を許可」というルールを作成します．

<img width="1550" alt="スクリーンショット 2020-01-28 13.03.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131552/f58da576-cdb9-c24a-17e3-21abc7bae092.png">

「内向き」のアクションを「許可」するようなルールとします．
ここでいう「内向き」とは，外部から Mac へ SSH 接続する際の方向です．

<img width="1550" alt="スクリーンショット 2020-01-28 13.03.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131552/08a0831d-aa55-fef6-a57a-757e2cff19a5.png">

「ローカル」の「ssh」で使用されるポートに対して「TCP & UDP」の通信を許可します．
Mac の 22 番ポートに対する SSH 接続のことです．

<img width="1550" alt="スクリーンショット 2020-01-28 13.03.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131552/c8da013c-e64f-b347-3e4f-96dd5783bd09.png">

このルールを「インターネット全体」に対して適用します．
もちろん，特定の IP アドレスからの通信のみを許可しても良いでしょう．

最後に「終了」を選択すれば無事にルールが追加されます．


## 注意

ルールを追加してもうまくいかない場合は，以下を確認してみてください．

- ルールを追加した「プロファイル」と，Mac の接続先ネットワークの「プロファイル」が一致しているか
- そもそも Mac 標準のファイヤウォールが有効になっていないか（下図を参照）

<img width="780" alt="スクリーンショット 2020-01-28 16.14.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131552/a3bee139-4898-c904-2efb-5d593de660cb.png">


## おわりに

今回の設定だと，Mac にグローバル IP が付与されていた場合，全世界に SSH 接続を許可することになります．
特別な事情がない限り，公開鍵認証のみを許可するようにしましょう．

- [[Catalina] Mac の OpenSSH Server を公開鍵認証のみにする - Qiita](https://qiita.com/khys/items/8c7cfed78a06023e00f8)
MacからGKEを操作するための認証メモ

## 概要

* 作業端末（Mac）からGKEにアクセスしたい
* Macから認証情報を取得できなかった
* CloudShellからは認証情報取得可能
* 権限周りが問題と推測
* コマンドは以下



## 詳細

### Macの場合

```
$ gcloud container clusters get-credentials cluster-1 --zone asia-northeast1-a
Fetching cluster endpoint and auth data.
ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Required "container.clusters.get" permission(s) for "projects/[PROJECT_NAME]/zones/asia-northeast1-a/clusters/[CLUSTER_NAME]".
```

### CloudShellの場合

```
$ gcloud container clusters get-credentials cluster-1 --zone asia-northeast1-a
Fetching cluster endpoint and auth data.
kubeconfig entry generated for cluster-1.
```

#### 原因

* GoogleCloudSDKに認証をしていなかった


### Google Cloud SDKの認証


```
$ gcloud auth login
Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?code_challenge=...
```

* ここでユーザアカウント（Googleアカウント）かサービスアカウント（GCP用Googleアカウント)を選んで認証する必要がある
* ここではサービスアカウントを選択
* ユーザアカウントを選択してみたがgcloudコマンドによる認証は失敗した

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/83168117-0653-6dd6-cfa0-f9c5ae417f4f.png)

* 許可を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/999263a8-8b0d-82ea-cf18-10519293ff58.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/d174faf3-10db-1de3-550f-206508de370d.png)

```
$ gcloud container clusters get-credentials cluster-1 --zone asia-northeast1-a
Fetching cluster endpoint and auth data.
kubeconfig entry generated for cluster-1.
```

## 結論

* MACからGKEを操作するにはまず”gcloud auth login”でCloudSDK認証をする事
* その際はサービスアカウントでログインする必要がある（たぶん）

## 参考

[公式：認証について](https://cloud.google.com/sdk/docs/authorizing?hl=ja)