OmniAICreator/Qiita-1.07M huggingface dataset:
docker composeとmakeでDjango開発環境を半自動化

#　目標
1 コマンドで Django アプリケーションの起動・停止が行えるようにする。

# 1. Dockerfileを書く
ベースは Python の公式イメージ

```dockerfile

FROM python

ENV PYTHONUNBUFFERED 1

RUN mkdir /code
WORKDIR /code

ADD requirements.txt /code/
RUN pip install -r requirements.txt

ADD . /code/

```

# 2. requirements.txtを書く
ここに書いた Python モジュールが自動でインストールされる。

```text
django
django-cors-headers
django-filter
django-graphql-jwt
graphene_django
djangorestframework
djangorestframework-simplejwt
isodate
```

# 3. docker-compose.yml を書く
今回はデフォルトの SQLite を使用するので、 db の指定はしない。

```yaml
version: "3"
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    env_file: docker-compose.env
    command: python manage.py runserver 0.0.0.0:8000
```

# 4. Makefile を書く
前項まででインフラのコード化は終了しているが、migrate や makemigration のコマンドがいちいち長い。(例: docker compose run --rm web python3 ~~~)

だから、make を使ってコマンドを短く省略するとうれしい。

```makefile
# start up server
up:
	docker compose up

# start up as background task
upd:
	docker compose up -d
	
# stop server
down:
	docker compose down

# access to container's terminal
shell:
	docker compose exec web bash

# create docker image
build:
	docker compose build

service=null
# create new project
startproject:
	docker compose run --rm web python3 manage.py startproject ${service}

# create new app
startapp:
	docker compose run --rm web python3 manage.py startapp ${service}

makemigrations:
	docker compose run --rm web python3 manage.py makemigrations

migrate:
	docker compose run --rm web python3 manage.py migrate

createsuperuser:
	docker compose run --rm web python3 manage.py createsuperuser
```

これで make ~~ で各種コマンドが使える。
バーチャルSNS、ClusterにUnityワールドをアップロードする方法

今回は、コロナ渦でよく使われるようになったClusterの波がこちらまでやってきたので、さっそく使っていきたいと思います。

