OmniAICreator/Qiita-1.07M huggingface dataset:
Listを利用した組み合わせパターンの列挙

#1.概要
これまで組み合わせの全パターンを取得する際には、1文字単位でのアナグラム方式で順列の列挙を行っていた。
例、A.B.C では以下の 3! (= 6) パターン

```java
ABC
ACB
BAC
BCA
CAB
CBA
```
参考：<a href="https://qiita.com/masakinpo/items/b6ae147d9a61b592240a">全組み合わせの列挙 Java</a>

しかし、上記の方法だと2文字以上の値をひとつの要素として扱いたいときに上手くいかなかった。（※例えば、4.8.10 の場合、10をひとつの要素としたいが、1文字単位で組み換えが起こるため、以下のように4.8.1.0 の 4! パターンで列挙されてしまう)。

```java
4810
4801
4180
4108
4081
4018
8410
8401
8140
8104...
以下略
```

そこで、文字数に関わらない順列の列挙をどうにかして実現できないかと考えた。
#2.Listを利用した要素の列挙
上記参考ではcharの集合であるStringを利用して組み合わせパターンを列挙しており、であれば集合体が配列であってもパターンの列挙は実現可能な筈である。上記参考ではメソッドの中で要素のサイズが変調しているため、可変長配列であるListを利用することを思いついた。

以下、作成したコード

```java

    public static void main(String[] args) {
        String[] sArray = {"4", "8", "10"};
        List<String> sList = new LinkedList<>(Arrays.asList(sArray));
        List<String> cList = new LinkedList<>();
        permutation(sList, cList);
    }
    
    private static void permutation(List<String> sList, List<String> cList) {
    	for (int i = 0; i < sList.size(); i++) {
    		if (sList.size() == 1) {
    			cList.addAll(sList);
    			System.out.println(cList);
    		} else {
    			List<String> base = new LinkedList<>(sList);
    			List<String> container = new LinkedList<>(cList);
    			container.add(base.get(i));
    			base.remove(i);
    			permutation(base, container);
    		}
    	}
    }  
```

以下、出力

```java
[4, 8, 10]
[4, 10, 8]
[8, 4, 10]
[8, 10, 4]
[10, 4, 8]
[10, 8, 4]
```

目的であった文字数に関わらない順列の列挙を実現した。
#3.まとめ
取り急ぎコーディングしたため、もっといい形での書き方があるかもしれない。

プログラミング初心者であり、Qiitaも初投稿のため、何かご指摘の点などございましたらご意見いただけると幸甚です。
Zigbeeのおさらい

# Zigbee エンドデバイスを作る場合の設定

Zigbee エンドデバイスに必要な設定は大きなレイヤ順に以下の通りです。

- 周波数を指定
- チャンネルを設定
- デバイスタイプを設定
- アドレス設定
- エンドポイント番号を設定
- プロファイルIDを設定
- クラスタを設定

## 周波数

IEEE802.15.4が使われていて、IEEE802.15.4は以下の仕様となっています。

| 周波数帯域 | チャネル | 変調方式 | データ転送速度 | 地域 |
|:---:|:---:|:---:|:---:|:---:|
|868MHz|0|BPSK|20kbps|主に欧州|
|915MHz|1〜10|BPSK|40kbps|主に北米、南米|
|2.4GHz|11〜26|O-QPSK|250kbps|日本を含む世界|



## チャンネル

2.4GHz帯を使う場合はチャンネルが11〜26となります。
全てのチャンネルをスキャンして接続先を探すこともできますが、チャンネルマスクを設定して任意のチャンネルの組み合わせのみで使うこともできます。

## デバイスタイプ

コーディネーター、ルーター、エンドデバイスがあり、今回の目的ではエンドデバイスを指定します。

## アドレス設定

通信に使用するアドレスはIEEE 802.15.4デバイス製造時に付加される64ビットのロングアドレスと、稼働時に割り振られる16bitのショートアドレスがあります。Zigbeeではショートアドレスを主に使います。エンドデバイスのショートアドレスは、PAN接続時にコーディネーターから割り当てられます。

## エンドポイント番号を設定

TCP/IP の ポート番号のように、通信に番号をつけてアプリケーションごとに管理できます。

## プロファイルIDを設定

Zigbee AllianceにおいてプロファイルIDが規定され、それに対応する通信パケットの通信形式と解釈が定義されています。
例えば、パブリックプロファイルとして定義されているものとして以下のものがあります。 
Home Automation Profile = 0x0104


パブリックプロファイルは Zigbee Alliance が策定するもので、プライベートプロファイルは製造者が製造者固有プロファイルの認定を受けた上割り当てた番号が使えるようになります。


## クラスタを設定

パブリックプロファイルでは、データ形式や単位があらかじめ規定されています。送るデータの種類ごとにクラスタという番号で以下のように定義されています。

```

・・・


  /* General clusters */
  ZB_ZCL_CLUSTER_ID_POLL_CONTROL = 0x0020,          /**< Poll control cluster identifier. */
  ZB_ZCL_CLUSTER_ID_GREEN_POWER  = 0x0021,          /**< Green Power cluster identifier. */

  ZB_ZCL_CLUSTER_ID_KEEP_ALIVE = 0x0025,            /**< Keep Alive cluster identifier. */

  /* Closures clusters */
  ZB_ZCL_CLUSTER_ID_SHADE_CONFIG = 0x0100,          /**< Shade configuration cluster identifier. */
  ZB_ZCL_CLUSTER_ID_DOOR_LOCK = 0x0101,             /**< Door lock cluster identifier. */
  ZB_ZCL_CLUSTER_ID_WINDOW_COVERING = 0x0102,       /**< Window covering cluster identifier. */
  /* HVAC clusters */
  ZB_ZCL_CLUSTER_ID_PUMP_CONFIG_CONTROL = 0x200,    /**< Pump configuration and control cluster
                                                      identifier. */
  ZB_ZCL_CLUSTER_ID_THERMOSTAT = 0x201,             /**< Thermostat cluster identifier. */
  ZB_ZCL_CLUSTER_ID_FAN_CONTROL = 0x202,            /**< Fan control cluster identifier. */
  ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL = 0x203,        /**< Dehumidification control cluster
                                                      identifier. */
  ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG = 0x204,   /**< Thermostat user interface configur
・・・

```



# 資料

https://zigbeealliance.org/wp-content/uploads/2019/12/07-5123-06-zigbee-cluster-library-specification.pdf

日本語仕様書(旧1.7) http://www.wirelessdesign.jp/doc/zigbee-spec_081209.pdf

ZigBee入門 - Skyley Support Wiki
http://www.skyley.com/wiki/index.php?ZigBee%E5%85%A5%E9%96%80
#Rails ransack で null または not null の検索をする例

```
Book.ransack(user_id_null: true).result
```

```
Book.ransack(user_id_not_null: true).result
```

