OmniAICreator/Qiita-1.07M huggingface dataset:
Macでパスワードつきzipファイルを開く方法

<h2>実行環境</h2>

Mac OS Catalina 10.15.2

<h2>困ったこと</h2>

パスワードつきのzipファイルをFinderから普通に開こうとしたら、ひらけなかった。

<img width="704" alt="スクリーンショット 2020-01-24 22.18.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253272/d71dfcd0-09fb-8871-d651-0ecff6b86f61.png">

<h2>解決した方法</h2>

```
$ ditto -V -x -k --sequesterRsrc --password --rsrc xxx.zip ./
```

Terminalで上記のコマンドを打ち込むと、パスワード入力を求められるので入力すると、現在のディレクトリにzipファイルを解凍したフォルダを展開してくれます。

※ 「xxx.zip」は、zipファイル名（zipファイルへのパス）を指定。

dittoは、Mac OS X 10.0（Cheetah）以降で、ファイルのコピーやアーカイブの作成・展開をするときに使えるコマンドらしいです。

<h2>参考になった記事</h2>

<a href="https://macwiki.osdn.jp/wiki/index.php/OSX%E3%81%AE%E5%9B%BA%E6%9C%89%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89#ditto_.E2.80.A6_.E3.83.95.E3.82.A1.E3.82.A4.E3.83.AB.E3.81.AE.E3.82.B3.E3.83.94.E3.83.BC.E3.82.84.E3.82.A2.E3.83.BC.E3.82.AB.E3.82.A4.E3.83.96.E3.81.AE.E4.BD.9C.E6.88.90.E3.83.BB.E5.B1.95.E9.96.8B">OSXの固有コマンド - ditto … ファイルのコピーやアーカイブの作成・展開</a>

<a href="https://www.real-world-systems.com/docs/ditto.1.html">Mac OS X ditto copy directory hierarchies, create and extract archives</a>
Google SREの説明の勘所

https://cloud.google.com/blog/ja/products/gcp/how-to-start-and-assess-your-sre-journey

<img width="589" alt="スクリーンショット 2020-01-24 22.26.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39852/7dfee48c-984d-beb0-cfc6-8d37f65124d7.png">

本稿の中心的な問いに答えるということは、チームの影響力と健全性、そして何よりも大切なことですが、実際の仕事のしかたを評価するということです。結局のところ、最初の SRE 本で書いたように、自動化できないプロセスやソリューションを作っているなら、システムを維持するために人員を確保し続けなければなりません。人間がいなければ仕事がまわらないのであれば、人間の血と汗と涙をマシンに注ぎ込んでください。


人間の血と汗と涙をマシンに注ぎ込んでください。


もっと儲けさせてください、Googleを、ということ。
rails sとは　localhostとは

Railsでアプリケーションをローカルで起動する際に
ターミナルでrails s実行し
ブラウザでlocalhost:3000を入力すると表示されると思います。

これって何をしてるのと疑問に思ったので書いてみました。


##rails sについて
まず、railsのアプリを起動する為にはアプリケーションサーバを起動する必要があります。
それを担っているのが、rails sです。
rails sを実行するとpumaと呼ばれるアプリケーションサーバが起動します。

下の　=>Booting Pumaです。

```
$rails s
=> Booting Puma
=> Rails 5.0.7.2 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.0 (ruby 2.3.1-p112), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

つまりrails sでアプリケーションサーバを起動しています。
##localhost:3000について

localhost:3000とは自身のPCを指すドメインの事です。

つまり自身のPCをアプリケーションサーバにみたてて(rails sで)ブラウザでlocalhost:3000というドメインにアクセスさせる事で自身の書いたアプリケーションが表示されているという事です！
【MySQL】エラー：Warning: A partial dump from...

# Warning: A partial dump from ...
mysqldumpしようとすると発生。

```shell
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 
```

エラーメッセージをちゃんとみていなかったのですが、 `--set-gtid-purged=OFF`をオプションにつけて再度mysqldumpコマンドを叩けばOK.

---

https://saba.omnioo.com/note/50/mysql%E3%82%A8%E3%83%A9%E3%83%BC%E9%9B%86/

こちらの記事を参考。
Q17.数式を入力するには？

今回はVBAで数式を入力する方法を考えていきます。

以下のようなエクセルを用意しました。
![Q17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560479/64ee66b1-7015-0d13-4542-c453c624312d.png)


合計と平均の列が未記入の状態となっています。
合計と平均については、通常、セルの値を変数に格納してそれぞれ計算してやれば、
求めること自体は簡単にできます。

ただ、数式を入力するともっと簡単に実装することができますので、
今回は数式を入力する方法について考えていきます。



###■ポイント
数式を入力するのは単純です。
そのままRange("A1").value = "=SUM(A2:A3)"といった具体に=を含めた数式を、
valueプロパティにそのまま代入するだけです。

回答を見るとものすごく単純なのが分かります。



###■回答
```VB
Sub Q17_Answer()
    Range("F3:G16").Value = Array("=SUM(C3:E3)", "=AVERAGE(C3:E3)")
