OmniAICreator/Qiita-1.07M huggingface dataset:
Geolocation APIを使って位置情報を取得する

位置情報を取得する際に使用した構文や引数について、次回以降スムーズに取得できるようまとめておきます。
「**Geolocation API**」にアクセスするには、「**navigator.geolocation**」オブジェクトを使用します。


##メソッド①：**Geolocation.getCurrentPosition()** <br> <端末の現在の位置を受け取る>


###構文
```Javascript
navigator.geolocation.getCurrentPosition(success[, error[, [options]])
```
|引数|詳細|
|:---|:---|
|success|コールバック関数。 GeolocationPosition オブジェクトを唯一の入力引数として受け取る|
|error|任意のコールバック関数。GeolocationPositionError オブジェクトを唯一の入力引数として受け取る（省略可）|
|option|任意の PositionOptions オブジェクト。（省略可）|
|maximumAge<br>（optionの例）|整数 (ミリ秒)キャッシュされた位置の最大寿命。（キャッシュの有効期限。）|
|timeout<br>（optionの例）|整数 (ミリ秒)。エラーコールバックが呼び出されるまでの時間。（タイムアウトまでの時間）|
|enableHighAccuracy<br>（optionの例）|falseまたはtrue。高精度の取得を行うかどうかを示すフラグ|



##メソッド②：**watchPosition()**　<位置を定期的に取得する>


###構文
```Javascript
navigator.geolocation.watchPosition(success[, error[, options]])
```
|引数|詳細|
|:---|:---|
|success|コールバック関数。GeolocationPosition オブジェクトを入力引数として受け取る|
|error|任意のコールバック関数。 GeolocationPositionError オブジェクトを入力引数として受け取る（省略可）|
|option|任意の PositionOptions オブジェクト。位置を監視する構成オプションを提供（省略可）|



##位置情報

|値|内容|
|:---|:---|
|coords.latitude|緯度|
|coords.longitude|経度|
|coords.altitude|高度|
|coords.accuracy|正確性（値が小さいほど正確）|
|coords.altitudeAccuracy|高度の正確性|
|coords.heading|方位|
|coords.speed|速度|
	
##参考サイト

https://developer.mozilla.org/ja/docs/Web/API/Geolocation_API

https://blog.codecamp.jp/javascript-geolocation
RailsでScrollTriggerを導入する【メモ】