[how to?: search with condition OR 'is null' · Issue #290 · activerecord-hackery/ransack](https://github.com/activerecord-hackery/ransack/issues/290)

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3146











<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
用語集

# いろんな用語

いろいろ勉強していく中で用語の意味が分からなくて積んだので、、自分用です。


**インターフェース**
何かと何かを繋ぐもの
例えばUSBなんかもインターフェース（パソコンと周辺機器を繋ぐものだから）

**API**
Application Programming Interface」の頭文字
ソフトウェア同士をつなげるもの

**APIキー**
APIの呼び出し元のプロジェクト（アプリケーションまたはサイト）を識別する

**認証トークン**
アプリまたはサイトを利用するユーザー（個人）を識別する


#　参考資料
https://data.wingarc.com/what-is-api-16084
https://cloud.google.com/endpoints/docs/openapi/when-why-api-key?hl=ja
【JavaScript】【RPGツクールMV】alert,confirmを使った利用規約

alert,confirmの理解に加え、ゲームでの応用を考えてみました。

##alert
alert("文字列")でポップアップを表示

##confirm
confirm("文字列")でOK,キャンセルを問うポップアップを表示

OKを押下した際はtrueを返すので、if文と組み合わせることで設問に対する処理も行える

##応用例　RPGツクールMVでalert,confirmを使った利用規約確認

要件：
・confirmで設問
・キャンセル時にalertでメッセージを表示後、ウィンドウを終了
・テストプレイ時は実行しない

```js

    //rpg_scenes.jsの391行目の処理。起動時に実行される。
    Scene_Boot.prototype.start = function() {
      Scene_Base.prototype.start.call(this);
      SoundManager.preloadImportantSounds();
      if (DataManager.isBattleTest()) {
          DataManager.setupBattleTest();
          SceneManager.goto(Scene_Battle);
      } else if (DataManager.isEventTest()) {
          DataManager.setupEventTest();
          SceneManager.goto(Scene_Map);
      } else {
          this.checkPlayerLocation();
          DataManager.setupNewGame();
          SceneManager.goto(Scene_Title);
          Window_TitleCommand.initCommandPosition();
      }
      this.updateDocumentTitle();
      //ここから追加処理。
      if(!$gameTemp.isPlaytest()){//テストプレイではないときに実行
        const answer = confirm("利用規約に同意しますか？");
        if (answer){
          //OK押下時の処理。同意したら二回目以降は問わないフラグを立て、if(!$gameTemp.isPlaytest()の実行条件にすれば便利になる
        } else {
          //キャンセル押下時の処理
          alert("終了します");
          window.close();
        }
      }
    };
```

結果、正しく動作することができました。

![20200506_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372612/e4724002-0290-7aad-6f17-5a8f1b8d7b3a.jpeg)

![20200506_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372612/3c0abeb6-ac2b-5e07-0c07-c299fbaf96b4.jpeg)

##課題
同意した際に変数を変化させ、2回目以降確認しない処理ができませんでした。

具体的にはScene_Boot.prototype.startの処理前に
let confirmAnswer = 0;
とし、

```js

      if(confirmAnswer === 0){
        if(!$gameTemp.isPlaytest()){//テストプレイではないときに実行
          const answer = confirm("利用規約に同意しますか？");
          if (answer){
            confirmAnswer = 1;
          } else {
            alert("終了します");
            window.close();
          }
        }
      }
```

のとしても、起動都度、let confirmAnswer = 0;を読んでしまうためか、confirmAnswer = 1の値が保持されないのか、毎回確認が発生してしまいました。
勉強不足を痛感した次第です。
解決したら加筆します。
Windows 10 でISOファイルをマウントする

#やりかた
拡張子がisoの場合、
エクスプローラ上でアイコンを右クリック=>マウント
でマウント可

#いつから？
昔のWindowsは別途ツールが必要でしたが、
Windows 10 は標準機能でいけちゃうんですねー
Automatically assigning platform `iOS` with version `8.0` on target `Runner` because no platform was specified. Please specify a platform for this target in your Podfile. 

flutterの勉強の過程で、わりと古いGitHubにアップされたコードを手元にインストールして立ち上げようとしてみたら、上の様なエラーがでた。

結論から述べると、puspec.yamlファイルに記載されたdependenciesが古過ぎた様子。
使用されているパッケージのバージョンを全て最新に変えた上で、pub getし、再度runしてみると無事立ち上がった。
テーブル結合 コマンドプロンプトによるALTER TABLE

-- コマンドプロンプトによるALTER TABLE
-- テーブル名を変更
-- alter table テーブル名　rename 新しいテーブル名;
alter table sample01 rename sample02;
show tables;
-- カラム名を変更　変更するカラムのデータ型も指定する
-- カラム名を変更
-- alter table テーブル名　change 変更するカラム名　データ型;
desc sample02;
alter table sample02 change id Number int;
desc sample02;

desc sample02;
alter table sample02 change mail mailaddress varchar
(255);
desc sample02;
-- カラム名を変更mailというカラムををmailaddressに変更

-- カラムのデータが頼みを変更alter tableのあとにmodifyを使用
-- class enumをvarcharに変更する
desc sample02;
alter table sample02 modify class varchar
(255);
desc sample02;
-- テーブルの追加
-- テーブルを追加する際は、alter tableのあとにaddを使用します。
-- alter table テーブル名　add　カラム名　データ型；
desc sample02;
alter table sample02 add age int;
desc sample02;
-- ageというカラムをデータ型をintにして追加

-- カラムを削除する際は、alter tableのあとに drop を使用します
-- alter table テーブル名 drop カラム名;
-- classというカラムを削除
alter table sample02 drop class;
desc sample02;

alter table sample01 rename sample02;
desc sample02;
-- sample01をsample02に変更　名前

alter table sample02 change id Number int;
desc sample02;
-- sample02のカラムidをNumberに変更しデータ型intを指定し　desc sample02;で構造を確認

-- カラムのデータ型を変更
-- alter table テーブル名　modify カラム名　新しいデータ型

alter table sample02 modify class varchar
(255);
desc sample02;
-- sample02のカラムclassのデータ型をvarchar(255)に変更

alter table sample02 add age int(11);
desc sample02;
-- データ型がint(11)カラムageを追加

alter table sample02 drop class;
desc sample02;
-- classカラムを削除

-- テーブル結合

-- 内部結合

-- 写経
select *
from table_a inner join table_b on table_a.fruit_id = table_b.fruit_id;
-- inner join on table
-- idと同じ数字の欄を結合

select *
from table_b inner join table_c on table_b.place =table_c.place;
-- placeと同じ文字列の欄を結合

select *
from table_b left outer join table_a on table_a.fruit_id = table_b.fruit_id;
-- 左外部結合
-- LEFT　OUTER　JOIN
-- fruit_idと同じ数字の欄を結合 
-- table_bを基準として抽出してtable_aをtable_bに結合させた。

select *
from table_a right outer join table_b on table_a.fruit_id = table_b.fruit_id;
-- 右外部結合
-- right outer join
-- fruit_idと同じ数字の欄をaを基準にbが結合

select *
from table_a inner join table_b on table_a.fruit_id = table_b.fruit_id;
-- 内部結合

select *
from table_a left outer join table_b on table_b.fruit_id = table_a.fruit_id;
-- aとbを左外部結合

select *
from table_a right outer join table_b on table_a.fruit_id = table_b.fruit_id;
-- aとbを右外部結合
[Rails] ユーザー登録時に、子モデル・孫モデルを関連付けしたい時


##前提
devise使用。
ユーザー登録すると、とある`post`（子）とそのいいね`like`（孫）をデフォルト登録されるようにしたい。
アソシエーションは、User：Post：Comment = １：多：多

##ユーザー登録時に子モデルをビルド


```registrations_controller.rb
  def create
    super
    # 子モデルのビルド
    resource.posts.build( cotent: "あほ" )
    resource.save
  end
```
superのあとにビルドするコードを普通に記述する。

##ユーザー登録時に子孫モデルのビルド

```registrations_controller.rb
  def create
    # 子モデルのビルド
    post = resource.posts.build( cotent: "あほ" )
    post.save
    # 孫モデルのビルド
    comment = post.comments.build( content: "あほあほ" )
    comment.save
  
```
以上！
Excel×Pythonで作業フローを効率化する方法を調べてみた、自分記事まとめ★

自分の記事をまとめてみた。

####Excel×Pythonで作業フローを効率化する方法を調べてみた①
PythonでExcelファイルを操作する環境準備作業
https://qiita.com/t20190127/items/9298546576b6456da7e2
####Excel×Pythonで作業フローを効率化する方法を調べてみた②
PythonでExcelファイルを取り込み、別名でExcelとcsvファイルを出力
https://qiita.com/t20190127/items/023e5dd0128252f46378
####Excel×Pythonで作業フローを効率化する方法を調べてみた③
PythonでExcelファイルを取り込み、書式を追加して出力
https://qiita.com/t20190127/items/e682cfcc104d8f0cfeb4
####Excel×Pythonで作業フローを効率化する方法を調べてみた④
PythonでExcelファイルを取り込み、グラフを追加して出力
https://qiita.com/t20190127/items/2a069f3e4e1fd37afe70
####Excel×Pythonで作業フローを効率化する方法を調べてみた⑤
PythonでExcelファイルをPDFに変換して出力
https://qiita.com/t20190127/items/4788699feb81526ebab7
eslint install (linter to js)

https://www.npmjs.com/package/eslint

#Installation and Usage
Prerequisites: Node.js (^8.10.0, ^10.13.0, or >=11.10.1) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
前提条件：Node.js() SSLが支援しているものでビルドされているもの(普通公式サイトで配布されているNode.jsを使ったら、その中でSSLは入っているはず)

You can install ESLint using npm:
npmを利用してESLintをセットアップしましょう

```$ npm install eslint --save-dev```
You should then set up a configuration file:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/b143bc8f-b12c-ebb4-b229-852cca051a7c.png)


