OmniAICreator/Qiita-1.07M huggingface dataset:
[Android] logcat の使い方を見直す

# はじめに
この記事では、Android Studio の logcat の使い方を見直して、より快適に開発を進める Tips をいくつか紹介します。
紹介する Tips は、公式ドキュメントや記事を参考しています。

**実行環境**

- Android Studio 4.0.1
- OS: Mac

# 1. Logcat Header を設定する
logcat の左下の[歯車マーク]をクリックすると、[Configure Logcat Header]の画面が表示されます。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215440/1783d3b8-3616-f99a-2580-228291fbd437.png)

[Configure Logcat Header]の画面では、ログの先頭に表示するものを設定できます。
私の環境では、以下の画像のように設定されていました。
チェックを付けたり外したりすると、インタラクティブにログのサンプルが変わります。

![スクリーンショット 2020-08-19 8.01.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215440/70fae192-925c-147e-014b-fda42e51f49f.png)

**メリット**
不要なもののチェックを外すと、1つのログが短くなって、見通しがよくなります。
私は、[Show date and time]と[Show tag]にチェックをいれています。

# 2. logcat 内の改行を有効/無効にする
以下の画像のように、logcat内のアイコンのクリックすると、logcat内でログを改行するかどうか選択することができます。
公式ドキュメントでは「ソフトラップの使用」という機能名で紹介されていました。

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215440/6cf239a7-d8b2-6722-1ead-48ed4050d7e2.png)

**メリット**
改行が無効になっている場合、ログに表示されたエラーメッセージをコピーしたい時に、横にぐーっとスクロールしながら選択することが多々あると思います。
そこで改行を有効にすると、横にスクロールすることなくメッセージを選択できるようになります。

# 3. 正規表現でログメッセージを検索する
普段ログメッセージを検索する時は、検索したい文字列をそのまま入力しているかと思いますが、実は正規表現を使って検索することができます。
以下の画像のように、[Regex]にチェックを付けると有効になります。
（始めから有効になっていると思います）

以下の画像では、「a.d」で検索しています。
正規表現での検索が有効になっているので、「a から始まって、d で終わる文字列」を検索していることになります。
ログを見てみると、「android」と入ったメッセージが表示されていることがわかります。
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215440/d1e2872c-5746-a2a4-2cd1-8684f304282b.png)

**メリット**
正直、正規表現で検索することは少ないですが、正規表現をマスターしている方なら嬉しい機能かもしれません。

# 終わりに
この記事では、Android Studio の logcat の Tips をいくつか紹介しました。
logcat の使い方を見直すことはあまりないと思うので、この機会に logcat のいろんな機能を調べてみてはいかがでしょうか。

# 参考（2020/08/19現在）