End Sub
```

###■解説
今回、合計と平均の未記入の箇所すべてを対象に数式を入力しています。
Array関数は複数の値を入力するときに使います。
これは、F列には第一引数である=SUM(C3:E3)を、G列には第2引数である
=AVERAGE(C3:E3)を代入することを意味しています。

複数の行に渡りセルを指定したとしても、相対参照により、
行が１つずれるにつれて入力する数式の中の列もひとつずれます。

これにより、たった1行で簡単に実装することができました。


マクロを実行した結果は以下のとおりです。
![Q17-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560479/1e386578-da0f-6b22-d689-4e9ebccbc079.png)
初心者の初心者による初心者のためのAndroidアプリ開発

# はじめに

こんにちは。
現在、高専の4年生をしており、最近Androidアプリ開発について勉強しています。きっかけとしては単純なもので、自身の研究内容にAndroidアプリの開発の知識が必要だったというだけです。プログラミング自体に興味を持ってからの日々が浅いので、正直見るもの見るもの新鮮です。

この記事を見られているということは、タイトルにも書かれているようにAndroidアプリ開発の初心者、もしくは、これから学んでいくという方がほとんどだと思います。そのため、『これからAndroidアプリ開発について学んでいきたいと思ったけどプログラミング全然知らないけど大丈夫かな？』って方をメインに、つまずきやすいと感じた部分を初心者なりに精一杯わかりやすく解説して学んでいけたらと思っています。

#イベントとイベントハンドラ、リスナ

今回はイベントとイベントハンドラとリスナについて解説していきます。正直、イベントとリスナはまだしも、イベントハンドラなんていう単語聞いたことないと思います。もちろん私も聞いたことなかったです。意味自体は非常に簡単で一度聞いてしまえば難しく考える必要なものではないです。

イベントとは、ボタンのタップ、アイコンをドラッグなど使用者が画面に対して何かの操作を実行することです。いわゆるスマートフォンの基本操作です。そのイベントに対して実行する処理のことをイベントハンドラと呼びます。こちらは、画面の遷移やアプリケーションの起動などといった動作のことです。そして、このイベントの検出を行っているものをリスナと呼びます。
この考え方自体はAndroidに限らず、iOSやデスクトップアプリなどといった使用者の操作に応じて特定の処理を実行するアプリケーションでの共通の考え方でもあります。

#Androidでリスナを設定する手順

ここでは実際に簡易的なアプリケーションの作成をしていきます。あらかじめ下記のコードを記述しておくことをお勧めします。このとき、『override』にコンパイルエラーが発生していても問題ありません。

res/value/strings.xml
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552605/f71a8f03-3494-6a34-6454-1205a0cef5f0.png)

res/layout/activity_main.xml
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552605/d9f07d52-13ff-9599-0047-2d977b2f333c.png)

java/com.websarva.wings.android.ibennto/MainActivity.kt
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552605/a2665312-17e7-3164-e14d-663f83ebd790.png)



1.各イベントに対応したリスなクラスを作成する
2.リスナクラス内の所定のメソッド（つまりイベントハンドラ）に処理を記述する
3.リスナクラスのインスタンスを生産してリスナ設定メソッドを引数（媒介）として渡す

**リスナクラスの作成する**

MainActivityのonCreate()メソッド以降に次のコードを記述します。ここでは、privateインナークラスにListenerクラスを追記することで、『ボタンのタップ』という操作に対してリスナクラスへ移ります。

java/com.websarva.wings.android.ibennto/MainActivity.kt
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552605/61590cd9-1924-00a8-3e11-a1632345a447.png)

リスナクラスには専用のインターフェースを実装します。タップという操作に対してのリスナクラスを作成するには『View.OnClickListener』インターフェースを実装します。インターフェースを実装した時点でそのインターフェースに定義されているメソッドを記述する必要があります。今回のコードのView.OnClickListenerインターフェースではonClick()メソッドのことです。つまり、これがイベントハンドラです。

**リスナクラス内の所定のイベントハンドラに処理を記述する**

次に、イベントハンドラであるonClick()メソッドに処理を記述していきます。EditTextから入力された文字を取得し、TextViewに表示させる動作です。

java/com.websarva.wings.android.ibennto/MainActivity.kt
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552605/ba405ad2-8adb-f516-60df-3de382d96e11.png)


**リスナクラスのインスタンスを生産してリスナ設定メソッドを引数として渡す**

最後にリスナを設定します。onCreate()メソッド内に以下のコードを挿入します。

java/com.websarva.wings.android.ibennto/MainActivity.kt
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552605/8e4780cb-16ad-4d70-42ea-6c653bca0a2c.png)


**完成です！**


#最後に

今回作成したものは単純なアプリケーションですが、今後の必要となる要素が詰まっているので繰り返し学習していきたいですね。

本記事は、『基礎＆応用力をしっかり育成！ Androidアプリ開発の教科書 Kotlin対応 なんちゃって開発者にならないための実践ハンズオン』を参考にしております。
Pipenvを用いた仮想環境上でDjangoを起動する

#はじめに
Pipenvを用いた仮想環境上でDjangoを起動させます。

Pipenvを用いた仮想環境上にDjangoを配置することでDockerやチーム開発でのビルドが常に同じ結果となり、開発がスムーズになります。複数人やDockerを用いた開発でのベストプラクティスと考えています。

本記事は[DjangoアプリをDocker上に構築しAWS Fargateにデプロイする](https://qiita.com/keita_gawahara/items/66e58a6eed5c0c5f31d2)プロジェクトの一部です。

#pipenvのインストール

pipを用いてpipenvをインストールします。

```
$ pip install pipenv
```

#仮想環境上にDjangoをインストールする
pipenvをインストール後、デスクトップでhelloディレクトリを作成、helloディレクトリに移動します。

```
$ cd ~/Desktop
$ mkdir hello && cd hello
```

Pipenvコマンドを使用して仮想環境上にDjangoをインストールします。

```
$ pipenv install django==2.2.3
```
実行後、PipfileとPipfile.lockファイルが作成されます。
Pipfileにはインストールするライブラリ名とバージョンが記録されます。
Pipfile.lockには実際にインストールされたライブラリの情報が記録されます。

```
$ ls
Pipfile		Pipfile.lock
```
仮想環境に入り、startprojectコマンドを実行し新しいDjangoプロジェクトを作成します。ピリオドを忘れずに。


```
$ pipenv shell
(hello)$ django-admin startproject hello_project .
```

マイグレートを実施してデータベースの初期化を実行し、Django開発用サーバーを起動します。


```
(hello)$ python manage.py migrate
(hello)$ python manage.py runserver
```

http://127.0.0.1:8000/ にブラウザでアクセスするとDjangoのwelcomeページが表示されています。これにより仮想環境上でDjangoを立ち上がっていることが確認できました。

<img width="1194" alt="スクリーンショット 2020-01-24 21.30.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560888/7aa6e34f-8008-d950-2853-093212093fd2.png">
Android 10で、端末からIMEIなどのSIM情報を取得する方法

# はじめに

Android 10から、端末からIMEIなどのSIM情報を取得するためには、「READ_PRIVILEGED_PHONE_STATE」という権限をAndroidManifest.xmlに追加する必要が出てきました。

>Android 10 以降で IMEI とシリアル番号の両方を含む再設定不可能なデバイス ID にアクセスするには、アプリに READ_PRIVILEGED_PHONE_STATE 特権が必要です。
注意: Google Play ストアからインストールされたサードパーティ製アプリでは特権を宣言できません。
[Privacy changes in Android 10  |  Android デベロッパー  |  Android Developers](https://developer.android.com/about/versions/10/privacy/changes?hl=ja#non-resettable-device-ids)より引用

追加するにあたって、以下のように```tools:ignore="ProtectedPermissions"```を追加することで、Android Studioから警告されることなく追加できます。(```tools:ignore="ProtectedPermissions"```を追加しなくても一応ビルドはできます)

```xml:AndroidManifest.xml
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
        tools:ignore="ProtectedPermissions" />
```

しかし、サードパーティ製アプリ(Google Playに公開されているアプリ)では宣言していても、特権を利用することはできません。該当メソッド呼び出し時にSecurityExceptionがスローされます。
上記の宣言に加えて、主に以下の対応が必要になります。

1. プリインアプリ化する
2. 「READ_PRIVILEGED_PHONE_STATE」をホワイトリストに追加する

# プリインアプリ化する

「READ_PRIVILEGED_PHONE_STATE」を有効にするには、まずアプリをプリインアプリ化する必要があります。
プリインアプリとは、主に```/system/app```や```/system/priv-app```配下にあるアプリのことです。出荷時にあらかじめインストールされているアプリのことですね。
その中でも、```/system/priv-app```配下にある、「システム権限を必要とする特権アプリ」である必要があります。

# 「READ_PRIVILEGED_PHONE_STATE」をホワイトリストに追加する

「READ_PRIVILEGED_PHONE_STATE」をAndroidManifest.xmlに追加し、プリインアプリ化したのち、さらに以下のような感じで権限をホワイトリストに追加する必要があります。

```xml:/etc/permissions/privapp-permissions-OEM_NAME.xml
<permissions>
  <privapp-permissions package="アプリのパッケージ名">
    <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
  </privapp-permissions>