```$ ./node_modules/.bin/eslint --init```
After that, you can run ESLint on any file or directory like this:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/91efd3fd-79fd-b638-6496-7d2ad90594a2.png)
なんか選べる~~

```$ ./node_modules/.bin/eslint yourfile.js```



#拡張(Extensions)セットアップ
eslint-plugin-prettier
https://github.com/prettier/eslint-plugin-prettier

In addition to the above installation instructions, install eslint-config-prettier:

```npm install --save-dev eslint-config-prettier```
Then you need to add plugin:prettier/recommended as the last extension in your .eslintrc.json:

```json
{
  "extends": ["plugin:prettier/recommended"]
}
```

This does three things:

Enables eslint-plugin-prettier.
Sets the prettier/prettier rule to "error".
Extends the eslint-config-prettier configuration.
You can then set Prettier's own options inside a .prettierrc file.

In order to support special ESLint plugins (e.g. eslint-plugin-react), add extra exclusions for the plugins you use like so:

```json
{
  "extends": [
    "plugin:prettier/recommended",
    "prettier/flowtype",
    "prettier/react",
    "prettier/standard"
  ]
}
```
For the list of every available exclusion rule set, please see the readme of eslint-config-prettier.
PythonとArduinoを連携してIMEのOn/OffをLEDで表示する

#概要
IMEのOn/Offがどうしても覚えられないので、機械に頼ることにしました。
IMEの状態をPythonで取得して、シリアル通信でArduinoに教えます。

#Python
下記の追加モジュールを使用します。pipなどでインストールしてください。
* serial
* pywin32

```python:python.py
from ctypes import *
from time import sleep
import win32gui
import win32con
import win32api
import serial

imm32 = WinDLL("imm32")

while True:
     hWnd1 = win32gui.GetForegroundWindow()
     hWnd2 = imm32.ImmGetDefaultIMEWnd(hWnd1)
     #下記の0x005は、IMC_GETOPENSTATUSを示しています。
     IMEStatus = win32api.SendMessage(hWnd2 ,  win32con.WM_IME_CONTROL, 0x005, 0)
     
     #COM7は、接続先のシリアルポートに応じて変更してください。
     ser = serial.Serial('COM7',9600)
     if IMEStatus == 0:
          ser.write(b"b")
     else:
          ser.write(b"a")
     ser.close()
     sleep(0.05)  # 秒単位（=50ms)
```
#Arduino
シリアルで受けて、LEDのOn/Offを判断しています。

```c:arduino.ino
const int PinLED = 13;

int responseDelay = 10;  // ミリ秒単位
char input_char;

pinMode(PinLED, OUTPUT);
Serial.begin(9600);

void loop() {
if (Serial.available() >0){
    input_char = Serial.read(); 

    if(input_char == 'a'){
      digitalWrite(PinLED, HIGH); 
    }else{
      digitalWrite(PinLED, LOW);
    }
 delay(responseDelay);
}
Zoom SDKをPHPとJavaScriptでサクッと動かす

Zoomのビデオ通話を最短で動かしてみる。

# 準備

ZoomのApp MarketplaceでCreated Apps => JWTを選択し、API KeyとAPI Secretを取得する。

# ソースコード

`$apiKey`, `$apiSecret`, `$meetingNumber`などを変更し、以下のソースコードを　PHPの動作する環境に設置してアクセスする。

## Signature作成

```
<?php
$apiKey = '**********';
$apiSecret = '**********';

$meetingNumber = '0000000000';
$role = '0'; // 1 is host, 0 is participants

$time = time() * 1000 - 30000;

$data = base64_encode($apiKey . $meetingNumber . $time . $role);

$hash = hash_hmac('sha256', $data, $apiSecret, true);

$sig = $apiKey . "." . $meetingNumber . "." . $time . "." . $role . "." . base64_encode($hash);

$signature = rtrim(strtr(base64_encode($sig), '+/', '-_'), '=');
?>
```

## ページ

```
<html lang="ja">
<head>
    <link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.7.5/css/bootstrap.css" />
    <link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.7.5/css/react-select.css" />
</head>
<body>
<script src="https://source.zoom.us/1.7.6/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/1.7.6/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/1.7.6/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/1.7.6/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/1.7.6/lib/vendor/jquery.min.js"></script>
<script src="https://source.zoom.us/1.7.6/lib/vendor/lodash.min.js"></script>

<script src="https://source.zoom.us/zoom-meeting-1.7.6.min.js"></script>
<script>
    ZoomMtg.preLoadWasm();
    ZoomMtg.prepareJssdk();
    ZoomMtg.setZoomJSLib('https://dmogdx0jrul3u.cloudfront.net/1.7.6/lib', '/av');

    ZoomMtg.init({
        debug: true,
        leaveUrl: 'https://xxx.xxx/leave.php',
        isSupportAV: true,
        success: function() {
            ZoomMtg.join({
                signature: '<?php echo $signature; ?>',
                apiKey: '<?php echo $apiKey; ?>',
                meetingNumber: <?php echo $meetingNumber; ?>,
                userName: 'name',
                userEmail: '***@gmail.com',
                passWord: '',
                error(res) {
                    console.log(res);
                }
            });
        }
    });
</script>
</body>
</html>
```
とりあえず役にたちそうなLinkをまとめてみる

#はじめに

自分の知識が古すぎてつらいので、いろいろ学び中。そのためのメモ。

#R
 
###tidyverse

```R:
library(tidyverse)
```

- https://tidyverse.tidyverse.org/

###その他
いろいろなモジュールのチートシート。
- [RStudio Cheatsheets](https://rstudio.com/resources/cheatsheets/)


#Python
###pandas

```python
import numpy as np
import pandas as pd
```

- [pandas User Guide](https://pandas.pydata.org/pandas-docs/stable/user_guide/index.html#user-guide)

###seaborn
matplotlibをベースにした、よりきれいなグラフが描けるモジュール。set関数はデフォルトがstyle='darkgrid'になっており、sns.set()だけでggplotライクなグラフが描ける。ggplotもいじれば見た目は変わるだろうけど。

```python
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

sns.set()
```
- [Official seaborn tutorial](https://seaborn.pydata.org/tutorial.html)

###scikit-lean
- https://scikit-learn.org/stable/index.html

#GCP

###Big Query

###AI Platform Notebook
JupyterからRが使える！

- [AI Platform Notebooks のドキュメント](https://cloud.google.com/ai-platform/notebooks/docs?hl=ja)
よく使う Git コマンドまとめ

## はじめに
最近 Git に関する勉強会を主催しました。
その中でコマンド操作がイマイチ分からないとの声が多かったので、
よく使うコマンドをまとめてみました。

## ブランチを切る
### ブランチを切るだけ
```
git branch <ファイル名>
```
### ブランチを切って移動する場合
```
git checkout -b <ブランチ名>

git switch -c <ブランチ名> （ver2.23.0以降はこちらでも可）
```
## ブランチを移動する場合
### ブランチを指定して移動
```
$ git checkout <ファイル名>

$ git switch <ファイル名> （ver2.23.0以降はこちらでも可）
```
### 直前のブランチに移動する場合
```
$ git checkout -