# ScrollTriggerとは
2020年5月にGSAP（GreenSock Animation Platform）から生まれたスクロールアニメのためのライブラリです。とても少ないコードで実装でき、簡単にアニメーションが出来上がります。[ドキュメント](https://greensock.com/docs/v3/Plugins/ScrollTrigger)に動画付きで方法が乗っているので見てみてください。
今回はそんなライブラリを導入する方法を自分のためのメモとして残しておきます。
また、どなたかのお役に立てたら、嬉しいです。

# YouTube
<iframe width="560" height="315" src="https://www.youtube.com/embed/X7IBa7vZjmo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 導入方法
1,GSAPのモジュールをインストールします

```terminal
% yarn add gsap
```
2,gsap、ScrollTriggerをそれぞれimportします
※Nuxt.jsの場合は別の記述が必要なので、ドキュメントを参照してください

```application.js
require("greensocks")
import { gsap } from "gsap";
import { ScrollTrigger } from 'gsap/ScrollTrigger'
```
# 参照
[ドキュメント](https://greensock.com/docs/v3/Plugins/ScrollTrigger)
[【2021年最新】GSAPの「ScrollTrigger」を使って爆速でスクロールアニメを実装する](https://www.to-r.net/media/scrolltrigger/)
flutter設定備忘録

flutterで直面したエラーの備忘録を記しておく

```
Flutter 2.2.1 
firebase_core: "^0.7.0"
cloud_firestore: "^0.16.0+1"
```

**Firebaseの初期化エラー**

```
core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
```

以下のようにInitializeする｡この時Saveだけでなくアプリを再起動させることが重要｡ここでハマった｡

```
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  FirebaseFirestore firestore = FirebaseFirestore.instance;

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    CollectionReference collectionReference = firestore.collection('users');
    return MaterialApp(
　　　　　　　　　　･････
)
```

***iosのバージョンエラー***

```
Error output from CocoaPods:
↳
[!] Automatically assigning platform `iOS` with version `9.0` on target `Runner` because no platform was
specified. Please specify a platform for this target in your Podfile. See
`https://guides.cocoapods.org/syntax/podfile.html#platform`.

Error running pod install
```
`ios`>`Podfile`を開いて以下のように編集｡この時 `Podfile.lock`があったら消しておく｡

```
# Uncomment this line to define a global platform for your project
platform :ios, '14.5'
```

***flutter run時のエラー***

```
Error: Cannot run with sound null safety, because the following dependencies
don't support null safety:
- package:･････
- package:･････
- package:･････

For solutions, see https://dart.dev/go/unsound-null-safety
```

これがAndroid Stadioで発生している場合は､
`Run` > `Edit Configuration`を選択して
`Additional run args:`の項目に　`--no-sound-null-safety`を設定する｡

上記のエラーが出るときはpluginで　`Legacy`を使用している場合に発生する｡これはflutterの最新がnullを受け付けなくなっているので　`Null Safty`の方を使用する｡

![スクリーンショット 2021-06-12 22.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79473/fab5185d-8793-e89b-c189-fac8f455f734.png)

***　コンパイルエラー***

```
1/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.javaは推奨されないAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
```
特に気にする必要はないが煩わしい際は以下を編集
`android`>`app`>`build.gradle`

```
minSdkVersion 23  (←ここを23にする)
targetSdkVersion 30

```
2Dアクションゲームを作りながらUnity学習　#2~3日目

# 環境
* MacBookAir(M1,2020)
* UnityHub 2.4.3
* Unity バージョン2020.3.10f1

# 学習内容
* 敵キャラの設置
* 敵キャラに関する挙動
  * 移動
  * 倒した際の挙動
  * 折り返し
* 敵キャラにプレイヤーキャラがぶつかった際の挙動
* 敵キャラをプレイヤーキャラが踏んだ際のキャラ挙動

# 苦労した点
* 敵キャラを倒した際にステージの裏側に隠れないようにする設定
* 敵キャラにプレイヤーキャラがぶつかったのか踏んだのかの判別

# 感想
敵キャラに上手くバリエーションを持たせてユーザーが飽きないゲームを作成していきたいです。
https.requestでPromiseを使う

[https.request](https://nodejs.org/api/https.html#https_https_request_url_options_callback) が [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest) を返すので、続けて https.on や [https.end](https://nodejs.org/api/http.html#http_request_end_data_encoding_callback) が利用可能。

## 環境

```sh
$ node -v
v16.2.0
$ yarn info jsdom version
16.6.0
$ yarn info https version
1.0.0
$ yarn info  typescript version
4.3.2
```

## コード

```js
import * as https from "https";

const request = (options) => {
  return new Promise((resolve, reject) => {
    https
      .request(options, (res) => {
        const data = [];
        res.on("data", (d) => data.push(d));
        res.on("end", () => resolve(data.join("")));
      })
      .on("error", reject)
      .end();
  });
};
```
TypeScript ver.

```ts
import * as https from "https";

const request = (options: string | URL | https.RequestOptions) => {
  return new Promise<string>((resolve, reject) => {
    https
      .request(options, (res) => {
        const data = [];
        res.on("data", (d) => data.push(d));
        res.on("end", () => resolve(data.join("")));
      })
      .on("error", reject)
      .end();
  });
};
```

そのまま [jsdom](https://github.com/jsdom/jsdom) に渡せる。

```ts
import { JSDOM } from "jsdom";

request("https://www.google.com/")
  .then((data) => {
    const dom = new JSDOM(data);
    // Google
    console.log(dom.window.document.title);
  });
```

## 参考

- [HTTPS | Node.js v16.3.0 Documentation](https://nodejs.org/api/https.html)
- [node.js - nodejs - How to promisify http.request? reject got called two times - Stack Overflow](https://stackoverflow.com/questions/38533580/nodejs-how-to-promisify-http-request-reject-got-called-two-times)
- [jsdom/jsdom: A JavaScript implementation of various web standards, for use with Node.js](https://github.com/jsdom/jsdom)
Firebase Authenticationトラブルシューティング


## VSCodeのDebugger for Chromeでデバッグする際にAuth認証を実行しようとするとエラーが出る

### エラー内容
`This browser or app may not be secure. Try using a different browser. If you’re already using a supported browser, you can refresh your screen and try again to sign in.`

### 解決方法
`launch.json`に`"userDataDir": false`(新しいプロファイルを使用しない)を追加し、起動中のChromeを全て終了してから、デバッグを再開する。

~~~json:launch.json
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "Launch Chrome against localhost",
            "url": "http://localhost:3000",
            "webRoot": "${workspaceFolder}",
            "userDataDir": false
        }
    ]
~~~

### 参考

https://stackoverflow.com/questions/51725854/run-vscode-chrome-debugger-with-its-extensions
JDLA E資格取得（ラビット★チャレンジ）

#はじめに
2021年8月に実施される日本ディープラーニング協会(JDLA) E資格の受験を目標に「JDLA認定プログラム」のひとつであるStudy-AIの「ラビット★チャレンジ」を受講しており、そこで学習した内容についてまとめていきます。

[日本ディープラーニング協会(JDLA)](https://www.jdla.org/)
[ラビット★チャレンジ](http://ai999.careers/rabbit/)

#E資格を受験するために必要なこと
E資格を受験するには、JDLAが認定したディープラーニングに関するプログラム(講座)を受講し修了する必要があります。
[JDLA認定プログラム](https://www.jdla.org/certificate/engineer/#certificate_No04)

#なぜラビット★チャレンジなのか
簡潔に言うと「安いから」です。
と言うのも、少し前までは、認定プログラムを受講するのに数十万かかりましたが、最近になって低価格の講座も出てきてます。そのひとつが「ラビット★チャレンジ」です。（そろそろ★を打つのがめんどくさくなってきた。）

ただし、安いのには理由があります。
基本的に講座は全てビデオ視聴のみで、講師への質問等は一切できません。
そのため、ある程度前提の知識があったり、わからないことを自分で調べることに慣れている人にはおすすめできますが、そうじゃない人にはあまりおすすめできません。

また、ラビット・チャレンジ以外にもスキルアップAIから同様のプログラムが提供されています。
[スキルアップAI](https://www.skillupai.com/deep-learning/)

#勉強を進めるにあたって注意すること
ちゃんと調べてなかったからなのかわかりませんが、申し込み後に受講できる期間に制限があることを知りました。（月額制だから特にないと思ってた）
基本的には、次回のE資格を受験するのを目標に勉強するため、短期集中型のプログラムとなってます。
受講しようと思ってる方は、勉強に十分な時間が充てられるか、今一度確認した方が良いと思います。

#ブログを書く理由について
修了にはレポートを提出する必要があるのが一番の理由です。
あとは、備忘録と復習のため。
普通に書いても面白くないので、できるだけ噛み砕いて書くように努力します。

ただ、ここだけの話、だいぶ進んだ時点でレポートが必要なことに気づいて焦ってます。。

#私の経歴について
高専卒。今は、車載関係で音のチューニングに関わる仕事をメインにしてます。
AIやディープラーニングについては、音声認識の性能評価で少し触れたことがある程度。
そこから「これからの自分の生きる道はこっちじゃないか？」と思い始めて（間違ってるかもしれないけど）いくつか研修を受けてきました。
そのため、全くの無知ではないですが、コードをゴリゴリ書くような仕事でもないのでほとんど素人同然です。

#まとめ
見切り発車で始めた感は否めませんが、なんとかE資格が取れるように頑張っていきます。
【Swift】タップした時に追従してくるViewを作成する

#はじめに
このような感じで、タップした位置に追従してくるようなViewを作成したいと思います。
![ezgif.com-gif-maker (6).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/a20ef30f-d110-a484-2d26-10e8e0527835.gif)

#実装

コピペで作成できます。

```swift
final class ViewController: UIViewController {
    
    private var myView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        myView = UIView()
        myView.frame.size = CGSize(width: 100, height: 100)
        myView.center = self.view.center
        myView.backgroundColor = .red
        myView.isUserInteractionEnabled = true
        self.view.addSubview(myView)
        
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if touches.first!.view == self.view {
            let after = touches.first!.location(in: self.view)
            let before = myView.center
            let deltaX = after.x - before.x
            let deltaY = after.y - before.y
            UIView.animate(withDuration: 0.3) {
                self.myView.transform = CGAffineTransform(translationX: deltaX, y: deltaY)
            }
        }
    }
    
}
```

#解説

`touchesBegan`はタップした時に呼ばれるメソッドです。([touchesBegan](https://developer.apple.com/documentation/uikit/uiresponder/1621142-touchesbegan))

一番はじめにタップした箇所の座標を取得します。これがViewの目的地の座標というわけです。

```swift
let after = touches.first!.location(in: self.view)
```

移動前のViewの座標も取得する必要があります。

```swift
let before = myView.center
```

xとyの変化量をそれぞれ求めます。(変化量というのは、どれぐらい値が増減したかを表すものです)
例えば、移動前の座標(10, 300)から移動後の座標(30, 200)に移動した場合のxとyの変化量Δx, Δyは
Δx = 30 - 10 = 20
Δy = 200 - 300 = -100
よって、変化量は(20, -100)となるわけです。

```swift
let deltaX = after.x - before.x
let deltaY = after.y - before.y
```

そして、求めた変化量がViewが移動するべき移動量になるので、CGAffineTransformでアニメーション付きで移動させてあげます。（[CGAffineTransform](https://developer.apple.com/documentation/coregraphics/cgaffinetransform)）

```swift
UIView.animate(withDuration: 0.3) {
    self.myView.transform = CGAffineTransform(translationX: deltaX, y: deltaY)
}
```

#おわりに
おわりです。
AWS KMS describe-key --key-id にはエイリアスを指定できる

今までキーIDしか指定できないと思っていた。

```
aws kms describe-key --key-id 1234abcd-12ab-34cd-56ef-1234567890ab
```

>   describe-key
--key-id <value>
[--grant-tokens <value>]
[--cli-input-json <value>]
[--generate-cli-skeleton <value>]

しっかりドキュメントに書いてあった。

> For example:
Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
Alias name: alias/ExampleAlias
Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias

`--key-id` にエイリアスを指定。

```
aws kms describe-key --key-id alias/mykey
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/cfb512cf-6ee2-b695-bbf0-8cdf9f8adee7.png)

# 参考記事

https://docs.aws.amazon.com/cli/latest/reference/kms/describe-key.html
Python仮想環境の構築方法

# 概要
この記事では、Pythonの仮想環境を構築する方法を簡潔にメモします。
構築後の仮想環境への入り方、抜け方、不要になった仮想環境の削除の方法も含みます。

# 前提条件
Visual Studio Code:1.56.2
ターミナルはWindows PowerShellを使用

# 方法
それでは、具体的な方法の説明に入ります。
途中でつまづかないように、できるだけ細かくステップ分けしています。

## ①任意のディレクトリを選択
ターミナルを開き、仮想環境を構築したいディレクトリまで移動しておきます。
例：`Documents`の直下に仮想環境ディレクトリを置くこととします。

## ②仮想環境を構築
ターミナルで下記のコマンドを入力して、仮想環境を構築します。
例：仮想環境名は`venv_sample`とします。

```terminal
PS C:Documents> python -m venv venv_sample
```

コマンドが正しく動作していれば、下記のとおり選択したディレクトリの直下に仮想環境ディレクトリが作成されています。
例：`C:Documents>venv_sample`

<br>

なお、作成された仮想環境ディレクトリは、次のような構成になっています。

```
Documents>
　venv_sample>
　　Include>
　　　（空のディレクトリ）
　　Lib>
　　　site-packages>
　　　　（以下略）
　　Scripts>
　　　（以下略）
```


## ③仮想環境に入る
### ③-1　Scriptsディレクトリに移動
ターミナルで下記のコマンドを入力して、Scriptsディレクトリに移動します。

```terminal
PS C:Documents> cd ./venv_sample/Scripts
```

<br>

コマンドが正しく動作していれば、ターミナルが下記の表示になります。

```terminal
PS C:Documents\venv_sample\Scripts>
```

<br>

### ③-2　仮想環境を有効化
ターミナルで下記のコマンドを入力して、仮想環境を有効化します。

```terminal
PS C:Documents\venv_sample\Scripts> .Activate.ps1 
```

<br>

仮想環境が有効化されれば、ターミナルが下記の表示になります。

```terminal
(venv_sample) PS C:Documents\venv_sample\Scripts> 
```

## ④仮想環境から抜ける

ターミナルで下記のコマンドを入力して、仮想環境から抜けます。

```terminal
(venv_sample) PS C:Documents\venv_sample\Scripts> deactivate
```

<br>

仮想環境から抜けられれば、ターミナルが下記の表示になります。

```terminal
PS C:Documents\venv_sample\Scripts>
```

## ⑤仮想環境を削除
仮想環境を削除するには、作成した仮想環境ディレクトリ`C:Documents>venv_sample`を削除します。

# まとめ
この記事では、Pythonの仮想環境の構築の仕方を簡潔にまとめました。
素人のメモですので、誤りや不足の点があるかもしれませんがご容赦ください。
Windows Terminalで、エクスプローラーで開いているディレクトリを任意のシェルで開く

# TL;DR

開きたいファイルエクスプローラーのアドレスバーに

```txt
wt -d . -p "Command Prompt"
```

と打てばOK。`Command Prompt`は適宜開きたいシェルの名前に置き換えてください。

# はじめに

Windows Terminalは様々なシェルを使えて便利です。
ファイルエクスプローラーで開いたところをカレントディレクトリで開こうと思ったとき、コンテクストメニューで『Open in Windows Terminal』とか選ぶと思いますが、これではデフォルトで設定したプロファイルしか選べません。地味に不便。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091433/5cc3fbf2-8929-1f90-5c7a-67d480324d12.png)

