OmniAICreator/Qiita-1.07M huggingface dataset:
偏微分について -なぜを解決する-

#偏微分の目的
A；説明変数が複数ある中でのデータの関連付けの可能性や現状の把握について役立つため。

##微分では何をしていたか？
二次元上のグラフを考えた時に、二値の範囲における傾きを作る。
##なぜ求めるか？
①ある点における直線や曲線においての法則についてさらに細かく考え、精度の高いものにするため。
②これによって２値の間にある関連性についてさらに把握でき、法則性として他に当てはめることができるようになるため。

##手順
①二値の最初の値の接線を引く。
②これを数式によって計算する（極限値）

次に偏微分について考える
偏微分は、多変数関数における微分を目的として行うもの
###2変数関数、３変数関数、多変数関数


###どのように行うか？
多変数関数におけるグラフ（入力多数、出力１）を考える。
三次元上で基本的に考えることができる

一点を固定し、複数の軸から傾き（極限値）を求める。

グラフは多次元で表されて曲線になるイメージを持つ

###？？ラウンドディーが出てくる
この記号は偏微分と微分を区別するための記号

###??デルターが出てくる
方向に対しての微動に関して表すため

#最終的にデータ分析の観点から考えてみた
どのようにこの多変数関数を活用していくか？
機械学習を用いたデータ分析において説明変数が２値以上である場合に出てくる計算。

##メリット；
###①グラフからデータが線形か非線形か求めることができる
###②数値の間にあるデータから精度の高い法則を見つけ出し、予測の精度を上げるため。

つまり、よく
「とりあえず、微分しましょう」
と言う言葉は、与えられたデータの中で精度の高い法則を見つけ出しましょう！！
と言うことだったことが判明。

思ったより簡単だったのかもしれません。
コンストラクタ関数を表す型定義

以前 「へぇ～😀」と思ったのに忘れてしまっていたのでメモ

## すること
「コンストラクタ関数を受け取る」関数を定義することで、関数内でインスタンスを生成したりすることができるようになります。
そのために必要な型定義はどのようにするべきでしょうか？
(文章では伝わりにくいですね...)

## 先に結論