$ git switch - （ver2.23.0以降はこちらでも可）
```
## ブランチを削除する
### マージ後
```
$ git branch -d <ブランチ名>　（-d はマージ前だと削除できない）
```
### マージ前（強制削除）
```
$ git branch -D <ブランチ名>
```
## ファイルをステージングエリアに追加する
### 個々にファイルを指定する場合 
```
$ git add <ファイル名> (ファイルは半角スペースで区切って複数選択可)
```

### 変更した全てのファイルを指定する場合
```
$ git add . (現在のディレクトリ以下の変更内容全てをステージングエリアへ追加）
```
## ステージングエリアに上げた変更を取り消す
### 全ての変更を取り消す場合
```
$ git reset (git reset HEAD と同じ）
```
### ファイルを指定する場合
```
$ git reset <ファイル名>
```
## 変更ファイルを確認する
```
$ git status
```
## 差分を確認する
### ステージングエリアに追加する「前」のファイルを確認する場合
```
$ git diff
```
### ステージングエリアに追加した「後」のファイルを確認する場合
```
$ git diff --staged
```
## コミットする
### コミットメッセージを複数行入力したい場合
```
$ git commit （エディターでコメントを入力する）
```
### コミットメッセージを１行で入力したい場合
```
$ git commit -m "<コミットメッセージ>" （※エディターでの入力を省略できる）
```
## コミットを修正したい場合　(リモートへ push した後は注意が必要）
### 最新のコミットを上書きする
```
$ git commmit --amend 
```
## コミット履歴を確認する
```
$ git log
```
### コミット履歴から変更差分を確認したい場合
```
$ git log -p
```
### コミット履歴を１行ごとに表示したい場合
```
$ git log --oneline
```
### 
## リモートへ push する
### 現在のブランチを push する場合
```
$ git push origin HEAD
```
## リモートリポジトリの情報をローカルに反映する
### 現在のローカルのブランチにリモートのブランチの内容を反映させる
```
$ git pull origin HEAD
```
## ファイルの変更自体をなかったことにしたい場合
### Git が追跡していてステージングエリアに追加していないとき
#### `ファイルを指定したい場合`
```
$ git checkout <ファイル名>

$ git restore <ファイル名> （ver2.23.0以降はこちらでも可）
```
#### `全てのファイルの変更を取り消したい場合`
```
$ git checkout .

$ git restore . （ver2.23.0以降はこちらでも可）
```
### Git ステージングエリアに追加したファイルを全てなかったことにしたい場合
```
$ git reset --hard  (git reset --hard HEAD と同じ)
```
---

その他、必要に応じて適宜追加していきたいと思います。

※ やりたいことに辿り着くのに、方法が１つではないのでどれが1番分かりやすいか模索しています
dockerのイメージ一覧APIのfiltersパラメータについて

こんにちわ。
ゴリラです。

dockerのイメージAPIを`curl`で叩いた時にイメージをフィルターしたいが、詰まっていたのでそのやり方を備忘録として残しておきます。

## やりたいこと
`curl`でdockerのイメージ一覧を絞り込みたい。
`docker`コマンドだとこんな感じ。

```sh
$ docker images -f reference=mysql
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7                 84164b03fa2e        2 months ago        456MB
```

## やりかた
筆者はfishをつかっているため、`urlenc`コマンドの実行結果を`()`で取得していますがbashなどの方は`$()`に置き換えてください。

```sh
curl -s --unix-socket /var/run/docker.sock (urlenc -e 'http://localhost/images/json?filters={"reference": ["mysql"]}') | jq
[
  {
    "Containers": -1,
    "Created": 1583343003,
    "Id": "sha256:84164b03fa2ecb33e8b4c1f2636ec3286e90786819faa4d1c103ae147824196a",
    "Labels": null,
    "ParentId": "",
    "RepoDigests": [
      "mysql@sha256:f4a5f5be3d94b4f4d3aef00fbc276ce7c08e62f2e1f28867d930deb73a314c58"
    ],
    "RepoTags": [
      "mysql:5.7"
    ],
    "SharedSize": -1,
    "Size": 455508074,
    "VirtualSize": 455508074
  }
]
```

## 解説
[公式のAPI定義](https://docs.docker.com/engine/api/v1.40/#operation/ImageList)には
`A JSON encoded value of the filters (a map[string][]string) to process on the images list. Available filters:`
と書いてあって、なるほどわからんって状態だったので、わかったことを解説します。

以下がポイントです

1. 検索条件は`filters`クエリパラメータで指定
2. 指定する時のJSONの形は`{"key": [xxx, yyy]}`という形でなければいけない(goの`go[string][]string}`をJSONにエンコードした形)

今回はイメージ名をつかって絞り込みたいので`filters`には`{"reference": ["イメージ名"]}`をエンコードした値を渡しています。

ちなみに、`urlenc -e 'http://localhost/images/json?filters={"reference": ["mysql"]}'`はエンコードしたURLを取得できます。

```sh
$ urlenc -e 'http://localhost/images/json?filters={"reference": ["mysql"]}'
http://localhost/images/json?filters=%7B%22reference%22%3A+%5B%22mysql%22%5D%7D
```

検証に使った`urlenc`はこちらに置いてあります

https://github.com/skanehira/go-enc
pythonでElasticsearchを操作する（登録・検索）

# 目的

* pythonからElasticsearchを操作する
* python、Elasticsearchは別々のDockerコンテナで動作し、それぞれはdocker-composeで起動している

# やらないこと

* docker-composeで行うDockerコンテナの起動方法（参考：[DockerコンテナでElasticSearchを起動する（docker-compose）](https://qiita.com/hiroky_814/items/7a8ddddd472d47f6435b)）
* pythonの基礎知識（importとか）

# 環境

* OS: macOS Catalina 10.15.4
* Docker: 2.2.0.5
* docker-compose: 1.25.4
* ElasticSearch: 7.4.2

# やったこと

## 登録処理を作成

コンテナでのpip installやコンテナ名は、構築した時の投稿を参照してください（参考：[DockerコンテナでElasticSearchを起動する（docker-compose）](https://qiita.com/hiroky_814/items/7a8ddddd472d47f6435b)）

``` python:registration.py
import os
import elasticsearch

# 接続先のElastisearchを指定（今回はElasticsearchのコンテナ名を指定）
client = elasticsearch.Elasticsearch("elasticsearch")

game = {}
game['title'] = 'hiroky quest'
game['genre'] = 1
game['release_date'] = '2020/05/01'
game['memo'] = 'memo'
# indexを指定して登録を行う
client.index(index='games', doc_type='_doc', body=game)
```

接続先は今回はDocker Networkを使用しているので、コンテナ名を指定する
（ローカルで起動しているElasticsearchであれば「localhost:9200」を指定する）

``` python
# 接続先のElastisearchを指定（今回はElasticsearchのコンテナ名を指定）
client = elasticsearch.Elasticsearch("elasticsearch")
```

indexはRDSのテーブルにあたるものである（はず）で、RDSと違うところはindexを作らなくても登録を実行すると自動でindexを追加してくれる
mappingも自動で作成される（RDSのテーブル定義みたいなもの）

``` python
# indexを指定して登録を行う
client.index(index='games', doc_type='_doc', body=game)
```

## 検索をして登録を確認する

``` python:search.py
import os
import elasticsearch

# Elasticsearchのコンテナ名を指定（Docker Network）
client = elasticsearch.Elasticsearch("elasticsearch")

# index指定で検索
result = client.search(
    index='games'
)
print(result)
```

``client.search``で検索を行う。この場合はindexを全件検索する

``` sh
# python3 search.py
{'took': 11, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 1, 'relation': 'eq'}, 'max_score': 1.0, 'hits': [{'_index': 'games', '_type': '_doc', '_id': 'AAyn53EBfM-Vwr_FW_d7', '_score': 1.0, '_source': {'title': 'hiroky quest', 'genre': 1, 'release_date': '2020/05/01', 'memo': 'memo'}}]}}
```

検索条件を指定して検索することも可能

``` python:search.py
import os
import elasticsearch

# Elasticsearchのコンテナ名を指定（Docker Network）
client = elasticsearch.Elasticsearch("elasticsearch")

# 条件検索
result = client.search(
    index='games',
    body={'query': {'match': {'genre': 1}}}
)