</permissions>
```

この辺りはおそらく手動で追加するものではなく、端末によっても格納先が異なると思われるので、あくまで参考程度にしてください。当然ながら、追加するには端末をroot化しないとできません。

# 注意

- プリインアプリがショートカットアプリ(起動するとGoogle Playのアプリページに飛ばすだけのもの)の場合、ショートカットアプリに対しても「READ_PRIVILEGED_PHONE_STATE」を宣言しないと無効になってしまうので注意！
- プリインアプリ更新時、APKファイルの格納先が移動されるようですが、どうやら仕様のようです。
- アプリ更新時にAndroidManifestがまるまる上書きされるものかと思っていたのですが、まるまる上書きはされず、以前に宣言した内容は残るらしいです。AndroidManifestの仕組みについて勉強しておかないとまずいと実感しました。
- [複数のマニフェスト ファイルをマージする  |  Android デベロッパー  |  Android Developers](https://developer.android.com/studio/build/manifest-merge?hl=ja)の内容を理解すると良いのかもしれないと感じました。（まだちゃんと読めてませんが）

# コマンドメモ

この対応を行うにあたって使用したコマンドを下記にまとめます。

## 対象のアプリ(APKファイル)が端末内のどこにあるのかを調べる

```
adb shell pm list packages -f | grep -i "アプリのパッケージ名"
```

## プリインアプリの上書き(root権限必須)

```
adb root
adb remount
adb push "APKファイルのパス" /system/app/
adb shell chmod 644 /system/app/"APKファイル名"
adb reboot
```

## 端末のシャットダウン(再起動を繰り返すようになってしまった場合に使用) 

```
adb shell reboot -p
```

## ホワイトリストを端末内にプッシュ

```
adb push "ホワイトリストのパス" /etc/permissions/
```

# 参考URL

- [/system/app と /system/priv-app の違い | 穀風](https://kokufu.blogspot.com/2017/04/systemapp-systempriv-app.html)
- [Privileged Permission Whitelisting  |  Android Open Source Project](https://source.android.com/devices/tech/config/perms-whitelist)
- [Unique Identifier in Android Q - Stack Overflow](https://stackoverflow.com/questions/56730796/unique-identifier-in-android-q)
- [android - adb install system app - Stack Overflow](https://stackoverflow.com/questions/43526134/adb-install-system-app)
【AWS/Lambda】lambdaに固定IPをつける/VPCに所属させる

「困ったら大体lambda（とS3）」「lambda イズ 仙道」、AWSの基本ですね（）
ただ彼は基本的に固定IPを持ちません。仙道同様、気まぐれです。
今回はそんな彼に**固定IPを付与する方法**をまとめます。
また、結果として**VPC＆サブネットへ所属させる方法**にもなります。
# どんな時に役立つか
例えば

- 申請式で特定IPからのアクセスしか認められないサービスとの連携
- インスタンス内で動くIP制限付きサイトの死活監視
- プライベートサブネット内のインスタンスと通信

※インスタンスそのものの監視はcloudwatchでどうぞ
# 構成図
以下の形です。
![lambdaから外へ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488789/4b7a4f6f-eaf0-a254-287c-d4c18e82e4a6.png)
# 手順
手順的には大まかに以下の形です。
1. lambdaをVPC内のプライベートサブネットに設置
2. lambdaのロールにvpc、eniに関する権限を追加
3. パブリックサブネットにNATゲートウェイを設置
4. プライベートサブネットのルートテーブルを編集

順番に見ていきましょう。
VPC内に**プライベートサブネット（インターネットゲートウェイを持たない）、パブリックサブネットが一つずつある**前提です。

## 1. lambdaをVPC内のプライベートサブネットに設置
lambda関数の作成時、デフォルトでは非VPCとなっています。
普段はこれで問題ないですが、今回は既存のVPC、**プライベートサブネット**、セキュリティグループを設定して下さい。
<img width="557" alt="lambda_ネットワーク設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488789/3deb0900-d39b-a4e3-a18e-631738fea3f4.png">

ちなみにパブリックサブネットに設置するとVPC内はいけますが、外に出られません。
[公式より](https://aws.amazon.com/jp/premiumsupport/knowledge-center/internet-access-lambda-function/)

## 2. lambdaのロールにvpc、eniに関する権限を追加
lambda関数作成時に指定したロールにVPCアクセス、eni作成、削除の権限が必要になります。
「IAM -> ロール」より当該ロールを選択し、**AWSLambdaVPCAccessExecutionRole、AWSLambdaENIManagementAccess**をアタッチしてください。
<img width="932" alt="IAM_ポリシーアタッチ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488789/65a3f5fc-cfd4-907e-c9fb-745f5f2910fc.png">
## 3. パブリックサブネットにNATゲートウェイを設置
「VPC -> NATゲートウェイ」よりNATゲートウェイを作成します。
サブネットに**パブリックサブネット**を指定する点に注意してください。
<img width="881" alt="NATゲートウェイの作成.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488789/86cac2fb-b1e6-7269-7bf7-4c1bd66ae4df.png">
## 4. プライベートサブネットのルートテーブルを編集
最後の手順です。
「VPC -> ルートテーブル」より**プライベートサブネット**に紐づくルートテーブルを選択し、ルートテーブルの編集より、以下のように**送信先に0.0.0.0/0**、**ターゲットに3.で作成したNATゲートウェイ**を指定したルートを追加してください。
<img width="1247" alt="ルートの編集.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488789/a2b13ad2-e5b0-33cd-c199-ae71923efa4c.png">
これにより、lambda関数から外に出る際に、パブリックサブネット内のNATゲートウェイを経由する形となります。

ちなみにサブネットを作成した直後は、サブネットのルートテーブルにVPCのものが紐づいているので、間違ってそちらを編集しないように気をつけてください。
# おしまい
あとはlambda関数内で外部アクセスするコードを記述、検証してOKなら問題なしです。

なにか抜けや間違いなどありましたらご指摘いただけると幸いです。
Javaのequalsは結構気持ち悪い

#導入
こんにちは、けちょんです。
**Java書いてますか？**
そんな私はここ数か月コーディングしてません。
焦ってJava goldの勉強を始めました（今日から）
その際気持ち悪かったことがあったので紹介します。

#なにが気持ち悪かったか
皆さん、文字列を比較する際、どう比較しますか？

##素人プログラマの場合
```
String str1 = "test";
String str2 = "test";
if (str1 == str2) {
	System.out.print("same");
} else {
	System.out.print("diff");
}
```
はい、だめですね。
こんなコード書いたら怒られます。はい、私です。
演算子である"=="はオブジェクトのメモリアドレスを比較します。

異なるオブジェクトは基本的に異なるメモリアドレスを保持します。
今回比較したいのはオブジェクトの持つ文字列であるため、意図に反しています。

**が、この場合は"same"が出力されます。**
String自体が気持ち悪いため、注意が必要です。
本題ではないし、詳しく知らないため省略します。

##一般プログラマの場合
```
String str1 = "1";
String str2 = "1";
if (str1.equals(str2)) {
	System.out.print("same");
} else {
	System.out.print("diff");
}
```
普通ですね。よく見ます。
でも、皆さんObject.equalsの中身みたことありますか？

中身は、、、

```
public boolean equals(Object obj) {
    return (this == obj);
}
```

**"=="を使っとるやーーーん**

"=="を使っていて怒られた私は大激怒です。

#まとめ
文字列の比較はeqaulsも"=="も一緒？？？？




#いやいや
**もちろんそんなことはありません。**

equalsメソッドは、Stringクラスがオーバーライドしています。
以下がString.equalsの中身です。

```
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String aString = (String)anObject;
        if (coder() == aString.coder()) {
            return isLatin1() ? StringLatin1.equals(value, aString.value)
                              : StringUTF16.equals(value, aString.value);
        }
    }
    return false;
}

```

これも"=="は使っているものの、メモリアドレスが異なる場合は別の比較を行っていますね。

#まとめ
Object.equalsはただの"=="での比較
String.equalsは"=="で比較するものの、比較対象が文字列だった場合は特殊な動きをする(こちらの期待する動き)
[Blue Prism] ライセンスが足りないときどうなるか / ランタイムリソースが足りないときどうなるか

やりたかったこと
------------------------

Blue Prism はサーバー型のRPAで、「本番環境で同時に実行するロボット数（セッション数）」でライセンスされるという価格体系になっています。
そのため、うまくスケジューリングされていないと「あるプロセスの実行を試みた際に、別のプロセスが実行中で、ライセンスが不足してしまう」という事態が起こり得ます。

この記事では、実際にライセンス数が不足した場合、どのような挙動をするのか確かめてみます。

一定時間実行が続くプロセスを作成する
---------------------------------------------------------------

検証した環境では、5セッションの同時実行がライセンスされていたので、4セッション同時実行される環境を用意します。

まず、5分間など一定時間実行されるシナリオを用意します。
赤枠部分に、実行モードを「排他的」に設定したオブジェクトを入れて、このプロセス自体の実行モードが「排他的」になるようにしています。

<img width="509" alt="long_runnning_process.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/5f99f70e-e081-eaab-7720-bdea71528146.jpeg">




ランタイムリソースのプールを作成する
---------------------------------------------------------------
[こちら](https://qiita.com/muuuuuwa/items/8fdd65eb0e0b71263644#public-%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81%E3%81%A7%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%9F%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B) を参考に、ポート番号（8182~8186）を変えてランタイムリソースを5台立ち上げます。（本来なら異なるマシン上で、同一のポートで立ち上げるところですが、今回は一つのマシン上で検証します）

<img width="426" alt="AA_runtime_resources.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/a4f1913a-cb39-1dc3-fea4-f265d253cf9f.jpeg">


そうして立ち上げたランタイムリソースをプールとしてまとめます。（「システム」タブの、「リソース > プール」から設定します）

<img width="507" alt="AA_pool.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/8e9828b7-5667-f1f6-2301-5b9654857094.jpeg">


ライセンスが不足する状況を試す
---------------------------------------------------------------

スケジューラを設定し、6セッション同時に実行するようにします。
（※ タスク1つに、複数のセッションを設定しても良いのかもしれません）

<img width="508" alt="AA_schedules.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/2c5be708-89ab-db20-9dd6-2f5e09c0a6c7.jpeg">


その結果、6セッション目を実行するタイミングで、エラーが発生します。

<img width="883" alt="AA_error_msg.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/fa1807a5-8562-824e-f0b3-e3f4f128893f.jpeg">


終了理由に表示されるエラーメッセージは下記の通りです。

> タスク : 00- セッションの作成はリソース 'myPool' で失敗しました : myPoolにセッションを作成できませんでした - 現在使用中のライセンスでは許可されていないため、要求された操作は実行できません。現在のライセンスで許可されている同時セッションの最大数を超えます。

おまけ：ランタイムリソースが不足する状況を試す
---------------------------------------------------------------
適切にプールなどを設定していないと、「実行時のライセンスは足りているが、ランタイムリソースが足りない」という状況も起こりえます。

プールに登録していたランタイムリソースの合計が4つになるように調整して、再度6プロセスが順次実行されるようにスケジューリングします。
その結果は下記のようになります。

<img width="818" alt="AA_schedule_log_viewer.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/9b127a54-b250-77cf-892b-cfdbc5e20028.jpeg">

終了理由に表示されるエラーメッセージは下記の通りです。

> タスク : 00 - セッションの作成はリソース 'myPool' で失敗しました : myPoolは他のタスクを実行中のためこのプロセスを実行できません。
リレーショナルデータベースの備忘

随時追加してきます。
自分がやってしまった失敗。巻き込まれてしまったこと。
うちの新人に教えるために残しています。

#最悪なシステム
##全テーブル、サロゲートキーで主キーが隠れてしまっている。。。。
###困ったこと
主キーはリレーショナルデータベースの胆だと思っており、非常に不安を覚えました。
トランザクション系であれば、理解ができるのですがマスタも全てサロゲートキー
ユーザーコードの隣の列に「id」という列がある状況。
データ重複等不正なデータの取り扱いはどうするつもりなんだろう。。。   
担当者に聞いても、DBが連番で自動的に割り振る列をサロゲートキーだと思っている節がありました。

###そもそもサロゲートキーとは
ナチュラルキーが多数の組み合わせないと主キーにならない時、プログラムから
主キーで操作しやすくするために定義する。

###どうしてほしかったのか
- マスタ系のテーブルにはサロゲートキーは原則つけない
- 個人的には3つ以上の複合キーを必要とする時はサロゲートキーを検討する。
- 複合キー２つはプログラム側で頑張る
- サロゲートキーとするなら「主キーA」と「主キーB」を文字列結合したものにしてほしい。
- トランザクション系のサロゲートキーは「登録日時（ミリ秒）+ 登録ユーザーID + 主キーの中でも重要なキー」がおすすめ

###注意点
- 容量を喰ってしまう認識はしておかないといけない
- テーブルの情報量が減ってしまう。
- テーブル定義書等にナチュラルキーを絶対書く
Atcoder Beginner Contest152のきろく（python）

## 1

正答数と問題数が一致した時ACとする

```
N , M = map(int,input().split())
if N == M:
    print("Yes")
