OmniAICreator/Qiita-1.07M huggingface dataset:
Video Indexer ってどんなデータが抽出されるんだろう

自分が YouTube にアップロードしている動画を Video Indexer に処理させて、どんな分析結果がでるのか試してみます。
動画はこんな感じの料理動画です。(この外出自粛の機会にはじめたばかりですがチャンネル登録お願いします笑)
https://youtu.be/eF3xswnCGjk

Video Indexer には既存でサンプルが用意されており、非常にキレイに単語などが抽出されています。それらは Video Indexer が分析しやすいようにカスタマイズされたものや、カスタマイズモデルを使用していると思いますので、今回は自分の作成した動画を読み込ませてみて、どんな感じで分析されているか主観的に見てみたいと思います。
では早速試してみたいと思います！

#結果
顔が映っていない動画なので、顔認識、感情分析はされませんでしたが、以下のような結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/d4c84eea-1cd0-47fc-5ef9-347663867a74.png)
##Topics
動画の中で取り上げられている Topics を認識した結果は以下のようになりました。なぜかニンニクが抽出されましたね笑
まぁでも、野菜、ショッピング、という大きな項目はあながち間違っていないですね。脱毛ってなんだろう、、おそらく、オマール貝を洗っているときに、藻のようなものを抜いていたからからな、、笑
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/846fcfd1-d718-a8b3-fc76-1187d4e33e64.png)
##Labels
Label は以下のような結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/0fa15109-6b7b-96b7-c55c-519c26ab3c14.png)
かなり細かく Label が張られるんですね。これは認識したものにすべて貼られるようです。1度しか出てきていないものにもラベルが張られています。
##Named Entities
Named Entities とは、`自然言語処理 (NLP) を使用して、音声および視覚テキストからブランド、場所、および人物を抽出します` の様です。つまり今回のような音声をあとから吹き込んだ動画に関しては、ビデオ、オーディオのマルチ分析がうまくできないため、あまり良い結果が出ないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/bb1493e8-abe5-145b-4926-3762ecefeca9.png)
##Scene
シーンは特に代わり映えないですが、こんな感じでした。場面が変わるような動画でないとあまり面白い結果はでないですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/d3d7ea9e-8e4c-4c82-6dc7-5c1be0faad0c.png)
##Timeline
タイムラインはこんな感じですね。これは音声認識で文字お越しをしているので動画は関係ないです。精度はまずまずといったところでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/3ea0e852-2fd0-6374-c56d-82b04d8515ed.png)
でも正直まだ微妙なところも多く、例えば以下の部分とかはしっかり認識した欲しかったですね、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/7acfa108-6d98-0d3d-ce47-56aa3c309b8a.png)

```
(誤)Nさあ始めました。魚さばくチャレンジ本日は十七匹目を回るが、いいでございます。
(正)さあはじまりました。さかなさばくチャレンジ、本日は17匹目、オマール貝でございます。
```
いい、とは、、？笑

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/77fa755e-eaf6-754c-4051-046714eecd9d.png)

```
(誤)そしたらですね。フライパンにオリーブオイルしてあげまして、その上にニンニクですね。辞めていきます。
(正)そしたらですね、フライパンにオリーブオイルを敷いてあげて、その上にニンニクを炒めていきます。
```
ニンニクを辞める、とは、、？笑

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/ee2ac913-d653-9a10-1d05-7f3355ea279d.png)

```
(誤)白いんですね。白ワインを入れて、ちょっとエビの色が変わるぐらいまでにしてあげます。汐音加えながら味を調整しつつ炒めていきます。
(正)次にですね、白ワインをいれて、ちょっとエビの色が変わるぐらいまで熱してあげます。塩を加えながら味を調整しつつ炒めていきます。
```
汐音ってなんかおしゃれ、、、笑

#結論
活舌の問題もありますが、日本語の音声認識精度はもう少しといったところです。
ただ、API で色々カスタマイズして使えそうですし、最近もアップデートが多い Video Indexer なので今後も色々試して使ってみたいと思います！