print(result)
```

この場合は``'genre': 1``に該当するレコードが検索結果として得られる
``'match'``は完全一致として検索する

# 感想

pythonのclientの使い方が簡単なので、楽に実装できた
まだ単純な登録と検索のみなので、使い込んでいきたいところ
CentOS7にDocker, MySQL, Gitをインストールする方法(Vagrantfileあり)

忘れてはググるをあまりにも多い回数繰り返しているので、備忘録を兼ねて書きます。全部httpdみたいに思考停止のyumで入ってくれればいいのにと常々思っています。

👇Vagrantfileはこちら
https://github.com/Polarbear08/centos7-vagrant


## 環境
* CentOS Linux release 7.8.2003

## 各種ソフトウェアのインストール
すべてroot権限で実行しています。
### Docker
参考：[Install Docker Engine on CentOS](https://docs.docker.com/engine/install/centos/)
最新版が入ります。

```
# 既にDockerが入っていたら、アンインストールする
yum remove docker \
              docker-client \
              docker-client-latest \
              docker-common \
              docker-latest \
              docker-latest-logrotate \
              docker-logrotate \
              docker-engine

# 依存パッケージのインストール
yum install -y yum-utils device-mapper-persistent-data lvm2

# Docker CE をインストール
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum makecache fast
yum install -y docker-ce

# Dockerサービスを起動
systemctl enable docker
systemctl start docker
echo $(docker --version)
```

### Docker Compose
参考：[Install Docker Compose](https://docs.docker.com/compose/install/")
下記方法では1.25.5が入ります。バージョンは適宜書き換えて指定してください。
リリース一覧：[docker/compose releases](https://github.com/docker/compose/releases)

```
curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod 755 /usr/local/bin/docker-compose
echo $(docker-compose --version)
```


### MySQL
参考：[MySQL Installation Guide](https://dev.mysql.com/doc/mysql-installation-excerpt/5.7/en/)
rpmファイルのリリースバージョンは変わる可能性があるので、そんなファイルないよ的なエラーが出たときは[yumリポジトリのページ](https://dev.mysql.com/downloads/repo/yum/)をご確認ください。

* 8.0.xを入れる場合

```
yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
yum install -y mysql-community-server

# mysqldサービス起動
systemctl enable mysqld
systemctl start mysqld
echo $(mysql --version)
```


* 5.7.xを入れる場合

```
yum localinstall -y https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum install -y mysql-community-server

# mysqldサービス起動
systemctl enable mysqld
systemctl start mysqld
echo $(mysql --version)
```

### Git
参考：[Git のインストール（ソースからビルドする場合）](https://qiita.com/silverskyvicto/items/c4ce4552a030c2205fd2)
**`yum install git`してはいけません。**とんでもなく古いもの(バージョン1.8.3.1)を入れられてしまいます。
下記方法では2.26.2が入ります。yumでgit2が入ってるリポジトリを追加する方法もありますが、バージョンが古めだったのでソースからビルドします。
ちょっと時間がかかります。

```
# 必要なパッケージをインストール
yum install -y wget openssl-devel libcurl-devel expat-devel

# git本体を入手
mkdir -p /usr/local/src
cd /usr/local/src
wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.26.2.tar.gz
tar xf git-2.26.2.tar.gz
rm -rf git-2.26.2.tar.gz

# gitをビルド
cd git-2.26.2
make prefix=/usr/local all
make prefix=/usr/local install
echo $(git --version)
```


## 以上をまとめたVagrantfile
https://github.com/Polarbear08/centos7-vagrant
ベースのboxは[centos/7](https://app.vagrantup.com/centos/boxes/7/)(virtualbox)です。


## おわりに
ProでないWindowsユーザがDockerを使いたいとなったら、Vagrant(+Virtual Box)が非常に便利です。また、Vagrantにはスクラップ&ビルドが容易という利点もあります。ただ、マシン作成のたびに必要ソフトをインストールするのは割と面倒なので、だいたいいつも使ってるなあというソフトはあらかじめVagrantfileに突っ込んでおくと楽ですね。
apache log を python で csv にする


## apache_log_parser を install

```bash
pip install apache_log_parser
```

## 下記コードを作成

ほぼ下記なんですが、一部バグフィクス
https://github.com/isonet/apache-log-to-csv

```python:alog2csv.py
#!/usr/bin/env python
# coding: utf-8

import csv
import apache_log_parser
import argparse

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'


def main(**kwargs):

    print('Converting, please wait...')

    line_parser = apache_log_parser.make_parser(kwargs['format'])
    header = True

    with open(kwargs['input'], 'rb') as inFile, open(kwargs['output'], 'w') as outFile:

        lines = inFile.readlines()
        writer = csv.writer(outFile, delimiter=',')

        for line in lines:
            try:
                log_line_data = line_parser(line)
            except apache_log_parser.LineDoesntMatchException as ex:
                print(bcolors.FAIL + 'The format specified does not match the log file. Aborting...' + bcolors.ENDC)
                print('Line: ' + ex.log_line + 'RegEx: ' + ex.regex)
                exit()

            if header:
                writer.writerow(list(log_line_data.keys()))
                header = False
            else:
                writer.writerow(list(log_line_data.values()))

    print(bcolors.OKGREEN + 'Conversion finished.' + bcolors.ENDC)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Convert Apache logs to csv', version='%(prog)s 1.0')
    parser.add_argument('format', type=str, help='Apache log format (see http://httpd.apache.org/docs/2.2/logs.html)')
    parser.add_argument('input', type=str, help='Input log file ex. /var/log/apache/access.log')
    parser.add_argument('output', type=str, help='Output csv file ex. ~/accesslog.csv')
    args = parser.parse_args()
    main(**vars(args))
```

## 実行する

`alog2csv.py format source output` の順

```bash
python alog2csv.py "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" access_log_20200430 output.csv
```
B2 Cloud StorageのS3互換APIをboto3から試してみた

Backblaze B2 Cloud StorageがS3互換のAPIに対応したとのことなので、boto3から接続してみました。



- S3互換APIの仕様
https://www.backblaze.com/b2/docs/s3_compatible_api.html

- チュートリアル
https://help.backblaze.com/hc/en-us/articles/360047629793?_ga=2.53071599.676934675.1588719972-849540261.1588719972


# 必要なもの

- Backblazeのアカウント

# バケット作成・バケット一覧・ファイルアップロードを試してみる

###1. boto3.client経由

```test1.py
BUCKET = 'sirotosiko-b2-test1'
MYFILE = 'test.txt'

s3 = boto3.client('s3',
endpoint_url = 'https://s3.us-west-002.backblazeb2.com',
aws_access_key_id = '<b2_keyId>',
aws_secret_access_key = '<b2_appKey>')

res = s3.create_bucket(Bucket=BUCKET)

res = s3.list_buckets()
for bucket in res['Buckets']:
    print(bucket['Name'])

with open(MYFILE, 'rb') as data:
    s3.upload_fileobj(data, BUCKET, MYFILE)
```

```
$ python test1.py 
sirotosiko-b2-test1
```

###2. boto3. resource経由

```test2.py
import boto3

BUCKET = 'sirotosiko-b2-test2'
MYFILE = 'test.txt'

s3 = boto3.resource('s3',
endpoint_url = 'https://s3.us-west-002.backblazeb2.com',
aws_access_key_id = '<b2_keyId>',
aws_secret_access_key = '<b2_appKey>')

mybucket = s3.create_bucket(Bucket=BUCKET)

buckets = s3.buckets.all()
for bucket in buckets:
    print(bucket)