else:
    print("No")
```

## 2
辞書順で先に来るとは数が小さいことと同義である。
その為、smallの値をlargeの回数繰り返せば良い

```
a, b = map(int,input().split())
ans = str(min(a, b)) * max(a, b)
print(ans)
```

## 3

chokudaiさんも解けてほしいと言っていた問題。
問題文が複雑であるが、問題文をあるiが任意のすべてのjのうち最小であるという問題に帰着できる。
その為、左から値を保持し、常に最小であるか判定すれば$O(N)$で解ける。

```
N = int(input())
P = list(map(int, input().split()))
now = P[0]
ans = 1
for i in range(1, N):
    if now >= P[i]:
        now = P[i]
        ans += 1
print(ans)
```

## 4

条件に適した二組の整数が何個あるかの問題。

制約より、$O(N)$で解けることがわかる。また、１〜２０くらいまで書き出すと明確な法則がないように思える。

この問題のポイントは値を1〜9までしか使わない為、9*9の二次元配列を作る。それをforでカウントし、2数の組合せが答えとなる。


```
from pprint import pprint
N = int(input())
digit_cnt = list([0] * 9 for _ in range(9))
now = 1
for i in range(1, N + 1):
    str_i = str(i)
    row = int(str_i[0])
    column = int(str_i[-1])
    if row != 0 and column != 0:
        digit_cnt[row - 1][column - 1] += 1
# pprint(digit_cnt)
 
ans = 0
for i in range(9):
    for j in range(9):
        ans += digit_cnt[i][j] * digit_cnt[j][i]
print(ans)
```
[Perl] Smart::Commentsで安全にデバッグする

今までずっと `Data::Dumper` を使ってデバッグしてました

```test.pl
use Data::Dumper;

my $hoge = rand 10;
warn Dumper $hoge;
```

```
$ perl test.pl 
$VAR1 = '2.82097955540852';
```

調べてみたところ、Dumperした結果を同じく表示してくれるデバッグ用のモジュールで `Smart::Comments` というものがあるみたいです

#### 導入

```
$ cpanm Smart::Comments
```

#### 使ってみる
先程のものを、 Smart::Comments で書き換えてみます
デバッグしたいものの先頭に、コメントアウトを3つ付与します

```test.pl
use Smart::Comments;

my $hoge = rand 10;
### $hoge;
```

```
$ perl test.pl
### $hoge: '5.59813882530765'
```

表示されました！先頭にコメントマークが3つついてますね

実行時だけモジュールを読み込ませてあげるようにする事もできます

```test.pl
my $hoge = rand 10;
### $hoge;
```

```
$ perl -MSmart::Comments test.pl

### $hoge: '6.25320952226506'
```

こうすることで、完全にソースコードを汚さずに実行できるのがいいですね
もしデバッグを消し忘れたりタイポしても、ただのコメントアウトとしてperlは処理してくれるのでエラーになりません

```perl
my $hoge = rand 10;

# Data::Dumperlの場合、タイポしたらエラーになる
warn Dumper $hogee;

# Smart::Commentsの場合、コメントなのでタイポしててもエラーにならない
### $hogee;
```

心理的に楽かも？
Railsの思想

## はじめに
「パーフェクト Ruby on Rails」に Rails の特徴、強く打ち出している思想について始めのほうに記載されていたので「パーフェクト Ruby on Rails」を振り返り、メリットを知りたいと思いましたのでまとめます。


## CoC(Convention over Configuration)
直訳では「設定より規約」になります。有名です。
従来のアプリケーションフレームワークには規約がなく、開発者が自由に設定ができますが、Railsはファイル名の規約やテーブル定義の規約など様々な規約があります。

### パーフェクト Ruby on Railsの例（そのままではないです）
- 社員情報を表現するモデルをEmployeeモデルとした場合、Railsで規約には則って開発することが求められる
 - データベースのテーブル名はモデル名の複数形のEmployeesにする
 - /employeesというURLは社員の一覧を表す
 - /employees/1というURLは社員ID:1の社員情報を表す

### ✔️メリット
- 規約に則って記述することで、設定のファイルを書く必要がない
- プロジェクトごとに設定の差異を生んでしまうことがない
- 共通のルールなので、他のエンジニアとコミュニケーションが取りやすい
- 開発者が決定すべきことが減る


## DRY(Don’t Repeat Yourself)
「繰り返してはいけない」「同じことは繰り返さない」と訳されます。
同じソースコードを統一し短くコードを書く事を推奨する思想があります。
情報の重複をなくし、１つのことは１箇所に記述します。

### ✔️メリット
- DRY原則を守ることにより、コードを変更する際に何箇所も変更する必要がなくなる


## REST(REpresentational State Transfer)
Webのアプリケーション設計思想のひとつです。
RESTfulという言葉をよく目にしますが、RESTという設計思想に則ったアーキテクチャのことをいいます。

### パーフェクト Ruby on Railsの例（そのままではないです）
- /employees/1というURIが指す内容が「リソース」とすると
 - /employees/1にHTTPのGETメソッドでアクセスすることで、社員情報を取得する処理を行える
 - /employees/1にHTTPのDELETEメソッドでアクセスすることで、社員情報を削除する処理を行える

### ✔️メリット
- アプリケーション中のリソースがURIによって参照できる
- 機能追加がしやすい自然な設計になる
- CRUD操作と、4つの基本的なHTTPrequestメソッド(GET,POST,PUT,DELETE)の両方に対応している

## おしまい
　「パーフェクト Ruby on Rails」を進められ最近読み始めました。話題がたくさんで読み応えがあると聞いたので、読み進めて知識を増やしたいですね〜！頑張ります。
ちょっとだけ[Rails tutorial](https://railstutorial.jp/)も参考にいたしました。
CSS,SCSSで画像を背景にする方法

SCSSで作成

.クラス名 {
background: url(/フォルダ名/ファイル名) no-repeat top / 横px 縦px;
height: 要素の高さ;
wight: 要素の幅;
}


backgroundで背景にする

urlで画像を指定する

no-repeatで画像が何枚も投稿されるのを防ぐ
（これがないと勝手に何枚も表示される）

topで上に詰める？

画像の縦横を指定してあげる


間違いがあれば指摘をお願いします。
Djangoで区分値を定義し、簡単に画面へ反映する

# Djangoで区分値を管理する
## 要件
`model.py`で区分値を定義し、履歴のリストを表示するhtmlページへ反映します。


## 1. モデルに定義する
`History`テーブルに`STATUS`という区分値を持たせます。
ポイント：`choices=`

```python:manage.py
class History(models.Model):
    STATUS = (
        ('001', '実施前'),  # BEFORE_EXECUTE
        ('011', 'ログイン中'),  # DURING_LOGIN
        ('012', '取得中'),  # WHILE_GETTING
        ('101', '完了'),  # DONE
        ('401', '失敗')  # fail
    )
    
    start_at = models.DateTimeField()
    status = models.CharField(max_length=3, choices=STATUS)