#Unityのインストール
[こちら](https://store.unity.com/ja/download-nuo)から。
ライセンスを通し、Unityをインストール、そして新しいプロジェクトを作成します。
Unityのインストールの際は、AndroidやMacOS、Windowsのモジュールを追加しておきましょう。

忘れてしまった場合でも、以下から追加できます。
![add_module.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667272/6dcfec7a-6238-3c47-10b3-1e942b486146.jpeg)

``モジュールを加える``が見当たらない場合は下の``アンインストール``を選択後、[こちら](https://unity3d.com/jp/get-unity/download/archive)から同じバージョンを選び、緑色のUnity Hubと書かれたボタンを押せば解決します。

#Cluster用ワールドに必要なもの
Clusterにアップロードするためには以下の3要素が必須になります。
・SpawnPoint(プレイヤーが降り立つ場所)
・DespawnHeight(落下したプレイヤーが消滅する高さ、無限落下を防ぐ)
・Collider(衝突可能なオブジェクト、床や壁など)

Colliderは``GameObject->3D->Cube``を用意して板状に広げれば大丈夫です。
残りの二つはCubeを用意して板状に広げたり、大きさをなくしたりといった部分は同じですが、それに加えてコンポーネントの追加が必要になります。
``Inspector(ない場合はwindow->windowsから出す)->add component``からそれぞれ、``SpawnPoint``、``DespawnHeight``、と入力すると出てくると思いますので、それをEnterで追加します。

#Creator Kitの導入
最後に、ワールドをアップロードしましょう。
まずCreator Kitを導入します。
([こちら](https://clustervr.gitbook.io/creatorkit/installation/install-creatorkit)に書かれていますが、一応書いておきます。)
``Edit->Project Settings``を開きます。
そこから``PackageManager->Scoped Registries``を選択し、以下を入力し``Save``してください。

```
Name：Cluster
URL：https://registry.npmjs.com
Scope(s)：mu.cluster
```

次に、``Window->Package Manager``から``Packages``ウィンドウを開きます。
上部の``Unity Registry``をクリックして``My Registries``に変更します。
表示されたリスト内から ``Cluster, Inc.->Cluster Creator Kit``を選択して、``Install``ボタンを押してインストールを開始します。
UnityのメニューにClusterがあれば成功です。

#Worldのアップロード
あとは、アップロードするだけです。
Unityメニューから``Cluster->ワールド アップロード``を選択。
開いたウィンドウから、新規作成を選び、名前、説明、画像をセット。
そして``'ワールド名'としてアップロードする``というボタンを押せば完了です。
その後はワールド管理ページが設定によっては開かれますので、Clusterのアプリが入っていればワールドに入れます。
公開設定を変えることで、ほかの人も自由に入ることができます。
ワールドは50人までなので多人数を呼ぶなら500人まで入ることができるイベント用のステージを作ってもいいかもしれません。

#最後に
今回はUnityワールドをClusterにアップロードする方法を書きました。
最後まで読んでいただきありがとうございました。
【試してみた①】if文が1つ増えると、どのくらい遅くなるのか？？

# はじめに
実装していて気になったことを『試してみた』シリーズとして、書き溜めていきたいと思います。

# 検証内容 『if文が1つ増えると、どのくらい遅くなるのか？？』

# 前提
```bash
$ php -v
PHP 8.0.3 (cli) (built: Mar  4 2021 20:39:15) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.3, Copyright (c), by Zend Technologies
```

# 検証方法
- CLIで実行
- ループは1億回行う
- 速度計測は[こちら](https://qiita.com/ao_love/items/a2d8b8566d0426195002)を参考に

```php
$time_start = microtime(true);

// 計測したい処理

$time = microtime(true) - $time_start;
echo "{$time} 秒";
echo PHP_EOL;
``` 


#『if文が1つ』
```php
// 1億回
for ($i = 0; $i < 100000000; $i++ ) {
    if (true) {}
}
```

||実行速度(秒)|
|:-:|:-:|
|1回目|0.83141899108887|
|2回目|0.83102893829346|
|3回目|0.83084988594055|
|4回目|0.84071087837219|
|5回目|0.83305191993713|
|6回目|0.8305721282959|
|7回目|0.83240604400635|
|8回目|0.8325400352478|
|9回目|0.82936096191406|
|10回目|0.84361791610718|
|平均|0.8335557699|

## 『ifが2つ』
```php
// 1億回
for ($i = 0; $i < 100000000; $i++ ) {
    if (true) {}
    if (true) {}
}
```

||実行速度(秒)|
|:-:|:-:|
|1回目|1.0328588485718|
|2回目|1.0523581504822|
|3回目|1.0424981117249|
|4回目|1.0342919826508|
|5回目|1.0429739952087|
|6回目|1.0470108985901|
|7回目|1.0428569316864|
|8回目|1.0457961559296|
|9回目|1.0605390071869|
|10回目|1.060231924057|
|平均|1.046141601|

# 結果
1億回のループでは...
『if文が1つ増えると、**0.2秒** 程遅くなる』

```
1.046141601 - 0.8335557699 = 0.2125858307(秒)
```

また...
『if文1つあたりの実行速度は、**0.000000002秒** 程』

```
0.2125858307 / 100000000 = 0.000000002125858307 = 2 × 10^9(秒)
```

# おまけ 『if文の中にif文がある時』
```php
// 1億回
for ($i = 0; $i < 100000000; $i++ ) {
    if (false) {
        if (true) {}
    }
}
```

||実行速度(秒)|
|:-:|:-:|
|1回目|0.99202299118042|
|2回目|1.0408618450165|
|3回目|0.99025511741638|
|4回目|0.99592709541321|
|5回目|0.99485802650452|
|6回目|0.99443888664246|
|7回目|0.99625897407532|
|8回目|1.0110659599304|
|9回目|0.99769306182861|
|10回目|1.0038778781891|
|平均|1.001725984|

判定処理に入らなれけば、前者と同じくらいのスピードが出るかと思いきや、意外と遅くなりました...
単純に文字数が増えて、字句解析/構文解析に時間がかかるのでしょうか。それぐらいしか原因が思いつかないです。

# 所感
速度と可読性が裏と表の関係にある時、どちらを取るか迷いますよね。
「**if文が1つ増えるだけでは、さほど速度落ちないということ**」がわかったので、これからは可読性を取ろうと思います。

# まとめ
**if文が1つ増えるだけでは、速度はさほど変わらない**。結局、if文の評価内容、処理内容の方が実行速度に影響しそう。
GitとGitHubを基本からまとめてみた【随時更新】【用語一覧】

## GitHubとは?
GitHubとは、Gitというバージョン管理ツールを用いた開発者向けのサービスの事。
特徴：Web上からWebサービスやアプリなどを開発する際に必要なソースコードを確認して
編集及び編集日時や各データの内容などを簡単に管理できる。

## Gitとは?
GitとはGithub上で利用できる、ソースコードを管理するためのツールの事。
特徴：オンラインでもオフラインでもソースコード管理ができる。

### Gitの仕組み：リポジトリ
Gitでは『リポジトリ』という単位でソースコードのデータ管理を行う。
『リポジトリ』を基に履歴をたどってトラブルのある以前にソースコードを戻す、といった作業が可能。

#### ローカルリポジトリ
開発者側のGit環境にローカルで保存されている『リポジトリ』。
ローカルリポジトリを用意する際は新規にリポジトリを手元で作成する方法と、
一旦、リモートリポジトリからひな形としてデータをコピーして作成する方法がある。
必要になった時に、リモートリポジトリのほうに変更履歴を保存する。

#### リモートリポジトリ
管理の中心となるサーバー上に保存される『リポジトリ』。
ローカルリポジトリの作業内容をリモートリポジトリへアップロードすることで、
メンバー間のソースコード内容の共有が可能で、他メンバーの作業内容をダウンロードして参照できる。リモートリポジトリはGitHub上で簡単に作成できる。

## Gitで行う基本操作・機能

#### commit（コミット）
『commit（コミット）』はソースコードの編集内容をリポジトリへ記録して保存する行為。
上書き保存を行ってデータが消えないように処理を行う。

#### push（プッシュ）
リモートリポジトリへ作業内容を変更する行為を『push（プッシュ）』と呼ぶ。
ローカルリポジトリのデータをリモートリポジトリへプッシュする。

#### pull（プル）
『pull（プル）』は他の人のソースコード環境を自分の環境へ反映させたい時に使う。
リモートリポジトリが変更されている時に『pull』を利用すれば、ローカルリポジトリへ
リモートリポジトリの内容を反映できる。
自分のリポジトリの内容を最新にして開発の遅れをなくす機能。

#### branch（ブランチ）
統合を取りながら複数のメンバーでソースコードの編集を行う為のコマンド。
作業を枝分かれさせて分岐を行い、流れを紐づけながら保存できるのがポイントです。複数のプログラミング環境を用意することで動作のテストを行う、本番の環境を用意して動作させるといった使い分けが簡単にできるようになっています。

#### merge(マージ)
『マージ』は、Git において分岐した履歴を戻して統合する手段。
git merge コマンドは、git branch を使用して作成された、独立した複数の開発ラインをひとつのブランチに統合するコマンド。


## 参考サイト
[今さら聞けないGitHubとは？超基本のGitから使い方まで徹底解説](https://qeee.jp/magazine/articles/16022)
[Gitチュートリアルとトレーニング](https://www.atlassian.com/ja/git/tutorials)
【初心者向け】コピペで使えるシンプルなカウントダウンボタン

##コード
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="RwVGMvv" data-user="naostudy0" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/naostudy0/pen/RwVGMvv">
  start_button</a> by naostudy0 (<a href="https://codepen.io/naostudy0">@naostudy0</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

##説明
```html:html
<!-- ボタンを押すとcountDownが実行されます。(5)は秒数で、変更可能です。-->
<button id="start-btn" onclick="countDown(5)">スタート</button>

<!-- countDownにより、秒数や開始のメッセージが表示されます。 -->
<p id="text"></p>
```

```javascript:javascript
// 指定した秒数カウントダウンし、その後メッセージが表示されます。
function countDown(second) {
  // 何回もボタンを押すとおかしな挙動になるので、ボタンを1度押した後はボタンを非表示にしています。
  document.getElementById("start-btn").style.display = "none";

  // 秒数が0になるまでの処理
  if (second >= 0){
      /* 
　　　　　　　　　　　　　　　　　　setTimeoutはタイマー機能です。setTimeoutの中にsetTimeoutを記載することで、
         連続して動作させています。
         書き方は、setTimeout(実行する内容, 間隔); 間隔はミリ秒なので、1000で1秒です。 
　　　　　　　　　　　　*/
      setTimeout(function () {
          // id="text"に秒数を表示します。
          text.innerHTML= second;
          // 秒数を1減らします。
          second--;
          // もう一度countDownが実行されます。秒数は、second--;によって１秒ずつ減っていきます。
          countDown(second);
      }, 1000);
  //秒数が0になった時の処理
  } else {
    // id="text"にstartの文字を表示します。
    text.innerHTML= "start";
  }
}
```

## おわりに
JavaScriptの勉強も始めました。
簡単にコピペで使えそうなコードを公開していこうと思います。
interactivemarkerでstlを表示する

# 概要
interactivemaekerをrvizで表示させる際に、基本図形ではなく、任意のSTLを表示させました。．

# 実行環境

| Soft and Hard       |       バージョン | 
|:-----------------:|:------------------:|
| Ubuntu             |              20.04 |    
| ROS               |              noetic |  


# 説明
interactivemarkerでstlを表示させる際には、markerクラスのメンバにstlを使う設定を指定します。
package nameには、stlがあるパッケージ名、stl directory nameはstlがあるディレクトリ名、stl file nameにはstlのファイル名を指定します。

```python3
marker = Marker()

# mesh fileを使用する設定にする
marker.type = Marker.MESH_RESOURCE
# 表示させるmesh fileのpathを指定する
marker.mesh_resource = "package://（package name）/ (stl directory name) / (stl file name )
```

[こちらのリポジトリ](https://github.com/SOutaHI/interactive_stl_marker)から試すことが可能です.

![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/156ff731-efb7-d05e-af0c-9f0c62667cb4.png)


#参考
http://wiki.ros.org/ja/rviz/Tutorials/Interactive%20Markers%3A%20Basic%20Controls
Macのキーボード設定

#キーボード左下のキーをCtrl（Cmd）にする設定

####MacキーボードCommandキーの位置をWindowsキーボードCtrlキーの位置と同じにしたい方向け（Cmdキーを左下に持ってきたい人）

　1.システム環境設定を開く
　2.キーボードを開く
　3.キーボードタブ内の右下にある「修飾キー...」をクリックする
　4.Caps LockをCommandに変更する※
　5.OKを押す
　※使用しているキーボードによって配置が違う場合があるため注意



#Macのキーボード入力をWindows風にする設定

####Enterキーを2回押すというのが煩わしい方向け

　1.システム環境設定を開く
　2.キーボードを開く
　3.入力ソースタブ内をスクロールして「Windows風のキー操作」にチェックをする
イメージマップ(クリッカブルマップ)を超簡単に拡大縮小する方法

<h2>概要</h2>
<p>
イメージマップをレシポンシブにする方法で検索すると<br/>
「jQuery-rwdImageMaps」を利用する方法が圧倒的に多いのですが<br/>
もっと簡単な方法を見つけました。（一部では常識なのかもしれませんが...）
</p>
<p>
とにかく「jQuery」も「jQuery-rwdImageMaps」も不要です。<br/>
javascriptで拡大縮小を指定すればレシポンシブにも対応できます。<br/>
※レシポンシブに対応する方法は今回は割愛
</p>

<h2>方法</h2>
<p>
CSS の transform を設定するだけです。<br/>
※画像の左上を原点として1.5倍に拡大する例です。
</p>
<pre>transform-origin:left top;
transform: scale(1.5,1.5);</pre>

<h2>例</h2>
<pre>&lt;html&gt;&lt;head&gt;
&lt;style&gt;
  img{
    transform-origin:left top;
    transform: scale(1.5,1.5);
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;&lt;img src=&quot;（画像URL）&quot; alt=&quot;サンプル&quot; usemap=&quot;#example&quot; width=&quot;500&quot; height=&quot;200&quot;&gt;&lt;/p&gt;
&lt;map name=&quot;example&quot;&gt;
  &lt;area shape=&quot;rect&quot; coords=&quot;50,50,150,150&quot; href=&quot;map1.html&quot; alt=&quot;四角&quot;&gt;
  &lt;area shape=&quot;circle&quot; coords=&quot;250,100,50&quot; href=&quot;map2.html&quot; alt=&quot;丸&quot;&gt;
  &lt;area shape=&quot;poly&quot; coords=&quot;400,50,450,150,350,150&quot; href=&quot;map3.html&quot; alt=&quot;三角&quot;&gt;
&lt;/map&gt;
&lt;/body&gt;&lt;/html&gt;</pre>

<h2>備考</h2>
<p>間違いなど何かお気づきの点などございましたら、ご指摘いただけますと幸甚です。</p>
簡単localhost:3000をスマホ（iPhone）でも確認する方法

#　スマホ(iPhone)でローカル環境を見ることが出来る
###　きっかけ
AWS（インフラ）の仕事をメインにしていますが、週末は__RubyOnRails__をつかってアプリケーションの構築を学習しています。
Railsアプリ開発中に、ターミナル画面から__rails s__を利用して、Web画面での見え方を確認することはあったのですが、スマホからローカル画面の見え方を確認したいと思い調べることにしました。
___
### 1.同じWi-FiでPC(Mac)とスマホ(iPhone)を接続する
最初に自分は、PCを5Gで、スマホを2Gを選択していたため、接続できなかったことはここだけの話し。

・PCでの画面
![スクリーンショット 2021-07-11 9.23.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/c4db5d7d-b189-79ea-11c7-bd8bec81f5b6.png)

・スマホ（iPhone）での画面
![スクリーンショット 2021-07-11 9.28.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/07a715f2-76fd-7720-9661-88685ddaaf33.png)
____
### 2.PC(Mac)のIPアドレスを確認する
1.システム環境設定を選択する
![スクリーンショット 2021-07-11 9.39.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/2238a9a1-8a28-6326-d253-b36cfb792f13.png)

2.ネットワークを選択する
![スクリーンショット 2021-07-11 9.40.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/0f1f92f6-0399-d39d-c0f1-27c811edec92.png)

3.IPアドレスの確認
![スクリーンショット 2021-07-11 9.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/70172c5e-8f3d-f972-e484-ba5dc87dc2bf.png)
____
### 3.PC(Mac)のターミナルで『bundle exec rails s -b XXX.XXX.XXX.XXX』を打ち込んででサーバを起動する


![スクリーンショット 2021-07-11 10.07.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/5bf96332-801e-9286-350d-bf1da4f9268d.png)

__※『Rails s』で起動している記事もありました。自分の場合は『bundle exec』がないと、スマホでは見ることが出来ませんでした。RailsのPathの都合かと思っています。__
____
### 4.スマホ(iPhone)で 【IP:ポート番号】 にアクセスする
ローカル環境を確認することが出来れば完了です
![スクリーンショット 2021-07-11 10.21.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694365/30a77989-aa9e-16d9-14b7-95a8772abf85.png)

____
###　おわりに
振り返ると、なぜ「今までスマホ（iPhone）をつかって確認する」ということをしなかったのか不思議に思います。当たり前を改めて定義するというのでしょうか？こうやって改めて見直していくことが学習の面白みなのかもしれないと感じました。
能書きはさておき、これでレスポンシブの状況を実機で直ぐに確認できるのは嬉しいすぎる。是非とも皆さんの開発ライフが捗ればいいかと存じます。
____
### 参考記事
[Qiita記事【localhost をスマホ実機で確認する方法】](https://qiita.com/nanarya/items/8d01dfb4de434e7b8acc)
[Qiita記事【localhostにスマホから繋げてみた!!(Mac編)】]
(https://qiita.com/TeppeiMimachi/items/8f19e111cd1766a7d084)
[Qiita記事【bundle execって必要なの?】](https://qiita.com/d0ne1s/items/fa2dafcee02e963fe997)
internal.ReadableとNodeJS.ReadableStream

mp4やmp3をインターネット上から取得して、その音声をDiscord.jsでBotに流し込むためにちょっと躓いたことがあったのでメモ書き
両方とも、Streamであることは変わりないのだけど、簡単に言えば古いのと新しいのという関係性らしい

## internal.Readable
新しい形式のStream。Discord.jsではこちらが使われている。大体新しいライブラリはこっちのStreamを吐くことが多いみたい。

## NodeJS.ReadableStream
古い形式のStream。node-fetchのbodyとかは(なぜか)こっちの形式でデータを返してくる。

## 互換性
互換性はない。ただし、古い形式である`NodeJS.ReadableStream`を新しい`internal.Readable`に変換(ラップ)することは可能([この記述を公式ドキュメント内で見つけるの](https://nodejs.org/api/stream.html#stream_readable_wrap_stream)にかなり時間がかかった...)

### 変換(ラップ)の例
Discord.jsで作るBotに搭載する実例をもとにサンプルコードを載せておく

```TypeScript:example.ts
import { Client, Message, VoiceChannel } from 'discord.js';
import fetch from 'node-fetch';
import { Readable } from 'stream';

const client = new Client();

client.on('message', async (message: Message) => {
  if (message.author.bot) return;
  const voiceChannel = message.member?.voice.channel;
  if (message.content === 'play' && voiceChannel) {
    musicPlayAndStreamConvert(voiceChannel)
  }
});

async function musicPlayAndStreamConvert(voiceChannel: VoiceChannnel) {
  const res = await fetch('<mp3 file url>');
  const readableStream = new Readable().wrap(res.body);
  const connection = await voiceChannnel.join();
  const dispatcher = connection.play(readableStream);
  this.dispatcher.on('finish', () => {
    connection.disconnect();
  })
}

void client.login('<bot token>');
```

## おわりに
私自身も理解が浅いので、間違ってる部分があれば突っ込んでもらえると。
あとは、私と同じ問題に躓いて諦めない人が増えますように(少し遅い七夕)。
Flutter × Firestore 追加、更新、取得

## 値を追加する

Firebaseのusersコレクションのフィールド値に値を追加したいときは以下のように書きます。
今回はnameというフィールド値に名無しのごんべを追加します。＊　addは任意のドキュメントIDが生成されます

```dart

FirebaseFirestore.instance.collection('users').add({
      'name' : '名無しのごんべ'
});

```

![スクリーンショット 2021-08-28 12.06.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295942/fd37ab69-9b2d-5527-d590-765589a2b751.png)


setはドキュメントIDを指定して追加・一括更新をすることができます。

```dart

FirebaseFirestore.instance.collection('users').doc(uid).set({
      'name' : '名無しのごんべ'
});

```

## 値を更新する

フィールド値を更新するには doc(uid) とドキュメントIDを指定してkeyにフィールド値、valueに追加したい値を挿入します。

```dart

FirebaseFirestore.instance.collection('users').doc(uid).update({
    'name' : 'ymktmk'
});

```


## 値を取得する

QuerySnapshotは複数のドキュメントIDを取得することができます。複数のドキュメントIDを1個ずつforEachで回しています。

```dart

FirebaseFirestore.instance.collection('users').get().then((QuerySnapshot snapshot) {
   snapshot.docs.forEach((doc) {
     /// usersコレクションのドキュメントIDを取得する
     print(doc.id);
     /// 取得したドキュメントIDのフィールド値nameの値を取得する
     print(doc.get('name'));
   });
});

```


DocumentSnapshotは単一のドキュメントIDを取得します。そのため doc(uid) とドキュメントIDを指定します

```dart

FirebaseFirestore.instance.collection('users')
     .doc(uid).get().then((DocumentSnapshot snapshot) {
     print(snapshot.get('name'));
});

```






## リアルタイムに取得する

リアルタイムで取得するときにはgetではなくsnapshotをつけます。

```dart

FirebaseFirestore.instance.collection('users')
   .snapshots().listen((QuerySnapshot snapshot) {
     snapshot.docs.forEach((doc) { 
       print(doc.get('name'));
     });
});

```

```dart

FirebaseFirestore.instance.collection('users')
      .doc(myId).snapshots().listen((DocumentSnapshot snapshot) {
      print(snapshot.get('name'));
});

````



## StreamBuilderを使う

ぶっちゃけStreamBuilderを使ってリアルタイムでViewに表示させるのがいいかもし れません

```dart

class Example extends StatelessWidget {

  final myId = FirebaseAuth.instance.currentUser!.uid;

  @override
  Widget build(BuildContext context) {

    return StreamBuilder<DocumentSnapshot>(
        stream: FirebaseFirestore.instance.collection('users').doc(myId).snapshots(),
        builder: (BuildContext context,  AsyncSnapshot<DocumentSnapshot> snapshot) {
          if (snapshot.hasData) {
            return Text(snapshot.data!['name']);
          } else {
            return Container();
          }
        }
    );
  }

}

```

以下のようにも書くことができます。stream: MeetController.getMatch(), ではStream<List<RoomModel>>を返すようなモデルを作成すればOKです。


```dart

class Example extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<RoomModel>>(
      stream: MeetController.getMatch(),
      builder: (BuildContext context, AsyncSnapshot<List<RoomModel>> snapshot) {

        print(snapshot.data![0].roomId);
             
      }
    );
  }
}

```
stateのtypeを指定しないと怒られるようです。→　Property 'value' does not exist on type 'Readonly<{}>'

Componentのtypeはdefaultで以下のようになっているから自前のstateのtypeを指定
してあげないと「Property 'value' does not exist on type 'Readonly<{}>'
」というように怒られるようです。
![Screen Shot 2021-07-11 at 10.07.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497426/0619aeb5-8f4e-68b0-2961-975debb5ca70.png)
参考リンク
https://stackoverflow.com/questions/47561848/property-value-does-not-exist-on-type-readonly
【iOS】Universal Links実装時にハマったこと

Universal Linksを実装した際にいくつかハマったことがあったので、覚書として残しておきます。

# 【おさらい】 Universal Linksとは
* iOS9〜利用可能
* 通常のWeb URL経由でアプリを起動できる
    * アプリがインストール済み →アプリが起動する
    * アプリが未インストール →Webページが開く
* Custom URL Schemeとは違って、`test-app://`のような起動用URLは不要
* 「アプリを開きますか？」などのポップアップは表示されず、シームレスにアプリに遷移する

参考: [URLスキーム・独自ディープリンク実装に代わる、Universal Links(iOS 9で導入)でより良いUXを実現 - Qiita](https://qiita.com/mono0926/items/2bf651246714f20df626)
参考: [iOS ディープリンク（Custom URL Scheme）でアプリを起動する | DevelopersIO](https://dev.classmethod.jp/articles/ios-custom-url-scheme/)

# ハマりポイント
## 1. `apple-app-site-association`ファイルが反映されるタイミング（リリース版）
Universal Linksの仕組みは「`Associated Domains`で設定したドメインの`apple-app-site-association`ファイルが、アプリの初回起動時にダウンロードされ、ファイルに記載のあるパスのみ、タップ時にアプリに遷移するようになる」というものです。
では、その後`apple-app-site-association`ファイルの内容に変更を加えた場合、反映されるのはいつでしょうか？

[apple-app-site-association caching? | Apple Developer Forums](https://developer.apple.com/forums/thread/6972)
[Universal Link not working on TestFlight | Apple Developer Forums](https://developer.apple.com/forums/thread/108339)
上記のサイトによると「**アプリのインストール時・更新時に、アプリ側で`apple-app-site-association`ファイルがフェッチされる。その後、数日間に1回程度継続して取得される**」そうです。
なお、これはAppStoreからリリース版アプリをインストールした場合のことであり、TestFlight版アプリの場合は少し事情が異なります（後述）。

アプリインストール済みのユーザーにすぐに変更を届けたい場合、アプリのアップデートや再インストールをしてもらうのが確実かもしれません。

## 2. `apple-app-site-association`ファイルが反映されるタイミング（TestFlight版）
「`apple-app-site-association`ファイルを書き換えたので、TestFlightを配布して検証したい」なんてことがあると思います。

[Universal Link not working on TestFlight | Apple Developer Forums](https://developer.apple.com/forums/thread/108339)
上記サイトにあるように、**TestFlight版アプリで`apple-app-site-association`ファイルがフェッチされるまでには、インストール後15分〜2時間程度かかります**。

インストールしたからと言ってすぐにはすぐには反映されないので、お茶でも淹れて気長に待ちましょう:tea:

## 3. `apple-app-site-association`ファイルの`paths`の優先度
とあるサイトの全てのページをUniversal Links対応させたい場合、`apple-app-site-association`ファイルの`paths`は以下のようになります。

```json
"paths": ["*"]
```

しかし、そのサイトの中で`/hoge/`にだけは遷移させたくない場合、どの位置に記述したらいいでしょうか？
`paths`は**上に書いてある条件が優先される**ため、以下のようにする必要があります。

```json:正しい
"paths": ["NOT　/hoge/", "*"]
```
以下だと`"*"`が優先されてしまい、除外が効かないので注意です。

```json:正しくない!!
"paths": ["*", "NOT　/hoge/"]
```

参考: [apple-app-site-associationのpaths(遷移対象パス)の作り方（UniversalLinks対応） - Qiita](https://qiita.com/keroppi0_0/items/1a7fab4a8cc78412d30c#white_check_mark-%E4%BE%8B%EF%BC%95%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%92%E9%81%B7%E7%A7%BB%E3%81%95%E3%81%9B%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84)

## 4. 同一ドメイン上のUniversal Linksの有効性
**`https://hoge.com`というWebサイトがあり、`https://hoge.com`をUniversal Linksの対象パスに設定した場合、サイト上からアプリへの遷移はできません。**

参考: [Swift 同一ドメインでのユニバーサルリンク(Universal Links)は動作しないので注意 - Qiita](https://qiita.com/takashico/items/dafb0a749bca8156ddd6)

## 5. SNS上のUniversal Linksの有効性
**一部のSNSアプリに投稿されたURLは、タップしてもアプリへの遷移ができませんでした**。

* LINE App →タップしてもLINE内のWebViewが開くだけ :heavy_multiplication_x:
* Facebook Messenger App →タップしてもMessenger内のWebViewが開くだけ :heavy_multiplication_x:
* Apple純正のメッセージApp →タップすると正常にアプリが起動した :o:
レスポンスはすぐ返して、処理は裏で継続する方法：メールの送信など重い処理に

ログインなどでタイムラグがあってはいけないときなど、レスポンスだけはすぐに返したいときがあります。別プロセスで走らせればいいやんといったらその通りなのですが、バックエンドにめちゃくちゃ弱い僕はexec()なんて関数は知りません。知っていても使うと、ミスって永遠にプロセスが落ちなくなりそうです。。
そこで探したらいい感じの実装方法がありました！でも初心者の調べた範囲なので実装するときはちゃんと自分で調べてください（自己責任でお願いします）。あと、ご指摘もよろしくお願いします。
# コードサンプル
```php:PHP
<?php
ignore_user_abort(true); // レスポンス後も処理を続行できるように
set_time_limit(100); // ずっと走ると怖いので 100 秒後にタイムアウト
ob_start(null, 0, PHP_OUTPUT_HANDLER_FLUSHABLE | PHP_OUTPUT_HANDLER_REMOVABLE); // 出力をバッファっていう感じで制御できるように、好きなタイミングで吐けるようにオプションをつけておく

print "Hello, Qiita!"; // なんか出力する

// echo "\r\n"; // うまくいかないときは改行させて
header( 'Content-length: ' . ob_get_length() ); // 文字数をヘッダに出力
header("Connection: close"); // コネクションを切る

while (ob_get_level() > 0) { // バッファが溜まってたら
    ob_end_flush(); // 出力して終了
}
flush(); // サーバーから出力
if (session_status() !== PHP_SESSION_NONE) { // セッションが始まってたら
    session_commit(); // セッションを保存
}

// 重い処理
sleep(5);
file_put_contents("./example.txt", "Hello, File!");
```
# 参考文献
- PHP オンラインマニュアル（2021/7/11 参照）
（ https://www.php.net/manual/ja/function.ignore-user-abort.php 、 https://www.php.net/manual/ja/ref.outcontrol.php 、 https://www.php.net/manual/ja/function.flush.php ）
- PHPでレスポンスを出力した後に処理を続ける方法 - 昼メシ物語（2021/7/11 参照） 
（ https://blog.mirakui.com/entry/20090313/1236961372 ）
- 【PHP】レスポンスを返した後も処理を続ける - stylagy（2021/7/11 参照）
（ https://ameblo.jp/stylagy/entry-12425262997.html ）
キーボードでファイル操作できるからVSCodeのSidebarがいらない

# はじめに

Youtubeに、キーボード（ショートカットや拡張機能）でVSCodeのファイル操作を紹介する動画を見つけた。

https://www.youtube.com/watch?v=s3H6PmB4SZ4

ファイルの開く、閉じる、切り替え、作成、削除、名前変更、移動などの操作がすべてキーボードで操作するので、Siderbar経由の操作より速くなる。

この記事は、動画で紹介した操作のメモです。
すべてのショートカットはマックブック版VSCodeで確認済み。

# 詳細

## ファイルを開く、閉じる、切り替え

**ファイルを開く**

1. CMD＋P
1. ファイル名を入力で探す　

**ファイルを閉じる**

1. CMD+W

**開いたファイルを切り替え**

1. Control Tab

## ファイルの作成、削除、名前変更、移動

これから拡張機能が必要

**ファイルの作成**

拡張機能[advanced-new-file　Extension](https://marketplace.visualstudio.com/items?itemName=patbenatar.advanced-new-file)がおすすめ

インストールあと：
1. CMD + Shift + PでCommand Paletteを開く
2. Advanced New Fileを入力
3. path を入力
4. ファイル名を入力

**ファイルの削除、名前変更、移動**

拡張機能[File Utils Extension](https://marketplace.visualstudio.com/items?itemName=sleistner.vscode-fileutils)がおすすめ

削除：
1. CMD + Shift + PでCommand Paletteを開く
2. File: Deleteを入力
3. 確認してファイルを削除

名前の変更：
1. CMD + Shift + PでCommand Paletteを開く
2. File: Renameを入力
3. 新しいファイル名を入力し、ファイルを名前変更

ファイルの移動：
1. CMD + Shift + PでCommand Paletteを開く
2. File: Move
3. 新しいパスを入力しで、ファイルを移動
中卒・業界未経験者がJava学習ロードマップを作った方法

<a href="#hajimeni">・はじめに</a>
　　<a href="#mokuteki">①目的地を決める</a>
　　<a href="#a">②Google先輩に聞く</a>
　　<a href="#b">③複数メンターに聞く</a>
　　<a href="#c">④聞いた情報についてまたググる</a>
　　<a href="#e">⑤勉強法について勉強する</a>
　　<a href="#f">⑥改善を繰り返す</a>
<a href="#g">・さいごに</a>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597725/1bb71adb-66f8-1502-ca83-848d5b4cfedf.png)

<h2 id="#hajimeni">はじめに</h2>
はじめまして、ながけいといいます。いきなりですが私の略歴はこんな感じです。


<h5>・27歳現場作業員</h5>
<h5>・中卒、業界未経験だがプログラマーへ就職したい</h5>
<h5>・2021年6月からプログラミング学習を独学で開始</h5>
<h5>・言語はJava</h5>


金銭的な都合でプログラミングスクールには通わず、独学でJavaを学習しています.
業界未経験が学習ロードマップを作る方法について、私が調べた限りで解説していきます。<h5>（あくまでまだ結果を出していない初心者が偉そうに語っているだけなので、嘘をつきまくっている可能性大です。あまり信用しないでください・・・）</h5>

<h2 id="#mokuteki">目的地を決める</h2>
私の場合は就職が目的なので、求人数が最も多い（らしい）Java言語を選択しました。難易度は高い方だという記事を幾つか見かけましたが、なるべく間口が広い所に行きたかったので、そこはいったん無視で決定です。<h5>（おい）</h5>

<h2 id="#a">Google先輩に聞く</h2>
Javaを学ぶといっても何が何だかサッパリなので、学習の進め方についてGoogle先輩に聞きました。
ネットには色んな情報が散乱しているので、<b>”どの情報を信用するか問題”</b>で引っ掛かりましたが、最終的には、某プログラミングスクールのブログに記載してある学習ロードマップを参考にし、一旦自分なりのロードマップを作成しました。

某プログラミングスクールのブログの情報を信用した理由は、
<b>「プログラミングを教えるプロが、適当な情報を記載していると、スクールの評判が落ちて入会する生徒も減っていくから、ある程度は信用できる内容を書いているだろう」といった理由です。</b>
(偉そう)


<h2 id="#b">複数メンターに聞く</h2>
次に、MENTAというサービスを利用し、複数のメンターの方にこの学習ロードマップが正しいかどうか質問をしました。複数の方に質問させて頂いた理由は、<b>”その人に教えて頂いた学習方法が自分に合っているか分からない為、一人ではなく複数”</b>に聞いています。

<h2 id="#c">聞いた情報についてまたググる</h2>
教えて頂いた学習方法についても、再度Google先輩に聞きました。疑いすぎだろと思われるかもしれませんが、,<b>学習ロードマップが間違っていれば、多くの時間を無駄にしてしまう</b>ので”念には念を”といった感じでやっています。

<h2 id="#e">勉強法について勉強する</h2>
ある程度、ロードマップが完成したら、次は<b>勉強の仕方</b>を勉強しました。
「プログラミングを独学して、就職をする」為の道筋はある程度見えてきましたが、<b>一番肝心な「勉強の仕方、独学の仕方」を知らずに我流で勉強を進めても、無駄が多くなるだろうといった感じです。</b>ちなみに、調べた結果使っている勉強法はDAIGOさんお勧めのメンタルモデルです。

<h2 id="#f">改善を繰り返す</h2>
学習ロードマップが正しいか、独学法が正しいか、毎日疑い改善を重ねていきます。

<h2 id="#g">さいごに</h2>
<b>目的地が明確に決まっていなければどこに辿り着けないし、道筋が間違っていれば、そもそもたどり着けないもしくは、無駄に時間と労力がかかる</b>かなーといった感じで、学習ロードマップには力を入れてみました。
冒頭でも説明しましたが、私は業界未経験で結果を出していないヤツなのでこの記事の中でも多分ウソをついているかもしれません・・・。（あまり信用しないでください）

１ミリでも参考になるところがあれば幸いです。
Docker コマンド　メモ

python manage.py collectstatic

作成するファイル(3つ)
Dockerfile
requirements.txt
docker-compose.yml

Djangoプロジェクト作成

```
docker-compose run --rm web django-admin.py startproject mysite .
```

複数Dockerコンテナを起動

```
docker-compose up
```


マイグレーション

```
$ docker-compose run --rm web python3 manage.py makemigrations

$ docker-compose run --rm web python3 manage.py migrate
```

dockerビルド

```
$ docker-compose build
```

docker実行

```
$ docker-compose up
```

コンテナ一覧表示

```
docker ps -a
```

コンテナを起動する

```
$ docker start [コンテナID]
```

コンテナの削除

```
$ docker rm [コンテナID]
```

停止コンテナ一括削除

```
<=1.12

$ docker rm `docker ps -f "status=exited" -q`
>=1.13

$ docker container prune
```

docker-compose.ymlの
services:
  アプリ名(webなど):

```
Sudo docker-compose run web python manage.py makemigrations
Sudo docker-compose run web python manage.py migrate
```

dockerのimage全て削除

```
docker rmi $(docker images -q) -f
```

docker 再起動

```
osascript -e 'quit app "Docker"'

open /Applications/Docker.app
```

#メモ
dockerを使用し、postgresqlを実装する場合
自身のローカル環境のpostgresqlは停止させること
(brew services stop postgres)
理由は、port5432がpostgresqlとdocker-composeで競合するため

dockerの再起動

```
sudo launchctl start docker
```
M5StickCのボタン反応の検出感度向上を2ステップで目指します

2ステップでM5StickCのボタン反応の検出感度向上を目指します

# 1 はじめに  
ボタン状態更新はM5.updateをコールして行います  
しかし、M5.updateのコールをloopタスクでポーリングで行うと、
ポーリング周期によっては状態変化を取りこぼすことがありました  
そこで、ボタン状態変化を割り込みで検知し、割り込みからM5.updateをコールするようにしました  

取りこぼしが気持ち減った気がするけど  
本当に減ったのかな？？？  


# 2 準備  
ステップ1 割り込み登録  

setupに下記を追加します  

```
  attachInterrupt(digitalPinToInterrupt(buttonA_GPIO), buttonA_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(buttonB_GPIO), buttonB_isr, CHANGE);
```

| パラメータ | 条件 |
| - | - |
| LOW | ピンがLOWのとき発生
| CHANGE | ピンが変化したときに発生
| RISING | ピンがLOWからHIGHに変わったときに発生
| FALLING | ピンがHIGHからLOWに変わったときに発生 

ステップ2 割り込みハンドラ実装  

```
static void buttonA_isr(void) {
  M5.update();
  Serial.printf("A interrupt %d\n", millis() );
}
 
static void buttonB_isr(void) {
  M5.update();
  Serial.printf("B interrupt %d\n", millis() );
}
```

準備完了です  


# 3 コード全体  

```
#include <M5StickC.h>
#include <LovyanGFX.hpp>

static LGFX lcd;

// button gpio number
const uint8_t buttonA_GPIO = 37;
const uint8_t buttonB_GPIO = 39;

static void buttonA_isr(void) {
  M5.update();
  Serial.printf("%d A interrupt\n", millis() );
}
 
static void buttonB_isr(void) {
  M5.update();
  Serial.printf("%d B interrupt\n", millis() );
}

void setup() {

  // put your setup code here, to run once:
  Serial.begin(115200);
     
  // Initialize the M5Stack object
  M5.begin();
 
  lcd.init();                       // 初期化

  // START
  lcd.fillScreen(BLACK);
  lcd.setCursor(10, 10);
  lcd.setTextColor(WHITE);
  lcd.setTextSize(1);
  lcd.printf("START");

  attachInterrupt(digitalPinToInterrupt(buttonA_GPIO), buttonA_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(buttonB_GPIO), buttonB_isr, CHANGE);

}

void loop() {
  // put your main code here, to run repeatedly:

  if(M5.BtnA.wasPressed() != 0 ) {
    Serial.printf("%d was pressA\n", millis());
    lcd.println("was pressA");
    delay(10);
  }

  if(M5.BtnA.isPressed() != 0 ) {
    Serial.printf("%d is pressA\n", millis());
    lcd.println("is pressA");
    delay(10);
  }

  if(M5.BtnB.wasPressed() != 0 ) {
    Serial.printf("%d was pressB\n", millis() );
    lcd.println("was pressB");
    delay(10);
  }

  if(M5.BtnB.isPressed() != 0 ) {
    Serial.printf("%d is pressB\n", millis() );
    lcd.println("is pressB");
    delay(10);
  }

}
```

# 4.結果  

実験でボタンを連打しても検出もれをしなくなった  
良かった  

```
18797 A interrupt
18803 was pressA 
18903 is pressA
18967 A interrupt
23147 B interrupt
23153 was pressB
23263 is pressB
23294 B interrupt
```
node.js で PN532 を使ってNFCを読む

このあいだ、Raspberry pi で node.js + typescriptで書いてるアプリでNFCを読む機会があり、調べたのでメモ。

## ハードウェア

NFCリーダーはこれ

https://wiki.seeedstudio.com/Grove_NFC/

中身は PN532

これを、Raspberry Pi のGPIOピンヘッダにGroveコネクタ生やすやつで接続した。こういうの。 
https://amzn.to/3wwxkSB


## UART を使用可能にする
Raspberry Pi 3以降ではBluetoothの接続でuartを使っているために、そのままではuartが使えない(これ知らずに結構時間をロスした...)。

Device Tree Overlay の miniuart-bt で対処した。

以下など参照。

https://www.ingenious.jp/articles/howto/raspberry-pi-howto/gpio-uart

https://qiita.com/hidenorly/items/f6ffe79fb6f81740eff3

## node.js

PN532のデバドラは以下のライブラリを使用。

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

使い方はこんな感じ。

```javascript
import SerialPort from 'serialport';
import pn532 from 'pn532';

const DEVICE_FILE_PATH = '/dev/serial0';
const SERIAL_OPTION = { baudRate: 115200 };
const serialPort = new SerialPort(DEVICE_FILE_PATH, SERIAL_OPTION);
const rfid = new pn532.PN532(serialPort);

// Poll for a tag
rfid.on('ready', async () => {
    console.log('Listening for a tag scan...');
    rfid.on('tag', (tag) => {
        console.log(tag);
        console.log('tag:', tag.uid);
    });
});
```

動かすとこんな感じ。

![Screen Shot 2021-06-03 at 0.39.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52410/8e0ad5be-c4bd-e8ef-fd8d-6531dc4b0e2e.png)

実際には、上記をラップしたdomainオブジェクト作成して、tagを検知した時にeventemitterで飛ばしてる。
エンジニアおすすめショートカットキー

## エンジニアおすすめショートカットキー
ここに随時おすすめのショートカットキーを載せていきます！
もし面白い、マニアックなの知ってたらコメントでお願いします。

### Mac 
| キー 　　　　| 挙動 | 
|:-----------|:------------|
| command + ctrl + F | 拡大/縮小 |
| command + space | Spotlightの起動 |
| Shift + Command + 4 + （control） | 指定範囲のキャプチャ（controlを入れるだけでその後ctrl+Vで貼り付け可能） |

### Windows
可変多次元配列テスト

可変多次元配列テストのプログラムを作りました。



```java
package nogizaka;

//可変配列のテスト処理

public class Manatsu {
	public static void main(String[] args) {
		String[][] array2 = {{"まなちゃん","真夏さん","まなったん"},
				            {"キャプテン","マナハラ","ずっきゅん","あざとい","女子校カルテット"},
							{"真夏さんリスペクト軍団","黒石さん"}};
		System.out.println(array2[0].length);
		System.out.println(array2[1].length);
		System.out.println(array2[2].length);
		for(int i=0;i<array2.length;i++) {
			for(int j=0;j<array2[i].length;j++) {
				System.out.println(array2[i][j]);
			}
		}
	}
}
```
pyinstallerのメモ

## 作成するときは仮想環境で

普通に作成したらexeの実行から動き出すまで、
10秒以上かかりフリーズしたのか心配になりました。

仮想環境を作成してそのままexeファイルを作成すると
必要なライブラリのフォルダが少なくなるのか軽くなりました。

参考
https://qiita.com/plumfield56/items/3296b24fea4ea5bbbbcf


## pandasを使うときは--hidden-importオプションをつける

この記事を参考にしました。
https://stackoverflow.com/questions/47318119/no-module-named-pandas-libs-tslibs-timedeltas-in-pyinstaller


私の場合は下記のエラーが表示されました。

```
no module error named 'pandas._libs.tslibs.base'
```

なのでexeファイルを作成時に下記のコマンドへ変更したら問題なく動くようになりました。

```
pyinstaller --onedir --onefile --hidden-import pandas._libs.tslibs.base myScript.py
```

## オプションについて

なぜ--ondirを付けたのか自分でもわからず調べたがぱっとわからなかったので、
必要なタイミングで調べて追記予定

https://pyinstaller.readthedocs.io/en/stable/usage.html#what-to-generate


## pandasからのフォルダの保存

保存先の絶対パスを作成するのに`os`を使用しました。
seleniumでドライバーを指定するのにも同じような書き方をします。

```py
import pandas as pd
import os

df = pd.DataFrame(data)

file_name = f'\\{ファイル名}.csv'
path = os.getcwd() + file_name # 保存先のパスをexeファイルと同じにする

df.to_csv(path, encoding="utf-8_sig", index=False)
```


これ気になったので次回触るときに参考にしたい

https://qiita.com/kunishou/items/b2e8754886107292926d
大園桃子卒業プログラム②

大園桃子プログラムを改良いたしました。（改良というより研修の仕事をしていたときに模範解答が間違っていたので正しいものを掲載いたします。元のJava研修で使用していたサイトは削除されているのを確認済みです(7月10日に確認いたしました)

```Java
package nogizaka;

import java.util.Scanner;

class Oozono{
	private String msg;
	Oozono() {}

	void Setter(String x) {
		this.msg = x;
	}
	String Oozono(String s,String t) {
		 String comment="";
		 if (s.equals("大園桃子")) {
			 comment = s + "、乃木坂卒業し、卒業後は" + t +"に帰ります";
		 } else {
			 comment = s +"は乃木坂46を卒業しないぞ!";
		 }
		 return comment;
	}
	String Getter() {
		return msg;
	}
}

public class Momoko {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		input_name();
		String line = sc.nextLine();
		input_pref();
		String ken = sc.nextLine();
		Oozono om = new Oozono();
		String msg2 = om.Oozono(line,ken);
		msg(msg2);
		om.Setter(line);
		String msg3 = om.Getter();
		msg(msg3);
	}
	static void input_name() {
		System.out.println("「大園桃子」と入力してください");
	}
	static void input_pref() {
		System.out.println("「鹿児島県」と入力してください");
	}
	static void msg(String x) {
		System.out.println(x);
	}
}

```

私が作成した模範解答です。この課題は「中級編」で、「例外処理」と「継承」はカリキュラムで「上級編」に入っているので例外処理と継承はここでは省略しております。
STM32F767とにおいセンサーAE-TGS8100で液晶表示 (Arduino)(AQM0802A)


目的
コロナ等を含め室内の空気のよごれをにおいを通して値数表示する。

構成
AE-TGS8100 K-15562
AQM0802A-RN-GBW P-06669

説明
3.3V系で使いたいのでマニュアルの式から
プログラムを作った。秋月の式と値が正しい事を確認した
0で割るとエラーになることを確認したので何でも良かったので
0を-1に変換した。現実的には、マイナスの大きい数になるので
区別が付くからマーいいか
そのままだとつまらないので液晶を付けた。
CO2センサーの為の前段階

main - 初期化
loop - 繰り返し処理
i2c_led_w - 2バイトI2Cに送る


![serial_nioi_767_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5e8a66d3-4784-b0cc-2ce5-1455051f91bb.jpeg)




```c++


#include <Wire.h> //I2C library

//STM32G031J6M6
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

// I2C  address. 
#define I2Cadr  0x3e  // 固定

char    data_read[2]={'@','t'}; //i2cバッファー
int     ii;                     //ループカウンター

char INIT_com[]={0x0,0x38,
0x0,0x39,
0x0,0x4,
0x0,0x14,
0x0,0x70,
0x0,0x56,
0x0,0x6C,
0x0,0x38,
0x0,0xC,
0x0,0x1,
0x40,0x41};

char INIT_cls[]={0x0,0x1};

void i2c_led_w(char *buff1){
  Wire.beginTransmission(I2Cadr);
  Wire.write(buff1[0]);
  Wire.write(buff1[1]);
  Wire.endTransmission();
  delay(2);
}//i2c_led_w

int adval = 0;
float sensor_r;

void setup() {

  delay(3000); //not delete

  //i2cの初期化
  Wire.begin(); // initialise the connection //767 UNO
  //Wire.begin(sdaPin,sclPin); //STM32G031J6M6

  //液晶の初期化
  for(ii=0;ii<11;ii++){
    i2c_led_w(&INIT_com[ii*2]);
  } //for

  Serial.begin(9600);
  pinMode(A0, OUTPUT);
}//setup

float v1;
float rs;

void loop() {
  digitalWrite(A0, HIGH);
  delay(1);
  analogReadResolution(12);
  adval = analogRead(A1);
  delay(1);
  digitalWrite(A0, LOW);

//Serial.println(adval);
//adval = 4096;
//adval = 300; //242mV 114.121kOME
//adval = 0;

if(adval == 0) {adval = -1;}

v1 = (    ((float)adval) * 3.300) / 4096.0;

//Serial.println(v1,3);

rs =( (3.0-v1)/v1 ) * 10.0;

Serial.println(rs,3);

/*
  if(adval != 0) {
    sensor_r = 6144.0 / adval - 10;
    Serial.println(sensor_r,3);
  } else {
    Serial.println("0");
  }//end if
*/
  delay(998);

  int s = rs;
  int n0,n10,n100;

  n10  = s / 10;           // 123 -> 12
  n0   = s - (n10 *10);    // 123 - 120 -> 3
  n100 = n10 / 10;         // 12  -> 1
  n10  = n10 - (n100 *10); // 12 - 10 -> 2
  
  //画面のクリア
  i2c_led_w(INIT_cls);

  //液晶に表示
  data_read[1] = '0' + n100;
  i2c_led_w(data_read);
  data_read[1] = '0' + n10;
  i2c_led_w(data_read);
  data_read[1] = '0' + n0;
  i2c_led_w(data_read);

}//loop




```
仮想環境の作り方

何度か目のチャレンジです。
Anaconda Promptを使ってvenvで仮想環境を作っていきます。

実行環境はWindows10で、MacやLinux環境だとvenvで作られるファイル名や
仮想環境への入り方が異なるみたいです。


## 仮想環境の作成

参考の公式サイト
https://docs.python.org/ja/3/library/venv.html

まずは仮想環境を作りたいフォルダまで移動します。

```bash:ディレクトリの移動
$ cd パス
```

そこで仮想環境を作成します。

```bash:仮想環境に必要なファイルを作成
$ python -m venv {ファイル名}

# (例)envフォルダを作成
$ python -m venv env
```

すると今いるディレクトリにenvフォルダが作成されます。
Windowsの場合は下記で仮想環境に入ります。

```bash:仮想環境に入る(windows)
$ .\env\Scripts\activate
```

下記の表記に変われば成功です。

```bash
# 仮想環境前
（base） C:ディレクトリ

# 仮想環境に入った後
(env) (base) C:ディレクトリ
```

```bash:仮想環境を終了
deactivate
```

## 最初に実行すること

pipのアップグレードしてくれと表示されるのでやっておきます。

```bash
# ちゃんと書くならpython -mを入れるらしい
python -m pip install --upgrade pip
pip install --upgrade pip
```

必要なライブラリをインストールして構築を進めましょう。

```bash
# スペースでライブラリを並べると一度にインストール可能
pip install pandas pyinstaller
```


## requirements.txtの作成

良く忘れるのでメモ

```
pip freeze > requirements.txt
```


## condaで仮想環境を作成

condaコマンドで仮想環境を作る下記のようなコマンドもよくみかけます。
condaコマンドだとuserフォルダ配下に仮想環境用のフォルダが作成されて一か所で管理されます。

```bash:conda
# 仮想環境の作成
$ conda create -n 環境名 [python=バージョン]
$ conda create -n env python=3.8

# 仮想環境の確認(2パターンあります)
$ conda info -e
$ conda env list

# 仮想環境の切り替え
$ conda activate 環境名

# 仮想環境の終了
$ conda deactivate

# 仮想環境の削除
$ conda remove -n 環境名 --all
```


## Flaskをテスト環境で実行する場合

いくつか設定が必要？なのでメモ

```bash
#仮想環境で実行するための設定
set FLASK_APP=app.py
set FLASK_ENV=development
flask run
```
DockerDesktopを起動してみたらWslKernelUpdateNotInstalledException。WSL2ってなに？


OS：Windows10 Home 64bit
## 経緯
Docker Desktop（for Windows）を入れてみて起動してみたところ、WslKernelUpdateNotInstalledExceptionなるエラーが出ました。
![err_cap.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203352/e48193c9-1a5e-3b7d-2bd4-dee8b41a49d3.png)

以下のリンクを参考に「Linuxカーネル更新プログラム（wsl_update_x64）」をインストールして無事解決。

## 参考リンク　thx
[【Docker 1-2】Dockerをインストールしてみよう](https://www.butteryarou.com/docker-1-2/)

## このエラーは？
そのまま、カーネルの更新プログラムがインストールされてないのでしょう。（詳しくはよくわからなかった）

## WSL2とは？
Windows Subsystem for Linux 2
Windows 10上でLinuxを動作させるための仕組み（バージョン2）

## WSLとの違いは？
* 軽量、高速起動
* Linuxの完全な互換性（WSLではWindowsシステムコールへの命令の変換自体が完全でなかった）
* ファイルアクセス速度の向上
* 仮想マシン化（Hyper-Vを使用）
* 仮想化で別のIPアドレスの割り当てが可能（WSLはIPアドレスがWindowsと共通）

## まとめ
Docker Desktopでこのエラーが出たらLinuxカーネル更新プログラムをインストールしよう。

## 参考リンク2　thx
[WSL 2(Windows Subsystem for Linux 2)の違いとインストール方法](https://www.pc-koubou.jp/magazine/40465)
言語 vs Python の速度対決 (ができてない)

ふと気になったので初心者がC言語とPythonの
速度対決
をしたいと思います。
<font color="red">追記: 注意:後でいいますが、これでは速度対決になっていません。</font>
#どのようなコードか
```Python:a.py
import time

s = time.time()
a = 0
for i in range(0,9):
    for i in range(0,999999):
        a += 1
print("Python:",time.time()-s,"\nループ数:",a)

```

```C:a.cpp
#include <stdio.h>
#include <time.h>

int main(void) {

    clock_t start_clock, end_clock;
    start_clock = clock();
    int a = 0;
    for (int i=0;i < 9;i++){
      for (int i=0;i < 999999;i++){
        a++;
      }
    }
    end_clock = clock();
    printf(
        "C言語: %f\nループ数: %d", 
        (double)(end_clock - start_clock) / CLOCKS_PER_SEC, a
    );

    return 0;
}
```
#結果

```
Python: 1.204263687133789
ループ数: 8999991

C言語: 0.022000
ループ数: 8999991
```

意外と差がありました。
やっぱりC言語の方がはやいようです。

という無知がやった実験でした

#<font color="red">追記</font>
記事を投稿した後、コメントのにて様々な指摘がありましたので、そのまま記事にのせたいと思います。
まず、今まで分からなかったのですが、C言語の場合で速度を評価する場合、最適化オプションをつけてコンパイルするのが普通らしいです。
自分の環境で試したところ、最適化オプションをつけたところ、本当に一瞬で終わるようになりました。
ということで、まずこのコードで比較ができないわけです。
さらにコメントで
>python の整数は多倍長ですが、C++ の整数は固定長です。なので、単なる加算を比較すること自体が公平じゃないかもしれません。

というご指摘をいただきました。そのような違いがあったということは知らなかったです。

また、この記事の一番最初では大量のたし算の速さを比べるものであります。
(999999+999999という計算を何回も繰り返すというやつです。気になる場合は編集履歴を確認してみてください。)

「999999+999999」はコンパイルする時点でその答えに置き換わるようです。

訂正：コンパイルする時点でその答えに置き換わるというよりかは、その計算の答えが使われないため、
何もなかったかのように除去されるということでした。
それはPythonでも同様だということでした。

とても勉強になりました。

##さらに追記

さきほどこんな感じに書いたと思います。

>自分の環境で試したところ、最適化オプションをつけたところ、本当に一瞬で終わるようになりました。
ということで、まずこのコードで比較ができないわけです。

コメントでアドバイスをもらいました。変数 a の宣言にvolatileを付けたり、ループ中に変数 a への最適化を阻害するインラインアセンブラを書いたりすればできるようでした。

```C
volatile int a = 0;
```

```C
__asm __volatile("":"+r"(a));
```

たしかに、これなら最適化オプションを付けても一瞬で終わる　っていうことがなくなりました。
`gcc -O2 a.c`
ちなみにタイムはこんな感じです。

```
C言語: 0.017000
```

###環境
Windows 10 Pro
64 bit
Python 3.9.5
gcc 6.3.0
[個人開発] StremlitでDjango初学者お助けアプリを開発したよ！

# はじめに

今回は個人開発で「**Django初学者お助けアプリ**」を作成しました。

もう少し具体的にいうと、データベースに必要な値を設定できる「**models.py**」をコードを書かずに作成できるものです。

初学者だからこそ、実際にコードを書いて覚えたほうが良いという感がもあると思いますが、初学者が知らない設定があることも事実です。

つまり何が言いたいかというと「**バランス**」ということです。

「**全初学者がこのアプリしか使うな！**」と言っているわけではなく、まずはこのアプリを使ってみて、どんな設定ができるかを知ることがより成長につながると言いたいわけです。

ぜひこのアプリを使って、Djangoの理解を深めていってください！

「**stremlit**」というものを使って開発したので、ぜひそちらも調べてみてください！

# アプリURL

**[Djangoお助けアプリ](https://share.streamlit.io/cardene777/django-help/main/stremlit/model_help/model_help.py)**

# 使用技術

**Stremlit**
**googletrans**

# 動画

https://twitter.com/cardene777/status/1413815668940681221


# 終わりに

個人開発は楽しいし、今なら簡単に作成できるツールが溢れているので、個人開発したことない方はぜひ挑戦してみてください！

何か質問などがあれば下記のTwitterのDMまで！
AtCoder Beginner Contest 209 参戦記

# AtCoder Beginner Contest 209 参戦記

連敗をようやくストップできたのに、結局その1回だけで、また連敗入り…….

## [ABC209A - Counting](https://atcoder.jp/contests/abc209/tasks/abc209_a)

1分半で突破. 書くだけ.

```python
A, B = map(int, input().split())

if A > B:
    print(0)
else:
    print(B - A + 1)
```

## [ABC209B - Can you buy them all?](https://atcoder.jp/contests/abc209/tasks/abc209_b)

2分で突破. 書くだけ.

```python
N, X, *A = map(int, open(0).read().split())

if sum(A) - N // 2 <= X:
    print('Yes')
else:
    print('No')
```

## [ABC209D - Collision](https://atcoder.jp/contests/abc209/tasks/abc209_d)

15分?で突破. 街cと街dの間の距離が奇数なら道路上で、偶数なら街で遭遇する. *N*≦10<sup>5</sup> なのでワーシャルフロイドで全街間の距離を計算することは出来ない. *N* 個の街と *N*−1 本の道路という条件と、どの街からどの街へもいくつかの道路を通ることで移動できるという条件から木構造(=ループがない)であることが分かる. であれば、ある特定の街aからその他の街まで最短の距離を全て求めれば任意の街cと街dの距離の偶奇が*O*(1)で分かる. 街iから街jまでの距離を距離<sub>ij</sub>とする. 街aから街cを通らないと街dに行けない場合、距離<sub>cd</sub>=距離<sub>ad</sub>-距離<sub>ac</sub>となる. 街aから街cを通らずに街dに行け、なおかつ街aから街dを通らずに街cに行ける場合、街aから街cや街dに行くときは途中の街bまで同じ道を通ることになるが(a=bのこともある)、その場合距離<sub>cd</sub>=距離<sub>ac</sub>+距離<sub>ad</sub>-2×距離<sub>ab</sub>となる. 結論的に距離<sub>ac</sub>+距離<sub>ad</sub>は常に距離<sub>cd</sub>の偶奇と一致する.

```python
from collections import deque
from sys import stdin

readline = stdin.readline

INF = 10 ** 15

N, Q = map(int, readline().split())

links = [[] for _ in range(N)]
for _ in range(N - 1):
    a, b = map(lambda x: int(x) - 1, readline().split())
    links[a].append(b)
    links[b].append(a)

dp = [INF] * N
dp[0] = 0
q = deque([0])
while q:
    a = q.popleft()
    for b in links[a]:
        if dp[b] <= dp[a] + 1:
            continue
        dp[b] = dp[a] + 1
        q.append(b)

result = []
for _ in range(Q):
    c, d = map(lambda x: int(x) - 1, readline().split())
    if (dp[c] + dp[d]) % 2 == 0:
        result.append('Town')
    else:
        result.append('Road')
print(*result, sep='\n')
```

## [ABC209C - Not Equal](https://atcoder.jp/contests/abc209/tasks/abc209_c)

38分半?で突破. ものすごい勢いで解かれているのに全然分からなくて焦ったし、これのせいでパフォを大きく落とした. 分かってしまえば簡単で、Cは順序を変えても答えが変わらないので、昇順に並び替えて良い. 並び替えれば C<sub>i</sub>-(i-1) を掛け続けるだけというのはすぐ分かる. i番目を処理するときには、既にそこまでに i-1 個が使われていて選択肢にならないからである. 昇順に並んでいれば瞬殺じゃんと分かった瞬間に、これだけ解かれているから並び替えていいに決まっているという腐った読みで突破. 後で考えてみれば A<sub>i</sub>≠A<sub>j</sub> の条件で i, j の前後は問われていない=順序に依存性がないので、順序を変えていいことは分かった.

```python
m = 1000000007

N, *C = map(int, open(0).read().split())

C.sort()
result = 1
for i in range(N):
    result *= (C[i] - i)
    result %= m
print(result)
```

## [ABC209E - Shiritori](https://atcoder.jp/contests/abc209/tasks/abc209_e)

突破できず. ループ検出+メモ化再帰で解けたかなあと思ったら WA. そうすると端点から順に確定していくしか無いのかなあと考え始めた辺りでタイムアップ. 後退解析という言葉を知らなかった時点で敗退が決定づけられていた気はする.
Fedora Workstation Live から Silverblue をインストールする

[諸事情](https://qiita.com/Mercury/items/e5bf8a9bdb565c4159d4) により、Fedora のインストール・メディアからのインストールではインストーラがクラッシュするので、
Live イメージで起動して ostree コマンドで Sliverblue をインストールしてみた。

# 前提
- 対象 PC に新規パーティション(/sysroot 用と /var 用)を作成してそこにインストールする。
    - /sysroot は md raid1
    - /var は LVM2 mirror で btrfs
- /boot は既存のものを流用
- 用意したファイルシステムにはラベルを付けておくと便利
    - /sysroot に SB-sysroot
    - /var に SB-var

# 手順
- Fedora Workstation Live で起動する
- ostree 関連のモジュールのインストール

```
# dnf install fedora-repos-ostree greenboot-rpm-ostree-grub2 osbuild-ostree ostree ostree-grub2 ostree-tests rpm-ostree
```
-  用意したファイルシステムの mount

```
# mkdir /sysroot
# mount -L SB-sysroot /sysroot
# mount -L SB-var /sysroot/var
```

- /sysroot の初期化

```
# ostree admin init-fs /sysroot
# cd /; ln -s sysroot/ostree .
```

- Fedora 34 の場合には[鍵の追加](https://qiita.com/Mercury/items/932fd43b9bcddb23285e)が必要

- /boot の既存フォルダを退避

```
# cd /boot
# mv grub2 grub2-
# mv loader loader-
# mv loader.0 loader.0-
# mv loader.1 loader.1-
```

- Silverblue イメージの取得

```
# ostree pull fedora:fedora/34/x86_64/silverblue
```

- deploy時のエラー回避の為に次を実行

```
# touch /etc/default/grub
```

- md raid1 で作成した /sysroot のメンバー・パーティションのものを調べておく

```
# blkid | fgrep SB-sysroot
/dev/md3: LABEL="SB-sysroot" UUID="c20bb89b-3552-4b71-9b83-f666decdd42c" TYPE="ext4" 
# mdadm -Ds /dev/md3
# mdadm -Ds /dev/md3 |tail -5

    Number   Major   Minor   RaidDevice State
       0       8        3        0      active sync   /dev/sda3
       1       8       20        1      active sync   /dev/sdb4
       2       8       33        2      active sync   /dev/sdc1
# blkid /dev/sdc1
/dev/sdc1: UUID="6af04dcd-6224-2033-f61b-cc926fd3b549" TYPE="linux_raid_member"
```

- Silverblue のインストール
    - 調べておいた uuid を下記で使用。

```
# ostree admin os-init fedora
# ostree admin deploy --os=fedora fedora/34/x86_64/silverblue --karg-append=root=LABEL=SB-sysroot --karg-append=rd.md.uuid=6af04dcd-6224-2033-f61b-cc926fd3b549
```

- インストール先の環境を幾つか事前に修正しておく
    - cd /ostree/deploy/fedora/deploy/<今回の環境>
        - etc/selinux/config ... SELINUX=permissive とでもしておく
        - etc/fstab ... 正しく mount されるよう記述
        - etc/mdadm.conf ... SB-sysroot の記載
        - etc/shadow ... root のパスワード削除
    - cd /boot/grub2
        - grubenv ... menu_auto_hide=0

- reboot すると無事に Silverblue が起動する筈なので、追加の環境設定を実施
プログラミング実務未経験者がBubble公式のBootcampに参加してみた！Part 1

## 目次
1. 参加したBootcampの概要
1. このコースでできるようになること
1. 先生や他の受講者はどんな人？
1. Mariel先生についてもう少し詳しく
1. レッスン1の内容
1. このコースに期待していること。
1. 最後に


## 参加したBootcampの概要
* コース名：Build and Launch No-Code Bootcamp
* 値段：600アメリカドル（通常は800ドルだが、早起きして参加なら-200ドルの模様）
* 学習期間：8週間
* 時間割：毎週木曜日の日本時間7:00amから9:00am(土日のコースもある)
* 参加人数：最大で8名(私の場合は5名でした。)
* 言語：現在は英語でのみ受講可能です。
* その他：毎週宿題があり、8週間は先生に質問し放題です。

## このコースでできるようになること
* コース名の通り、プログラミング未経験が二週間後にはオリジナルサービスを完成させ、リリースできる模様。（Part 8まで読んでいただければその真相が明らかになります！）

## 先生や他の受講者はどんな人？
* 先生：現在だとイギリス、アメリカ、シンガーポールの先生から好きな人を選べます。(私の場合はアメリカ人のMariel Vargas先生でした。)
* 受講者：今回は私とブラジル人の方の二人以外の受講者は皆さん英語のネイティブスピーカーの方々でした。（カナダ、スコットランド、アメリカ）

## Mariel先生についてもう少し詳しく
* PMとして、10億ドル以上のプロジェクトを40人以上のエンジニアと成功へ導かれたそうです。
* 2年ほど前から、企業し、Bubbleで受託開発を開始。
* これまでに、300人以上のプログラミング、またはBubble未経験者を指導。オリジナルサービスをリリースするところまで支援。

## レッスン1の内容
* 受講者全員が開発したいサービスを発表。
* Bubbleでできることの紹介。
* No code開発において、Mariel先生一押しの便利ツールの紹介。
* Sign upページを実装。（カリキュラムでInstagramの簡易版を作成予定。）

## このコースに期待していること。
* 実務未経験ですが、0からアプリを開発し、実際にリリースする。
* リリースしたアプリから1円でもいいので収益を上げる。
* 上記の経験により、アプリ開発において、明確な全体像を把握し、学習の効率を大幅に上昇させる。
* あわよくば、No codeの受託開発やオリジナルサービスで副業。

## 最後に
* 来週のPart 2ではデータベースの設計を学びます。
JavascriptでAPIキーを隠す方法

# JavascriptでAPIキーを隠す方法

- nodeや.envを使わずに隠す方法

- [JavascriptでAPIキーを隠す方法](https://ontakeo.blogspot.com/2021/07/doctype-html-html-head-meta-charset-utf.html 'JavascriptでAPIキーを隠す方法')

https://ontakeo.blogspot.com/2021/07/doctype-html-html-head-meta-charset-utf.html