mybucket.upload_file(MYFILE, MYFILE)
```

```
$ python test2.py 
s3.Bucket(name='sirotosiko-b2-test1')
s3.Bucket(name='sirotosiko-b2-test2')
```

### 3. 作成されたバケットとファイルの確認

作成したバケットの一覧

<img width="707" alt="bucket_after.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192584/15e24241-f832-40f7-32dc-eadb17d7f0ad.png">

アップロードしたファイルの一覧

<img width="701" alt="file_after.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192584/71504a63-79c0-a491-5e3d-b4a2041094ee.png">

<img width="713" alt="file_after2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192584/88545378-b0a2-6d5e-1713-e845a2fa7158.png">

# 雑感

- そのままboto3から違和感なくアクセスできました。
- GCP AnthosのAWS対応とか、どんどんクラウドの垣根がなくなっていく感じがします。
Excel×Pythonで作業フローを効率化する方法を調べてみた⑤

#今回の目的
PythonでExcelファイルをPDFに変換して出力する。
※例のごとく、説明はプログラムのコメントで記載しています。

###事前準備
Win32comパッケージのインストール（PythonでのCOMを通じたExcel操作のため）
https://github.com/mhammond/pywin32/releases
ここから、自分の環境に合わせてダウンロードインストール（pythonのバージョン、64ビットか32ビット）
※pipでもいいのかな？（やっていないですが）

###プログラムの流れ
①sample_pdf.xlsxファイルを取り込む
②PDFファイル名を作成（pdf_[title]_[createdate].pdf　※[]はエクセルから取得）
③PDFファイルを出力する

#プログラム実行結果確認
※プログラムは一番下

###取り込むエクセル（sample_pdf.xlsx）
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/076d4a46-8ff8-34cc-9bb5-f894274dfab8.jpeg)

###出力ファイル（pdf_[title]_[createdate].pdf）
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/51b42f3c-6072-43e9-1f27-57f7124395ef.jpeg)
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/a1bb78b1-de3a-45b9-378d-4a59a42699c8.jpeg)

#プログラム
```python:pdf_create.py
import pathlib
import openpyxl
from win32com import client

#読み込むエクセルファイル
in_filepass = pathlib.Path("./data/sample_pdf.xlsx")

#win32com > client > Excel操作オブジェクトを取得
xlApp = client.Dispatch("Excel.Application")

#sample_pdf.xlsxを取得（※resolveは相対パス⇒絶対パス）
book = xlApp.workbooks.open(str(in_filepass.resolve()))

for sheet in book.Worksheets:

    #エクセルからタイトル（セルC2）を抽出
    title = str(sheet.Range("C2").value)
    #エクセルから資料作成日付（セルH2）を抽出
    createdate = str(int(sheet.Range("H2").value))

    #出力するPDFのファイルパスobjを作成（pdf_[title]_[createdate].pdf）
    out_filepass = pathlib.Path("./data/output/pdf_" + title + "_" + createdate + ".pdf")

    #PDFファイルを出力（※resolveは相対パス⇒絶対パス）
    sheet.ExportAsFixedFormat(0, str(out_filepass.resolve()))

