OmniAICreator/Qiita-1.07M huggingface dataset:
Androidアプリ開発の第一歩　Android実機での起動

今日はいよいよAndroidの実機にアプリを入れてみようと思います。
関連記事は最後に掲載していますので、こちらもご参照ください。

# 開発環境
- OS：Windows 10 Home 64bit（バージョン1903）
- 開発ソフト：Android Studio 14.0
- 開発言語：Kotlin
- テストするスマホ：Pixel 3a（Android 10）

# まずはAPK（Androidアプリのインストール用ファイル）を作成
1．下図のように[Buiild APK(s)]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/fda7ebeb-769c-d084-3606-ac56602b8674.png)

2．少し時間がかかりますが、無事successfullyと表示されました。このEvent Logにある[Locate]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/1358abd1-ef08-53be-a344-1b5a92f9b3ab.png)

3．無事APKファイルが作成されていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/d98411b3-f32b-ca5f-0979-33e96e3c859e.png)

# Androidの実機でアプリ起動！
あとはこのAPKファイルをAndroidの実機で開くだけです。どうやってこのファイルをAndroidの実機に送るかですが、私は**Google Drive**に置きました。
（始めGmailに添付して送ろうとしたのですが、セキュリティ上ブロックされてしまいました。。）

1．スマホの方で**Drive**のアプリを立ち上げ、アップロードした場所に移動します。
ファイルをタップすると、危険なアプリじゃない！？と疑われますので、[設定]をタップします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/02fe2a05-aa8a-c978-2aed-a9929a4cd6d7.png" width=40%>

2．チェックをONにして、左上の「←」をタップします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/fc6e4994-a568-6a55-9b0c-acca5c150d1a.png" width=40%>

3．[インストール]！！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/810b712e-15ad-695a-30e7-6683af6b691a.png" width=40%>

4．危険なアプリじゃない！？と疑われますが、[インストールする]
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/f355bf8a-8280-2e04-28dd-b813e803b04c.png" width=40%>