```
## 2. URLを定義する
履歴のリストを表示するページへのURLを定義。

```python:url.py
urlpatterns = [
    # リスト
    path('history_list', views.HistoryListView.as_view(), name='history_list'),
]
```

## 3. ListViewに定義する
履歴のリストを表示するページのhtmlへ渡すViewを定義。

```
class HistoryListView(ListView):
    model = History
    template_name = 'history_list.html'
```

## 4. Htmlへ反映させる
ポイント：`get_FIELD_diaplay `

```html:example.html
<td>
    {{ history.get_status_display }}
</td>
```
Python3 で Cloud Firestore のデータを削除 (Delete)

こちらで作成したデータのひとつを削除します。
[Python3 で Cloud Firestore のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/4288176394947283c84a)

```py:firestore_delete.py
#! /usr/bin/python
#
import sys
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
key_in = sys.argv[1]
#
print(key_in)
#
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {
  'projectId': 'my-project-2020-01-22',
})

db = firestore.client()
#
db.collection('cities').document(key_in).delete()
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行コマンド

```bash
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_delete.py t0924
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.8.6
```
Poetryでライブラリがインストールできない時の解決方法


## 起こるエラー

poetryを使っていると、よく遭遇する

```sh 
$ poetry config virtualenvs.in-project true 
$ poetry new project-name
$ poetry add lib-name
```

みたいにしたときに、以下みたいなエラーが出た時の解決方法

```
[SolverProblemError]
The current project's Python requirement (>=2.7,<2.8) is not compatible with some of the required packages Python requirement:
  - environs requires Python >=3.5

Because environs (7.1.0) requires Python >=3.5
 and no versions of environs match >7.1.0,<8.0.0, environs is forbidden.
So, because ops depends on environs (^7.1.0), version solving failed.
```

## 解決方法

```sh 
poetry env use python-version
```

で解決しましょう。例えば、Python3.7を使いたい場合は、

```sh 
poetry env use python3.7
```

と打てば、環境を再構築してくれるので次回以降エラーが出なくなるはずです。
Python3 で Cloud Firestore のデータを更新 (Update)

こちらで作成したデータを更新します。
[Python3 で Cloud Firestore のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/4288176394947283c84a)

```py:firestore_update.py
#! /usr/bin/python
#
import sys
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
key_in = sys.argv[1]
population_in = int(sys.argv[2])
#
print("%s\t%d" % (key_in, population_in))
#
project = 'project-aaa'
#
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {
  'projectId': project,
})

db = firestore.client()
#
city_ref = db.collection('cities').document(key_in)
city_ref.update({'population': population_in})
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行コマンド

```bash
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_update.py t0922 98456200
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.8.6
```
Python3 で Cloud Firestore のデータを読む (Read)

こちらで作成したデータを読みます。
[Python3 で Cloud Firestore のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/4288176394947283c84a)

```py:firestore_read.py
#! /usr/bin/python
#
import sys
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

# ------------------------------------------------------------------
def data_read_proc(doc):
	results = doc.to_dict()
	str_out = doc.id + '\t'
	str_out += results['name'] + '\t' + str(results['population'])
	str_out += '\t' + str(results['date_mod'])
	print(str_out)
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {
  'projectId': 'my-project-2020-01-22',
})

db = firestore.client()
#
users_ref = db.collection('cities')
docs = users_ref.stream()
#
for doc in docs:
	data_read_proc(doc)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行コマンド

```bash
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_read.py
```

実行結果

```text
*** 開始 ***
t0921	宇都宮	38921	2020-12-16 04:36:37.271232+00:00
t0922	小山	56417	2020-12-16 04:36:37.953997+00:00
t0923	佐野	92385	2020-12-16 04:36:38.075886+00:00
t0924	足利	39546	2020-12-16 04:36:38.180650+00:00
t0925	日光	18492	2020-12-16 04:36:38.300083+00:00
*** 終了 ***
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.9.7
```
Python3 で Cloud Firestore のデータを作成 (Create)

ライブラリーのインストール

```bash
sudo pip install --upgrade firebase-admin
```

```py:firestore_create.py
#! /usr/bin/python
#
import sys
import datetime
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore


# ------------------------------------------------------------------
def add_data_proc(db,key,name,population):
	sys.stderr.write("key = " + key + "\n")
	doc_ref = db.collection('cities').document(key)
	doc_ref.set({
		'name': name,
		'population': population,
		'date_mod': datetime.datetime.utcnow()
	})
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
try:
	cred = credentials.ApplicationDefault()
	firebase_admin.initialize_app(cred, {
		'projectId': 'my-project-2020-01-22',
		})

	db = firestore.client()
#
	add_data_proc(db,'t0921','宇都宮', 38921)
	add_data_proc(db,'t0922','小山', 56417)
	add_data_proc(db,'t0923','佐野', 92385)
	add_data_proc(db,'t0924','足利', 39546)
	add_data_proc(db,'t0925','日光', 18492)
#

except Exception as ee:
	sys.stderr.write("*** error *** in firestore.Client ***\n")
	sys.stderr.write(str(ee) + "\n")
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行コマンド

```bash
export GOOGLE_APPLICATION_CREDENTIALS="***.json"
./firestore_create.py
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.8.6
```

プロジェクトがないと次のようなエラーが出ます。


```text
*** error *** in firestore.Client ***
404 The project project-jan25-2020 does not exist or it does not contain an active Cloud Datastore or Cloud Firestore database.
 Please visit http://console.cloud.google.com to create a project or https://console.cloud.google.com/datastore/setup?project=project-jan25-2020 to add a Cloud Datastore or Cloud Firestore database.
 Note that Cloud Datastore or Cloud Firestore always have an associated App Engine app and this app must not be disabled.