`tsyringe` の [constructor](https://github.com/microsoft/tsyringe/blob/v4.3.0/src/types/constructor.ts) にあるように定義すればよいです

```ts:constructor.ts
type constructor<T> = {
  new (...args: any[]): T;
};
```

`new` することができる関数(つまりコンストラクタ関数) みたいな感じかな🤔

## 実際に試してみる

以下のようなコードで試してみました。
`create` という関数を用意し、インスタンスを生成して返すだけです。
その際前後にログを仕込んでいます。

```ts

type constructor<T> = new (...args: any[]) => T;

//インスタンスを生成する関数
function create<T>(ctor: constructor<T>, ...args: any[]): T {
  console.log("before create");
  const t = new ctor(...args);
  console.log("after create");
  return t;
}

//----------
//クラスの準備
class A {
  constructor() {
    console.log("new A()");
  }
}

class B {
  constructor(public val1: string) {
    console.log("new B()");
    console.log({ val1 });
  }
}

//----------
// 実行
const a = create(A);//aの型はA
const b = create(B, "xxx");//bの型はB
```

実行結果は以下のようになります。

```
before create
new A()
after create
before create
new B()
{ val1: 'xxx' }
after create
```

これだけではあまり ありがたみはないですが
`tsyringe` のようなDIコンテナを作ったり、その他の共通処理を作ったりするときには覚えておいて損はないテクニックかなと思います。
[該当箇所のコード](https://github.com/microsoft/tsyringe/blob/v4.3.0/src/dependency-container.ts#L362)

## おわりに
`new` は型定義の部分でも使えるという新しい発見をすることができました。
【超初心者用】GitHub リモートリポジトリの作成、ローカルリポジトリの紐付け

# はじめに
プログラミング初心者の方こんにちは。

某プログラミングスクールで学び始めて２ヶ月程経ちましたため、
備忘録・アウトプットも兼ねて今の知識を少しづつ書いていこうと思います。
自分と同じ超初心者の方の少しでも助けになれば幸いです。

**※初心者による初心者のための記事のため、用語の使い方等が一般的なものと異なる場合があります。「あくまで備忘録」であることをご承知くださいませ。**

#GitHubとは
という概要はすっ飛ばします。
他のページをご覧ください。

#注意
①　前提としてGithubのアカウントに登録済みであることとします。

②　この記事ではリモートリポジトリを作成、新しいブランチの作成など「作業前の準備」をしていきます。
　　完成したコードをGitHubにアップロードするだけの場合はこの方の記事をご覧ください。とても分かりやすいです。
https://qiita.com/under_chilchil/items/ec9d0050c1e3fb6576de
（自分は最初スクールでのGitHubのテキストがよくわからず、こちらの方法で提出する時のみgitを使用しておりました、、、）

それでは、実際にやってみましょう！
#やり方





###①GitHubのマイページへ

リモートリポジトリを作成します
<img width="1440" alt="スクリーンショット 2020-08-13 20.31.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691544/f05e8a45-8d4a-c454-5434-9c142a3d0d1b.png">


<img width="1436" alt="スクリーンショット 2020-08-13 20.18.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691544/c7f88c5b-9147-1907-1bf9-b552b549fa71.png">

<img width="1440" alt="スクリーンショット 2020-08-13 21.11.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691544/b10dd830-567b-b3fb-7ec3-9693c69b653d.png">


###②アプリケーションを作成

```ruby:ターミナル
$ rails new 好きなアプリケーション
```
（$は入力しないで大丈夫です。）

###③リモートとの紐付け

```ruby:ターミナル
#git初期化
$ git init

#ステージングに登録
$ git add -A

#コミットする（リモートリポジトリにセーブ）
$ git commit -m "first commit"

#先ほど作ったリモートリポジトリを紐付け
$ git remote add origin 先ほどコピーしたURL

#リモートリポジトリに登録
$ git push -u origin master
```
（一行ずつエンターキー押してくださいね）

#ちょっと一息&解説
gitでは　add（編集したデータ持ってくるよ！）→　commit（セーブしたよ！）　→　push（セーブしたやつリモートに持っていくよ！）という３ステップかけて作業データを更新します。
なので「こまめにコミットしてね！」と言われて「？」がたくさん浮かんできた方は「こまめにセーブしてね！」と解釈するとまだ理解しやすい、、、かな、、？
作業を進めていくとなんとなくわかってくるので、一緒になれていきましょう笑

#続きいきます
###④作業ブランチ（自分の作業場みたいなところ）の作成
作業用のブランチでできた内容を本番用のブランチにコピーしていくイメージです。
誤ってアプリケーションに不具合が起きても本番用のが生きてるから大丈夫的な。
（個人だとあまり分かりませんが、チームで作業する時に重要さに気づかされます笑）

```ruby:ターミナル
#ブランチの確認
$ git branch
#エンター押すと、、、
*master　←masterにいる状態（今いるブランチには*がつきます）
```
```ruby:ターミナル
#作業ブランチの作成・移動
$ git checkout -b 好きなブランチ名
（checkout -bは新しいブランチを作って、同時にそのブランチに移動します）

#エンター押すと、、
　master　
*作成したブランチ名　←（今いるブランチが移動していることを確認）
```
###⑤作成したブランチに空コミットする
（作成したブランチとリモートリポジトリが紐付けされているか確認）

```ruby:ターミナル
$ git add -A
(add -Aで新規作成、変更部分を選択します）

$ git commit --allow-empty -m "first commit"

$ git push origin 作成したブランチ名
```



ここまできたら、GitHubのInsights→Networkでブランチとコミットを確認できると思います。


あとは、コードを追加・編集したら

```ruby:ターミナル
$ git add -A 

$ git commit -m コミットメッセージ（〇〇追加など）　

$ git push origin 作成したブランチ名
```
でどんどん作業内容を保存していってください。

#最後に

この後にもマージやプルなどありますが、初めての投稿で意外と時間がかってしまったのでこの辺で終わりにしたいと思います、、、、

また時間ができましたら続きを書こうと思います！
お楽しみに〜
chrome拡張機能の開発について少し理解できた

最近chrome拡張機能について調べていてサンプロを見たりしているが、いまいちcontent_scriptやbackground.js、chrome.*APIの挙動がよくわからなかったが、なんとなくつかめた気がするので備忘録としてメモ

#content_script
##特徴

- DOMにはアクセスできる
- 開いているページのディベロッパーツールでデバッグができる
- chrome.*APIには色々制限があり、使えないものがある

#Background-Page
##特徴

- chrome.*APIが全て使える
- 常にバックグラウンドで動くのでメモリを常に消費してしまう。そのためEvent-Pageを使うことが推奨される。manifest.jsondで`"persistent": false`を書くことでEvent-Pageになる。

#content_scriptとBackground-Pageの連携
この2つのファイルの連携をchrome.*APIが行う

例としては以下
####メッセージを送信する
```javascript:content_ascript
//変数sendをメッセージで送る
chrome.runtime.sendMessage(send, function(response) {
   console.log(response);//メッセージの受け手がレスを返したときキャッチできる
});
```
参考：[Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】](https://qiita.com/guru_taka/items/37a90766f4f845e963e5)

####メッセージを受け取る
```javascript:background-page
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
  console.log(msg);//送られたメッセージをキャッチ
  sendResponse(response);//sendResponseでmsgを送ったスクリプト側にレスを返せる
});
```
参考：[Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】](https://qiita.com/guru_taka/items/37a90766f4f845e963e5)

##何をしているか
またこのコードではcontent_script→background-pageへメッセージを送信している。
そして、変数sendの内容がbackgroundのコールバック関数の引数msgに渡される
そして関数sendResponseの引数へ渡したものがメッセージの送信元へ送られることで双方の連携ができている。

##chrome.runtimeではコンテンツスクリプトへ送信できない
またこのコードではcontent_script→background-pageへメッセージを送信するのに
**chrome.runtime.sendMessage()**を使用しているが、逆をやりたい場合、
つまりbackground-page→content_scriptへメッセージを送信したい場合は**chrome.tabs.sendMessage()**を使用する。

参考：https://developer.chrome.com/extensions/tabs

**chrome.tabs.sendMessage()**を使用する際にはどのcontent-scriptに送信するかを決めるためにtabIdなるものが必要になる。
参考：https://developer.chrome.com/apps/runtime


##デバッグ関連

|種類|説明|
|---|---|
|content-script|通常のデベロッパーツール|
|background-page|拡張機能の管理画面から|
|popup|ポップアップを出して右クリック→検証|



#参考
- [Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】](https://qiita.com/guru_taka/items/37a90766f4f845e963e5)
- [Chrome Extension の作り方 (その4: Event Page / Background Page)](https://qiita.com/sakaimo/items/edd910a770b3d5ba83e3)
【完全備忘録】よく使うけど覚えられないコード集

# はじめに
よく書くけどなぜか覚えられず，毎回ググっているコードをまとめました．

# Python

### おまじないのあれ
```python
if __name__ == '__main__':
    print('Hello World!')
```

### 警告を非表示にする
```python
import warnings
warnings.filterwarnings('ignore')
```

### list を txt ファイルに保存する
```python
# 保存
with open('list.txt', 'w') as f:
    print(*list_obj, sep='\n', file=f)

# 読み込み
with open('list.txt') as f:
    list_obj = f.read().splitlines()
# list_obj = list(map(lambda x: x.split(','), list_obj)) # 二次元以上の場合
```

### リスト内の検索
```python
list = [i for i in list if 'hogehoge' in i]
```

### プログレスバーの表示
```python
from tqdm import tqdm

# jupyter notebook
from tqdm import tqdm_notebook as tqdm
```

### pandas のカラムを全表示
```python
import pandas as pd
pd.set_option('display.max_rows', None)
```

### pandas 内の文字数制限の設定
```python
import pandas as pd
pd.set_option('display.max_colwidth', 1000)
```

### 図の大きさの変更
``` python
fig = plt.figure(figsize=(20, 10))
```

### Bar Plot
```python
plt.bar(df.index, df['value'], align='center')
plt.xticks(df.index, df.index)
```

### 変数の相関関係をヒートマップでプロット
```python
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns

plt.figure(figsize=(10,10))
sns.heatmap(df, linewidths=0.1, vmax=1.0, square=True, cmap=plt.cm.RdBu, annot=True)
```

### ある文字列より前の文字列を取り出す(ある文字列より後の文字を削除する)
```python
t = 'abc/def'
print(t.split('/')[0]) # abc
print(t.split('/')[1]) # def

# 行列に map するときに指定した文字がないとエラーを吐くため，以下の関数で map すると良い．
def pick_char(t):
    try:
        return t.split('/')[0]
    except IndexError:
        return t
df.map(pick_char)
```

### 余計な文字列を削除する

```python
t = '\n\t\r\u3000        abc        \u3000\r\t\n'
print(t.strip()) # abc
```

### pip のキャッシュ削除してインストール
```
$ pip install --no-cache-dir <Library>
```
`-I` で再インストール

### 極座標変換
``` python
np.sin(2*np.pi*data[col]/max_val)
np.cos(2*np.pi*data[col]/max_val)
```

# git

### キャッシュの削除
```python
$ git rm -r --cached .
```

# コマンドライン

### 権限の付与
```
$ chown -R $USER <dir>
```

# おわりに
便利な文字列操作に出会い次第，追記していく．
M5StickCでPuppyCを動かす

![20200813_145834.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/ef4e3326-789b-64d4-4d3c-d5d2e2bab476.jpeg)

M5StickC + PuppyC のセットアップをした時の覚書きです。

## M5StickCのセットアップ

![20200813_145857.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/f3934e0d-2bbe-fa7f-3cfd-a5de768e3f24.jpeg)


開発環境はUIFlowを使います。
M5StickCへのUIFlowのファームウェア書き込みは、M5Burnerを使いました。
[M5Stackサイト](https://m5stack.com/)からSOFTWARE > Downloadsをクリック。
![M51.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/fa9ac5a5-9bb9-0081-300c-1aa1a2d589cf.png)

CP2104 DriverとM5Burnerをダウンロード。
![M52.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/9ac32cef-d46a-257b-5548-06941e638ef7.png)

CP2104はWindows版をダウンロードして、x64のexeをダブルクリックしてインストールを実行。
![M53.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/44eb2590-96d5-ff1d-f9f7-7a2bf1a0d3f0.png)

M5BurnerはWin10 x64版をダウンロードして解凍したファイルを任意の場所に配置します。
![M54.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/da707027-c424-28ed-a713-e47be48d2877.png)

## M5BurnerでM5StickCにUIFlowを書き込む
M5StickCをUSBケーブルでWindows PCに接続します。
M5Burner.exeをダブルクリックしてM5Burnerを起動して、Wifiの接続先のSSID、パスワードを入力。
左側からSTICKCを選択するとUIFlowが表示されるのでBurnを実行するとUIFlowのファームウェアが書き込まれます。
![M55.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/9792ead7-e4ce-cc70-1039-ad81edcaf3b4.png)

M5StickCの左側にあるボタンを押して電源を入れると、APIキーが画面に表示されます。
![20200813_161115.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/d4f855cd-a27e-61b0-46c8-ea862806651c.jpeg)


## ブラウザでUIFlow起動
ブラウザから[UIFlow](http://flow.m5stack.com/)を起動します。
バージョンを選択。
![M56.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/82907441-d318-6e7f-da1c-65a5589b28b3.png)

設定画面が表示されます。
M5StickCに表示されていたAPIキーを入力して、言語、デバイス：Stick-Cを選択してOK。
![M57.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/5fd994c1-23e9-4d12-9a7c-934aeb5a681a.png)

UIFlowが表示される。
![M58.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/34c92dfd-69ea-7c8f-de5b-8422ba29dbbc.png)

##Puppyのブロック追加
PuppyCのプログラム作成のためにPuppyのブロックを追加します。
M5StickCのイメージ画像の下のHatを選択して＋をクリック。
![M59.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/3cc3e086-3dce-8a13-406d-0471600e8dff.png)

HatからPuppyCを選択してOK。
![M5-10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/179d289d-6acd-c873-5cd0-7969f7bdb62d.png)

ブロックカテゴリのHATにPuppyのブロックが追加されます。
![M5-11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/a4af0796-360b-3023-4ffb-67a41a1a9d07.png)

## M5StickCをPuppyCに接続する
![20200813_170239-COLLAGE.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/617b0ed2-819d-9a56-e5f1-553de77b33b7.jpeg)


## プログラムを実行する
M5StickCがPCと接続されていることを確認します。
接続されていない場合は、再読み込みマークをクリックします。
![M5-13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/35df4308-4310-7ac0-cccd-af29b4777b44.png)

右上の実行ボタンをクリックして、プログラムをM5StickCに転送して実行します。
![M5-12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/8b4e4a53-1804-56a1-b700-3e379dda620c.png)

PuppyCの電源をON（左から右にスイッチをスライド）すると、PuppyCが歩きます。
Julia基本演算子一覧

Juliaの算術演算子は比較的シンプルで覚えやすいですが、他の言語と混ざりやすいのでメモ程度に書いておきます。

#算術演算子

||||
|:-----------:|:------------:|:------------:|
| x + y | 加算 | 加算を行う |
| x - y | 減算 | 減算を行う |
| x * y | 乗算 | 乗算を行う |
| x / y | 除算 | 除算を行う |
| x \ y | 逆除算 | y / x と等価 |
| x ^ y | べき乗 | 冪乗計算を行う |
| x % y | 余剰 | 余剰を計算, rem(x, y)と等価 |
| ! x | 否定 | xがブール代数のときtrueとfalseを逆転させる |


#論理演算子


|||
|:-----------:|:------------:|
| && | 論理積(短絡評価) |
| I I | 論理和(短絡評価) |
| & | 論理積 |
| I | 論理和 |


#比較演算子

|||
|:-----------:|:------------:|
| == | 等価 |
| != , ≠ | 非等価 |
| < | 未満 |
| <= , ≤  | 以下 |
| > | より大きい |
| >= , ≥ | 以上 |
【メモ】Sourcetreeのスタッシュを一括削除する

気づいたらスタッシュが沢山溜まっていて、ポチポチ消していくのも面倒だし、一括削除したいな〜ときってありますよね。
一括削除はSourcetree上（GUI）ではできないので、ターミナルから行います。

# 手順

**スタッシュ一覧を確認**

```shell
$ git stash list
```

**スタッシュを全削除**

```shell
$ git stash clear
```

すぐに Sourcetree にも反映されます:star2:
【SQL入門】% や _ を含む文字列を LIKE で探したい

## LIKE 演算子

文字列があるパターンに合致しているかをチェックすることを**パターンマッチング**という。
SQLではこのパターンマッチングに**LIKE 演算子**を用いる。

```sql

式 LIKE パターン文字列
```

LIKE演算子以降の**パターン文字列**には、以下のパターン文字を使用できる。

| パターン文字        |       意味　        |
|:-----------------|:--------------------|
| %                |  任意の0文字以上の文字列|
| _ (アンダースコア)   |     任意の1文字      |

```sql
-- title に '100' を含むデータを取得 
SELECT * FROM movie WHERE title LIKE '%100%';
```

## パターン文字のエスケープ処理

パターン文字ではなく単なる文字として `%` や `_` を使いたい時は、**ESCAPE句**を使用する。
ESCAPE句で指定した文字(エスケープ文字)に続く `%` や `_` は、ただの文字として扱われる。

```SQL
-- title が '100%' で終わるデータを取得 
SELECT * FROM movie WHERE title LIKE '%100$%' ESCAPE '$';
```

ちなみに、MySQLではデフォルトで `¥` がエスケープ文字として扱われる。

```sql
-- title が '100%' で終わるデータを取得
SELECT * FROM movie WHERE title LIKE '%100¥%';
```

参考図書：[スッキリわかるSQL入門 第2版](https://www.amazon.co.jp/dp/4295005096/ref=cm_sw_em_r_mt_dp_IGtnFbPQ9MTVT)
Ubuntu Vue CLIインストールエラーで助けられた記事まとめ

UbuntuでVue.jsを学習中にVue−CLIをインストールしようとしたら最後の方で
code EEXIST ~やらのエラーが出て正しくインストールできなかった。

エラー解決のために参考にさせて頂いた記事。
①
https://qiita.com/NaokiIshimura/items/cc07441939b226e779c6

②
https://webjin.work/install-vue-js-on-ubuntu-16-04-at-npm/

①→②の順で実施したら無事VueCLIがインストールできた。
ちなみに ②の記事の手順ではVueCLIのインストールの際に、
sudo npm install -g @vue/cli　となっているがエラーになる。
sudo を外して、　npm install -g @vue/cli としたら成功。

その後は vue create my-cli による自動生成もちゃんと出来ました。
ありがたやありがたや。
【ネットワーク・ストレージ編】AWS SAA試験に関連するサービスをまとめてみた👑

 
こんばんは。ちなです( *^^* )

現在、絶賛AWSソリューションアーキテクトアソシエイト試験取得のため、絶賛勉強中です✎

簡単にではありますが、試験に出てくるサービスをまとめてみようかなと思います〜〜〜！
今回は、以下の２つに関連するサービスです☆

・ネットワーキングとコンテンツ配信に関連するもの
・ストレージに関連するもの



##ネットワーキングとコンテンツ配信
###VPC（Amazon Virtual Private Cloud）
AWS内に作成するユーザー専用の仮想ネットワーク。
サブネット・IGW（インターネットゲートウェイ）、ネットワークACL、ルートテーブル等のリソース使用し、簡単にカスタマイズができる。

###CloudFront（Amazon CloudFront）
テキストファイル・プログラム・写真・動画等のコンテンツをキャッシュし、配信ができるCDN（Contents Delivery NetWork）サービス。
オンプレサーバーにも利用できる。

###Route 53（Amazon Route 53）
DNS管理サービス。
ドメインの取得・更新や、DNSのルーティング、リソースの状態のチェック（ヘルスチェック）ができる。

##ストレージサービス
###S3 （Amazon Simple Storage Service）
高い可用性と耐久性を保持したオブジェクトストレージ。
用途に応じて、以下の5つのストレージクラスを使い分ける。
・STANDARD：デフォルトのストレージ。
・STANDARD-IA：STANDARDよりも格納コストが安価である。データの読み出しは従量課金制。
・ONEZONE-IA：単一AZのみでデータを複製する。それ以外はSTANDARD-IAと同等。
・INTELIGENT-TIERING：STANDARDとSTANDARD-IAの2層構造。ライフサイクルを自動化でき、30日以上参照されなかった場合、STANDARD-IAに移動させられる。

###Glacier（Amazon Glacier）
アーカイブ目的用のストレージ。
アクセスされるまでに数時間必要のため、保管専門的な感じ。
新規作成時はGlacierを利用できない。

###EBS（Amazon EBS）
ブロックストレージサービス。
RDSのデータを保存したり、EC2のOS領域や追加ボリュームとして利用される。

###EFS（Amazon EFS）
フルマネージドなファイルストレージ（NFS）サービス。
複数のEC2インスタンスからアクセス可能。

###StrageGeteway（Amazon Strage Gate）
オンプレとAWSのデータ連携を簡単に行うために、受け口を提供するサービス。










余力があるときにもっと内容書き足せたらいいなあ〜と思っていますが、今回はこの辺で𐀪𐁑
Google Compute Engine (GCE)のインスタンスを再起動したらApacheが起動しなくて困った

受託開発しているサイトを乗せたGCEインスタンスのスペックが足りなくなったということで、一度インスタンスをシャットダウンしてスペックアップ→再起動したところなぜかApacheが起動してくれない。
さあ困った！どうしよう！ということで試したこと＆解決方法メモ。

#まず結論

```
$ which fuser
```
fuserが叩けるか確認して、インストールされてなければ

```
$ sudo apt-get install psmisc
```
これでfuserコマンドを使えるようにしたあと（必要に応じてyumと読み替えてください）、

```
$ sudo fuser -k -n -tcp 80
```

をひたすら連打。10回くらいやったらなんもメッセージが返ってこなくなったら適当にhttpdをrestart。で治った。

#環境と現象

LAMP Certified by BitnamiをデプロイしたGCEインスタンス。CentOS 7の至って普通なLAMP環境です。

Apache2でLaravel製のサイトを動かしてたところ、アクセス数増加に伴ってちょっと重くなる頻度が増えてきた。GCPのモニタリングでも割と高めの使用率で張り付くことが多いと分かったので、スペックを上げることに決定。

もともとCPU 1Core, RAM 1.7GB, ROM 10GBだったのを新しくCPU 2Core, RAM 7.5GB, ROM 20GBにしてサーバー再起動しようとしたところ、httpdが立ち上がってこない。スペック低すぎとかは言わんといて。

#やったこと

まずスペック上げたことが原因か？と思ったものの、逆に落としたわけでもないので首をかしげながら念のため各種設定確認。MySQLもPHPも正常に動作してるし、きちんとストレージもマウントされてる。

そして、このタイミングでApacheの動作がおかしいと判明。restartかけようとすると

```
$ sudo /opt/bitnami/ctlscript.sh restart apache
(98)Address already in use: AH00073: make_sock: unable to listen for connections on address [::]:80
(98)Address already in use: AH00073: make_sock: unable to listen for connections on address 0.0.0.0:80
```

こんなメッセージで怒られてApacheが起動できない。
なるほどこれは他のプロセスが80番ポートを塞いでるのだということで、愚直に

```
$ sudo netstat -ltnp | grep ':80'
```

を叩くと、

```
tcp6   0   0  :::80   :::*   LISTEN   8833/apache2
```

と出てくるので、やはり愚直に

```
$ sudo kill -9 8833
```

でプロセスをキル。よしこれで解決だ……と思い再度httpdをrestartさせようとすると

```
$ sudo /opt/bitnami/ctlscript.sh restart apache
(98)Address already in use: AH00073: make_sock: unable to listen for connections on address [::]:80
(98)Address already in use: AH00073: make_sock: unable to listen for connections on address 0.0.0.0:80
```

やはり怒られる。あれぇぇ！？

再度netstatを叩いてみると、やはり謎にapache2のプロセスが動いている。もしやこれは起動に失敗して多重プロセスになってるやつでは……と思い立ち、他に方法も思いつかなかったので

```
$ sudo fuser -k -n -tcp 80
```

をひたすら叩きまくっていく。すると途中からメッセージが返ってこなくなったので、満を持してrestart。

```
$ sudo /opt/bitnami/ctlscript.sh restart apache
Unmonitored apache
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : apache not running
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd started at port 80
Monitored apache
```
よし通った！
ということで無事にhttpd起動、ブラウザからのアクセスも確認。めでたしめでたし。さすがに冷や汗かいたけど……

#おわりに

正直原因がなんなのかは全く分かってないですが、とりあえず解決したので何より。まあWebサーバーなんてせいぜい月イチで再起動かければ多いほうなので、いいっちゃいいんですが。

冗長化っぽいことを何もしてない小規模のサイト運用なので、こういう些細なトラブルが出てきたときヒヤっとしますね。ということで他の方のヒヤリハット防止も兼ねた備忘録でした。おしまい。
App Engineスタンダード環境でMemorystore for Redisを使う(Laravel)

Redisの使い方とローカル環境に関しては割愛。

## Laravelにpredisを追加

```bash
composer require predis/predis
```

## redisを設定

GCPの管理画面からインスタンスを作成。
リージョンはGAEと同一にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533120/675275b8-f0fb-2811-3712-3cecbc07cb37.png)

作成後、IPアドレスとポートをメモっておく。

## サーバーレス VPC アクセスを作成

GCPの管理画面からコネクタを作成。
リージョンはGAEと同一にする。IP範囲は10.8.0.0でいいらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533120/1658d037-9fa8-b03a-5f6f-5532014cd776.png)

作成されたら、コネクタの名前をメモっておく。

## app.yamlに追加

REDIS_HOSTとREDIS_PORTは「redisを設定」でメモった値を設定。
vpc_access_connectorのプロジェクト名、リージョン、コネクタ名はそれぞれの環境で変更

```yaml:app.yaml
runtime: php73

....
....

  REDIS_CLIENT: predis
  REDIS_HOST: 10.xx.xx.xx
#  REDIS_PASSWORD: null
  REDIS_PORT: 6379

vpc_access_connector:
  name: 'projects/my-project/locations/asia-northeast1/connectors/my-connectors'
```

## app deployして終了

しかし、下記エラー

```bash
ERROR: (gcloud.beta.app.deploy) PERMISSION_DENIED: Operation is not allowed. The "vpcaccess.connectors.use" permission is required.
```

## cloud buildを使っているならもう一つやることが。

IAMと管理を開き、cloudbuildに対して以下の権限を与える。

- App Engine 管理者
- Cloud Build サービス アカウント
- Compute 管理者
- サーバーレス VPC アクセス ユーザー
ferenOSの導入３（パッケージのアップデート、インストール）

##パッケージのアップデート
次のコマンドを実行します。
`apt update && sudo apt upgrade`
Ubuntuの場合と同じですね。付属の「アップデートマネージャ」からでもアップデート可能です。

##パッケージ、アプリケーションのインストール方法まとめ
Ubuntu,Debian系のディストリビューションへのパッケージのインストール方法と同じdebファイルからのインストール。
ferenOS上で、アプリケーションを使用するには以下の通りの方法があります。
 1.パッケージ管理システムのaptコマンドを使用
　Ubuntu,debianと共通したインストール方法
　　`sudo apt install <hoge>`
 2.Storeアプリを使用
 3.Synapticパッケージマネージャ使用
 4.dpkg -iコマンド使用。（個別にパッケージファイルdebファイルをダウンロードしてインストールする場合に用いる
   `sudo dpkg -i <hoge.deb>`
 5.snap
 6.Flatpak
 7.ソースからのビルド
 8.AppImageファイルの利用
 9.shファイルからのインストール（ドライバのインストールに使いました。）
 
このうち、２と３は１をGUI上で使用できるようにしたアプリケーションです。２と３で殆どのアプリケーションのインストールは賄えると思います。
個人的には、ほとんど１〜３しか使いません。

ただ、これだけだとUbuntuのリポジトリとferenOSにデフォルトで設定されているリポジトリにあるアプリケーションしかインストールできないので、リポジトリ、PPAを追加します。
PPAの場合は次のようにして、
  `sudo apt-add-repository ppa:hoge/hoge`
あるいは,PPAではないリポジトリはwgetで公開鍵を入手して、
`wget -qO- https://repo.hoge.com/archive/hoge_key.pub | sudo apt-key add -`　
そののち、リポジトリを追加します。
`sudo apt-add-repository 'deb http://repo.hoge.com/hoge'`

追加したリポジトリ、PPAは「Software Sources」アプリから確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535888/e6cb1026-db74-27c0-b293-77c7dd395181.png)
すでに、VivaldiやWineのリポジトリが追加済みです。
![Screenshot_20200813_213053.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535888/e19c7231-0641-e2ad-7448-359e41c5f2ab.png)
graphic-driversはすでに設定済みのPPA。チェックマークを入れると有効になります。
適当なPPAを設定しましたが、反映されているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535888/7f3c77a4-ef6d-fd86-091f-250d5a6071df.png)
こちらは、公式のリポジトリです。ミラーサーバは自由に変更できます。
「Linux mint(tracia)」のミラーサーバの設定ですが、このアプリを再起動したところ、デフォルトの設定のままになっているエラーが確認されています。設定ファイル(/etc/apt/sources.list.d/official-package-repositories.list)を確認したところ、ちゃんと設定の変更はできているようなので、表示だけがおかしいようです。
【AWS Lambda】Lambdaで「Hello World!」

#はじめに
[「Hello, World!」をサーバーレスで実行する](https://aws.amazon.com/jp/getting-started/hands-on/run-serverless-code/)の記事で、Lambdaで「Hello World!」を行なってみた。

#手順
##設計図の選択
Lambdaコンソールで「関数の作成」を選択する。
<img width="1069" alt="スクリーンショット 2020-08-13 21.05.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/fbd0ed17-f5d4-860c-9231-05f9927f1541.png">
「設計図の使用」を選択。
フィルターに「hello-world-python」を入力し、「hello-world-python」を選択して、「設定」ボタンを選択。

<img width="1082" alt="スクリーンショット 2020-08-13 21.06.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/414efd04-bbf0-d22a-d7c8-39b5b9c955ea.png">

##関数の設定
基本的な情報で、下記内容を入力。
「関数名」:`hello-world-python`
「実行ロール」:`AWSポリシーテンプレートから新しいロールを作成`
「ロール名」:`lambda_basic_execution`
<img width="937" alt="スクリーンショット 2020-08-13 21.09.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/1079a7a5-55bc-3310-d004-0e1cdc6f4079.png">
「関数の作成」を選択。
<img width="955" alt="スクリーンショット 2020-08-13 21.09.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/9f7ae1ad-7c32-0e33-b7d8-0cab26bd4ab4.png">

##関数の呼び出し
「テストイベントの設定」を選択する。
<img width="1049" alt="スクリーンショット 2020-08-13 21.14.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/88dcd93f-0c8e-b364-21ac-9fb45a4c3000.png">
イベント内容を下記のように入力。
イベントテンプレート：`hello-world`
イベント名：`helloworldevent`
サンプルJSON内の`value1`を`hello, world!`に変更。
「作成」ボタンを選択。
<img width="833" alt="スクリーンショット 2020-08-13 21.16.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/033dcf08-f0a0-dad1-767d-72888c6bf6fe.png">
「テスト」を選択する。
<img width="1066" alt="スクリーンショット 2020-08-13 21.16.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/976c2022-c053-98c5-c86c-c452d9c3a99d.png">
結果が表示される。
<img width="1036" alt="スクリーンショット 2020-08-13 21.17.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/1634e405-21aa-0efd-2056-8748045ae96c.png">
【初心者向け】GitLabで突然ssh接続できなくなったら試す事

セキュリティの観点からGithubは使えないが、Gitは導入したいという企業にGitLabは支持されているのではないでしょうか。
Git自体があまり詳しく無い初心者にはGitLabでググってもドンピシャの答えが出てこないので、今後の為にメモっておこうと思います。

## 記事の対象像と事例
- Git初心者
- セットアップはやった事があるが、詳しい仕組みやエラー表示は理解していない
- SourceTreeというGitクライアントソフトウェアを利用している。
- GitLabを利用している。※Githubでも同じではないかとは思うのですが.....
- 突然、pullやcommitができなくなった。

以上の様な対象と、事例の方であれば同じ様に解決ができる可能性があるかもしれません。

# 突然pullできなくなった。
正直な話、突然では無いんですよね。PCが壊れてしまいデータと環境を丸ごと別のPCにいれたのですが、環境もそのままなので、問題ないかと思ったのですが、GitLabと接続できなくなってしまいました。

```
Please make sure you have the correct access rights
and the repository exists.
Completed with errors, see above
```
"あなたが正しいアクセス権を持っているかそのリポジトリが存在することを確認してください。"
と表示されるようになってしまいました。

ちなみに元々作成してた公開鍵は~/.ssh/id_rsaという名前で作成していました。
この公開鍵はGitLab以外にも使用していたので、なるべくもう一度id_rsaでGitLabとのssh接続が可能になるようにしたいと思いました。

# SSHファイルの「パーミッションの問題！？
ディレクトリへのアクセス権限が無い事でエラーになっている場合があるようです。
前のPCからデータを丸ごと復元しましたが、ファイルパーミッションが変わることもあるかもしれないと試してみました。

```
//sshフォルダのid_rsaファイルのパーミッション
$ ls -l ~/.ssh | grep id_rsa 
```
> -rw-------  1 [UserName]  staff  2622  6 17  2019 id_rsa

この様にid_rsaのパーミッションが所有者のみ書き出し、読み込み（600）になっていれば大丈夫です。
※パーミッションの詳しい内容は下記のページが参考になると思います。
[初心者に分かるアクセス権（パーミッション）の基本](http://kawatama.net/web/1392)

もしパーミッションが異なっていたらコマンドラインからの変更は、chmodで行う事ができますが、初心者には安心のGUIから行うことも可能です。
Macの場合ですが、対象フォルダ、対象ファイルを右クリックし、「情報を見る」をクリックします。
情報ウィンドウ共有とアクセス権と記載がある箇所で、対象のuser（大概自分の名前とかつけてる）のアクセス権を「読み/書き」にします。他のユーザーはアクセス不可にします。これで600に設定されます。

# あきらめて別名で公開鍵・秘密鍵を作り直す
色々試してみたのですが結局、公開鍵・秘密鍵を作り直すというのが、簡単だし、早かったです。
公開鍵・秘密鍵は複数作成する事が可能ですので、使えない時は作り直すという決断もありだと思いました。

もう一度sshキー(秘密鍵・公開鍵)を作成するのですが、単純に[$ ssh-keygen]で作成してしまうと、id_rsa（デフォルトのファイル）を上書きしてしまいます。
※前回わからず上書きしてしまい面倒な事になりました

```
//sshキー(秘密鍵・公開鍵)を作成するディレクトリに移動
cd ~/.ssh
//sshキー(秘密鍵・公開鍵)の名前を指定して作成
ssh-keygen -f gitlab（作成したいファイル名）
```
パスワード入力を求められますので、入力して「The key's randomart image is:」などの文言が表示されたら新規に作成完了です。

sshファイルの中に今回作成した**gitlab（新たに作成したファイル名）.pub**があるのを確認したら、内容をGitLabのssh鍵に登録して完了です。

# configファイルを修正する
デフォルトのファイル（id_rsa）と、新たに作成したファイル（gitlab）の2つになったので、configファイルを書き直す必要があります。
configファイルはsshキー(秘密鍵・公開鍵)を作成したディレクトリ.ssh/の中にあります。

```ruby:.ssh/config
# 初期で読み込むファイル
IdentityFile ~/.ssh/id_rsa
# GitLabで読み込むファイル
  HostName gitlab.com
  IdentityFile ~/.ssh/gitlab
  port 22
  user git
  TCPKeepAlive yes
  IdentitiesOnly yes
```
# configファイルが認識されなかったら
configファイルが認識されなかったら下のコマンドを打ってください。ssh-agent（秘密鍵を一時的に保存してくれる）に鍵を渡してくれます。

```
$ ssh-add ~/.ssh/gitlab(←自分で設定した名前）
```

Macのキーチェーンストアに保存する場合は

```
$ ssh-add -K ~/.ssh/gitlab(←自分で設定した名前）
```

以上が、自分が試してみたことです。色々やってみましたが、新たに公開鍵・秘密鍵を作り直して、$ ssh-addすれば最短だったのではないかと思いました。
C言語に関する英文を翻訳してみる

C言語に関するある未公開の英文を著者の了解を得て翻訳してみる。

 <この項は書きかけです。順次追記します。>

原文

>The "undefined" definition on the IS are important c language technologies that C language does not forbid the development of CPU.
The "unspecified" definition on the IS also same as undefined that
C language does not forbid the development of CPU.
Some suggestions, some definitions are provided by C langage to CPU and C language implementations that choice a definition of them.
The "implementation definition"s on the IS are the same context.
But implementation shall inform C programmers to understand what implementation are designed.
```

翻訳
```
国際規格の「未定義」の定義は重要なC言語技術であり、C言語国際規格はCPUの開発を禁じていません。

国際規格の「未規定」の定義も未定義と同じです。C言語国際規格はCPUの開発を禁じていません。
いくつかの提案、いくつかの定義は、それらの定義を選択するCPUおよびC言語の実装への提供します。

国際規格の「実装定義」は同じ文脈です。しかし、C言語実装はCプログラマに対して、どの実装を設計したかを理解させる必要があります。
``
`
英文が公開されたら、表題、著者名なども記載する予定です。

なお、権利義務関係の用語は法律用語を参照するようにしている。

民法
http://www.japaneselawtranslation.go.jp/law/detail/?id=2057

>第五章　法律行為
Chapter V Juristic Acts
第一節　総則
Section 1 General Provisions
（公序良俗）
(Public Policy)
第九十条　公の秩序又は善良の風俗に反する事項を目的とする法律行為は、無効とする。
Article 90　A juristic act with any purpose which is against public policy is void.
（任意規定と異なる意思表示）
(Manifestation of Intention Inconsistent with Default Rules)
第九十一条　法律行為の当事者が法令中の公の秩序に関しない規定と異なる意思を表示したときは、その意思に従う。
Article 91　If any party to a juristic act manifests any intention which is inconsistent with a provision in any laws and regulations not related to public policy, such intention shall prevail.
（任意規定と異なる慣習）
(Custom Inconsistent with Default Rules)
第九十二条　法令中の公の秩序に関しない規定と異なる慣習がある場合において、法律行為の当事者がその慣習による意思を有しているものと認められるときは、その慣習に従う。
Article 92　In cases there is any custom which is inconsistent with a provision in any law or regulation not related to public policy, if it is found that any party to a juristic act has the intention to abide by such custom, such custom shall prevail.

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

#文書履歴(document history)
ver. 0.01初稿 20200813
ver. 0.02 民法追記 20200814
rails serverを起動しようとすると "A server is already running."のエラーが表示されるときの対処法

rails serverを起動しようとしたら、以下のようなエラーが表示されて、起動できない場合があります。

```
$ rails s -b 0.0.0.0
=> Booting Puma
=> Rails 5.2.4.2 application starting in development 
=> Run `rails server -h` for more startup options
A server is already running. Check /ディレクトリパス/tmp/pids/server.pid.
Exiting
```
これはサーバーがすでに実行中のため、起こるエラーです。
この場合の対処法をご紹介いたします。

# server.pidのPIDをkillする
/tmp/pids/server.pid内のPIDの番号をkillすればOKです。
server.pidファイルを手動で削除しても、サーバーは起動したままなので、
以下のコマンドを実行し、3000番で動いているプロセスを探し、killします。

```
$ lsof -i:3000
COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ruby2.5 3033 vagrant   16u  IPv4  27499      0t0  TCP *:3000 (LISTEN)
```
上記のコマンドで判明した、PIDの番号を以下のコマンドでkillします。

```
$ kill -9 3033
```

これでサーバーが切れ、うまく起動できます。

# 参考記事
https://qiita.com/motty93/items/d22c1eb8f5128f8cd7f8
TypeScriptのEnumの何がダメなのか

# TypeScriptのEnumの何がダメなのか

TypeScriptのEnum使うのは避けようという事を耳にしたのできちんと調べた
自分なりに脱却案を記した

## 数値型Enum

```enum.ts
enum Sex {
  male,
  female
}

console.log(Sex.male) //0
console.log(Sex[0]) //male
```

数値は自由に選択可能

```enum.ts
enum Sex {
  male = 1,
  female
}

console.log(Sex.male) //1
console.log(Sex.female) //2
console.log(Sex[1]) //male
```

#### 問題点

コンパイルエラーにならないので気づかずに999を代入できてしまう。むかつく。

```enum.ts
enum Sex {
  male = 1,
  female
}

const hoge: Sex = 999 //コンパイルエラーにならない

console.log(hoge) //999
console.log(Sex[hoge]) //undifined
```

EnumはTypeScriptの独自機能なのでコンパイルされるとこうなる

```enum.js
var Sex;
(function (Sex) {
    Sex[Sex["male"] = 1] = "male";
    Sex[Sex["female"] = 2] = "female";
})(Sex || (Sex = {}));
```

## 文字列型のEnum

文字列を指定することができる。文字列での代入ができないので変更があった場合に最小限で済む。

```enum.ts
enum Sex {
  male = "男性",
  female = "女性"
}

const hoge: Sex = Sex.male
const fuga: Sex = "男性"  //コンパイルエラー

console.log(hoge) //男性
console.log(Sex["male"]) //男性
```

以下でもできる。コンパイル結果は変わらないのでキーが文字列で記述することが明示的なことから個人的にはこちらが良い気がしてる
Enumを使うとするならばですが。。。

```enum.ts
enum Sex {
  "male" = "男性",
  "female" = "女性"
}
console.log(Sex["male"]) //男性
```

```enum.ts
var Sex;
(function (Sex) {
    Sex["male"] = "\u7537\u6027";
    Sex["female"] = "\u5973\u6027";
})(Sex || (Sex = {}));
```

## const Enum

```enum.ts
const enum Sex {
  male = 1,
  female
}

const hoge: Sex = Sex.male
```

constを入れることによって使用時にインライン化してコンパイルされる。

```enum.ts
const hoge = 1 /* male */;
```

## Enumがダメなところ

### 全般

- 数値型Enumが型安全でない
    - 上記で示した通り

### constでないEnum

constでないEnumの欠点は2つ

- そもそもTypeScriptの概念に合っていない
    - TypeScriptはJavaScriptとの互換性があり静的型付けができることがコンセプトなのに互換性がない
- Tree-shakingできない
    - コンパイル時に即時関数を作り出すので使われているかどうか判断できない

### const Enum

- Babelでのトランスパイルができない
    - 方法はあるがプラグインを入れたりなど手間が生じる

## Enum脱却

じゃあどうするか…
コンパイル時にオブジェクトを生成するんだったら
初めからオブジェクト作ればよくないか!?ってことで以下にした

```index.ts
const sexNumber = {
  male: 0,
  female: 1
} as const

console.log(sexNumber["male"]) //0

const sexString = {
  male: "男性",
  female: "女性"
} as const

console.log(sexString["male"]) //男性
```

脱却できたかと思う。
ご意見があればコメントお願い致します!!

## 参照
[さようなら、TypeScript enum](https://www.kabuku.co.jp/developers/good-bye-typescript-enum)
[TypeScriptのenumを使わないほうがいい理由を、Tree-shakingの観点で紹介します](https://engineering.linecorp.com/ja/blog/typescript-enum-tree-shaking/)
LFTP の -x オプションで最上位の該当ディレクトリのみを除外する

以下のディレクトリ構造の際
`home/` 直下の `img/` 以下は除外しつつ、`home/upload/img/` 以下は同期したかった。

```bash
home/
　├ img/
　│　└ dummyA.png
　└ upload/
　 　└ img/
　 　 　└ dummyB.png
```


よく紹介されている下記の指定をした場合、全階層を対象に除外されてしまう。

```terminal
mirror --reverse -x img/ --delete /home /site
```

```bash
site/
　└ upload/
```

# 対処法
`^\` を指定すると最上位のみが除外対象となる。

```terminal
mirror --reverse -x ^\img/ --delete /home /site
```

```bash
site/
　└ upload/
　 　└ img/
　 　 　└ dummyB.png
```

# 参考
https://serverfault.com/questions/291255/what-is-the-syntax-of-lftps-mirror-x-exclude-option
Dockerfileでの|(パイプ)の扱い

# [hadolint DL4006](https://github.com/hadolint/hadolint/wiki/DL4006)について

## Set the SHELL option -o pipefail before RUN with a pipe in

Dockerfileの`RUN`命令の前に、`SHELL`命令で、`-o pipefail`を指定しておくべしというもの

なぜつけた方がいいのか？

```dockerfile:example(ダメな例)
RUN wget -O - https://some.site | wc -l > /number
```

上の例では、`wc -lコマンドが成功している限り、wgetコマンドが失敗しても、このビルドステップは成功して新しいイメージを生成`します。

そこで`SHELL命令`の出番

```dockerfile:example(良い例)
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN wget -O - https://some.site | wc -l > /number
```

### [bash -o pipefail / set -o pipefail](https://qiita.com/daisukeshimizu/items/c01f29f8398cc7f5c396)

パイプでつないだ各コマンドの中で終了ステータスが0以外(正常終了以外)だった場合に、最後に0以外だったコマンドの終了ステータスが返されます。

すなわちwgetコマンドが失敗した場合に、ビルドが成功しないようになるということです
初心者によるbit全探索まとめ

こんにちは。

Atcoderを初めて1.5ヶ月緑コーダーのうなぎです。
今回は@e869120 さんの作成された[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編：目指せ水色コーダー！】](https://qiita.com/e869120/items/eb50fdaece12be418faa#2-3-%E5%88%86%E9%87%8E%E5%88%A5%E5%88%9D%E4%B8%AD%E7%B4%9A%E8%80%85%E3%81%8C%E8%A7%A3%E3%81%8F%E3%81%B9%E3%81%8D%E9%81%8E%E5%8E%BB%E5%95%8F%E7%B2%BE%E9%81%B8-100-%E5%95%8F)のbit探索に関する問題を初心者が実際にどう考えて解いていたのかをこの記事に記して置こうと思います。

あくまで、初心者が初心者の時に感じたことを書いている記事となっています。

#bit全探索
bit全探索を用いる例としてはn個数の選択肢が与えられた時にそれぞれについて「選択する」or「選択しない」（「買う」or「買わない」とか）のパターンを全て試したい時に使う。（つまり$2^n$通り）
要は

```python:sample.py
for i in range(2):
    for j in range(2):
        for k in range(2):
            for l in range(2):
                ....
```
みたいに書くとやってられないため、この「選択する」or「選択しない」を2進数の0と1に見立てて全探索するということ。全探索のためnはだいたい30よりは小さいイメージ。逆にnが30未満くらいの範囲ならbit全探索が求められていることを疑っても良い？？
#基本的な書き方

```python:sample.py
for i in range(1<<n): #全パターン列挙
    for j in range(n): #各bitについて
        if (i>>j)&1: #選んだパターンiのうちどのbitが立っているか
            ....
```
のようになります。
####初心者に分かりにくい点
先輩方のコードを参考にした時、すっと入ってこなかった部分をまとめました。

+ `(1<<n)`と`2^n`は同じ。`<<`はbit演算子で1をn個左にシフトするという意味。例として`1<<4`は2進数で`0b10000`で10進数で16となり`2^4`と一致する。
+ `(i>>j)&1`は選んだiのj+1桁目と1のANDを取るというもの。つまりiのj+1桁目が1かどうかを判定する。ここでjは0からn-1までなので、iを2進数で100とした時、100と1、10と1、1と1、...とbit演算子でずらしていったものと1を比較することになる。
もう一つは`i&(1<<j)`も見る。本質的には同じ。iと1をjだけずらして各桁が1かどうかを見る。
ちなみに自分は最初の頃この書き方を知らず、あるパターン`i`を`bin(i)[2:]`というめちゃくちゃ面倒なことをしていた。（これはbin(i)で'0b100'が取り出せて0bを除く。その後、各値が`'1'`かどうかを判定する。）
以下です笑

```python:sample.py
#最初の頃のクソコード
for i in range(2**N):
    I = bin(i)[2:]
    I = I.zfill(N)
    for j in range(len(I)):
        if I[j]=='1':
            ....
```
+ 「立っている」という用語はそれが`1`であるかどうか。

#解いた問題
@e869120 さんの作成された[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編：目指せ水色コーダー！】](https://qiita.com/e869120/items/eb50fdaece12be418faa#2-3-%E5%88%86%E9%87%8E%E5%88%A5%E5%88%9D%E4%B8%AD%E7%B4%9A%E8%80%85%E3%81%8C%E8%A7%A3%E3%81%8F%E3%81%B9%E3%81%8D%E9%81%8E%E5%8E%BB%E5%95%8F%E7%B2%BE%E9%81%B8-100-%E5%95%8F)の該当問題(64-67)を2020年8月時点でレート900の私が解いた感想です（あくまで感想です、いかに述べる解き方などが最適解とは限りません）。
一緒に精進する人にとってのモチベーションになれば幸いです。
以下該当問題を解いた感想（**ネタバレ注意**）

+ [ALDS_5_A - 総当たり](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_5_A&lang=ja)
基本問題。nが20以下なので全探索しても$10^6$程度だからゴリ押せるという発想。あとは基本的なbit探索。
+ [AtCoder Beginner Contest 128 C - Switches](https://atcoder.jp/contests/abc128/tasks/abc128_c)
nが10以下なので高々1024通りについて考えれば良い。色々勉強するとこういう問題でシンプルに全探索すればいいのだと気づかなくなりやすい気がする。各場合についてスイッチがonのものを数えるだけ。
+ [AtCoder Beginner Contest 002 D - 派閥](https://atcoder.jp/contests/abc002/tasks/abc002_4)
これもnが12以下のケース。各桁1のものだけ集めてそれらが全て友達であるかを$\rm O(n^2)$でみていく。
+ [JOI 2008 予選 5 - おせんべい](https://atcoder.jp/contests/joi2008yo/tasks/joi2008yo_e)
rが10以下であることに注目して、全ての行の表裏で全探索する。あとは各列で表と裏の大きい方をカウントすれば良い。（裏が多かったらその列はひっくり返すと考える。）pypy使えば2s以内に抑えられる。
+ [Square869120Contest #4 B - Buildings are Colorful!](https://atcoder.jp/contests/s8pc-4/tasks/s8pc_4_b)
単調増加が続く部分は確実に見えるのでその部分を取り除いた箇所でbit探索すれば良い。





#最後に
今回はbit探索についてまとめてみました。
ここが分かりにくかったとか、もっとこう書いた方が良いなどのアドバイスがあれば遠慮なく質問してください。
URLにアニメーションをつける

# はじめに
友達からおもしろいと言われ、この[ツイート](https://twitter.com/nealagarwal/status/1293578708247248897)を見ました。
「URLに動きがついていておもしろい！」と感動したので、自分も作成してみました。
GitHub Pagesに公開しましたので[こちら](https://takashi0602.github.io/url-animation/)からURLの動きを見ることができます。

# URLにアニメーションをつける

`location.hash`を使用し、URLの`#`以下に動きがつくようにします。

```app.js
const moons = ["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"];

const loop = (arr, count = 0, time = 75) => {
  location.hash = arr[count % arr.length];
  setTimeout(loop.bind(this, arr, count + 1, time), time);
};

loop(moons);
```

上記のコードを実行すると以下のように動きます。

![moon.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192833/02c9a80e-90ca-ff70-f332-aecd809c181c.gif)

`loop`関数は第一引数に文字列を持つ配列を指定し、第二引数には配列の開始位置を数値で指定します。第三引数には何ミリ秒ごとに`loop`関数を実行するかを数値で指定します。

上記のコードを応用して以下のように記述することもできます。

```app.js
const clocks = ["🕛", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚"];

const loop = (arr, count = 0, time = 75) => {...}

loop(clocks, 1, 100);
```

上記のコードを実行すると1時の絵文字から100ミリ秒間隔で動きます。

![clock.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192833/7030c4bb-430b-15aa-7e11-96b91a14ab49.gif)

# おわりに
普段の開発ではURLにアニメーションをつけることはほとんどありませんが、ポートフォリオなどにつけると少し遊び心があっていいのではないでしょうか。

# 参考URL

https://matthewrayfield.com/articles/animating-urls-with-javascript-and-emojis/
Windowsコマンドプロンプトでスクリプト格納場所の親ディレクトリの絶対パスを取得

# 概要

Windowsのコマンドプロンプトで、スクリプトのあるパスの親ディレクトリの絶対パスを取得したいことがあったので、自分用にメモ
（要はスクリプトの格納場所を基準にして、相対パスを絶対パスに変換したい）

# 実践

- スクリプトの格納場所自体は例えば[ここ](https://qiita.com/k1tajima/items/ebf4145367ef268dc124)などを参考に`%~dp0`で取得可能
- `pushd`と`popd`によるディレクトリ移動と`cd`コマンドによる絶対パスの取得を使うことで、スクリプトの場所からの相対パスを絶対パスに変換

```cmd:get_parent.bat
@echo off
:: スクリプトのあるディレクトリの絶対パスを取得
set script_dir=%~dp0

:: 相対パスを使って一時的に移動（この場合は`%script_dir%`の親ディレクトリ）
pushd %script_dir%..

:: 現在のカレントパスがスクリプトの親ディレクトリ
set PARENT_PATH=%CD%

:: 元のパスに戻る
popd

:: %script_dir%は一時的な変数なので一応消去しておく
set script_dir=

@echo on
```

- 上の例で`call path\to\get_parent.bat`のような感じでコマンドプロンプトで実行すると、スクリプト(batファイル)の親ディレクトリの絶対パスが`PARENT_PATH`に格納される

# 参考

- https://qiita.com/k1tajima/items/ebf4145367ef268dc124
- https://qiita.com/noraworld/items/81c12253d22b7575151a
- https://www.atmarkit.co.jp/ait/articles/0609/16/news022.html
- https://www.adminweb.jp/command/command/index4.html
[Mac]右クリックメニューから動画をアニメーションGIFに変換する

2020年に書くことか・・・？と思いつつ、右クリックメニューからクイックアクションで動画をアニメーションGIFできるようにしたので書いた。
ffmpegが必要なのでインストールしておくこと。

```
brew install ffmpeg
```

# やったこと

- Automator でクイックアクションを自作する
- ffmpegで動画をアニメーションGIFに変換する

![test.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/4c9a8131-4570-ee16-c154-82fa1d85d7c6.gif)

# クイックアクションの作成

## 新規作成

Automatorを起動したら `⌘N` で書類を新規作成。クイックアクションを選択。

![step1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/0f0379ce-0042-6589-8f8d-9d5de5becf29.png)

## ワークフローの設定

画面上部の設定欄で、ムービーファイルを受け取るよう設定する。
イメージはただのアイコンなので適当に選ぶ。

![step2.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/19749ce8-3e77-d40a-31bf-8c18e4949f22.gif)

## ワークフローの組み立て

左のアクション一覧から `シェルスクリプトを実行` と `AppleScriptを実行` を順にドラッグしてくる。
AppleScriptは処理時間が意外に長いので追加したが、通知が必要なければ追加する必要はない。

![step3.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/c0d16845-d85d-83a0-c073-4d229a68f273.gif)

## スクリプト

シェルを `/bin/bash` に変更し、入力の引き渡し方法を `引数として` に変更する。
それから `シェルスクリプトを実行` にこのスクリプトを貼り付ける。
ffmpegのパスは、Homebrewでインストールした場合のパスになっているので、適宜変更すること。

`split[a][b]; [a]palettegen[c]; [b][c]paletteuse` の部分は画質を良くするたために設定しているが、これを使うとサイズがかなり大きくなるので、画質が悪くてもいい|サイズが大きすぎる、場合は外したほうがいいと思う。
[綺麗なGIFアニメを作る（カラーパレットを自動作成し適用） | Qiita](https://qiita.com/saka212/items/fae883a4030857f41c1c)

```bash
dir=$(dirname "$1")
cd $dir
/opt/homebrew/bin/ffmpeg -i "$1" -vf "scale=640:-1,split[a][b]; [a]palettegen[c]; [b][c]paletteuse" -r 10 "$1.gif"
```

AppleScriptはただの完了通知処理。
こちらも貼り付ける。

```applescript
on run {input, parameters}
	display notification "変換処理が完了しました" with title "アニメーションGIFに変換する"
	return input
end run
```

![step4.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/96331c49-47c9-b516-7d2c-78f3bd90ae1b.gif)

## 名前を付けて保存

`アニメーションGIFに変換する.workflow` という名前で保存する。
この名前がクイックアクションメニューに表示されるっぽい。

# クイックアクションの実行

動画ファイルを右クリックし、クイックアクションを選ぶと `アニメーションGIFに変換する` というメニューがあるはず。

![test.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/4c9a8131-4570-ee16-c154-82fa1d85d7c6.gif)

この記事の動画とGIFのサイズはこんな感じだった。

![size.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379/1be759be-60d0-892f-7f3b-4a1347a838b8.png)

# gifsicle

あまりサイズが変わらなかったので外してしまったが `gifsicle` を使うと最適化されて画質はほぼそのままで多少サイズが小さくなる。
`split[a][b]; [a]palettegen[c]; [b][c]paletteuse` の部分を外して使うなら `gifsicle` を使ってもいいと思う。
その場合 `シェルスクリプトを実行` のスクリプトは下記のようにする。
最適化も結構時間がかかるので、最適化レベルを下げることもできる。

```
/opt/homebrew/bin/ffmpeg -i "$1" -vf "scale=640:-1" -r 10 - | /usr/local/bin/gifsicle --optimize=3 > "$1.gif"
```

[gifsicle を用いた gif アニメーションの作成方法](https://www.gfd-dennou.org/arch/cc-env/make_animation/gifsicle.htm)
ある型があるinterfaceを実装しているかを保証する


## 目的

ある型がinterfaceを実装しているかを保証したい。

## 環境

Go: go1.14 darwin/amd64

## サンプルコード

```go
package main

// 適当なinterfaceを定義する。
type Somether interface {
    Method() bool
}

// 適当な type alias を定義する。Sometherを満足することを期待する。
type MyType string

// メソッドリストにないメソッドを定義する。つまりインターフェースを満足していない。
func (m *MyType) Method2() bool {
    return true
}

// Somether型の変数を定義する。変数は利用しないので _ で無視する。
// インターフェース値の型にMyType型のポインタ、値はnilをアサインする。
var _ Somether = (*MyType)(nil)

func main() {}

// 実行結果
// cannot use (*MyType)(nil) (type *MyType) as type Somether in assignment:
// *MyType does not implement Somether (missing Method method)
```

[playground](https://play.golang.org/p/3jqSsi_h7r4)

## 標準パッケージ

標準パッケージでも一部実装されている箇所がある。以下、一例。

* [testing.T](https://github.com/golang/go/blob/release-branch.go1.14/src/testing/testing.go#L611)
* [net.Buffers](https://github.com/golang/go/blob/release-branch.go1.14/src/net/net.go#L667)

## 参考

* [guarantee_satisfies_interface](https://golang.org/doc/faq#guarantee_satisfies_interface)
* [golang-interface-compliance-compile-type-check](https://stackoverflow.com/questions/17994519/golang-interface-compliance-compile-type-check)
VSCodeの設定

# VSCodeの設定

OpenCVとかいくつかのライブラリだけで補完？的なものが働かなかったので設定を変えて何とかした時のメモ

VSCodeのバージョン　1.47.3
Windows10

#### 困っていたこと    
cv2.と入力しても、.以降に何もでない。
候補が出たり、入力したら説明みたいな便利なのが出てほしい

#### やったこと
VSCodeの設定ファイルに追記
使っているPythonのライブラリ?が入っているところのパスを追記
もともとは空っぽだった

    "python.autoComplete.extraPaths": [
        "～\\Lib\\site-packages"
    ]


Pylanceというのがいいよ！ってだれかから聞いて使っていたけど、そっちだとうまくいかない感じだったので

```
"python.languageServer": "Pylance"
```
を

```
"python.languageServer": "Microsoft"
```
に変更

そもそもPylanceに変えて何が変わったのか気づいていなかったのでとりあえずOkとする
（元がMicrosoftだったのかは分からないが。。。）

#### 参考（ほぼそのまま）
https://qiita.com/kusanoiskuzuno/items/fc6a32ef32dd9500f746
[Swift] 配列の要素を重複なくランダムに取り出す。永遠に...

##これはなに？

与えられた配列の要素をランダムにかつ重複なくとりだすstructです。
なお、全て取り出し終えると最初に戻って繰り返します。

###永遠に...


```swift
struct RepeatingRandomIterator<T>: IteratorProtocol {
  private let base: [T]
  private var indexes: [Int] = []

  init(base: [T]) {
    self.base  = base
  }

  mutating func next() -> T? {

    if indexes.isEmpty {
      indexes = (0..<base.count).shuffled()
    }

    return base[indexes.removeFirst()]
  }
}

struct RepeatingRandomQueue<T>: Sequence {
  private let base: [T]

  init(_ base: [T]) {
    self.base  = base
  }

  func makeIterator() -> RepeatingRandomIterator<T> {
    .init(base: base)
  }
}
```
### 使い方

```swift

let array =  [0, 1, 2, 3, 4, 5]
let randomQueue = RepeatingRandomQueue(array)

// 終了条件をきちんと決めましょう
// さもなくば永遠に繰り返します
zip(1...100, randomQueue)
 .forEach { print($0.1) }
```


##おまけ
あまりここに書いても意味ないけど、永遠に繰り返さないバージョン

### 永遠じゃない
```swift
struct RandomIterator<T>: IteratorProtocol {
  private let base: [T]
  private var indexes: [Int] = []

  init(base: [T]) {
    self.base  = base
    self.indexes = (0..<base.count).shuffled()
  }

  mutating func next() -> T? {

    guard !indexes.isEmpty else { return nil }

    return base[indexes.removeFirst()]
  }
}

struct RandomQueue<T>: Sequence {
  private let base: [T]

  init(_ base: [T]) {
    self.base  = base
  }

  func makeIterator() -> RandomIterator<T> {
    .init(base: base)
  }
}
```


###使い方
```swift

print(
    Array(
        RandomQueue("これはつまならいでしょ".map { $0 })
            .map(String.init)
    )
    .joined()
)
```
51歳（現52）からのプログラミング　備忘　Path と File

忘れていたので確認しました。
java7以降のファイル操作は
1. java.nio.file.Pathsクラスのメソッドで、操作するファイルやディレクトリを指定し
2. java.nio.file.Filesクラスのメソッドで、ファイルやディレクトリを操作する

```java
  Path    p1 = Paths.get ("sample.dat"); // Pathsメソッド
  Boolean b  = Files.isDirectory(p1);    // Filesメソッド
  System.out.println(b);
```
<br>
[ Files.newBufferedReader(path) ]は、これでいいのかな？

```java
  Path p1 = Paths.get("sample.dat");
  BufferedReader br = Files.newBufferedReader(p1);
  String l;
  while( (l=br.readLine()) != null){ System.out.println(l); }
```
Flutter WebでWebカメラを使う

パソコンとWebカメラを使ったちょっとしたツールのアイディアが思い浮かびました。しかし普段Androidアプリを作っていて、WindowsネイティブやJavaScript + CSSを思い出すのが大変だと思ったので、Flutter WebでWebカメラを使うことにしました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/b279209a-305d-bf8f-2a53-64157748137c.png" width="480px">


# 前準備

[公式のこちらの記事](https://flutter.dev/docs/get-started/web)を参考に環境構築とプロジェクト作成を行いました。

# Flutterの世界の中にWebの世界を作る

今回はブラウザで動くJavaScriptのプログラミングをDartで行い、Webカメラへの接続(getUserMedia)とプレビュー表示(videoタグ)を行います。そのためにFlutterの世界の中にWebの世界を作ります。

まず、Webの世界を作りたい箇所に`HtmlElementView` を貼ります。`viewType` パラメータで名前を設定します。

```main.dart
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: HtmlElementView(viewType: 'videoView'),
    );
  }
}
```

# Webプログラミングを行う

こちらの2つのライブラリをインポートします。

```main.dart
import 'dart:ui' as ui;
import 'dart:html';
```

下記のように `HtmlElementView` の内容をWebプログラミングします。 `ui.platformViewRegistry.registerViewFactory` メソッドの第１引数は `HtmlElementView` を貼ったときに設定した名前と同じにします。そして第２引数で渡すブロックがWebの世界になります。ブラウザで動くJavaScriptをDartで書けます。

```main.dart
ui.platformViewRegistry.registerViewFactory('videoView', (int viewId) {
  // このブロックはWebの世界
  // videoタグを作る
  final video = VideoElement();
  // ソースが設定されたら自動再生
  video.autoplay = true;
  // Webカメラへの接続を要求する
  window.navigator.getUserMedia(video: true).then((stream) {
    // Webカメラへの接続が成功
    video.srcObject = stream;
  });
  // HtmlElementViewの内容を返却する
  return video;
});
```

# 全体ソースコード

[GitHubリポジトリに全体ソースコードがあります。](https://github.com/tfandkusu/try_user_media_flutter_web/blob/master/lib/main.dart)
Webカメラが無かったり許可されていなかったりしたときのエラー処理も実装しています。


# 注意点

## Android Studioのエラー表示

`dart:ui` ライブラリの `platformViewRegistry` 変数へのアクセスはAndroid Studioではエラーを表す赤い下線が表示されました。しかし、コマンドラインではビルドできます。

![スクリーンショット 2020-08-13 20.33.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/e2388d33-a023-dd57-95d9-7f3ae375ad3f.png)

## 公式のgetUserMediaメソッドの解説について

[公式のgetUserMediaメソッドの解説](https://api.flutter.dev/flutter/dart-html/Navigator/getUserMedia.html)では取得したMediaStreamクラスのオブジェクトに対してこのような使い方を案内しています。

```dart
video.src = Url.createObjectUrlFromStream(stream);
```

しかしこのやりかたは実行時エラーになりました。

```
html_dart2js.dart:30757 Uncaught (in promise) TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.
```
VueCLIのインストールから開発用サーバの起動まで

vue.js はJavaScriptのフレームワークの一つで、シングルページアプリケーションの作成などのため導入される。
VueCLIはvue.jsで開発をするためのツールである。
大規模な開発になるとこのようなツールがあったほうがいいようです。

# Node.jsをインストール
JavaScript環境であるNode.jsを[公式ページより](https://nodejs.org/ja/)インストールする。
Node.jsのパッケージ管理ツールであるnpmが使用できるようになる。

#VueCLI インストール
ここからはターミナルから操作する。（今回はbashを使用。）
先ほど使えるようになったnpmコマンドにより、VueCLIを導入する。

```
$ npm install -g @vue/cli 
```
`-g`はグローバルインストールとするための宣言で、インストールしたパッケージをどのディレクトリからでも実行できる（パスを通す）ことができる。
これを付けずにローカルインストールした場合、カレントディレクトリにパッケージが置かれ、実行時にパスの指定が必要になる。
実行環境でパスが通されてない場合を考えるとローカルインストールにした方がいいという考えも多々あるので状況次第で選ぶ。

#vueプロジェクトを作成
インストールが完了したらvueコマンドが使用可能になる。
プロジェクトを作成する下記コマンドを実行。

```
$ vue create {プロジェクト名}
```

設定のオプションが表示されるので必要なものを選択してenterを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547333/1a5eba13-5ad5-2acf-05a2-8a68ab57f7f7.png)

このほかに中国国内で使用できるようにtaobaoとの接続を有効にするオプションも表示されることがあるようだ。

# 開発用サーバの起動
開発を始められる。
開発中のページを確認するために、下記コマンドで開発用サーバを起動する。

```
$ npm run serve
```

localhost:8080からページを確認することができるのでブラウザからアクセスしよう。
プロジェクトのソースに変更があると、このページにも逐次反映される。
【Flutter】安心してレポジトリを公開するために必要なgitignoreの設定

# この記事を読んで習得できること
Flutterのフォルダを安心してgithub or gitlabに載せられるようになる

# 結論
`.gitignore`に
`!*.gitignore`を追加する

これより下は時間がある人だけでいいですよん

# 安心して,とは…？
Flutter関係の記事を載せようと思っていて、その際にソースコードも公開したいなーと思っていた。

全世界に公開するのなら、自分のPC内の情報は載せたくないなー（当然）と思っていたので、フォルダ内に自分の情報が載っていないか、調べてみた。

調べたっていっても、そんなたいそうなことはしてなくて、
フォルダ内のソースを、以下の文章で検索してみるってだけ。
`/Users/<自分で付けたPCのユーザー名>/`

すると、結構な分量が出てきてしまった。

![スクリーンショット 2020-08-13 19.52.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389553/e498988b-b9dd-d61a-510b-26da20cd58bb.png)

記載があったのは、以下の４ファイル。
`.package`,
`ios/Flutter/Generated.xcconfig`,
`ios/Flutter/flutter_export_environment.sh`
`android/local.proparties`,

こうなると、安心して公開出来ないぞ…

# これらのファイルはgit ignoreされていた
どうしよう、毎回これらのファイルを消さないといけない…と思っていたのだが、
どうやらこれらのファイルは差分が出ていない。

それもそのはず、
`.gitignore`、
`ios/.gitignore`、
`android/.gitignore`、

この３ファイルのgitignoreに、先ほど示した4ファイルも含まれていた。

なので、安心してgithubに公開することが出来ました！

# 問題解決！とはいかなかった…
これで晴れて解決！と思って、試しにgithubに公開して、そのレポジトリからcloneしてみた。
すると、、、
なんと、先ほどの4ファイルが、差分対象になっているではないか！！！

個人で開発するには、問題内が、もし、チーム開発するんだったら、いちいちこれらのファイルを除外してpushしないといけない。

初めはignoreされていたのに、なぜだろう…？

# 原因: .gitignoreがignoreされていたから
当然ちゃ当然ですが、差分対象になっている原因は、`.gitignore`ファイルも差分対象外になっていたからだった。

# .gitignoreもレポジトリに入れてあげればいい
なので、レポジトリ内に`.gitignore`ファイルを入れてあげさえすればいいんだなと考え、
結論に書いたような

`.gitignore`に
`!*.gitignore`を追加する

を行ったというわけ。

# 無事公開されたレポジトリを見てください

いろいろあったが、これで無事公開されました。
これからも、勉強したことをこのレポジトリに載せていこうと思います。

https://github.com/taichi6930/flutterstudyapp