ということで、今開いているディレクトリをカレントにして、デフォルト以外のプロファイルで開く方法を探してみました。

# 方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091433/d3997bf7-0962-c30c-08a9-4c96724a2a32.png)

開きたいディレクトリ上のアドレスバーを右クリック、または`Alt + D`でアドレスバーをアクティブにします。したら、

```txt
wt -d . -p "Command Prompt"
```

と打ちます。`Command Prompt`のところには、開きたいプロファイルの「Name」の部分に置き換えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091433/aeaeda8a-02d6-e629-1364-a66191d3b3e1.png)

## 簡単な説明

`wt`コマンドは引数を持てるので、ディレクトリ指定の`-d`引数でカレントディレクトリを、プロファイル指定の`-p`引数で開くシェルを指定しました。
他にもバッチファイルなどで使える引数が色々あるので、[こちら](https://docs.microsoft.com/en-us/windows/terminal/command-line-arguments?tabs=windows)のドキュメントとかを参考にしてみてください。

# おわりに

コマンドが長い！
コマンドプロンプトなら`cmd`だけで開けるんですけどねえ。せめて、ディレクトリ指定の`-d .`がなければ……。まあWindows Terminal開いて、使いたいシェルを開いて、`cd`して――とかが要らない分いいんですけどね。

```jsonc:Settings.json
{
    "name": "cmd",
    "tabTitle": "Command Prompt",
    "commandline": "cmd.exe",
    "hidden": false
}
```

こんな感じで`name`を短くしてタイプ数を短くして足掻いてみたり。
もっといいやり方があるとかあるんですかね。

ではでは、今回はこのへんで。
職業訓練校　Webプログラマ養成科

<h1>職業訓練校に通い始めました</h1>
前職を辞めてからしばらくはJavaScript,PHPを中心に勉強していましたがオブジェクト指向の餌食になってしまい、エラーのオンパレード。:skull:そこで海外留学やプログラミング教室など誰かに教えて貰おうと思ったのですが高額すぎて諦めました。そんな中とある日何気無くYoutubeで2chの元管理人のひろゆきさんのライブ配信（本人曰く録画放送）の中で<b>お金を貰いながら勉強できる公的サービス</b>があると聞いて調べてみた所、職業訓練と言う働く気がある者なら誰でも受ける資格があり場合によれば職業訓練手当と言う在学中月10万円ほどもらえる仕組みがある事を知りました。※詳しくは各地方自治体のハローワークのホームページをご参照ください
Seleniumを使ってe-typingを自動化した  ②実装編

##はじめに
前回の記事でselenium準備編を書いたので、ブラウザを動かすコードを書いていきます！

##実装

以下実装したコードになります。

```javascript:e-typing.js
const {Builder, By, Key, until} = require('selenium-webdriver');
const tesseract = require('tesseract.js');
let fs = require('fs');

async function example() {
    // Chrome / Chromiumセッションをインスタンス化
    let driver = await new Builder().forBrowser('chrome').build();

    // e-typingのWebサイトを開く
    await driver.get('https://www.e-typing.ne.jp/roma/check/');

    // e-typingサイトの「今すぐチェック」というボタン要素をidから取得してclickする
    await driver.findElement(By.id('level_check_btn')).click();
    // 表示に時間がかかる為、5秒スリープさせる
    await driver.sleep(5000);

    //iframeが表示される為、iframeの要素をidから取得
    const iframe = await driver.findElement(By.id('typing_content'));
    //取得したiframeの要素をへ移動する (これがないとiframe内の要素にアクセスできない)
    await driver.switchTo().frame(iframe);

    // 「スタート」ボタン要素をidから取得して、クリック
    await driver.findElement(By.css('#start_btn')).click();
    // 表示に時間がかかる為、3秒間スリープさせる
    await driver.sleep(3000);

    // スペースキーをクリックするとゲームが開始される為、スペースキーをクリック
    await driver.actions().keyDown(Key.SPACE).perform();
     // 表示に時間がかかる為、3秒間スリープさせる
    await driver.sleep(3000);

    while (true) {
        try {
            // 画面に表示されている英字を取得する
            const sentenceText = await driver.findElement(By.id('sentenceText')).getText();
            // 取得した文字を一文字づつループさせる
            for (i = 0; i < sentenceText.length; i++) {
                word = sentenceText[i].toLowerCase();
                // 取得した文字のキーを押す
                await driver.actions().keyDown(word).perform();
                // キーを打つ速度を遅くする処理 (無くても動く)
                await driver.sleep(50);
            }
        } catch (error) {
            // 「sentenceText」というidを持った要素が取得できない場合エラーが発生して、処理終了
            console.log(error);
            return;
        }
    }
};

example();

```

nodeで動きます！

```bash
$ node e-typing.js
```

##まとめ
コードを書いて自動化するのは、すごく好奇心をくすぐられる。もっと色々と自動化できるもの探して行くつもりです！
実務の中でテストに利用して、テストの時間を短縮できたらめちゃ便利だなと思いました:smiley:
※動画を載せれたら載せます。
MongoDB クエリ覚書

しょっちゅう忘れるので自分用のメモとして。

・環境
MongoDB：4.2.8

※クライアントは「Robo 3T 1.3」を使用

・ソート

```
db.getCollection('collectionName').find({}).sort({'sortkey':1}) #昇順
db.getCollection('collectionName').find({}).sort({'sortkey':-1}) #降順
```
ボリュームの中身が更新されているか確認する(初心者向け)

#はじめに
Dockerにてマウントする方法にバインドマウントとボリュームマウントがあるかと思います。
バインドマウントはマスター環境で作成したディレクトリにデータを直接放り込む事でコンテナに直接反映されますが、ボリュームマウントはDockerEngine上にボリュームをマウントするのでボリュームの中身を確認しづらいかと思います。
力技？でボリュームマウントで作成したボリュームの中身を確認する方法を試してみたのですが、忘れてしまいそうなので備忘録として残しておきます。
これを書いている現在、Dockerを学び始めて1ヵ月程度＆エンジニアですらないので、「そんなのなんちゃってな確認方法だ」「ただの２重チェックに過ぎない」と思われるかもですが、温かくご指摘頂けると嬉しいです。
私自身インフラ的知識もプログラミングスキルも初心者ですので、初心者にも解りやすい内容になっていればい良いなと思います。

#環境
・Windows10 Home(64bit)
・DockerDesktop for Windows(WSL2)

#図解
ボリュームをマウントしたapacheコンテナを起動し、そこにhtmlファイルを作成するという体で進めていきます。
ボリュームマウントでマウントされたボリュームの中身を確認するために確認用のLinuxコンテナ別途起動し、ボリュームに接続して確認をしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1617152/2b448a06-6d9f-a833-9214-9c32616ccaf2.png)



#①ボリュームを作成
```
$ docker volume create hoge_volume
```

#②ボリュームがマウントされたApacheコンテナを起動する
``` 
$ docker run --name hoge_apache -d -p 8080:80 -v hoge_volume:/usr/local/apache2/htdocs httpd
```
公式で用意されているApacheイメージを使用します。
これでボリュームがマウントされたApacheコンテナが立ち上がりました。
ちゃんと起動できているか確認してみます。
ブラウザに`http://localhost:8080/`と入力。ちゃんと起動できている事が確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1617152/d584237a-6f28-a2e4-f8db-1dce614a641f.png)



#③同じボリュームがマウントされたlinux(ubuntu)コンテナを起動する
```
$ docker run --name hoge_ubuntu -dit -v hoge_volume:/home ubuntu
```
apacheコンテナと同じボリュームにマウントされたlinuxコンテナが立ち上がりました。

#④ボリューム内のhtmlファイルを更新してみる
```
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>更新したよ</h1>
  </body>
</html>
```

ボリューム内のhtmlファイルを上記に変更します。
今回はマスター(windows)のドキュメント下に「hoge_directory」フォルダを作成し、更新用htmlファイルを作成しました。
これをcpコマンドでボリュームに移します。

```
$ docker cp C:\Users\[ユーザー名]\Documents\hoge_directory\index.html hoge_apache:/usr/local/apache2/htdocs/
```

#⑤ボリューム内がちゃんと更新されているか確認してみる
cpコマンドで更新したので、Apacheコンテナのhtdocs下を調べるともちろん更新されていますが、ちゃんとボリューム内が更新されているのかLinuxコンテナから確認してみます。
Linuxコンテナでは`/home`ディレクトリにボリュームをマウントしているので、ここがちゃんと更新されていたら正常にボリューム内が更新されたという事になりますよね。

```
$ docker exec -it hoge_ubuntu /bin/sh
```
上記コマンドでLinuxコンテナ内に入ります。
`/home`ディレクトリを確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1617152/ac083b4f-7326-59f6-61d7-aac43e8409f1.png)
ちゃんと更新されてました！

root権限で確認したり、ボリューム内を確認する専用のイメージを使う方法等やり方は沢山あるみたいですが、自分の様な初心者ならこの方法のほうが理解しながら進められるような気がしました。
GitLabでSentryをの設定をする(+nuxtjs)