5．危険なアプリじゃない！？と疑われますが、[送信しない]
![Screenshot_20200716-213835.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/60359505-d0f6-3b7e-843e-eca71d35e4da.png" width=40%>

6．インストール完了しました！[開く]をタップすると・・・
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/b2e2c31a-c35f-f81c-c337-82ce28e2ffcd.png" width=40%>

7．無事起動できました:clap:
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/c070cc74-95ef-ae1f-edac-628be0fc24f7.png" width=40%>

8. ホーム画面に戻ると、ちゃんとアイコン出てますね。

# ちなみに：アイコンの変え方

公式サイトに記載されていますので、参照ください。
https://developer.android.com/studio/write/image-asset-studio?hl=ja


# 今までの感想　Android最高！
Androidはアプリ導入のハードルがめちゃめちゃ低いです。
開発ツールも準備されてますし、何といってもどこぞのスマホのように、ストアからしかインストールできない、ということがありません。
今回のように署名なしだとしつこく警告は出されますが、それでもちゃんと動くアプリが作れるのは良いなぁと思いました。
まぁWindowsもPowerShellやマクロを簡単に自作できるので、やはりあのスマホのせいでハードル高いってイメージを植え付けられてるだけなのかもしれないですね。

# 関連記事

- [Android Studioのインストール](https://qiita.com/yasu006/items/dee6c7b5a8da4d96d2ee)
- [超簡易アプリの修正＆テスト（エミュレータ実行）](https://qiita.com/yasu006/items/6f5d8194ab78b3081e3a)
- Android実機での起動（今日はここです）
自分用メモ libyang で node のサイズを知りたい


[libyang: Data Tree のマニュアル](https://netopeer.liberouter.org/doc/libyang/master/group__datatree.html#ga5abf7246d33de62b57e65347fa157530)

`lyd_lyb_data_length()`
で行けそう。

デカいサイズのデータを一回で設定する場合に、
メモリの消費量の目安を知るために利用する。

(7/18 追記)
検証後、結果を追記します。
期待する情報が得られないかもなんで。。
64bit版Raspberry Pi OSにdocker-composeをインストールする

# はじめに

Dockerについて勉強したくて、Raspberry Pi 4を買い、せっかくなので64bit版のRaspberry Pi OSをインストールした。
docker-composeをインストールするときにちょっと引っかかったので簡単に記録する。

2020/07/22追記：64bit版Ubuntu20.04LTSでも同じ症状が出て、同じ方法で解決した。

# 環境

Raspberry Pi4 Model B（RAM4GB）に 、[Raspberry Pi OS (64 bit) beta test version](https://www.raspberrypi.org/forums/viewtopic.php?f=117&t=275370)をEtcherで焼いたmicroSDカードを入れた。

```bash
$ uname -srv
Linux 5.4.42-v8+ #1319 SMP PREEMPT Wed May 20 14:18:56 BST 2020
```

下記の作業前に一通り初期設定を行った。

# 作業

## Dockerのインストール

[Docker公式サイトの手順](https://docs.docker.com/engine/install/debian/)の下の方に書いてあるスクリプトを使ってインストール。

```bash
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
```

## docker-composeのインストール

[Docker公式サイトの手順](https://docs.docker.com/compose/install/)のAlternative Install Optionsに書いてあるpipを使った方法でインストールをするだが、そのままだと`c/_cffi_backend.c:15:10: fatal error: ffi.h: そのようなファイルやディレクトリはありません`などとエラーが出て失敗する。
なので先にlibffi-devをインストールしておく。

```bash
$ sudo apt install libffi-dev
```

libffi-devをインストールした後ならpip3でdocker-composeをインストールできる。

```bash
$ sudo pip3 install docker-compose
```

インストールできていることを確認。

```bash
$ docker-compose version
docker-compose version 1.26.2, build unknown
docker-py version: 4.2.2
CPython version: 3.7.3
OpenSSL version: OpenSSL 1.1.1d  10 Sep 2019
```
Google Driveで共有URLを変えることなくファイルを更新する

#書いた理由
GoogleDriveで共有フォルダを頻繁に使うが、利用者の知識背景や習熟度が異なるためファイルの更新方法が全員バラバラであるため、統一してほしいと考えて書きました。(こっそりと)

#具体的な方法
版の管理を使います。
対象ファイルを右クリックして、｢版の管理｣を開きます。
｢新版をアップロード｣をクリックして更新したいファイルをアップロードします。
<img width="903" alt="図1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596630/9263eefc-1329-4fee-20e4-4e230d0b9190.png">
写真の例では、.cファイルから.pngファイルの物に変更されました。
こうすると、名前は更新前のもの、中身は新しくアップロードしたものとなります。もちろん、過去の版もダウンロードできます。過去の版を３０日以上保存したい場合には、版の管理で旧版のファイルを右クリックして｢この履歴を削除しない｣にチェックを入れましょう。
こうすることによって、共有リンクを更新することなくファイルの中身が更新されます。また、過去の版が必要になったときも用意に取り出せますね。
【AWS】S3 Glacierの種類とは？(備忘録)

# はじめに
現在、AWSSAAについて勉強しております。
その中で「S3 Glacier」の種類について混同しやすい印象があったため、記事としてアウトプットします。

# そもそも「Glacier」って何？

**Glacier**とは、「アーカイブ用途で使用するストレージクラス」です。
**テープバックアップの代替**で使うものになります。

**特徴**

- 保存したデータにアクセスするためには、取り出し手続きが必要
- データ取り出しには、数分～数時間かかる
- 通常アクセスしないデータを保存する用途で利用
- 可用性設計は、99.99%
- 低コスト


# アーカイブの取り出しオプション

| オプション | データ取り出し時間 | 特徴 |
| :--- | :--- | --- |
| 迅速 | 1～5分 | ・最大規模のアーカイブ(250MB以上)は1～5分でのデータ取り出し対象外<br><br>・不定期に発生する、アーカイブのサブセットに対する緊急リクエストの際にデータに迅速にアクセスできる。 |
| 標準 | 3～5時間 | 取り出しオプションのデフォルト設定 |
| 大容量 | 5～12時間 | ・最も安価な取り出しオプション<br><br>・大量のデータ(ペタバイトのデータを含む)を1日以内に低コストで取得可能 |

# Glacier Deep Archiveとは？(番外編)

**Glacier Deep Archive**とは、1年に1~2回しかアクセスされないようなデータを対象にしたストレージクラス。

**特徴**

- 取り出しに12時間かかる
- 1GBあたり月額0.002ドル(東京リージョンの場合)
- Amazon S3 Glacierより安価


# 参考
[アーカイブの取り出しオプション](https://docs.aws.amazon.com/ja_jp/amazonglacier/latest/dev/downloading-an-archive-two-steps.html#api-downloading-an-archive-two-steps-retrieval-options)
[Amazon Glacier](https://ja.wikipedia.org/wiki/Amazon_Glacier)
証明書のエラーでSpringBootプロジェクトが新規作成できない

自分自身で解決できたわけではないですが記録として残しておきます。

# エラーの内容

- 「ファイル->新規->Springスタータープロジェクト」を選択すると、以下のエラーが出てロケーション選択の画面が出てこない。(利用可能なロケーションがありませんというメッセージが出る)

`sun.security.provider.certpath.suncertpathbuilderexception `

- Eclipseマーケットプレースが開けない

# 環境

OS: Windows10

EclipseのVersion: 2019-09R(4.13.0)

# 原因

JREがルート証明書を読み込めないため(？)

会社のプロキシの設定が根本的な原因かも？とのこと。

# 対処法

1. `eclipse.exe`と同じディレクトリ内の`eclipse.ini`を開く

2. JDKが配置されているフォルダ内の、`bin/javaw.exe`のパスをコピー

3. `eclipse.ini`の最初の方に書かれている`jre/bin/server`をコピーしたパスに置き換える(この時に￥は/に置き換える)

4. eclipseを再起動する

# 終わりに

研修の講師の方曰く、長らくEclipseで研修を行ってきたがこのエラーは初めてだそうです。
私が尊敬する先輩(強烈に優秀な方)ですら分からなかったエラーを、先輩の師匠の方がほんの10分で解決してしまいました。。。

同期も先輩方も優秀すぎてこの会社怖すぎる。。。
LineNotify+SpringBootで定期的に通知を送る

#初めに
SpringBootでwebアプリ作成していた際に、特定の情報を定期的に通知したい！！！と考え方法を調べた結果、意外にもあっさり実装できたのでまとめてみました。


# 実行環境

- java  : 11
- Spring Boot : 2.4.0
- Maven : 3.6.3

##①LINE Notify公式ページでアクセストークンを取得
下記URLにアクセスし、表示されているQRコードを読み取りLINE Notifyを友達追加します。

https://notify-bot.line.me/ja/

その後同ページで自身のLINEアカウントでログイン後に「マイページ」→「アクセストークンを発行」と進みます。トークン名（LINEで実際にメッセージが通知される際に、そのメッセージの一番上に表示される）を入力し、任意のトークルームを選択するとトークンが表示されます。

なおトークンが表示されるのは***一回こっきり***なので注意が必要です。
とはいえ発行自体はいくらでも出来るのでその点はご安心を。



##②通知を送るためのクラスを作成
LINEに通知を飛ばすためにDIコンテナに登録するBeanを作成します。
必要となる特別な依存性はありません。


```java:LineNotify.java

@Component
public class LineNotify {
    public void executeNotification() {
         String message = "送りたいメッセージ";
         String token = "取得してきたトークン";
        
	     sendNotification(message,token);
	}

	public void sendNotification(String message, String token) {
		HttpURLConnection connection = null;
		try {
			URL url = new URL("https://notify-api.line.me/api/notify");
			connection = (HttpURLConnection) url.openConnection();
			connection.setDoOutput(true);
			connection.setRequestMethod("POST");
			connection.addRequestProperty("Authorization", "Bearer " + token);
			try (OutputStream outputStream = connection.getOutputStream();
					PrintWriter writer = new PrintWriter(outputStream)) {
				writer.append("message=").append(URLEncoder.encode(message, "UTF-8")).flush();
			}
		} catch (Exception e) {
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
    }
}
```
sendNotificationメソッドの引数に送りたいメッセージとトークンを渡し、指定のURLにPOST通信を走らせてます。LINE Notifyで通知を送るためにはOAuth認証が必須となりますが、メソッド内でリクエストヘッダに `Authorization: Bearer <access_token>` を付与してアクセスすることで、認証が実行されています。

##③通知を定期的に送るための設定
スケジュールされたタスク実行機能を有効にするため
メインクラスに`@EnableScheduling`アノテーションを使用します。

```java:Application.java

@SpringBootApplication
@EnableScheduling //・・・追加
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
```
これにより`@Scheduled`アノテーションが使用されているDIコンテナ内の任意のBeanを検出できます。
ということで先ほど通知機能を実装したクラスに戻り、実際に定期実行したいメソッドにアノテーションを追加します。

```java:LineNotify.java

@Component
public class LineNotify {
    @Scheduled(cron = "0 * * * * *", zone = "Asia/Tokyo") //・・・追加
    public void executeNotification() {
         String message = "送りたいメッセージ";
         String token = "取得してきたトークン";
        
	     sendNotification(message,token);
	}

     ...
```
ここまで出来たら、後はサーバーを起動するだけでタスクが実行され、通知が届くようになります。


`cron`でタスクを実行する周期を、`zone`ではタイムゾーンをそれぞれ指定しています。
`cron`は左から「秒・分・時・月・日・曜日」のトリガーを設定でき、上記のサンプルコードでは毎分0秒にタスクを実行するよう設定されています。例えば毎日9時0分0秒にタスクを実行したいという場合は
「`cron = "0 0 9 * * *"`」といったように設定します。

他にもアプリケーションの起動からn秒後の実行を指定させる`initialDelay`や、メソッド処理の実行完了からn秒後の実行を指定させる`fixedDelay`などのオプションもあるため、比較的自由にカスタマイズすることができます。

#参考
[・5分で実装するJavaからLINE Notifyによる通知](https://yusuke.blog/2020/04/29/2571)
[・Spring Bootでtaskを定期実行する方法](https://qiita.com/rubytomato@github/items/4f0c64eb9a24eaceaa6e)
Same-Site CookiesのエラーをChrome DevToolで検出

#Same-Site Cookiesの設定

Same-Site Cookies設定がNoneだとこのスクリーンショットのようなアイコンとイシュータブが出てきます。

Laravelの場合、Config>>session.phpの最後の行、
'same_site' => "lax",
または
'same_site' => "strict",
と設定しましょう。そうするとこのイシューポップアップは無くなります。
カード決裁やログインなどの外部連携を使う場合に、確認するようにすると良いです。

<img width="1080" alt="スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309843/6edaa9a9-cd50-0ea2-3ba0-8afb9505dd0b.png">

[Chromeバージョン: 84.0.4147.89]
Windows環境でDockerからOracleを起動する

# 始めに
Windows環境でDockerからOralceを起動する記事がネット上にないので、書いてみることにする

# 手順
https://qiita.com/gorilla0513/items/f22e8cce4e08da031abe
に記載されている手順でできる
ただ、上記サイトはMacOSなので、イメージファイルをビルドするのはすんなりできる
Windowsはshを実行する環境はデフォルトで用意されていない
困った

# Gitを導入する
なら、WinodwsでもBashが使えるようにすればいいんじゃね？
ということで、GitをインストールしてGitBashが使えるようにする
というかOracle公式からビルドツールをゲットするにはGitと導入しないといけないから必然的に導入されているわけだが

# 手順の変更点
https://qiita.com/gorilla0513/items/f22e8cce4e08da031abe
から手順を変更しているのはshの実行をGitBash上からやること所だけ
あと、Oracle本体はLinux-x86の64bit版を導入すること
間違っても、Windows用のファイルをダウンロードしないように

# DockerからOralceを起動するメリット
- 軽い、Windowsで余計なサービスが実行されないのでOracleを使っていると思えないくらい軽快に動く
- インストールが簡単、Windows版のインストーラは画面操作が面倒くさいし、何よりSystemユーザのpasswordをDokcerはdocker-composeの環境設定で設定できるので忘れることがない、
- 12c以降ではまりがちなCDBとPDBの設定をdocker-composeに書けるのでスムーズに使うことができる
ゼロから始めるLeetCode Day88「139. Word Break」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day87 「 1512. Number of Good Pairs」](https://qiita.com/KueharX/items/f31bb0b6f4d2b74f3d8f)

[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！

# 問題
[139. Word Break](https://leetcode.com/problems/word-break/)
難易度はMedium。
[コーディング面接対策のために解きたいLeetCode 60問](https://1kohei1.com/leetcode/)からの抜粋です。

問題としては、空ではない文字列`s`と、空ではない単語のリストを含む辞書`wordDict`が与えられた場合、`s`が1つ以上の辞書単語のスペースで区切られたシーケンスに分割できるかどうかを判断する、というものです。


>Example 1:

>Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".

>Example 2:

>Input: s = "applepenapple", wordDict = ["apple", "pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
             Note that you are allowed to reuse a dictionary word.

>Example 3:

>Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
Output: false

# 解法
```python
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        dp = [True]
        for i in range(1,len(s)+1):
            for j in wordDict:
                if i >= len(j) and s[i-len(j):i] == j and dp[i-len(j)] == True:
                    dp.append(True)
                    break
            if len(dp) <= i:
                dp.append(False)
        return dp[-1]
# Runtime: 28 ms, faster than 98.48% of Python3 online submissions for Word Break.
# Memory Usage: 14 MB, less than 36.33% of Python3 online submissions for Word Break.
```

よくあるDPの問題だったので仮に条件を満たせばTrueを返すように書いています。
そこまで激烈に難しい問題というよりはきっちり条件付けができるかどうかが重要な問題だと思いました。

にしてもDPっていざ問題にぶつかるとあれ？どうだったっけ？となりがちなのは僕だけでしょうか？
比較的アルゴリズムというよりは考え方の問題、という感じがします。

割と問題をガッツリ解きたい気持ちはあるのでどこかでそういう企画ができたら良さそうですね。

では今回はここまで。お疲れ様でした。
マイクロサービスアーキテクチャとドメイン駆動開発の比較

## 初めに
とある事からどちらもメンテナンス性に優れるという特徴を持つ、

- マイクロサービスアーキテクチャ
- ドメイン駆動開発

の違いを調べることになったのでメモ感覚でアウトプットしてみます。
私の主観が大いに入っていますので、気になる点がありましたらご指摘ください！

## マイクロサービスアーキテクチャの簡単な説明
__サービスの変化に強い開発手法。__

__メール、DB、ログイン機能、決済機能...とサービス単位でアプリケーションを分けてしまう。__
Dockerのコンテナオーケストレーションを採用するパターンが多い。
__新たな機能追加や改修も影響範囲が極小で済む。__
アプリケーション単位でのスケーリングも可能。__障害に強い。__

### メリット

- 障害に強く、メンテナンスが非常にしやすい
- 機能追加や改修に寛容
- 他の機能を全く気にせず実装できる
- 機能ごとにアプリが違うからこそ、Java、PHP、Node、Ruby等開発者の好きな言語、環境を選択できる
- 開発チーム結成時に全員Java、全員PHP等技術者の縛りがなくなるので人員を集めやすい

### デメリット

- 機能全体としてのテストがしにくい
- APIでアプリケーションを繋ぐので通信の遅延がネック(オーバーヘッド)
- 複数機能を跨ぐ整合性やトランザクションを保つ仕組みがない
- 開発時に多言語で実装したは良いが、保守時に人員・スキル不足に陥りやすい

参考：http://album.cloudit.co.jp/?p=5212

## ドメイン駆動開発
システムで__解決したい業務フロー(=ドメイン)の掘り下げを徹底的__に業務フローの有識者(=ドメインエキスパート)と行い、
業務フローの__システム解決に必要な情報を抽出し(モデリング)__、
__既存の優秀なドメイン駆動開発で採用されているデザインパターンを積極的に採用__して(EntityやRepository等。__戦略的DDD__と呼ぶ)、__モデリングから利益を最大限に得る開発手法。__
###メリット
- ドメインの徹底的な掘り下げによってサービスをモデリングしているのでブレない
- 戦略的DDDで開発コストやメンテナンス性を向上させている

###デメリット
- ドメインの掘り下げに非常に時間がかかる。掘り下げが甘いと機能追加や変更でシステム崩壊。

参考：https://qiita.com/little_hand_s/items/721afcbc555444663247

## マイクロサービスアーキテクチャ の ドメイン駆動開発の目立った差異

###1.準備段階の違い
__ドメイン駆動は課題解決を注視しており、マイクロサービスは変化に強いサービスであることを注視している。__
ドメイン駆動は__ウォーターフォールチックでドメインを抽出することに慎重に時間をかける。__
かっちりドメインが固まってから動き出す。
対して、
__マイクロサービスはアジャイルチックで機能ごとにアプリケーションが違うからこそ、
大元の要件がある程度決まったら直ぐに動き出せるフットワークの軽さがある。__

###2.システム構成の違い
__マイクロサービスは機能ごとにアプリケーションが分かれている。__
対して、
__ドメイン駆動は機能ごとに分けたりせず、基本的に1つのアプリケーションに纏まっている。__

###3.メンテナンス性が高い理由の違い
__マイクロサービスは、__機能ごとにアプリケーションが分かれており、__互いに依存しないからこそ改修や機能追加が容易。__
__ドメイン駆動は__モデリングをかっちりやって__土台が固まり、過去実績のある技術を活用している→どんな仕様追加も問題ない、__という理屈。

## 最後に
簡単ですが上記のように理解しております。
個人的にはドメイン駆動開発の方が好みです！
Kerasのインストール(Anacondaで使用)

## 概要
- MacのAnaconda上でKerasを使用するためのインストール。
今回AnacondaでKerasを使用しようとしたら、少しつまづいたので、参考になればと思い投稿します。

## 環境
- MacOS Catalina V-10.15.3
- Python 3.7.6
- anaconda custom

## インストール

kerasを使用するためには、tensorflowも必要なためインストールします。
成功結果から言うと

```
$ sudo conda install tensorflow

$ sudo conda install keras
```

でanaconda上で使用可能になりました。

pythonでのインストールは、pipをよく使用しますが、今回はcondaでインストールを使用しています。keras以外にもpythonには豊富なライブラリがありますが、大抵のは、pipでのインストールで使用可能でしたが、今回のkerasの場合は、私の場合pipでは使用できませんでした。
pipでインストールした方は、pipでアンインストールして、上記の記述でインストールしてもいいかもしれません。　
- pip uninstall tensorflow
- pip uninstall keras

conda install keras でsudoを付けなかった場合も、成功しているように見えていたのですが、ようく見るとエラーが出ていました。私の場合、sudo(管理者権限)が必要だったみたいです。
他のライブラリのインストール時も、sudoをつけることで成功したのもあったので、失敗した場合は、つけるのもいいかもしれません。
【CSS】hoverしたら画像が拡大する

## シンプルな造りです

```html:index.html
<div class="inner">
  <ul>
    <li>
      <a href="" class="inview">
        <img src="img/cat01.jpg" alt="" class="img-zoom">
      </a>
    </li>
  </ul>
</div>
```

```css:style.css
    img {
      max-width: 100%;
    }
    .inner {
      width: 800px;
      margin: 0 auto;
    }

    .inview {
      position: relative;
      overflow: hidden;
      display: block;
    }

    .img-zoom {
      opacity: 1;
      transition: transform 0.3s ease;
    }

    .img-zoom:hover {
      transform: scale(1.1);
    }
```
制約の種類について

#制約の種類について

制約とは特定のデータの保存を許さないためのバリデーションの事。例えば同じメールアドレスのユーザーを登録できないようにする、名前のデータが空のユーザーを保存できないようにするといったことができるようになる。このように安全なデータ保存が実現する。主に下記の４つがある。

- NOT NULL制約
- 一意性制約
- 主キー制約
- 外部キー制約

## NOT NULL制約
NOT NULL制約はテーブルの属性値にNULL（空の値）が入ることを許さない制約。例えば、usersテーブルのnameというカラムにNOT NULL制約を設定すると、nameが空(nil)レコードは保存できなくなる。

```_create_users.rb
create_table :users do |t|
      t.string :name, null: false
      t.timestamps null: false
    end
```

##一意性制約
一意性制約はカラムに設定する制約。一意性とはユニークで他とは違うという意味です。一意性制約を設定したカラムには同じ値を設定できなくなる。例えばAさんのemailが「test@gmail.com」だった場合、他にemailが「test@gmail.com」のレコードを保存できなくなる。

```_add_email_to_users.rb
 def change
    add_column :users, :email, :string
    add_index :users, :email, unique: true
  end
```

##主キー制約
主キー制約は、主キーである属性値が必ず存在してかつ重複していないことを保証する制約。主キーに対してNOT NULL制約と一意性制約を両方設定するのと同義になる。Railsでテーブルを作成する際、主キー制約は元々実装されていて、Railsでは主キーはidカラムとして自動で作成されます。つまりidカラムの値は重複しないようにできている。

##外部キー制約
外部キー制約とは、外部キーに対応するレコードが必ず存在することを保証する制約。例えばstudent_idが3のレコードを保存するためにはstudentsテーブルにidが3のレコードが存在していなくてはいけない。

```_create_scores.rb
def change
    create_table :scores do |t|
      t.string :name
      t.integer :score
      t.references :user, foreign_key: true
      t.timestamps null: false
    end
  end
```
foreign_key: trueとすることで外部キー制約を設定。

以上。
Vue開発環境を作った時の備忘録

# はじめに
Vueの開発環境を作った。この手の記事はいくらでもある。ただその過程で、`.env`ファイルにのみ変数を閉じ込めたものは自分は見つけられなかった。その際に詰まった過程を残しておく。

# 成果物

gitへのリンク：https://github.com/yCroma/VueEnv.git

```
.
├── .env
├── Dockerfile
├── Makefile
├── README.md
├── commands
│   ├── copyenv.sh
│   └── create.sh
├── docker-compose.yml
└── spa
```

`spa`フォルダ下にマウントされるようになっている。ちなみにアプリ名を変更すると、そのアプリ名に変わる。

# 使い方

```
$ git clone https://github.com/yCroma/VueEnv.git
$ cd VueEnv
$ make vue-create
```

[http://localhost:8080](http://localhost:8080)にWelcomeページが表示される。

# 詰まったもの

- Makefileで.envを利用したい
- bashで.envを読み込む方法
- Makefile内でのdocker-compose run exec の違い

### Makefileで.envを利用したい

結論から言うと、適していないらしい。代わりにbashを書いて、Makefileで動かすのが筋だそうだ。

### bashで.envを読み込む方法

```
.
├── .env
└── commands
    ├── copyenv.sh
    └── create.sh
```

今回のようなツリー構造の場合、`commands`下にあるbashでは以下のようにして読み込んだ。

```.:.env
APP_NAME=spa
```

```test.sh
#!/bin/bash
. ../.env
echo ${APP_NAME}
```

```.:結果
spa
```

参考は以下のとおり

・[Bashで=で区切られたファイルを変数の設定ファイルとして読み込む](https://qiita.com/yousan/items/bf387f2cc008cb5cdafd)
・[シェルスクリプトで外部ファイルに記述された変数を利用する方法](https://orebibou.com/ja/home/201411/20141117_001/)

### Makefile内でのdocker-compose run exec の違い

これは、runにするだけで別のコンテナが立つというものだ。指定したコンテナに対して動かしているようで、できていないということが起こる。これにはまった。

# おわりに

以前からずっとやりたかった、環境変数を`.env`のみで完了させるということができたことは嬉しかった。ただ、メンテナンスや可読性は良いとは言えない代物なので今後も勉強していこうと思う。

# おまけ

[docker run / exec や docker-compose の command / entrypoint で複数コマンドを連続して実行するには？ #docker](https://qiita.com/YumaInaura/items/9f8a15aac406a9ee0a42)
Raspberry PiでPythonから使えるGPIOライブラリの比較

#####いまさらだけどラズパイでPythonを使ってGPIOを制御したいけどライブラリが乱立していて何を使えばいいのかわからないので整理してみた。
ここの翻訳
https://raspberrypi.stackexchange.com/questions/58820/compare-and-contrast-python-gpio-apis

#比較

- [WiringPi-Python](http://wiringpi.com/) : 開発停止
- [RPi.GPIO](https://pypi.org/project/RPi.GPIO/) : PWMはソフトウェアのみ、RPi4B対応、2019年7月の0.7.0が最終版。開発停止?
- [RPIO](https://pypi.org/project/RPIO/) : RPi.GPIOの機能強化版、ハードウェアPWM可能、コマンドラインツール付属、ドキュメント豊富。
- [gpiozero](https://gpiozero.readthedocs.io/en/v1.3.1/) : 初心者向け、RPi.GPIOで出来ることは全て可能。ADC(MCP3001/3002/3004/3008/3201/3202/3204/3301/3302/3304)サポート。ラズパイZero専用ではなくてラズパイ3,3CM,4でも使える。
- [pigpio](http://abyz.me.uk/rpi/pigpio/python.html) : ハードウェアPWM(GPIO0～31(可能、機能豊富だがドキュメントが少なく、経験豊富なプログラマ向け。BME280,DHT11/21/22/33/44/AM2302/DS18B20のPythonコードはexamples→Python codeにあり、MCP3202/3008はCだけど。

#結論

- 初心者は gpiozero がドキュメント豊富なことと、SPIをローレベルで記述しなくてもSPI接続のADCが使えるので便利。
- 2015～2019年頃はRPi.GPIOの一人舞台だったらしいので、その頃の資産を受け継いで作りたいなら RPIO。
- 慣れたら玄人向きの pigpio がいいらしいが、I2C/SPIデバイスは自分でドライブする必要あり。
Dockerの操作手順

#概要
###1 イメージを取得/ビルドする

イメージの作成２点
Ⅰ.イメージをインターネットに保存できる場所（Dockerレジストリ/DockerHub）からダウンロードしてきて使用する方法
この保存場所はオープンなので他の人が作ったイメージをダウンロードして使用することも可能
Ⅱ.自分でイメージを作成する方法
イメージのベースはレジストリ上にあるイメージ（Dockerfile）を使用して自分なりに設定やコートをカスタマイズしてビルドしていく
例えば、PHPの公式ホームページにあるイメージを利用して自分なりのライブラリや設定を追加してビルドすると
イメージの完成


###２　コンテナを生成・起動する

イメージからコンテナを作成してコンテナを起動すると使用可能

#コマンド手順

＜イメージ＞
1.取得：　$ docker image pull

2.ビルド： $ docker image build
＜コンテナ＞

3.生成：　$ docker container create

4.起動：　$ docker container start
(3.4を同時にしたいときは　$ docker container run)

5.停止：　$ docker container stop(再起動：　$ docker container restart)

6.削除：　$ docker container rm
twitterscraper-rubyを使って数年前のツイートを日付指定で検索する

Twitterのツイートを検索するには、Twitter Search APIを使う方法がありますが、**直近の7日間分**しか検索することができません。

この制限を回避するために、[twitterscraper-ruby gem](https://github.com/ts-3156/twitterscraper-ruby)を使ってみます。twitterscraper-rubyはTwitterを直接スクレイピングするため、**ツイッターが始まった最初の日からいつのツイートでも**検索することができます。

##### 注意1
twitterscraper-rubyはTwitterを直接スクレイピングしますが、Twitterの利用規約ではスクレイピングは禁止されています。個人的な少量のツイート収集程度の利用にとどめておきましょう。

##### 注意2
Twitterの検索機能は全ツイートを対象としていません。さらに、日本語のツイートについてはうまく検索できないこともあるようです。そのため、全量のツイート収集には適していません。


## 日付指定でツイートを検索する

twitterscraper-rubyを使う場合とTwitter Search APIを使う場合の結果をそれぞれ比較してみます。

### twitterscraper-rubyを使う場合

試しに2020年1月1日のツイートを上限1000件取得してみます。

```ruby:Gemfile
gem 'twitterscraper-ruby'
```

```ruby
require 'twitterscraper'

# IPがbanされる可能性を減らすためのプロキシ機能があるのですが、
# 代わりに速度がかなり遅くなるので、プロキシはオフにしています
client = Twitterscraper::Client.new(proxy: false)

tweets = client.query_tweets('Twitter', start_date: '2020-01-01', end_date: '2020-01-02', lang: 'ja', limit: 1000)

puts tweets.size
# => 1000

tweets.take(3).each { |t| puts t.created_at }
# => 2020-01-01 23:59:59 +0000
# => 2020-01-01 23:59:59 +0000
# => 2020-01-01 23:59:59 +0000
```

ぴったり1000件取得できました。他の数値も試してみましたが、少し超えることもあるみたいです。

### Twitter Search API（twitter gem）を使う場合

Twitter Search APIを利用して同じ日付のツイートを取得することも試してみましたが、こちらは想定通り1件もツイートが取得できませんでした。Twitter Search APIは直近の7日間のツイートしか取得できないためです。

```ruby
# https://github.com/sferik/twitter
client = Twitter::REST::Client.new

tweets = client.search('Twitter since:2020-01-01 until:2020-01-02', count: 100)

puts tweets.size
# => 0
```

## 参考リンク

- [twitterscraper-ruby gem](https://github.com/ts-3156/twitterscraper-ruby)
簡単レシート印刷 receiptline で商品名と金額を配置してみた

日本発のオープンソース receiptline でレシート印刷に少しずつトライしています。
まだレシートプリンターがないので、[前回](https://qiita.com/dopperi46/items/8a4389eb6be79e5e7635)利用した開発ツールを引き続き使います。
今回はテーブルで商品名と金額を配置します。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/a2ef39a6-c1ca-5aef-affb-3ced4eacf1af.png)

# 2列のテーブル

テーブルを利用して、レシートによくある商品名と金額のペアを作ってみます。
1 列目は商品名で左揃え、2 列目は金額で右揃えにします。

商品名と金額を `|` で区切って、位置揃えスペースを入れたら、出来上がり。

```text:ReceiptLine
冷奴 | 380
竜田揚げ | 480
もつ煮込み | 580
小計 | 1,440
(内消費税等 | 130)
^合計 | ^1,440
```

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/3195fdf9-2bf9-d601-3e7f-66b301f238b8.png)

# 列の数は可変

表題、水平線、注記を追加します。これらは 1 列で、中央揃えです。
2 列の途中で 1 列を混在させることができます。列の数は可変なのです。

列が分かるように、`|` とスペースを追加して、見た目を整えてみました。
ちなみに、空の行は改行が出力され、`-` のみの行は水平線になります。

```text:ReceiptLine
|           "領収書"           |
|                              |
|冷奴          |            380|
|竜田揚げ      |            480|
|もつ煮込み    |            580|
|------------------------------|
|小計          |          1,440|
|(内消費税等   |           130)|
|^合計         |         ^1,440|
|                              |
|※印は軽減税率(8%)対象商品です|
```

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/50cda88f-a5fe-3e70-8902-1c1a02665030.png)

# 文字列の折り返し

では、長～い商品名を入れるとどうなるでしょう。
行の半分くらいのところで文字列が折り返されます。

```text:ReceiptLine
冷奴竜田揚げもつ煮込みトリプルセット | 1,280
```

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/0a1340b3-a2f1-7df1-a30f-4ccfb0ee7103.png)

商品名を意図的に折り返したいこともあります。
そのときは、折り返したいところに `\n` を書きます。

```text:ReceiptLine
冷奴\n竜田揚げ\nもつ煮込み\nトリプルセット | 1,280
```

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/951396e1-f319-1b05-9e9d-1d1359d65212.png)

商品名を折り返したくないときは、おまじないが必要です。
`{text:nowrap}` を追加すると、はみ出す文字列が省略されます。

```text:ReceiptLine
{text:nowrap}
冷奴竜田揚げもつ煮込みトリプルセット | 1,280
```

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669512/48bc5241-1288-f655-dfaf-4add58224e5b.png)

これは text プロパティというもので、この行以降の文字列の折り返しを設定しています。
名前は `text` または `t`、値は `wrap` で折り返す、`nowrap` で折り返さない、です。

これでレシートらしい配置ができました。
次回はテーブルを調整して見栄えを良くしたいと思います。
Schemeのnamed-letのサンプル

Schemeのnamed-letの記述例．いつものように[Gauche](https://www.jdoodle.com/execute-scheme-online/)で実行確認．

```scheme:named-let.scm
gosh> (define (sum x y l) ; named-letを使用しない．
        (cond ((> x y) (reverse l))
              (else
                (sum (+ x 1) y (cons x l)))))
sum
gosh> (sum 3 11 '())
(3 4 5 6 7 8 9 10 11)
gosh> (define (sum x y l)
        (let loop ((x x) (l l)) ; named-letを使用する．
          (cond ((> x y) (reverse l))
                (else
                  (loop (+ x 1) (cons x l))))))
sum
gosh> (sum 3 11 '())
(3 4 5 6 7 8 9 10 11)
gosh> (define sum ; lambda式のdefine形式にする．
        (lambda (x y l)
          (let loop ((x x) (l l)) ; named-letを使用する．
            (cond ((> x y) (reverse l))
                  (else
                    (loop (+ x 1) (cons x l)))))))
sum
gosh> (sum 3 11 '())
(3 4 5 6 7 8 9 10 11)
gosh>
```

どれも同じ内容でどんどん長くなっているけど，本質は3番目かもしれないと思っていたり．つまり，無名関数であるlambda式で再帰関数が定義できるということで．たとえば，こんな記述が書けたり…してもあんまし意味ないか．むう．

※2020-08-02追記：いや，意味大いにあるか．`map`に[無名再帰関数を指定している](https://qiita.com/ytaki0801/items/596efbbcb07d38630bc9)ということではないか…．

```scheme:map-lambda.scm
gosh> (map (lambda (p)
            (let loop ((x (car p)) (y (cadr p)) (l '()))
              (cond ((> x y) (reverse l))
                    (else
                     (loop (+ x 1) y (cons x l))))))
           '((1 5) (4 9) (3 8)))
((1 2 3 4 5) (4 5 6 7 8 9) (3 4 5 6 7 8))
gosh>
```

※2020-08-17追記：named-letを`letrec`でマクロ定義してみた例．

```scheme
gosh> (define-syntax nlet
        (syntax-rules ()
          ((_ fn ((n v) ...) body)
           (letrec ((fn (lambda (n ...) body))) (fn v ...)))))
#<undef>
gosh> (nlet loop ((n 40) (f1 0) (f2 1))
        (if (= n 0) f1 (loop (- n 1) f2 (+ f1 f2))))
102334155
```

#参考文献
* Practical Scheme：[なんでもλ](http://practical-scheme.net/docs/lambda-j.html)
【Rails】デプロイエラー　”NoMethodError: undefined method `[]' for nil:NilClass”　の解決方法【デプロイ物語】


#### 【バージョンやら環境】
Rails 5.2.4.3
Ruby 2.5.1
macOS Catalina 10.15.4
Capistrano 3.14.1



#### 【内容】
Capistranoを用いた初回のデプロイは成功している状態で、S3の条件分岐（本番環境のみS3にアップロード）を加えてデプロイ（bundle exec cap production deploy）したら上記のエラーが出ました。
<br>


```ruby:ターミナル
Exception while executing as ec2-user@XXX.XXX.XXX.XXX: rake exit status: 1 (SSHKit::Runner::ExecuteError)
NoMethodError: undefined method `[]' for nil:NilClass
```

というエラーが出た。

SSHとあるため、てっきりSSHキー系のエラーかと思って、SSHの設定をしなおしたりいじったりしたが直らず。<br>
どうやら、この手のエラーは、別にみるポイントがあるようです。

さらに下を読み進めます。


```ruby:ターミナル
/var/www/アプリディレクトリ名/releases/20200627035734/config/initializers/carrierwave.rb:15:in `block in <top (required)>'
```

とあります。config/initializers/carrierwave.rbの15行目でエラーが起きているよ、という意味のようです。<br>
該当の箇所を見に行くと

```ruby:ターミナル
aws_access_key_id: Rails.application.credentials.aws[:access_key_id],

```

とありました。つまり、前述の「NoMethodError: undefined method `[]' for nil:NilClass」については、[:access_key_id]がnilだよ、と言われているようです。
<br>

どうやら、設定をしたと思っていた、「config/credentials.yml.enc」に記述するAWSのアクセスキー設定ができていなかった模様。（うまく保存されていなかった）。

AWSのアクセスキーを設定し直したらエラーが解決しました。


【あとがき】
最初に記述されていたエラー分がSSHだと書いてあって、キーワードのインパクトにそこだと疑わなかったためエラーの本質に気づくのが遅れました。エラー解決は仮説をできるだけたくさん立てなくてはいけないですね。

デプロイのエラーは少しわかりにくいのですが、恐ろしいことに慣れてきました（少しずつですけど。
最初は大変だと思いますが一個一個根気強く解決していくことが大事ですよね。きっと。

そしてやっぱりがんばれデプロイ担当。
【Perl】b(ac+1)=d^3(a<b<c)を満たす整数を見つける

アプローチ方法が分からなかったので、Perlで虱潰しに見つけることにした。

# メモ
それでパターンが分かった。

```
d^3
= d(d^2)
= d(d^2-1+1)
= d((d^2-1)+1)
= d((d-1)(d+1)+1)
```

# スクリプト
```
#!/usr/bin/perl -w

########### EXEC

&main();

########### MAIN

sub main()
{
        my($i);

        for($i = 2; $i < 20; $i++)
        {
#               print "Hello World!! $i\n";
                &calc($i);
        }

        return 0;
}

########## SUB

sub calc()
{
        my($max) = $_[0];

        my($ia,$ib,$ic,$num);

        for($ia = 1; $ia <= $max; $ia++) {
                for($ib = $ia+1; $ib <= $max + 1; $ib++) {
                        for($ic = $ib+1; $ic <= $max + 2; $ic++) {
                                $num = $max ** 3;
                                if($num eq $ia * $ib * $ic + $ib) {
                                        print "$ia,$ib,$ic,$num\n";
                                }
                        }
                }
        }

        return 0;
}

########## END
```

```
1,2,3,8
2,3,4,27
3,4,5,64
4,5,6,125
5,6,7,216
6,7,8,343
7,8,9,512
8,9,10,729
9,10,11,1000
10,11,12,1331
11,12,13,1728
12,13,14,2197
13,14,15,2744
14,15,16,3375
15,16,17,4096
16,17,18,4913
17,18,19,5832
18,19,20,6859
```
Pythonで半角全角の表記ゆれ修正

# この記事の目的
半角や全角の表記ゆれを簡単に修正するための関数を作ります。


# 準備

変換の前後の文字を用意します。

```python 
abc_half = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
abc_full = "ａｂｃｄｅｆｇｈｉｊｋｌｍｎｏｐｑｒｓｔｕｖｗｘｙｚＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰＱＲＳＴＵＶＷＸＹＺ"

digit_half = "0123456789"
digit_full = "０１２３４５６７８９"

katakana_half = "ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝ"
katakana_full = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン"

punc_half = "!#$%&¥()*+,-./:;<=>?@[]^_`{|}~"
punc_full = "！＃＄％＆￥（）＊＋，－．／：；＜＝＞？＠［］＾＿｀｛｜｝～"

```

半角カタカナの破裂音は2文字で１文字を表現しているので、他とは別に変換テーブルを作成します。

```python 

tmp01 = "ｶﾞｷﾞｸﾞｹﾞｺﾞｻﾞｼﾞｽﾞｾﾞｿﾞﾀﾞﾁﾞﾂﾞﾃﾞﾄﾞﾊﾞﾋﾞﾌﾞﾍﾞﾎﾞﾊﾟﾋﾟﾌﾟﾍﾟﾎﾟ"
tmp02 = "ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ"

transtable02 = {}
for i in range(len(tmp02)):
    be = tmp01[i*2:i*2+2]
    af = tmp02[i]
    transtable02[be] = af
```


関数 `clean_text` の中で `transtable01 = str.maketrans(before, after)` で変換テーブルを作成し、それを `text = text.translate(transtable01)` で適用させています。

```python 

def clean_text(text):
    text = str(text).replace("\u3000", " ") #全角スペースを半角に

    before = abc_full + digit_full + katakana_half + punc_full
    after = abc_half + digit_half + katakana_full + punc_half

    transtable01 = str.maketrans(before, after)
    text = text.translate(transtable01)
    text = text.translate(transtable02)

    return text
```



# 使い方

```python 

text = "ﾒﾓﾔﾕﾖﾗﾘﾙﾚ，－．／：；ｑｒｹﾞｺﾞｻﾞｼﾞｽﾞｾﾞｿﾞﾀﾞﾁﾞ"
clean_text(text)

>>> メモヤユヨラリルレ,-./:;qrケﾞコﾞサﾞシﾞスﾞセﾞソﾞタﾞチﾞ
```

以上！

# あとがき
送り仮名とか漢数字とか、日本語には他にも表記ゆれがあると思うので追々追加していけたらいいなと思ってます。


# 参考

[【全角⇔半角】Pythonで日本語の表記ゆれを整えるライブラリおすすめ](https://srbrnote.work/archives/3750)
[[python] いろいろな文字種のリストを作成](https://qiita.com/okkn/items/3aef4458ed2269a59d63)
PandasのDataFrameで2つの列の時間差を計算

#Pandasと日時データ
Pandasはデータの読込や型変換を柔軟に実行してくれる非常に便利なライブラリです。
ただし、intやfloat型と比べると**日時型（64bit OSではdatetime64型）は取扱いに注意が必要で、特に引き算はハマりやすい処理です**。

#日時の引き算
さっそく日時同士の列の引き算を実行してみます。

###使用するデータ

```time_diff_test.csv
A,B
2020-06-02 13:45:16,2020-06-02 13:50:23
2020-06-02 13:50:15,2020-06-02 14:55:19
2020-06-02 13:52:10,2020-06-03 13:57:21
```

###データを読み込んで引き算を実行するコード
pd.read_csv()で読み込む際に、引数を指定しないとdatetime型ではなくstr型で読み込まれるので注意してください。
datetime型の列として読み込む方法はいくつかありますが、下記のように引数parse_datesを指定するのが楽です。

```time_diff_test.py
import pandas as pd
df = pd.read_csv('time_diff_test.csv',parse_dates=['A', 'B'])
df['diff'] = df['B'] - df['A']
print(df)

#0   0 days 00:05:07
#1   0 days 01:05:04
#2   1 days 00:05:11
#Name: diff, dtype: timedelta64[ns]
```

上記のように単純に列同士の引き算をすると、timedelta64型で出力されます

#日時の引き算を秒（分、時、日‥）単位で取得
実際の使用時には秒や分単位で取得したい場面が多いかと思います。

###うまくいかないコード
timedelta型の変数を秒単位に変換したい場合**.total_seconds()**が有効ですが、
DateFrameの列（Series）にそのまま実行してもうまくいきません

```python:
import pandas as pd
df = pd.read_csv('time_diff_test.csv',parse_dates=['A', 'B'])
df['diff'] = df['B'] - df['A']
print(df['diff'].total_seconds())

#'Series' object has no attribute 'total_seconds'
```

###うまくいくコード
timedelta型のSeriesを秒に変換する方法はいくつかありますが、
下記のように**mapとlambdaを組み合わせると、1行で記述できて楽です**

```time_diff_test_seconds.py
import pandas as pd
df = pd.read_csv('time_diff_test.csv',parse_dates=['A', 'B'])
df['diff'] = df['B'] - df['A']
df['diff_ts'] = df['diff'].map(lambda x: x.total_seconds())
print(df['diff_ts'])

#0       307.0
#1     3904.0
#2    86711.0
#Name: diff_ts, dtype: float64
```

###【追記】Series.dt.total_seconds()を使用
※@nkayさんよりコメント頂きました
上のmap + lambdaよりシンプルに計算でき、ベストチョイスになりそうです。

```python
df['diff_ts'] = df['diff'].dt.total_seconds()
print(df['diff_ts'])

#0      307.0
#1     3904.0
#2    86711.0
#Name: diff, dtype: float64
```

###時間差を分、時単位で
total_minutes()、total_hours()‥**なんてメソッドはありません、、笑**
total_seconds()を60、3600で割りましょう

```python
print(df['diff'].map(lambda x: x.total_seconds()/60.0))
print(df['diff'].map(lambda x: x.total_seconds()/3600.0))

#0       5.116667
#1      65.066667
#2    1445.183333
#Name: diff, dtype: float64
#0     0.085278
#1     1.084444
#2    24.086389
#Name: diff, dtype: float64
```

##total_seconds()とsecondsの違い
timedeltaを秒単位に変換する方法には、**total_seconds()**以外にも**seconds**があります。
違いを調べてみます

```python:total_seconds()
print(df['diff'].map(lambda x: x.total_seconds()))
#0      307.0
#1     3904.0
#2    86711.0
#Name: diff, dtype: float64
```

```python:seconds
print(df['diff'].map(lambda x: x.total_seconds()))
#0     307
#1    3904
#2     311
#Name: diff, dtype: int64
```

[こちら](https://docs.python.org/ja/3.5/library/datetime.html#datetime.timedelta.total_seconds)によると、
**total_seconds()：差分を秒単位で表したもの（float型）**
**seconds：差分を日数、秒数、マイクロ秒数、ミリ秒数、分、時間、週で分解したうちの秒数（int型）**
となっているようです。

いわゆる**「時間差」を表すのはtotal_seconds()**の方みたいですね

**本記事は以上です**
最後まで見て頂きありがとうございました！
docker上のnginx.confに環境変数を適用する方法

備忘録です。
## docker上のNGINXに環境変数を適用するいい方法が無いか探していました。
envsubstを使ってホニャララする方法がメジャーなのかなーと思って、Docker Hubのnginxのページを見てみると
なにやらversion1.19からいい方法ができてるっぽい？？

dockerHub
https://hub.docker.com/_/nginx

ということで早速Google翻訳しながら試してみる。

## 全体図

```
├　docker-compose.yml
├ .env
├　nginx
		├ templates
		│		└ default.conf.template　//これがポイント
		└ Dockerfile
```

### .envの中身

```
#.env
NGINX_PORT=8080
```

.envファイルをdocker-compose.ymlと同じ階層においておくと環境変数として読み込んでくれる。

```dockerfile
#nginx/Dockerfile

FROM nginx:1.19.1
RUN rm /etc/nginx/conf.d/default.conf
```

```yml
  #docker-compose.yml
  
  nginx:
    container_name: nginx
    build: ./nginx

    ports:
      - ${NGINX_PORT:-80}:${NGINX_PORT:-80}
    depends_on:
      - django
    volumes: 
      - ./nginx/templates:/etc/nginx/templates
      
    environment:
      - NGINX_PORT=${NGINX_PORT:-80}
```

${NGINX_PORT:-80}の部分で.envに書かれているNGINX_PORTの値を取得しています。取得できない場合はデフォルト値で80を設定するようになっています。

```
#default.conf.template

server {
    # 環境変数の値を取得
    listen ${NGINX_PORT};
}
```

> デフォルトでは、この関数は/etc/nginx/templates/*.template内のテンプレートファイルを読み取り、envsubstの実行結果を/etc/nginx/conf.dに出力します。

↑日本語翻訳の結果、なんかetc/nginx/templates内の.templateを上手いこと読み取って環境変数で置き換えてconf.dに出力するそうです。しらんけどｗ

あとは docker-compose build,docker-compose upしたら無事に接続できました。
CentOS8がオフラインインストールできない

#はじめに

(追記: CentOS8.2では改善してます。)

ネットワークの都合でネットにつながずにCentOS8.1をインストールする事にしました。

ハードウエア環境はVMWARE ESXi 6.5u3 (2020/7/16時点の最新パッチ適用)の環境です。

CentOS8.1を以下のDVDイメージからインストールしようと思ったのですが

> CentOS-8.1.1911-x86_64-dvd1.iso

インストールの途中で以下のメッセージが出て

> パッケージのダウンロード中です

しばらく止まり、最終的に次のエラーで止まります。

> 未知のエラーが発生しました

![tmp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61370/62afdba7-af87-c750-d641-ccb3663f0ac7.jpeg)

#オフラインインストールできない。

ソフトウエアが足りないのがあるからダウンロードしてるんだろうと予想し、ソフトウエア選択をいろいろ試してみました。

> サーバ(GUI使用)
> サーバ
> 最小限のインストール

すべて同じエラーで止まりました(>_<)

#対策
ひとつ前のCentOS8.0のDVDイメージだと「サーバ(GUI使用)」のインストール成功しました。

> CentOS-8-x86_64-1905-dvd1.iso

なんだかな。
[MySQL]緯度経度による距離計算を高精度で行う[Rails]

# 目的
レコードにある緯度経度と入力値の緯度経度から距離を計算し
一定距離内のレコードのみを取得したかった

# 計算方法とそれぞれへの所感

ざっとググってみると主に3つの方法が見つかりました

- 1. 三角関数を駆使する方法
- 2. `LINESTRING()`や`GLENGTH()`を使う方法
- 3. `ST_Distance_Sphere()`を使う方法

最終的に採用したのは3番の`ST_Distance_Sphere()`を使う方法でした

## 1. 三角関数を駆使する方法について
ぶっちゃけめんどい
他にいい方法がなければ仕方なく使う最終手段

## 2. `LINESTRING()`や`GLENGTH()`を使う方法
試してみたけどちょっと精度が悪い
580m程度の距離を計算した時に120m程度の誤差が出て許容できなかった
主に1km前後の距離を精度よく計算することが求められていたので不採用

## 3. `ST_Distance_Sphere()`を使う方法(採用)
MySQLにある関数を使うだけなので非常に使い勝手が良く
高精度の距離計算ができたのでこれを採用！！

試してないけど`ST_Distance_Spheroid()`っていう速度は落ちるがさらに高精度な関数もあるらしい 

ちなみに計算結果の単位はメートル
インチとかヤードとかじゃなくて本当に良かった


# 実際の実装では
Railsを使っていたため緯度経度のカラムの型にgeometry型が扱えず
代わりにdouble型のカラムで緯度経度を保持していました
geometry型の代わりにdouble型のカラムで十分だと判断した理由については別の記事でまた書きます

計算する時は`POINT()`を使って緯度経度をキャストしたものを`ST_Distance_Sphere()`の引数に渡して計算しました

## Railsでの実装
前提として、店舗(Store)と住所(Address)という1:1のモデルがあり、
Addressモデルが持つ緯度経度と入力値の緯度経度から距離を計算して
一定距離内の店舗一覧を取得する処理を実装した

```ruby:app/models/store.rb
  DISPLAYABLE_METER = 1000
  DISTANCE_METER_COLUMN = 'distance_meter'

  scope :select_with_distance_meter, lambda { |lat:, lng:|
    joins(:address).select(
      "
      #{self.table_name}.*,
      ST_Distance_Sphere(
        POINT(lng, lat),
        POINT(#{lng}, #{lat})
      ) AS #{DISTANCE_METER_COLUMN}
      ",
    )
  }
```

```ruby:店舗の一覧取得
Store
  .select_with_distance_meter(lat: lat, lng: lng)
  .having("#{Store::DISTANCE_METER_COLUMN} < #{Store::DISPLAYABLE_METER}")
```

`AS` でエイリアスにしているカラムに対しては`where`使えないので`having`使ってます


# 参考資料
[MySQLのgeometry型で○km以内の場所を取得してみました](https://qiita.com/mitani/items/6909406ac4fe0db2d35c#%E8%BF%91%E3%81%84%E9%A0%86%E3%81%AB%E6%97%85%E3%82%92%E5%8F%96%E5%BE%97)
[ST_Distance_Sphere](https://aginfo.cgk.affrc.go.jp/docs/pgisman/1.5.1/ST_Distance_Sphere.html)
初心者によるプログラミング学習ログ 372日目

#100日チャレンジの372日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
372日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>昨日の作業・やったこと⇩<br><br>●寝る直前の筋トレ5分、kindle読書 10分<br>●ブログ1記事作成<br>●プログラミング学習372日目 2h<br>・メンターの課題<br>・調整用メディアクエリ追加<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%E3%81%A4%E3%81%AA%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><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></p>&mdash; ぱぺまぺ@社畜✕投資✕ブロガー (@ppmp65) <a href="https://twitter.com/ppmp65/status/1283495894571073536?ref_src=twsrc%5Etfw">July 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
基礎から学ぶ　人工知能の教科書　第4章　章末問題

# はじめに
機械学習の勉強として、「*[基礎から学ぶ　人工知能の教科書](https://www.ohmsha.co.jp/book/9784274224263/)*」 を読んでいます。

この本の特徴は、章末問題に`Python`の簡単なプログラムが載っていてるところです。

ここでは、それを`Ruby`にて写経しています。
# 第4章　章末問題
```isa.rb
semnet = {"portable terminal"=>"computer",
          "laptop PC"=>"computer",
          "stationary PC"=>"computer",
          "smartphone"=>"portable terminal",
          "tablet"=>"portable terminal",
          "desktop PC"=>"stationary PC",
          "server PC"=>"stationary PC"}
while true
  puts "「AはBですか？」という質問を扱います。AとBを入力してください"
  print "Aを入力："
  a = gets.chomp
  print "Bを入力："
  b = gets.chomp
  puts "質問：「#{a}は#{b}ですか？」"
  puts "推論を開始します"
  if semnet[a].nil?
    puts "「#{a}」がわかりません"
    next
  end
  obj = a
  while obj != b
    puts "#{obj}は#{semnet[obj]}です"
    if semnet[obj] == b
      puts "結論：#{a}は#{b}です"
      break
    end
    unless semnet.keys.include?(semnet[obj])
      puts "結論：#{a}は#{b}ではありません"
      break
    end
    obj = semnet[obj]
  end
  puts "推論終了"
end
```
意味ネットワーク(semantic network)におけるリンクの一つである`is-aリンク`を用いた推論を実装する問題です。

*[is-a - wikipedia](https://ja.wikipedia.org/wiki/Is-a)*

`python`は日本語入力でもうまくいくのですが、`ruby`ではうまくいかなかったので英単語に変更しています。

```
「AはBですか？」という質問を扱います。AとBを入力してください
Aを入力：smartphone
Bを入力：computer
質問：「smartphoneはcomputerですか？」
推論を開始します
smartphoneはportable terminalです
portable terminalはcomputerです
結論：smartphoneはcomputerです
推論終了
```
# まとめ
+ 第4章まで読んだ
expressサーバーでbase64画像を受けとって保存するメモ【LINE BOTなどで利用】


いつも忘れるのでメモ。

LINE BOTでサーバー作るときなどによく使うので

こんな感じで保存できました。

```js
const base64Data = req.body.image.replace(/^data:image\/png;base64,/, '');
fs.writeFileSync(`hoge.png`,base64Data, 'base64');
```

expressと組み合わせるこんな感じ。

```server.js
省略

app.post('/post', async (req, res) => {
    try {
        const base64Data = req.body.image.replace(/^data:image\/png;base64,/, '');
        fs.writeFileSync(`hoge.png`,base64Data, 'base64');
        console.log(`save done`);
        res.send({msg: 'success'});
    } catch (error) {
        res.error(error);        
    }
});

省略
```

LINEと組み合わせる際はこちらの記事も参考にして下さい。

> [1時間でLINE BOTを作るハンズオン (資料+レポート)](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)
品質を左右する自工程完結がAgile開発のプラクティスに存在する。

TPSのプラクティスに**自工程完結**があります。
狙いは、当たり前に作業して良品が出来る事を目指していますが、二つの柱があります。
それは、
**A）不良を発生させない**
**B）不良を後工程に流さない**
です。
ペアプログラミング（モブプログラミングも含む）、テスト駆動開発は**A**の効果が期待できます。
常時結合とDoneの定義は**B**の効果が期待できます。
これらは、従来手法（W/F)には無いプラクティスです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621379/0ed7a825-488b-2c8e-b613-886708ce3bb5.png)

さらに、Agile開発では上の図の様に多くのフィードバックループが存在します。
このフィードバックループにより、単なるバグが軽減されるだけでなく、仕様祖語も無くなります。

以上の様に、**Agile開発では従来手法よりも品質が高くなります。**
WordPressで動的ページを作るには

Wordpressで動的ページを作るにはどうしたらいいのかを考えていきたいと思います。
ここでいう動的ページとは、MySQLデータベースに独自のテーブルを持ってそのデータを参照しながら、ページを作っていくことです。

##やりたいこと
１．MySQLデータベースから情報を引っ張ってきて動的に表示させる
２．タイトルも動的に変更する
３．metaタグも動的に変更する
４．SEO的にも問題ないように仕上げて、Googleさんにインデックスしてもらう

##１．MySQLデータベースから情報を引っ張ってきて動的に表示させる

↓（以前の記事）WordPressで自作テーブルを作成してデータを利用する方法
https://qiita.com/healing_code/items/3c70284fc6c302ae78ec


##２．タイトルも動的に変更する
http://www.initialsite.com/g07/16443

固定ページ-属性-テンプレートを使った方法
https://webcodezero.com/wordpress/wpfixedpage/#i-5


##３．metaタグも動的に変更する
https://kantaro-cgi.com/blog/wordpress/no_show_meta_in_custom_theme.html
https://wordpress.japanbookmark.com/wordpress/header-php/
頻出の再帰処理とクロージャーパターンを覚えよう

# 始めに
再帰処理では処理速度を向上したり無限ループを防ぐために処理と処理の間で共有する記憶データを利用する場合があリます。
そのような記憶データは再帰関数の外側に定義する必要がありますが、再帰関数をエクスポートして再利用する場合に記憶データを保持する変数がメモリリークの原因となってしまいます。
この記事ではそのような再帰処理で共有される変数をクロージャーの中に閉じ込めるパターンを紹介します。

## 1.単純な再帰処理
再帰処理の例ではフィボナッチ数列の例がよく上がります。フィボナッチ数列は、前の二つの数字を足して次の数字を作っていく数列です。

```
0 1 1 2 3 5 8 13 ... 
```

typescriptでフィボナッチ関数のf(n)を求める式は以下のようになります。

```typescript
function fibonacci(n: number): number {
    if (n === 0) {
        return 0;
    }
    if (n === 1) {
        return 1;
    }
    return fibonacci(n - 2) + fibonacci(n - 1);
}
```


## 2.メモリを用いた再帰処理
1の例でアルゴリズムは動くが、`fibonacci(100)`を実行してみるととても長い実行時間がかかってしまいます。
これが何故かというと、フィボナッチ関数が同じ計算を何度も繰り返しているためです。例えば、 f(100)はf(99)とf(98)を呼び出し、f(99)はf(98)とf(97)を呼び出し、f(98)はf(97)とf(96)を呼び出し...と続きます。ここで、f(98)とf(97)は二回呼び出されている事が分かります。
f(0)などは全てのf(x)から呼び出され、合計で実行される数は2^100となっています。
しかし、本来ならば計算しなければいけない数はf(100),f(99),f(98)...f(0)の合計100の計算でいいはずです。

100回の計算ですませるためには、一度した計算結果を保存しておき、計算済みの値を再利用するようにします。

書き換えると以下のようになります。

```typescript:fibonacci-memory.ts 

const memory: {
    [ key: number ]: number
} = {};

export function fibonacci(n: number): number {
    let result;
    if (n === 0) {
        result = 0;
    } else if (n === 1) {
        result = 1;
    } else {
        result =
            (memory[ n - 1 ] ? memory[ n - 1 ] : fibonacci(n - 1))
            + (memory[ n - 2 ] ? memory[ n - 2 ] : fibonacci(n - 2));
    }
    memory[ n ] = result;
    return result;
}

console.time("fibonacci");
console.log(fibonacci(100));
console.timeEnd("fibonacci");

```

少し複雑ですが、要はフィボナッチ関数で一度計算した結果を`memory`に格納して再利用するように実装したものです。実行してみると、数秒で計算が完了します。

```shell

$ ts-node fibonacci-memory.ts 
354224848179262000000
fibonacci: 2.280ms
```

## 3.メモリを用いた再帰処理のクロージャー関数
さて、ここでこのフィボナッチ関数を外部のファイルからインポートして使いたいとします。

```typescript:fibonacchi-import.ts
import { fibonacci } from "./fibonacci-memory";

console.time("fibonacci");
console.log(fibonacci(100));
console.timeEnd("fibonacci");


```

実行してみると以下のようになります。

```shell
$ ts-node fibonacci-import.ts 
354224848179262000000
fibonacci: 2.429ms
```

外部ファイルから利用しても`memory`オブジェクトによって処理が早くなっています。しかし、フィボナッチ関数の外にある`memory`は関数の実行が終わってもメモリから解放されず、メモリリークを起こしてしまいます。

これを防ぐために、クロージャー関数で`fibonacci`関数をくくりましょう。

```typescript:fimanacci-memory-colosure.ts
function fibonacciClosure(m: number) {
    const memory: {
        [ key: number ]: number
    } = {};

    function fibonacci(n: number): number {
        let result;
        if (n === 0) {
            result = 0;
        } else if (n === 1) {
            result = 1;
        } else {
            result =
                (memory[ n - 1 ] ? memory[ n - 1 ] : fibonacci(n - 1))
                + (memory[ n - 2 ] ? memory[ n - 2 ] : fibonacci(n - 2));
        }
        memory[ n ] = result;
        return result;
    }

    return fibonacci(m);
}

```

これでフォボナッチ関数の呼び出し完了とともに`memory`は解放されメモリリークを起こすことはなくなります。

```typescript:fibonacci-import.ts
import { fibonacciClosure } from "./fibonacci-memory-closure";
console.log(fibonacciClosure(100));
```
VS CodeでAnaconda環境のPythonを使おう

# これは何？
実験でコードをJupyter notebookに貼り付けてプログラムを実行しろとのことだったので、めんどくさいなという感じでした。
なのでVSCode上でconda環境でPythonを実行するQiitaに書こうかなと。

# 環境
macOS Mojave 10.14.4

Visual Studio Code 1.47.1

Anaconda-Navigator 1.9.12

（おそらくWindowsも同じやり方だと勝手に思っています。）

# やり方
Anacondaをインストール(ほか参照)
VS Codeをインストール(ほか参照)
拡張機能から
Python：Pythonの拡張機能
をインストール


Anaconda navigatorからVSCodeを実行
VSCodeで環境を選択
Pythonファイルを実行

# Anaconda navigatorからVSCodeを実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/43bcfc6a-2a94-f13d-4efe-17b21981b633.png)


Anaconda navigatorを起動して、メインの画面からVSCodeをlaunchします。これでVSCodeで実行することができます。

余談
condaは仮想環境の一種で、root以外にも違ったバージョンの環境を簡単に作ることができます。
最新版の環境では動かない(例えばpython2系のみの時)などに仮想環境で環境構築すると楽です。同様の方法でVSCodeで開くことができます。


VSCodeで環境を選択

次にVSCodeを開き、左下のPython~と書かれているところをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/14a004c5-4f2c-2354-c336-4d5cfaa9f5a8.png)




環境を選択します。この部分でどの環境を使ってpythonを実行するかを選択します。今回は作成したPython 3.7(conda:base) を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/35205e67-3fc1-adf3-1043-0cba88ec447e.png)



これで、conda内の仮想環境を選択することができました。最後にファイルを実行します。


ファイルの実行

今回は、デバック機能を使って実行します。VSCodeの左側にある虫のマーク(デバック)をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/fdb66dab-6432-fdee-0981-5b44101bad72.png)


実行するをクリックすると、デバイス環境の選択が出てくるので、Python File Debugを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/d8ca4a54-40e6-428c-e793-0df572c2a7c1.png)



これでPythonのファイルを実行できました。
下のコマンドウィンドウに結果が返ってきていると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/5593c14f-179f-f32c-9c82-d758045a4e13.png)


Jupyterで実行すると提出の時にpyファイルに移さなきゃいけなかったり、色々同じコードをセルに貼り付けまくったりしてどれが最新かわからなくなったりする（経験者）なので、VSCodeを使おう！
AnacondaだとSpyderとか使って、pyファイルを実行できますが、個人的にVSCodeが好きなので、VSCodeでの実行をお勧めします。

# 何をやってくれているか(コマンドで頑張る編)

このコマンドでガヤガヤやるのをVSCodeがやってくれているんだと勝手に思っています。

```
$ conda activate (環境名)
```
仮想環境に入る

```
(環境名）$ python3 (ファイル名).py
```
仮想環境でPythonを実行する。

ここら辺をbashでやってくれてる感じなんだと思います。

実験の手順書には、condaでpipを使ってインストールする方法が書かれていたので、ちょい怖くなりました。（経験者）

最近VSCodeが便利すぎて、他のエディタは考えられない感じになってきているので、たまにはXcodeとかも使ってみようかなと思います。すごくVSCodeは便利です。

# VSCodeでJupyter Notebookを使う

残りは余談ですが、VSCodeでJupyter Notebookを使えます。ブラウザでコード書くのは、コードの保管やVSCodeの拡張機能で自分用にカスタマイズした機能が使えないので、VSCodeでJupyter Notebookを使いましょう。

やり方は非常に簡単です。.ipynbファイルを右クリック→このアプリケーションで開く→Visual Studio Codeで簡単に開けます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/fded106c-f836-1ec5-816c-2cb4636ef4ef.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548598/0a51a2cd-3dee-d1cf-484d-a5bae8ce69f3.png)

VSCode上でブラウザ同様に使うことができるので、エラーメッセージをググった結果とコード２つをタブ分けることなく見比べることができますね。

ノートブックの０からの作成に関してはこのページがすごくわかりやすいです。
https://dev.classmethod.jp/articles/visual-studio-code-jupyter-notebook/
（VSCode上でPython：Pythonの拡張機能の追加が必要です）
【組み込み系エンジニアのメモ】PowerShellにてApp(Arduino)を起動

# まずPowerShellってなに？
いきなりわからないw
　調べたところ、
　- wsh
　　- 要.vbs 
　- PowerShell
　- コマンドプロンプト
　　- 最初にできたやつ。
　など...それぞれメリットはあるが使ってみないとわからなそう。

# PowerShellでArduinoを起動してみた。

```startApp.ps1
'Get-AppxPackageで、-NameにArduinoを含むパッケージマニフェストを検索。
ヒットしたらマニフェスト内のApplication IDを取得。'
PS C:\Users\User-san> (Get-AppxPackage -Name *Arduino* | Get-AppxPackageManifest).Package.Applications.Application.Id
ArduinoIDE
'同じようにファミリーネームを取得'
PS C:\Users\User-san> (Get-AppxPackage -Name *Arduino*).PackageFamilyName
ArduinoLLC.ArduinoIDE_<IDIDIDIDIDIDIDID>
PS C:\Users\User-san> Start-Process shell:AppsFolder\ArduinoLLC.ArduinoIDE_<IDIDIDIDIDIDIDID>!ArduinoIDE
```

※1 パッケージ マニフェストは、システムが Windows アプリを展開、表示、または更新するために必要とする情報を含む XML ドキュメントです。
※2 Get-AppxPackageは一回実行してみてみると何なのかわかると思われる。処理実行時間が長いので注意。

うまくいった、とりあえず今日はここまで。