- [Debugging in Android Studio](https://medium.com/androiddevelopers/debugging-in-android-studio-dfbbf8a8d03c)
- [logcat を使用してログを書き込み、表示する](https://developer.android.com/studio/debug/am-logcat)（公式ドキュメント）
スマホの見た目のときだけ電話番号のリンクをアクティブにする

```html:HTML
<a href="tel:0120-000-000" class="telephone">TEL:0120-000-000</a>
```

これだけだとPCのブラウザでも電話番号のリンクがつながってしまうので、スマホだけにする
メディアクエリでウィンドウ幅769px以上の場合はリンクを無効にするCSSを設定する

```css:CSS
@media screen and (min-width: 769px){
 a.telephone [href*="tel:"] {
    cursor: default;
    pointer-events: none;
    text-decoration: none;
 }
}
```
ABC175

AtCorder Beginner Contest 175 に参加しました。 
ABCの3問ACでした。 
Python3を使用しています。

# A問題
まず雨(R)の数を求めます。 
今回は連続した雨(R)の数を求めるので、RSRの場合は1と答える場合分けの処理を行います。 
3日間の天気しか入力されないため例外は1つ考慮すれば十分です。

```python
import sys
def input():
    return sys.stdin.readline()[:-1]


def main():
    s=input()
    c = s.count("R")
    if c == 2 and s[1] == "S":
        c += -1
    print(c)

    
if __name__ == "__main__":
    main()
```
# B問題
*問題文ではi、j、kを選んだ棒の番号になっていますが、以下の解答では棒の長さになっています。 
棒の長さリスト(L)から、3本の棒を選びます。  
棒を選ぶ順番は影響しない、かつ長さi,j,kは全て異なるので、i,j,kの順に大きくなると制限します。 
さらに選んだ3本の棒で三角形の成立条件 
「a+b > c かつ b+c > a かつ c+a > b」 
を満たす場合の数を数えます。 

```python
import sys
def input():
    return sys.stdin.readline()[:-1]


def main():
    N = int(input())
    L = list(map(int,input().split()))
    ans = 0
    for i in L:
        for j in L:
            for k in L:
                if i < j and j < k and (i+j) > k and (i+k) > j and (j+k) >i:
                    ans +=1
    print(ans)

    
if __name__ == "__main__":
    main()
```


# C問題
高橋君の行動パターンは大きく2つに分けることができます。
・K回行動してもXから0に到達できない(可能な限り近づいた) 
・K回より少ない回数でXから0に到達しており、残った回数で往復して0付近まで戻ってきた  
さらに2つ目のパターンは、残った回数が偶数か奇数かで場合分けしています。  

```python
import sys
def input():
    return sys.stdin.readline()[:-1]


def main():
    X,K,D = map(int,input().split())
    x = abs(X)
    if K * D < x:
        ans = x - K * D
    else:
        shou = x // D
        nokori = K - shou
        
        if nokori % 2 == 0:
            ans = x % D    
        else:
            ans = abs((x % D) - D)
            
    print(ans)


    
if __name__ == "__main__":
    main()
```
Arduino Leonardo > Digital Pin2..9の状態を読み取りシリアル出力

```txt:動作環境
Windows 10 Pro v1909
Arduino IDE v1.8.13
Analog Discovery 2
Arduino Leonardo
```

### 概要

- GPIOの状態をロギングしたい
- GPIOの状態をシリアル出力する機能をLeonardo向けに実装した
    - Digital Pin 2..9の読み取り

### GPIO

https://www.electroschematics.com/arduino-leonardo-pinout/

画像の右下のDigital Pin 2..9を使用する。


### AD2と接続

動作確認はAD2の電圧出力(Supplies)を使用した。オープンピンは誤読を起こすため、電圧出力以外のピンはGNDに接続すること。
(実際の使用ではケーブルが接続されるので、オープンピンにはならない。使うピン数だけの実装に`Table_pins[]`を変更して使う）。

AD2の方では以下のようにPosivitve Supplyを3Vとして使用した (3.3V駆動のMCUのGPIO読み取りに使う)。
Master Enable is OnのボタンをON/OFFして電圧をH/Lに変更する。

![コメント 2020-08-19 090942.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/426a4b7d-abfe-33b9-506b-364426dc58ec.png)


### 実装

```c

#include <TimeLib.h>  // installed Time by Michael Margolis

/*
 * 2020-08-19 
 * Digital Pinのシリアル出力
 *   出力例: 2020/08/19,12:30:45,1,0,1,0,1,1,1
 * 
 * Digital PinのRX, TXを飛ばして、2..9のピンを使う
 * オープン状態にすると誤読を生じるので、実際に接続するピンだけをTable_p[]で定義すること
 */
#define PIN_DIGPIN2 (2)  // Pin 19
#define PIN_DIGPIN3 (3)  // Pin 18
#define PIN_DIGPIN4 (4)  // Pin 25
#define PIN_DIGPIN5 (5)  // Pin 31
#define PIN_DIGPIN6 (6)  // Pin 27
#define PIN_DIGPIN7 (7)  // Pin 1
#define PIN_DIGPIN8 (8)  // Pin 28
#define PIN_DIGPIN9 (9)  // Pin 29

int Table_pins[] = {
  PIN_DIGPIN2, PIN_DIGPIN3, PIN_DIGPIN4,PIN_DIGPIN5, PIN_DIGPIN6,
  PIN_DIGPIN7, PIN_DIGPIN8, PIN_DIGPIN9,
};
int tableSize;

void setup() {
  Serial.begin(9600);
  tableSize = sizeof(Table_pins) / sizeof(Table_pins[0]);
  for(int idx=0; idx < tableSize; idx++) {
    pinMode(Table_pins[idx], INPUT);
  }
}

void myPrintf(char *fmt, ...) 
{
  char buf[128];
  va_list args;
  va_start(args, fmt);
  vsnprintf(buf, 128, fmt, args);
  va_end(args);
  Serial.print(buf);  
}

void loop() {
  int val;

  myPrintf("%04d/%02d/%02d,", year(), month(), day(), month());
  myPrintf("%02d:%02d:%02d,", hour(), minute(), second() );

  for(int idx=0; idx < tableSize; idx++) {
    val = digitalRead(Table_pins[idx]);
    Serial.print(val);
    if (idx != (tableSize - 1)) {
      Serial.print(",");
    }
  }
  Serial.println(); 

  delay(1000); // msec
}
```


```txt:結果
1970/01/01,00:13:30,0,0,0,1,0,0,0,0
1970/01/01,00:13:31,0,0,0,1,0,0,0,0
1970/01/01,00:13:32,0,0,0,1,0,0,0,0
1970/01/01,00:13:33,0,0,0,1,0,0,0,0
1970/01/01,00:13:34,0,0,0,1,0,0,0,0
1970/01/01,00:13:35,0,0,0,1,0,0,0,0
```

### 備考

時計合わせをする実装をするか。

C++ Builderでシリアル受信ソフトを作れば、そちらで時計合わせがしやすい。
とりあえずこの実装はここでいったんやめる。


### 関連

- [ESP8266 > 磁気センサーの動作確認 > Sunhayato MM-DE21P](https://qiita.com/7of9/items/7b5ffd3e9bd9608459ef)
    - pinMode(), digitalRead()
- [ Reference > Language > Functions > Digital io > Digitalread ](https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/)
- [Arduino > Time > 日時設定 > setTime(hh, nn, ss, dd, mm, yyyy);](https://qiita.com/7of9/items/4a611ae804dbe2619466)

### 「時計合わせ」のその後

シリアル出力された文字列を受けるWindows ソフトを作った。
そのソフト上でPC時刻を使って時計情報を持たせることにした。Arduino側は上記のままとすることにした。
Windowsソフト側ではシリアル受信をUDPに変換する機能もつけ、UDPでデータをグラフ表示するなどできるようにしている。
チュートリアルのとおりOptuna使ってみたけどわからなかったので少し調べてみた

## Optunaとは

PFNが開発したハイパーパラメータ自動最適化フレームワーク

機械学習モデルのハイパーパラメーターの最適化のために作られたベイズ最適化Package

## 何ができるのか

ベイズ最適化のTPEを用いた最適化を行う

シングルプロセスで手軽に使うことができる

多数のマシンで並列に学習することもできる

## どう使うのか

```python
import optuna
from sklearn.metrics import log_loss # 損失関数を計算するライブラリ

# Optunaで最適化するための関数を定義
# Optunaは、return（ここではscore）で返す値が最小になるようなハイパーパラメータを探索してくれる
def objective(trial):
    # ハイパーパラメータの探索範囲を設定
    # ↓はLightGBMのパラメータ
    # 参考：https://qiita.com/nabenabe0928/items/6b9772131ba89da00354
    #* objective:目的関数
    #  * regression:回帰を解く
    #  * binary:二値分類
    #  * multiclass:他クラス分類
    #* learning_rate:学習率。デフォルトは0.1。大きなnum_iterationsを取るときは小さなlearning_rateを取ると精度が上がる
    #  * num_leaves:木にある分岐の個数。デフォルトは31。大きくすると精度は上がるが過学習が進む。
    #  * max_bin：一つの分岐に入るデータ数の最大値。小さくすると細かく学習ができるので精度を上げられる。大きくするとざっくりとした学習となり一般性が上がる。
    params = {
        'objective': 'binary', # objectiveはbinaryで固定
        'max_bin': trial.suggest_int('max_bin', 255, 500), # max_binは255~500の間の整数値を探索
        'learning_rate': 0.05, # learning_rateは0.05で固定
        'num_leaves': trial.suggest_int('num_leaves', 32, 128), # num_leavesは32~128の間の整数値を探索
    }
    
    # LightGBMを用いて学習
    lgb_train = lgb.Dataset(X_train, y_train, categorical_feature=categorical_features)
    lgb_eval = lgb.Dataset(X_valid, y_valid, reference=lgb_train, categorical_feature=categorical_features)

    model = lgb.train(
        params, lgb_train,
        valid_sets=[lgb_train, lgb_eval],
        verbose_eval=10,
        num_boost_round=1000,
        early_stopping_rounds=10
    )

    # 検証用データセットに対する性能を調べている
    y_pred_valid = model.predict(X_valid, num_iteration=model.best_iteration)
    score = log_loss(y_valid, y_pred_valid)
    return score
```

```python
# Optuna最適化のためのセッションを作成。seed=0とすることで乱数を固定。
study = optuna.create_study(sampler=optuna.samplers.RandomSampler(seed=0))
# Optunaの計算を実行。第一引数に最小化したい関数を渡す。n_trialsは実行回数で今回は小さめの40回を指定している
study.optimize(objective, n_trials=40)
study.best_params
```

```python
params = {
    'objective': 'binary',
    'max_bin': study.best_params['max_bin'],
    'learning_rate': 0.05,
    'num_leaves': study.best_params['num_leaves']
}

# LightGBMを用いて学習
lgb_train = lgb.Dataset(X_train, y_train, categorical_feature=categorical_features)
lgb_eval = lgb.Dataset(X_valid, y_valid, reference=lgb_train, categorical_feature=categorical_features)

model = lgb.train(
    params, lgb_train,
    valid_sets=[lgb_train, lgb_eval],
    verbose_eval=10,
    num_boost_round=1000,
    early_stopping_rounds=10
)

y_pred = model.predict(X_test, num_iteration=model.best_iteration)
```
Nuxt.jsで作ったSPAをGitHub ActionsでFirebaseにデプロイしてみた

# 背景

Nuxt.jsで作成したSPAアプリをFirebase Hostingにデプロイしてみた。
先人の知恵を借りようとググってみると、そのやり方に納得行かない点があったのでアレンジを加えている。

# おおまかな流れ

1. Firebaseにプロジェクトを作成
2. Firebaseの設定ファイルを生成
3. Firebaseのトークンを取得
4. GitHubにFirebaseのトークンを登録
5. GitHub Actions用のワークフローを作成
6. デプロイ

# 実際の手順

#### 1. Firebaseにプロジェクトを作成



#### 2. Firebaseの設定ファイルを生成

デプロイしたいプロジェクトのリポジトリ内で下記のコマンドを実行する。

```
firebase init
```

各設問には、以下のように回答する

設問|回答
---|---
? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices.|Hosting
? Select a default Firebase project for this directory:|あらかじめ作成しておいたプロジェクトを選択
? What do you want to use as your public directory?|dist
? Configure as a single-page app (rewrite all urls to /index.html)?|Yes
? File dist/index.html already exists. Overwrite?|No





すると、`.firebaserc`ファイルと`firebase.json`が生成される


#### 3. Firebaseのトークンを取得

下記のコマンドを実行して、ブラウザでログインに成功するとコマンドラインにトークンが表示される。

```bash
firebase login:ci
```

#### 4. GitHubにFirebaseのトークンを登録

GitHub上のリポジトリページに移動し、`Settings` > `Secrets` > `New Secret`をクリック。

入力欄|設定値
---|---
Name|FIREBASE_TOKEN
Value|あらかじめ取得したトークンを貼り付け

#### 5. GitHub Actions用のワークフローを作成

ここが先人の知恵からカスタマイズしたポイント。
他の方々はビルドのジョブでデプロイまでしてしまっていたが、`本来はビルドとデプロイのジョブは分けるべき`だと思う。

ということで、以下のようなワークフローを作成した。

```yml:.github/workflows/actions.yml
name: Build and Deploy
on:
  push:
    branches:
      - master

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@master
      - name: Install Dependencies
        run: yarn install
      - name: Build and Generate
        run: yarn generate
      - name: Archive Production Artifact
        uses: actions/upload-artifact@master
        with:
          name: dist
          path: dist

  deploy:
    name: Deploy
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@master
      - name: Download Artifact
        uses: actions/download-artifact@master
        with:
          name: dist
          path: dist
      - name: Deploy to Firebase
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only hosting
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```

#### 6. デプロイ

ローカルの変更を`master`へpushすると、GitHub Actionsのワークフローが実行されて、Firebaseにデプロイされます。
iOS連写カメラをつくる【最小実装】

指定した間隔で連写するカメラをつくります。

AVCaptureSessionの構成。
PhotoOutputではなく、VideoOutputのフレームを取得します。

```swift
var captureSession = AVCaptureSession()
var previewView = UIView()
var previewLayer:AVCaptureVideoPreviewLayer?
let videoDataOutput = AVCaptureVideoDataOutput()

let videoDevice = AVCaptureDevice.default(for: AVMediaType.video)
let videoInput = try! AVCaptureDeviceInput.init(device: videoDevice!)
        
captureSession.beginConfiguration()
captureSession.addInput(videoInput)
videoDataOutput.setSampleBufferDelegate(self, queue: videoDataOutputQueue)
videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)]
videoDataOutput.alwaysDiscardsLateVideoFrames = true
captureSession.addOutput(videoDataOutput)
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.frame = previewView.bounds
previewView.layer.addSublayer(previewLayer!)
captureSession.commitConfiguration()
let captureConnection = videoDataOutput.connection(with: .video)
captureConnection?.videoOrientation = .portrait
captureConnection?.isEnabled = true
captureSession.startRunning()
```

AVCaptureVideoOutputDelegateのCaptureOutputメソッド内で、取得したフレームを保存します。

```swift
var isGettingBuffer = false

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    if isGettingBuffer{         
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return
        }
        let image = UIImage(ciImage: CIImage(cvImageBuffer: pixelBuffer))
        let data = image.jpegData(compressionQuality: 1)
        PHPhotoLibrary.shared().performChanges({
            let creationRequest = PHAssetCreationRequest.forAsset()
            creationRequest.addResource(with: .photo,
                                        data: data!,
                                        options: nil)
        })
        isGettingBuffer = false
    }
}

```

指定した間隔でフレームを保存するようにタイマーを設定します。

```swift
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (Timer) in
            //好きなキャプチャ間隔を指定する。ここでは１秒。
            self.isGettingBuffer = true
        }
```

**＊＊＊**
Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[MLBoysチャンネル]
(https://www.youtube.com/channel/UCbHff-wfjTnB3rtXIP6y0xg)
[Medium](https://medium.com/@rockyshikoku)

[相棒](https://twitter.com/oka_yuuji)
[note](https://note.com/oka_yuuji)
Nuxt.jsのバージョンを下げてみた（2.14.x → 2.13.x / 2.12.x）

# 背景

`create-nuxt-app`は非常に便利だが、その時点での最新のNuxt.jsでプロジェクトが作成される。

Nuxt.jsでSPAを作成していたのだが、[ある問題](https://qiita.com/itTkm/items/2211877b3d41088e4c10)の調査のためにNuxt.jsのダウングレードを試してみた。
そのときの手順を参考までに残しておく。

# 基本的な流れ

1. インストール済みの依存パッケージを全て削除
2. `package.json`を修正
3. 依存パッケージを再インストール
4. `nuxt.config.js`をバージョンに合わせて修正

# 手順

## 2.14.x → 2.13.x

#### 1. インストール済みの依存パッケージを全て削除

```bash
# 既存の依存パッケージとビルド成果物を削除
rm -rf node_modules/ dist/

# yarnの場合
rm yarn.lock

# npmの場合
rm package-lock.json
```

#### 2. **`package.json`を修正**

修正するのは下記の2点

* scripts
    * `generate`を削除
    * `export`と`serve`を追加
* dependencies
    * `<2.14.0`とすれば、2.14.0未満、つまり2.13.x系の最新バージョンがインストールされる。

```json:package.json
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "export": "nuxt export",
    "serve": "nuxt serve"
  },
  "dependencies": {
    "nuxt": "<2.14.0"
  },
```

#### 3. 依存パッケージを再インストール

```bash
# yarnの場合
yarn install

# npmの場合
npm install
```

#### 4. `nuxt.config.js`をバージョンに合わせて修正

2.14.x → 2.13.xの場合は修正は不要そう。
間違っていたらごめんなさい。

## 2.14.x → 2.12.x

#### 1. インストール済みの依存パッケージを全て削除

```bash
# 既存の依存パッケージとビルド成果物を削除
rm -rf node_modules/ dist/

# yarnの場合
rm yarn.lock

# npmの場合
rm package-lock.json
```

#### 2. `package.json`を修正

修正するのは下記の2点

* scripts
    * `start`を削除
* dependencies
    * `<2.13.0`とすれば、2.13.0未満、つまり2.12.x系の最新バージョンがインストールされる。

```json:package.json
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "generate": "nuxt generate",
  },
  "dependencies": {
    "nuxt": "<2.13.0"
  },
```

#### 3. 依存パッケージを再インストール

```bash
# yarnの場合
yarn install

# npmの場合
npm install
```

#### 4. `nuxt.config.js`をバージョンに合わせて修正

修正するのは下記の2点

* `target: 'static'`をコメントアウト
* `components: true`をコメントアウト

```js:nuxt.config.js
export default {
      :
    (省略)
      :
  /*
  ** Nuxt target
  ** See https://nuxtjs.org/api/configuration-target
  */
  // target: 'static'
      :
    (省略)
      :
  /*
  ** Auto import components
  ** See https://nuxtjs.org/api/configuration-components
  */
  // components: true
      :
    (省略)
      :
}
```
Nuxt.jsで作ったSPAをFirebaseにデプロイしたら無限クルクルになった

# 背景

Nuxt.jsでSPAを開発し、Firebase Hostingにデプロイするつもりだった。
いざデプロイしてワクワクしながらアクセスしてみると、下のスクショのように真っ白の画面にLoadingのクルクルが延々と回り続ける状態に。
`yarn dev` (`npm run dev`)で、ローカルでは問題なく動いていたのに。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562193/f2ce7a32-8da0-45b9-073d-c8f7f938a971.png)

# 環境

tool|version
---|---
node|v14.7.0
npm|6.14.7
yarn|1.22.4
nuxt|2.14.1

# 対処

最新の依存パッケージをインストールし直すことで解決した。
nuxtのバージョンも`2.14.3`まで上がったので、nuxt側に何らかのバグがあったのかもしれない。

```bash
# 既存の依存パッケージとビルド成果物を削除
rm -rf node_modules/ dist/

# yarnの場合
rm yarn.lock
yarn install
yarn generate

# npmの場合
rm package-lock.json
npm install
npm run generate

# Firebase Hostingへデプロイ
firebase deploy
```
Django migrationに関するメモ


* アプリごとにmigrateを行う

        python manage.py migrate アプリ名


* migrationの履歴を確認する

        python manage.py showmigrations アプリ名


* migrationファイルを全て実行済み扱いにする

        python manage.py migrate --fake アプリ名


* migrationファイルを全て未実行扱いにする

        python manage.py migrate --fake アプリ名 zero


* 特定のmigrationファイルを実行する

        python manage.py migrate アプリ名 ファイル名
GCS FUSEを使いローカルディレクトリとGCSを同期させる ~Mac~

# GCS FUSE を使い GCE 内のディレクトリと GCS を同期させる ~Mac~

## 環境

```
MacOS X 10.15.5 (Catalina)
Homebrew 2.4.9
Google Cloud SDK 304.0.0
osxfuse 3.11.0
gcsfuse 0.30.0
```


# GCP アカウント登録

[【画像で説明】Google Cloud Platform (GCP)の無料トライアルでアカウント登録](https://qiita.com/komiya_____/items/14bd06d0866f182ae912)

# Google Cloud SDK のインストール

[Google Cloud SDK のインストール ~ 初期化](https://qiita.com/komiya_____/items/5af0dcc8639fad9fee29)

# プロジェクト作成

[Google Cloud SDK でプロジェクトを作成する](https://qiita.com/komiya_____/items/fb02f38e1886db280d52)

# FUSE の設定

## osxfuse のインストール

```sh
$ brew cask install osxfuse
```

## gcsfuse のインストール

```sh
$ brew install gcsfuse
```

パスが通らない場合はシンボリックリンクを作成
※ 冒頭に記載の環境ではインストール後自動でリンクがはられていたため下記操作は不要でした。

```sh
ln -s /usr/local/Cellar/gcsfuse/${インストールしたgcsfuseのバージョン}/bin/gcsfuse /usr/local/bin/
ln -s /usr/local/Cellar/gcsfuse/${インストールしたgcsfuseのバージョン}/sbin/mount_gcsfuse /sbin/
```

## PC 側のセキュリティ設定

### osxfuse の許可

システム環境設定 > セキュリティとプライバシー > プライバシー > フルディスクアクセス

![スクリーンショット 2020-08-14 16 26 54](https://user-images.githubusercontent.com/63569663/90224818-3f0dbd80-de4b-11ea-8fea-e8b1c4f77866.png)

### アプリケーションにフルディスクアクセス権限を付与

システム環境設定 > セキュリティとプライバシー > プライバシー > フルディスクアクセス
から、利用するアプリケーションにチェック
下記は`iTerm`と`VSCode`にアクセス権限を与えている例です。

※ フルディスクアクセス権限は macOS Mojave から導入されたセキュリティ機能。
許可したアプリケーションのみ重要データにアクセスすることができるように管理。

## アプリケーションの認証

アプリケーションが API にアクセスするための認証。

```sh
gcloud auth application-default login
```

確認

```sh
gcloud auth application-default print-access-token
```

Token が出力されれば OK です。

### マウントするディレクトリを作成

```sh
$ mkdir ./test
```

### GSC バケットを作成

```sh
$ BUCKETNAME='your-bucket-name'
$ gsutil mb gs://$BUCKETNAME
```

### 対象ディレクトリを GSC バケットにマウント

バケットの指定に`gs://`は不要なので注意。

```sh
$ gcsfuse $BUCKETNAME ./test
```

### 確認

ファイルを作成

```sh
$ touch ./test/test.py
```

バケットの中身を確認

```sh
$ gsutil ls gs://$BUCKETNAME

gs://your-bucket-name/test.py
```

同じファイルが入っていれば OK です。

#### 中身がある場合はどうなる？

ローカルディレクトリの中身がGCSバケットと同じ状態になります。
ローカルディレクトリにファイルなどが入っていた場合、削除されてしまったように見えますが隠れているだけです。
下記手順でマウントを解除することで元の状態にもどります。


### マウントを解除

アンマウントする場合も`gs://`は不要。

```sh
$ umount $BUCKETNAME
```

#### マウントしたディレクトリを削除

マウントした状態のディレクトリは削除できないので、アンマウントしてから削除するようにします。
マウント中に削除しようとすると、このようなエラーが出ます。

```sh
rm -rfi ./test

rm: test/: Resource busy
```

## GCE上でやってみる

こちらもよろしければ

[GCS FUSEを使いGCE内のディレクトリとGCSを同期させる ~GCE x Ubuntu~](https://qiita.com/komiya_____/items/b3969dd5018b18b7ad04)

## おしまい

最後まで読んでいただきありがとうございました。
ブラウザ上の文章に蛍光ペンを使ってマークする

# デモ

次のCodePenの文章上をマウスを左クリックして、文字を選択してみてください。
選択した部分が黄色く残ります。

<p class="codepen" data-height="565" data-theme-id="light" data-default-tab="result" data-user="ledsun" data-slug-hash="xxVOvoQ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="マウス選択した文字をマークする">
  <span>See the Pen <a href="https://codepen.io/ledsun/pen/xxVOvoQ">
  マウス選択した文字をマークする</a> by shigeru.nakajima (<a href="https://codepen.io/ledsun">@ledsun</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 実装
## 黄色

選択した文字を黄色くするには[mark](https://developer.mozilla.org/ja/docs/Web/HTML/Element/mark)タグを使います。

## markタグの追加

テキストが選択されたら、JavaScriptでmarkタグを追加します。
選択領域の取得には[Selection](https://developer.mozilla.org/ja/docs/Web/API/Selection)を使います。
指定した範囲をタグで囲うには[Range.surroundContents](https://developer.mozilla.org/ja/docs/Web/API/Range/surroundContents)を使います。



```js
const text = document.querySelector('.text')

// text でなく document.body を監視しないと
// 選択領域上でmouseupしたとき
// 選択しつつtext外でmouseupしたとき
// を拾えない
document.body.addEventListener('mouseup', () => {
  const selection = window.getSelection()

  if (selection.type === 'Range') {
    // 選択領域の選択開始位置のNodeと選択終了位置のNodeを取得
    const anchorNode = selection.anchorNode
    const focusNode = selection.focusNode

    // 選択開始位置と選択終了位置のNodeが同じでないと、タグで囲えない
    if (anchorNode === focusNode) {
      // markタグ内にmarkタグを作らないように、textの子を選択したときだけ
      if (anchorNode.parentElement === text) {
        const range = document.createRange()

        // 後ろから前に選択したときは、無効なrangeになる。
        // 今回は気にしない。必要であれば、anchorOffsetとfocusOffsetを入れ替えれば良い
        range.setStart(anchorNode, selection.anchorOffset)
        range.setEnd(anchorNode, selection.focusOffset)

        const mark = document.createElement('mark')
        range.surroundContents(mark)
      }
    }
  }
})
```
NVIDIA GPU で infoROM is corrupted at  gpu ワーニングのメモ

中古で買った GTX TITAN(Kepler)で発生.
 
Linux で nvidia-smi とすると

WARNING: infoROM is corrupted at gpu という warning が出る.

Windows だと出ない.

## 原因

https://github.com/NVIDIA/gpu-operator/issues/20

何らかの理由(経年劣化によるメモリ一部破損, firmware 書き換え?)でチェックサムが合わないときに出る模様.

保証期間内なら交換でしょうか.

中古や保証期間切れのなどの場合は特に機能制限がかかるわけではないようなので, 普通に使える(e.g. CUDA/OpenCL アプリ)場合は無視してもよさそうです!
【Xcode】requires a development team. Select a development team in the Signing & Capabilities editor.エラーが出た時の対処法

>Showing Recent Messages
Signing for "Unity-iPhone" requires a development team. Select a development team in the Signing & Capabilities editor.

UnityからiOS向けビルドした際の話。
Xcodeビルド時に上記のようなエラーが出た時は、`BuildSettings > Signing > Development Team`の未選択状態が原因です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/a3c9e426-bb70-c994-ffca-078641f9a353.png)

選択し直すと正常にビルドは通るようになりました。

## 環境

Unity2019.4.4f1
Xcode 11.6
macOS Catalina 10.15.5
Vue.js+axiosでAPIを叩く時のパラメータをCamelCase・snake_caseに変換してみた

今回、vue.jsでaxiosを使ってAPIを叩く際に、GET・POSTのリクエストパラメータやPOSTのレスポンスパラメータのkey名を自動でキャメル・スネークケースに変換するコードを実装しました。

<h2>実現したいこと</h2>
POST/GETのリクエストパラメータ
<pre> 
変換前
{
  "userId" : 1,
  "accountDate : "2020-08-01"
}

変換後
{
  "user_id" : 1,
  "account_date : "2020-08-01"
}
</pre>

POSTのレスポンスパラメータ
<pre>
変換前
{
  "user_id" : 1,
  "account_date : "2020-08-01"
}

変更後
{
  "userId" : 1,
  "accountDate : "2020-08-01"
}
</pre>

【実行環境】
vue.js 2.5.17
axios 0.19
laravel 7.0
laravel/passport 9.3

<h2>事前準備</h2>

まず、今回はライブラリのlodashを利用します。
laravelプロジェクト内で「npm install」を実行すれば自動的にインストールされていると思いますが、もし入ってない場合は

<pre>
npm install lodash
</pre>
でライブラリをインストールする必要がります。

<h2>axiosの設定を変更する</h2>
 今回はlaravelプロジェクト内でvue.jsを利用しています。
laravelプロジェクト内でaxiosの設定は「resources/bootstrap.js」で行えます。


```js:resorces/bootstrap.js
// ライブラリを読み込む
window._ = require('lodash');

// 初期設定
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

// 下記コードを追記
const mapKeysDeep = (data, callback) => {
    if (_.isArray(data)) {
        return data.map(innerData => mapKeysDeep(innerData, callback));
    } else if (_.isObject(data)) {
        return _.mapValues(_.mapKeys(data, callback), val =>
            mapKeysDeep(val, callback)
        );
    } else {
        return data;
    }
};

const mapKeysCamelCase = data =>
    mapKeysDeep(data, (_value, key) => _.camelCase(key));

const mapKeysSnakeCase = data =>
    mapKeysDeep(data, (_value, key) => _.snakeCase(key));

axios.interceptors.response.use(
    response => {
        const { data } = response;
        const convertedData = mapKeysCamelCase(data);
        return { ...response, data: convertedData };
    },
    error => {
        console.log(error);
        return Promise.reject(error);
    }
);

axios.interceptors.request.use(
    request => {
        // GETでパラメータを送る時
        if(!_.isEmpty(request.params)){
            const convertedData = mapKeysSnakeCase(request);
            const convertedParams = mapKeysSnakeCase(request.params);
            return { ...request, data: convertedData, params: convertedParams }

        // POST送信時        
        }else{
            const { data } = request;
            const convertedData = mapKeysSnakeCase(data);
            return { ...request, data: convertedData };
        }
    },
    error => {
        console.log(error);
        return Promise.reject(error);
    }
);
```
interceptors.response.useとinterceptors.request.useで、それぞれaxiosを実行する前、後に行う処理を追加しています。

実際にkey名を変換しているのは、_.camelCase(key)と_.snakeCase(key)です。
mapKeysDeepで、再帰的にkeyを取得しているので、key・valueの階層が深くても、全てのkeyを取得・変換できます。



・今回のコードを書く上で参考にしたサイト

<a href="https://qiita.com/reflet/items/d5658d5d69e8e1ccd489">axiosライブラリを使ってリクエストする</a>
<a href="https://qiita.com/buntafujikawa/items/78e9204cc9ea7eaabd3d">axiosのinterceptorsで、リクエストの前処理を共通して行う</a>
<a href="https://qiita.com/kobakazu0429/items/160379f95ac5674b27b7">AxiosでAPIレスポンスをcamelCaseに変換するお話</a>
json-serverでstaticを指定してもプレビューのページを表示する

## json-server
わたしは自分のことをxRアプリエンジニアだと思っていたのですが、最近はいろんなサーバをいっぱい立てています。
そのうちのモックサーバなんてjsonを返せればいいので[json-server](https://github.com/typicode/json-server)を使いました。

> Get a full fake REST API with zero coding in less than 30 seconds (seriously)

が嘘じゃないすごいやつです。
あと、たのしい顔文字がいっぱい出力されます。

## `--static`の罠

![2020-08-08 02.02.01 localhost 65269d951fd9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/69386e82-39ff-5445-5b3b-e32ce7ba552e.png)

[http://localhost:3000](http://localhost:3000)

にアクセスするとこんなページが出てきて現在の設定を確認することができます。
`CLI`でも確認することはできますが、ブラウザで手軽に可視化して、クリックでAPIのレスポンスも確認できるので、これがあると楽です。
ですがこのページ、`public`フォルダを実行ディレクトリに作成するか`--static`でオプションを渡して静的ファイルを指定すると見られなくなってしまいます。

![2020-08-18 23.54.57 localhost 7211da89cc19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/ef0b9472-c0cb-e285-b939-c359c64254db.png)

なぜかというと、ページの最後に書いてある以下の設定が適用されて、上書きされた空のパスにアクセスしてしまうためです。
> To replace this page, create a ./public/index.html file.

## 解決法

### （（（何事も暴力で解決するのが一番だ）））

![output-palette.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/5c09d555-ee78-e49d-5c58-f73689a647c6.gif)

`-g`でインストールしていれば、目指すファイルは以下のパスに入っています。
`/Users/***/node_modules/json-server/public`
なのでそれをぶっこ抜いて自分が静的ファイルを格納している場所に展開してしまえばいいのです。

### middleware

`json-server`には`middleware`のオプションもあります。
なので「特定のURLが要求されたら`node_modules`内のファイルを読み込んで返す」`middleware`を作れば返すこともできます。

[gist](https://gist.github.com/nekomimi-daimao/e86023cb7305d7cd42a8e2aa34132c26)

```js:home.js
const fs = require('fs');

const moduleId = "json-server";
const serveUrl = ["/", "/script.js", "/style.css", "/favicon.ico",];

module.exports = (request, response, next) => {
    if (serveUrl.includes(request.url)) {
        const fileName = request.url == "/" ? "/index.html" : request.url;
        const path = require.resolve(moduleId).split(moduleId)[0] + moduleId + "/public" + fileName;
        fs.readFile(path, (err, data) => {
            if (!err) {
                response.end(data);
            }
        });
        return;
    }

    next();
}
```

起動するときの引数に`-m`でこの`module`を指定してやればOKです。

`json-server --watch db.json --routes routes.json -m home.js`
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/7dd95d3f-ccfc-4799-6662-be6a629771e4.png" width=50%>
なんでか絵文字が大変なことになってますが動いてっからよォ！

## まとめ
どちらの解決法も**暴力で解決している**ことには変わりないので、より*スマートな暴力*である最初の方法がよいと思います。殴ればわかる。

ちなみにわたしが考える`json-server`のベストプラクティスとしては、下手に`module`として扱ったりせずに、`CLI`で運用して`middleware`で細かいところを補うのがよいと思っています。
ただ、`json-server`のレスポンスをフックして改造したい場合はどうも`middleware`ではできないように見えたので、結局わたしはガシガシ書いて改造する羽目になりました。

で、この記事の本題なんですけど同じ作者の[hotel](https://github.com/typicode/hotel)を使うとローカルサーバのssl化が簡単だよ！　って書いてあるんですが、やり方よくわかんないので詳しい人書いといて！[^googlability]

おしまい。


## 参考
[今更使うJSON Server](https://qiita.com/Lurium/items/313f8f770a710b5ed188)
[json-server に、express ミドルウェアを指定するオプションが追加された](https://qiita.com/zakuro9715/items/fbc0dfe98c304b880f31)
[NodeJSのrequireがどのファイルを探索しているのかを調べる](https://himenon.github.io/javascript/require-resolve/)

[^googlability]: 名前のせいで検索してもホテルしか出てこないの困る
LeapMotionとLuppet体験版を動かすまでの備忘録

Luppet(ラペット)というものを知ったので、手元に5年以上前に購入したLeapMotionもあったためサクッと試してみるという記事です。

>WebカメラとLeapMotionで完結する、バストショット特化の3D VTuber向けトラッキングシステム

LuppetとはWebカメラとLeapMotionを使用します。

## LeapMotion SDKのインストール

Luppetの前にLeapMotionが動かせる状態を作っていきます。

[Leap Motion Developer](https://developer.leapmotion.com/)
公式サイトからLeaepMotionのSDKをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/d3afdd2b-c096-b23c-5d65-2e308078368b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/491d9895-1901-3371-6629-359dc1cd0148.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/5ac1f772-249d-146e-ad41-ba687e66a71b.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/06ade84e-57f6-5d8b-5c66-f40b7b83e901.png)

ダウンロードが完了したらインストーラーを実行してインストールします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/61e9e97e-2aad-e38b-45e3-3359e5d56667.png)

次へを何回かクリックするとLeapMotionのインストールは完了です。


## Luppetのインストール

今回は体験版を試します。

[Luppet - 合同会社ラペットテクノロジーズ - BOOTH](https://negipoyoc.booth.pm/items/1196507)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/4d62654c-bbd1-fd64-6a26-8fe16d29f5ad.png)

無料ダウンロードをクリックしてダウンロードします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/541b3db7-dbee-b10e-180a-9f61c0a0178e.png)

Luppet.exeを実行。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/5293d0fe-ef31-d851-24a5-bf252e22a55a.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/c34ccbae-181a-0e79-9d3e-f671aae12b53.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/72d15fc3-6d18-c154-1305-a570ff9a4d7e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/cb7094ae-b985-582c-4d3e-4e3cffb98a66.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/e39922ab-e77a-0b2e-4d4a-ddc05ab6a94e.png)
`ログインせず体験版を始める`をクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/dbd6c8b1-0db1-f40c-4453-f9715298435e.png)
モデルは同梱されているShibuさんを使わせてもらいます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/852d1590-bab6-bfec-9dac-d0905de047e6.png)
設定する項目がいくつかありますが、重要なのはこのLeapMotionの設定でした。
キャラの手が体に突き刺さるのを、ここで調整できます。




## トラブルシューティング

LeapMotionがLuppetに認識されないという状態に遭遇しました。
おそらくLuppetを起動したまま、LeapMotionSDKをインストールしたのが原因だと思うので、Luppetを起動しなおすと認識されました。

## 最後に

軽く触った感じ、あまりこの界隈の技術的知見がなく客観性はありませんが、主観として凄く良く出来ているツールだと思いました。

- リップシンク
- 自分とキャラの向きの同期
- LeapMotionによる手、指の同期

これらがLuppetとLeapMotionだけで(簡単セットアップで)動いてしまうのが凄いなと。

体験版ではキャラ画面に透かしがガッツリ入ってしまって見た目の確認がよくできませんでした。
早速個人ライセンスを購入してガッツリ検証していこうと思います。

※キャラ画面はESCトグルで切り替えられました(izmさんありがとうございます。Twitterで教えて頂きました^^)


## 環境

- Windows10
- LeapMotion SDK 4.0.0
- Luppet ver1.9.0
Elasticsearch 7.9.0で追加された Data streams機能が気になった


## きっかけ

Elasticsearch 7.9.0のリリースノートを読んでいて、ILM周りのにdata streamsという言葉がいくつか書いてあり、7.9.0で追加されたようなので、興味をそそられ調べてみました。

[Elasticsearchバージョン7.9.0 | Elasticsearchリファレンス[7.9] | 弾性](https://www.elastic.co/guide/en/elasticsearch/reference/7.9/release-notes-7.9.0.html)

## Data streams

### Data streamsの概要

これまで、時系列データを時間やサイズごとにindex分割し、aliasを使って書き込みや読み込みをいい感じに処理していた、一連のindex運用を改めて提供する機能のようです。

公式リファレンスに図とともに説明されていますので、詳しくはそちらをご参照ください。
[Data streams | Elasticsearch Reference [7.9] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/7.9/data-streams.html)

### Data streamsの開発動機

時系列indexの分割やaliasを用いた一連の運用手法は、rollover / shrink APIやIndex Lifecycle Management(ILM)やその他ElasticStack全体として少しずつ改善を進めていて便利になってきたなあと個人的には感じていましたが、[Data Streams · Issue #53100 · elastic/elasticsearch](https://github.com/elastic/elasticsearch/issues/53100)の冒頭にaliasの概念や実装に問題があり、利用者が混乱をきたしていると書かれています。

> Data streams are targeted towards time-based data sources and enable us to solve bootstrap problems when indexing via a write alias (logstash-plugins/logstash-output-elasticsearch#858). Today aliases have some deficiencies in how they are implemented in Elasticsearch; namely they are not first-class concepts, making them confusing to use. Aliases have a broad type of usages, whereas data streams will be a solution focused for time-based data sources. Data streams should be a first-class concept, but should also be non intrusive.

そのような中で、Data stremasはaliasを用いた時系列データのindex運用を第1級の機能として提供するとのことです。

個人的にも、検索用aliasに紐づいている一部の削除候補indexをcloseすると、aliasを使った検索がエラーになった覚えがあり、扱いが難しい印象を持っていました。ILMを使うと、手作業不要なのでそれも無いと思いますが、そういった一連の操作を簡単にしていく方向性をData streamsという機能で示されていると感じました。

### Data streamsの使い所

リファレンスにもきっちり書いてあり、使い所をは下記の通りです。

- 大量の時系列データを扱う
- ILMを使用してインデックスの管理を自動化することにより、運用コストを下げたい
- データを格納した後に削除や更新がほとんどない

所感としては、7.9.0の段階ではFilebeatやLogstash、Logstash plugin側の対応が無いように見えますので、すでに上記の状況でも困っていなければ、新たにData streamsに移行するメリットはあまり無いように思えます。これから新しいデータを取り込むといった場合であれば、新しい物が好きな方は是非チャレンジしてみてはいかがでしょう。

余談ですが、ILMが無い頃に自作のShellスクリプトで上記のような運用を自動化していて、使い勝手もそんなによく無い上に、自分の汚いShellスクリプトを早く消し去りたいので、なるべく早くData streamsへの移行したいと思います。

## まとめ

時系列データの運用について、ElasticStack全体で整合性が取れた機能を提供する礎として、今後しばらくData Streamsに注目です。
フォルダの中身をまるごとGithubにアップロードする手順


#はじめに
独学でプログラミング学習をしていく過程で、GitHubは使えた方が良いと言われたので、
自分用のメモも兼ねて超基本的な使い方について書いておこうと思います。

初心者の覚書的なモノなので、間違い等があるかもしれません。
間違いや問題があったら指摘してください。

#ローカル環境で作成したファイルを、ターミナルを利用してGithubにアップロードする方法

```terminal:①ディレクトリの移動
[コンピュータ名]@MacBook-Air % cd [アップロードしたいディレクトリ] (enter)
```

```terminal:②リポジトリの初期化
[コンピュータ名]@MacBook-Air % git init (enter)
```

下記のいずれかのメッセージが出ればOK

```terminal:②'新規で空のリポジトリが作成された場合
Reinitialized empty Git repository in /Users/[ユーザー名]/[指定ディレクトリ]/.git/
```
```terminal:②'Gitリポジトリは既に作成されているので、新規作成する必要ない場合
Reinitialized existing Git repository in /Users/[ユーザー名]/[指定ディレクトリ]/.git/
```

```terminal:③現在のディレクトリにあるファイルをaddする
[コンピュータ名]@MacBook-Air % git add . (enter)
```

addと.の間に半角スペースが必要なので忘れないように。

```terminal:④addしたファイルをコミットする
[コンピュータ名]@MacBook-Air % git commit -m "[任意のコメント]" (enter)
```

```terminal:⑤リモートリポジトリの登録
[コンピュータ名]@MacBook-Air % git remote add origin [GithubのリポジトリURL] (enter)
```

`fatal: remote origin already exists.`のエラーが出た場合
参考→[fatal: remote origin already exists. と表示された場合の解決法](https://qiita.com/yu-ki0718/items/3c8aae2c81ca3f82f522)

```terminal:⑤'エラーが出てリモートリポジトリが登録できない場合
[コンピュータ名]@MacBook-Air % git remote rm origin (enter)
```

GithubのリポジトリURLは下記の場所で確認できます。
![200819.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597055/950d94d4-3289-6668-09ff-c6dae4158f8d.png)

```terminal:⑥ローカルリポジトリのファイルをアップロード(push)
[コンピュータ名]@MacBook-Air % git push -u origin master (enter)
```

`error: failed to push some refs to`のエラーが出た場合
参考→[GitHubにpushする時にerror: failed to push some refs と表示されてpushできない時](https://qiita.com/kazuki0714/items/ceda3a6721a9a99082de)

```terminal:⑥'エラーが出てpushできない場合の強制push方法
[コンピュータ名]@MacBook-Air % git push -f origin master (enter)
```

以上でファイルのアップデートは完了です(たぶん)

#ローカルリポジトリを削除する方法
作業の途中でうまくいかなくなったりして、最初からやり直したい時とか。


作業するディレクトリに移動した状態で、

```terminal:ローカルリポジトリを削除
[コンピュータ名]@MacBook-Air % rm -rf .git (enter)
```

このあと①からやり直せば、ちゃんとできるはず…

勉強させていただいた記事
・[GithubにTerminalからプロジェクトをcommit, pushする](https://qiita.com/ka0ru19/items/1a8ff0fb9e945ef01256)
・[ローカルのディレクトリをGithubへアップロードする方法](https://note.com/koushikagawa/n/nfccf06fa845b)
・[gitのローカルリポジトリを削除する方法](https://www.codeadvisor.jp/entry/2018/02/18/124557)
Pytorch 学習済みモデルで識別[MNIST]

##初めに
- PytorchでCNNを構築し，MNISTデータセットを学習した。
- 学習したモデルを読み込んで使うプログラムを組んだ。(意外と記事少なかった)
- モデルの作成は以前記事にしたのでよかったら是非。( [こちら](https://qiita.com/TKC-tkc/private/42ff569be496621fc016) 参照)

<対象>
- 機械学習初心者(細かい内容についての解説はしません)
- PyTorch触り始めた方
- アバウトな解説でも耐えられる方
<非対象>
- Pytorch詳しい方
- 精度向上したい方

[環境]
Python 3.6.9
torch 1.6.0
numpy 1.16.4
Pillow 6.2.0

##モデルの保存
```python
PATH = "./my_mnist_model.pt"
torch.save(net.state_dict(), PATH)
```

学習済みモデルを保存する。
`torch.save()`の引数を`net.state_dict()`とすることによりネットワーク構造や各レイヤの引数を省いて保存する。これにより保存したモデルの容量を削減することができるらしい。
逆に言うとモデルをロードする側はネットワーク構造を記述する必要がある。

##モデルを利用する
```python
import torch
import torch.nn as nn
import torch.nn.functional as f
import torchvision
from torchvision import datasets, transforms
from PIL import Image, ImageOps
from torchsummary import summary

# モデルの定義
class MyNet(nn.Module):
    def __init__(self):
        super(MyNet,self).__init__()
        self.conv1 = nn.Conv2d(1,32,3,1)
        self.conv2 = nn.Conv2d(32,64,3,1)
        self.pool = nn.MaxPool2d(2,2)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(12*12*64,128)
        self.fc2 = nn.Linear(128,10)

    def forward(self,x):
        x = self.conv1(x)
        x = f.relu(x)
        x = self.conv2(x)
        x = f.relu(x)
        x = self.pool(x)
        x = self.dropout1(x)
        x = x.view(-1,12*12*64)
        x = self.fc1(x)
        x = f.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)

        return f.log_softmax(x, dim=1)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = 0
model = MyNet().to(device)
print(device)
print(model)
print(summary(model, (1, 28, 28)))

# 学習モデルをロードする
model.load_state_dict(torch.load("my_mnist_model.pt", map_location=lambda storage, loc: storage))
model = model.eval()

# 画像ファイルを読み込む(黒背景, 白文字を想定)
PATH = "mnist/3.jpg"
image = Image.open(PATH)
image = ImageOps.invert(image)
image = image.convert('L').resize((28,28))
# データの前処理の定義(モデル生成の際と同じ平均値と標準偏差で正規化する)
transform = transforms.Compose([
                                transforms.ToTensor(),
                                transforms.Normalize((0.1307,), (0.3081,))
                                ])

# 元のモデルに合わせて次元を追加
image = transform(image).unsqueeze(0)

# 予測を実施
output = model(image.to(device))
_, prediction = torch.max(output, 1)
# 結果を出力
print("{} -> result = ".format(PATH) + str(prediction[0].item()))
```

##実行結果
結果①
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515626/5310fb34-04b1-edf8-214d-987051edfe4f.jpeg)

```
mnist/2.jpg -> result = 2
```

結果②
![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515626/68168f97-a194-ce08-caeb-a4c839e27ece.jpeg)

```
mnist/6.jpg -> result = 6
```

##まとめ
なんかうまくいってる雰囲気。
PyTorchはOpenCVではなくPillowを使う場合が多いみたい。
モデル自体の精度はあまり高くなかった。過学習してるのかもしれない。
(Capistrano)デプロイ後、本番環境でWe're sorry…のエラーが出てしまう

ローカル環境で問題なく動いたアプリを自動デプロイした際に、本番環境でエラーが出てしまいビューが表示されない
となると何をして良いかわからず絶望的な気持ちになりますよね。。。
![スクリーンショット 2020-08-17 8.01.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603218/327fd7c0-b9e2-b83f-8605-395f7351f4b0.png)
そんな時に解決方法の一つとして是非お試しください。

#結論: drop,createは手動で、migrateは自動で
ec2にログインをし、手動でコマンドを打ちデータベースのdrop,createだけを行います。
その後、Capistranoの自動デプロイでmigrateをさせるという方法でページが表示できるようになりました。

#コマンド
ec2にログインをしたら、まずは以下のコードを実行し、本番環境上でのデータベースの削除、作成までを行いましよう。

```
cd /var/www/<%アプリケーション名%>

cd current

rails db:drop RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1

rails db:create RAILS_ENV=production
```

その後、unicorn、mysqlの再起動も行います。(右側に長いコードです)

```
ps aux |grep unic 

//実行結果（番号は異なります）
ec2-user 24327  0.1 11.5 504288 116388 ?       Sl   22:46   0:02 unicorn master -c /var/www/<%アプリケーション名%>/current/config/unicorn.rb -E production -D                                                                                            
ec2-user 24334  0.0 12.3 651728 124368 ?       Sl   22:46   0:00 unicorn worker[0] -c /var/www/<%アプリケーション名%>/current/config/unicorn.rb -E production -D

kill -9 24327 //masterのプロセス番号24327を入力

sudo service mysqld restart　//mysqlを再起動
```

最後にローカルのターミナルに戻り自動デプロイ
`マイグレーションはこの時点で行われます。`

```
bundle exec cap production deploy
```

完了です！

#まとめ
特に特殊な操作は行なっていませんが、capistranoのmigrate機能を利用するという所がミソですね。
なぜこれでうまく行ったかはわかりませんが、これからも本番環境でのエラーは色々と試行をする必要がありそうです。。。
本当にAndroidのFragmentには空のコンストラクタが必要なの？


フラグメントに空のコンストラクタがなぜ必要なのかを、とっさに説明できなかったので、簡単にまとめてみた。


## 空のコンストラクタを作成しないとどうなるか
あなたが複数の引数をとるコンストラクタを持つFragmentを作ったとする。
そのFragmentは正常に動くだろう。
その後あなたはアプリをリリースする。

その後以下のエラーメッセージ付きのクラッシュ報告がたくさん上がってくる。
開発時はエラーなんて吐かなかったのに、古いAndroidを使い続けるユーザーが悪いんだとあなたはは思いつつエラー対応に当たることになる。

```
Unable to instantiate fragment 
make sure class name exists, is public, and has an empty constructor that is public
```

fuck you android(これは本当にそう)

## 正しい空のコンストラクタの作り方
とにかくFragment内部のコンストラクタをoverrideするのは止める。
常に空のコンストラクタを記述し、Fragment初期化時に引数を渡したい時のために
newInstanceメソッドを作成するのが良いだろう。

```java

public static final MyFragment newInstance(int title, String message){
  MyFragment f = new MyFragment();
  Bundle bel = new Bundle(2);
  bdl.putInt(EXTRA_TITLE, title);
  bel.putString(EXTRA_MESSAGE, message);
  f.setArguments(bel);
  return f;
}
```

そしてFragment内では以下のようにargumentを使用する。

```java

@Override
public void onCreate(Bundle savedInstanceState) {
  title.= getArguments().getInt(EXTRA_TITLE);
  message = getArguments().getString(EXTRA_MESSAGE);
}
```

作成したFragmentは以下のように使用する。

```java

getSupportFragmentManager()
  .beginTransaction()
  .replace(R.id.content, MyFragment.newInstance(
  R.string.alert_title,
  “Oh no, an error occurred””
  ))
  .commit();
```

## 参考
https://stackoverflow.com/questions/10450348/do-fragments-really-need-an-empty-constructor
Google Spread Sheetの情報を取得したメモ

## 概要
Google Spread Sheetの情報をAPIで取得した。

## 前提
* GCPに登録済
* プロジェクト作成済
* Spread Sheetは公開設定済
## 手順
* プロジェクトの[API利用ページ](https://console.developers.google.com/apis/library)から、Google Spread Sheet APIを使用できるようにする
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/80bd333c-b77b-ead8-ac45-91294401762f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/84eb8d95-936b-f7b2-4300-8fd427cdeec2.png)

* [認証情報のページ](https://console.developers.google.com/apis/credentials)にアクセス
* 認証情報を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/26a58301-02df-30e6-8d6d-de48be237993.png)
* APIキーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/619c286a-01cf-2a93-3a64-f04f85b952e4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/8096ac28-82bb-fe78-24bb-7bce8fce54b8.png)

* APIキーを制限

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/3fe4809e-533f-7398-f64b-bd71556b2f73.png)

* apiをhttps://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}/values/{SheetId}!{開始Cell}:{終了Cell}?key={API キー}で叩いて、jsonが返ることを確認する

## 参考

[Google spreadsheetの値を取得する](https://qiita.com/suisuina/items/a41932088acacea4835e)
[ElmでGoogle Spread Sheetの値を読み込んだメモ](https://qiita.com/hibohiboo/items/5f64637f511c74e157c1)
Java SE Bronze試験のテスト内容

**Java SE Bronze試験のテスト内容**
言語未経験者向けの入門資格。Java言語を使用したオブジェクト指向プログラミングの基本的な知識を有することを評価することを目的としている。


**1. Java言語のプログラムの流れ**
- 1.1.Javaプログラムのコンパイルと実行
  1.2.Javaテクノロジーの特徴の説明
  1.3.Javaプラットフォーム各エディションの特徴の説明

**2.データの宣言と使用**
  2.1.Java言語でのデータ型の説明(基本型、参照型)
  2.2.各種変数や定数の宣言と初期化、有効範囲
  2.3.配列(1次配列のみ)の生成と使用
  2.4.コマンドライン引数の利用

**3.演算子と分岐文**
  3.1.各種演算子の使用
  3.2.演算子の優先順位
  3.3.if、if/else文の作成と使用
  3.4.switch文の作成と使用

**4.ループ文**
  4.1.while文の作成と使用
  4.2.for文及び拡張for文の作成と使用
  4.3.do-while文の作成と使用
  4.4.ループのネスティング

**5.オブジェクト指向コンセプト**
  5.1.具象クラス、抽象クラス、インタフェースの説明
  5.2.データ隠蔽とカプセル化について説明と適用
  5.3.ポリモフィズムについての説明と適用

**6.クラス定義とオブジェクトの生成、使用**
  6.1.クラスの定義とオブジェクトの生成と使用
  6.2.オーバーロードメソッドの作成と使用
  6.3.コンストラクタの定義
  6.4.アクセス修飾子(public/privateに限定)の適用とカプセル化
  6.5.static変数及びstaticメソッドの定義と使用

7.継承とポリモフィズム
  7.1.サブクラスの定義と使用
  7.2.メソッドのオーバーライド
  7.3.抽象クラスやインタフェースの定義と実装
  7.4.ポリモフィズムを使用するコードの作成
  7.5.スーパークラスのコンストラクタまたはオーバーロードされたコンストラクタの参照型の型変換
  7.6.パッケージ宣言とインポート
プログラムを書くときの注意点：その３

プログラムを書くときの注意点：その３
----------------------------------------
<b>1.結論</b>
<b>2.リスコフの置換原則とは何か</b>
<b>3.なぜリスコフの置換原則が必要か</b>
<b>4.リスコフの置換原則はどう使うのか</b>
<b>5.ここから学んだこと</b>
<br>

1.結論
----------------------------------------
<b>リスコフの置換原則にも従う！
<br>

2.リスコフの置換原則とは何か
----------------------------------------
●リスコフの置換原則とは、

簡単にいいますと、<b>親クラスは子クラスと
同じ動きにしないといけない</b>

逆を言うと、子クラスが親クラスのメソッドの
挙動を変えてはいけないということです。
<br>


3.なぜリスコフの置換原則が必要か
----------------------------------------
結論としては、プログラミングを書く際の要は以下の
3つに集約されると思っています。

Ⅰ）保守性：修正（エラー発見のしやすさ）・管理のしやすさ
Ⅱ）拡張性：追加機能実装のしやすさ
Ⅲ）可読性：記述のわかりやすさ
が必要だと考えております。

上記3つのことは自分が他の4つの原則を説明する際に
同じことを言うので、５つの原則のうちどれかを読んでいただくと
結論はすべてこの３つに収まります。

つまり、上の3つを叶えるには
<b>リスコフの置換原則に”も（他の４つの原則もあるので）”従う！！</b>
<br>

4.リスコフの置換原則はどう使うのか
----------------------------------------
こちらも例を用いて説明いたします！

```ruby:リスコフの置換原則
class A
 def initialize(aaa)
 end

 def a
 end
end

class B < A
 def initialize(aaa)
  @bbb = aaa
 end
 
 def b
 end
end

================

class C < A 
 def initialize(aaa)
 @bbb = aaa
 @ccc = aaa
 end
 
 def a
 end
 
 def c
 end

```


```ruby:リスコフの置換原則ではない
class A
 def initialize(aaa)
 end

 def a
 end
end

class B < A
 def initialize(aaa)
  @bbb = aaa
 end
 
 def b
 end
end

class B < A 
 def initialize(aaa)
 @ccc = aaa
 end

================

class B < A
 def initialize(aaa)
  @bbb = aaa
  @ccc = aaa
 end

def a
 if ccc
 else
    ccc_a
 end

 def c
 end
end
```

”リスコフの置換原則ではない”の方に、
================の下に
classBにしていますが、
”リスコフの置換原則”の方に、
================の下に
classCに変換しています。

classBに一緒にするより、
classCに分けて原則に則っています。

 <br>

5.ここから学んだこと
----------------------------------------
i)リスコフの原則自体、まったく知らなかったので
　調べること自体にすごく価値がありました！

ii)親クラスと子クラスを連動はさせるものの、
子クラスから親クラスに影響を受けないようにすることがポイントでした！


<br>
Git for Windows(Git Bash)で起こる日本語ファイル名の文字化けを解決

# 最初に
WindowsでGitを使いたいときはGit for Windowsを使うことが多いが、
日本語ファイル名が文字化けしてaddできない問題が起こったので解決策をメモします。

# 環境
- Windows10
- GitBash設定：デフォルト
- GitBashターミナル：コマンドプロンプト
- Git for Windowsバージョン：Git-2.28.0-64-bit

# 解決策
以下のコマンドを叩いて解決しました。

``` 
git config --global core.quotepath false
```
[覚書] MVVM の各層と配置

これもオレオレ解釈ですが、
覚え書きで挙げていた MVVM の各層と構成要素、サードパーティーの配置、それぞれの役割を一旦まとめると、以下の図のようになります（と思っています）。

実際にプログラムを書いていると思惑通りにいかず、妥協を迫られることも間々あります。
たとえ脱線しても、何らかの指針があれば乖離を抑えることができるかもしれません。

![mvvm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561457/5a3685bc-fccc-0430-b918-fdf232d62e98.png)


今後新しい仕組みが登場すれば、これらの要素の関係はもちろん、MVVM という考え自体が様変わりすることも考えられます。
現状の UWP や WPF では MVVM による開発が推奨されていますが、その前の Windows Forms ではイベントドリブンが標準でした。
とは言え、過去の仕組みは不要になった訳ではなく、新しい仕組みが引き出しとして増えただけであって、その時々で最適なものにシフトすれば良いのだと思います。
これから先も定期的に起こるであろう変化に、柔軟に対応していきたいものです。
Azure Administrator Associate模擬試験問題サイトまとめ

## はじめに

国内でもAzure Administrator Associateの受検者が増え、
受験された方の体験談なども増えてきている。

本記事では、受験された方の体験談を元に模擬試験を利用できるサイトをまとめた。

## 無料サイト

* JPN試験 (日本語)
https://www.jpnshiken.com/

* EXAMTOPICS (英語)
https://www.examtopics.com/exams

* vceguide (英語)
https://vceguide.com/how-should-you-configure-the-app-4/

---

## 有料サイト

* Whizlabs (英語)
https://www.whizlabs.com
[Whizlabs紹介記事](https://ohina.work/post/whizlabs/)

* Skillcertpro (英語)
https://skillcertpro.com

* Certification Questions (英語)
https://www.certification-questions.com/practice-exam/microsoft/az-103

* クラムメディア (日本語)

https://www.crammedia.com/AZ-103-Microsoft-Azure-Administrator/p/444/260

* 練習テスト付き Microsoft Exam Replay
https://jp.mindhub.com/MCP-bundles-practice-test-vouchers-p/microsoft_exam_replay_pt.htm

* pluralsight
https://app.pluralsight.com/roleiq/roles/2dff9be4-04ef-454f-9a4c-0279aff97b4e?aid=7010a000001xDURAA2

---

## 実試験と模擬試験の違い

模擬試験ではWEBサイトの仕様上、選択問題しかでない。

実試験だと選択肢の順序を問う問題もでるので、設問で問われそうなソリューションの手順は概要だけなく、正確に暗記しておいたほうがよい。

---

## 合格者の学習ノートや体験談

* [AZ-103合格に向けて試験直前に読み込んだ公式ドキュメントとその要点
](https://qiita.com/piyonakajima/items/f99c3a50ad214d280391)

* [サブスクリプションおよびリソースを管理](https://ohina.work/post/az-103_sub/)

* [IDの管理](https://ohina.work/post/az-103_ad/)

* [仮想ネットワークの設定と管理](https://ohina.work/post/az-103_vnet/)

* [仮想マシン(VM)の展開と管理](https://ohina.work/post/az-103_vm/)

* [ストレージの作成と管理](https://ohina.work/post/az-103_storage/)

* [試験でよく出るリソース操作](https://ohina.work/post/az-103_deploy/)


* [Microsoftが試験配信ミス？AZ-103 合格したが異様に点数が低くひょっとしたら...
](https://qiita.com/mnoda/items/5ae5151ef6d99338254b)


* https://javarevisited.blogspot.com/2020/02/top-5-AZ-900-exam-Azure-Fundamentals-certification-practice-tests-and-mock-exams-to.html