OmniAICreator/Qiita-1.07M huggingface dataset:
SPSSのライセンスがActivateされたマシンを調べる方法

SPSS ModelerのライセンスがActivateされているマシンを確認する方法をご紹介します。

まず、Modelerの導入されたマシンで、ライセンス認証ウィザードを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5bd0c720-2f14-4090-4afe-012d01f88fd8.png)

ライセンスの状態を確認して次へをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/a3253dc5-a0f4-2e1c-8b10-e2bfefd748af.png)

以下のように「このマシンのロックコード」としてこのマシンの固有のコードが表示されます。この例では4-1F0A9です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/0be9fcf6-89b0-0850-9d70-307d3c85698e.png)

次に、SPSS License Key Centerにログインして、View Codes by Hostをみるとアクティベートされているロックコードが表示されます。
確かに4-1F0A9が記録されているので、正しくアクティベートされていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7da3fc08-6d95-5a7b-9bd0-0848779c32a1.png)

View Codes by Hostにロックコードがない場合は正しくアクティベートされていない可能性があります。サポートに相談してください。
また、View Codes by Hostに記録されているロックコードに対応するマシンが見つからない場合は、そのライセンスが使われていない可能性があります。
SonarQubeで技術的負債を測る

## はじめに

こんにちは、運動通信社でバックエンドメインに携わっている Takeya です。

"技術的負債"。弊社も悩まされてます。
これを計測する方法はないのかな〜? と探してみたところ、 SonarQube というツールの出力結果に"Techinical Debt (技術的負債)"という項目があるとのこと。
試してみましょう！

## SonarQube って? 何ができるの?