book.Close()
xlApp.Quit()
```

#まとめ
PDFもできました。やった感がありますね！
ただ、PDFはネットを調べているとExcelに戻せそうなので改ざんされると困るのであれば、使えなさそうですね。
win32comパッケージですが、いろんな事ができそうです。
ショートカットをつくったり、メールを自動保存したり。
このあたり、調べてみるのも面白い気がしました。

以上です、ありがとうございました(*'▽')
（備忘録）AWS EC2モニタリング

# 1. はじめに
2020年5月6日に[ヤマムギ](https://yamamugi.connpass.com/)様主催にて開催された[ヤマムギ vol.10 (AWS)EC2モニタリングハンズオン](https://yamamugi.connpass.com/event/174798/)について、自分への備忘録としてまとめてみました。ご参考になれば幸いです。

# 2. 学んだ内容

- 環境準備
- IAMロールにポリシーを追加
- CloudWatch Agentのインストール
- CloudWatch Agentの設定
- 必要パッケージのインストール
- CloudWatch Logsエージェントの開始
- メトリクスフィルタの作成
- ダッシュボードを作成動作
- 動作確認
- リソースの削除

# 3. 学習サイト

- [ヤマムギ vol.10 (AWS)EC2モニタリングハンズオン 手順](https://www.yamamanx.com/yamamugi-10-handson/)


# 4. ハンズオンで得た豆知識

- Run CommandでOptional Configuration Locationのパラメータ名指定で、AmazonCloudWatch-linuxと入力せずに、AmazonCloudWatch-Linux（LinuxのLを大文字）とすると正常動作せずにハマるらしい。（AmazonCloudWatch-linuxと指定することが正解）
- リソースの削除は、作成した手順を逆順にたどりながら削除してゆき、最後にEC2インスタンス状態を終了すればOK。（メトリクスフィルターの削除は、その後に個別削除でOK。）
- [メトリクスフィルターの削除](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/DeletingMetricFilter.html)の仕方がわかりづらい。

# 5. 参考サイト

- [メトリクスフィルターの削除](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/DeletingMetricFilter.html)

# 6. おわりに
AWS学習の参考になれば幸いです。
ハンズオン開催してくださいました[ヤマムギ](https://yamamugi.connpass.com/)様、感謝いたします。

2020/05/06 NISHIZONO Takahiro
YouTuberになってみた結果【2ヶ月分のデータを全公開】

# 背景
これからは動画の時代なのではないか？
と思い立ち、動画作成とマーケティングが学べそうだったのでYouTubeを始めてみました。


**youtubeチャンネルはこちらです**
https://www.youtube.com/channel/UC9ZSQjR4502aRkU5rJpJ7dg/
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/9a1b8a1d-2a93-5502-cf1c-5e3da38a2f0f.png">

# やったこと
## 期間
**3月6日-5月6日**の2ヶ月間
ほぼ毎日1本程度動画を上げ続けました。(偉い！)
今、現在は127本ほどですね。
多い…

## 内容
内容はわからないことやっても駄目だと思ったので、技術情報系をメインで行いました。

 * プログラミング学習系
 * 環境構築方法、使い方系
 * 電子工作、RaspberryPI系
 * プログラミング学習用のゲームの実況
など

## 作成方法
**前半：** 
基本的に先に声が入った動画を撮影して、それをiMovieで加工しました。

**中盤：** 
基本は前半と同じなのですが、バックグラウンドの音楽と終了画面を追加しました。

**後半；** 
まず、技術的に可能か確認後、台本を作成し、撮影…その後声を入れてそれに合わせて動画加工しています。

>台本書くのがすごく辛い…
>あとしゃべるとどうしても つっかえたり どもる。

# 結論(2020年5月6日 現在)
## 登録者数
登録者：22人

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/693b4eb6-4da6-1606-5244-e9a3eb6ea6c9.png)


>厳しいですね。
>多分ですが前半と後半で来ていただいて見ていただいたときに、
>過去動画などがクオリティが異なることも原因だと思っています。
>過去のものをある程度消して、必要なものをとりなおすことを検討してみます。
>根本的に面白くない説も大いにあります。

## 視聴回数/総再生時間
視聴回数：1195回

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/70938d63-38eb-7cc2-1fb5-2ce51f9159e0.png)

総再生時間：32.1時間

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/6199341a-b59a-76d5-d88f-3cac66ee2aaa.png)

>全体的に視聴回数はあまり大きく変わっていないですが、視聴時間が増えているのでいい傾向だとは思っています。
>もう少し高いクオリティのものを求めているのかなとも思っていますが…そもそも視聴回数が増えないということは
>題材/題名が悪いかサムネイルが悪いんですよね。
>題材を大きく変えることを検討したほうが良いかも。


## 人気の動画

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/84b7fd6d-95cd-3f36-3fac-0ba002a6de4a.png)

>電子工作系が人気ですね。
>Qiitaにもリンクが張ってあるのでそちらからの流入もあると思います。

一番人気の「距離センサ使ってみた」です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/3cc02579-fc06-032a-c178-f1f52e273396.png)

どこから来たかを確認してみると「ブラウジング機能」から来ていることが分かります。
ブラウジング機能とはYoutubeのトップ画面に出てくるおすすめ動画のことのようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/0ea717a7-00b1-874e-c32c-feb6dbfc67ca.png)

>やはり、外部からの流入を期待するのではなく、Googleに気に入られて 
>お気に入りに表示してもらったほうが視聴回数は伸びそうですね。
>このような動画を増やして、気に入られて 伸びないものは削除していったほうが効率が良いような気もします…

## リーチ
リーチはどのような人たちにGoogleが私の動画を宣伝したか？
宣伝した結果どうなったのか？などが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/9c44698f-86ee-1a44-e03c-952a4bc87683.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/260eb4ee-645f-1144-a1d5-1febc495a1f0.png)

>インプレッションのクリック率は上がっていません。
>サムネイルと題名のクオリティはそこまで上がっていないという意味なのか…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/ccf02ad6-ac11-9717-c2b4-a6a8eba8e910.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/08396023-3aeb-b5c8-69bd-d8a415924157.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/5a75ca27-f727-ab90-6b0d-d5fab985f507.png)

>全動画対象なのでよくわからないですね。

## 視聴者

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/98271dff-1bd5-e1a4-165b-0aeaeae28b9a.png)

>ジャンルが原因なのか、超偏っています。

# 最後に
散々な結果になりますが、もう少しチャレンジして進めていきたいと思います。
また、このデータが見たい！などがあれば、コメントいただければ追加いたします。

ご観覧ありがとうございました。
どうかチャンネル登録をよろしくおねがいします！
（正直クソほど嬉しいです）
【Salesforce】リード取引開始時の取引先と個人取引先の比較

# 動作確認
取引先の場合、リードから1.取引先、2.取引先責任者、3.商談が作成され、
個人取引先の場合、リードから1.取引先、2.商談が作成されます。

## 取引先
※「取引開始時、商談は作成しない」にチェックすると、商談を作成しない
<img width="1044" alt="スクリーンショット 2020-05-06 11.20.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/06b9a1da-fef5-62e1-aca8-7cff177f9e62.png">

## 個人取引先
※「取引開始時、商談は作成しない」にチェックすると、商談を作成しない
<img width="1050" alt="スクリーンショット 2020-05-06 11.21.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/70bff55d-b167-0584-c898-041c2136eccf.png">

# 実現方法
## 取引先
取引先に関しては特に必要な手順はありませんでした。

## 個人取引先
Developer Editionで技術調査していたところ、個人取引先を有効化する手段が見つからず、
困っていたのですが、以下サイトの情報で一時的な個人取引先を有効化している環境を用意できました。
[Salesforce Tips: 無料で個人取引先が有効な組織を作りたい](https://sfblog.markhammer.net/entry/2019/06/24/090000)

個人取引先を有効化するとリードの会社名の必須チェックを外すことができます。
そこで会社名をブランクで保存することで、リード取引開始時に個人取引先が作成できます。
[リードの会社名項目を必須でなくする](https://help.salesforce.com/articleView?id=000325733&language=ja&type=1&mode=1)

# 参考リンク
[Salesforce との個人取引先の同期](https://help.salesforce.com/articleView?id=pardot_sf_connector_person_accounts_parent.htm&type=5)
上記リンク先にて記載していますが、「Pardot は Salesforce の個人取引先と同期できます。この機能を有効にする場合は、Pardot サポートまでお問い合わせください。」とのことですね。

[リードの取引開始に対するリードのカスタム項目の対応付け](https://help.salesforce.com/articleView?id=customize_mapleads.htm&type=5)
リードで作成したカスタム項目は上記のリンクの方法で紐づけることが可能です。
## リードの項目の対応付け

<img width="1674" alt="スクリーンショット 2020-05-06 14.10.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/e50d8bfb-7e26-2e6b-e1f6-c0f8d9e3f339.png">

<img width="1401" alt="スクリーンショット 2020-05-06 14.11.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/0a26ac78-744c-a546-9197-187dca7cbc13.png">

## リードレコードに値を設定

<img width="856" alt="スクリーンショット 2020-05-06 14.12.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/3852734e-bc55-4e01-ca06-7ea79f3d71bc.png">

## 取引開始

<img width="1108" alt="スクリーンショット 2020-05-06 14.13.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/2002b24f-89a1-d891-772a-6eff6dc8d15d.png">
Herokuでお名前.comの独自ドメインを設定する

##Herokuにてdomainを設定
###「Add domain」でドメインを追加

##お名前.comでの設定
###DNSレコード
|ホスト名|Type|TTL|VALUE|
|:--:|:--:|:--:|:--:|
|ドメイン名|CHAME|3600|（DNSターゲット）|
###ネームサーバー
| ネームサーバー名 |  |
|:--|:--|
| ネームサーバー1 | 01.dnsv.jp |
| ネームサーバー2 | 02.dnsv.jp |
| ネームサーバー3 | 03.dnsv.jp |
| ネームサーバー4 | 04.dnsv.jp |

参考
-
[お名前.comで購入したドメインをHerokuに設定する](https://qiita.com/ozin/items/62bc7ef1dd3c827177fb)
Android Studioでimport 'package:xxx'の補完が効かなくなったらやるべきこと

Android Studioでimport 'package:flutter' などのpackageについての補完が効かなくなった時は、

1. `.dart_tool` を削除
2. Android Studioを再起動 または、$ flutter pub get

すると、補完が効くようになります。

参考: https://stackoverflow.com/questions/59665885/flutter-android-studio-import-package-path
AWS AmplifyのチュートリアルでJavascript(React)の環境を構築する（その２）

いつも忘れないように、コンセプトから。

###コンセプト
・お金かけてまでやりたくないのでほぼ無料でAWSを勉強する
　→ちょっとしたサービスを起動すると結構高額になりやすい。
・高いレベルのセキュリティ確保を目指す
　→アカウントを不正に使われるととんでもない額を請求されるので防ぐ

今日は[昨日行った「AWS AmplifyのチュートリアルでJavascript(React)の環境を構築する」](https://qiita.com/auf/items/98d9ff7a787fffa0fb16)の続きです。昨日は作ったままで終わりにしてしまったので、少し考察していきます。



###構築した環境をマネジメントコンソールから確認（Amplify編）
コマンドをクライアントから投入してできてしまったので、結局何が作られたのかよくわかっていません。作られたその都度確認すべきなんでしょうけど、リズムってもんがありますからね。

まずはマネコンにログインしてAmplifyの画面にいきます。作成したreact用のものがありますのでクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/3d8392a7-3b01-9952-e099-b20d5035ab4f.png)

すると、フロントとバックのタブがあって分かれています。フロントエンドには何もやっていませんね。普段はGitHubは使わずにローカルのGitLabを使っていますが、選択できそうなので今後試したいところです。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/fd3b25cc-6a39-410d-2877-6095254bc05c.png)

バックエンド側に遷移します。こちらには作成したdevがあります。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/76a90721-73f6-bca7-5334-cc17829b45e1.png)

devをさらにクリックするとどのように構築されたかがわかります。ちゃんと機能の日付になっていました。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/685c1af7-8945-8385-f7f2-70383115060b.png)

Auth設定はしていないのでAPIを見ていきます。GraphQLのAPIが作成されています。「View in AppSync」のタブもあるので後で見ていきます。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/807d5b77-b5bf-dc9f-3aeb-e1b64e834cca.png)


###構築した環境をマネジメントコンソールから確認（DynamoDB編）

データソースを確認します。概要を確認するとTodoテーブルがちゃんとできていました。どこでDynamoDBの設定をしていたかまで確認してなかったんですが、便利なもんですね。ちょっと前までDynamoはKMSに問題があって使ってなかったのですが、去年クリアされたので本格的に使ってみましょうか。。。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/0b901c01-e182-360f-514c-8d00c22ca571.png)

元々OracleエンジニアなんでDB周りは理解しやすいのですが、ちゃんと定義されたスキーマにデータが入っています。NameとDescriptionが昨日出来上がったGUIから入れた値です。TESTとTEST2で２件入れたのでちゃんと入っていました。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/ca81bb61-a983-67f5-90f5-edd4d9ef5d54.png)



###構築した環境をマネジメントコンソールから確認（Appsync編）

AppSyncは利用の検討すらしたことがないので全く知らないサービスです。ちょっと調べてみたところ、こちらのサイト↓が勉強になりました。
[「まだAPI Gatewayで消耗してるの？AppSyncのススメ」](https://qiita.com/nakayama_cw/items/b7e5db8d25b516440db7)
インフラエンジニアですし普段モバイルなんて接点も無いのでスルーしていましたが、なかなか便利そうですね。そもそもGWの勉強でAPIGatewayをもっと勉強しないといけないのかなぁと思っていたので、いろいろとためになりました。

さて、実際にAppSyncを見ていきます。スキーマ定義とクエリ、アプリからの利用ができる感じですね。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/b51786c2-ed12-76eb-3b80-48514e207f82.png)

スキーマ定義を見ていきます。ここは設定ファイルを確認した覚えがあるので、これなのね、という感じです。DynamoDBの定義とも一致してますね。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/f2108b67-b607-f6fc-df0f-b9b207c50879.png)

一旦確認はここまでです。なんとなくAmplifyを勉強してみようと思ってはじめましたが、AppSyncも出てきてお腹いっぱいです。とはいえ、便利であることは間違いなさそうなのでもうちょっと勉強してみようと思います。ちなみに、業務で使うにはいろいろと課題もあるので簡単には使えないですね。。。セキュリティの考え方が緩いのと、デプロイコントロールも緩いのでそれらをクリアする必要がありますが、ちょっと現状では打つ手無しという印象です。ライトにWebサイトを作ったり、モバイルアプリを作るにはいいかなと思いますけど。まあ技術トレンドや進化を知るにはやってみないとわからないことも多いのでいい勉強になりました。

チュートリアルもまだ残っているのでもう少し頑張りますか。。。
【GAS初心者ピットフォール】グーグルフォームでform.publishedUrlやform.setDestinationがエラーになる時 


#はじめに
こんにちはGoogle Apps Scriptを扱い初めてまだ２ヶ月の初心者山口です。ここ一ヶ月くらい悩んでいたエラーがやっと解決したのでQiitaに初投稿します。気づいてみれば初心者らしい基本的な間違いなのですが、ググってもヒットしなかったので、同じようなエラーに悩んでいる人のためにまとめました。

#やりたいこと：フォームの入力先URLを得る
グーグルフォームの入力用URLを毎日メールで配信しており、これを自動化したいとスクリプトを組んでました。

作業としてはテンプレートのformをコピーして新しいファイルを作り、フォームの入力先URLを得る(.publishedUrl)というだけの単純なスクリプトです。

```createform.js
function createform() {
 var templateFile = DriveApp.getFileById('XXXXXXXXXX');   //テンプレートのフォームのIDを取得
 var OutputFolder = DriveApp.getFolderById('yyyyyyyyyy'); //コピー先フォルダ
 var OutputFileName = 'hogehoge'　　//新しいファイル名
 
 var form = templateFile.makeCopy(OutputFileName, OutputFolder); //テンプレートをコピーしたものをformに
 var PublishedUrl = form.getPublishedUrl(); 　　　//入力用URL取得

```
しかし、これがエラーになるのです。回答先のシートを変更する(.setDestination)でも同じエラーが帰ってきます。

```typeError
TypeError: form.getPublishedUrl is not a function（行 7、ファイル「コード」） 
```

##TypeError:(オブジェクト)(メソッド) is not a function
このtypeErrorをぐぐってみると、

>・エラーの理由：関数以外のオブジェクトを関数呼び出ししている
・よくある原因：undefinedを関数呼び出ししている
・対策：undefinedに気をつける
（中略）
つまり、だいたいタイプミスかメソッド名の勘違いです。undefinedには気をつけましょう。
[Subterranean Flower Blog](https://sbfl.net/blog/2019/02/01/javascript-error-messages/)

とのことで目を皿のようにして何回もチェックしたり、webからコードをコピーして貼り付けたりしましたが、うまくいきません。１ヶ月ほど悶々と悩んで、今日やっと原因に気づきました。

#オブジェクトのクラスが違っていた
原因は formというオブジェクトがfileとして定義されていることでした。makeCopyというメソッドはFileクラスなので、それで得られたformもfileオブジェクトになっていたのでした。
あらためてformオブジェクトとしてopenしたところうまくいきました

```formOpen.js
var form = Formapp.openById('zzz')  //id=zzzのフォームを開く
```
普通フォームを作るときは

```createForm.js
  var form = FormApp.create('ファイル名');
```
という風にやると思いますが、これだとマイドライブにフォームが作られてしまって、そのあと希望のフォルダーに移動しないといけないので面倒です。いっぽうmakeCopyは同じフォルダーにコピーしてくれるので便利です。しかし、今回はこれが落とし穴だった訳ですね。すっぽりハマりました笑。

#コンテンツアシスト大事ですね
ちなみに気づいたきっかけはコンテンツアシストを使い始めたら、getpubshedUrlや.setDestinationが選択肢に出てこないことでした。もしかしてクラスが違うのかな？と思って、formとして開いたらうまくいきました。日頃からコンテンツアシストを使うのも重要ですね。

あとオブジェクトのクラスが調べられると良いなぁと思ったのですが、そのような機能はないようです。（あったら教えて下さい）

#まとめ
" is not a function"のエラーがでたら関数のスペルチェックとともにオブジェクトのクラスを確認
予防としてコンテンツアシストを日頃から使おう
Coursera の Machine Learning を受講して良かったこと・苦労したこと

# はじめに
[Coursera (コーセラ)](https://www.coursera.org/) の [Machine Learning](https://www.coursera.org/learn/machine-learning) を受講しました。受講して良かったこと，苦労したことを書き留めておき，今後，受講する人の後押しができればと思います。
Coursera の Machine Learnin の講座の内容そのものについては，[参考](#参考) の記事をご確認下さい。

# 受講したきっかけ
職場で，機械学習や深層学習をツールとして使う人がぽつぽつ出てきました。表面的には何となく話について行ってますが，中身がほとんど分かってません。そこで，緊急事態宣言 (2020/04/07) によって生じた時間で，機械学習を勉強しようと思いました。
勉強方法はいろいろありますが，たまたま Coursera の Machine Learning の紹介記事にたどり着き，トライしてみることにしました。

# 良かったこと
## 機械学習の知識が一通り身につきます
単に動画を聞くだけでなく，動画の途中のクイズや，テスト (5 問中，4 問以上正解しないと先に進めない)，まとまった分量の課題 ([Octave](https://www.gnu.org/software/octave/) で実装し，提出する) があるので，身についた感があります。
動画の最後の最後に，「ここまで受講した人は機械学習のエキスパートと言って良い」というようなことを言われるので，間違いないでしょう (笑)。

## 基本的なポイントを押さえることができます
機械学習が正しく動いているか確認するにはコスト関数が各繰り返しで減少しているか確認するとか，機械学習の精度がイマイチのときにデータを増やすのが正しいのかどうかとか，そのような「基本的なポイント」を理解することができます。

## Octave を使えるようになります
課題には，Octave を使います。一通りの課題をこなすうちに，Octave を使って普通に計算できるようになります。機械学習以外でも，普通のちょっとした計算にも便利です。

## 過度に数学に踏み込まない
行列計算は避けて通れませんが，偏微分やアルゴリズムの数学的な背景など，難しい数学については「このコースの範囲外だから」といってスルーしてくれます。でも必要なことは，直感的に理解できるように分かりやすく説明してくれるので，理解が中途半端でモヤモヤしながら先に進むということもありませんでした。

# 苦労したこと
## ニューラルネットワークが山場だった
振り返ってみると，ニューラルネットワークが山場でした。動画に映し出された行列をメモしているうちに説明が先に進んでしまうので，動画を止めて行列をメモした後に，再生して説明を聞きながら日本語訳を追いかけるということをしてました。
課題も，行列の掛け算で次元が合わないというミスを連発して苦労しました。
でもここを越えると，後は下り坂を降りていくようなイメージでした。

## Octave のデバッグ
Octave で自分の書いたプログラムが動かないと，解決のヒントが欲しいのですが，周りに聞く人がいません。そんなときは，プログラムが止まったときにコンソールで `whos` と打つと，課題のプログラムで使っている変数の一覧がでるので，行列のサイズを確認したり，手動で数式を入力して正しく動くかどうかを確認しました。

# 今後
ディープラーニングと Python を勉強しようと思ってます。
ディープラーニングは，Coursera に有料の[ディープラーニング専門講座](https://www.coursera.org/specializations/deep-learning) があります。ただし聴講だけなら [YouTube に同じ講座の動画がある](https://www.youtube.com/channel/UCcIXc5mJsHVYTZR1maL5l9w) ので，それを聴講しようと思います。
Python も Coursera に有料の [みんなのための Python 専門講座](https://www.coursera.org/specializations/python) がありますが，違うところで無料の講座を探そうと思ってます。

# 参考
- [機械学習をゼロから1ヵ月間勉強し続けた結果] (https://qiita.com/junichiro/items/3457e33e502086a200f1)