OmniAICreator/Qiita-1.07M huggingface dataset:
PHP: コロン構文（初心者向け）

`if` `while` `for` `foreach` `switch` に関する別の構文が***コロン構文***です。

[公式: 制御構造に関する別の構文](https://www.php.net/manual/ja/control-structures.alternative-syntax.php)

####基本的な考え方

各構造において***開き波括弧をコロン`:`***、***閉じ波括弧をそれぞれ `endif;`,`endwhile;`, `endfor;`,`endforeach;`,`endswitch;`に変更する***のが コロン構文の基本的な形式となります。

```php:sample_通常使わない形ですが、コロン構文の基本形はこうなります。
<?php
if ($a == 5):
    echo 'aは5に等しい';
else:
    echo 'aは5と等しくない';
endif;
?>
```
####タグとコロン構文の融合（重要）
####if 文[（公式）](https://www.php.net/manual/ja/control-structures.if.php#112231)
```php:sample_if
<?php
if ($a == 5) {
    echo 'aは5と等しい';
} else {
    echo 'aは5と等しくない';
}
?>
コロン構文
<?php if ($a == 5): ?>
aは5に等しい
<?php else: ?>
aは5と等しくない
<?php endif; ?>
```
####foreach 文[（公式）](https://www.php.net/manual/ja/control-structures.foreach.php#82511)
```php:sample_foreach
<?php
$users = [0 => ['name' => 'ichiro'],
          1 => ['name' => 'jiro'],
          2 => ['name' => 'saburo'], //最後のカンマはあってもなくても可（PHP5.4~）
];
foreach ($users as $user) {
    echo $user['name'] . '<br>';
}
?>
コロン構文1
<?php foreach ($users as $user): ?>
<?= $user['name'] . ','; ?>
<?php endforeach; ?>              //-> ichiro,jiro,saburo,

コロン構文2: foreachとif
<?php foreach ($users as $user): ?>
<?php if ($user['name'] == 'jiro'): ?>
<?= $user['name']; ?>
<?php endif; ?>
<?php endforeach; ?>              //-> jiro
```
####switch 文[（公式）](https://www.php.net/manual/ja/control-structures.switch.php#control-structures.switch)
```php:sample_switch
<?php
$user = 'ichiro';
switch ($user) {
    case 'ichiro':
        echo 'イチロー';
        break; 
    case 'jiro':
        echo 'ジロー';
        break; 
}                              //-> イチロー
?>
コロン構文: インデントを入れると無効なコードになる
<?php switch ($user): ?>
<?php case 'ichiro': ?>
イチロー
<?php break; ?>
<?php case 'jiro': ?>
ジロー
<?php endswitch; ?>             //-> イチロー
```
####while 文[（公式）](https://www.php.net/manual/ja/control-structures.while.php#control-structures.while)：　参考
```php:sample_while_コロン構文
<?php $i = 0; ?>
<?php while ($i <= count($users) - 1): ?>
<?= $i . ':' . $users[$i]['name'] . ','; ?>
<?php $i++; ?>
<?php endwhile; ?>              //-> 0:ichiro,1:jiro,2:saburo,
```

####for 文[（公式）](https://www.php.net/manual/ja/control-structures.for.php#control-structures.for)：参考
```php:sample_for_コロン構文
<?php for ($i = 0; $i <= count($users) - 1; $i++): ?>
<?= $i . ':' . $users[$i]['name'] . ','; ?>
<?php endfor; ?>              //-> 0:ichiro,1:jiro,2:saburo,
```

####endの後のセミコロンについて
`<?php endif; ?>` or `<?php endif ?>` ***？？***
公式を眺めていると`なし`の省略形を多用していますが、統一感があればどちらでもいいと思います

```php:セミコロン
コロン構文の基本形
<?php
if ($a == 5):
----
endif;          //-> セミコロンあり
?>
タグと融合している形
<?php if ($a == 5): ?>
----
<?php endif; ?>  //-> セミコロンなしは省略形
```

注： できるだけ短く記述するために、[ショートタグ](https://www.php.net/manual/ja/language.basic-syntax.phptags.php)`<?=`を使っています。
`<?=`は`<?php echo`の省略形です。

LGTMお願いします！
モチベーションがあがります！
laradockコマンド

### laradockフォルダ内で下記コマンドを実行しワークスペースコンテナに入る
```
docker-compose exec workspace bash
cd /var/www/web
composer install

npm install
npm run dev
```

### DBマイグレーションを実行し、DBテーブルを作成
```
php artisan migrate
```
### シーダーを実行し、テストデータ作成
```
php artisan db:seed --class=ItemsTableSeeder
php artisan db:seed --class=AdminUserTableSeeder
```
### マイグレーション、シーダーの実行をやり直す場合
```
rm -rf storage/app/public/images
php artisan migrate:fresh
php artisan db:seed --class=ItemsTableSeeder
```
【C#】【DxLib】サウンドタイプを"WASAPI"や"DirectSound"や"ASIO"にしたい。【 WASAPI共有対応 】

#概要
今回はDxLibの関数を利用して、サウンドタイプを"WASAPI"や"DirectSound"にする方法を紹介します。
誰でも簡単にできると思うので、やっていきましょう！

#やりたいこと
ソフトウェアのサウンドタイプを"WASAPI"や"DirectSound"にしたい。

#要素
``DX.DxLib_Init();``の前部に以下のコードを追加してください。

###DirectSound : ``DX.SetEnableWASAPIFlag(DX.FALSE);``
###WASAPI(共有) : ``DX.SetEnableWASAPIFlag(DX.TRUE, DX.FALSE);``
###WASAPI(排他) : ``DX.SetEnableWASAPIFlag(DX.TRUE, DX.TRUE);``
###ASIO : ``DX.SetEnableASIOFlag(TRUE);``

#使用例

```csharp
//enumを利用したほうがわかりやすいと思いますが、今回はintで分岐処理を行います。

//type = 0: DirectSound
//type = 1: ASIO
//type = 2: WASAPI(排他)
//type = 3: WASAPI(共有)
int type = 0;

switch (type)
{
	case 0:
		DX.SetEnableWASAPIFlag(DX.FALSE);
		break;
	case 1:
		DX.SetEnableASIOFlag(DX.TRUE);
		break;
	case 2:
		DX.SetEnableWASAPIFlag(DX.TRUE, DX.TRUE);
		break;
	case 3:
		DX.SetEnableWASAPIFlag(DX.TRUE, DX.FALSE);
		break;
	default:
		goto case 3;
}

```

#最後に
今回は以上です。
何か分からないことがあれば、ご気軽にコメント欄で聞いてください。
【コードレビュー】レビュアーの心構え

## はじめに

業務中、ふと「雰囲気でコードレビューしてしまっている」ということを自覚しました。
そこで、コードレビューにおいて気をつけていること、こうすればさらに良くなりそう！を言語化してみました。

「**雰囲気レビューを卒業したい**」、「**コードレビューの質を向上・体系化したい**」といった方はぜひ読んでみてください。

## ✊ レビュアーの役割

レビュアーが果たすべき重要な役割として、**システムの品質を保証する**ことが挙げられます。

- 要件不十分
- 不具合
- コード品質低下

などの発生責任は、レビュアーにも共有されます。
それらの発生を防ぐために、レビュアーが心がけるべきことをについて書いていきます。

## 👀 コードレビューの視点 

コードレビューのときに特に見るべき観点は、大きく分けると以下の３つです。

1. 仕様を満たしているか
2. バグが含まれていないか
3. コードの品質が低くないか

1と2は言わずもがな重要です。死ぬ気で見ましょう。

３はリリーススピードを優先するためにおざなりになりがちですが、品質の低下は**将来的なバグ発生や開発・レビューコストの増加**につながります。
忙しいからと言い訳せず、できるかぎり見るようにしましょう。

また、疑問・不安はしまいこまず、できるだけ解消するようにしましょう。
仮に意見が不適当だったとしても、あなたにとって学習の機会になり、同様の疑問を抱えている他のレビュアーの助けになります。

## 🗣 コードレビューの伝え方

指摘内容が妥当でも、伝え方が不適切だと反映されないという結果になりかねません。
良い意見を無駄にしないために、伝え方にも配慮しましょう。

### 指摘のしかた

指摘について書くべきは以下です。

1. 改善してほしいこと
1. 理由（根拠）
1. 解決方法

#### 1. 改善してほしいこと

何が課題なのか、該当行へのリンクやコードブロックなどを用いてわかりやすく説明しましょう。
このときに、頭ごなしに拒否せず肯定から入るようにすることで、より受け入れられやすくなります。

#### 2. 理由（根拠）

論理的な正しさを証明するためには**根拠を添えること**が効果的です。

- 仕様書
- 公式ドキュメントやリファレンス
- スタイルガイド
- 他参考サイト

参照元は１次情報に近ければ近いほど信憑性が高い為、その点も意識しましょう。

#### 3. 解決方法

課題提起にとどまるのではなく、解決のサポートまでできればベストです。
思いつかない場合でも議論を喚起するなどして、必要な協力を惜しまないようにしましょう。

ただし成長を促したい場合は、あえて解決方法まで教えないことも選択肢です。

### 心理的安全への配慮

#### なぜ心理的安全に配慮するべきか

それは、「正しく意見交換をする為」です。

レビューで少しでも辛い気持ちになったことはありませんか？（私はあります）
心理的安全性の欠如は、以下のようなことを引き起こします。

- 不健全な対立によるコミュニケーションの消極化
- モチベーションおよび生産性の低下

コードレビューのコメントでは基本的に意見の違いを伝えることになります。

間違いを受容することは、決して簡単ではありません。
その上理不尽だと感じる要求は、さらに受け入れがたいものになります。

#### どうすればいよいか

##### 「指摘のしかた」を遵守する

上で述べている「指摘のしかた」を心がけましょう。

**レビューイがコードの指摘を人格否定だと勘違いしてしまうこと**が、心理的安全を損なう要因の一つです。

論理的であることは大前提です。
その上で解決方法を提案し、寄り添うスタンスを示しましょう。

#### 褒める

コードレビューでは指摘が連なりやすく、レビューイの心は荒みがちです。
そうなりやすいことを強く念頭に置き、良い点にも積極的にリアクションするようにしましょう。

👍 のような絵文字１つでも、かなり雰囲気が和みます。

#### 感情を表現するツールを使う

テキストコミュニケーションは感情が伝わりにくく冷淡に受け取られやすいため、無自覚に相手にネガティブな印象を与えてしまっていることがあります😿

感情の受け取られ方に気を払うことで、それを未然に防ぐことができます💪
感嘆符（`！`）、絵文字、顔文字は感情を表現する強力なツールなので、ぜひ活用しましょう！！

ただ、このようなコミュニケーションが合わないという方もいらっしゃると思います🙋
そういう方はコメントをする前に一度読み返し、相手に不安を与えるような表現がないか確認することを習慣づけましょう！

## まとめ

コードレビューは開発者がメイン、レビュアーはサポート的立場だと考えがちですが、実際は責任を共有する立場です。
レビュアー側も当事者意識を持つことで、建設的なレビューを実現していきましょう😺

また、レビューを依頼する側の考えを理解しておくと、より歩み寄りがしやすいです。
[>> コードレビューを依頼する側の心構えはこちら](https://qiita.com/hinora/items/fb083a97d6e2ab8a9aa3)
【メモ】PCのJupyter Notebookを等幅フォント表示にする (Mac)

# はじめに
PCで動かすJupyter Notebookは、フォントがデフォルトでプロポーショナルになっているため、出力がガタガタしてなにかと不便。これを等幅フォントに変えるための手順です。
動作確認はMacでしています。

# 手順 
ターミナルを立ち上げて、以下のコマンドを実行します。

```sh
$ cd ~/.jupyter
$ mkdir custom
$ cd custom
$ echo '.CodeMirror pre, .output pre { font-family: Monaco, monospace; }' > custom.css
```

この状態で

```sh
$ Jupiter notebook
```

とすると、numpyの行列も次のようにきれいに表示されます。

![スクリーンショット 2020-09-25 9.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/60cece51-3b0f-c55d-ba47-1a7e7b7c71ca.png)

ご参考までに、上記のコードは私の著作[「Pythonで儲かるAIをつくる」](https://www.amazon.co.jp/dp/4296106961/)の実習コードの一部です。
他のコードを含めて下記リンク先にアップされていますので、関心ある方は参照されて下さい。

https://github.com/makaishi2/profitable_ai_book_info/blob/master/refs/notebooks.md
Swiftでデザインパターン【Factory Method】

元ネタ → [ochococo/Design-Patterns-In-Swift](https://github.com/ochococo/Design-Patterns-In-Swift#-factory-method)

# クラス図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37598/94bffe11-a6ae-090a-e664-e9a57ff51516.png)

図の引用元：[Wikipedia: Factory Method パターン](https://ja.wikipedia.org/wiki/Factory_Method_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)

# 概要
The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time.
Factory Methodパターンは、クラスコンストラクターを置き換えるために使用され、インスタンス化されたオブジェクトのタイプを実行時に判別できるように、オブジェクト生成のプロセスを抽象化する。

# サンプルコード
```swift
// Product
protocol CurrencyDescribing {
    var symbol: String { get }
    var code: String { get }
}

// ConcreteProduct
final class Euro: CurrencyDescribing {
    var symbol: String {
        return "€"
    }
    
    var code: String {
        return "EUR"
    }
}

// ConcreteProduct
final class UnitedStatesDolar: CurrencyDescribing {
    var symbol: String {
        return "$"
    }
    
    var code: String {
        return "USD"
    }
}

// like ConcreteCreator
enum Country {
    case unitedStates
    case spain
    case uk
    case greece
}
// Creator
enum CurrencyFactory {
    // factoryMethod
    static func currency(for country: Country) -> CurrencyDescribing? {

        switch country {
            case .spain, .greece:
                return Euro()               // インスタンス生成
            case .unitedStates:
                return UnitedStatesDolar()  // インスタンス生成
            default:
                return nil
        }        
    }
}

// usage //
let noCurrencyCode = "No Currency Code Available"

CurrencyFactory.currency(for: .greece)?.code ?? noCurrencyCode
CurrencyFactory.currency(for: .spain)?.code ?? noCurrencyCode
CurrencyFactory.currency(for: .unitedStates)?.code ?? noCurrencyCode
CurrencyFactory.currency(for: .uk)?.code ?? noCurrencyCode
```

# クラス図との対応
|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **CurrencyDescribing** |  **Product**  |

|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **Euro**, **UnitedStatesDolar**  |  **ConcreteProduct**  |

|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **CurrencyFactory** |  **Creator**  |
|  currency  |  factoryMethod  |

|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **Country** |  **ConcreteCreator**  |
※ConcreteCreatorではないが、具体的なProductを識別しているという意味で。


# 考察
`ConcreteProduct`は`CurrencyDescription`プロトコルに準拠させている。`CurrencyFactory`の`currency()`では、戻り値を`CurrencyDescription`にしておくことで（アップキャスト）、実行時にenumのcaseで、具体的な`ConcreteProduct`を判別・生成できるようになっている（**ポリモーフィズム**）。
Java等のサンプルでは、`Creator`の`anOperation()`のなかで、`ConcreteCreator`で実装された`factoryMethod()`が呼ばれていることが多い。
Firebaseのサイトをリダイレクトする

【背景】Firebaseで作成していたサイトを別サイトに移動、リダイレクトを実施

【実施】下記を参考にfirebase.jsonを変更
[Hosting 動作をカスタマイズする](https://firebase.google.com/docs/hosting/url-redirects-rewrites?hl=ja)

実際のfirebase.jsonは下記の通り

```json
{
  //既存  
  "hosting": {
   "public": "public",
     "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    
    //追加
    "redirects": [{
      "source" : "/",
      "destination" : "https://sisterroom.stchan130.com",
      "type" : 301
    }]
  }
}
```

【結果】問題なくリダイレクトできた
シンプルに「なぜinterfaceを使うのか」を考察

#それは実装をシンプルにして部品化を促すため
interfaceはカオスな**現実世界**と厳格な**コンピュータ世界**をつなぐ、あるいは分離する役割を担っています。
部品化しやすくするために、実装はできるだけシンプルに、複雑さはinterfaceがブロック！

#interfaceでは多重継承を許し、一般クラスでは許さない理由
interfaceはカオスな現実世界に近い業務**仕様**を記述するため、多重継承を許容することで、実装レベルの一般クラスの複雑化を代替します。

※補足
**シンプル化**：問題領域を小さくすることで、問題の連鎖や波及を制限し、部品としての汎用性が向上します。
**多重継承を許容**：言語によって差異はありますが、interfaceの意味を尊重するなら、他の言語でも一般クラスをinterfaceのようにするなどして、多重継承を自主的に制限することがオブジェクト指向の本来の利点を活用することになると考えます。

#おまけ#
interface間の関係性や条件を規定するのは、設計者です。
実装者は業務の複雑さを意識することなく、設計に従って淡々とコーディングしてゆきます。
ただし、interface内に実装（処理）条件を持ち込まないよう注意することが重要です。
逆に実装（処理）にinteface間の（業務）条件を持ち込まないよう注意することが重要です。
そのために、interfaceでは複雑さを表現するため多重継承を許可し、実装では複雑さを防止するため多重継承を制限します。

また、業務と処理を関連付ける**機能**は双方の**共通言語**になります。


※参考
業務、機能、処理ってなに？（本当は抽象化と哲学の話）
https://qiita.com/J_Cotan/items/3e28ee4cd52e2e2f199e
ffmpegでフォルダの中を一気に処理する

aviフォルダの中の動画ファイル（aviなど）を全部mp4に変換する

```avi2mp4.sh
# ffmpeg -i avi/MOVI0192.avi mp4/MOVI0192.avi.mp4
 ls avi/ | xargs -i ffmpeg -i avi/{} mp4/{}.mp4
```

フォルダの中のmp4を一個のmp4に連結する

```concat.sh
echo -n > list.txt
ls mp4/ | xargs -i echo file mp4/{} >> list.txt
ffmpeg -f concat -i list.txt -c copy concatmp4/$(date "+%Y%m%d").mp4
```

list.txtというファイルに連結すべきファイルを書いて、それをffmpegに引数としてわたしています。

xargsでリダイレクトされた各行を、次のコマンドの{}に渡しています。上記の例では、lsで出力されたファイルを名が{}に変換されて、繰り返しコマンドが実行されます。
【Rails】on: :actionの条件付きで設定したコールバックはskip_callback、set_callbackを用いて回避することができない

skip_callbackとset_callbackを用いて一時的にコールバックを回避しようとしたらset_callbackがうまくいかなかった。その時の状況と回避策を記録。

### やりたいこと
こちらのコールバックを一時的にスキップしたい。
```ruby
before_validation :func, on: :action
```

### 最初にやったこと
`skip_callback`、`set_callback`を用いて実装した。

```ruby
skip_callback(:validation, :before, :func)
------------------------------------------
# 処理を実行
------------------------------------------
set_callback(:validation, :before, :func)
```

しかし、このあと他の動作に不具合が出てしまい、原因を調査した。

#### skip_callback、set_callbackとは

`skip_callback`は設定されているコールバックをスキップさせることができる。ただし、一度実行するとずっとskipしたままになってしまうため、`set_callback`を用いて戻す必要がある。

### うまくいかない原因
`on: :action`の再設定ができていないため。


つまり、以下のようにコールバックの設定が変わってしまっていたため、挙動が変わってしまった。


```ruby
# スキップ前
before_validation :func, on: :action
# スキップ後
before_validation :func
```
### 対処

最初に行った`set_callback`は、`on: :action`に関して特に指定をしていない。
```ruby
set_callback(:validation, :before, :func)
```

set_callbackでは、`on: action`の設定をしておらず、`on: action`の設定が無くなってしまっていた。


`on: :action`の設定をしなければいけないため、onで設定している場合はその設定も引数に入れなければならないらしい。

https://stackoverflow.com/questions/46810340/how-to-set-callback-with-the-on-create-option-in-rails-test

```ruby
set_callback(:validation, :before, :func, on: :action)
```
しかし、こちらをやってみても改善されず。

ソースを調べてみた。
https://github.com/rails/rails/blob/070d4afacd3e9721b7e3a4634e4d026b5fa2c32c/activesupport/lib/active_support/callbacks.rb#L674

ソースコードにコメントしてある引数には`if`, `unless`, `prepend`しか無いため`on: :action`の設定は難しそう。


最終的な対処法としては、コールバックを回避して処理を行うメソッドが存在するため、こちらを用いることにした。
https://railsguides.jp/active_record_callbacks.html#%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%82%92%E3%82%B9%E3%82%AD%E3%83%83%E3%83%97%E3%81%99%E3%82%8B


### まとめ
`skip_callback`、`set_callback`はコールバックを回避するための便利なメソッドですが、`on`を用いた条件付けがされている場合かつ全てのコールバックを回避しても問題ない場合はそもそもコールバックを回避できるメソッドを使った方が良いのかなと今のところ考えています。
EC-CUBE4のrepository関数の使い方

EC-CUBE4で利用できる、twig関数`repository`の使い方です。

通常、データを取得する際には、コントローラ側でデータを取得し、twigテンプレートへ渡す必要がありますが、`repository`関数を使えばtwigテンプレート内でデータ取得を行うことができます。

乱用すると可読性が悪くなるので注意が必要ですが、データがほしいけどphpのプログラムを触るのは敷居が高い、ような場合に使うと良いかと思います。

repository関数の文法は以下の通りです。

```
repository(エンティティクラス名).findBy({検索条件}, {ソート順}, 取得件数)
```

例えば、公開ステータスの新着商品を5件取得する場合は以下のようなサンプルになります。

```twig
{% set Products = repository('Eccube\\Entity\\Product').findBy({ Status: 1 }, { create_date: 'desc' }, 5) %}
{% for Product in Products %}
    {{ Product.name }}
{% endfor %}
```
阿弥陀仏モジュールを再生するメモ

# はじめに
Aliexpressで購入したお経を再生してくれる阿弥陀仏モジュールを動かしてみたので、そのメモです。
ついでに安いスピーカーもAliexpressで買いました。

- [阿弥陀仏モジュール](https://ja.aliexpress.com/item/32878634086.html?spm=a2g0s.9042311.0.0.10d84c4dcHnUqI)
- [スピーカー](https://ja.aliexpress.com/item/32810636214.html?spm=a2g0s.9042311.0.0.10d84c4dcHnUqI)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/30244498-8520-1a6b-e714-61a8a4172029.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/60468345-f055-726f-1596-352ea6c6f96f.png)


# 回路図
スイッチで曲を進めたり、戻ったりします。

![考え中-90.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/05552e62-41cd-4a03-5677-7a5d41a8cf25.jpeg)

# 動作確認
こんな感じ。
ちょっと電源周りが不安定な感じがあるので、改善します。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">阿弥陀仏モジュール🤔 <a href="https://t.co/tYcAPxmSSi">pic.twitter.com/tYcAPxmSSi</a></p>&mdash; たくろーどん (@takudooon) <a href="https://twitter.com/takudooon/status/1309089344284696580?ref_src=twsrc%5Etfw">September 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Tekton Triggersのログレベルを変更する

毎回TektonのTaskRunやPipelineRunを手動で作成するのは手間ですし、Git PushやDocker Pushのイベントと連携したくなるのがエンジニア。

そこで、[Tekton Triggers](https://github.com/tektoncd/triggers)を利用するのですが何故かTaskRunが実行されなくてデバッグ用のWebサーバーとEventListenerを差し替えてリクエストの確認をしてました。実はもっと簡単な方法があって、単純にログレベルをdebugにすれば見れました。

# リクエストのPayloadが見たい！

EventListenerを作成した時に自動的に作成されたConfigMapをおもむろにeditします。
https://github.com/tektoncd/triggers/blob/master/config/config-logging.yaml

```
$ kubectl edit cm config-logging-triggers
```

loglevel.eventlistener: "info" の行を編集して "debug" にして保存します。
編集後のConfigMapを再読み込みさせるためにEventListener Podを再作成すれば、ログにリクエストのHeaderとPayloadが表示されるようになります。
macとRaspberry Pi 3 Model B+ をサーバ接続してみた

みなさんこんにちは。こんばんは。おはようございます。

🐻([@hawks__fan](https://twitter.com/hawks__fan))です。


今回は、タイトルにもあるように「macとRaspberry Pi 3 Model B+ をサーバ接続してみた」ことを記事にしていきたい。

#準備したもの
#####Raspberry Pi 3 Model B+ （付随のマイクロSD込）
![CF67D32F-98A1-463E-9E8C-B780A034A144.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311354/5db19ae8-02c9-a7dd-4b24-963a768e7652.jpeg)
![D552D771-1E3D-49FB-80C6-C48D55A2AAF0.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311354/74ed7879-e120-b59b-b086-d4731354a598.jpeg)
![8505B197-7656-4B04-8178-B125787B3001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311354/480fd647-314d-efac-da28-a48937d3bff9.jpeg)
#####モニタ
#####キーボード
#####マウス
#####HDMIケーブル
#####MacBook Pro

#参考にした記事
•1[[超初心者向け]RaspberryPiにOS(Raspbian)をインストールして起動し、vimやScratchが使えるようになるまで](https://qiita.com/Ichiro_Tsuji/items/e7ff30f0ec0b7d0ceed5)


•2[Raspberry PiのSSH有効化方法
](https://qiita.com/hikobotch/items/a33fc77114a4963cc68b)

•3[macしかない状況でRaspberry Piに接続してみた](https://qiita.com/murs313/items/81757bf8bc74b6b76cdf)

•4[Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)


#できたこと
最初は[1の記事](https://qiita.com/Ichiro_Tsuji/items/e7ff30f0ec0b7d0ceed5)
を参考にしながら、作業していたのだが、途中の「SSHを有効化する」の箇所あたりからうまくいかなくなってしまった。

どこがうまくいかなかったのかというと、[1の記事](https://qiita.com/Ichiro_Tsuji/items/e7ff30f0ec0b7d0ceed5)の手順で示されていた、[SSHを有効化する](https://qiita.com/Ichiro_Tsuji/items/e7ff30f0ec0b7d0ceed5#ssh%E3%82%92%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B)の箇所だ。


「困ったな」と思いながら、ネットサーフィンをしていると、[2の記事](https://qiita.com/hikobotch/items/a33fc77114a4963cc68b)を見つけたのだ。

原因は恐らく、自分の所有しているRaspberry Pi 3 Model B+と[1の記事](https://qiita.com/Ichiro_Tsuji/items/e7ff30f0ec0b7d0ceed5)で使われていたRaspberry Pi の型が違うためなのかもしれない。

SSHを有効化するための画面が違うのだから分からなかったわけだ…

ここで[1の記事](https://qiita.com/Ichiro_Tsuji/items/e7ff30f0ec0b7d0ceed5)はもう役に立たなくなったなと思ったので、また記事を探して発見した記事が[3の記事](https://qiita.com/murs313/items/81757bf8bc74b6b76cdf)だ。

結果的に、1度はmacとRaspberry Pi 3 Model B+ をサーバ接続できたものの（その時のスクショをとるべきだったorz）、2度目3度目の接続はできなかった。

原因はわからないが、問題はパスワードを要求されて設定したパスワードを入力しても接続できなかったというものだ。

まぁ何をするにしても初めての挑戦には失敗はつきものだ。

また、まとまった時間を作ってトライしてみようと思う。




#まとめ

初めてQiitaで記事を書いてみたが、気づいたことがいくつかあったので、雑にまとめておこうと思う。

•1度接続できたのに、2度目3度目で失敗したことを踏まえて、自分の能力不足が原因で再現できなかったのだとしたら悔しいので、再度挑戦してみようと思った。

•Qiitaはユーザーに黙って情報取得していたので、<strike>脱退したみたいな記事</strike>を読んで、ぴえん🥺となってしまった。

•何をするにしても失敗はつきものなので、恥ずかしからずに原因を見つけて改善することはだいじだな（小並感）と思った。

それでは。🐻でした。
仮想デスクトップのショートカット - Windows Tips


#仮想デスクトップのショートカット
|ショートカット|内容|
|---|---|
|[Win]+[Tab]|タスクビューを表示|
|[Win]＋[Ctrl]+[D]|仮想デスクトップを新規追加|
|[Win]＋[Ctrl]+[→]|次の仮想デスクトップに移動|
|[Win]＋[Ctrl]+[←]|前の仮想デスクトップに移動|
|[Win]＋[Ctrl]+[F4]|現在の仮想デスクトップを削除|


#仮想デスクトップの設定
初期設定では、タスクバーや[Alt]+[Tab]によるアプリの切り替えは、単一の仮想デスクトップ内だけで行われます。

複数の仮想デスクトップにまたがってアプリの切り替えを行う場合は、下記の設定を「使用中のデスクトップのみ」から「すべてのデスクトップ」に変更します。


[スタート]-[設定]-[システム]-[マルチタスク]

- タスクバーに次の場所に開いているウィンドウを表示する
- Alt + Tab キーを押した時に開いているウィンドウを表示する

![rapture_20200925053007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39680/301889dc-261e-91d7-817c-b724fda4a1f2.png)
【Flutter】GridViewの下にボタンWidgetを配置する方法



今回は、`GridView`で、画像下にあるというボタンWidgetの設置方法について。

![Screenshot_20200924-061148 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699790/6a5c14be-0efa-3525-2925-c5629bd74204.jpeg)


上図のオレンジ色の`RaisedButton`のことです。

## GridViewの下にボタンWidgetを配置する

普通に`RaisedButton`を追加しようとすると、以下のエラーに遭遇します。

```
The method '>' was called on null
```

画面サイズがおかしくなっているためにエラーが発生しているのでしょうが、詳細は分かりません。


## 方法：Expandedでラップする

ExpandedでGridViewをラップしてあげると、先ほどのエラーは発生しないで適切に表示されるようになります。

```dart:コード例（GridView）
  Widget get _gridViewSection =>
      Consumer<CheckListProvider>(builder: (context, model, _) {
        return Expanded(   // ★ExpandedでGridViewをラップする。
          child: GridView.builder(
            itemCount: model.checks.length,
            shrinkWrap: true,
            padding: const EdgeInsets.all(4),
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
            ),
            itemBuilder: (BuildContext context, int index) {
              return _listItem(model, index); // Grid一つ分のデザインを作成(割愛)
            },
          ),
        );
      });
```
GridViewの説明には関係ないですが、`Consumer<CheckListProvider>…`はProviderを利用しています。
ご存じない方はこちら。
>[【Flutter】アプリ製作から学ぶProviderの使い方【図解付き】](https://qiita.com/mamoru_takami/items/d12cba1e274721cf8848)


あとは、GridViewの下に`RaisedButton`を普通に追加すればOK。
詳細は割愛していますが、`_addSection`内で`RaisedButton`を作成しています。

```dart:コード例（body部）
body: Column(
  children: [
    // GridView
    _gridViewSection,
    // 「Add to Todo List」ボタン
    _addSection,
  ],
),
```


## 参考

GridViewの使い方
>Flutter Doc JP GridView
https://flutter.ctrnost.com/basic/layout/gridview/

エラー対処法
>https://stackoverflow.com/questions/58559145/the-method-was-called-on-null
New RelicのApdexを利用アカウント単位で算出できるようにした

# はじめに
私が所属しているチームではNew Relic APMを利用しており、SLAレポートでユーザ満足度を測るようにしております。
ただし、各アカウントのサービス利用状況によってサービスの利用体験に差異がありそうなのは明白だったので、アカウント毎にApdexを算出できるようにしたいと考えておりました。

今回はNew Relic APMに対してカスタム属性としてアカウント情報を付与し、NRQLを用いてアカウント単位でApdexをダッシュボード化した話をお話します。

# New Relic APMのカスタム属性

New Relicでは[カスタム属性](https://docs.newrelic.co.jp/docs/using-new-relic/data/customize-data/collect-custom-attributes)を付与することで通常収集される情報に加え任意の情報を付与することが出来ます。

私達のチームではrailsを使用しております。今回は `ApplicationController` の `before_action` でカスタム属性としてアカウントIDとユーザIDなどのアカウント情報を付与するようにしました。

こうすることで各リクエストに対してアカウント情報を付与した形でNew Relic APMに返すことが出来ました。

```rb
class ApplicationController < ActionController::Base

~~

  before_action :add_custom_attributes

~~

  def add_custom_attributes
    ::NewRelic::Agent.add_custom_attributes({
      user_id: current_user&.id,
      account_id: current_user&.account&.id,
    })
  end

~~

```

# New Relic APMよりカスタム属性を確認

以下のようにNew Relic APMのトランザクション情報を見るとカスタム属性として追加したアカウント情報が付与されていることが確認できます。

![スクリーンショット 2020-08-21 18.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215051/1234885c-0af9-1e5c-2671-ea9538f75433.png)

# NRQLよりカスタム属性を確認

以下のようにNew Relic APMで取得した情報をNQRLで抽出し、そのなかにカスタム属性として追加したアカウント情報が付与されていることが確認できます。

![スクリーンショット 2020-09-25 3.36.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215051/675b9c46-c27d-f649-5a20-f30d74a7506d.png)

# アカウント毎にApdexを算出

以下のようなNRQLを組むことでアカウント単位にApdexが表示されることを確認しました。

![スクリーンショット 2020-09-25 3.35.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215051/a1db52c0-a18b-9faa-71cc-e41edf959cad.png)

# New Relicのアラート通知にアカウント情報を付与

我々のチームではNew Relic APMから取れるメトリクスに対してSlackでアラート通知など行っております。
Slack通知に対してアカウント情報を付与することでどのアカウントに対してどういう影響があったのかをパット見ですぐわかるようにしております。

![スクリーンショット 2020-09-25 3.59.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215051/0343273e-c84a-2aef-e002-7d7b650576e4.png)

# まとめ

今回はNew Relic APMに対してアカウント情報を付与し、アカウントごとのApdexをNRQLで可視化するところを紹介しました。
我々のチームではNew RelicのAPI機能を使って外部データソースにデータ転送し、各アカウントごとの満足度などを可視化するダッシュボードの要素の1つとして利用しています。この話は機会があればまた今度。

短いですが、今回は以上となります。それでは！
頻繁に使う10パターンの正規表現をRegex101で確認する。


[Regex101](https://chrome.google.com/webstore/detail/regex101/pjoipnocgklcnjhohaaeffemifmbnkho/related)はこんな風に正規表現を確認することができるChromeプラグインです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/2eebc2a1-4c0b-360a-a8a6-6b02c75b5834.png)

これ:point_up_tone1:を使って、正規表現の復習と確認をしたいと思います。

__任意の１字にマッチ__

`.`
ru.y

○ ruby
○ ruuy
× ruuby


__0文字以上直前の文字が続く__

`*`
elixir*


○ elixir
○ elixirrrr



__1文字以上直前の文字が続く__
`+`
elixir+

× elixir
○ elixirrrr

__なんでもいいから１文字以上続くもの__
`.+`
elixir.+

○ elixir/phoenix

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/2a367d98-8b5b-074b-d6eb-95628ec4ac2c.png)


## []ブラケット

[aiu]
`a` `i` `u`のどれかにマッチする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/d42ccb33-899a-4327-664d-cbf6acf11879.png)


[a-z]
小文字アルファベットにマッチする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/e605d343-298e-b257-d5c1-a298e6843adb.png)


[0-9]
数字にマッチする。


## {n}ブレース
直前の文字がn文字続く。

`a{4}`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/989f8f63-9bf2-8d15-6f91-1f7c3ca9636d.png)


`a{4,5}`
aが４個以上、5個以下という意味になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/51d52d02-f5a9-c616-8753-889b45fa3b49.png)

`0[5,7-9]0-[0-9]{4}-[0-9]{4}`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/4f9fb842-6ffa-b19d-d4e1-50e6a73c2948.png)



## 行頭と行末

`^`行頭
キャレット

`$`行末
ドル

使用例を省略します。


## ()カッコと$1

()カッコは囲った正規表現にマッチした内容を記録する。
$1は記録したものです。

例えばCotEditorで`検索と置換`を使って該当のgmailの@までを`username:`の右に置くようにする。(タイトルと矛盾してすみません）
検索：`([a-z]+)@gmail.com`
置換：`username:$1`

`すべて検索`を押下してから`すべて置換`を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/c008e1de-7874-6e5f-4145-7a4f29e22511.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/f6a719d1-e12a-9edc-f74e-aeb4bb02dcdc.png)
エラーが解決しない時は、元を断つという考え方

どうも、三町哲平です。

プログラミングをしていたら必ずエラーに出会す場面が出てきます。
簡単に解決できるエラーもあれば、何時間、下手したら数日掛かっても解決しないそんなやる気すら失ってしまうエラーも存在します。

そういうやる気を失ってしまう時に役立つエラーに使えるかも知れないテクニックを一つ紹介します。
尚、今回はRuby on Railsで発生したエラーですが、データベース絡みのエラーだとRails問わず、どのプログラミング言語での開発環境においても効果的です。

今回は、エラー発生から３日掛かって解決しましたので、短くわかりやすくまとめてみました。

# まず、結論
この記事の概略を説明すると、
__データベースが元の異常ぽかったら、データベースを再作成した方が早いよ。__
ていう話。

では、３日間の闘いをどうぞ！

## 1日目. Template::Error
![スクリーンショット 2020-09-09 13.33.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688029/480b986b-36d4-66fd-60a6-7f1dcef94075.png)

```
undefined method `image_name' for nil:NilClass
```
上記の文をピックアップしてfor nil:NilClassの部分を無視して考えた時に
__image_nameというメソッドが定義されていない__という意味です。

__1. メソッドの定義忘れ
2. シンプルに誤字脱字__

この辺りを疑い色々試してみましたが、
メソッドの定義悪でも、誤字脱字でもない...

ググってみても正解には辿り着けない...

とりあえず初日は疲れて寝てしまいました。

## 2日目. データベースっぽい

誤字脱字がないか再調査したが、問題なし。

ここで余り気に留めていなかった

```
for nil:NilClass
```
の部分についてググってみるようになります。

ちなみにRubyを使ったことない方は、
__nil__って何？となるかもしれませんが、

__nilは、nullと同じ意味です。__
つまり、__「何もない」__ということです。

何もないという内容で思い付くのは１つ...
__データベース絡みっぽいな__ということに

そして気付けば深夜1時、またすっかり日付が変わっていました。

## 3日目.ググり続けた結果

[Ruby on Rails 5 - undefined method `image_name' for nil:NilClass といエラーがでています｜teratail](https://teratail.com/questions/117648)

上記のサイトに辿り着きました。
ここからは、引用が続きますが、

>![スクリーンショット 2020-09-09 16.20.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688029/9207fcde-3ea3-61aa-649b-0533a6d40940.png)

このやり取りが全てです。

文字多いし小さしで読みたくない方に向けて結論だけ簡単に要約すると、
__原因はおおよそ掴めたけど、もうデータベースを作り替えた方がいいよね。__
という話。

__postsテーブルを作成してデータを複数入力
↓
nilの状態(何もない)のカラムを作成してはいけないルールに途中からプログラミングする
↓
新しいカラム(user_id)を作成する
↓
今までのuser_idカラムは全てnilの状態である
↓
エラー発生__

### さいごに

原因はデータベースに入れてはいけないデータが含まれている。それならばそのデータを削除すれば良い。
もしくは開発環境のデータベースで消しても問題ないのならば今回のように再作成すればそれで復旧できます。

仮にRuby on Railsの場合ですと、


```ruby:Rails
$ rails db:drop # データベースを削除する
$ rails db:create # データベースを作成する
$ rails db:migrate # データベースにマイグレートする
```

これと同じようにあなたの開発環境にあったソースコードを入力したら、良い訳ですね^^

### 追記

ちなみにdb:drop → db:create → db:migrate　をまとめて行うこともできます。

```ruby:Rails
$ rails db:reset
```
※このコマンドでまとめて、dbの削除からマイグレートまでを行えます。
フォルダ配下の全てのBOMありUTF-8ファイルをBOMなしにするPythonスクリプト

#作ったきっかけ
業務で必要に迫られて、BOMありのUTF-8ファイルをBOMなしのUTF-8ファイルに
一括変換するスクリプトを作成しました。

思いの外、便利だったので公開します。
処理内容については、ソース中のコメントを参照してください。
#スクリプト

```python:convert.py
#--- BOM除去ツール
import sys, os, codecs, shutil

#--- コマンドライン引数の取得
args = sys.argv

#--- カレントパスの取得
current_path = os.getcwd()

#--- 作業用一時ファイル名の設定
tempfile = ''.join([current_path,'\\tempfile'])

#--- 処理件数カウント用変数
conv_count = 0

print("BOMファイル除去スクリプト")

#--- 引数がない場合は、エラー出力して終了
if len(sys.argv) == 1:
    print("引数がありません。")
    sys.exit(1)
else:
    #--- 第一引数を取得
    filepath = args[1]

#--- 指定引数のファイルパスの存在チェック
if(os.path.exists(filepath)):

    #--- os.walk関数のループ
    for (current, subfolders, files) in os.walk(filepath):
        
        #--- 取得したファイル一覧(files)でループ
        #--- filesからfileNameに個別に取得
        for fileName in files:
        
            #--- 処理対象のファイルパス生成
            target_path = '\\'.join([current, fileName])
            
            #--- UTF-8BOMからUTF-8NOBOMへの変換処理
            
            #--- 処理対象のファイルをUTF-8BOMとして読込モードでオープン
            with codecs.open(target_path, 'r', 'utf_8_sig') as r:
            
                #--- 一時ファイルをUTF-8NOBOMで書込モードでオープン
                with codecs.open(tempfile, 'w', 'utf-8') as w:
                
                    #--- 処理対象ファイルから一行ずつ読込処理(lineに代入)
                    for line in r:
                    
                        #--- 一時ファイルにlineの内容を一行出力
                        w.write(line)

            #--- ファイルの置き換え処理
            #--- 一時ファイルを処理対象ファイルに上書きコピーする
            shutil.copyfile(tempfile, target_path)
            
            #--- 一時ファイルを削除する
            os.remove(tempfile)
            
            #処理件数カウントアップ
            conv_count += 1

else:
    #--- 指定引数のパスが存在しない場合、エラー出力して終了
    print("指定されたフォルダがありません。")
    sys.exit(1)

#--- 終了メッセージ
print(filepath + "配下のファイルを駆逐しました（BOMなしに変換）")
print('変換したファイル件数:{}'.format(conv_count))
sys.exit(0)
```
#実行方法
スクリプトは機種依存がないので、Windowsでも、Macでも、Linuxでも動作します。
Pythonスクリプトを、ファイル名 convert.py で保存しているとします。

・Windows,Linuxの場合

```
> py convert.py dir_path
```
・Macの場合

```
> python convert.py dir_path
```
dir_path はフルパスで、指定してください。
#まとめ
今回作成したスクリプトは、指定フォルダ配下を再帰的に走査し
全てのファイルに対して処理を実行します。

現在のコードに、例えば特定種類のファイルを対象にするといった事や、
引数としてファイル名を与えて一致するファイルだけを
対象にするという改良を加えると、より便利だと思います。

BOM変換については、もっとスマートな方法もあるかとは思いますが、
基礎的な命令だけで、このような処理が書けてしまうPythonは、
やっぱり便利な言語ですね。
ビデオからぺろっと 3D モーションキャプチャする FrankMocap の動作メモ


FrankMocap: A Fast Monocular 3D Hand and Body Motion Capture by Regression and Integration
https://penincillin.github.io/frank_mocap

2020 年時点での, ナウでヤングな感じのビデオからの 3D モーションキャプチャ(body 推定, hand 推定)です.

## 環境

* Ubuntu 18.04
* NVIDIA GPU

## インストール

基本手順にある通りです.

ただ, opendr が OSMesa(OffScreen Mesa) を使っているため, osmesa ライブラリのインストールが必要です.

Ubuntu 18.04 では apt で `libosmesa6-dev` でインストールできます.

### モデルデータ

SMPL と SMPL-X のデータが必要です.
それぞれのサイトでアカウント登録し, Licensse agreement をよんで, 同意できる場合にダウンロードしましょう.

同意できない場合は, SMPL, FrankMocap 相当を自作しましょう!
 
## 実行

ありがとうございます.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ありがとう FrankMocap 😍😍, ありがとうビクトリアファッションショー 😊😊😊 <a href="https://t.co/9rfoG4z8Fd">pic.twitter.com/9rfoG4z8Fd</a></p>&mdash; Syoyo Fujita 🌸 レイトラ 🐯 2 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1309082622283390976?ref_src=twsrc%5Etfw">September 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

2019 年から Victroria's Secret ファッションショーなくなって悲しいですね :cry:
postmanからOAuth2.0でTwitterAPI v2を実行する

[Twitter API v2: Early Access](https://developer.twitter.com/en/docs/twitter-api/early-access)を見て試したくなり、公式ドキュメントを読み勧めていたら [run Postman](https://documenter.getpostman.com/view/9956214/T1LMiT5U) のリンクがあり、公式が [Postman](https://www.postman.com/) を推していたので使ってみることにした。

postmanは初めて使ってみたが、OAuth2.0用のBearer Tokenを何処に設定すればいいのかよく分からなかったので、APIを実行できるようにするまでの備忘録を残す。



# 環境
- MacOS
- Postman App

## TwitterAPIを実行するまでの事前準備

- https://developer.twitter.com/en/apps/ で申請済で、Bearer Tokenもあること(参考：https://tech-lab.sios.jp/archives/21238)
- postmanのアプリがインストールされていること

# postmanの設定とAPI実行
## 1. TwitterAPI v2 を Postman のコレクションに導入する
![Twitter_API_v2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125552/c8890501-5571-8706-8e4b-38a798924338.png)

https://documenter.getpostman.com/view/9956214/T1LMiT5U で、Run in Postmanを押す。
ダイアログがでるので、Postman for Mac を選択すると、ローカルアプリにコレクションが導入される。

## 2. コレクション全体の設定として、OAuth2.0 のBearer Tokenを設定する
![Postman_Collection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125552/b5bccddf-f2bd-32f4-73c1-6425fdebe12f.png)
コレクションを選択して、設定画面を開く。

![Postman_auth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125552/b1d4d9dc-6cb4-7450-52b1-7b20f445102c.png)
OAuth2.0を選択してBearer Tokenを入れる

### 備考
![Postman_unnecessary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125552/500015f6-39fd-0acf-cf13-ab7d31748d33.png)
変数に bearer_token があるが、入れなくてもよい。
変数なのでテストを書くときとかに使うのかな？


## 3. APIを実行する
試しに [GET User by Username](https://documenter.getpostman.com/view/9956214/T1LMiT5U#288337e6-91e5-4297-bde2-cae96a549732) を実行する。
API リファレンスでは、Path Variables に username だけあり、同期したコレクション内の User by Username APIもそれに準じたパラメータになっているのがわかる。

![Postman_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125552/a1bd6f10-3407-0951-cbc9-7c317b1f3748.png)

username の value に検索したいアカウントを入力して、Sendを押すと結果が返る。
PyMySQL

# PyMySQL
PythonからMySQLを操作するパッケージ。
 [PyMySQL/PyMySQL](https://github.com/PyMySQL/PyMySQL)

```bash
ubuntu:~$ pip3 install PyMySQL
Requirement already satisfied: PyMySQL in ./.local/lib/python3.8/site-packages (0.10.1)
```

# 既存のテーブルにレコードを追加する
データベース test、テーブル table1 に値を追加します。
mysqlユーザやデータベースは作成済みです。(それぞれ、ubuntu, test)

```python
import pymysql.cursors

# MySQLに接続
connection = pymysql.connect(host='localhost',
                         user='ubuntu',
                         password='ubuntu',
                         db='test',
                         charset='utf8',
                         cursorclass=pymysql.cursors.DictCursor)

# レコードを挿入
with connection.cursor() as cursor:
    sql = "INSERT INTO table1 VALUE ('2020-09-25 01-14-11','python',888);"
    cursor.execute(sql)

# 変更をコミット
connection.commit()

# 切断
connection.close()
```

# 既存のテーブル table1 はこんな感じ
```sql
mysql> USE test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> desc table1;
+--------+----------+------+-----+---------+-------+
| Field  | Type     | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| time   | datetime | YES  |     | NULL    |       |
| value  | char(10) | YES  |     | NULL    |       |
| number | int      | YES  |     | NULL    |       |
+--------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)
```

# python 実行後の table1 を確認
```sql
mysql> SELECT * FROM table1;
+---------------------+-----------+--------+
| time                | value     | number |
+---------------------+-----------+--------+
| 2020-09-25 01:14:11 | python    |    888 |
+---------------------+-----------+--------+
1 rows in set (0.00 sec)
```
Kubernetes Job のハマリポイント6つ

**Kubernetes Job** を業務で使用した後の反省点、注意点。

<details><summary>実行環境</summary><div>

| | version|
|:-:|:-:|
|kubectl   | 1.16+ |
|gke cluster   | 1.14.10-gke.42 |
|gke node   | 1.14.10-gke.36 |

</div></details>

<details><summary>Kubertes Job とは</summary><div>
<br/>

以下[公式ドキュメント](https://kubernetes.io/ja/docs/concepts/workloads/controllers/job/#job-patterns)より。

> Jobは1つ以上のPodを作成し、指定された数のPodが正常に終了することを保証します。 JobはPodの正常終了を追跡します。正常終了が指定された回数に達すると、そのタスク(つまりJob)は完了します。

</div></details>

## Job の単位を小さくする

Job は1つのタスク

- Cloud Storage (S3) へのファイルのアップロード

- メールの送信など

を管理するためのコントローラーオブジェクトです。1つの Job に複数のタスクを含まないようにしましょう。開発が進み、必要機能が増えていくと意外とやってしまいがちです。

## Job は Node に残り続ける

> Jobオブジェクトは完了後も残るため、ステータスを表示できます。ステータスを確認した後、古いJobを削除するのはユーザーの責任です。

Job を残したままにしておくとリソースを消費してしまうので削除する必要があります。一般には

- `spec.ttlSecondsAfterFinished`を Job に設定

- `successfulJobsHistoryLimit`、`failedJobsHistoryLimit` を設定した **Cron Job**[^1] の利用

といった方法があるのですが...

 [^1]: 時刻ベースのスケジュールによって Job を実行する Kubernetes のオブジェクト 

## アルファ/ベータ版機能

`spec.ttlSecondsAfterFinished`はアルファ版機能、Cron Jobはそれ自体がベータ版機能で未解決のバグもある模様。筆者環境では思い通りに動いてくれませんでした。結局 Kubernetes Job のクライアントライブラリを利用した独自の削除機能を実装しました:sweat:

## Job 実行には cluster-admin 権限が必要

Job の操作には `cluster-admin` 権限を実行アカウント(KSA[^2])に付与する必要があります。

```
$ kubectl create clusterrolebinding cluster-admin-permission-binding \
  --clusterrole=cluster-admin \
  --user=system:serviceaccount:default:default \
  --namespace=default
```

 [^2]: Kuberetes Service Account (詳細はこちらの[記事](https://qiita.com/kyo2bay/items/01bf2ffd85036db90af7))

## Job 起動リクエストは時折タイムアウトする

> "Failed to runJob: The POST operation against Job.batch could not be completed at this time, please try again."

筆者環境だと1000回に1回くらいタイムアウトが発生します。Job は「タスクが完了するまでのリトライ機能を備えたもの」とも言えますが、Job 自体が起動しないとどうしようもないので、Job 起動リクエストのタイムアウトは検知し、再度起動リクエストを行うような実装にしましょう。

## restartPolicy

> 備考: JobにrestartPolicy = "OnFailure"がある場合、Jobのバックオフ制限に達すると、Jobを実行しているコンテナが終了することに注意してください。

特に理由がない限りは、`.spec.template.spec.restartPolicy = "Never"`としておいた方が無難です。
【Java】String型配列の要素一つをInt型に型変換する方法

例えば従業員の情報を、名前、年齢と入力されそれを一つの配列にScannerを使って代入すると
```  yamada 20 ```

```
  Scanner sc = new Scanner( System.in);
  String[] employee = sc.nextLine();
```

となるが、javaは静的型付のため配列内の名前も年齢もString型となる
年齢をInt型にキャスト（型変換）しなくてはならない
そこで```Integer.parseInt```メソッドを使う

```
　int age = Integer.parseInt( employee[1] );
```

これでString型からInt型へのキャストは終了
たとえば1歳年を増やしたければ

```
　int addAge = Integer.parseInt( employee[1] ) + 1;
```

となる。
()内は引数なのでもちろん普通の変数でも問題ありません。
go/mysqlで値が上手く取れない


go/gorm/mysql
で値が上手く取れない現象が起きたので備忘録がてら例えばこのようなテーブルを作成し、

```sql
CREATE TABLE dataids (
    id INT, 
    titleid INT,
    titleid2 INT
);

```

以下のように、insertしときます。

```sql
INSERT INTO collectq_db.dataids (id, titleid, titleid2) VALUES
(1,1,1),(2,1,2),(3,1,3);
```

そしてgormで取得しようと以下のようにしました

```go
type Dataid struct {
	id       int
	titleid  int
	titleid2 int
}

func GetAllDataids(db *gorm.DB) []Dataid {
	var dataids []Dataid
	db.Find(&dataids)
	fmt.Println("確認！！", dataids)
	return dataids
```

とすると、以下のように、
fmt.Println上では
``` [{0  } {0  } {0  }]```
googlechrome上では、
````[{},{},{}]```
と表示されます。

##解決策

構造体の中身の変数名さえ頭文字大文字にしなければ、反応gormのFindで
反応してくれない。
（errではなくよくわからないのが帰ってくる(まあ対応する変数がないので、代入されないだけだと思うけど)）

```go
type Dataid struct {
	Id       int
	Titleid  int
	Titleid2 int
}
```
Commitizenを使ってもうコミットメッセージに迷わない

## はじめに

gitのコミットメッセージをどう表現するかで迷うことが多々あります。
チームによってざっくりと指針が決まっているものの、明確ではない場合も多いのではないでしょうか？
私自身`fix:` `chore:` `feat:`などの接頭辞を使って書くことが多いですが、それぞれの接頭辞の意味を毎回ググっている気がします。特に `chore:`...
そんな悩みを [Commitizen](https://github.com/commitizen/cz-cli)を使って解決したのでその備忘録として記します。


### 対象

もう実装は終わっているのに。。。なぜコミットするだけなのに。。。ここでこんなに時間を使わないといけないの。。。といった悩みを持っている方。

## Commitizenとは?

CLIを使って対話的にコミットメッセージを作ることができます。
コミットメッセージのルールは `angular.js`のコミットガイドラインが元になっているそうです。

### コミットメッセージのフォーマット

コミットメッセージのフォーマットは以下のようになっています

```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

### 対話の内容

はじめにcommit typeが聞かれます
![スクリーンショット 2020-09-25 0.33.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194935/d75c16c8-e4af-0a81-aa50-7ceb3eb27cf0.png)

その後はcommitに対しての質問をされます
![スクリーンショット 2020-09-25 0.41.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194935/419cd4e4-d35a-2eeb-2557-1c990e13257a.png)

一つ一つ答えていくと

![スクリーンショット 2020-09-25 0.41.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194935/b940fc37-898e-fa69-b55a-61eada7f9d8a.png)

こんな感じのコミットメッセージが出来上がります。

## インストール

ローカルにインストールすることもできますが、今回はグローバルにインストールします。

```sh
$ npm install commitizen -g
$ npm install -g cz-conventional-changelog
$ echo '{ "path": "cz-conventional-changelog" }' >> ~/.czrc
$ exec $SHELL -l
```

以上のコマンドで簡単にインストールでき、

```
$ git cz
```

このコマンドでcommitzenがスタートします。

### 日本語化

日本語化もできるそうなのでお好みで設定してみてください。
https://www.npmjs.com/package/cz-conventional-changelog-ja
Laravel ランダムな文字列の生成

# 目的

- Laravelで桁数を指定したランダムな文字列の生成方法をまとめる

# 例

- 下記のようにヘルパ関数を用いてランダムな文字列を生成する。

    ```php
    Str::random(生成桁数);
    ```
- 本処理はPHPのrandom_bytes関数を使用してランダムな文字列を生成している。
- 余談であるがPHPのrandom_bytes関数が使用する不規則性のソースはOSやプラットフォームによって異なっているらしい。どれも使えないとき（例外時）は基底クラスを投げるらしい。
    - Windows: CNG-API
    - Linux: getrandom(2)
    - その他: /dev/urandom
# 具体例

- 30桁のランダムな文字列を生成し`$str`に格納する処理を下記に記載する。

    ```php
    $str = Str::random(30);
    ```

# 参考文献

- [https://readouble.com/laravel/8.x/ja/helpers.html](https://readouble.com/laravel/8.x/ja/helpers.html)
- [php random_bytes](https://www.php.net/manual/ja/function.random-bytes.php)
独自のdocker-compose.ymlをコマンドラインで使う

## 独自のdocker-compose.yml
プロジェクトの`docker-compose.yml`を独自に書き変えたい場合

```
docker-compose -f docker-compose.myenv.yml
```
と`-f`オプションにカスタマイズしたYAMLファイルを指定することで、独自のCompose設定ファイルをもとにコマンドが実行されます。

しかし、毎回指定するのは面倒ですよね。

## シェルの設定ファイル
`.bashrc`などに以下を追記することで、ディレクトリ直下に独自の設定ファイルがある場合、`dc`を実行すると`docker-compose.myenv.yml`が適用されます。

```bash:.bashrc
function dc() {
    if [[ -f docker-compose.myenv.yml ]]; then
        echo 'Using docker-compose.myenv.yml'
        docker-compose -f docker-compose.myenv.yml $@
    else
        docker-compose $@
    fi;
}
alias dc=dc
```

## 例
```bash:.docker-compose.myenv.ymlがあるとき
$ dc
Using docker-compose.myenv.yml
Define and run multi-container applications with Docker.
...
```
メモ：デスクトップアプリケーションとWebアプリケーションの違い

webアプリケーションの仕組みを理解していなかった為学習内容をメモ
<h1>デスクトップアプリケーションとは...</h1>
・処理を行う時は主に、操作元のPC上で行われている
・画面はOSの機能を利用して表示している
・操作を行うためにはあらかじめアプリケーションをダウンロードをしておく必要がある

<h1>Webアプリケーションとは</h1>
・処理を行う時は主に、サーバ上で行われている
・画面はHTMLで表現され、Webブラウザ上に表示される
・アプリケーションを事前にOSへダウンロードしておく必要がない

<h1>デスクトップアプリケーションとWebアプリケーションの違い</h1>
・主な処理：手元のPCで行われるかサーバ上で行うか
・表示：OSかHTMLでブラウザ上に表示するか
・事前準備：ダウンロードが必要か不必要か
機械学習におけるLDAとQDAについて簡単にまとめる

#プログラミング勉強日記
2020年9月25日
大学の授業で論文を読んでいるときにLDAとQDAに触れたので、この機会にまとめる。

#LDA(線形判別分析)とは
　LDAはLinear discriminant analysisの略で、日本語では線形判別分析と呼ばれる。特徴抽出の手法の1つで、コンピュータサイエンスでは画像処理や顔認識などでよく使われる人気の技術である。

　LDAの目的はクラス内分散とクラス間分散を最大化することにある。2つのクラスを最もよく判別できる直線を求める手法である。データが直線のどちら側にあるかを見ることでクラスのデータ群を分離させる。この直線を決定境界という。

#QDA(二次判別分析)
　QDAはQuadratic Discriminant Analysisの略で、日本語では二次判別分析と呼ばれる。

　古典的な機械学習の手法の1つで、LDAから派生したもの。LDAと同様にデータは二乗距離が最小のクラスに分類される。しかし、二乗距離は線形関数に単純化されないので、LDAとは異なり二乗距離は対称的ではない。

#LDAとQDAの違い
　LDAは全群団で分散が等しくなければいけないが、QDAは群団間で分散が異なる場合にも対応することができる。

　

#参考文献
[線形判別分析(LDA)](https://blog.octopt.com/lda/)
[線形判別分析](https://axa.biopapyrus.jp/machine-learning/preprocessing/lda.html)
[２次判別分析をRでやってみた（スイス銀行紙幣②）](https://r-std.hatenablog.com/entry/2016/05/04/102740)
[2次判別分析とは](https://support.minitab.com/ja-jp/minitab/18/help-and-how-to/modeling-statistics/multivariate/supporting-topics/discriminant-analysis/what-is-quadratic-discriminant-analysis/)
Vuex + TypeScript + vuex-module-decoratorsでのmutationとgetterの単体テスト

# やりたいこと

[vuex-module-decorators](https://github.com/championswimmer/vuex-module-decorators)を使うことで、TyepScriptでVuexを記述する際により型付けの恩恵を受けられるようになります。この記事ではvuex-module-decoratorsを使った際のVuexのmutationとgetterのJestでの単体テストの記述方法を紹介したいと思います。

以下の環境で動作検証しています。

- Vue.js: 2.6.19
- Vuex: 3.0.1
- vuex-module-decorators: 0.9.9
- 単体テストユニット: Jest


# テスト対象のVuex
テスト対象として以下のVuexを作成します。

```TSX:counter.ts
import { Action, Module, Mutation, VuexModule } from "vuex-module-decorators";

@Module({ name: "counter", namespaced: true })
export class Counter extends VuexModule {

  // state
  private count: number = 0;

  // mutaion
  // カウンターをインクリメントする
  @Mutation
  public increment(): void {
    this.count++;
  }

  // getter
  //　カウンターの値を取得
  get getCount() {
    return this.count;
  }

  // action
  // カウンターの値を2インクリメントするアクション
  @Action({})
  public add2(): void {
    this.increment();
    this.increment();
  }
}

```

# Jestでの単体テスト
以下のように単体テストを記述できます。ポイントとしては、Counter.mutations!.increment(mockState, {})のようにモック化したstateに対してmutation, getterを実行することでテストケースごとに別のステートを使用している点です。

テストケースごとにステートの値を変更できる点と、mutaionとgetterを独立してテストできる点がメリットです。

```TSX:counter.spec.ts
import Vuex from "vuex";
import { Counter } from "@/store/modules/counter";
import { createLocalVue } from "@vue/test-utils";
import { cloneDeep } from "lodash";
import { Action, getModule } from "vuex-module-decorators";

// ローカルのVueインスタンを使用する
const localVue = createLocalVue();
localVue.use(Vuex);

describe("Counter test", () => {

  // mutationnのテスト
  it("mutation test increment1", () => {
  
    // ステートをモック化
    const mockState = {
      count: 0
    };

    Counter.mutations!.increment(mockState, {});
    expect(mockState.count).toBe(1);
  });

  // mutationnのテスト
  it("mutation test increment2", () => {
  
    // ステートをモック化
    const mockState = {
      count: 0
    };

    // テストケースごとに別のモック化したステートを使用できる
    expect(mockState.count).toBe(0);
    Counter.mutations!.increment(mockState, {});
    Counter.mutations!.increment(mockState, {});
    expect(mockState.count).toBe(2);
  });

  // getterのテスト
  it("getter test", () => {
  
    // ステートをモック化、カウンターの初期値を変更
    const mockState = {
      count: 3
    };
    
    expect(Counter.getters!.getCount(mockState, null, null, null)).toBe(3);
  });
});
```

# おわりに
actionも同様にモック化したstatenを使用してテストしたかったのですが、記述方法がわかりませんでした。ご存知の方がいらっしましたら教えていただけると嬉しいです。
JavaScriptで指定した期間の、月単位、日単位の連番を作成する

#やりたいこと
datepicker等で選択した日付の範囲を、月単位、日単位で区切り配列にぶち込む。

'2020-08-17' から '2020-09-03' で期間指定したとき、
日単位の場合は素直に
['2020-08-17','2020-08-18','2020-08-19',...,'2020-09-03']
月単位の場合は、'yyyy-mm' 部分をみて
['2020-08','2020-09']

が欲しい。

#本題

今回は、期間は決め打ちで。
配列を用意して

```
var fromDate = '2020-08-17'
var toDate = '2020-09-03'

var monthlyRange = [];
var daylyRange = [];
```

for文で日、月を加算していくので、date型に変換

new Date('yyyy-mm-dd')
の形でOK。
参考：http://cly7796.net/wp/javascript/how-to-use-new-date/

new Date('yyyy-mm')
だとddの部分は '01' になる。月の加算、配列格納はこちらを利用。

```
// 指定した日付から年と月を取り出す。'yyyy-mm-dd' => 'yyyy-mm'
regexp = new RegExp(/\d\d\d\d-\d\d/);
var fromYM = fromDate.match(regexp)[0];
var toYM = toDate.match(regexp)[0];
    
// 日付の大小比較のため、date型に変換
var start = new Date(fromDate);
var end = new Date(toDate);
// ddを省略することで、その年月の一日のdateが手に入る
var startYM = new Date(fromYM); 
var endYM = new Date(toYM);

```

後は以下。
型変換は下で定義した関数で行う。

```
// date型を文字列に変換し配列に格納
for(var ym = startYM; ym <= endYM; ym.setMonth(ym.getMonth()+1)) {
    var strYearMonth = convertToStr(ym, 0);
    monthlyRange.push(strYearMonth);
}

for(var d = start; d <= end; d.setDate(d.getDate()+1)) {
    var strDate = convertToStr(d, 1);
    daylyRange.push(strDate);
}

// date型を文字列に変換する
function convertToStr(date, day){
    // dayはフラグ。真のとき'yy-mm-dd'、偽のとき'yy-mm'。
    var strDate;
    
    if(day){
        strDate = [
            date.getFullYear(),
            ('0' + (date.getMonth() + 1)).slice(-2),
            ('0' + date.getDate()).slice(-2)
        ].join('-');
    }else{
        strDate = [
            date.getFullYear(),
            ('0' + (date.getMonth() + 1)).slice(-2),
        ].join('-');
    }
    return strDate;
}
```

# 結果


```
["2020-08", "2020-09"]
["2020-08-17", "2020-08-18", "2020-08-19", "2020-08-20", "2020-08-21", "2020-08-22", "2020-08-23", "2020-08-24", "2020-08-25", "2020-08-26", "2020-08-27", "2020-08-28", "2020-08-29", "2020-08-30", "2020-08-31", "2020-09-01", "2020-09-02", "2020-09-03"]
```

最適解ではないと思いますが、とりあえず思い通りです。
Ansible初心者 自己証明書の作成

#0. はじめに
Ansibleで作成したCSRをもとに自己証明書を作成、Apacheの設定を行いHTTPS通信を試みる。
ご参考[Ansible初心者 CSRの作成](https://qiita.com/say8/items/a452193aa4e584a1b320)

#1. 自己証明書を作成
openssl_certificateモジュールを利用して自己証明書を作成。

```
- name: Generate OpenSSL certificate
  openssl_certificate:
    path: "{{ tmp_dir }}/{{ cert_name }}.crt"
    privatekey_path: "{{ tmp_dir }}/{{ private_key_name }}.key"
    csr_path: "{{ tmp_dir }}/{{ csr_common_name }}.csr"
    owner: "{{ cert_owner }}"
    group: "{{ cert_group }}"
    mode: '0600'
    provider: selfsigned
```

変数を設定するvasファイルは以下のように設定。

```
cert_name: "test"
cert_owner: "apache"
cert_group: "apache"

```

実行結果は以下。

```
-rw-------. 1 apache apache 1257  9月 24 22:57 test.crt
```

#2. Apacheの設定

## Apacheインストール
Apacheのインストールを実施

```
httpd -version
Server version: Apache/2.4.37 (centos)
Server built:   Sep 15 2020 15:41:16
```

## SSLモジュールのインストール
SSLモジュールのインストールを実施

```
httpd -M |grep ssl
 ssl_module (shared)
```

##秘密鍵、証明書の配置
Ansibleで秘密鍵、証明書配置用のディレクトリを作成する。

```
- name: Create dir
  file:
    state: directory
    path: "{{ item }}"
  loop:
      - "/etc/httpd/conf/ssl.key"
      - "/etc/httpd/conf/ssl.crt"
```

作成したディレクトリ配下に秘密鍵、証明書を配置する。


##ssl.confを修正
ssl.confを修正。

```
vi /etc/httpd/conf.d/ssl.conf
```

秘密鍵、証明書のパスを設定する

```
SSLCertificateFile /etc/httpd/conf/ssl.crt/test.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/test.key
```

#3. 実行結果
HTTPSでの通信を実施したところ、以下のブラウザが表示された。
証明書も上記で作成したものと同一であることを確認。
![実行結果](
https://ryoybq.dm.files.1drv.com/y4mDgJkJ1qPN_hJk2E6ylBHfgzG3iDJCbQ5NIrQl8tx0lQbePT6HoyMgTI-9sHoReTXwe1-4qyqlr0ysiTAPUmSvU5mNjXt8JN2DxYoySYsHbB8TbD2vA5WTQ1CQVKROcq4MXLXqLqRf78Yk-a6dd5uq1XKjItPLe_eUisZ4lvBjMFsAibeLP8xYVMonRxszkCY8iPZcgGk-IYrUUXLuYX_lQ?width=779&height=583&cropmode=none)