参考情報 : [Video Indexer](https://www.videoindexer.ai/)
参考情報 : [さかなさばくチャレンジの YouTube チャンネル](https://www.youtube.com/channel/UCx792-Hy-d4vna0K7OgzpOw) 登録お願いします！笑
Andoroid端末上でNode.jsアプリを実行してみた

# 概要  
コロナの関係で妻と二人在宅勤務を実施中。2階で仕事をしている妻が送ったメッセージ（コーヒーが飲みたい、など）を1階リビングのgoogle homeに喋らせるシステムをNode.js、Node-REDで作成した。自宅に‎Raspberry Piが無いためPC上でシステムを動作させていたが、PCの変わりにスマホ上で動作させられないかと考え、本対応を実施。
# 環境  
 * 端末  
   * Android 9  
 * Androidにインストールしたアプリ  
   * [Termux](https://play.google.com/store/apps/details?id=com.termux&hl=ja)：Android上でLinuxターミナルを実行するためのアプリ。root化不要。無料アプリ。
   * [WiFi Keyboard](https://play.google.com/store/apps/details?id=com.volosyukivan&hl=ja)：PCのキーボードでスマホの入力が可能。  
   * [Termux:Boot](https://play.google.com/store/apps/details?id=com.termux.boot&hl=ja)：Nodeアプリ、Node-REDの自動起動に利用。有料アプリ。  
 * Termux上でインストールしたアプリ  
   * Node V14.0.0
   * npm 6.14.4  
   * Node-RED   

# 構成  
Termuxにnode.js、npm、Express、Node-REDをインストール。  
Node-REDの`node-red-contrib-cast`ノードを利用しPOSTしたメッセージをgoogle homeに喋らせるWEB APIを作成。  
Expressでメッセージ入力用の簡単なページを作成し、入力されたメッセージをWEB API経由でgoogle homeに送信する。

# 実施内容  
## 必要なアプリのインストール  
  1. Termux  
    Android上でNode.jsを動作させるため、初めは[Dory - node.js](https://play.google.com/store/apps/details?id=io.tempage.dorynode&hl=ja)を試したが、Node.jsのバージョンがv6と古く、アップデートする方法がわからなかったため断念。v6だとNode-REDがインストールできない。Termuxは最新のNode.jsがインストールでき、Node-REDも問題なくインストールできた。ちなみにNode-REDの[公式ページ](https://nodered.jp/docs/getting-started/android)でもTermuxを利用することが推奨されている。  
  1. Node、npm、Express  
    Termuxのターミナルから通常の手順でインストール可能。WiFi Keyboardを利用するとコマンド入力が楽になる。
  1. Node-RED  
    [公式ページ](https://nodered.jp/docs/getting-started/android)掲載の手順でインストール。フローの編集はPCのブラウザから`http://スマホのIPアドレス:1880`にアクセスして実施
  1. Termux:Boot  
    Google Playからインストール（有料）。インストール後、アプリの説明欄に従い、ホームディレクトリは以下に`~/.termux/boot/ `の様にディレクトリを作成。このディレクトリに後ほど自動起動用のスクリプトを作成する。  

## Node-REDでgoogle homeへのメッセージ送信APIを作成  
  基本的な手順は以下のページを参考に実施。  
https://qiita.com/dozensofdars/items/6cec7db44636374b5382  
今回Node.jsアプリからPOSTできるようにするため、node-red-contrib-castノードの前後を`http in`ノードと`http response`ノードで挟めばOK。`http response`ノードを設定しないと、APIを呼び出したままアプリがだんまりになってしまうので注意。アプリからは`message`パラメタにgoogle homeに喋らせたい文言をセットしてPOSTするよう実装する。  
##  メッセージ入力用ページの作成  
  Expressでメッセージ入力ページ、メッセージ送信結果表示ページを作成。詳しい説明は割愛。  
##  Termux:Bootの設定  
  NodeのアプリとNode-REDの自動起動のためTermux:Bootの設定を実施。`~/.termux/boot/ `ディレクトリ配下に任意の名前でファイルを作成し、以下の様にコマンドを記載。これでスマポ起動時に自動的にNode-REDとNodeアプリが実行される。  

```  
node-red    
node (Nodeアプリ配置フォルダ)/bin/www  
```  

以上
YouTrack を良い感じに設定する方法

## 概念

```
Project > Board > Sprint
Project > Board > Swimlane
```

みたいな感じ。

Project に対して Card は連番がつく

## どの Board を選択するか

Scrum Board で。

## Backlog column

Board Settings > Columns and Swimlanes > Backlog を Add する

default の Backlog は Swimlanes の概念がなく使いにくい。

## TimeTracking

Edit Project > Time Tracking > Enable time tracking

## Estimation field > Story points

Board Settings > Estimation field > Story points

## Card 一覧で表示する Field を設定する

Board Settings > Custom fields

Assignee
Story points
Spent time

## Swimlanes

作ってる機能毎に Swimlanes つくるとまとまりが良い感じ。
コードを書かずにAIを構築してみる ー リベンジ編

[前回](https://qiita.com/y_k_individual/items/4e780356d8cc5c3b8590)と同様、六角ボルト長の判別を行う

## 学習データの作成

[前回](https://qiita.com/y_k_individual/items/4e780356d8cc5c3b8590)は過学習が起きていたと考えられる  
過学習を解消するためにも、今回はデータ拡張前のデータ数確保に重点を置いた

### カメラアングルの限定

- カメラアングルは上方からのみとし、45°より寝かせた角度は学習不要とする
![angle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/7dcef6bc-ab05-d4ab-89b1-ca9a0ea87e5a.png)


### 学習データ数の確保

- 真上から45°までの撮影角度を４分割する
![view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/376dc4c9-7bcc-3a83-d8fa-2e9ee6f04e84.png)

- 取りうる光源の位置を考慮し、それぞれの光源下でのデータを準備する
![view_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/810a37e2-8c8c-065b-2086-33e41d6c80fa.png)


- 撮影方向を前回より増し、16方向から撮影する
![view_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/1d98f23c-67fd-d789-30c0-b3dfd3cd98ee.png)


## 学習

[前回](https://qiita.com/y_k_individual/items/4e780356d8cc5c3b8590)に同じ

### 学習結果評価

![study_result_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/a802ae74-c176-6cc0-2c8e-2a8279f4c766.png)


[各パラメータの意味](https://qiita.com/dl_from_scratch/items/4efdf647b397d794cd67)

学習セットの一部をテストデータに使う設定の場合、テスト用データの選抜基準はランダムのようである  
よって、推論モデルを複数つくり、一番目的に合致したものを使う

![採用モデル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/3b75efc5-0f79-40c4-9675-1d8a27e5db4b.png)
![没モデル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/4cd507af-68d9-c50d-c15c-82f89e26ca79.png)


## テスト

CLIにて確認  
（2020/04現在 Windows最新版未対応）
![result-20mm_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/70f77d4d-04a8-2a89-ea8c-1366597fce41.png)
![result-25mm_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/ebc0e6a9-8dc6-5e84-abe8-9aa767d76ab8.png)




## まとめ

- 学習データの質・量を確保するためにも、AIの運用要件を事前に固めておく必要がある
いい感じにステータスバーの色をアクションバーの色と合わせる方法(Android)

## はじめに

Androidでは、アクションバーの色を濃くしてステータスバーの色にセットしているアプリが多く見られます。

|Nintendo Switch Online|Trello|Instagram|
|:--|:--|:--|
|![EVm70iSUcAEwsn6.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/81d261b6-6dfe-985e-4439-b83ba0e7e4f7.jpeg)|![EVm71buU4AA5jP-.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/78bf2ca3-9e9f-8deb-cba6-94a7fb974ecb.jpeg)|![EVm711fVAAIQdP3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/61f22788-212b-837e-4660-4f79835d41ff.jpeg)|

その理由として、 `colorPrimary` がアクションバーの色、 `colorPrimaryDark` がステータスバーの色に紐付いているからだと思います。

本記事では、アクションバーの色を元に、このような有名アプリと同じようにステータスバーの色を濃くする方法を紹介します。

## 結論

アクションバーの色のHue（色相）を `-6` 、Lightness（輝度）を `-0.09` してステータスバーの色にセットするだけです。

コードでは以下で実現できます。

```kotlin:MainActivity.kt
import android.graphics.Color
import com.theuhooi.uhooipicbook.extensions.actionBarColorToStatusBarColor

val actionBarColor = Color.parseColor("#6200EE")
this.window.statusBarColor = actionBarColor.actionBarColorToStatusBarColor()
```

私は `Int` に `actionBarColorToStatusBarColor()` という拡張関数を作って実現しました。

```kotlin:Int+Color.kt
package com.theuhooi.uhooipicbook.extensions

import androidx.core.graphics.ColorUtils

fun Int.actionBarColorToStatusBarColor(): Int {
    val hsl = FloatArray(3)
    ColorUtils.colorToHSL(this, hsl)
    hsl[0] = max(0F, hsl[0] - 6)
    hsl[2] = max(0F, hsl[2] - 0.09F)
    return ColorUtils.HSLToColor(hsl)
}
```


緑、紫、赤で実行した結果です。

|緑|紫|赤|
|:--|:--|:--|
|![Screenshot_1588813316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/ee7b2846-896d-9f3b-a52e-f23be154dc64.png)|![Screenshot_1588813327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/23102ee8-1f42-28d2-4616-98842fe4eb05.png)|![Screenshot_1588813333.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/3a0e45bf-67af-b8fb-23c2-02c48afac243.png)|

__いい感じ__ だと思いませんか？

## 解説

デフォルトの `colorPrimary` と `colorPrimaryDark` のHSLを分析し、同じバランスにしただけです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">`colorPrimary` と `colorPrimaryDark` のデフォルト値を分析してみる<br>色相は赤を減らし、彩度を変えず、輝度を暗くしている <a href="https://t.co/EYV8JEm1pv">pic.twitter.com/EYV8JEm1pv</a></p>&mdash; ウホーイ (@the_uhooi) <a href="https://twitter.com/the_uhooi/status/1250248647226187776?ref_src=twsrc%5Etfw">April 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

要は、色をRGBでなくHSLで扱い、ちょっと色を変えて暗くした、ということです。

## おわりに

かんたんにステータスバーの色をいい感じにすることができました！
しかし、単純にHとLをマイナスしているだけなので、デザイナーがいるチームではきちんと色を考えて定義すべきだと思います。
私は個人開発でサクッと実現したかったので今回紹介した方法を使っていますが、業務で使うかはわかりません。

HSLについても勉強不足です。
特にHを単純にマイナスするのは微妙な気がしているので、もっといい調整方法があれば教えていただけると嬉しいです。

## 参考リンク

- [ColorUtils  |  Android Developers](https://developer.android.com/reference/androidx/core/graphics/ColorUtils)
- [HSL色空間とは : PEKO STEP](https://www.peko-step.com/html/hsl.html)
- [uhooi/UhooiPicBook-Android: Uhooi's character book.](https://github.com/uhooi/UhooiPicBook-Android)
文房具の物体検出をやってみた

# 文房具の物体検出をやってみた

docker-composeで環境構築。
https://github.com/notfolder/keras-yolo3

学習の手順は下記のサイトを参考にさせていただきました。
というか、ほぼこのサイトのまま実施しただけ。
https://sleepless-se.net/2019/06/21/how-to-train-keras%E2%88%92yolo3/

データセットは以前文房具判別機を作成した際の画像にVoTTでラベリング。
ひたすら四角で囲ってラベル付け。。。辛い。。
VoTTはある程度機械学習でボックス付けてくれますが、ずれているので結局ほぼ手動。
https://github.com/microsoft/VoTT

で、検出結果。
https://youtu.be/spyw4qVf3bo

単体で合っている場合もあるが、ペン類の分類が間違っていたり、
複数では検出しにくいように見える。
コロナがあるので、この文房具を実際に見せることができないため、
誰でも入手可能な対象のデータセットの作成が必要そう。。。

iPhoneアプリにしようとflutterアプリにモデルを取り込もうとしたが、
flutterのtfliteライブラリはyolo2にしか対応していない？
tfliteに変換しようとしたら、入力tensorサイズが無指定では変換できない。。。
ので、これからtensorflow.jsとreactに切り替えてみる。
ArcGIS で iOS SDK を使用してみた！

新しくはてなブログを開設しました。今後はこちらを中心に記事を書いていきます。
https://freedom-tech.hatenablog.com/

今回は、ArcGIS の iOS 版の SDK を使用して、住所検索や品川区の観光情報を地図に表示してみました。

最終版のイメージは以下のとおりになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102251/604b951b-789d-922a-526e-7a2a3fddd788.png)

詳細は、こちらのはてなブログに詳しく書いてますので参照して下さい。
[ArcGIS で iOS SDK を使用してみた！](https://freedom-tech.hatenablog.com/entry/2020/05/03/015550)
async / awaitへの誤解と理解：async==new Promiseではない

`async/await`について勝手に誤解していたこと。

# `Promise`まわりの記述を置き換えるわけじゃない
なんか勝手にそう思ってたので飲み込めてなかった。

#### `async` は`return new Promise`とおなじこと　...正しいようで違う

以下のコードでは「同じ」ように振舞う。

```javascript: 
let f1 = () => {
    return new Promise((resolve) => {
        return 'resolved';
    });
}

let f2 = async () => {
    return 'resolved';
}

// f1() == Promise { 'resolved' }
// f2() == Promise { 'resolved' }
```

が、それは非同期処理をしていないから。現実には`Promise`を使うなら必ず非同期処理をするから、以下のポイントが重要になる。

#### `async`中の`return`は`resolve`と同じように使える　...間違い

下のコードで`f4`の戻り値が`Promise { undefined }`になっていることからわかるように、`async`関数は`resolve`と違い、非同期の`return`を待ってくれるわけではない。

```javascript: 
let p1 = new Promise((resolve) => {
    resolve('resolved');
});

let f3 = async () => {
    let p1Text = await p1;
    console.log(`f3: ${p1Text}`);
    return p1Text;
};

let f4 = async () => {
    p1.then((p1Text) => {
        console.log(`f4: ${p1Text}`);
        return p1Text;
    });
};

let f5 = () => {
    return new Promise((resolve) => {
        p1.then((p1Text) => {
            console.log(`f5: ${p1Text}`);
            resolve(p1Text);
        });
    });
};

let f3Result = f3();
let f4Result = f4();
let f5Result = f5();

console.log([f3Result, f4Result, f5Result]);

Promise.all([f3Result, f4Result, f5Result]).then((results) => {
    console.log(results);
});

// 実行結果
// [ Promise { <pending> }, Promise { undefined }, Promise { <pending> } ]
// f3: resolved
// f4: resolved
// f5: resolved
// [ 'resolved', undefined, 'resolved' ]
```

# 結論
- `async`関数内での非同期処理は`await`しか使えない。
    - `async`とは下の２つ以上でも以下でもない。
        - 戻り値が`Promise`に入る
        - 中で`await`を使える
    - `resolve`と違って`return`を非同期に待つわけではないので、やれることは`new Promise`の方が多い。
    - なので、`await`を使わないなら使う意味ない。
- よって、チェーンの起点となるような`promise`は従来通り`new Promise`でつくるしかない。


ということで、 **「`await`使わないなら`async`使わない」** が正しそう。（反論募集）

# コメントをいただいて追記
`f4`の`then`を`await`して`return`すればいい（もっというと`await`なくてもいい）とのコメントをいただきました。確かに...!

しかしこうするともはや`async`の意味ないので、やはり上の結論が正しそう。

というか、`Promise`に`Promise`いれると中間の`Promise`消えちゃうんですね。知らなかった...

```javascript: 
let p1 = new Promise((r) => {
    r('resolved');
});

let p2 = new Promise((r) => {
    r(p1);
});

p2.then((p1) => {
    console.log(p1)
});

// 実行結果
// 'resolved'
```
PumaやSidekiqでメモリが肥大する問題の対処法

RailsアプリケーションでPumaを使ったり、非同期処理のためにSidekiqを使うことはよくあると思います。
アプリケーションを長期運用しているとPumaやSidekiqのメモリ使用量が肥大しOOM Killerにプロセスを殺されたり。なんてことがよく起きます。

# 原因
メモリ使用量が肥大化する原因の一つとして、Rubyのメモリ管理とmallocの仕様(スレッド単位メモリアリーナ)によりメモリの断片化が発生していることが挙げられます。

メモリの断片化であって、メモリリークしているわけではありません。

## 解決策1. Puma Worker Killerを使う
Puma Worker KillerというGemがあります。
PumaのWorkerプロセスが設定したメモリを超えた時に自動でそのプロセスを殺して安全に再起動することでメモリの肥大を防ぎます。
**根本的な解決ではありませんが、環境をいじれない人にとってや有効かもしれません。**
ただPumaのみの解決であってSidekiqの解決にはなりません。

https://github.com/schneems/puma_worker_killer

## 解決策2. メモリアリーナの最大数を変更する
MALLOC_ARENA_MAX環境変数でメモリアリーナの最大数を設定することによってメモリの断片化が改善できます。
**MALLOC_ARENA_MAX=2**が最適値と言われています。
ちなみにHerokuではMALLOC_ARENA_MAX=2がデフォルトになっているようです。

https://devcenter.heroku.com/changelog-items/1683

ただこちらもトレードオフとしてレスポンスタイムが悪化するという実験結果もあります。
https://devcenter.heroku.com/articles/testing-cedar-14-memory-use

## 解決策3. jemallocを使う
**個人的にはこちらの方法をおすすめします。**

アロケーターはmallocからjemallocに変更することで解決できる可能性があります。
jemallocもスレッド単位アリーナを実装していますが、mallocで起きる断片化を回避する設計となっています。

**Rubyの再ビルドが必要になるので既存のアプリケーションに導入する場合はしっかり検証してください。**

### 手順

jemallocのインストール

```
sudo yum install jemalloc-devel
```

rbenvでrubyをビルド

```
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install X.X.X
```

### 導入されているか確認

irbで確認します

```
$ irb
irb(main):002:0> RbConfig::CONFIG['MAINLIBS']
> "-lz -lpthread -lrt -lrt -ljemalloc -lgmp -ldl -lcrypt -lm"
```

ljemallocが入っていればOK



# 参考
https://www.speedshop.co/2017/12/04/malloc-doubles-ruby-memory.html
PysideでGUI作成　その２＜クラス利用＞


#はじめに
クラスを利用したQtWidgetの作成方法の覚書です。

クラスについて以前まとめた記事はこちら
https://qiita.com/kashiba/items/339b81f63612ffdba573


#今回作るもの
##完成図
ボタンが1個あるだけのシンプルなWindowです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560169/174548a3-fa80-3d8f-277c-76ac0dd9b0f1.png)

ボタンをクリックする度に「Hello world」とprintされます。

```
Hello world
Hello world
Hello world
Hello world
```
##コード

```.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-



import sys
from PySide2.QtWidgets import *


class window_A(QWidget):
    def __init__(self, parent=None):
        super(window, self).__init__(parent)
        self.w = QWidget()
        self.layout = QVBoxLayout()
        # ボタンを作成して配置
        self.button = QPushButton("Button")
        self.layout.addWidget(self.button)
        #　ボタンのクリックを、関数helloとリンク
        self.button.clicked.connect(self.hello)
        self.w.setLayout(self.layout)
        self.w.show()

    #　ボタンクリックによって呼び出される
    def hello(self):
        print("Hello world")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = window()
    sys.exit(app.exec_())

```

#解説
```.py
class window_A(QWidget):
    def __init__(self, parent=None):
        super(window, self).__init__(parent)
```
QWidgetを継承したクラス`window_A`を作成しsuperクラス（QWidget)のinitを継承します。
この辺りは「クラス　継承」で調べると情報がたくさん出てきます。

```.py
        self.w = QWidget()
        QVBoxLayout
```
windowの土台になる`QWidget`と、ボタンをレイアウトする為の枠組みとなる`QVBoxLayout`をそれぞれ作成します。QVBoxLayoutのVはVertical、垂直レイアウト、QHBoxLayoutのHはHorizontal、水平レイアウトを示しています。

■QVBoxLayout作成例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560169/d9e9f0d3-8194-b54f-3f43-046744f5b009.png)

■QVHoxLayout作成例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560169/75d0f133-1fec-43d9-8bcd-2e91c600c8c7.png)

```.py
        self.button = QPushButton("Button")
        self.layout.addWidget(self.button)
```
`QPushButton`オブジェクトを作成し、`Button`というラベルをボタンに貼り付けています。
`addWidget`コマンドで、`self.layout` = `QVBoxLayout`にボタンをレイアウトしています。

```.py
        self.button.clicked.connect(self.hello)
```
`self.button`に`self.hello`関数を接続しています。
`.clicked.connect`を用いると、ボタンクリック時のイベントに指定の関数を接続する事が出来ます。`self.hello()`ではなく、`self.hello`と指定している事に注意してください。**（）が不要です。**

```.py
        self.w.setLayout(self.layout)
        self.w.show()
```
`.setLayout`で`self.w` = `QWidget`の上に、`self.layout` = `QVBoxLayout`を乗せます。
■イメージ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560169/9ad41d91-c14f-f54e-3291-631443eaf378.png)

```.py
    def hello(self):
        print("Hello world")
```
Hello world　をプリントするだけの関数です。

```.py
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = window()
    sys.exit(app.exec_())
```

pythonファイル起動時の処理です。
QApplicationを作成したあと、windowクラスを生成します。
windowクラス生成と同時に、__init__でwindowが生成されます。


`QApplication`や`sys.exit(app.exec_())`について以前まとめた記事はこちら
https://qiita.com/kashiba/items/95f04ea9700236853803


#参考にしたページ
http://tommy-on.hatenablog.com/entry/2019/04/17/231229
React Nativeで開発するならExpoでするのが素晴らしい3つの理由

React Nativeでアプリ開発をする際、Expoで開発するかしないかで、その後の開発が大きく変わっていきます。

イメージとしてはおそらく
**Expoあり　→　お手軽だけど制限あり**
**Expoなし　→　自由にカスタマイズできるけど難易度高い**

上記のようなイメージをもっている方が多いのではないでしょうか。
筆者は両方の開発環境の構築、アプリ作成をした経験がありますが結論から言うと、

**Expoの導入一択**

です。

ではなぜその結論に至ったのか、紹介してきます。
## 開発環境の構築スピードが天と地の差ほど違う
#### Expoなし
「nodeインストールして、watchman入れて、cocoapods入れて、initでプロジェクト作成して、、、。あ。TypeScriptも入れて」
#### Expoあり
「`npm install -g expo-cli` `expo init プロジェクト名` Done!」

**Expoのインストールをしてプロジェクトを立ち上げるだけで終わりです。**
`expo init`をしたら、TypeScriptでするか、などなど、セッティング内容を選択していくので非常に楽です。

Expoなしの場合、nodeやwatchmanなど既に入っている場合もありますし、cocoapodsも入れなくても動かすことはできるので、「開発環境の構築スピードそんなに変わらないよね」と思われる方もいるでしょう。しかし、2つのコマンドだけで、パッと、開発環境が構築できるExpoの手軽さは強みだと感じます。
## 実際に開発に入るまでの苦労が違う
#### Expoなし
「このパッケージ入れたいから、`pod install パッケージ名`、Podfileにも設定内容書くべきものは書いて、Xcode側でも設定して、、、」

#### Expoあり
「`expo install パッケージ名` Done!!」

PodfileやInfo.plistファイルの編集など、ExpoなしだとSwiftに関わってくるようなファイルもいじっていく必要があるので、一つのパッケージやツールを使いたいと思っていても、設定が複雑で時間がかかります。

その点Expoありなら、インストールすれば設定完了なのですぐに使用できます。`react-native-link`の設定もいりません。断然開発スピードが違ってきます。
## ビルド環境が一発で整う
#### Expoなし
「iOS用の環境走らせて、Android用の環境も走らせて、あ、WEB用にもビルド環境も作んなくちゃ」

#### Expoあり
「`yarn start` でAndroid、iOS、WEBの環境走らす準備OK　→　Done!!!」

ExpoがなくてもiOS、Androidの環境走らすことは簡単です。大きな利点としては、ビルド環境の構築を`yarn start`で一発でできるのと、その際生成されるQRコードを読み取れば実機確認も簡単にできる、というところです。

特にWEB用のビルド環境がExpoありだと初めから作成されているのはかなり助かります。

## 終わりに
といっても、Expoだと制限がかかって使用できない、ようなツールもあります。例えばreduxを通してデータの永続化をする、`redux-persist` はまだExpoありでは使用できません。筆者が知らないだけで他にもまだまだあるかもしれませんが、付けたい機能が実装できない、といったことはほぼほぼないでしょう。

エンジニアなら、Expoなしで自由にカスタマイズしていきたい、と思う方が多いと思いますが、それならばSwiftやKotlinを使用して開発していく方が高価値のスキルを身に付けれる分、断然お得だと思います。

アプリ開発したいけど、JavaScriptで簡単に、スタートアップだからMVP、PMFのサービス開発をスピーディーにお手軽に、ということなら、ExpoありのReact Nativeで開発が断然コスパが良いので、Expo入れるか入れないかで迷っている方がいたら、この記事が参考になれば良いです。
apt-dailay.timer のログが頻繁に記録されたことへの対処 

# 概要

PCの設置場所変更したら、頻繁にHDDへのアクセス音が発生することに気づいて対応した記録。

# 環境

* debian 9.12（on Hyper-V Server 2019）

# 現象

syslogに同じログが大量に記録されていました。

```:/var/log/syslog
May  7 09:50:00 gembu systemd[1]: Time has been changed
May  7 09:50:00 gembu systemd[1]: apt-daily.timer: Adding 9h 40min 12.034469s random time.
May  7 09:50:00 gembu systemd[1]: apt-daily-upgrade.timer: Adding 12min 8.894713s random time.
May  7 09:50:00 gembu systemd[41984]: Time has been changed
May  7 09:50:05 gembu systemd[41984]: Time has been changed
May  7 09:50:05 gembu systemd[1]: Time has been changed
May  7 09:50:05 gembu systemd[1]: apt-daily.timer: Adding 11h 20min 8.000032s random time.
May  7 09:50:05 gembu systemd[1]: apt-daily-upgrade.timer: Adding 24min 114.276ms random time.
```
これが10秒間隔で出力されます

# 対応

Hyepr-V Managerで仮想マシンの設定を開き、「統合サービス」-「時刻の同期」のチェックを外します。
適用したらすぐにログが止まりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617842/725fe5aa-f9d6-b677-78e8-83f03aee5890.png)

# 参照サイト

```apt-daily.timer``` で検索してもなかなか情報が得られずハマり気味だったのですが
```Time has been changed``` で検索したら一発でした。

* [Hyper-V のゲスト環境で systemd timer がうまく動いていなかった](https://blog.n-z.jp/blog/2017-07-06-hyperv-systemd-timer.html)

なお、```apt-daily.timer``` と ```Hyer-V``` の組み合わせで検索しても一発でした。
キーワード不足か…:worried:

# まとめというか教訓

* 時刻を見ると ```Time has been changed``` が起点
* Hyper-V で動いてるからこその不具合もあることを認識すべき

だから検索キーワードはよく考えましょう、といったことろかな。
作り直したら確実に再発生してしかも気づかなそうなので、忘れないようメモしておきます。
【爆速メモ】VSCodeで.NETcoreSDKとmonoをオフラインで入れる方法【テキストのみ】

この記事では、
####VSCodeのいっちばん最初に出てくるエラー画面をオフラインで解決する内容
が書かれています。

---

Macで端末クリーンインストール後に、
VSCodeを新規でインストールする際、変なエラーが出てきませんか?

**私は出てきます。**

調べると、
.NET core SDK　と
mono
が必要なことがわかってくるのですが、

HomeBrewとかいうのが良く出てくるんですよ。(monoを入れようと調べているとき)
みなさん、そんなにターミナル使っていますか?

**私は使っていません。**

そこで、クリーンインストールが発生しているような環境(職場など)は、
だいたい一台や二台ではすまないので、
事前のインストーラーのダウンロードをすることによって、オフラインで解決できるようリンクを貼りました。
ご活用ください。

.NET core SDK
https://dotnet.microsoft.com/download

mono
https://www.mono-project.com/download/stable/
P5.js 日本語リファレンス(plane)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の plane関数を説明します。

## plane()

### 説明文

指定した幅と高さで平面を描く。

### 構文

plane([width], [height], [detailX], [detailY])

### パラメタ

- width  
Number：平面の幅(オプション、省略時は50) 

- height  
Number：平面の高さ(オプション、省略時は50)

- detailX  
Integer：x方向の三角形分割数(オプション、省略時は1)

- detailY  
Integer：y方向の三角形分割数(オプション、省略時は1)

### 例1

```javascript
function setup(){
  createCanvas(300, 300, WEBGL);
}

function draw(){
  push();
  translate(-100, -100);
  fill(255, 0, 0);
  plane(60, 60, 1, 1);
  pop();
  
  push();
  translate(-0, -100);
  fill(0, 255, 0);
  plane(60, 60, 0, 0);  // xy方向の三角形分割数が0のため描画されない
  pop();
}
```

### 実行結果
![plane.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43467/385e4134-9bc9-bad1-e422-0af95289cf2e.png)



### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
Kubernetes アーキテクチャ

# クラスタ

## コントロールプレーン [マスターノード]

クラスタの頭脳

- kube-apiserver

コントロールプレーンのフロントエンドサーバで、APIリクエストを処理する

- etcd
Kubernetesが、存在するノードの詳細やクラスタに存在するリソースの詳細など、 あらゆる情報を保存するデータベース

- kube-scheduler
新たに作成されるPodが実行される場所を決定する

- kube-controller-manager
リソースコントローラ(Deploymentなど)の実行を管理する

- cloud-controller-manager
クラウドプロバイダと情報をやり取りして、ロー ドバランサやディスクボリュームなどのリソースを管理する


## データプレーン [ワーカーノード]

- kubelet
ノードにスケジューリングされているワークロードを起動するコンテナランタイムの運用と、そのステータスの監視を担当する

- kube-proxy
バックエンドとなるPodのグループに対してトラフィックをルーティングする単一で不変な仮想IPアドレスを提供する機能を実行管理する

- container-runtime
実際にコンテナを起動および終了し、必要な通信を処理します。通常はDockerですが、Kubernetesは他のコンテナランタイム(rktやCRI-Oなど)もサポートする
PythonでABC037のA~Cを解く

### はじめに
今日は早起きできたので、記事書きます.

### A問題
[問題](https://atcoder.jp/contests/abc037/tasks/abc037_a)

**考えたこと**
minとって、割る

```python
a, b, c = map(int,input().split())

if a > b:
    ans = c // b
    print(ans)
else:
    ans = c // a
    print(ans)
```

### B問題
[問題](https://atcoder.jp/contests/abc037/tasks/abc037_b)

**考えたこと**
Qが小さいので、forで回せる

```python
n, q = map(int,input().split())

lrt = [list(map(int,input().split())) for _ in range(q)]

a = [0] * n
for i in range(q):
    a[lrt[i][0]-1:lrt[i][1]] = [lrt[i][2]] * (lrt[i][1]-lrt[i][0]+1)

for i in range(n):
    print(a[i])
```

### C問題
[問題](https://atcoder.jp/contests/abc037/tasks/abc037_c)

**考えたこと**
スライス使うと、おそらくTLEするので累積和を使います。numpyを使うと楽なので、numpyを使います。

```python
import numpy as np
n, k = map(int,input().split())
a = list(map(int,input().split()))

a = np.cumsum(a)
a = np.append(0,a) #np.cumsumだと0が追加されないのでappendします
ans = 0
for i in range(n):
    if i + k >= n + 1:
        break
    ans += a[i+k]-a[i]

print(ans)
```

### まとめ
Dはできない。ではまた。
時間がない人のためのスクラム開発用語集

# 本題に入る前に

本記事は、頑張って短い文章でスクラム開発用語を説明しています。
明らかに意味が違う！間違っている！という場合は、教えていただけるとありがたいです。

詳しく知りたい場合は、今回使った参考文献である ↓ を参照してください。
[SCRUM BOOT CAMP THE BOOK (Amazon リンク）](https://www.amazon.co.jp/SCRUM-BOOT-CAMP-BOOK-%E8%A5%BF%E6%9D%91/dp/4798129712/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%A0&qid=1588769992&sr=8-2)
kindle だと 1320 円なのでかなりお得です。

# 登場人物

- **プロダクトオーナー (PO)**
- **スクラムマスター**
- **開発メンバー**

### プロダクトオーナー (PO)

プロダクトに責任を持つ人。
機能の優先順位や仕様を決定する人。

### スクラムマスター (SM)

スプリントを回すことに責任を持つ人。

### 開発メンバー

開発することに責任を持つ人。

# スプリント

1~2週間で1サイクルを回す。
下記の4つで、1つのスプリントを表す。

1. **リファインメント**
2. **スプリントレビュー**
3. **スプリントプランニング**
4. **スプリントレトロスペクティブ**

毎日やることとして**デイリースクラム**

### デイリースクラム

朝会。（毎日やること。夕方とかにやってもいい）
**スプリントバックログ** を使って行う。

### リファインメント

各作業の見積もり。
プロダクトオーナー（PO）がタスクの優先順位を決め、開発チーム内でポイントをつける。
（時間がかかりそうだから5ポイント、すぐ終わりそうだから2ポイントなど）

つけた見積もりのポイントを **ストーリーポイント（SP）** という。

### スプリングレビュー

スプリントの終わりに行う。
プロダクトオーナーの思っていたものができているか確認する。
作業を完了とするかどうかをここで確認。

### スプリントプランニング

次のスプリントでやることを計画する。

### スプリングレトロスペクティブ

スプリント内で起こったことを振り返る。
チームで良かったこと、悪かったことを洗い出す。
（個人のことではない）

# バックログ

### スプリントバックログ

1回のスプリントでやりたいことを並べた一覧。

**ToDo** … 未着手の作業
**Doing** … 着手して進行中の作業
**Done** … 完了した作業
で列がそれぞれ分かれている。

### プロダクトバックログ

プロダクトに必要だと把握しているものをすべて順番に並べた一覧。
今後のリリースで実装するプロダクトのフィーチャ・機能・要求・要望・修正をすべて一覧にしている。

# 見積もり

### ストーリーポイント（SP）

各作業の見積もりに対してつけるポイント。
（時間がかかりそうだから5ポイント、すぐ終わりそうだから2ポイントなど）

### ベロシティ

1スプリントで消化できるチームの SP の合計
ベロシティを使って、1スプリントの作業を計画する
Jupyter Notebook 起動してみる 〜 エスパーの修行

# Jupyter Notebook 起動するまで

- この記事をカテゴリ分けすることが難しい
    - そもそも何が問題なのかがわからないので，最初にタイトルやカテゴリを決められない
    - そもそも問題認識が間違っていることもある
        - タイトルは付け直せばいい

## 環境を想像する

画像で貼ってあったので想像できた，予想だと jupyter か？

- https://qiita.com/fuku_tech/items/6752b00770552bf4f46b
- https://qiita.com/littlem/items/4893bc46bbdff4f97dfb

```yml:docker-compose.yml
version: '3'
services:
  jupyter:
    image: jupyter/scipy-notebook
    ports:
      - 10000:8888
    volumes:
      - $PWD:/home/jovyan/work
    command: start.sh jupyter lab --NotebookApp.token=''
```

```shell-session
$ docker-compose up
```

http://localhost:10000/ にアクセスしてconsole を見る

## やってみる

誰かが試すときはコードがあると嬉しいけど無かったので手で打つ

```python:ソース1
data = {'name': ['Ryo', 'Kaori', 'Hideyuki', 'Hayato', 'Miki', 'Saeko'],
        'gender': ['M', 'F', 'M', 'M', 'F', 'F'],
        'height': [186, 168, 175, 210, 160, 163],
        'weight': [72, 47, 62, 90, None, numpy.NaN],
        'age': [30, 20, None, numpy.NaN, 23, 25],
        'size': ['L', 'M', 'L', 'XL', None, 'S']
        }
```

```python:エラー
NameError: name 'numpy' is not defined
```

- 解決する
    - https://pythondatascience.plavox.info/numpy

```python:修正後1
import numpy
data = {'name': ['Ryo', 'Kaori', 'Hideyuki', 'Hayato', 'Miki', 'Saeko'],
        'gender': ['M', 'F', 'M', 'M', 'F', 'F'],
        'height': [186, 168, 175, 210, 160, 163],
        'weight': [72, 47, 62, 90, None, numpy.NaN],
        'age': [30, 20, None, numpy.NaN, 23, 25],
        'size': ['L', 'M', 'L', 'XL', None, 'S']
        }
```

## やってみる2

```python:ソース2
size2int = {'S': 1, 'M': 2, 'L': 3, 'XL': 4}
df['size'] = df['size'].map(size2int)
df
```

```python:エラー
NameError: name 'df' is not defined
```

まあ，そうよね

- https://qiita.com/simonritchie/items/d7dccb798f0b9c8b1ec5


```python:修正後2
import pandas as pd
df = pd.DataFrame(data)
# size2int は size to int の意味
size2int = {'S': 1, 'M': 2, 'L': 3, 'XL': 4}
df['size'] = df['size'].map(size2int)
df
```

<img width="382" alt="スクリーンショット 2020-04-30 13.41.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398927/edce8387-619d-f4b8-3622-fff118ca7198.png">

できてしまった．どうして動かないんだろう．
エスパー力が足りない．

## エスパー

予想としては，size2int がミスっている状態で一度`size` カラムを上書きしてしまった．以降は NaN にしかならない．

```python:sample
size2int = {'Ｓ': 1, 'Ｍ': 2, 'Ｌ': 3, 'ＸＬ': 4}
```
みたいな

とすると，data → df をもう一度やってみよう．というのが何かになる．

本当か？

```python:一度失敗する
import pandas as pd
df = pd.DataFrame(data)
size2int = {}
df['size'] = df['size'].map(size2int)
df
```
```python:あとは何度やっても
size2int = {'S': 1, 'M': 2, 'L': 3, 'XL': 4}
df['size'] = df['size'].map(size2int)
df
```

一応再現はできる

## WIP エスパー力を追加する

- pandas.DataFrame
    - https://note.nkmk.me/python-pandas-dataframe-values-columns-index/
- map

## まとめ

- 大抵すごくどうでもいいところでつまずく
- 最初からやってみることができる環境を作るのは意外に大事
- 環境をさっと作るときに docker は便利．コードなので渡したりもできる
【PowerApps】複数選択したユーザーをJSON関数でPowerAutomateに渡す

今回紹介するのは、PowerApps で複数選択したユーザーをJSON関数で PowerAutomate に渡す方法です。

コンボボックスなどで複数選択した値やテーブル値などは、単純に PowerApps から PowerAutomate に渡しても、すべてのデータを受け取ることはできません。
しかし、JSON形式にすることで、テーブルごとすべてのデータを渡すことができるようになります。
結論、複数選択した値を PowerApps から PowerAutomate へ渡す場合は PowerApps 上でJSON関数を用いてJSON形式にしましょう。

　
**※本記事は、はてなブログに移行しました。
　記事は最新化しています。よろしければそちらをご覧ください。**

**[【PowerApps】複数選択したユーザーをJSON関数でPowerAutomateに渡す](https://kurattyodiary.hatenablog.com/entry/SomeUserDatajsontoPA)**
クイックアクションとレコードタイプ


+ [Case オブジェクトが関連するトレイルヘッド](https://qiita.com/Keiji_otsubo/items/8bfc07ed970c3e33f50f)


# レコードタイプが複数ある時で、クイックアクションが表示されない場合の注意点


なかなか、気付けない。Answersにも時々質問がありますね。

[Quick Actions and Record Types](https://help.salesforce.com/articleView?id=actions_and_record_types.htm&type=5)


**デフォルトグローバルアクション: 特別なケース**
組織にデフォルトグローバルアクションがあり、レコードタイプを使用している場合、ページレイアウトに割り当てられたデフォルトアクションのすべてがユーザに表示されるとは限りません。

デフォルトグローバルアクションは、ほとんどのプロファイルではアクセスできないマスタレコードタイプに割り当てられます。そのため、ほとんどのユーザは、レコードタイプが設定された対象オブジェクトに関連付けられたマスタレコードタイプを持つデフォルトグローバルアクションを使用できません。この問題を解決するには、対象オブジェクトに関連付けられたデフォルトグローバルアクションを編集し、それを別のレコードタイプに再度割り当てます。

たとえば、[新規取引先責任者] デフォルトグローバルアクションには、取引先責任者という対象オブジェクトがあります。取引先責任者オブジェクトにレコードタイプを設定し、[新規取引先責任者] デフォルトグローバルアクションをページレイアウトに追加したとします。デフォルトではアクションがマスタレコードタイプに割り当てられるため、そのページレイアウトに基づいてユーザがレコードにアクセスしたときに [新規取引先責任者] アクションは表示されません。[新規取引先責任者] デフォルトグローバルアクションを編集し、それをマスタ以外のレコードタイプに割り当てると、割り当てられたレコードタイプへのアクセス権を持つすべてのユーザが使用できるようになります。

+ [Action buttonが表示されない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T5fhJ)

:::note
I opened a case with Support and they told me when I have multiple record types, I needed to go to Global Actions, select the action (New Contact in this case) and activate it for that record type. 
:::
Typescriptでeslintを設定する手順

毎回調べるのが煩わしかったのでメモ

# 前提

- globalでeslintをいれている(cliも動く)
- VSCodeなどでeslintの設定がすんでいる
- あとはプロジェクト内でeslintの設定ができればOKという状況

# 実行
`eslint --init`で質問に答えていく。

その後、npmなら上記コマンドの続きとしてパッケージを入れることができるが、yarnなら以下を実行する。

`yarn add -D @typescript-eslint/parser@latest @typescript-eslint/eslint-plugin@latest eslint-plugin-react@latest eslint@latest`


# Reactの場合

hooksのdepsチェックを入れる

`yarn add -D eslint-plugin-react-hooks`

eslintの設定ファイルに以下を追加

```.eslintrc.json
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
    "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}
```

参考1: https://qiita.com/kobayang/items/88a104c0be28e16e65e8
参考2: https://ja.reactjs.org/docs/hooks-rules.html
【爆速メモ】Macですでに作った管理者権限を持っているログインアカウント名が間違えていたのでそれを変える方法【テキストのみ】

Macをクリーンインストールしていて、アカウント名を間違えて設定したことはないですか?

**私はあります。**

そこで、この記事では、
### 「Macですでに作った管理者権限を持っているログインアカウント名が間違えていたのでそれを変える方法」 
を書いていきます。ラノベっぽくていいですね。

※記事の内容としては二番煎じどころではない

---

####【ミスった垢でログインしている編】
1. まずは、どんなに不本意でも、ミスった垢でログインします。
2. [システム環境設定]-[ユーザとグループ]を選択します。
3. かなり割愛しますが、ここで「捨て垢として管理者権限をもつアカウントを作成」します。
    - 【注意】捨て垢名は、「本当に使いたかった名前にしないこと」。
    - **私は何回か間違えてます。**「xxxx_xxxx_temp」とかにして作業しています。
4. 再起動が求められるので、再起動して、捨て垢でログインします。

####【捨て垢でログインしている編】
1. Finderが起動している状態で、[移動]-[フォルダへ移動]を選択します。
2. 表示されたウィンドウ内に`/ユーザ`と入力します。
3. ミスった垢のホームフォルダの名前を変えます。
4. [システム環境設定]-[ユーザとグループ]を選択します。
5. 捨て垢を、[control]キーを押したまま選択します。
6. 「詳細設定」みたいな小窓が出てくるので、それを選択します。
7. 新しく出てきたウィンドウ内で、ミスった垢に該当する文言を変えます。たぶん三箇所ぐらいあるはず。
8. ひととおり修正したら、再起動します。
9. ミスった垢が、本当に作りたかった垢になっているはずなので、それでログインします。

####【本当に作りたかった垢でログインしている編】
1. [システム環境設定]-[ユーザとグループ]を選択します。
2. 捨て垢を選択します。
3. [-]を押下して削除します。
4. 捨て垢なので、ゴミは残さず、ホームフォルダごと削除する選択をしましょう。

####以上です。
CodeBuildでdocker run --nameがコンフリクトする問題

## 概要

CodeBuildとGithubを連携していたりすると、連続でビルドが走ることがよくあります。
たとえば、以下のようにバックグラウンドでコンテナを動かしておいてテストなどをしていると、コミットが一気に押し寄せて`複数のビルドが同時`に走ってしまうことはよくあります。

```sh
$ docker run -d --name nginx1 nginx:alpine
$ docker run --link nginx1 alpine \
    sh -c 'apk add curl && curl nginx1:80 && sleep 100'
```

そんなときに、以下のようなエラーが発生することがあります。

```sh
docker: Error response from daemon: Conflict. The container name "/nginx1" is already in use by container "XXXXXXXXX". You have to remove (or rename) that container to be able to reuse that name.
```

これは、nginx1という名前ですでにコンテナが動いていて、その名前は使えないのでrenameしてくださいという旨の警告文です。

通常の検証環境だとrenameすれば問題ないのですが、CodeBuildなどCI環境だと困ります。

## 結論

以下のリポジトリで検証しました。

- https://github.com/fnaoto/codebuild-sample

前回、DOCKER_BUILDKITが原因と書きましたが、実は`ローカルキャッシュのDockerLayerCache`が原因でした :bow:



## 検証

以下のような`buildspec.yaｍl`を用意して検証しています。

※ `echo $rand は、latestのイメージが他のビルドで上書きされないかの検証`

```yml
version: 0.2 

env:
  variables:
    DOCKER_BUILDKIT: "1"

phases:
  build:
    commands:
# 省略
      - |
        docker build -t app --build-arg rand=$RANDOM .
        docker run app sh -c 'echo $rand'
        docker run --name test alpine sh -c 'sleep 120'
        docker run app sh -c 'echo $rand'
```


#### DockerLayerCacheありの場合

以下のようなエラーが出ます。

```sh
21546 # echo $randの結果
docker: Error response from daemon: Conflict. The container name "/test" is already in use by container "XXX". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
21546
```

DockerLayerCacheありの場合は、実行中のビルドでコンテナリソースを共有しているみたいです。
逆に、CustomCacheやSouceCacheは影響がありませんでした。
 

## どうでもいいこと

bashなどで`docker run --name`を使いたいけど、毎回動かすとコンフリクトが面倒というかたは`$RANDOM`をお使いください

```sh
$ docker run -d --name nginx-$RANDOM
```
Clone with Related Campaign Error

#キャンペーンオブジェクトに複製ボタンを追加した時のエラー

最終的には
It seems to be important to keep the API-Names of those two default status.

You can rename the values to whatever you want as long as the API-Names "Sent" and "Responded" still exist in the picklist.

"Sent" と "Responded"　との２つを選択リストに残しておくことが重要みたい。

https://success.salesforce.com/answers?id=9063A000000eYwQ
docker-composeでReact環境構築できなかった対策

##概要
React開発環境をDockerで作ろうとした際に遭遇したエラーに対する対処の備忘です。

##環境
>Windows10 ver2004(19041.208)
>WSL2
>docker 19.03.8
>docker-compose 1.25.4

##コンテナ作成
Dockerfile, docker-compose.yml作成は以下を参考にしました。

>**docker-composeでReact環境構築**(@kerochelo様)
https://qiita.com/kerochelo/items/1063da8893026de5ebbf

##起動しない
docker-compose up後、勝手に終了する。

```
PS > docker-compose up
Recreating react_web_1 ... done
Attaching to react_web_1
web_1  | yarn run v1.15.2
web_1  | $ react-scripts start
web_1  | ℹ ｢wds｣: Project is running at http://172.18.0.2/
web_1  | ℹ ｢wds｣: webpack output is served from
web_1  | ℹ ｢wds｣: Content not from webpack is served from /usr/src/app/react-sample/public
web_1  | ℹ ｢wds｣: 404s will fallback to /
web_1  | Starting the development server...
web_1  |
web_1  | Done in 29.34s.
react_web_1 exited with code 0
```
##対策


docker-compose run で--service-ports付きで実行する。
これでなぜいけるのかはわからない。


```
docker-compose run --rm --service-ports web
```
Gitコマンド　〜良く使う便利なコマンドまとめ〜

#はじめに
Gitを少しずつ使えるようになってくると、間違ってmasterにプッシュしてしまって焦ったり。
『あそこのコミットまで戻りたい〜〜』って事があるんですよね。

そんな時のためのコマンド集です。

#良く使うコマンドたち

#＜修正系＞

##●あそこのコミットしたところまで戻りたい！！
```
$ git log
commit:　ここの部分の『ハッシュ値』を使う
Author:ーーーーーーーーーーーー
Date:ーーーーーーーーーーーーー

$ git reset --hard ハッシュ値
```
このコマンドでは、```--hard```とありますが、**『HEADの位置、インデックス、ワーキングツリー』の全て**が指定したハッシュ値のコミットまで戻ってしまいますので注意！

これで、晴れて、戻りたいコミットに戻れます！

##●取り消したコミットを取り戻す
コミット履歴は```git log```で確認できますが、消してしまったコミットは```git log```で確認できません。
その場合は、

```
$ git reflog 

ハッシュ値 HEAD@{1}: commit: First commit
```
で、取り消したコミットの履歴を確認する事ができます。

```
$ git reset --hard ハッシュ値
```
これで、戻りたいコミットへ戻す事ができます。

##●間違ってmasterにプッシュしてもた！ヤバイ
戻す方法は、

```
$ git push -f origin 0830890ae0:master
```
この修正方法は、ローカルの変更内容はそのままで、 リモートにプッシュした内容を削除しています。

-fで強制的にmasterを0830890ae0の状態へ戻しています。

元の状態に戻りました！

##●コミットメッセージ、間違えた。。

```
$ git commit -m 'I like Wasabi'
```

いやいや、サビ抜きしか無理です。間違えた。どうしよう。
メッセージを変えるために、もう一度コミット？？
いやいやそんな、必要はないはず。
こんな時はですね。

```
$ git commit --amend -m "I don't like Wasabi"
```
これで、メッセージだけ変更できました。
amendですがpushした後でも変更はできるのですが、pushの前に変更しておくのが無難です。

#＜作成＞

##●ブランチを作りましょう！

```
$ git branch <branchname>
```
ブランチnameを指定することでブランチを作成できます。シンプルですね。

ついでに言うなら、ブランチnameを指定せずに```$ git branch```コマンドだけだと現在のブランチを確認できます。

```
$ git branch
  babashoya
* master
```
*がついているのが現在のブランチですね。

#＜取り消し系＞

##●リモートのブランチ。一回消そう

```
$ git push --delete origin <branchname>
```
リモートブランチを触ることになるので、多発はしないほうがいいかもですね。
間違ってでも、masterブランチは消さないでくださいね。笑

##●直前のコミットの取り消し
```
$ git reset --hard HEAD^
```

・```HEAD^```：直前のコミットのこと。

また、```HEAD^```の代わりに、ハッシュ値を打てば、指定されたコミットが打ち消される。
20分で作成したドラクエ10バザー相場取得プログラム

# はじめに
自粛中、ドラクエ10に勤しんでいます。
ドラクエ10には、旅人バザーという仕組みがあり、ユーザー同士でアイテムの売り買いが可能になっています。
そこで、冒険者の広場から旅人バザーの価格情報を取得し、Excelのシートに貼り付ける簡易的なコードを書きました。

# 環境
Windows10 Pro

Python 3.8.2

selenium 3.141.0

ChromeDriver 81.0.4044.69

openpyxl 3.0.3

# コード
```python:config.py
USERID = 'ユーザーID'
PASSWORD = 'パスワード'
```

```python:bazaar.py
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import re
import config
import openpyxl
import datetime

# 出品情報を格納するリスト
exhibition_data = []

options = webdriver.ChromeOptions()

#ヘッドレスモード
#options.add_argument('--headless')

#webdriverのパスを指定
driver = webdriver.Chrome(executable_path="chromedriver.exe", chrome_options=options)
#検索先のURL
driver.get('https://hiroba.dqx.jp/sc/search/')

time.sleep(3)

#検索窓入力
s = driver.find_elements_by_xpath('//*[@id="sqexid"]')
s[0].send_keys(config.USERID)
s = driver.find_elements_by_xpath('//*[@id="password"]')
s[0].send_keys(config.PASSWORD)

# ログインボタンクリック
driver.find_element_by_xpath('//*[@id="login-button"]').click()
driver.find_element_by_xpath('//*[@id="welcome_box"]/div[2]/a').click()
driver.find_element_by_xpath('//*[@id="contentArea"]/div/div[2]/form/table/tbody/tr[2]/td[3]/a').click()

# 検索
time.sleep(2)

while True:

    print("検索するアイテム名を入力してください：")
    # 検索するアイテム名を格納
    search_word = input()

    # 何も入力されなければ終了
    if search_word == "":
        print("プログラムを終了します")
        break
    
    # 検索フォームに入力
    s = driver.find_elements_by_xpath('//*[@id="searchword"]')
    s[0].send_keys(search_word)

    driver.find_element_by_xpath('//*[@id="searchBoxArea"]/form/p[2]/input').click()
    driver.find_element_by_xpath('//*[@id="contentArea"]/div/div[4]/table/tbody/tr/th/table/tbody/tr/td[3]/a').click()
    time.sleep(3)
    driver.find_element_by_xpath('//*[@id="btn_lock"]/a').click()
    time.sleep(5)

    # 出品データの取得
    elements = driver.find_elements_by_tag_name('tr')
    
    # リストに格納
    for elem in elements:
        exhibition_data.append(elem.text.split())
    
    # 先頭に5つ入ってくる無駄な要素を削除
    del exhibition_data[:6]

    workbook = openpyxl.Workbook()
    sheet = workbook.active
    
    # Excelのシートへ出力
    for i in range(len(exhibition_data)):
        for j in range(len(exhibition_data[i])):

            sheet.cell(row=i + 1, column=j + 1).value = exhibition_data[i][j]
    
    # リストの中身を一旦リセット
    del exhibition_data[:]

    # Excelファイルを保存
    workbook.save(search_word + "_" + datetime.datetime.now().strftime("%Y%m%d%H%M") + '.xlsx')

    # ワークブックを閉じる
    workbook.close()

# ドライバーを閉じる
driver.quit()
```

# 課題
簡易的に書いたコードなので、結果の1ページ目しか取得しない仕様になっているのと、エラー処理もないので使用する時は、書き足したいとおもいます。
SEOについて【僕の備忘録】

##前書き
自分用にまとめているのでおおざっぱに書いてます！

##SEOとは
さーち　えんじん　おぷてぃまいぜーしょん
グーグル検索とかヤフー検索したときに検索結果の上位に表示されるようにために行う施策のこと

##メリット
・広告費などがかからない分低コスト。
・CMなどと違って効果が長期間持続する。
・検索上位を獲得するとブランド力が上がる。
・一度コンテンツを作成してしまえば資産となる。

##なにをすればいい？
[クローラー](https://qiita.com/99knights0/items/c394393bacc97cb08eb9)が各Webサイトを巡回して採点してインデックスします。
つまりこの**クローラーの採点を上げればいい**ということですね。

##ブラックハットSEOとホワイトハットSEO
一昔前は有益なコンテンツでなくてもクローラーの採点だけを上げる方法がありました。かの有名な黒帽子、ブラックハットSEOです。主に**被リンクの多さが採点に大きくかかわるという特性**を活かしてリンクのサテライトサイトを多数用意し順位を上げたいサイトへのリンクを設置する手法です。
これに危機感を頂いたgoogleはみんな大好きなあの動物たちの力を借ました。そう**ペンギンアップデートとパンダアップデート**です。それぞれ大規模で不自然なサテライトサイトを取り締まるアップデートとコピーコンテンツや役に立たない質の低いサイトを取り締まるアップデートです。2匹の動物の活躍により黒帽子は姿を消しました。
そして現代、これこそあるべき姿というユーザーの役に立つ質の高いコンテンツが評価される白帽子、通称ホワイトハットSEOが世界のデファクトスタンダードになっています。
それでは白帽子の世界ではどのようにしたら上位の検索結果を得られるのでしょうか？？

##採点基準たち
例
①多くの種類のキーワードで検索結果にヒットさせる
②有益なコンテンツが掲載されているページを増加させる
③トップページを充実させるより、下層のページを充実させる。
④3段階構造、トップページから2クリック以内で各ページにたどり着ける構造にすることでクローラーが巡回率をあげる。
⑤テキストのリンクを設置する。テキストのリンクのほうが画像のリンクよりも巡回率が高い。
⑥パンくずのリストを設置する。
⑦一覧画面などのページネーションの表示は前へ次へなどより数字のほうがいい。
⑧リンクにリンク先の内容がわかるようなテキストを設定する。
⑨被リンクの多さ。
⑩重複コンテンツは減点される。別々のURLでアクセスできる同じ内容のページなどがあると減点対象。「www.」のあるなしなど。

これら以外にも基準となる項目はいくつもあると思います。明確な基準はgoogleしか知りません。
そしてクローラーの採点基準は流行とともに変わるものです。
さてここで問題です、採点基準の細かな変化はどこに注目すれば気づけるでしょうか？？
はい正解です。**検索結果の一覧**ですね。

①**上位に表示されているサイト**と比較してみる。被リンクサイトを見るツールもあるらしいので、ライバルの流入元に自分も入る努力を、、
②**検索結果ページの下にある検索ワードのサジェスト一覧**。ここでサジェストされているワードはやはり人気ということなので取り扱っていると上位に表示されたりされなかったり。
③**検索結果の差し込み**。たまに検索してみるとサイドカラムや結果の中に動画があったりすると思います。そういう時はそのワードの検索者は動画を求めているのでは？と予測できます。動画に限らずその検索ワードで調べる人たちの求めているものを取り込んでみるのも一つの手かも。

##まとめ
現代のSEOは努力すればした分だけ返ってきます。
そのためにはクローラー、ひいては世間の流行を抑えることが大事となります。
日々情報を収集しながらよりよいサイト作りを楽しみましょう！！
それではしーゆー　ねくすと　た～いむ

##参考にさせて頂いたサイト
https://innova-jp.com/3711/
https://ds-b.jp/media/pages/209/
Simple URL to Send Email

#メール送信用のパラメータ

http://forcetips.blogspot.com/2013/02/url-hack-to-send-email-by-simple-button.html

p3_lkid : Related To retURL ? Return URL if cancel is pressed 
p2_lkid : To (Contact or Lead ID)
p3 : Related to name (input text) 
p4 : CC 
p5 : BCC 
p6 : Subject 
p23 : Email Body 
p24 : Additional To template_id ? ←　間違えている？ 正解はこっちSalesforce Email Template ID 
p26 : From Email Address

separate with semicolons is right

```
p24={!WF_Outreach_Version__c.Project_Manager_Email__c}+;+{!WF_Outreach_Version__c.Listening_English_Email__c}

```
https://support.conga.com/content/contracts/conga-contracts-administrator-guide/program-basics
Djangoいまさらまとめ

# いまさらのDjangoまとめ
Web開発初心者。
チュートリアルを読み下した自分用メモ。

# Django

ジャンゴと発音。
※python3.6以降をサポートしている。

* pythonのウェブフレームワークの一つ
* ウェブフレームワークとは
webサービスの実装を手助けしてくれるテンプレートのこと。
ウェブサービスを作りやすいように、
ウェブフレームワーク側でいろいろな機能を提供してくれている。
Djangoの場合DBとやり取りが楽に書けるらしい。
ただし、制約：階層やファイル名の規則が定義されており、ちゃんと従わないと動かない。

## WSGI(web server gateway interface)
WebアプリケーションとWebサーバを接続するためのインターフェース
Apacheの代わりにWSGI使う。
Webサーバ上ではこれでDjangoを実行する。
本環境ではGunicornを使用

## Django標準のDB:sqlite3
Djangoではクエリ文がほぼ隠蔽されてる
代わりにmodelでデータ型を定義
他にもPostgreSQL,MySQL,Oracleが使用できる
DBを冗長化させるにはこちらを使用するべきか
本環境ではSQLiteを使用

## 使い方

```console
$ django-admin startproject mysite #step1:プロジェクト作成
$ cd mysite ## 作成したdjangoのプロジェクトに入ったら、manage.pyがあるはず。そのdirまで移動。基本操作はmanege.pyで実施
$ python manage.py startapp polls #pollsはサーバ名、公式から流用 #step2:開発用サーバ作成
```

### フォルダ構成
公式Documentの例を引用する。

- mysite/
	- manage.py
	- mysite/
		- __init__.py
		- settings.py	#設定統括。アプリケーションやmodelが何かをここで定義必要
		- urls.py
		- asgi.py
		- wsgi.py
	- polls
		- __init__.py
		- admin.py
		- apps.py
		- migrations/
			- __init__.py
		- models.py	#データベースのレイアウトとそれに付随するメタデータ
		- tests.py	#テストはここ	
		- views.py	
		- url.py 	#URLconfを記載自分で作成必要、ここにも作っておいたほうがわかりやすい)


### url定義
url内の'url_pattern'リスト内にpath関数で指定する。

```python:polls/url.py
path('<int:question_id>/', views.huga, name='detail') #ここで指定した文字列をurlの名前としてhtml内でも使える。
```

これを、htmlファイル内でこう表現することができる。

```html
<li><a href="{% url 'detail' question_id %}">{{ question.question_text }}</a></li>
```

実際は、一つのプロジェクト内で複数アプリがあるため、まずそこで名前空間を分けて、全体で見てユニークになるようにする。

```python:polls/url.py
appname = 'polls'
urlpatterns = [
	path('<int:question_id>/', views.huga, name='detail'),
	]
```

```html
<li><a href="{% url 'polls:detail' question_id %}">{{ question.question_text }}</a></li>
```


### djangoサーバ操作

```console
$ python manage.py runsever #開発用サーバ起動。本番用サーバはWSGIで起動させるので違うコマンドになる
$ python manage.py migrate #INSTALLED_APPSを参照＆settings.pyファイルのDB設定に従ってデータベーステーブルを作成
$ python manage.py makemigrations polls #モデルの変更をDBに反映する
$ python manage.py createsuperuser #管理用ページのユーザを作成する
```

### HTTPレスポンス作成

```python:polls/views.py
from django.http import HttpResponse
from django.template import loader
from .models import Question

def index(request):
	latest_question_list = Question.object.order_by('-pub_date')[:5]
	template = loader.get_template('polls/index.html')
	context = {'latest_question_list':latest_question_list}
	return HttpResponse(template.render(context, request))
```

HTTPレスポンスはrender関数を使って書ける

```python:polls/views.py
from django.shortcuts import render
from .models import Question

def index(request):
	latest_question_list = Question.object.order_by('-pub_date')[:5]
	context = {'latest_question_list':latest_question_list}
	return render(request, 'polls/index.html' , context)
```

一旦ここまで。つづきは汎用ビューとかから
Rails に LivenessProbe 用のコントローラーを作る

ハラ 二 シボウ ガ タマッテキマシタネー

# 定期健康診断をうけさせられる
とある会社のクラウドシステムにはヘルスチェック機能がついて、Kubernetes の LivenessProbe に監視させていると、ロードバランサーにアクセスさせないという方法がとれる。しかしながら、その機能を使うにはデフォルトの設定だと URI のルートを参照するので、ホームページに下手に DB や キャッシュなんかを多用している場合は DDoS を受けているのと変わらない状態になってしまう。そんなことにならないように、今回はヘルスチェック専用のコントローラーを作って、動いているのをチェックさせたい。

# コード
今回のコードは [Github のレポジトリ](https://github.com/seahal/qiita) にアップロードしてあります。
### Routing 
```ruby
Rails.application.routes.draw do
  resource :health_check_up, only: [:show]
end
```
DHH が REST を活用しろ、とのことだったので一つだけしか画面がないのに、resource をつかってルーティングを書く。
### Controller
```ruby
# health_check_ups_controller.rb
class HealthCheckUpsController < ApplicationController
  def show
    render plain: Time.new.strftime('%c [OK]'), status: 200
  end
end
```
今回は Rails のジェネレータを使うといろいろファイルができちゃうので、ベタに /controllers/ 以下に上記のコードを打ち込む。

### 動作確認
![Screenshot from 2020-05-07 07-52-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190937/b1c7e3f3-9c41-15fc-eb49-050ae19cfc16.png)
とこんな感じになって良さそう。

### テストを書く
#### コントローラーにテストを書く
```ruby
require 'test_helper'

class HealthCheckUpsControllerTest < ActionDispatch::IntegrationTest
  test "should get show" do
    get health_check_up_url
    assert_response 200
  end
end
```
コントローラーにテストを書くのって、どうだっけ？


#### システムテストを書く
```ruby
require "application_system_test_case"

class HealthCheckUpsTest < ApplicationSystemTestCase
  test "visiting the index" do
    visit health_check_up_url

    assert_selector "body", text: /\d{1,2}:\d{1,2}:\d{1,2}/
    assert_selector "body", text: /OK/i
  end
end
```
二点測定をテストを書くのって、こんな感じでよかったかな？



# おわりに
計算機科学ノ進歩、発展ノタメニハ、犠牲ガツキモノナノデース.
初心者がQiitaでGoogle アナリティクスを試そうとして最初に躓いたこと

# この記事を読むとわかること
* QittaへのGoogleアナリティクス設定教訓
* Qiitaへの投稿がない状態でのGoogleアナリティクスの挙動（リアルタイム/概要）

# 対象者
* Qiita連携を考えているGoogle アナリティクス初心者

# 背景
広告とかマーケティングとかどうやるんだろうと思い、Google アナリティクスを触ってみようと思った

# 何が起きていたか
Qiitaへの投稿が0のアカウントに[公式](https://qiita.com/Qiita/items/c7f704e3786df3aa7a11)の設定に従い設定。
しかし、「4. 正しく設定できたか確認する」でアクティブユーザ数がカウントされない（0のまま）。

<img width="1338" alt="スクリーンショット 2020-05-07 7.35.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367586/27de612a-9c6f-f32b-bf80-1ab066139e49.png">

# 何をしたのか
以下のようなことをしました。

* 類似事象調査
* トラッキングIDに誤りがないか確認＆コピペ
* プロパティやビュー削除してから再作成
* マイページへの訪問

上記を2hくらいループしていましたが、
そもそもカウントの対象って何だっけと思い試しにテスト記事を書いてみたら・・・
<img width="887" alt="スクリーンショット 2020-05-07 7.38.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367586/7a401f37-19a4-10b0-0718-982cebf3159b.png">

出来たやん・・・
そりゃあ記事が解析対象だよねーと反省
過去のアクセスとか他どういう風に利活用できるかは今後確認していこう。
<img width="1338" alt="スクリーンショット 2020-05-07 7.37.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367586/4fa8e3b9-0a6b-6dd7-0731-94411f64f7ab.png">

# まとめ
* Qiitaに記事が投稿されていない状態ではGoogleアナリティクス（リアルタイム/概要）は動作しない
* Qiitaに記事を投稿してから設定・動作確認しましょう