```

次のようなエラーが出たら API を有効にする必要があります。

```text
*** error *** in firestore.Client ***
400 The Cloud Firestore API is not available for Datastore Mode projects.
```

次のようなエラーが出たら、CREDENTIALS の json ファイルを作り直します。

```text
*** error *** in firestore.Client ***
403 Missing or insufficient permissions.
```

実行がうまく行くと、次のようなデータが作成されます。

![firestore_dec16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/3f8caf8c-d2b7-8cc6-977e-5e2ed77d8497.png)

CREDENTIALS の json ファイルは、次の方法でも作成できます。

```bash
gcloud beta auth application-default login
```
初心者によるプログラミング学習ログ 219日目

#100日チャレンジの219日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

219日目は
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>219日目<br>・Vue.jsでアプリ作成講座<br>・javascript<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1220438203947274240?ref_src=twsrc%5Etfw">January 23, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
AWSアカウント作り直してみた

## はじめに
- これからawsの勉強をする予定です。
- ２年前くらいに、[railsチュートリアル](https://railstutorial.jp/chapters/beginning?version=5.1)をしました。その際に、一度AWSのアカウントを登録したのですが、途中で挫折して、ずっと放置されてたままになっていました....
- 今回、AWSアカウントを作り直そうか迷っていましたが、作り直すと``無料枠がリセットされる``ことが判明したので、作り直そうと思います！！（メールアドレスは変える必要があるみたいです）
    - [解約したAWSアカウントを再開したら無料利用枠がリセットされた件](https://hrhs37.hatenablog.com/entry/aws_free_tier_reset)

## 目次
 1. awsのアカウントを削除
 2. awsのアカウントを再登録
 3. 初期設定

## 1.awsのアカウントを削除
### rootアカウントでログイン
1. サインインの画面でrootアカウントに紐づくメールアドレスを入力します。

<img width="1439" alt="スクリーンショット 2020-01-24 19.34.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572604/73e11e09-a903-b040-7034-cdf33f091483.png">

2.　パスワードと多要素認証が求めれるので、それぞれ入力します。
3.　AWSマネジメントコンソール画面に入ることができます。

### アカウント解約へ
1. マネジメントコンソール画面から自分のアカウント管理画面へ
![qiita_aws_delete_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572604/744cf826-01d4-7100-28c1-de6b4dd9c844.png)

2. そのページをスクロールし、最下部へ
![qiita_aws_delete_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572604/69eb87e7-e6bd-a7f7-48b6-8d81ecd11788.png)
3. クリックすると、
![qiita_aws_delete_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572604/63e41229-91a7-31b9-18db-6d3d6be84a6f.png)
これでアカウントの解約ができました!!
解約手続き完了メールが登録したメールアドレスに届いているはずです。

## 2.awsアカウントの再登録
[ここから](https://aws.amazon.com/jp/register-flow/)基本情報を入力し、再度アカウントを作り直しました。
<img width="1436" alt="qiita_aws_regist.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572604/a478d150-3f09-27d7-0b83-d3bfdbacce39.png">
できました！！

## 3.初期設定
- 以下の記事を参考に初期設定を行いました。
    - [AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ](https://qiita.com/tmknom/items/303db2d1d928db720888)
- <img width="771" alt="qiita_aws_setting.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572604/d24239cd-c209-7886-81fc-0a8439ff5ee4.png">
 
多少記事のUIと異なることはありましたが、特に詰まることなく、**15分くらい**で設定することができました！！

## まとめ・感想
- 初めて作った時は、１時間くらいかかった気がしますが、特に迷うことなく作り直すことができました。調べてみると分かりやすい記事たくさんありますね。今後も勉強しやすそうです。
- やっと勉強する準備が整ったので、次回からは無料枠を使って何かしたいと思っています。アカウント作り直すことで``無料枠がリセットされる``の本当にありがたいです...
- そういえば、就活用にWordPressで作ったポートフォリオをサクラサーバに放置してあったはずなので、この機会にAWSに移行しようかなと思います。
インフラエンジニア、自由人として現状aws cloud9が最強だと思う理由

# メリット
- どのパソコンを使っても初期設定はいらない
- 回線の問題は4Gになってほぼ払しょくされた
- テザリングやwifiがあればどこでもPCはスペックに左右されずに作業ができる
- aws IAMで認証できて認証がセキュア
- 指定時間後に操作がない場合、インスタンスの自動シャットダウンができる（費用の圧縮になる）
- PCを買い替える頻度によってはトータルコストもそんなに高くない

# デメリット
- PCを５年とか買い替えない方はトータルコストが割高
- 回線速度と電波の問題には少なからず意識しないといけない
- IDEとしての機能は不十分（検索機能が遅いなどInteliJ利用者から見すると少し不便かも）
Wifi　GとAの違い

|       |          G        |          A         |
|:-----------------|------------------:|:------------------:|
| 周波数帯          |            2.4GHz |                5GHz|
| 距離          　　|            　○　 　|       　　　✖️    　　|
| 速度            |             　　 ✖️ 　|        ○    |
| 安定              |             　✖️ 　|         ○        |
| 電波の干渉しやすさ             |          ○ 　|       ✖️       |

とてもざっくりですが参考までに
【Kotlin】KClassからstatic関数/companion objectに定義した関数を取得する

# TL;DR
- `Java`の`static`関数は`KClass.staticFunctions`で取得できる
- `companion object`内の関数は`KClass.companionObject?.functions`で取得できる
- ただし、`@JvmStatic`の有無に関わらず、`Kotlin`のクラスで定義したメソッドは`KClass.staticFunctions`で取得できない

# やること
表題の通り、`KClass`から`static`関数/`companion object`に定義した関数を取得します。

## 環境
- `JDK1.8`
- `Kotlin 1.3.61`

# やり方
## static関数の取得
以下の方法で`static`関数の一覧が取得できます。

```java:取得対象クラス
class Hoge {
    public static void hoge();
}
```

```kotlin:取得方法
val hogeStaticMethods: Collection<KFunction<*>> = Hoge::class.staticFunctions
```

## companion objectに定義した関数の取得
以下の方法で取得できます。
取得対象クラスの`companion object`には名前がついてますが、名前の有無に関係なく動きます。

```kotlin:取得対象クラス
class HogeClass(val fuga: String) {
    companion object hoge {
        fun getInstance(): HogeClass = HogeClass("fuga")
    }
}
```

```kotlin:所得方法
val hogeCompanionFunctions: Collection<KFunction<*>> = HogeClass::class.companionObject?.functions
```

### 補足1. この方法で取れるもの
この方法で取得した場合、`object`由来で以下の3つのメソッドも同時に取得されてしまいます。

- `equals`
- `hashCode`
- `toString`

### 補足2. staticFunctionsは使えないのか
「先ほど同様`staticFunctions`で取得できないのか」と思いましたが、自分が試した限りでは取れませんでした。

まず、`@JvmStatic`無しの純粋な`Kotlin`では取れませんでした。
この状態でデコンパイルしても`static`関数は出てこないので、これは予想の範疇でした。

次に`@JvmStatic`を付与した状態でやってみましたが、これまた取れませんでした。
デコンパイル結果を見ると`static`関数としては定義されていましたが、それでも取れないようです。

```kotlin:取得対象クラスでメソッドに@JvmStaticを付与した例
class HogeClass(val fuga: String) {
    companion object hoge {
        @JvmStatic
        fun getInstance(): HogeClass = HogeClass("fuga")
    }
}
```
ifの入れ子をできるだけ少なくするための工夫


JSで処理を書いているとif文の中にifを書くこともあると思います。
ただ、if文を入れ子にすると可読性が下がり、読みにくい・わかりにくいコードになっていくと思います。今回入れ子が発生し、それを解消するために行った工夫を記載します。

##状況

かなりカンタンな例を作成しました。

１．名前と数値を設定
２．名前がメンバーと名付けた変数たちに含まれるか確認（大分類）
３．含まれる場合は数値が0か+(プラス) か -(マイナス) かで条件分岐（小分類）

コードで書くとこんな感じ

```javascript:test.js
const name = 'yamada';
const num = 100;

//メンバー
const member1 = 'sato';
const member2 = 'yamada';
const menber3 = 'suzuki';

//大分類：設定した名前がメンバー変数にあるか確認
if(name === member1 || name === member2 || name === member3){
    //大分類：設定した名前がメンバー変数にある場合
    //小分類：設定数値が 0 か +(プラス) か -(マイナス) か
    if(num === 0){
        //0の場合
    } else if (num > 0) {
        //+(プラス)の場合
    } else {
        //-(マイナス)の場合
    }
}
```
ifが入れ子になってます。

##解消後
※コメントでご指摘を頂き、内容を修正しました。必要に応じてブラッシュアップして行けたらと思います。

####修正点
・一度評価した式を再度評価することは避ける。（効率性）
・入れ子で分けていた大分類・小分類の分岐はわかりやすいままにする　

解消後のコード

```php:test.js
const name = 'yamada';
const num = 100;

//メンバー
const member1 = 'sato';
const member2 = 'yamada';
const menber3 = 'suzuki';

//メンバーを配列化
const list = [member1, member2, member3];

if(!list.includes(name)) {
    //大分類：設定した名前がメンバー変数にない場合
} else if (num === 0) {
    //小分類：設定数値が 0 の場合
} else if (num > 0) {
    //小分類：設定数値が +(プラス) の場合
} else {
    //小分類：設定数値が -(マイナス) の場合の場合
}
```

##まとめ
少しずつコードが書けるようになってくると、やりたいことは実現できるが、余計な動作も記載してしまっている、可読性が悪い、コードが長すぎて時間がかかる、などまだまだプログラミングは奥が深く、課題は山積みだと実感します。。！！
少しずつ綺麗で可読性が高くわかりやすいコードが書けるように勉強していきたいとおもいます。
【Python】beautifulsoup4の備忘録

## はじめに
``beautifulsoup4``による、htmlタグ検索の備忘録。

## 環境
- python: 3.7
- beautifulsoup4: 4.8.2

## 基本の検索
```py
# pタグ全部
find_all("p")

# 一番初めに見つかったpタグのみ
find("p")

# aタグかつhrefがhogehogeから始まるもの
import re
find_all("a", href=re.compile("^hogehoge"))
```

## cssセレクタ使った検索
```py
# 親子関係を指定、ゆるく
select('body div p')

# 親子関係その2、きびしく
select('body > div > p')

# クラス名
select('.myclass')

# id名
select('#myid')