[SonarQube](https://www.sonarqube.org/) は静的コード解析ツールです。
技術的負債計測ツールというわけではなく、その中に技術的負債の計測も含んでる感じです。
この手のツールでは一番メジャーなようです。

### 計測できるもの
https://docs.sonarqube.org/latest/user-guide/concepts/

色々ありますが、今回は 技術的負債 をみてみます。

> Technical Debt
> The estimated time required to fix all Maintainability Issues / code smells

"すべての保守性の問題/コードの臭いを修正するために必要な推定時間"

## 動かしてみる
[公式のDockerイメージ](https://hub.docker.com/_/sonarqube)があるので簡単に試せます。

https://qiita.com/takao-takass/items/5d54768ad0d315d3dad4

手順をざっくりまとめました。

https://github.com/take8/sonarqube-sample

### 解析してみる - Laravel (本家)
![ScreenShot 2021-11-18 9.43.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/725712f4-5546-878a-0e03-d70591b28e44.png)

バグ 0 !!!
技術的負債 2h 24min 少なっ!!!
Code Smells 16 !

"Debt" をクリックするとファイル別の一覧が表示されます。
![ScreenShot 2021-11-18 10.05.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/51e4e5cb-c200-a1d3-91b8-3410c20cfcbc.png)

ファイルをクリックすると個別の指摘内容を確認できます。

`config/database.php`
簡単な例ですが、4回出てきてるから定数化しなさい、と怒られてます。
![ScreenShot 2021-11-18 10.06.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/fef6277e-3941-591c-deab-107fb2873fb5.png)

↓こんな感じで時系列での増減も表示できます。
注: 今回PHPだけ解析した後に、JSの解析を追加で行ったのでグラフとしては増えちゃってるように見えてます。
![ScreenShot 2021-11-18 10.08.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/a57498b3-9656-d800-7581-5f5e0c6fc897.png)


## 社内でもちょっと試してみました

社内の古くからあるプロジェクトをいくつかピックアップして試してみたのですが、
意外にも（？） Maintainability の項目がA評価で驚いてます（笑）

"Debt" だけ記載してます。

### プロジェクト①：用途API
Maintainability A / `Debt 149 days`

### プロジェクト②：用途BFF
Maintainability A / `Debt 582 days`

※ Maintenabilityは5段階評価となっており以下のようになっているようですね。

|ランク||
|----|----|
|A|5%以下|
|B|6~10%|
|C|11~20%|
|D|21~50%|
|E|50%以上|

ちなみに、ファイル別での確認もできるのですが、
今回試した上記のプロジェクトでは、外部ライブラリである `jquery.js` が
`Debt 53 days` ということで最大値となってました。

プロジェクトの都合上、外部ライブラリをコミットしているケースもあったりすると
ひきづられて Debt が増えているところもありそうです。(設定で除外できるかも)

## 料金は?
今回はDockerで簡易的に実施したわけですが、実運用に載せる場合いくらくらいかかるのかも調べてみました。
オンプレミスとクラウドがあります。(クラウドがいいですよね)

https://www.sonarsource.com/plans-and-pricing/

クラウド版は、解析したコードのライン数で課金されます。

![ScreenShot 2021-11-17 15.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/89cd8e2b-f6a2-e3d1-b03d-96dcf12d3065.png)

## 課題
- 運用への乗せ方を検討して、仕組みの構築が必要
    - PRの時点でコード解析をかける
    - ブランチにマージしたらコード解析をかける
    - など
- 細かい設定を調べていく必要がありそう。
    - テストコードに使用している日本語関数名が parse error になっていた

## まとめ
細かいところまで見られていませんが、実プロジェクトで試してみるとなかなかリファクタリングし甲斐がありそうな状況でした。。。
自分が体感している負債は、アーキテクチャ自体の問題も多いのかなと思っており、今回検出している負債を返済しようとすると、そういった修正に手を入れることになるのかもしれません。

こういった静的解析ツールでまずは可視化から改善をしていきたいですね。

## さいごに
運動通信社は
「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、
一緒に働く仲間を募集しています！

https://sportsbull.jp/about/#recruit
SQLインジェクションを防ぐ 〜1

#####SQLコードインジェクション防止の８のベストプラクティス 
https://snyk.io/blog/sql-injection-cheat-sheet/


######第一章です。

[序章](https://qiita.com/bricolageart/items/f87dd0d98f1e1b5c4666)から、早速１つ目、クライアントサイドの入力バリデーションに依存しないについてご紹介します。



[序章](https://qiita.com/bricolageart/items/f87dd0d98f1e1b5c4666)
1. [クライアントサイドの入力バリデーションに依存しない](https://qiita.com/bricolageart/items/b442165360ef24d093da)
2. [制限された権限を持つデータベースユーザーを使用する](https://qiita.com/bricolageart/items/a857fa1c058a4527f155)
3. [プリペアドステートメントとクエリパラメータ化を使用する](https://qiita.com/bricolageart/items/ffe99886bdcdbf32658e)
4. [コードをスキャンしてSQLインジェクションの脆弱性を探す](https://qiita.com/bricolageart/items/37b13aaa59a28c148ac5)
5. [ORMレイヤーを使用する](https://qiita.com/bricolageart/items/1532b73057a260aaa755)
6. [ブロックリストに依存しない](https://qiita.com/bricolageart/items/6d4a78da2870dce6edf7)
7. [入力バリデーションを行う](https://qiita.com/bricolageart/items/36689c797a678e406b6c)
8. [ストアドプロシージャに注意する](https://qiita.com/bricolageart/items/2abfb7ef48a6bfd990bf)


[チートシート（英語）はこちら](https://snyk.io/wp-content/uploads/8-best-practices-to-prevent-SQL-injection-attacks.pdf)


### 1.クライアントサイドの入力バリデーションに依存しない
クライアントサイドの入力バリデーションは有用です。クライアントサイドの入力バリデーションを使用することで、無効なものがシステムロジックに送信されるのを防ぐことができます。ただし、残念ながら、これは悪意がなく、設計どおりにシステムを使用したいユーザーにしか通用しません。特定の値が無効であるという直接的なフィードバックをユーザーに提供することは、非常に有益で、ユーザーフレンドリーです。したがって、ユーザーエクスペリエンスを向上させるためには、クライアントサイドバリデーションを使用すべきです。

しかし、SQLインジェクションの観点からは、この方法には頼るべきではありません。ブラウザに読み込まれているJavaScriptコードを変更することで、クライアントサイドのバリデーションを削除できます。また、クライアントサーバ型のアーキテクチャでは、postmanのようなツールや昔ながらの`curl`コマンドを使い、バックエンドへの基本的なHTTPコールにSQLインジェクションを引き起こすパラメータを指定することは非常に簡単です。

バリデーションはサーバーサイドで、理想的にはできるだけソースに近い場所で行うべきです。この場合、SQLクエリを作成する場所でバリデーションします。クライアントから送られてくるものはすべて潜在的に有害であると考えるべきです。ですから、SQLインジェクションの観点から、クライアントサイドのバリデーションに頼るのは、とても危険です。



１つ目は以上です。
最後までお読みいただきありがとうございました！
######次回は[SQLインジェクションを防ぐ 〜2](https://qiita.com/bricolageart/items/a857fa1c058a4527f155)に続きます。


SQLインジェクションに関する英語全原文は[こちら](https://snyk.io/blog/sql-injection-cheat-sheet/)です。

---
######Contents provided by:
Jesse Casman, Fumiko Doi, Content Strategists for Snyk, Japan, and Randell Degges, Community Manager for Snyk Global
SQLインジェクションを防ぐ 〜序章


https://snyk.io/blog/sql-injection-cheat-sheet/


ソフトウェアというよりアプリ、SQLよりno SQLという言葉のほうがピンとくる人が増えてきているかもしれません。はじめてno SQLついて知ったときには、SQLじゃないのにDBなんだ？！、どういうこと？とびっくりしましたが、ネーミングもさることながら、データのマネージメント、データサイエンティストについて、高校の時からしっていれば（どんだけ前だよ！）、、、そうすれば、数学もっと頑張ったのに。。。と、後悔、先に立たずです。

ちなみにアプリは英語ではアップ（英語ではapp）というのが一般的。（アはエにちかいアですwww)
SQLは（エス・キュー・エル）は、英語ではシークェル。響きがけっこう違いますよね。
海外のエンジニアと話していて、
SQLのこと話してるのに、シーコールとか、Cカールとか聞こえるし、なんなん？と、とまどった経験があるある！の方も多いのではないでしょうか。

さて、前々回に[java sciptのnode.jpのコードインジェクション](https://qiita.com/bricolageart/items/96adf44a75a0e662ceee)についての記事を取り上げましたが、今回はSQLのインジェクションを防ぐためのベストプラクティスについての記事を取り上げたいと思います。

英語全原文は[こちら](https://snyk.io/blog/sql-injection-cheat-sheet/)です。
[チートシート（英語全文）はこちら](https://snyk.io/wp-content/uploads/8-best-practices-to-prevent-SQL-injection-attacks.pdf)です。

長〜い、濃い内容のため、１つの章ずつご紹介いたします。

##SQLインジェクションのチートシート：SQLインジェクション攻撃を防ぐための8つのベストプラクティス　序章

Brian Vermeer　ブライアン フェルメール
2021年3月26日

SQLインジェクションは、オンラインアプリケーションにとって最も危険な脆弱性の1つです。これは、ユーザーが信頼できないデータをデータベースクエリに追加したときに発生します。たとえば、Webフォームに入力する場合です。SQLインジェクションが可能な場合、ずる賢い攻撃者は、ユーザー入力を作成して、貴重なデータを盗んだり、認証をバイパスしたり、データベース内のレコードを破壊することができます。
SQLインジェクション攻撃にはさまざまな種類がありますが、一般的にはどれも攻撃されやすい共通の原因があります。例えば、ユーザーが入力した信頼できないデータは、クエリ文字列と連結されます。そのため、ユーザーの入力によって、クエリの本来の意図が変わってしまうのです。
 
SQLインジェクションの例をいくつか挙げてみましょう。


- `OR 1=1`のように常に真であるブーリアンをWHERE句に追加する
行コメントを入力してクエリの一部をエスケープする `--`
- 最初のクエリを終了し、新しいクエリを開始する。 `; DROP TABLE USERS;`
-  `UNION`を使って複数のテーブルからデータを接続する

このチェックリストでは、すべてのアプリケーションプログラマーがSQLインジェクション攻撃を防ぐために使用できる8つのベストプラクティスを取り上げます。それでは、アプリケーションのSQLi対策を行っていきましょう。


#####SQLコードインジェクション防止の８のベストプラクティス

1. [クライアントサイドの入力バリデーションに依存しない](https://qiita.com/bricolageart/items/b442165360ef24d093da)
2. [制限された権限を持つデータベースユーザーを使用する](https://qiita.com/bricolageart/items/a857fa1c058a4527f155)
3. [プリペアドステートメントとクエリパラメータ化を使用する](https://qiita.com/bricolageart/items/ffe99886bdcdbf32658e)
4. [コードをスキャンしてSQLインジェクションの脆弱性を探す](https://qiita.com/bricolageart/items/37b13aaa59a28c148ac5)
5. [ORMレイヤーを使用する](https://qiita.com/bricolageart/items/1532b73057a260aaa755)
6. [ブロックリストに依存しない](https://qiita.com/bricolageart/items/6d4a78da2870dce6edf7)
7. [入力バリデーションを行う](https://qiita.com/bricolageart/items/36689c797a678e406b6c)
8. [ストアドプロシージャに注意する](https://qiita.com/bricolageart/items/2abfb7ef48a6bfd990bf)

######[SQLインジェクションを防ぐ 〜1](https://qiita.com/bricolageart/private/b442165360ef24d093da) に続きます。



---
Contents provided by:
Jesse Casman, Fumiko Doi, Content Strategists for Snyk, Japan, and Randell Degges, Community Manager for Snyk Global
【所要時間1分】ノーコードプログラミングでBotデビュー　#IFTTT #ノーコード #iPaaS

##Twitterの定期配信は超簡単##

ノーコードプログラミングでTwitterBotデビューしてみました:poop:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122173/69816634-b718-d592-ea8d-f501bacf34eb.png)

所要時間１分は盛ってるかもですが、やりたいことが決まっていれば爆速です。

##IFTTT##
今回はIFTTT（イフト）というサービスを使いました。
複数のWebサービス/アプリを繋げられるサービスですね。

https://ifttt.com/home

##手順
個人的にはPCよりスマホのがお手軽でした。

トリガー（If This）を選択して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122173/03e0fb80-0c0c-c6b9-f268-19e9f1890b99.png)


アクション（Then That）を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122173/21194b25-98f0-7017-15c1-c7d1b7ca4c23.png)


終わった。笑

これで**「毎日●●時に●●という内容のツイートを自動で発信する」**ようになりました。

もはやプログラミングと言えるのかすら怪しいレベル。

**アプリの設定をちょっとイジったくらいの感覚**ですね。


ただ、使える材料が限られている分、どのアプリを繋げるかの**発想力が求められる**のだろうと思います。

いずれにしても、プログラミングのハードルが下がることはとてもいいことですよね:hugging:
【技術書まとめ】1週間でLPICの基礎が学べる本

# Linuxとオープンソース

- OSがハードウェアの違いを吸収してくれるから意識せずアプリケーションを開発できる


# Linuxの基本操作

- Linuxのファイル名
    - Linuxでは`.doc`としてもアプリケーションが関連づけられるわけではない
        - 拡張子はファイル名の一部に過ぎない
    - `.`で始まるファイルは隠しファイルとなる
- ファイルはiノードで管理されている
    - `ls -i`
    - iノード番号とファイル名の対応付けをリンクと呼ぶ
        - 一つのiノードに複数ファイルをリンクできる
            - ハードリンクという
                - ユーザー側からは別々のファイルのように見えるがハードディスク上のデータは一つだけ
                    - `ln 元ファイル 作成するリンクファイル`
                - パーティションを超えて作れない
                - ディレクトリのハードリンクは作れない
            - シンボリックリンク
                - 別名をつける
                    - `ln -s 元のファイル 作成するリンクファイル`
    - Linuxでの「ファイルの削除」はiノードとファイル名のリンクを切断すること
        - 上書きされるまでデータは残る


# ファイル管理・ユーザーとグループ

- ファイルのコピー
    - `cp コピー元ファイル名 コピー先ファイル（ディレクトリ）名`
- ファイル名の変更は`mv`コマンドで行う
- `tree`でツリー表示できる
- 圧縮アーカイブを作成・展開
    - `tar czvf アーカイブファイル名 ディレクトリ名`
    - `tar xzvf アーカイブファイル名`
- ユーザー名とUIDの対応情報は`etc/passwd`にある
    - 99以下のユーザーIDはシステムユーザー
- `su`は元のユーザーを待機させておいて別ユーザーとして作業開始するコマンド



# バーミッション・テキストファイルの編集

- ディレクトリのアクセス圏
    - r
        - `ls`でファイル名一覧を表示できる
            - ただし`Permission denied`のエラーが出る
                - `cat`はできない
    - w
        - ファイルの内容変更ができる
        - ディレクトリ内でファイル作成、削除ができる
    - x
        - ディレクトリ内に`cd`で移動できる
        - ディレクトリ内のファイルにアクセスできる



# シェル・シェルスクリプト

- リダイレクト
    - 標準出力先を変えること
        - `コマンド > ファイル名`で上書き
        - `コマンド >> ファイル名`で追記する
    - 標準エラー出力をリダイレクトする
        - `ls -l today nofile 2> stderr.txt`のように`2>`を使う
- 環境変数はグローバル変数ではない
    - 新しいシェルを起動したりするときに、その値がコピーされ、デフォルトで利用できるようになる変数と考える


# ファイルの操作・ソフトウェアパッケージ・ファイルシステム

- `tail`,`head`はデフォルトでは10行表示する
- `sort -n sample`で数値としてソートできる
- `cut -d: -f1,3 /etc/passwd`
    - `/etc/passwd`を`:`を区切り文字として1,3フィールドを取り出す
- パッケージ管理システムのYUMとAPT
- デバイスファイルは`/dev`にある
    - ファイルアクセスと同じ仕組みでデバイスにアクセスできる
- パーティション
    - ![スクリーンショット 2021-11-16 8.10.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/dc3cf3f6-c7bc-ca6b-5d51-4e15b6b679f9.png)
- マウント
    - ![スクリーンショット 2021-11-16 8.15.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/f7453757-bf90-dce8-0559-46f1b16629e9.png)


# プロセスとジョブ・ネットワークの利用・システムの管理

- `less /etc/services &`など`&`てバックグラウンドでジョブ実行できる
    - `fg %ジョブID`でフォアグラウンドで実行できる
        - ctrl+zでジョブを一時停止にできる
            - `bg %ジョブID`でまたバックグラウンドで実行できる
- プロトコル
    - 通信を行う上での取り決め、通信規約のこと
        - TCP
            - Transmission Control Protocol
                - パケット再送など通信信頼性の向上を図る
        - IP
            - Internet Protocol
                - IPアドレスを規定し、パケット伝送のネットワーク経路を制御する
        - UDP
            - User Datagram Protocol
                - パケット到達を確認しない通信
                    - スピーディな伝送ができる
        - ICMP
            - Internet Control Message Protocol
                - 通信でのエラーメッセージや制御メッセージを伝送する
- プライベートアドレスの範囲
    - `10.0.0~10.255.255.255`
    - `172.16.0.0~172.31.255.255`
    - `192.168.0.0~192.168.255.255`
[Drupal]カスタムの権限を追加する方法・カスタム権限を使うメリット

Drupal3年やってきてはじめて知ったんですが、カスタム権限の追加方法が案外簡単だったので紹介したいと思います。

## カスタム権限の作り方
### 静的権限の作り方
カスタムモジュールのルートに`my_module.permissions.yml`を作成し、以下のように記入して`drush cr`するだけ

```yml
display xxx:
  title: 'xxxを表示する'
  description: 'xxxを表示します.'
  restrict access: true
```
### 動的権限の作り方
権限名の中に変数を入れたい場合はこちらの方法を参照

https://codimth.com/blog/web/drupal/how-add-custom-permissions-drupal-8

## 権限の使い方

### 役割ごとに権限を割り当てる
作成した権限は`/admin/people/permissions`　に表示されるので、この権限を適用したい役割にチェックして保存
![スクリーンショット 2021-11-18 7.30.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/c8816be7-52d8-7c99-d5c5-182ae356e0b6.png)

### 権限チェックを行う
```php
// 現在のユーザーを取得.
$user = \Drupal::getCurrentUser();
if ($user->hasPermission('display xxx')) {
  // 処理.
}
```

## カスタム権限を使うメリット
### コードの可読性が高くなる
「ユーザーが〇〇の役割を持っている場合はXXをできる」という要件をコード化する際、

#### 役割で直接指定する場合
`hook_entity_presave`などで役割チェックしたい対象のユーザーの情報(`UserInterface`)をもともと持っている場合は単純に以下のように書ける。

```
if ($user->hasRole('editor')) {
  // 処理
}
```
ユーザー情報ではなくアカウント情報(`AccountInterface`)から役割を取得する場合は以下のようになる。（アカウント情報は`getRoles()`はあっても`hasRole`が無いのでコードが冗長になる。）

```php
$user = \Drupal::currentUser();
if (in_array('editor', $user->getRoles()) {
  //　処理
}
```
もしくは

```php
use Drupal\user\Entity\User
$account = \Drupal::currentUser();
$user = User::load($account->id());
if ($user->hasRole('editor')) {
  // 処理
}
```

#### 権限で指定する場合
ユーザー情報でもアカウント情報でも`hasPermission()`が使える。

```php
$user = \Drupal::currentUser();
if ($user->hasPermission('display xxx')) {
  //　処理
}
```
常に権限で指定するようにすればアカウント情報を使うときもコードがすっきりするし、役割よりも直接的でわかりやすい。

### システムの見通しがよくなる
上記のように役割ベースで処理を分けた場合はソースコードを見ないと実際に誰が何をできるのかがわからないけど、権限ベースにした場合、管理画面から「どんな権限が」「どの役割に割り当てられているか」が確認できる。

### 権限と役割を分離できる

- 権限: XXXをできるかどうか
- 役割: 単なる人のグループ

として、いきなり「役割→処理」じゃなくて「役割→権限→処理」とワンクッション置くことになる。それによって「○○だけでなく△△の役割の人もXXできるようにしてください」と言われたときにコードをいじることなく役割と権限の紐付けだけ変えればいい等のメリットがある。

（システム開発では何事もワンクッション置く方がいい気がする）

個人的に、とある大規模システムで役割ベースで処理を書きまくった結果、誰が何をできるかパッと思い出せないという状況になってしまって後悔中なので、今後はできるだけカスタム権限を取り入れていきたい所存。
気軽に使えそうなnode.js 4選

・開発の補助として、駄菓子感覚で使えそうなネタを集めてみました。
・Node.jsやnpmの導入方法は割愛させていただきます。
・javascriptに関しては、kotlinやswiftを使える方なら雰囲気で書けると思います。
・きっちりめな言語が良い場合はTypeScriptも利用できます。


# エンジニアっぽくYouTube動画をごにょごにょする
```
$ npm init
$ npm install --save-dev ytdl
$ vim index.js
```
```index.js
const fs = require('fs');
const ytdl = require('ytdl-core');
ytdl('https://www.youtube.com/watch?v=xxxxxxxx')
  .pipe(fs.createWriteStream('video.mp4'));
```
```
$ node index.js
```
・実行が終わるとvideo.mp4が生成される
・プログレスバーが欲しい場合は以下を参照

https://gist.github.com/kostasx/6ebfe030d44c59662c4721e2336a7cd4

# 静的htmlを表示
```
$ npm init
$ npm install --save-dev node-static
$ vim index.html
```
```index.html
<html><body>hello</body></html>
```
```
$ ./node_modules/.bin/static 
```

・ブラウザでlocalhost:8080にアクセスすると、helloが表示される
・index.html以外にもファイルを適当に配置してOK

# リバースプロキシ
```
$ npm init
$ npm install --save-dev http-proxy
$ vim index.js
```

```index.js
var proxy = require('http-proxy');
proxy.createProxyServer({target: 'http://localhost:8080'}).listen(3001)
proxy.createProxyServer({target: 'http://localhost:50021'}).listen(3002)
```
```
$ node index.js
```
・3001を8080、3002を50021にふりわける

# CRUD JSONサーバ
```
$ npm init
$ npm install --save-dev json-server
$ vim data.json
```

```data.json
{
  "user": [
    { 
      "id": 1,
      "name": "aaa"
    },
    { 
      "id": 2,
      "name": "bbb"
    },
    { 
      "id": 3,
      "name": "ccc"
    }
  ]
}
```
```
$ ./node_modules/.bin/json-server --watch data.json 
```
・http://localhost:3000/user で全てのuserのjsonを返す

```
[
  {
    "id": 1,
    "name": "aaa"
  },
  {
    "id": 2,
    "name": "bbb"
  },
  {
    "id": 3,
    "name": "ccc"
  }
]
```
・http://localhost:3000/user/1 でidが1のuserのjsonを返す

```
{
  "id": 1,
  "name": "aaa"
}
```
・読み込みだけでなく追加・編集・削除も可能。

以上、開発の補助にお役立て下さい。
【FireBase】初期設定編

## firebase の初期設定

### 1. 以下パッケージをインストール
   ・firebase //firebase と連携するのに必要

### 2. Firebase のサイトへ行ってログインしてコンソールへ移動
   https://firebase.google.com/?hl=ja

### 3. プロジェクトを追加よりプロジェクトを追加。
   プロジェクト名を決めて作成。プロジェクト名が URL になるっぽい

### 4. ウェブアプリの登録 </> <= このボタンを押下
   アプリの名前を決める。プロジェクト名と同じで良い？
   また、Hosting をチェックを入れない。⇒ 別途 Hosting の項で実施予定？
   登録後はコンソールに戻る。
   （※ここで表示される情報は Firebase に接続する際に利用するものなので機密。これが漏れると誰でも DB アクセスなどができるようになる。）
   （※SDK はすでに手順 1 でインストール済みなのでスキップ）

### 5. Firebase の情報を確認
   左サイドバーの歯車よりプロジェクトの設定を開く。
   「SDK の設定と構成」の「構成」ラジオボタンを押下することで接続に必要な情報(認証情報)を確認できる。

### 6. .env ファイルの作成と gitignore ファイルの更新
   src と同階層に.env 作成。.gitignore に「.env」を記述

### 7. .env に認証情報を登録
   REACT_APP は.env ファイルを React で読み込むために必要なので接頭辞として付ける。他は任意でわかりやすい名前なら OK。
   あとは認証情報を右辺に書いていく

```
REACT_APP_FIREBASE_APIKEY=""
REACT_APP_FIREBASE_AUTH_DOMAIN=""
REACT_APP_FIREBASE_DATABASE_URL="" // ここは次の項目で作成
REACT_APP_FIREBASE_PROJECT_ID=""
REACT_APP_FIREBASE_STORAGE_BUCKET=""
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=""
REACT_APP_FIREBASE_MESSAGING_APP_ID=""
```

### 8.　DataBaseURL について
   手順 5 で確認した認証情報には Databese へ接続するための URL が含まれていないので自作する必要がある。
   データベースの URL は以下の形式になる。プロジェクト ID を認証情報より読み取り置き換える。

```
https://プロジェクトID.firebaseio.com
```

### 9.　src 直下に firebase 設定ファイルを作成して完了
   firebase.ts を作成し以下の設定を記述

```ts
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import "firebase/compat/firestore";

firebase.initializeApp({
  apiKey: process.env.REACT_APP_FIREBASE_APIKEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_MESSAGING_APP_ID,
});

// 任意（呼び出しを楽に行うための記述）
export const auth = firebase.auth();
export const db = firebase.firestore();
```
Vue.js で 'Invalid Host header' というエラーが出た時の対策

ブラウザーに 'Invalid Host header' というエラーが出たときの対策です。
![vue_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/05bb167e-c756-3722-94c4-14d3fb322078.png)

こちらの記事を参考にしました。
[webpack-dev-serverで起動したアプリが「Invalid Host header」と表示される場合の対処法](https://qiita.com/yutasuzuki0206/items/542390f7a046772262fe)

サーバーの起動は次のコマンドで行います。

```bash
npm run serve
```

ポート 8080 にアクセスしてエラーが出ます。

#対策#
vue.config.js を編集します。

元のファイル

```js:vue.config.js_org
module.exports = {
  transpileDependencies: ["vuetify"]
};
```

編集後のファイル

```js:vue.config.js
module.exports = {
  transpileDependencies: ["vuetify"],
  devServer: {
    disableHostCheck: true
  }
};
```

サーバーを起動

```bash
npm run serve
```

8080 ポートにアクセスするとエラーは消えます。
stm32f303k8でLチカ(VSCのcubeide)(たまたま、今日初めて動きました。)


x その今日は、11/18
x cubeideは、初心者ころしである。
x MXは、動ないと思っていた　初心者にトラブルの自己解決は、不可能?
x 今後、STM32L010F4P6を動かす予定
x そのまま、ソース一式をscrディレクトリにコピーしたら動いた
x nucleo-f030k8をそのまま、繋いでコンパイルしたらデバッグモードで動いた
x 全て、初期の状態で動いた(特にいろいろいじる必要は、なかった)
x いろいろいじっている情報は、今日(いつ)の段階では、古い!!
x 君たちふるいんだよ!!(今日(いつ)の段階)(たぶん動かなくなるのかな?)

目的
stm32f303k8でPB3を光らせる
無改造
下記をインサートしました。




```c++



        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);

        HAL_Delay(1000);

        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);

        HAL_Delay(1000);


```

stm32f303_l_tika2内をいろいろ適当にコピー



https://os.mbed.com/users/caa45040/code/f303_h_p1/


ハード


https://os.mbed.com/platforms/ST-Nucleo-F303K8/


![o_con102.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/02725a74-0775-b464-2b0e-a67f151dae35.jpeg)
なぜ駆け出しフリーランスエンジニアはやらかしてしまうのか

## はじめに
本記事では、フリーランスエンジニアとしてどう開発していくと消耗しないかを書いています。
また、ついやらかしてしまう見積りの甘さについて簡単に解説します。

## 交渉が全て
戦いは見積りを出す時から始まっています。見積りには大きく分けて以下の2パターンあります。

- 要件定義を全て満たす機能を開発するための見積もり
- ある金額で実装できる機能のみを実装するための見積り

要件定義を全て満たす機能を開発するための見積りでは、自分が不利にならず利益も出る金額で見積りを出します。
ここで**遠慮して安い金額で短期間の見積りを出すのは自分だけではなくクライアントさえも不幸にします。** なぜなら、納期は開発する前に完全にわかる物ではありません。もしも途中で納期を伸ばす場合はその分、サービス残業をしていることになります。良かれと思って出した見積りが自分も損して納期も守れないとなるとお互いに嫌な気分で開発が進みます。

次にある金額で実装できる機能のみを実装するための見積りでは、遠慮せずこの金額ではここまでしか実装できませんと言うようにしましょう。金額が安いのに全部実装できますと言うのは破滅への始まりでしかありません。

## 完璧な見積もりはない

![スクリーンショット 2021-11-18 6.14.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/3bfcaf61-d910-2393-664b-6bed4bf19b22.png)
(図はソフトウェア見積り　人月の暗黙知を解き明かすから引用)

この図は見積の不確実性を表しています。見積りを出した初期は工数が多過ぎたり、少な過ぎたりしてプロジェクトが進んでいくに従って不確実性がなくなっていくということを表しています。

経験によってこの不確実性がわかったり、プロジェクトを進めてからじゃないとわからない不確実性もあります。なので、最初の見積りを適宜変えてもらうみたいな開発をしていく必要があります。

クラウドソーシングでは、そもそも開発について見積りは変わるという認識がないクライアントがほとんどなので気をつけないといけません。

実際に駆け出しの時は見積りを甘くしてしまうのはしょうがないと思います。そのプロジェクトの実績値をデータとして蓄積し、過去のプロジェクトと似ている場合はその実績データから規模感を算出して見積りを出すという方法もあります。これがタスクリストよりも正確に見積りを出す方法の一つです。

見積りはプロジェクトの成功の大部分を占めていると個人的には思います。ぜひ、良い見積りを出すようにしましょう。

## 参考文献

ソフトウェア見積り　人月の暗黙知を解き明かす   スティーブ マコネル 
https://www.amazon.co.jp/dp/B00KR96M6K/ref=cm_sw_r_tw_dp_3YNSBY0F0TMVF59JSGHE
【Linux】テキスト処理(wc、sort、uniq、diffコマンド)実践的な使い方

##はじめに
どうも、未経験からエンジニア転職を目指しているもきおです。

今回は輪読会でどうせ発表するならQiita記事にしちゃおうと思ったのでLinuxの<font color='red'> **テキスト処理**</font>に触れていきたいと思います。

第二弾はこちら

https://qiita.com/mokio/items/0516eb1894661befdcf2

今回の記事は新しいLinuxの教科書を参考にしています。
とてもLinux標準の教科書もやった事はありますが、よりわかりやすくまとまっているのでLinuxを学びたい方におすすめです！

https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E/dp/4797380942/ref=asc_df_4797380942/?tag=jpgo-22&linkCode=df0&hvadid=295706574430&hvpos=&hvnetw=g&hvrand=13172813495091438571&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009244&hvtargid=pla-523780191776&psc=1&th=1&psc=1

##テキスト処理って？
ターミナルでの出力結果を項目に絞ったり、並べ替えたり、差分を表示したりコマンドを加工する事によってより自分自身が見やすく必要な項目に整理することができるようにするのがテキスト処理だと自分自身は感じています。

より高度なテキスト処理になると置換処理、パターン一致検索等もコマンド実行により可能です。
今回は良く使いそうなコマンドに絞って記載していこうと思います。

###WCコマンド
WCは入力ファイルの行数、単語数、バイト数を数えるコマンドです。
今回はよく使用する「-l」オプションを使用しました。

```bash:WCコマンド
$ wc -l /etc/passwd
21 /etc/passwd　←行数を表示
↑行数　↑ファイル名
```
行数を把握する事によって1行に1件の測定データがある場合はデータの件数を把握することができます。

###sortコマンド
sortは行単位で並べ替えを行うことができるコマンドです。

例：file1の内容が以下の場合

```bash:file1
Hokkaido
Aomori
Iwate
Miyagi
Akita
Yamagata
Fukusima
```

```bash:アルファベット順に並べ替え
$ sort file1
Akita
Aomori
Fukusima
Hokkaido
Iwate
Miyagi
Yamagata
```
通常のソートコマンドだとアルファベット順に並べ替えられます。
他にも「-n」で数値順、「-r」で逆順に並べ替えることができます。

このコマンドが実際に役に立ってくるのはpsコマンドでターミナル上でプロセス(実行状態にあるプログラム)を確認する際に自分が確認したいプロセスをいち早く見つけるのに役立ちます。

pxに対する「ax」オプションは全てのユーザーのプロセスを表示するオプション。
「-k」はフィールド番号を指定しています。今回はコマンドフィールド5番目の実行コマンドを確認したいので以下のように記載しています。

```bash:アルファベット順に並べ替え
$ ps ax | sort -k 5
8155 pts/0 Ss 0:00 -bash　←プロセスの例、実行コマンドは5番目に記載されている
```
これによってプロセスをASCII(アスキー)コード順に並べ替えることができます。

###uniqコマンド
uniqコマンドは連続した同じ内容の行を省くコマンドです。

```bash:file2
Hokkaido
Hokkaido
Aomori
Iwate
Iwate
Akita
Yamagata
Fukusima
```

```bash:重複を省く
$ uniq file2
Hokkaido
Aomori
Iwate
Akita
Yamagata
Fukusima
```
「Hokkaido」、「Iwate」の重複を省き一つになりました。

続いて以下のファイルだとどうなるでしょうか？

```bash:file3
Hokkaido
Hokkaido
Aomori
Iwate
Hokkaido
```

```bash:
$ uniq file3
Hokkaido
Aomori
Iwate
Hokkaido　←重複が残る
```
最後の「Hokkaido」が残ってしまいました。
連続していないと重複を削除することができないみたいです。

この場合は一旦sortで並べ替えて重複行を連続させてからuniqで省く事によって解消できます。

```bash:
$ sort file3 | uniq
Aomori
Hokkaido
Iwate
```

###diffコマンド
diffコマンドは、二つのファイルの差分を表示するコマンドです。

書式
diff 【オプション】 (比較元ファイル) (比較先ファイル)

diffによる差分表示には様々な出力形式がありますが、今回はよく使われる形式として「-u」オプションを使用した「ユニファイド形式」を使用した例を記載したいと思います。

```bash:
$ diff -u file1 file2
--- file1 2012-07-06 13:21:21.219249366 +0900
+++ file2 2012-07-06 13:26:51.664814277 +0900
@@ -3,1 +3,2 @@
-test text
+overwrite text
+new line
```
最初の二行で二つのファイルのファイル名と更新日時が表示されます。3行目から差分表示になります。

最初の@@から始まる行はその差分表示が元のファイルの何行目に対応しているかを表しています。これを「@@ -(一つ目のファイルの変更開始行),(変更行する) +(二つ目のファイルの変更開始行),(変更行数) @@」という形式で表します。

今回でいう「@@ -3 +3,2 @@」は
- 一つ目のファイルにおいては3行目から1行分
- 二つ目のファイルにおいては3行目から2行分
に対応していることを意味しています。

あとは「-」記号は削除された行、「+」記号で始まるものは追加された行を表示しています。

##あとがき
いかがだったでしょうか？

これらのコマンドを使いこなせるようになる事によって実務での開発効率を上げることができそうですね。早く実践で使用していけるよう日々基礎固めをしていきたいと思います。

最後までご覧いただきありがとうございました！！
LaravelとPHPUnitでDB操作クラスの単体テストを行う

LaravelとPHPUnitでDB操作クラスの単体テストを実装しました

[テストの準備](https://readouble.com/laravel/8.x/ja/testing.html)

## テスト対象のドメインクラス
```php
<?php

namespace App\Domains\AdminCompany;

class AdminCompany
{
    private $adminCompanyName;

    public function __construct(
        AdminCompanyName $adminCompanyName,
    ) {
        $this->adminCompanyName = $adminCompanyName;
    }


    public function getName(): ?AdminCompanyName
    {
        return $this->adminCompanyName;
    }
}

```

## テストコード


> Note: テストクラスに独自のsetUpメソッドを定義する場合は、親のクラスのparent::setUp()／parent::tearDown()を確実に呼び出してください。

```php
<?php
namespace Tests\Unit\Domains\AdminCompany;

use App\Domains\AdminCompany\AdminCompany;
use ArgumentCountError;
use PHPUnit\Framework\TestCase;

class AdminCompanyTest extends TestCase
{

    private $adminCompanyName;

    protected function setUp(): void
    {
        // 必須
        parent::setUp();

        $this->adminCompany = new AdminCompany(
            $this->adminCompanyName = new AdminCompanyName('example'),
        );
    }

    public function test_コンストラクタに何も渡さない場合はエラーになる()
    {
        $this->expectException(ArgumentCountError::class);
        new AdminCompany();
    }

    public function test_getName_コンストラクタに正しインスタンスを渡すと渡された値を返す()
    {
        $this->assertEquals($this->adminCompanyName, $this->adminCompany->getName());
    }
}
```

## テストを実行する

```bash
./vendor/bin/phpunit

==== Redirecting to composer installed version in vendor/phpunit ====

PHPUnit 7.5.9 by Sebastian Bergmann and contributors.

..........                                                        2 / 2 (100%)

Time: 8.11 seconds, Memory: 24.00 MB
OK (2 tests, 2 assertions)
```

CI/CDするのは品質を維持できるのでぜひ導入してみてください!


## 最後に

読んでいただきありがとうございます。
今回の記事はいかがでしたか？
・こういう記事が読みたい
・こういうところが良かった
・こうした方が良いのではないか
などなど、率直なご意見を募集しております。
dayjsをいい感じにカスタマイズしてimportすると捗った話

デフォルトはタイムゾーンが"en"なので毎回変換するのも手間なのでモジュールをカスタマイズしてみた

https://github.com/iamkun/dayjs/blob/dev/docs/ja/Plugin.md


## カスタム設定する
```ts:src/commons/customs/dayjs.ts

import * as dayjs from 'dayjs'

// 最大値・最小値の計算するための拡張プラグイン
import * as minMax from 'dayjs/plugin/minMax'

// 日本時間に変換する
import 'dayjs/locale/ja'


// プラグイン拡張
dayjs.extend(minMax)
dayjs.locale('ja')

// export default 構文を提供し、“モジュール毎に1つのもの” のように見栄えを良くします。¥
export default dayjs
```

## 違い

### カスタムしていない場合
```ts
import dayjs from 'dayjs'

 dayjs()
d {
  '$L': 'en',
  '$d': 2021-11-18T04:21:44.245Z,
  '$x': {},
  '$y': 2020,
  '$M': 9,
  '$D': 20,
  '$W': 2,
  '$H': 13,
  '$m': 21,
  '$s': 44,
  '$ms': 245
}
```

### カスタムした場合
```ts
import dayjs from 'src/commons/customs/dayjs'

 dayjs()
d {
  '$L': 'ja',
  '$d': 2020-10-20T04:21:44.245Z,
  '$x': {},
  '$y': 2020,
  '$M': 9,
  '$D': 20,
  '$W': 2,
  '$H': 13,
  '$m': 21,
  '$s': 44,
  '$ms': 245
}
```

これで毎回日本時間に変換する手間がなくなりました。。。

Ts入門時はdate()を使用していましたが、最近はずっとdayjs()にお世話になってます
ErrorBoundaryを考える

# ErrorBoundaryを考える
Reactなどでエラーに直面する時、画面が真っ白になる場合がありました。
調べるとErrorBoundaryを実装すると（真っ白になるのを）防げるらしい

## 実装

```ts
import React, { ReactNode, ErrorInfo } from 'react';

type Props = {
  children: ReactNode;
};
type State = {
  hasError: boolean;
  error: Error | null;
  errorInfo: ErrorInfo | null;
};

export default class ErrorBoundary extends React.Component<Props, State> {
  constructor(props: Props | Readonly<Props>) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }
  static getDerivedStateFromError(): { hasError: boolean } {
    // 次のレンダリングでフォールバック UI が表示されるように状態を更新します。
    return { hasError: true };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    // エラー報告サービスにエラーを記録することもできます。
    this.setState({ error, errorInfo });
  }

  render() {
    if (this.state.hasError) {
      console.log('JavaScript のエラー発生');
      console.error(this.state.error?.message);
      console.error(this.state.errorInfo?.componentStack);

      // エラー時の表示
      return <div></div>;
    }
    return this.props.children;
  }
}

```

## どういった動作なのか
`static getDerivedStateFromError()` か `componentDidCatch()`でエラーを検知してレンダリングを制御するらしい

ここまでは、いろんなサイトで書いてある
### レンダリング
インターネットに例があったので実装してみた。
以下が実装結果
コンポーネントでのエラーの場合は、消えるようです。

![エラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549680/ca6e6e01-6986-ee7c-8df8-74fe4c972e03.png)
次の画像がコンポーネントでの処理で起こったエラーです。
下記のコードを実装して５より上ならエラーが発生します。

```ts
const [count, setCount] = useState(0);
  const setData = () => {
    setCount(count + 1);
    if (count > 5) throw new Error('エラーだよ');
  };
```

![スクリーンショット 2021-11-18 2.03.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549680/2be8aebd-14cc-2fea-a160-fd2daabc75c5.png)

１枚目のエラーで赤いエリアが消えたのは、レンダリング以前にエラーが発生しているから消えたのだと思います。

２枚目は、レンダリング事態には、問題がないため表示されます。しかし、カウントが５よりも上なので押すたびにエラーが発生します。

## 感想
コンポーネント自体が消えている場合、マウントされる前にエラーが起こっている。
再レンダリングされた際にコンポーネントが見えているのであれば処理系で何かエラーがあったんだと考えらばいいのかな？
【無料BGM素材】ゲーム・アプリ開発におすすめのBGMダウンロードサイトまとめてみた。3選！

アプリ制作におすすめの、BGMのダウンロードサイト【無料】をまとめてみました。

それぞれの短所・長所も追加でまとます。

https://kaedeee.com/app-famous-bgm-download-site/

#魔王魂

https://maou.audio/category/bgm/bgm-neorock/

![スクリーンショット 2021-11-17 19.08.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/c59338ab-3026-b172-19a1-9da25366e20e.png)



**長所**
BGMとSEの両方の素材が豊富。
無料なのに高クオリティ。開発者どんだけいい人なんだ、、、

**短所**
モダンなゲームには向いていない（と思う）レトロなゲームには合う。
Youtubeなどで、聞いたことのある曲が多い。

#DOVA SYNDROME

https://dova-s.jp/bgm/

![スクリーンショット 2021-11-17 19.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/4b9c91ef-21a7-5e24-3c6c-84df7b59a119.png)

**長所**
のほほん系BGMはここしか勝たん！
豊富すぎるBGM
ヒカキンが使ってる。

**短所**
神BGMを見つけるまで難しい。検索機能が弱い。


#NSC (NoCopyrightSounds)

https://www.youtube.com/c/NoCopyrightSounds

![スクリーンショット 2021-11-17 19.09.20.png]![スクリーンショット 2021-11-17 19.26.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/c476c2e0-e591-0922-d902-71b931993547.png)

**長所**
曲がイケメンすぎる。
豊富すぎるBGM

**短所**
非の打ち所がない音楽に、コンテンツが負けてしまう。
キラキラネーム的とおんなじ。

#終わり
3つのおすすめBGMダウンロードサイトをご紹介しました。
いつもありがとナス。

https://kaedeee.com/app-famous-bgm-download-site/
【React】'return' outside of functionの対処法

<h2>症状</h2>
reactでSPAアプリを開発していた時、以下のエラーが表示されました。
翻訳すると「関数外の「return」」になりました。

```terminal:error
SyntaxError: 'return' outside of function (169:0)
```

以下がソースです。

```react:APP.js

export const App = () =? {
  
  function Hoge () {
    console.log(処理！)
  }
}

  return(
    <div><div>
  )
}

```

<h2>解決方法</h2>
原因としては、return()が関数の外側にいたためエラーが発生しているというそのままの状況で、今回の場合、functionの閉じかっこを間違えて２つ書いてしまい、そのメソッドを閉じてしまった状況になってしまい、本事象は発生しました。

```react:APP.js

export const App = () =? {
  
  function Hoge () {
    console.log(処理！)
  }
}//ここを削除して解決

  return(
    <div><div>
  )
}

```
radius とは

## 勉強前イメージ

認証ってイメージ

## 調査

### radius とは

Remote Authentication Dial In User Service の略で、ユーザ認証のプロトコルになります。
ネットワーク上でユーザの認証・権限の付与・利用状況記録など行います。
インターネットの接続サービスや無線LANのユーザ認証にも使われています。
radiusの通信はIPとUDPが使用されており、パスワード等の情報は共通鍵暗号によって暗号がされて送受信される。

### radiusの構成

radiusにはまず3つの要素があり、それは以下になります。

- ユーザ
- radiusサーバ
- radiusクライアント

radiusクライアントはNASとも呼ばれていてアクセスポイントが該当します。
ユーザの認証の要求を受けてradiusサーバに情報を転送するのが radiusクライアントの役目になります。
ユーザの認証を許可するかどうかは radiusサーバが決め、
ユーザ情報はradiusサーバがローカルか外部DBに保持できます。
radiusサーバが一元管理するので、radiusクライアントが複数存在しても1箇所で制御ができます。

### radiusの認証の流れ

1. ユーザがradiusクライアントに接続します。
2. radiusクライアントのユーザに認証を要求します
3. ユーザはユーザ名・パスワードを記載
4. radiusクライアントは受け取ったデータからradiusサーバに認証をリクエストします
5. radiusサーバは認証の承認可否の判断を送り
6. radiusクライアントは承認結果を伝えます

![12021-11-18 # radius とは - diagrams.net - Google Chr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/c014fb55-5fd0-6802-9360-563b74d8b275.png)

### UDPを使う理由

認証とかだったらTCPの方が良いんじゃないかなーって思って調べてみたらありました。
一次情報じゃないけど....
radiusサーバは冗長化されてる前提で、再送処理をTCPに任せるのではなく、違うサーバに投げたほうがいいよね ってことらしい。

## 勉強後イメージ

wifiとかに使われるのねー
UDPな理由はわかったけど、それでもTCPのほうが・・？って思っちゃう
オライリーに載ってるらしいから見てみたい、、、

## 参考

- [RADIUSサーバとは](https://www.designet.co.jp/faq/term/?id=UkFESVVT44K144O844OQ)
- [RADIUS認証の仕組み](https://kfep.jp/radius-news-2016-03-28-3058)
- [RadiusはなぜUDPなんだろう?](https://stealthinu.hatenadiary.jp/entry/20060511/p1)
discord.jsでテキスト読み上げ機能を作った時に詰まったところの備忘録

#遭遇したエラー1つ目
```
Could not load the default credentials.
```
これはどうやらgoogle関連のパッケージを利用をしている時に出るようです。私はテキストの読み上げに「@google-cloud/text-to-speech」を使っていたのでそれで出たみたいです。ざっくり言うとgoogle cloud登録しろよってことです。
[こちらのページ](https://ichi.pro/googlecloud-to-node-js-o-shiyoshita-tekisuto-yomiage-sofutowhea-178736867703029)を参考にしてgoogle cloudに登録したりして無事解決。
#遭遇したエラー2つ目
```
Error:'FFmpeg/avconv not found!'
```
テキスト読み上げ機能が完成してからbotをherokuにデプロイしたものの読み上げてくれない...
ローカル環境では動いてくれたのに...
どうやらherokuで音声ファイルを再生したりするのに必要なもんがないらしい。
ターミナル上で

```
heroku buildpacks:add https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git
```
を実行すると無事読み上げてくれました！！
困った人の役に立てば幸いです。ではでは〜
【初学者】Atcoder ABC154A~Cの解説

jaascriptの学習としてatcoderをjavascriptで可能な限り解く。javascriptが一番とっつきやすい。


##ABC154A - Remaining Balls

###問題

https://atcoder.jp/contests/abc154/tasks/abc154_a


###解答

```
"use strict";  //標準入力。
const main = arg => {  

    const input = arg.trim().split("\n");  //trimで前後の空白を削除し、split関数で\n指定して改行する。
    const strngs = input[0].split(" ");　　　　　　　　//配列inputの0番目の値をsplit関数で半角を指定して改行する。
    const A = Math.floor(input[1].split(" ")[0], 10);  //配列inputの1番目の0番目の値をsplit関数で半角を指定して改行し、Math.floor関数で問題のルールである10以下であることを指定する。
    const B = Math.floor(input[1].split(" ")[1], 10);  //配列inputの1番目の1番目の値をsplit関数で半角を指定して改行し、Math.floor関数で問題のルールである10以下であることを指定する。

    const U = input[2]; //配列inputの２番目の値。

    if ( U === strngs[0]) {　　　　　　　　　　　//割愛
        console.log((A - 1), B);
    } else {
        console.log(A, (B - 1));
    }
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'));  //標準入力。

```

コメントアウトすると理解できるが、いざ書けとなると書けない。

###出てきた関数

####trim()
前後の空白を削除する。


####split("\n"); 
\nは改行を表す。

####Math.floor();
与えられた数値以下の最大の整数を返す。

##ABC154B - I miss you...

###問題

https://atcoder.jp/contests/abc154/tasks/abc154_b


###解答

```
"use strict";
const main = arg => {

    const inputLength = arg.trim().length; // 入力された文字列のの前後の空白を削除し、長さをlengthで取得する。
    const letter = "x"; //カンマは文字列と認識するために必要。
    const answer = letter.repeat(inputLength).trim().replace(/\r?\n/g, ''); //letterに格納された文字列xをrepeat関数でinputLength分繰り返し、trimで前後の空白を切り取り、正規表現を含んだreplace(/\r?\n/g,'')で文字列の改行を削除できる。
    console.log(answer);
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'));  

```
標準入力の文字列の長さを取得し、その値分repeat関数を使い文字列を表示するという発想ができなかった。
文字列を1文字ずつ分解して配列にし、配列の値それぞれをxに変更し、配列を一つの値にすると考えたができなかった。

##ABC154C - Distinct or Not


##ABC154D - Dice in Line




参考
https://qiita.com/ShinKano/items/50cba94a7c29cc690c18
Javascriptのオブジェクト型、プリミティブ型について

#JSのデータ型
Javascriptを***JS***と略して使います。
JSは主に```オブジェクト型```と```プリミティブ型```に分けられます。

#プリミティブ型
JSのプリミティブ型は下の7つです。

1 ```数値型(Number)```
正数、負の数、少数などの数値です。

2 ```文字列型(String)```
文字列のことでダブルクオテーションがシングルクオテーションで表せます。

3```論理型(Boolean型)```
trueかfalseで表します。

4　```Null型```
中身が空で何もない状態です。

5　```Undefined型```
未定義で何を表ているのかがわからない時です。

6　```Symbol型```
symbolの値を

7　```BigInt型```
巨大な整数のデータ


#オブジェクト型
***プリミティブ型以外***はオブジェクト型です。
なのでプリミティブ型を抑えておけばオブジェクトはすぐ理解できます。

#

#最後に
Rubyは全部オブジェクトでできていますがJSは違います。
1つ言語になれたら他の言語にも応用ができて
学習した言語と比較しながら学習するといいと思います。




⚫︎参考資料
https://qiita.com/makotoo2/items/9566cebf205ef8b42505
https://itsakura.com/javascript-data-type
【SPARQL】対象項目がないレコードを除外したい

## 概要
以前に[【SPARQL】レコード単位で保持されるデータを列の形式で取得したい](https://qiita.com/someone7140/items/12e28afa26e49cc233b1)で、外部結合のような機能を持つ`OPTIONAL`句について紹介しました。外部結合に似た機能ですので、このOPTIONAL句で指定した項目がレコードにない場合もあります。そのようなとき、対象のレコードを除外したい場合どうすれば良いかというのをメモ書きします。

## 対応
[Excluding Blank Nodes from SPARQL query results](https://stackoverflow.com/a/44113648)のstackoverflowの記事にある通り、`isBlank`関数を使えば空の項目を除外できそうです。OPTIONAL句で取得した項目を、FILTER句で`isBlank`で判定すればよさそうですね。

## クエリサンプル
今回も[gBizINFO](https://info.gbiz.go.jp/)の財務データを例にします。財務データでは売上高を取得できますが、登録されている会社とされていない会社があります。
以下は、売上高を登録されていない会社を`isBlank`の判定で除外し、結果を取得するクエリです。

```sparql
PREFIX hj: <http://hojin-info.go.jp/ns/domain/biz/1#>
PREFIX ic: <http://imi.go.jp/ns/core/rdf#>
SELECT ?companyId ?companyName ?address ?salesAmount
FROM <http://hojin-info.go.jp/graph/zaimu>
WHERE {
  ?s hj:法人活動情報 ?o .
  ?o ic:ID/ic:識別値 ?companyId .
  ?o ic:名称/ic:表記 ?companyName .
  ?o ic:住所/ic:表記 ?address . 
  OPTIONAL {
    ?o hj:数量コレクション/hj:数量 ?c2 .
    ?c2 ic:数値 ?salesAmount .
    ?c2 hj:指標 ?salesAmountName .
    FILTER(?salesAmountName = "http://hojin-info.go.jp/code/財務情報/売上高"^^ic:コード型) 
  } 
 FILTER(!isBlank(?salesAmount))
}
ORDER BY ASC(?salesAmount)
LIMIT 10 
```
AtCoder Beginner Contest 227

##[A - Last Card](https://atcoder.jp/contests/abc227/tasks/abc227_a)

O(N)
シミュレートします。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N, K, A;
    cin >> N >> K >> A;
 
    int cnt = 1;
    A--;
    while(cnt < K){
        cnt++;
        A++;
        if(A>=N) A=0;
    }
    cout << A + 1 << endl;

    return 0;
}
```

##[B - KEYENCE building](https://atcoder.jp/contests/abc227/tasks/abc227_b)

O(N)
与えられた式で計算量を減らす事ができます。

```
for(int a=1; a<=S[i]; a++)
```

ではなく

```
for(int a=1; 3*a + 4*a<=S[i]; a++)
```

のような全探索でいけるかと思います。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N;
    cin >> N;
 
    vector<int> S(N);
    rep(i, N) cin >> S[i];
 
    int res=0;
    rep(i, N){
        for(int a=1; 3*a + 4*a<=S[i]; a++){
            int ok=0;
            for(int b=1; 3*a + 4*b*a + 3*b<=S[i]; b++){
                if(3*a + 4*b*a + 3*b == S[i]){
                    res++;
                    ok=1;
                    break;
                }
            }
            if(ok) break;
        }
    }
    cout << S.size() - res << endl;
 
    return 0;
}
```

##[C - ABC conjecture](https://atcoder.jp/contests/abc227/tasks/abc227_c)

O(N)
これも与えられた式を変形し計算量を減らす問題です。
気をつけることはオーバーフローです。
A＊Aでオーバーフローします、この場合は割り算を使います。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    ll N;
    cin >> N;
 
    ll res=0;
    for(ll A=1; A<=N/A/A; A++){
        for(ll B=A; A<=N/B/B; B++){
            ll C = N / (A*B);
            res += C-(B-1); 
        }
    }
    cout << res << endl;
 
    return 0;
}
```
【MLOps】docker/mlflowを使った競馬AI開発環境構築（2021年版）~ docker構築 ~

今回は、分析データ用のデータベースやモデル管理用のmlflowをインストールするためのdocker環境の構築手順を紹介していきます。dockerに慣れない方は難しく感じる点もあると思うのですが、頑張っていきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69277/58e16da9-29bc-5849-22e1-947ac66227d2.png)


### docker環境構築手順

1. ローカル環境にdockerをインストールする
2. 分析用データ保存用MySQLとデータ参照用Adminerを設定する
3. mlflowとデータベース・リポジトリを設定する

今回は大サービスで、docker環境構築用のためのdockerfileを公開します！これを使えば簡単にあるコマンドを叩くだけで構築完了するので、感動しますよ！

#### 1. ローカル環境にdockerをインストールする

まずはdockerをインストールしましょう。公式サイトからdockerのインストーラをダウンロードして実行してください。

https://docs.docker.com/get-docker/

#### 2. 分析用データ保存用MySQLとデータ参照用Adminerを設定する/3. mlflowとデータベース・リポジトリを設定する

まずは、設定ファイルを保存するためのフォルダをローカルに作成してください。
docker環境構築用の設定ファイルをgitlabに公開していますので、こちらをダウンロードしてインストール用のフォルダに格納してください。

https://gitlab.com/horse_rasing_ai/development-kit-docker

最後に、コマンドプロンプト(windows)かTerminal(Mac/ubuntu)を起動して、先程のdocker設定ファイル
（docker-compose.yml）があるフォルダに移動して次のdockerコマンドを実行してください。

```
docker-compose up -d
```

エラーなく完了したら構築完了です。

### まとめ

今回はdocker環境の構築方法を説明しました。dockerコマンドを使えば簡単に環境構築ができることを実感してもらえたでしょうか？他に必要なコンポーネントが出てきた時には自分でdockerfileやdocker-compose.ymlを書き変えることで簡単にイメージを追加できるので、色々試してみたくださいね。
AWS環境設定(料金アラート設定)

# AWSで料金発生時に通知を出す方法
###### 今更感はありますが私が最近AWSの勉強を始めたので許してください。

まずはAWS公式サイトを見ていただくのがいいかと思います。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html

では、実際に作業した工程を画面キャプチャと一緒にお見せします。
###### ステップ１：まずはルートユーザーもしくは請求情報の設定権限のあるユーザーでAWSマネジメントコンソールにログイン
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/b0c36d08-5acd-c6ef-07e3-65663f661899.png" width=50%>
###### ステップ２：マイ請求ダッシュボードを開く
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/dbb41307-43ed-59d6-70d6-4c8a67b2b1d8.png" width=50%>
###### ステップ３：請求設定を選択する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/b8383ffd-0bff-9d88-2542-0c7fd8424c1e.png" width=50%>
###### ステップ４：画面内のチェックを付ける
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/811d5988-9972-0b78-f29c-b9fe52e5163a.png" width=50%>
###### ステップ５：設定の保存を行う
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/aa26e51f-4483-7f2c-6651-706eed5978b6.png" width=50%>

作業としては以上です。
これで知らない間に料金が多額に発生していたなんてことはなくなります！
Gitの場面別使い方

# 概要
[先ページ](https://qiita.com/sepakTama/items/a568c0998a0864bfa8be)では自分がよく使う（沼らなければ使わないコマンドが多数）コマンドの一覧を紹介した。本ページでは、職場の上司から「これやっといて！」って言われた時にできずに沼ってしまったシーンを再現し、どのように振る舞うべきかを（自戒の念を込めて）書いていく。


# 自分がミスした状況
1. ローカル上でmasterからブランチを切って作業をしていたが、リモートリポジトリのmasterブランチが更新され、そこから枝を生やすように言われた時。
1. 気づいたら変なところからブランチを切っていて、元に戻そうにもようわからなくなってしまった時。

## 1つ目の事象について

状況をもう少し細かく説明すると、複数人で同時に開発していたが、他者が開発していた部分がクリティカルパスとなっており、masterブランチが自身の生やした部分ではなく、新しいバージョンから生やしてほしいと言われた。具体的には以下のようにするべきである。

![git_scene_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207583/fa51fe02-614d-5bb1-296b-7fc07889008b.png)


ブランチの生やす場所を変えるコマンドは`git rebase`を用いる。（`git rebase`に関して知りたい方はこのページを参照したい）
方針としては以下の通りである。

1. developブランチにチェックアウトする
1. rebaseを行う
    1. このとき、コンフリクトが起こる（可能性がある）ためコンフリクトを一つずつ解消していく
1. rebaseができたら、リモートリポジトリにプッシュする

以上が大まかな流れである。それを表したコマンドが以下のようになる。

```terminal
> git checkout develop
> git rebase master
> git rebase --continue
> git branch
> git add .
> git commit -m "comment"
> git push -f origin master 
```
となる。`git branch`を行なった理由として、筆者は現在いるブランチが予定通りのところにいるか心配で確認したくなるからである。（念には念を押している）上記コマンドが分からなかった人は、ぜひ[このブログ](https://qiita.com/sepakTama/items/a568c0998a0864bfa8be)を見て確認してほしい。

https://qiita.com/sepakTama/items/a568c0998a0864bfa8be

## 2つ目の事象について
自身でも何が起こったかよくわからない状況だったが、タスクごとにブランチを切って作業をしており、何回かのコミットの後で切った元のブランチ（下図だとmaster）にマージをしようとしたがなぜかうまくいかなかった。（再現不可能のため説明能力はかなり低い。。。）求められていたことは、自身が行ったタスクが今後のクリティカルパスになり得るため、「developブランチをmasterにマージ」もしくは「developブランチで回収した情報をmasterブランチにも反映させる」ことであった。
問題点として、何故かdevelopブランチからマージを試みた時に（恐らくコンフリ等が起こり変な操作を自分がしたことによる、もしくは別のブランチから間違えてdevelopブランチを生やした可能性もある）ブランチがグチャグチャになってしまったことで、元に戻すのが厄介になってしまったことである。

![git_scene_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207583/b3c8de6d-d1ea-889b-d53e-94b4fa8e7ec2.png)

非常に簡潔に書いたが、前提としてdevelopブランチのログがグチャグチャになっていたことである。このタイミングで私はgitの強者に`cherry-pick`という技を学んだ。行いたい流れは以下の通りである。

1. developブランチにチェックアウト
1. logを確認し、masterブランチに反映させたい部分のハッシュ値をメモする
1. resetを行い、developブランチを切るタイミングまで遡る
1. cherry-pickを用い、メモしたハッシュ値を用いてdevelopブランチで改修していた部分を反映させる

`cherry-pick`の本来の使い方とは異なるかもしれないが、非常に便利だということを学んだ。上の流れを踏まえたコマンドが以下の通りである。

```terminal
> git checkout develop
> git log --oneline
# メモするのはAのハッシュ値(a_hashとする)とZのハッシュ値(z_hashとする)
> git reset --hard a_hash
> git checkout master
> git cherry-pick a_hash..z_hash
```

`git checkout master`を行なった理由として`git reset --hard a_hash`を行った時にその時点でいるブランチがどうなっているか不安だからである。上記コマンドが分からなかった人は、ぜひ[このブログ](https://qiita.com/sepakTama/items/a568c0998a0864bfa8be)を見て確認してほしい。

https://qiita.com/sepakTama/items/a568c0998a0864bfa8be

# 終わりに
一通りgitに関することを書いてきたが、今回触れたのはコマンドのほんの一例で自分が用いていないコマンド（GUIに頼ってしまっていたりする）があるため、そこの部分についてはまた別の機会に学習してまとめていこうと思う。
gitの初歩的なところからこのブログまでは実務において自身が役に立った部分にとどめており、少しでも多くの人がgitで苦しまないようになってほしいという思い（＋自分の備忘録として）から書いている。役に立つことを望んでいる。
【MLOps】docker/mlflowを使った競馬AI開発環境構築（2021年版）~VScode編~

今回は、コーディングやpythonコードの実行を行うためのvscodeをインストールしていきます。

VScodeを選んだ理由は、

- 仕事でもよく使う
- pythonコードを簡単に実行できる
- ipynbもvscode上で実行できる

ためです。以前はjupyter notebookを使っていたんですが、ブラウザだと使いにくいところがあったり、コード補完機能を使うための設定がめんどくさかったりしたので、やっぱりvscodeに戻ってきました。

### VScode構築手順
1. ローカル環境にVScodeをインストールする
2. 拡張機能をインストールする

#### 1. ローカル環境にVScodeをインストールする

公式サイトからインストーラをダウンロードして、ローカルで実行してください。基本的にデフォルト設定で問題ないです。

https://code.visualstudio.com/

#### 2. 拡張機能をインストールする

今回は下記の拡張機能をインストールしています。`VS Marketplace Link` をクリックすると、インストールページに飛ぶことができます。

##### Jypyter (ms-toolsai.jupyter)

```
Name: Jupyter
Id: ms-toolsai.jupyter
Description: Jupyter notebook support, interactive programming and computing that supports Intellisense, debugging and more.
Version: 2021.9.1101343141
Publisher: Microsoft
```

VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter


##### GitLens(eamodio.gitlens)

```
Name: GitLens — Git supercharged
Id: eamodio.gitlens
Description: Supercharge the Git capabilities built into Visual Studio Code — Visualize code authorship at a glance via Git blame annotations and code lens, seamlessly navigate and explore Git repositories, gain valuable insights via powerful comparison commands, and so much more
Version: 11.6.1
Publisher: GitKraken
```

VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens


### まとめ

今回は、私がおすすめするVScodeのインストール手順を説明しました。
画面タップを検知　復習

#今回の内容

* 画面がタップされた時に処理をさせようと思い書こうとしたら、すぐに思い出せなかった為復習です。

#コードと簡単解説

 * `UITapGestureRecognizer(target: self, action: #selector(メソッド名))`でタップ時の処理を作成します。
 
 * `.addGestureRecognizer()`でタップした時に処理が働くようになります。


```Swift:例
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    
    var tapCount = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let tapDetection = UITapGestureRecognizer(target: self, action: #selector(screenTap))
        view.addGestureRecognizer(tapDetection)
    }

    @objc func screenTap(){
        
        tapCount += 1
        label.text = "\(String(tapCount))回、画面をタップしました。"
    }

}
```
# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
開発環境と本番環境に対応したkintone customize uploaderを作ってみた

Cybozuがkintoneアプリのカスタマイズ開発者向けに提供しているcustomize-uploaderを簡単に使えるようにしたスクリプトを作成しました。
普段、kintoneアプリのカスタマイズ開発をする中で、開発環境のアプリと本番環境アプリの2つを用意して、通常業務に影響が出ないようにカスタマイズ開発を進めています。このような使い方でkintoneアプリを使っている方はほとんどいないと思いますが、普段の業務で必要があったのでスクリプトを作りました。
カスマイズファイルをgitで管理して、開発環境で動作確認をしながら本番環境に反映させることを想定しています。

Githubのソースコードはこちらから
[kintone-customize-uploader](https://github.com/masashihamaguchi/kintone-customize-uploader)


customize-uploaderについての詳しい情報はこちらから
[customize-uploaderでカスタマイズ用のJS/CSSファイルをコマンドラインからアップロードしよう！](https://developer.cybozu.io/hc/ja/articles/360015889812-customize-uploader%E3%81%A7%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA%E7%94%A8%E3%81%AEJS-CSS%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%8B%E3%82%89%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%97%E3%82%88%E3%81%86-)

## 使い方

基本的な使い方はcustomize-uploaderと同じです。

1. プロジェクトを任意の場所にcloneもしくはダウンロードして展開します。

2. `dest`ディレクトリ直下にある`customize-manifest-dev.json`に開発環境のアプリIDを、`customize-manifest-prd.json`に本番環境のアプリIDを入力します。

```json:customize-manifest-dev.json
{
  "app": "{アプリID}",
  "scope": "ALL",
  ...
}
```
　
3. customize-uploaderと同様に、kintoneアプリにアップロードするJavaScriptとCSSファイルを開発環境と本番環境の両方のマニフェストに追記します。
　　
4. 以下のコマンドを使うことで開発環境と本番環境へのアップロードを簡単に行うことができます。

## コマンド
`npm run`の後に以下のスクリプト名を入れて実行すると、customize-uploaderの各スクリプトを実行できます。

|scripts|実行内容|
|:--:|:--|
|`install`|customize-uploaderをインストールします。|
|`init`|マニフェストファイルを作成します。|
|`import-dev`|開発環境のアプリのカスタマイズ情報を取得します。|
|`import-prd`|本番環境のアプリのカスタマイズ情報を取得します。|
|`dev`|作成したカスタマイズファイルを開発環境のアプリにアップロードします。|
|`prd`|作成したカスタマイズファイルを本番環境のアプリにアップロードします。|
|`dev-watch`|ファイルの更新を監視して、開発環境のアプリに都度アップロードします。|
|`prd-watch`|ファイルの更新を監視して、本番環境のアプリに都度アップロードします。|

例えば、開発環境のアプリにカスタマイズファイルをアップロードする場合は、

```
$ npm run dev
```

と入力します。

※`import-dev`, `import-prd`コマンドはcustomize-uploaderの仕様上、新しいマニフェストファイルが生成されてしまいます。

　
　
短時間で作成したので間違いなどありましたらご指摘ください！