GitLabの運用のところにエラートラッキングがあり、[Sentry](https://sentry.io/)というサービスを統合できるオプションが有りますが無視していました。ふと使ってみたところ、設定方法が少しわかりにくかったのでメモしておきます。

# Sentryのアカウント作成

https://sentry.io/

# 認証トークンの取得

左上のをクリックするとプロジェクトとユーザーのプルダウンが表示されます。そこで、ユーザー項目のAPI Keysを選択するとAUTH TOKENの画面がでてきます。

このAUTH_TOKENをコピペしておきます。

# GitLab側の設定

プロジェクトの「設定」→「運用」→「エラートラッキング」を開きます。

Sentry API URL: https://sentry.io/
認証トークン: SentryのAUTH_TOKEN

トークンの右側の「接続」をクリックするとそのユーザーのアクセスできるプロジェクトがドロップダウンで選択できるようになります。

そこでエラートラッキングを表示したいプロジェクトを選択します。


# Sentryをnuxtjsのプロジェクトに追加する

```
yarn add @nuxtjs/sentry
```

モジュールの追加とプロジェクトのdnsの設定を行います。

```javascript:nuxt.config.js
{
  modules: [
    '@nuxtjs/sentry'
  ],
  sentry: {
    dsn: 'https://~~~@~~~.ingest.sentry.io/~~~~',
    config: {},
  }
}
```

## 使用方法

moduleで普通のnuxtのerrorは出るようですが、this.$sentry.captureException()でも独自にErrorを飛ばせるようです。例ではaxiosのerrorをcatchして飛ばしています。

https://sentry.nuxtjs.org/guide/usage
D言語　UFCS表記のcomplexの初期化

#D言語　虚数、複素数型が非推奨　dmd 2.097.0 より
##std.complex　ライブラリを利用する

ライブラリへの変更で使用できなくなるのが、虚数、複素数リテラル

```d:type_i.d
ifloat im = 0.123i;
cfloat c = 1.23 + 4.56i;
```
これを何とかする。
何とかしました。[https://github.com/deepprog/im4ufcs](https://github.com/deepprog/im4ufcs)
関数i で　complexを初期化します。

```d:test_i.d
import std.complex;
import im4ufcs;

//虚数は複素数の実数をゼロとして初期化
auto im = 1.2345.i;
assert(im == complex(0.0, 1.2345));

//＋は通常の演算子　  
auto c = 1.23 + 4.56.i;
assert(c == complex(1.23, 4.56));

auto x = 0.123;
auto y = 0.456;
//もちろん変数でも可
auto z = x - y.i;
assert(z == complex(0.123, -0.456));

```

```d:im4ufcs.d
module im4ufcs;
import std.complex;

auto i(T)(T im) @safe pure nothrow @nogc
{
    return complex(0.0, im);
}
```

虚数リテラルをufcs関数で模倣してます。
複素数はcomplexライブラリでうまいことなっています。


同じことを誰かに発見される前に記事にしておきます。
RubyでRubyで配列を標準入力に使う方法

Rubyで配列を標準入力に使う方法です。
競技プログラムをされる方向けに説明いたします。
今回はpaiza様のRuby問題集を題材にしています。

・文字列を文字列配列に標準入力して、数値に変換して、再度文字列で標準出力する場合

```Ruby
#文字列を入力してline配列に入れる
line = gets.chomp.split(":")
#line配列から要素を取り出して数値型に変換する。
hour = line[0].to_i
minute = line[1].to_i
#文字列型に変換して標準出力する。
puts hour.to_s 
puts minute.to_s
```

・mapを使う場合

```Ruby
#文字列を標準入力する
line = gets
#「:」で分けてmap関数を使ってhourとminute変数にそれぞれ数値に変換して代入する。
hour,minute = line.split(':').map(&:to_i)
#標準出力する。
puts hour
puts minute
```


mapを使うほうが分かりやすいですね。
CCNA試験学習(忘備録)〜ACL〜

#はじめに

引き続きCCNAの学習を進めていきます。

#ACLとは？
・Access Control Listの略。ルータの仕事。
・「ACL」で検索すると「アジアチャンピオンズリーグ」が出るので、注意。
・通信（アクセス）を制御するための情報を記述したリスト。
・特定のIPアドレスや通信に対して、自ネットワークへのアクセス制限をしたい場合にACLを使用する。制限されたパケットはルータで破棄される。
・ルータを通過するパケットをフィルタリング。
・目的に応じて複数作成も可能。

#ACLの動作

・パケットが到着するとルータは、自身のACLとパケット内の情報を比較して、そのパケットを許可or拒否する。
・条件にマッチしているかどうかは、表の上から順に確認していくのでリストの順番も非常に重要。**(トップダウン方式)**
・ACLの最後は**「暗黙のdeny」**(すべて拒否)が存在するので、ACLを作成する際はどこかに必ず「許可」を入れないと、全部拒否されてしまう。

#ACLの種類

**■標準ACL(Standard Access Control List)**
・**番号付き標準ACL**と**名前付き標準ACL**がある。番号付きの場合は**1〜99,1300〜1999**で識別。
・送信IPアドレスのみをチェック。詳細なACLは作成できない。大雑把なやつ。

**◆拡張ACL(Extended Access Control List)**
・**番号付き拡張ACL**と**名前付き拡張ACL**がある。番号付きの場合は**100〜199,2000〜2699**で識別。
・宛先・送信元アドレス、プロトコル、宛先・送信元ポート番号もチェック。柔軟で詳細なACLを作成できる。

#インバウンドとアウトバウンド

・ACLはインターフェース単位で設定を行う。
・ルータにパケットが入ってきたときにチェック(インバウンド)
・ルータからパケットが出ていくときにチェック(アウトバウンド)

#実際のコマンド

**■番号付き標準ACL**
・グローバルコンフィギュレーションモードで行う。
<font color="red">(config)#access-list [リスト番号]　[permit | deny] [送信元IPアドレス] [ワイルドカードマスク]</font>
・リスト番号は1〜99,1300〜1999で選択。
・許可の場合はpermit拒否の場合はdeny
・標準ACLではワイルドカードマスク[0.0.0.0]は省略可能。
・「暗黙のdeny」が存在するので最後の行に「すべて許可」をしないと結果すべて拒否されてしまうので
<font color="red">(config)#access-list [リスト番号] permit any</font>
をお忘れなく。
・条件文を作成した後はインターフェイスへインターフェイスへの適用とインバウンドorアウトバウンドの適用を行う。
<font color="red">(config-if)#ip access-group [リスト番号] [in | out]</font>
となる。

**◆番号付き拡張ACL**
・グローバルコンフィギュレーションモードで行う。
<font color="red">(config)#access-list [リスト番号]　[permit | deny] [プロトコル]
　　　　　　　　　[送信元IPアドレス] [ワイルドカードマスク] [送信元ポート番号]
　　　　　　　　　[宛先IPアドレス] [ワイルドカードマスク] [宛先ポート番号] [オプション]</font>
長い。覚えられるかしら。
・リスト番号は100〜199,2000〜2699で選択。

#確認コマンド

・特権モードで行う。
<font color="red">#show access-lists</font>

#最後に

お疲れ様でした。
私事ですが、SES企業に就職しもうすぐ２週間ですが面談の連絡がなく少し不安な気持ちで研修を受けております。
とりあえずこっそり爪を研いでいざという時に備えます・・・。
プログラミングとの出会い

<h2>はじめに</h2>
これは文系大卒未経験が一から勉強しプログラマになれるかを検証する物語になります。

まずプログラミングを学ぼうと思った経緯をお話すると今から約４年前私は就職活動真っ只中でした。私はその前年に一年間オーストラリアに留学をしており、TOEICも800点を獲得し意気揚々と超大手企業にエントリーシートを出しまくりました。結果大量のお祈りメールを受け取ることになりました。:cold_sweat:
今思うとその当時スポーツ馬鹿でなんのスキルもない若造（海外にかぶれていて紺色のストライプが入ったスーツで就活していた:joy_cat:）を採用するはずがないです。
兎にも角にもそのまま周りは内定を取り始めるなか私は書類選考すら通らない日々が続き心身共に（特にメンタル）が疲れ果てました。幸いな事にその当時のバイト先に採用してもらい（準社員）そのまま2年ほど働かせて頂きました。
その職場が特殊で就業中はお客さんとおしゃべりをひたすらすると言う内容で二年間で5000人ほどの方とお喋りをし、特に印象に残った方々は税理士さんや車両エンジニアの方など手に職があるスペシャリストの方で自分も何かスキル何か誇れる物が欲しいと思い昔からゲームやパソコンが好きだったので思い切って会社を退職しプログラミングの世界にやってきました。未経験で勉強も得意ではないので不安はいっぱいですが仕事も辞めてしまったのでやるしかない。今後もプログラミング情報や私の現状などを投稿させてもらいます。
Gravのスケルトン

# Grav

データベースを使わないフラットファイルCMSというのが便利だと聞いたので、Gravを導入しました。インストールはファイルをサーバに上げるだけなので簡単でした（アップロード先はさくらインターネットのレンタルサーバ）。しかし書式がどこを探してもなく、難儀したので自分用にメモを残します。日本語の情報もまだ少ないようなので、何かの助けになればということでQiitaに投稿します。

# インストール時のはまりポイント

その前に、最初のはまりポイント。管理画面付きのパッケージを導入しましたが、パスワードで登録をはねられます。画面に書かれているComplexというのは、大文字＋小文字＋数字の3種類すべてがそろうことだそうです。わからないって、そんなこと。

# 書式の参照先

[公式ページのダウンロード](https://getgrav.org/downloads/skeletons)のところに、Skeltonsというコーナーがあります。デフォルトのテーマQuarkで検索かけると数個出てきました。ダウンロードして解凍すると、user/pagesにダミーファイルがありました。テーマの配布元などでは書式の掲載がないので注意です。
![grav-skelton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81187/36a84539-a584-c7fd-e581-1b0b8712faca.png)
OSI参照モデルについて

## 背景
みなさまこんにちは、プレイライフの熊﨑です。

railsチュートリアル8章を見返していたときに、以下のような１文に出会いました。
> セッションはHTTPプロトコルと階層が異なる（上の階層にある）ので、HTTPの特性とは別に（若干影響は受けるものの）接続を確保できます。

階層が違うってどういうこと？？となったので、ここでまとめることにしました！

## 対象読書
- railsチュートリアルの8章をよんで、階層？？となった方
- OSI参照モデルについてざっくりと理解したい方

## OSI参照モデルとは
OSI参照モデルとは、コンピュータネットワークに求められる機能（通信機能）やルールを7階層の構造に分割し定義したものです。

## OSI参照モデルの７つの階層
OSI参照モデルは下表のように７つの階層に分けられています。

|層|名称|規格|概要|利用例|
|---|---|---|---|---|
|7層　|アプリケーション層　|HTTP,FTP,DNS,SMTP,POPなど|個々のアプリケーション|www,メール|
|6層|プレゼンテーション層|SMTP,FTP,Telnetなど|データの表現形式|HTML|
|5層|セッション層|TLS,NetBIOSなど|通信手段|HTTPS|
|4層|トランスポート層|TCP,UDP,NetWare/IPなど|エンド間の通信制御| TCP,UDP |
|3層|ネットワーク層|IP,ARP,RARP,ICMPなど|データを送る相手を決め最適な経路で送信|IP|
|2層|データリンク層|PPP,Ethernetなど|隣接する機器同士の通信を実現|Ethernet|
|1層|物理層|RS-232,UTP,無線|物理的な接続、電気信号|UTPケーブル,光ファイバーケーブル|

### 第７層 アプリケーション層

利用者が使用するアプリケーションの通信ルールを決める。例えば、webサイトを閲覧する場合ならHTTP、メールを送るならSMTPと言ったように、決められています。

### 第６層 プレゼンテーション層

文字のコードや圧縮形式などをチェックし、データを共通の形に変換するのがプレゼンテーション層です。例えば文字化けや画像の表示ミスが起こらないように処理するのが、共通の形に変換するというプレゼンテーション層のひとつの仕事となります。異なるコンピューターでも同じ内容を表示できるようにサポートし、相互の意思疎通をさせることが役割です。

### 第５層 セッション層

連続する対話的な通信の開始や終了、同一性の維持などを行っています。アプリケーション間が連携して状態を共有し、一連の処理を一つのまとまり（セッション）として管理する機能を実現するもので、利用者の認証やログイン、ログアウトなどの状態管理を行っています。

例：
- ２者間の接続開始から終了までのルール
- 接続の維持や回復に関するルール
- 接続情報の管理に関するルール
などを定義しています。

### 第４層 トランスポート層

通信における信頼性を確保するのが、第4層のトランスポート層です。さまざまな制御を行って通信データに情報を付加し、通信を信頼できる形にします。

例：
- 確実な伝送orスピードどちらを優先するか？
- 異常があった時の対処に関するルール
などを定義しています。

### 第３層 ネットワーク層

通信相手が異なるネットワーク間にあってもデータのやり取りを可能とするのが、ネットワーク層の役割です。論理アドレスと呼ばれるIPアドレスを元にネットワークを識別し、転送に必要な情報を付け加えて定義します。

例：
- データの送信元と宛先の識別方法に関するルール
- 送信先から受け取り先までの経路選択の方法に関するルール

などを定義しています。

### 第２層 データリンク層
隣接する機器（ノード）間の通信に関するルールを規定する層。

例：
- データの送信元と、宛先の識別方法に関するルール
などを定義しています。

### 第１層 物理層

データを通信回線に送るのに必要な物理的な仕様を規定するのが、第1層の物理層です。コネクタの形状、ケーブルの種類、通信速度などの物理的な要素を決めることで、さまざまな機種同士でデータのやり取りが可能となります。

例：
- ケーブルの種類や長さに関するルール
- 通信速度、電気信号の符号化に関するルール
などを決めています。

## 実際に通信する際の流れ
コンピュータ間で通信する場合、送信側では７層〜1層の順番に処理を行っていきます。各層の規定通りに順番に処理されると、その処理した情報はヘッダとしてデータの前に付加されていきます。このように上位層の処理情報をヘッダとして下位層で包み込んでいくことをカプセル化といいます。そして、７層から順番に処理されていくと、1層の処理でデータが最終的に電気信号となって送信されます。

一方、受信側のコンピュータでは受信した電気信号を1層〜7層の順で処理していきます。1層では電気信号をビット列に変換してコンピュータ上に取り込んでいき、2層では2層のヘッダの情報に基づいて処理した上で２層のヘッダを取り外します。3層以降も同様に、ヘッダ情報に基づいて処理した上でヘッダをとりはずし、最終的には受信側のコンピュータのアプリケーション上でもとのデータを受け取れます。このように、下位層から上位層にいくにつれて各層のヘッダを取り外していくことを非カプセル化といいます。

## HTTPとセッションの階層が違うことでどう影響があるのか？（個人的な見解）
今までの話からHTTPは第７層、セッションは第５層に存在することがわかったと思います。
しかし、冒頭にあった
> セッションはHTTPプロトコルと階層が異なる（上の階層にある）ので、HTTPの特性とは別に（若干影響は受けるものの）接続を確保できます。

は結局どういうことだったのでしょうか？？

階層が違うことにより、セッションとHTTPのデータは別のヘッダに存在することが考えられます。
そのため、HTTPの影響をほぼ受けずに、接続を確保できる。ということなのでしょうか？（こちらは個人的な見解ですので、理解が間違っている場合にはご指摘いただけますと幸いです。）

## まとめ
- OSI参照モデルとは、コンピュータネットワークの通信機能に求められる仕様を７つの層に分けて定義されたものである。
- 実際に通信をする際には送信側では7〜1層の順番に処理を行い、その過程で上位層の処理情報をヘッダとしてデータの前につけていく。これをカプセル化と呼ぶ。
- 実際に通信をする際には受信側では1〜7層の順番に処理を行い、その過程でヘッダを取り外していく、これを非カプセル化と呼ぶ。非カプセル化することで、受信側のコンピュータでも元のデータを受け取れる。

## 参考文献
[https://www.itmanage.co.jp/column/osi-reference-model/#anc002](https://www.itmanage.co.jp/column/osi-reference-model/#anc002)
[https://www.infraexpert.com/study/networking3.html](https://www.infraexpert.com/study/networking3.html)
CSR,SSR,SSG,ISRのまとめ

フロントエンドが進化するにつれて、ビルド方法やレンダリング方法も多様化したのでまとめてみたいと思います

# CSR
CSR(client side rendering)とは、ユーザーのブラウザで全てレンダリングする方法です。
1. ほぼ空のHTMLとレンダリングするためのjsやCSSを受け取る
2. ブラウザがjsとCSSを読み込む
3. jsで描画のためのCSSとHTMLを生成する
4. HTMLの特定のタグに生成されたHTMLやCSSを展開する
5. 最終的なDOM,CSSMOMをもとにブラウザが描画する

またケースによっては、初期描画のための情報をAPIなどで取得するケースもあリます。

## メリット
* 一度読み込めば、あとは都度情報を取得するだけでいいので、ページ遷移なく処理を組める。
* 都度ページ遷移を挟まないのでサーバーへの負荷は少ない

## デメリット
* ページを開いてからHTMLなどの生成を行うので初期描画に時間がかかる
* 全ての処理をユーザーに寄せるのでユーザーのCPUやメモリを食う
* 最初は空のHTMLしかないので、SEO的に不利

# SSR
SSR(server side rendering)とは、サーバー側でHTMLやCSS,またレンダリングに必要な情報を取得して、その生成結果のHTML,CSS,jsをユーザー側に返す方法です。

1. サーバーでJSを実行する
2. 描画に必要な情報をサーバー経由で取得する
3. 描画直前のHTML,CSSを生成
4. ブラウザHTML,CSSを受け取る
5. ブラウザが描画

## メリット
* 初期描画が非常に早い
* SEOに強い
* サーバーサイドでやってくれるのでユーザーへの負担が少ない

## デメリット
* 処理をサーバーに寄せるので、サーバーの負荷が高い
* SSR用のサーバーが必要になる。大抵の場合nodejs

# SSG
SSGとはビルド時に全ての情報を取得して完全な静的ファイルを作る方法です。
1. ビルド時にAPIなどでコンテンツを取得
2. コンテンツを埋め込んだHTML,CSS,jsを生成
3. 2.をホスティングサーバーに配置し配信する

## メリット
* 速度が非常に早い
* SEOにも強い

## デメリット
* ビルド時に全ての情報を取得してビルドするので、コンテンツ量が増えるとビルド時間も増える
* 頻繁に情報を更新するたぐいのサイトと相性が非常に悪い

# ISR
アクセスされた時に初めてSSGのビルドが走りサイトを生成する方法です。
1. ユーザーがページにアクセスする
2. SSGのビルドが走る
3. 生成結果をユーザーに返す 
4. 　二回目以降はビルド結果のHTMLが返される

## メリット
* SSGのビルド時間を考えなくていい
* 新しい記事などを再配置することで更新できる

## デメリット
* キャッシュがかかる場合は更新ページを反映する時がテクニカルになる場合がある


# 最後に
間違っている部分があれば指摘をお願いします。
では良きフロントエンドライフを
Matplotlib定量比較-散布図

## 散布図とは

散布図は２つの変数に対して、x-y座標上に点をプロットしたグラフです。
散布図で２つの変数の関係性が見えます。

## 簡単な散布図

```python
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.scatter(data['col01'], data['col02'])

ax.set_xlabel('Col01')
ax.set_ylabel('Col02')

plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/fc3421e6-454f-6382-b6be-719b93778f8b.png)

## 色で第3次元を表現する

色を使用して、時間を第3次元として表現できます。
下図では早い日付を暗い色、遅い日付を明るい色で表現しています。

```python
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.scatter(data['col01'], data['col02'], c=data['date'])

ax.set_xlabel('Col01')
ax.set_ylabel('Col02')

plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/f7106828-5c93-fbdb-64d6-81db4ee38191.png)
【GCP】組織ポリシー VS. Dataflow

GCPの組織ポリシーには、**VMの外部IPを制限するポリシー**(``constraints/compute.vmExternalIpAccess``)があります。
詳しい解説がGoogle Cloud Blogに載っていました。

https://cloud.google.com/blog/ja/products/identity-security/limiting-public-ips-google-cloud

この組織ポリシーを適用しようとして、Project内のCompute Engineを眺めていたところ、Dataflowジョブを実行後、外部IPを持ったワーカーVMが起動していることに気づきました。**Dataflow**はサーバーレスなデータ処理ですが、裏では**外部IPアドレスを持つワーカーVMを立ち上げている**ようです。

そこで、**組織ポリシーを適用後にDataflowが実行できるか**どうか、実験してみました。この戦いはどちらが勝つでしょうか？

# 実験の準備
この実験には組織が必要なので、**Cloud Identity**を利用して組織を作成しました。
Cloud Aceさんのページを参考にさせていただきました。ありがとうございます。
https://cloud-ace.jp/column/detail151/


# Dataflow（サンプルJob）を実行する
まずは、組織ポリシーをかけてないところで、DataflowのサンプルJob（Word Count）を実行しました。
![04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602803/37916577-c18e-0e5d-f112-bca41f0733c7.jpeg)

実行中にインスタンステンプレートをのぞいてみたところ、デフォルト設定では外部IPがエフェメラルで設定されているようです。
![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602803/d940ec35-6697-6738-d45f-db9f8a316ee1.jpeg)



# 組織ポリシーを適用する
VMの外部IPを制限するポリシー（``constraints/compute.vmExternalIpAccess``）をすべて**拒否**に設定しました。
![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602803/c213f56a-347d-4741-01cd-fd4e858a3e0d.jpeg)

# 対決・・・結果は？
**組織ポリシー適用後にDataflowを動かしました。**結果はどうなったでしょうか？
![09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602803/4903504b-7c56-aeb0-0705-7624c507f71d.jpeg)

**組織ポリシーが勝ちました！！**アクティビィをみるとVM作成で失敗していますので、**DataflowはワーカーVMが作成できず失敗した**ようです。

![07-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602803/ed072e68-25a1-02ba-0760-3e49b55b1a70.jpeg)

# まとめ
* 外部IPに関する組織ポリシーを適用するとデフォルト設定のDataflowは失敗します。
* 回避方法についても実験しましたので、別でまとめました。

https://qiita.com/sabawanco/items/0962b9c37d7a1e4db8de
Pythonでフォルダのファイル名を小文字（大文字）にする方法

フォルダに格納されているファイルが大文字小文字混在のファイル名だったので、これを小文字に統一したくPythonでちょこっとプログラムをかいたのでメモ。

``` python
import os     # OS操作
import glob   # パスのパターン（ワイルドカードなど）を使用するため

path = './cards/*.png' # cardsフォルダ内のpngファイルを指定

# パス指定のファイル名を取得して出力してみる
file_list = glob.glob(path)
print(file_list)

for file in file_list:
  # ファイル名を大文字→小文字変換（大文字変換の時はupper()を使用）
  os.rename(file, file.lower())

# ファイル名が変更されているか確認
file_list = glob.glob(path)
print(file_list)
```

### 悩み
小文字の「png」と大文字の「PNG」を両方取得するにはどうしたらいいんだろう？誰かPythonの賢者教えて。

### 参考
https://docs.python.org/ja/3/library/glob.html
powershell　メモ

###事前準備

操作する側
・Enable-PSRemoting
・Set-Item WSMan:\localhost\Client\TrustedHosts -Value *

Set-ExecutionPolicy RemoteSigned -Force
winrm quickconfig -force
Set-Item WSMan:\localhost\Client\TrustedHosts * -Force

操作される側
Set-ExecutionPolicy RemoteSigned -Force
Set-WSManQuickConfig -Force

ネットワークの設定
Set-NetConnectionProfile
Debianにsudoをインストールする

## sudoのインストール手順

リモートサーバー（OSはDebian）に、sudoをインストールする手順をまとめます。

1. `$ su -` コマンドで管理者権限を取得します。
`$ su`だとのちに行う、visudoコマンドが実行できないので、`-`をつけ忘れないように注意してください。
[Linuxで「su」と「su -」の違いは? | マイナビニュース](https://news.mynavi.jp/article/20180207-linux_su/)

2. `# apt install sudo`コマンドを実行します。
インストールの仕方を調べていると、apt-getやaptitudeを使っている人もいるので、何が違うか調べてみたところ、aptはapt-get の持っていた設計上のミスを克服しているみたいでした。aptを使うのが推奨されているようなので、今回はaptを使います。
[aptとapt-getとaptitudeの違い](http://ultra-genma.hateblo.jp/entry/2019/04/08/233718)

3. `# visudo`コマンドを実行します。

4. 写真の矢印の所に、`ユーザー名  ALL=(ALL:ALL)ALL`を記入します。
書き終わったら Ctrl + o を押して、Enterを押すと保存されます。保存が終わったら Ctrl + x で終了して下さい。画面の一番下に出てる「^X」とかの「^」はCtrlを押すことを意味します。
![image.png](https://bootcamp.fjord.jp/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBOXlrQVE9PSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--40d387a155f91c71e35e9506c2dd31b30d01e1ab/image.png)

5. `# exit`を実行してsuコマンドで入ったrootから出ます。

6. 最後にsudoがインストールされているか確認します。まずはsudoなしで、OS再起動コマンドの`$ shutdown -r now`を入力し、エラーメッセージが表示されることを確認して下さい。

7.  sudoを付けて、OS再起動コマンド`$ sudo shutdown -r now`を入力し、パスワードも要求されるので入力します。その後、OSが再起動されればsudoがインストールされています。


以上です。


##参考
http://pogin.hatenablog.com/entry/20111008/1318101299
https://qiita.com/osktak/items/f1746d64797a6a4dd6ae
Sphinxでrecommonmarkを使用する際の問題と対策

# 概要
recommonmarkを使うと、Sphinxは全てのドキュメントを毎回ビルドし直します
そもそも当該エクステンションはdeprecated[^1]なエクステンションなので、myst-parserを使う方法を調べました

# 目次
1. 全てのドキュメントを毎回ビルドし直す問題
1. myst-parserの使用方法
    1. myst-parserをインストールする
    1. conf.pyを編集する
    1. makeする

# 全てのドキュメントを毎回ビルドし直す問題
recommonmarkを使用すると、全てのドキュメントが毎回再生成される現象が発生します。[^2]
recommonmarkの公式ドキュメントがconf.pyに以下の★の記述を追加することを推奨していることが原因です

``` conf.py
# for Sphinx-1.4 or newer
extensions = ['recommonmark']

# for Sphinx-1.3
from recommonmark.parser import CommonMarkParser

source_parsers = {
    '.md': CommonMarkParser,   ★ ①
}

source_suffix = ['.rst', '.md']
```

``` conf.py
# At top on conf.py (with other import statements)
import recommonmark
from recommonmark.transform import AutoStructify

# At the bottom of conf.py
def setup(app):
    app.add_config_value('recommonmark_config', {
            'url_resolver': lambda url: github_doc_root + url,　　★ ②
            'auto_toc_tree_section': 'Contents',
            }, True)
    app.add_transform(AutoStructify)
```

①/②の設定はSphinxのキャッシュ(environment.pickle)に保存することができません。[^3]
このため、Sphinxはビルドの度に「*conf.pyが変化した*」と判断し、全てのドキュメントをビルドしなおします。

この問題を回避するために、myst-parserを使用することにしました

# myst-parserの使用方法
myst-parserに乗り換えることで問題を回避できました。使用方法は以下の通り。

### myst-parserをインストールする

``` bash
$ python3 -m pip install myst-parser
```

### conf.pyを編集する

``` conf.py
extensions = ['myst_parser']
```

### makeする
``` bash
$ make html
```


[^1]: https://github.com/readthedocs/recommonmark
[^2]: https://github.com/readthedocs/recommonmark/issues/197
[^3]: https://github.com/sphinx-doc/sphinx/blob/a55816deb546828db1383f2875be815bf805f858/sphinx/config.py#L46
【OS】/centos7/ firefox の情報

※flatpakからインストールして実行した方が動作が安定してそうです。
↓firefoxをインストールして実行する。
https://qiita.com/thi-mo/items/2d00ba9d11beebcad015
バージョンは89.0 で日本語にもなる、素晴らしい

→日本語が打てなかったが

```
yum install ibus-mozc langpacks-ja
```
した後　日本語(Mozc)に切り替えて日本語が入力できるようになった。

## firefoxの場所

基本的なfirefoxの格納フォルダ

```
/usr/lib64/firefox
```
→ここは結構色んな場所が設定されている可能性がある。

コマンドから実行

```
 cd /usr/lib64/firefox
./firefox
```
自分の場合は（/usr/bin/）にシンボリックリンクをはっている

```
sudo ln -s /usr/lib64/firefox /usr/bin/firefox
```
※特に理由はない

## 更新作業(非推奨)
最新バージョンを取得した後に解凍
ブラウザからDownloadした後は、~/Downloads に保存されている

```:この例ではバージョン78.11
tar -jxvf firefox-78.11.0esr.tar.bz2 
```
```:古いフォルダは別の場所に置きます(バックアップ)
sudo mv /usr/lib64/firefox /usr/lib64/firefox.old
```
ダウンロードしたファイルを規定の場所に置き換えます。

```
sudo mv ~/Downloads/firefox /usr/lib64/firefox
```

### GUIに関して
現状私が利用しているのはGNOMEの環境
・変更するだけだとGNOMEのランチャーから起動しない
→デスクトップエントリを設定してあげる必要があります。

```:デスクトップエントリ(全ユーザー共通)
/usr/share/applications
```

/usr/share/applications配下にvim等で新規作成する


```:firefox.desktop(flatpak)
[Desktop Entry]
Name=Firefox
Exec=/usr/bin/flatpak run org.mozilla.firefox
Terminal=true
X-MultipleArgs=false
Type=Application
Icon=/usr/bin/firefox/browser/chrome/icons/default/default128.png
StartupWMClass=Firefox
StartupNotify=true
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;
Categories=GNOME;GTK;Network;WebBrowser;
```

```:firefox.desktop(直接インストールした場合)
[Desktop Entry]
Name=Firefox
Exec=/usr/bin/firefox/firefox
Terminal=true
X-MultipleArgs=false
Type=Application
Icon=/usr/bin/firefox/browser/chrome/icons/default/default128.png
StartupWMClass=Firefox
StartupNotify=true
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;
Categories=GNOME;GTK;Network;WebBrowser;
```
※アイコンの場所はバージョンによって結構異なる
※ターミナルの表示がうっとうしい場合はTerminal=false

## バグに関して
centosに直接インストールした場合
パスワード入力時に点滅して入力ができなくなるバグあり。

確認状況

```:バグ発生環境
gnome-shell --version
>> GNOME Shell 3.28.3

```

→flatpakからインストールして実行した場合、このバグは回避できた。
トラブルが発生した場合は、報告して行きます。
APCの管理画面を見てみよう

## 勉強前イメージ

キャッシュ見れるやつ？

## 調査

### APCとは？

Alternative PHP Cache の略で、
PHPのコードをキャッシュしてPHPの実行を高速化する仕組みです。

### 入れてみる

- APCに必要なパッケージのインストール

今回はCentOS7を使用しました。

```
yum install php-pear php-devel httpd-devel pcre-devel gcc make
```

- APCのインストール

以下のコマンドでインストールします。

```
pecl install apc
```

今回は管理画面みたいだけなので、一旦デフォルトにするため全部そのままenterで進みました

```
PHP Api Version:         20100412
Zend Module Api No:      20100525
Zend Extension Api No:   220100525
Enable internal debugging in APC [no] : 
Enable per request file info about files used from the APC cache [no] : 
Enable spin locks (EXPERIMENTAL) [no] : 
Enable memory protection (EXPERIMENTAL) [no] : 
Enable pthread mutexes (default) [no] : 
Enable pthread read/write locks (EXPERIMENTAL) [yes] : 
```

- 拡張モジュールを有効にする

インストールの最後に `You should add "extension=apc.so" to php.ini` を記載があったので、
ファイルを追加して有効にします。

```
vi /etc/php.d/apc.ini
extension=apc.so
```

- httpdの再起動

```
systemctl restart httpd
```

- web管理のスクリプトを使用できるようにする

`/usr/share/pear/apc.php` に管理のファイルがあるので移動させます。

```
cp /usr/share/pear/apc.php /var/www/html/
```

- 管理画面の確認

```
vi /var/www/html/apc.php
```

※セキュリティガバガバなので、local環境でお試しください。
外部の環境で行うなら、IP制限やセキュリティ対策を行いお試しください。

```
# コメントアウトにする
#defaults('ADMIN_USERNAME','apc');                      // Admin Username
#defaults('ADMIN_PASSWORD','password');         // Admin Password - CHANGE THIS TO ENABLE!!!

# ユーザ名とパスワードの記載を行う
defaults('ADMIN_USERNAME','admin');
defaults('ADMIN_PASSWORD','pass');
```

`http://IPアドレス/apc.php` で確認することが出来ます。

![1APC INFO (localhost.localdomain).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/1cb0b3c9-45e9-8cee-b334-dffb33e2fc58.png)


右上のログインを押して、↑で記載したユーザ名とパスワードをbasic認証で認証させます

![1_apc.php_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/ad149617-aa52-bd8f-97bd-f590d6655347.png)


全部の情報を見ることが出来ます。

![2APC INFO (localhost.localdomain).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f1eda9ba-bffd-c4dd-5ae8-de874315b1bb.png)

## 勉強後イメージ

そもそもhttpdとして動かしてるサーバじゃないのであまり情報が見れないけど、
一応見れた。
中身は今度見よう。

## 参考

- [いまさらAPCをインストールして、PHPの実行を高速化してみた](https://havelog.aho.mu/develop/php/e167-php-apc-install.html)
- [APCでPHPを高速化(CentOS7)](https://sudachi.jp/wiki/APC%E3%81%A7PHP%E3%82%92%E9%AB%98%E9%80%9F%E5%8C%96(CentOS7))
- [CentOSにAPCをインストールする方法](https://blog.verygoodtown.com/2010/02/centos-apc-install-how-to/)
正規表現　カタカナチェック　メモ

# はじめに
カタカナの入力チェックを行う際に、躓いたため記録する。
※結構ざっくり書いているため参考程度に


# カタカナを表す正規表現
## カタカナの文字コード

```
ァ, ア, ィ, イ, ゥ, ウ, ェ, エ, ォ, オ, カ, ガ, キ, ギ, ク, グ, ケ, ゲ, コ, ゴ, サ, ザ, シ, ジ, ス, ズ, セ, ゼ, ソ, ゾ, タ, ダ, チ, ヂ, ッ, ツ, ヅ, テ, デ, ト, ド, ナ, ニ, ヌ, ネ, ノ, ハ, バ, パ, ヒ, ビ, ピ, フ, ブ, プ, ヘ, ベ, ペ, ホ, ボ, ポ, マ, ミ, ム, メ, モ, ャ, ヤ, ュ, ユ, ョ, ヨ, ラ, リ, ル, レ, ロ, ヮ, ワ, ヰ, ヱ, ヲ, ン, ヴ, ヵ, ヶ
```

このようになっている。
もし、〇ヶ月、〇カ所などをマッチさせたくない場合は「ヵ」「ヶ」を含まないよう正規表現を書く必要がある。

その場合は、***[ァ-ヴ]***とすることで対応可能。気にしない場合は[ァ-ヶ]でよい。
上記を踏まえ、以下のように実装した。

```php
preg_match('/^[ァ-ヴ]+$/', $string);
```

今回は、フリガナの入力欄で入力値がカタカナであるかどうか判定する際にこの正規表現を用いたがなぜか一部文字をカタカナと認識できていないことが分かった。

## 一部文字を認識できていない問題について
実装して動作確認をしていると、「サ行」「ダ」「マ行の一部」など一部文字をカタカナとして認識できていないことが分かった。

原因を調べたところ、どうやらUTF-8では修飾子「u」を付ける必要があるとのこと。

他にも、大文字小文字にマッチするパターンなど様々なものがある。

```php
preg_match('/^[ァ-ヴ]+$/u', $string);
```

これでうまく認識できた。
また、正規表現にパターン修飾子なるものがあるのも初めて知ったためとても勉強になった。

## 参考
[パターン修飾子](https://www.php.net/manual/ja/reference.pcre.pattern.modifiers.php)
[すべてカタカナかどうか調べる](https://pentan.info/php/reg/is_kana.html)
【YOLO v5】Google Colaboratory で学習してみる

# 1. はじめに
Yoloは、とっても扱いやすいフレームワークで、すぐに物体検出ができますが、やっぱり自分が検出したいものは、自分の用意したデータで学習させるしかないですよね。
ということで、学習させてみました。
# 2. やること
データセットを作るのは、たいへんですので、既存のデータセットを使わせてもらい、学習の手順を確認したいと思います。
学習は、マシンパワーが必要そうですから、やっぱりGPUを使いたいところです。ですので、Google Colaboratoryを使います。

# 3. やってみる
## 3.1 まずは、準備

新しいノートブックを作り、Googleドライブをマウントします。

``` 
from google.colab import drive
drive.mount('/content/drive')
```
yolo_train というフォルダの中で作業します。

```
%cd /content/drive/My Drive/Colab Notebooks
%mkdir yolo_train
%cd yolo_train

```

Yoloをクローンしてきます。

```
!git clone https://github.com/ultralytics/yolov5 
%cd yolov5
```
必要なパッケージをインストールします。

```
!pip install -r yolov5/requirements.txt  
```
いろいろ準備します。

```
import torch
from IPython.display import Image, clear_output 
from utils.google_utils import gdrive_download  
```
Yoloがちゃんと動くか、物体検出してみます。
以下を実行すると、ジダンが検出されます。

```
!python detect.py --weights yolov5s.pt --img 416 --conf 0.4 --source ./data/images/
Image(filename='runs/detect/exp/zidane.jpg', width=600)
```

ちゃんとできましたよね？

## 3.2 学習
はい、やっと準備ができましたので、ここから本題です。

まずは、rboflowのPublic Datasetsから学習用データをとってきます。サイコロの目を検出させるための学習用[データセット](https://public.roboflow.com/object-detection/dice)です。すでにYOLOv5用に編集されていますから、ダウンロードするだけですぐに使えます。
Downloadsのmedium-colorを選びます。
Available Download Formatsで「YOLO v5 PyTorch」を選びます。
データをダウンロードするかダウンロードのコードを得るか選べます。今回は、ダウンロードのコードを取得して直接GoogleDriveに保存するため、ダウンロードコードを得ることにします。[show download code]を選択して[continue]を押すと、ダウンロードするコードが表示されます。

ノートブックに戻り、以下の通りダウンロードと展開をします。今回は、diceというフォルダにデータを入れました。

```
torch.hub.download_url_to_file('<<ダウンロードコード>>', 'tmp.zip')
!unzip -q tmp.zip -d ../dice/ && rm tmp.zip
```

diceのフォルダ内にあるdata.yamlを少しだけ変更します。学習用データと検証データが分かれていないので、同じデータを使います。

```data.yaml
train: ../dice/export/images
val: ../dice/export/images

nc: 6
names: ['1', '2', '3', '4', '5', '6'
```

もう、これで準備完了です。驚くほど簡単です。

学習してみます。

```
# Train YOLOv5s on dice for 10 epochs
!python train.py --img 640 --batch 16 --epochs 200 --data ../dice/data.yaml --cfg ./models/yolov5s.yaml --weights "" --name dice --nosave --cache

```

画像点数が少ないため、エポック数を200ぐらいにしないと、物体検出ができませんでした。学習時間は、1時間ほどかかりました。

結果は、runs/train/diceの中に入っています。ちょっと見てみましょう。

```
Image(filename='runs/train/dice/train_batch0.jpg', width=800)  
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/004a7c66-8c9f-3a13-2d32-8911b7151ce9.png)

Tensorbordで結果を見てみます。

```
%load_ext tensorboard
%tensorboard --logdir "runs"

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/aad37d4b-cde3-6865-ecc7-186cd5016b68.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/6b42c989-97e0-bbbd-25d8-c05e2e48ced0.png)

なかなかいいのではないでしょうか？

では、サイコロの目を検出してみます。

```
!python detect.py --weights runs/train/dice/weights/last.pt --source ../dice/dice.jpg
Image(filename='runs/detect/exp/dice.jpg', width=800)
```

![index.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/94996f6f-9660-2e37-c20d-67ea3444e872.jpeg)

ちゃんと検出できてきますね！
こんなに簡単に学習できるなんて感激です。


お疲れさまでした！
MSBuild.exeで実行ファイルを作る 

* csc.exe での実行ファイル作成に限界を感じたのでMSBuild.exeを使うこととした。

https://codezine.jp/article/detail/674

## ファイル

![src.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/ca2cc1bf-5991-d16e-880d-d201f98e1a8a.png)

```xml:main.csproj
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <ItemGroup>
    <Compile Include="*.cs" />
  </ItemGroup>

  <Target Name="Build">
	  <Csc Sources="@(Compile)" References="@(Reference)" />  
  </Target>

</Project>
```

* `References=`でdll読み込みの指定を渡すことができる。
* `ToolsVersion="4.0"`を書かないと古いC#の記述方法しか使えなかった。

* ソースファイル

```cs:main.cs
using System;

namespace ConsoleApp1 {
    class Program {
        static void Main(string[] args) {
            Console.Write("hello");
        }
    }
}
```

* ビルドスクリプト

```dosbatch:compile.bat
del main.exe

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ^
    main.csproj

main.exe

pause
```

## 実行ファイルを作る

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/3dc05272-40c8-c5c7-3a01-d87e8f83fa7c.png)


## DLLの追加

```xml:main.csproj
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <ItemGroup>
    <Compile Include="*.cs" />
    <Reference Include="QRCodeEncoderDecoderLibrary.dll"/>
  </ItemGroup>

  <Target Name="Build">
	  <Csc Sources="@(Compile)" References="@(Reference)" />  
  </Target>

</Project>
```
productionモードでサーバー起動した際のエラー対処法

![スクリーンショット 2021-06-12 14.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1286751/6d9d476d-e147-b0d6-2b41-6e45bd6338ad.png)


production.rbに以下の一文を加えます。

```production.rb
config.hosts << "localhost"
```
そして再起動

```
$ bin/rails s -e production -b 0.0.0.0
```

解消しました。
【エラー備忘録】Target class does not exist.  Laravelの認証機能 LoginControllerが見つからない。

##状況
Laravelに備え付けの認証機能を使って、Googleの認証を実装する時のこと。
LoginControllerに処理を書き、route/web.phpに以下のルーティングを設定した。

```php:route/web.php
Route::get('login/google', 'Auth\LoginController@redirectToGoogle');
Route::get('login/google/callback', 'Auth\LoginController@handleGoogleCallback');
```


##エラー内容

Webページに表示されたエラー文はこちら。

```
Illuminate\Contracts\Container\BindingResolutionException
Target class [Auth\LoginController] does not exist.

Illuminate\Container\Container::build
vendor/laravel/framework/src/Illuminate/Container/Container.php:835
```
LoginControllerが見つからないとのこと。

##原因の検証
このパターンのエラーで私がこれまで経験した例では、以下ような問題が原因…。
・namespaceが定義されていない
・ルーティングファイルに書いているパスが不完全、誤っている
・ルーティングファイルに使いたいコントローラーをuseしていない

##解決法
今回はnamespaceの定義部分がコメントアウトになっていました。

```app/Providers/RouteServiceProvider.php
protected $namespace = 'App\\Http\\Controllers';
```
この部分のコメントアウトを外すと、エラーは解消しました。
【備忘録】 yarn コマンド

npm と yarn どっちも叩いていると、分からなくなってくるのでメモ
理解した内容が増えるたびに都度、`更新`していく

■ yarn コマンド

```terminal
// プロジェクトルートに存在する package.json の記述に従い、依存関係のあるパッケージをインストールする
// yarn と yarn install は同義
$ yarn

// 指定したパッケージをインストールする
$ yarn add ${packageName}

// 指定したパッケージをアンインストールする
$ yarn remove ${packageName}

// 指定したパッケージを最新バージョンに更新する
// package.json で指定された範囲を超えた最新バージョンをインストールするには --latest オプションを指定する
$ yarn upgrade ${packageName}

// 指定したパッケージについての情報を表示する
$ yarn info ${packageName}
```

■ 雑メモ

- デフォルトで生成される `yarn.lock` ファイルは、パッケージの各依存関係のどのバージョンがインストールされたのかを、正確に記述し続ける

- `$ yarn upgrade` コマンドは、バージョン整合を取りつつ、パッケージをアップグレードしてくれはするが`動作を保証するもの`ではないので、実行後のテストや動作確認を必要とする

- package.json 内に記述する scripts を実行する際に、 npm だと `npm run start` と言ったように run を記述しなければならない。 yarn であれば `yarn start` と run を記述する必要がない