# AND条件
select('.myclass1.myclass2')
```

## n番目のタグ
```py
# 下記のhtmlの3番目の<li>タグを検索する
# <html>
# <body>
#   <ul>
#     <li>指定されない</li>
#     <li>指定されない</li>
#     <li>指定される</li>
#     <li>指定されない</li>
#   </ul>
# </body>
# </html>

select('body > ul > li:nth-of-type(3)')

```

## nth-of-type()が効かないときなどの対処法
効かなかった原因は、スクレイピング元サイトのhtmlに、開始タグはあるが閉じタグがないものが存在していたこと。
解決策としては、その開始タグを削除すること。
（ちなみに、Chromeの開発者ツール上では閉じタグは存在していたため、ページのソースを表示してみるまで気づかなかった…）

```py
url = "http://hogehoge/"
soup = BeautifulSoup(url.text, "lxml")

# ddタグの閉じタグがないので、ddタグを除去
for tag in soup.find_all('dd'):
  tag.unwrap()
```

全ての``<dd>``タグを除去する。
ただし、``.decompose()``を使うと、``<dd>``より後ろにある要素も消えてしまうので、``.unwrap()``でタグのみを削除。

## 参考文献
- https://www.sukerou.com/2019/01/python3-beautifulsoup4web.html
Git　初期設定

1. Macには元々Gitがインストールされている。
2. ターミナルを開いて『git --version』を打ち込んで確認
3. xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun　と表示される
4. 『xcode-select --install』を入力し、Xcodeをインストール
5. 『git --version』を再び入力
6. gitのバージョンが表示される

macOSをアップデートするとこのようなエラーになるみたいです
Jest実行時にserverless.ymlの環境変数を読み込む

[jest-environment-serverless](https://github.com/fireeye/jest-environment-serverless) を利用して`serverless.yml`から環境変数を読み込みます。
（`.env`を読み込む以外の方法を試してみたかった）

## 手順

### パッケージのインストール

必要なパッケージをインストールします。

```.bash
$ npm install serverless jest jest-environment-serverless
```

### プロジェクトの作成

```.bash
$ npx serverless create --template aws-nodejs
```

### 設定

`serverless.yml`に読み込む環境変数の名称と値を記述します。

```serverless.yml
service: sample

provider:
  name: aws
  runtime: nodejs12.x

functions:
  hello:
    handler: handler.hello
    environment:

      # これを読み込みます
      SAMPLE_VALUE: Sample
```

`package.json`にjestの設定を追加します。

```package.json
{
  :
  "jest": {
    "testEnvironment": "jest-environment-serverless",
  }
}
```

### テストの作成

環境変数を console.log で出力する処理を記述します。

```__test__/handler.spec.js
describe('Sample', () => {
  it('check env', () => {

    // 表示
    console.log(process.env.SAMPLE_VALUE);

    expect('');
  });
});
```


### テストの実行

```.bash
$ npx jest
 PASS  __test__/handler.spec.js (10.71s)
  Sample
    ✓ check env (67ms)

  console.log __test__/handler.spec.js:5
    Sample

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        16.159s
Ran all test suites.
```

環境変数の値（`Sample`）を読み込むことができました。


### おまけ

環境変数の名称と値をAPIから取得することもできます。

```__test__/handler.spec.js
describe('Sample', () => {
  it('check env', () => {

    // serverless.yml の functions.hello.environment の読み込み
    const envVars = ServerlessWrapper.getEnv('hello');

    // 出力
    console.log(envVars);

    expect('');
  });
});
```



```.bash
$ npx jest
 PASS  __test__/handler.spec.js (8.714s)
  Sample
    ✓ check env (68ms)

  console.log __test__/handler.spec.js:8
    { SAMPLE_VALUE: 'Sample' }

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        13.556s
Ran all test suites.
```

環境変数の名称と値（`{ SAMPLE_VALUE: 'Sample' }`）を出力することができました。
初学者によるプログラミングMemo　#19 正規表現（基本編）

はじめに
今回は正規表現（基本編）のお話です
正規表現を初めに見たときは、"/\d+\/\/"みたいなのを見てなんだこれは、謎の記号の羅列やんと思ったものです
ですが、私もプログラミング学習を進めていくうちに、少しずつわかってくるようになったので、このタイミングで書きたいと思います
なお、本記述はMacにおいて、Railsでの開発を前提としています
また、まだまだひよっこですので、不備等ございましたらご指摘いただけると幸いです

#目次
- 正規表現の各パーツについて
- 正規表現でなんか取ってこよう

##正規表現の各パーツについて
まずは謎の記号の羅列が、各パーツに分解できるところから知りましょう（今回は解説含むので、理解できているものを紹介します）

```.rb
[abc]    #aかbかcのどれか１文字
[^abc]   #a,b,c以外の１文字
[a-z]    #a~zのうちのどれか１文字
[a-zA-Z] #a~zかA~Zのうちのどれか１文字
.        #任意の１文字
\d       #任意の数字
\w       #任意（文字、数字、アンダースコアのうちの）の１文字
(a|b)    #aかbどちらか
a?       #a（"?"の直前の文字）が0回か１回か
a+       #a（"+"の直前の文字）が１回以上
a{3}     #aが3回
\/       #\の使い方、"/"を文字として扱う
```

基本的なところはこんなところでしょうか
これを組み合わせることで正規表現が成り立っています
最初に述べた"\d+"は"\d"と"+"の組み合わせですね
つまるところ、任意の数字が１回以上、ということになります


##正規表現でなんか取ってこよう
以前記事で書いた"scan"メソッドでも使って、文字列の中から任意の文字列を取り出してきましょうか

###URLを取り出してみる
URLを取り出してみましょう
例えばこんな文章があるとします

```
私のQiitaのMYPageはhttps://qiita.com/Ikuy_hです
```
これからURLを取り出したいと思います
ただし、この一文にしかヒットしないのは汎用性が全くないので、汎用性のあるコードにしたいと思います

まず、URLの頭ですが、"http:"か"https:"のどちらかから始まっている（それしか知りません、間違ってたら教えてください）ので、まずはそこにマッチするかを記述してみましょう

```.rb
https?:
```
できました
次に"/"です
前述したように、"/"を文字として考えなくてはいけませんので、こうなります

```.rb
https?:\/\/
```
できました
次は何かしらの文字が来るはずです
その記述を行います
まずは文字が入っているかどうかと、文字が一回以上でるということを考えて記述してみます

```.rb
https?:\/\/[\w]+
```
できました
前述した基本パーツの組み合わせです
[]はどれか[]内のどれか１文字でしたよね
\wは任意（文字、数字、アンダースコアのうちの）の１文字でしたよね
+はそれが１回以上出現するかどうかですね
しかし、これではまだ不十分です
だって…


"."があるじゃないか！！


そうです、\wでは"."は補完されません
あと記号としては"-","?","%","&","=","/"が考えられそうですね
なので…

```.rb
https?:\/\/[\w\.\-?%&=\/]+
```
できました
()を使ったグループ化をする方がもっと綺麗にかけそうですが、まだ使いこなせていないので、今はこれでご勘弁を
ちゃんと理解したら、その時また記事書きます

さあ、では実際に、プログラミングしてみましょう

```.rb
hp = "私のQiitaのMYPageはhttps://qiita.com/Ikuy_hです"

p hp.scan(/https?:\/\/[\w\.\-?%&=\/]+/)

# => ["https://qiita.com/Ikuy_h"]
```

取り出せましたね


#さいごに
プログラミングというか、ものづくりあるあると言いますか、出来上がりを無知な状態で見ると「うわぁ…こんなん…」って思いがちですが、一つずつ理解していくとほとんどのケースで分解ができます
分解して考えるとより理解しやすくなりますね
SendGrid Javaライブラリの、メール配信失敗時の実装を確認した話

## 前置き
JavaでWebアプリケーションを作成しています。
システムからメール配信を行うため、[SendGrid](https://sendgrid.kke.co.jp/)を利用しているのですが、なんらかの原因でメール配信が失敗した場合に、想定していた後処理がコケていたので備忘録として記載します。
~~すべては前任者の「エラー時にもResponseで結果を返してくるだろう」という思い込みから発生した実装でした。~~


## SendGridを使用してメール配信処理を作成
build.gradleに[SendGrid Javaライブラリ](https://github.com/sendgrid/sendgrid-java)をプロジェクトにインストールしメール送信メソッドを作成。
SendGridが400番台のエラーを返してくる場合はこちらから送ったリクエストパラメータの不備やリクエスト超過のためリトライは行わず、ログを残してフロント側にエラー情報を返して処理を終了します。
500番台の場合はSendGridサーバにエラーが発生している状態のため、2〜3度リトライを行うように作成していました。
リトライ周りとか省略して（すみません）コードを記載します。

参考：[SendGrid：ステータスコードとエラー](https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/Mail/errors.html)

```
dependencies {
    compile ('com.sendgrid:sendgrid-java:4.0.1')
}
```

```java
import com.sendgrid.*;
import java.io.IOException;

public class Example {
  public static void main(String[] args) throws IOException {
    SendGrid sg = new SendGrid(System.getenv("SENDGRID_API_KEY"));
    try {
      Request request = new Request();
      request.setMethod(Method.GET);
      request.setEndpoint("api_keys");
      Response response = sg.api(request);
      if (response.getStatusCode() < 300) {
            // 200番台は正常送信として処理を続ける
      } else if (response.getStatusCode() < 500){
            // 400番台エラーはリクエストパラメータが不正と判断して処理終了
            // ログを残し、エラーメッセージをフロントへ返却
      } else {
            // 500番台エラーはSendGridのサーバエラーのため何度かリトライ
            // ログは残しておく
      }
    } catch (IOException ex) {
      throw ex;
    }
  }
}
```

## 想定された処理が行われない問題
上記のように返ってきたresponse内のステータスコードを判断してその後の処理を振り分けるように作成していました~~（前任者が）~~。
メール作成時のバリデーションチェック処理に不備があり、メールが送れなかった際に後処理が行われず、想定されたログも残っておらずでこの実装に不備があることが判明します。

## 実装を確認する
com.sendgrid.SendGridクラスのapi()メソッドからたどって実際にどこでSendGridにリクエスト送信を行っているかを確認します。（3〜4ステップでたどり着けるので中略）

```java

private Response executeApiCall(HttpRequestBase httpPost) throws IOException {
	try {
		CloseableHttpResponse serverResponse = httpClient.execute(httpPost);
		try {
			Response response = getResponse(serverResponse);
			if(response.getStatusCode() >= 300) {
				//throwing IOException here to not break API behavior.
				throw new IOException("Request returned status Code "+response.getStatusCode()+"Body:"+response.getBody());
			}
			return response;
		} finally {
			serverResponse.close();
		}
	} catch(ClientProtocolException e) {
		throw new IOException(e.getMessage());
	}
}
```

com.sendgrid.ClientクラスにexecuteApiCall()メソッドがあり、この3行目でexecute()していること、そしてなにより6行目のif文で、IOExceptionがthrowされていることがわかります。
ステータスコードが300より大きいときも、responseにその値を詰めて返してくれていいのよ。。。

## SebdGridの返却値とその後
```
Caused by: java.io.IOException: Request returned status Code 400Body:
{
    "errors": [
        {
            "message": "Invalid replyTo email address",
            "field": "reply_to",
            "help": null
        }
    ]
}
```

SendGridは上記の様にエラーメッセージを返してくれるので、responseではなくcatchしたIOExceptionから後続処理を書くべきでした。
なお、ここ1〜2年SendGridでは大規模障害が発生していなさそうなことと、メールの使用率を鑑みてリトライ処理は消してさくっとエラーメッセージを表示するようにしました（バリデーションチェックは直したので400番台エラーは発生しなくなるはず！）。

## 雑感
思い込みと諸々のテストの不備が重なったかなしい事件でしたが、使用ライブラリの返却値はしっかり確認して使おうねと学んだ出来事でした。

※あくまでJavaライブラリの実装なので、他言語のライブラリではエラー時にもresponseに詰めて返してくれるのかもしれません。
tdコマンドが "Error: There was a problem accessing the ..." となったのでバージョンアップして対策した手順

TreasureDateを利用していて、定期的にtdコマンドでCSVファイルをインポートするバッチが急に以下のエラーでこけるようになったので対策をしました。(TDの方に聞いて親切に教えてもらいました、感謝！)


> Error: There was a problem accessing the remote XML resource 'http://central.maven.org/maven2/com/treasuredata/td-import/maven-metadata.xml' (TreasureData::Command::UpdateError: An error occurred when fetching from 'http://central.maven.org/maven2/com/treasuredata/td-import/maven-metadata.xml'.)

具体的には以下のコマンドでTDコマンドをアップデートしました。OSはAmazonLinux2です。

```bash
$ curl -L https://toolbelt.treasuredata.com/sh/install-amazon2-td-agent3.sh | sh
=> td-agentなどが最新化されます

$ td-agent-gem list | grep td
=> 現バージョン確認(ちなみに v0.16.4 でした)
$ td-agent-gem update td
=> アップグレード
$ td-agent-gem list | grep td
=> 再確認
$ td --version
=> アクティブバージョンが v0.16.8であることを確認（※v0.16.8が本件対応済みのバージョン）
```

## 詳細

実際に運用していたのは以下のようなコマンドです。

```shell
td import:auto --format csv --auto-create hogehoge.fugafuga --parallel 4 --prepare-parallel 8 --columns hoge,piyo --column-types string,int -o /tmp --time-column hoge --time-format %Y-%m-%d %H:%M:%S /usr/local/sbin/treasureData/csv/hoge.csv
```

該当エラーで検索すると以下にたどりつきます。
[TDドキュメント - Legacy Bulk Import Tips and Tricks](https://support.treasuredata.com/hc/en-us/articles/360001502527-Legacy-Bulk-Import-Tips-and-Tricks)

ドキュメントを読むと回避方法は二つあるそうです。私たちは1のバージョンアップを選択しました。いい機会だったので。

1. TDコマンドのバージョンをアップする
2. 環境変数をセットする `export TD_TOOLBELT_JARUPDATE_ROOT=https://repo1.maven.org`


アップデート手順も公式にあります。
[TDドキュメント - Installing and Updating the Treasure Data TD Toolbelt for CLI Use](https://support.treasuredata.com/hc/en-us/articles/360001525887-Installing-and-Updating-the-Treasure-Data-CLI)

ただ、私の環境では以下のcurl実行だけでは足りなくて

```bash
# Amazon Linux 2
$ curl -L https://toolbelt.treasuredata.com/sh/install-amazon2-td-agent3.sh | sh
```

以下のtd-agent-gemコマンドも必要でした。

```bash
$ td-agent-gem update td
```

## エラーの原因
TDの方に確認したところ、"td importを実行した際に自動的にjar updateが走るのですが、既存のリポジトリのURLが廃止になったため発生したエラー" とのことでした。なるほどですね。

同僚がtdコマンドの該当の変更箇所も探し出していたのでこちらもご参考まで。
https://github.com/treasure-data/td/commit/00f0a341f0b78f387baaf83cbb30406836b6ada0

それでは良いTDライフをエンジョイ！
Pythonを使ってインストルメントとボーカルを分けてカラオケ音源をつくりたい

# Pythonを使ってボーカルとインストルメントを分けてカラオケ音源をつくりたい

私はPython未経験ですが、 Pythonのツールを使って簡単にインストルメントとボーカルを分けることができたので共有します。

## まずはPythonをインストール
下記記事を参考にPythonをインストール

```Terminal
$ brew install pyenv
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l
```
プロジェクトはPython3を使ってるのでanaconda3をインストール

```Terminal
$ pyenv install anaconda3-2019.10
$ pyenv global anaconda3-2019.10
```

https://qiita.com/aical/items/2d066801a7464a676994

## spleeterをインストール

今回使用するツールはspleeter
https://github.com/deezer/spleeter
参考動画
https://www.youtube.com/watch?v=HqanOjPBRAQ

```Terminal
$ git clone https://github.com/Deezer/spleeter
$ conda install -c conda-forge spleeter
```
これで準備は終わりました。

## インストルメントとボーカルを分けてみる

プロジェクトファイルのspleeterフォルダの中に分けたい音源を入れときます。

```Terminal
$ spleeter separate -i spleeter/（分けたい音源のファイル名）.mp3 -p spleeter:2stems -o output
```
このコマンドを打って処理が完了するとspleetrと同じディレクトリにoutputフォルダが生成されます。その中にインストルメントとボーカルのファイルが入っていれば成功です。

## まとめ
男性ボーカルは少し分けにくかったです。女性ボーカルのほうがきれいに抜けていました。友人いわくこのソフトでインストルメントとボーカルを分ける前に作曲ソフトの方でイコライザーを使って低音を削ってあげると抜きやすいらしいです。