OmniAICreator/Qiita-1.07M huggingface dataset:
[Ruby on Rails]scopeがnilを返すことができる理由

どうも、最近Ruby on Railsを始めたGroです。

##背景

[パーフェクトRuby on Rails](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88-Ruby-Rails-%E3%80%90%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88%E3%80%91-Perfect/dp/4297114623)のscopeについて見ていたら、以下のような記述がありました。

```ruby
class Book < ApplicationRecord
  略
  scope :written_about, ->(theme){ where("name like ?", "%#{theme}%") }
  scope :find_price, ->(price){ find_by(price: price) }
end
```
ここでfind_priceを、存在しないpriceを入れて実行(`Book.find_price(10000)`)すると`Book.all`の結果が返ってしまいます。
直感と異なるこの動作の意図について、以下のように書かれています。
>　クラスメソッドで定義した場合は想定通りnilが返りますが、Scopeで定義すると、結果がnilとなった場合は該当Scopeを除外したクエリを発行し、必ずActiveRecord::Relationを返すという動作をします。
　メソッドチェインで複数の条件を結合した場合のSQLを見ると、この動作の意図がよくわかるでしょう。

上記の説明の通り、ここで`Book.written_about("java").find_price(10000)`と実行した際のSQLを見ると、
written_aboutとfind_priceの検索SQLが発行されたのち、written_aboutだけの検索SQLが発行されます。

```bash
2.6.3 :001 > Book.written_about("java").find_price(10000)
   (0.4ms)  SELECT sqlite_version(*)
  Book Load (0.2ms)  SELECT "books".* FROM "books" WHERE (name like '%java%') AND "books"."price" = ? LIMIT ?  [["price", 10000], ["LIMIT", 1]]
  Book Load (0.1ms)  SELECT "books".* FROM "books" WHERE (name like '%java%') LIMIT ?  [["LIMIT", 11]]
 => #<ActiveRecord::Relation []> 
2.6.3 :002 >
```
**正直なところ、そのSQLを見ても、この動作の意図はよくわかりませんでした。**

##なぜscopeが除外されるのか

**それは、scopeがActiveRecord::Relationを返却しなくてはいけないからです**

いや

これだけじゃ納得できませんでした。
ActiveRecord::Relationを返すために、nilが返却されるとBook.allが実行されるのですが、
それならnilは返却できない制約にすれば良いのではないでしょうか。
nilを返すことができる理由、つまりnilが返却されると嬉しいことがあるのではないでしょうか。

##なぜscopeはnilが返却されると嬉しいのか

調べるためにStack Overflowを漁っていると、以下のブログを紹介している回答がありました。
[Active Record scopes vs class methods « Plataformatec Blog](http://blog.plataformatec.com.br/2013/02/active-record-scopes-vs-class-methods/)
このブログの中で以下のコードが記載されており、このscopeはstatusが空の場合にnilを返すことがあるのです。

```ruby
scope :by_status, -> status { where(status: status) if status.present? }
```
こうすることで、次の実行結果はscope（statusの検索条件）が除外されたものとなります。

```ruby
Post.by_status(nil).recent
# SELECT "posts".* FROM "posts" ORDER BY posts.updated_at DESC

Post.by_status('').recent
# SELECT "posts".* FROM "posts" ORDER BY posts.updated_at DESC
```

この場合、ソースコードでnilが返却されているので、SQLは発行されずに除外されています。

##scopeはnilまたはfalseが返却されるかどうかを除外条件としている

- scopeはActiveRecord::Relationを返却しなければならない
- scopeでnilまたはfalseが返却されるとデフォルトスコープ(この場合all)を実行する
- つまり**(パラメーターによる判定等で)nilを返すことで、scopeを除外できる**

##まとめ

正直、この結論で良いのか分かりません。
nullや空文字で検索したい場合もあるので、一律でscopeの構成のルールを決めることができないのではないかと思いました。
scopeではなく、通常のクラスメソッド定義にする方が良い場合もあります。
そんな感じでscopeは賛否両論ある機能なので、使い所は考慮すべきだと感じました。
AWSのクロスアカウントアクセスについてメモ


## はじめに
最近クロスアカウントアクセスを設定する機会があり、そのときにいろいろ調べたので備忘録的に書いておく。

「あるAWSアカウントから別のAWSアカウントにあるS3バケットにアクセスする」というユースケースを元に、必要な設定についてまとめる。


## ドキュメント
ここに全部書いてある。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html

読みにくい部分もあるため、この先の文章で補足する。

## 想定する構成
アカウントA：アクセスするユーザー（ユーザーA）が属するAWSアカウント。
ユーザーA：アカウントAに属するIAMユーザー。

アカウントB：アクセスされるリソースがあるAWSアカウント。
バケットB：アカウントB内にあるS3バケット。ユーザーAからアクセスしたい。

公式ドキュメントでは、アカウントAを「信頼されるアカウント（Trusted Account）」、アカウントBを「信頼するアカウント（Trusting Account）」と読んでいる。


## クロスアカウントアクセスを実現する二つの方法
「リソースベースのポリシーを使用したクロスアカウントアクセス」と「ロールを使用したクロスアカウントアクセス」の二つの方法がある。

後者はAssumeRoleとも呼ばれる方法で、それぞれの違いについては以下のドキュメントのにまとまっている。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_compare-resource-policies.html

特に以下が重要だ。

> リソースベースのポリシーを使用したクロスアカウントアクセスには、ロールを使用したクロスアカウントアクセスに比べて、いくつかの利点があります。リソースベースのポリシーによってリソースにアクセスする場合、プリンシパルは引き続き信頼されたアカウントで作業を行い、ロールのアクセス許可を受け取るために自身のアクセス許可を放棄する必要はありません。つまり、プリンシパルは信頼されたアカウントのリソースに引き続きアクセス可能である一方で、信頼するアカウントのリソースにもアクセスできます。これは、他のアカウントに属する共有リソースから、また共有リソースへと情報をコピーするといったタスクにおいて便利です。

「他のアカウントに属する共有リソースから、また共有リソースへと情報をコピーするといったタスク」とは、S3でいうとバケット間のデータコピーに当たると考えられる。

また、全てのAWSリソースが「リソースベースのポリシー」に対応しているわけではない。対応状況は以下のドキュメントにまとまっている。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html

## 「リソースベースのポリシーを使用したクロスアカウントアクセス」に必要な設定
今回、自分は「リソースベースのポリシーを使用したクロスアカウントアクセス」をすることにしたので、その設定方法について書く。

1. ユーザーAのIAMポリシーでバケットBのアクセスを許可する
1. バケットBのリソースポリシーでユーザーAからのアクセスを許可する


こう書いてしまうと単純だが、どちらのアカウントに対しても設定が必要な点が重要である。
単一のアカウント内の場合は、IAMポリシーとバケットのリソースポリシーのいずれかが許可されていれば（そして明示的な拒否がなされていなければ）、アクセスが成功する。

自分はバケットのリソースポリシーだけで十分だと誤解していて、クロスアカウントアクセスがしばらく上手くいかなかった。

以上です。
スモールライトを作る

## スモールライトを用意する
![small_light.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940684/4e54e36b-f1fe-37ee-64ce-c987d58d25d3.png)
まずスモールライトをモデリングします。
こちらの動画を参考に作成しました。
> 【blender初心者】ドラえもん・スモールライトを超簡単モデリング！
> https://www.youtube.com/watch?v=VlsbqZXfC-U

<br>
<br>
<br>

![small_light_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940684/3dc1218c-26f1-6cd3-67ce-db739413bad1.png)
光のシェイプも仕込んでおきます。
<br>
<br>
<br>

![SmallLight_Trigger.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940684/2a0f0f71-1bf9-c6f0-378f-397043b5e27c.png)
球のコライダーを2つTrigger状態でつけます。
RigidBodyも取り付けてください。
<br>
<br>
<br>

## 縮めたいオブジェクトに取り付けるスクリプト
```Smallable.cs
using UnityEngine;

public class Smallable : MonoBehaviour
{
    // 最小サイズ
    public Vector3 MinScale = Vector3.one;
    // 縮んでいく比率
    public Vector3 ScaleRate = Vector3.one * 0.001f;
}
```

Cubeなどに取り付けてください。
<br>
<br>
<br>

## 縮めるスクリプト

```SmallLightScaler.cs
using UnityEngine;

public class SmallLightScaler : MonoBehaviour
{
    void OnTriggerStay(Collider other)
    {
        var smallable = other.gameObject.GetComponent<Smallable>();
        if(smallable == null)
        {
            return;
        }

        var scale = smallable.transform.localScale;
        if(scale == smallable.MinScale)
        {
            return;
        }

        scale.x = Mathf.Max(smallable.MinScale.x, scale.x - smallable.ScaleRate.x);
        scale.y = Mathf.Max(smallable.MinScale.y, scale.y - smallable.ScaleRate.y);
        scale.z = Mathf.Max(smallable.MinScale.z, scale.z - smallable.ScaleRate.z);

        smallable.transform.localScale = scale;
    }
}
```
このスクリプトをスモールライトに取り付けます。
Smallableを取り付けたオブジェクトに当たっている場合、縮まります。
<br>
<br>
<br>

## 結果
![Small_Light_Result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940684/7a828424-906d-2913-c3c8-0606af5433b3.gif)
<br>
<br>
<br>

## おわり
応用でビッグライトも作れます。
Griffin Technology NA16029 PowerMate on Linux

<!-- Griffin Technology NA16029 PowerMate on Linux -->

![powermate.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/7ed4d26e-a18c-da24-aec3-af71b5128c5e.jpeg)

7年も前に購入した古い製品ですが紹介させていただきます（※ [Discontinued](https://griffin.zendesk.com/hc/en-us/articles/360004725800-PowerMate-USB-Discontinued-) になっています）

リモートワーク生活になってから、自宅の開発環境で音量のコントロールをする機会が増えました。ビデオ会議とか動画視聴、音楽を聴いたりする場合など、様々な場面で頻繁に必要となる操作なので、専用のデバイスがあるとたいへん楽ちんになります

Linux を普段使いしていますので、デバイスはその環境で動作可能である必要があり、この製品はその条件を満たしています。 [非公式ながらドライバが公開](https://en.wikipedia.org/wiki/Griffin_PowerMate#System_compatibility) されており、適切に設定すればちゃんと動くのです

[類似品](https://www.amazon.co.jp/s?k=Volume+Control+knob+usb) は販売されていますが、 Linux で使えるかどうかが肝心です。この記事執筆時点では動作成功が報告されている類似品は見当たりませんでした。ですので自分自身で動作確認できている PowerMate は貴重ということになります

質感や使用感はよいものです。金属製で見た目や触り心地もよく、長期使用していますがガタも出ていません。ボリュームの回転は適度な感触があり、引っかかったり鳴いたりすることもなく快適（高級オーディオであるとか、きっちりグリスアップされたカメラレンズのヘリコイドと比べたら安っぽいかもしれませんが）

ボリュームツマミだけのシンプルな見た目ながら、次の操作が可能

1. 時計回り
1. 反時計回り
1. 押下
1. 押下（長押し）
1. 時計回り（押し回し）
1. 反時計回り（押し回し）

そしてこの [ドライバ](https://github.com/stefansundin/powermate-linux) が大変良くできておりまして、上記それぞれの操作に対して任意のコマンドを割り当てることができ、音量の上下に留まらない多彩な操作を可能にさせてくれます
更に [ツマミの回転角に対する変化量](https://github.com/stefansundin/powermate-linux/blob/master/powermate.toml#L17) や、[何ミリ秒以上を長押し扱いとするか](https://github.com/stefansundin/powermate-linux/blob/master/powermate.toml#L29) も微調整可能。もはや文句のつけようが無いと言っても過言ではない。ありがたいことです:smile:

例えば [このように設定](https://github.com/o2346/pde/blob/master/debian/devices/powermate/powermate.toml) しまして、次のようになります

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/59c0c539-1bcc-1744-6659-419015ecea2f.gif)

*(※ [mpv](https://mpv.io/) でサンプルメディアファイル再生 -> ドライバ起動 -> 押下x2で停止/再開 -> 時計回り/半時計回りで音量調整)*

音量だけでなく、再生中のメディアプレーヤに対してよく使う操作をこのデバイスに集約することで、いちいちメディアプレーヤのウィンドウとの間を往復する手間が省けます（再生/停止、曲送り等）。同じことはキーボード・ショートカットを駆使すればわりと高速に出来はしますが、やっぱり楽な方の味をしめてしまうとそっちがいいとなってしまう。

自動車の運転中もですが、音量調整や曲送りのボタンがハンドルに組み込まれていて目線の移動や手を離す所作を要しないで制御できるのと、センターコンソールに手を伸ばさなくてはいけないのとでは面倒くささが違います
一見ちょっとした事のようですが、実は大きな違いなんですよ。よりよいユーザー体験の提供を生業とする側としても、このようなことには常に敏感でなくてはいけません（:point_left:なんだこいつ偉そうに笑）

課題はやはり代替品の調達です。冒頭で述べたように Discontinued になっていて、中古の出物も見当たりません。かと言って今購入可能な他社商品は比肩するどうかもわからない。ともかく、既に所有している個体は大切に使っていこうと思います
【初心者向け】CSSで色が変えれるSVG画像の作り方

# どうも7noteです。イラレやフォトショップで作成したアイコン画像をwebで使えるSVG画像として利用する方法。

## ①画像の作成

アイコンなど色をCSSで変更する場合は予め黒でアイコンを作成してください。

### 『イラレ』の場合

SVG画像として利用したい画像のファイルを開いた状態で

**「ファイル」⇒「別名で保存」⇒「ファイルの種類」をSVGにして「保存」**

### 『フォトショップ』の場合

**「ファイル」⇒「書き出し」⇒「書き出し形式」⇒「ファイルの設定」をSVGにして「書き出し」**

※**シェイプが重なっているところが白くなる場合は以下の処理をしてから**SVG書き出しをしてください。
「長方形ツール」を選択⇒上部メニューの中から「シェイプコンポーネントを結合」


## ②svg画像をsvgタグに変換

https://icomoon.io/app/#/select

上記のサイトがおすすめです。
このサイトで作成したsvg画像をsvgタグに変換していきます。

**1. 作成したsvg画像をドラッグ＆ドロップ**
**2. Untitled Set とかかれた場所にsvg画像が登録されます（複数登録可）。処理したいものをクリックで選択（複数選択可）。**
**3. 下部の左の「Generate SVG & More」を選択。**
**4. さきほど選択したアイコンが表示されていると思うので、カーソルを合わせて「Get Code」の文字がでてきたらクリック。**
**5. svgタグ、symbolタグ、cssが生成されます。これらを使います。**


## ③svgタグを使う

htmlの任意の場所にsymbolを記述。以下のsvgとdefsタグで囲ってください。
例ではbodyタグの直後に記載しています。

そして、アイコンを表示させたい場所にsvgタグの方を記述します。

```index.html
<body>
<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>

<symbol id="icon-home" viewBox="0 0 32 32">
<path d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z"></path>
</symbol>

  </defs>
</svg>

<p><svg class="icon icon-home"><use xlink:href="#icon-home"></use></svg>ホーム</p>

</body>
```

cssで大きさや色を指定すれば完了です。

```style.css
.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  stroke-width: 0;
  stroke: #f00;
  fill: #f00;
}
```


## まとめ

svg画像は複数ページで仕様したり、条件によってCSSで色を変えたいなどの場合でも1ファイルで完結できるので、作成・管理が楽に済みます。
ベクターデータ（拡大してもぼやけない）なので、綺麗にも見えるためメリットが大きいのが特徴ですね。

ただ使用方法が慣れるまではちょっと難しいので、手順をまとめているサイトを見ながら最初は使ってみることをおすすめします。

今回紹介した方法以外でもsvg画像を表示する方法はあるので、調べて様々な方法を試してみてください。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
【Rails】チーム開発を通して流れとRailsについて学ぶ #1日目

# 環境
* MacBookAir(M1,2020)
* Ruby on Rails 6.1.3
* Mysql2 0.5

# 学習内容
* 非同期通信によるチャット機能

# 苦労した点
* 中間テーブルを使用した為、各テーブルのアソシエーションを組むのに困惑してしまった

# 感想
非同期通信技術はチャット機能等で非常に重要になってくるので、理解をして活用出来るようになりたいです。
AWSのEC2上にPostgresをインストールし、EC2上でtsvファイルをPostgresに読み込みたい。

<h2>AWSにインスタンスを作成する。</h2>
・AWSのリージョンはバージニア北部を使用
・インスタンスサイズは、t2.micro を使用
・秘密鍵を作成

<h3>秘密鍵の権限を600にchange mode(権限変更)する</h3>

```
chmod 600 /Users/[ユーザー名]/.ssh/[秘密鍵]
```

<h3>awsのサーバーに入る</h3>
```
ssh -i [秘密鍵のパス] ec2-user@[ipアドレス]
```

<h2>ミドルウェアのインストール</h2>
https://qiita.com/fftcy-sttkm/items/b3e083df38edded7d82f

https://qiita.com/east_takumi/items/3c0c3043bc0edd9079d9


Postgresqlのインストール


```
$  sudo amazon-linux-extras install postgresql9.6
$  sudo yum install postgresql-server postgresql-devel postgresql-contrib
```

初期設定

```
$  sudo postgresql-setup initdb　　　← これで初期DBが作られる？

$  sudo systemctl start postgresql　　← 起動（.serviceは付けない）

$  sudo su - postgres　　← postgresユーザーにチェンジ

$  psql　　← postgresqlに接続
```

postgresユーザのパスワードが設定されていないので、以下でpostgresに設定

```
postgres=# alter role postgres with password 'postgres';
```

psqlを一旦抜けて、さらにpostgresユーザも抜けて　ec2-user に一旦戻る


```
$  sudo su -    でroot ユーザにスイッチ
```

★/var/lib/pgsql/data/pg_hba.conf をviで編集し、認証方法を変更する

```
# "local" is for Unix domain socket connections only
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
```

設定ファイル変更後はpostgresの再起動を忘れずに

```
$ exit　　　ec2-user に戻る

$  sudo systemctl restart postgresql　　　　←　postgres 再起動

$ psql -U postgres　　　　←　ec2-user でpsql 実行
```

ここまでいけば、ローカルからのpgAdminでSSHトンネル設定でもつながるはず。

<h3>SSHトンネル設定</h3>

![スクリーンショット 2021-06-19 21.35.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/791219/ad2e0e2c-c6d7-b06e-c988-c2654bfc5e0f.png)

トンネルホスト
　　→EC2インスタンスのパブリックIPに読み替える

識別情報ファイル
　　→鍵ファイルに読み替える

<h3>つながらない場合は？</h3>
<ul>
<li>サーバー側でちゃんとpostgreSQLが起動しているか</li>
<li>pg_hba.conf の設定はちゃんとできているか（METHODを「md5」に設定したか）</li>
<li>pg_hba.conf 設定後、postgreSQL を再起動したか</li>
</ul>

<h3>scpでローカルにあるtsvファイルをec2上に転送する</h3>
```
scp -i [秘密鍵のパス] [転送したいファイルのパス] ec2-user@[ipアドレス]:[/ec2上のディレクトリ]
```

<h3>本題のtsvファイルの読み込み</h3>
sshトンネルを使いec2上のPostgresにローカルのpgAdminでアクセスする。

pgAdminからcopyコマンドを実行したが、権限がないと怒られる。
→何の権限？

![スクリーンショット 2021-06-18 14.18.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/791219/b817611e-3470-12fe-22ff-2fc9620992bd.png)


しょうがないので、tmpディレクトリに一時的に.tsvファイルを移動し、再度copyコマンドを実行したら成功した。

```
/home/ec2-user/tmp
```

デプロイに関しては下記のURLが参考になりました。

https://case10.hateblo.jp/entry/2020/10/06/165543
Windowsでもcondaを使わずにRDKitを快適に利用する

#はじめに
RDkit の 2021.3.2.3 が pipでインストールできるようになり、有償化したAnacondaから解放されると喜んだ人もいるかと思う。

しか～し、残念ながら我らが Windows では、 ```pip install rdkit-pypi```しても、```ERROR: No matching distribution found for rdkit-pypi```と表示され、インストールできないのであ～る。

そこで今回はWindowsでも快適に pip 版の RDkit を使う方法を説明する。

# 方法
ネタバラシだが、LinuxベースのDockerイメージに RDKitをpipでインストールし、それを使うというものである。

# 環境
- Windows 10
- Docker
- python 3.8
- RDKit 2021.3.2.3

# 手順
前提として、Dockerはインストールされているものとする。

## Dockerイメージの作成

まずは requirements.txt に、RDkitやインストールしたいライブラリを記載しよう。

``` requirements.txt 
rdkit-pypi==2021.3.2.3
```

続いてDockerファイルを用意しよう

```Dockerfile
FROM python:3.8

WORKDIR /tmp
ADD requirements.txt /tmp
RUN pip install -r requirements.txt
WORKDIR /test
```

思考錯誤して分かったのだが、pip 用の RDKit が用意されている Python のバージョンが 3.8 であることに注意しよう。

続いて requirements.txt、Dockerfile のある場所で以下のコマンドを実行し、Dockerイメージを作成しよう

```sh
docker build . -t <タグ名> -f Dockerfile
```

これでRDkitがインストールされたLinuxベースのDockerイメージができる。

## Dockerのコンテナの起動

続いてDockerコンテナを起動しよう

```
docker run -it -d --name <コンテナ名> --mount type=bind,src=<アプリケーション開発を行っているフォルダ>,target=/test <タグ名> bash
```

コンテナ名は適宜に指定してほしい。

## Dockerコンテナにbashで接続

あとはアプリケーション開発を行っているフォルダに移動し、コンテナに bash で接続しよう。

```
docker exec -it <コンテナ名> bash
root@ed5354c38390:/test# 
```

すると、アプリケーションの開発を行っているフォルダがマウントされており、RDkitがインストールされたpython環境をあたかもローカルのように利用できるのだ。

さらに工夫すれば、Windowsで開発したアプリをフォルダ毎、Dockerに追加し、そのDockerイメージをDockerリポジトリに登録し、本番環境にあっという間にディプロイ、な～んてこともできてしまうのだ。

こういう体験をすると、Dockerが如何に便利かが良く分かる。

#補足
本記事は、VSCode等でRDkitのアプリケーションを開発するケースを想定したが、JupterLabで解析したりモデル作りたい！という場合は、上の手順に以下を追加すればできるだろう。(**試してないけど**)

1. 「Dockerイメージの作成」の requirements.txt に jupyterlab を追加する。
2. 「Dockerのコンテナの起動」の際に ```-p```オプションでローカルポートとコンテナ内部ポートを指定する。
3. 「Dockerコンテナにbashで接続」した後、``` https://qiita.com/RayDoe/items/e1ec21c63a15adb1a061 ``` を参考にJupyterLabを起動する。その際ポートは、2で指定したコンテナ内部ポートを指定して起動する。
4.  ローカルのブラウザより、3で起動したJupyterLabのURL、2で指定したローカルポートを指定して接続する。
airflowとはなんなのか?

CloudComposerで初めてAirflowを触ることになったのですが、そもそもAirflowがわからなかったのでまとめてみたいと思います。

# Airflowとは?
ワークフロー管理ツールです。類似のもので言うとdigdagやargoなどが該当します。
ある処理を実行して、次にある処理を実行する...といった一連の処理を管理し、処理や外部への疎通など柔軟なワークフローを組むことが可能です。

具体的にはpythonでファイルを実装して処理順番を指定していきます。

## airflowの構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179800/e40bec06-3ed5-7a5a-4c2e-942e9ea02635.png)
https://airflow.apache.org/docs/apache-airflow/stable/concepts/overview.html
より

DAGディレクトリはワークフローの設計図が保存されている場所です。
このDAGファイルをスケジューラー(executor)が見て、タスクを実行するためにworkerへ通知します。
workerはその情報をもとに処理を実行、監視します。
それぞれの状態(実行中など)はmetadatabaseに保存されます。

webserverは上記の情報をUIに表示したり、処理を受け取ってそれぞれに処理の実行などをそれぞれに通知します。

## DAGとは？
処理と順番を記述されたワークフローです。
airflowではこの処理の単位をTaskと呼ぶので、Taskとその実行順番が記載されたものといっても良いと思います。
ざっくり書くとこんな感じ↓
このファイルの実態はpythonのファイルです。

![スクリーンショット 2021-06-19 21.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179800/6cb42731-dd7c-d568-44e4-ae9962080cc1.png)

図にある通り、TaskB,TaskCを並列実行(厳密にはちょっと準備が必要)させたりできます。

# まとめ
Airflowを簡単にまとめてみました。
実際のソースコード云々は別にまとめたいと思います。
それでは良きAirflowライフを
aws cloudformationコマンドをMakefileにまとめたらﾁｮｯﾄﾀﾞｹ便利になった

CloudFormationをAWS CLIで直接操作すると色々辛いし、そもそもコマンドやオプションが難しい。

[rain](https://github.com/aws-cloudformation/rain) という優れたツールもあるが、そこまで多機能でなくても良いのでサッと使えるものが欲しかった。

# Usage
```bash
# テンプレートのバリデーション
make validate
# スタックの新規作成
make create
# スタックの更新
make update
# スタックの削除
make delete
```

# Makefile

Markdownからコピペするとインデントがスペースになるので、タブに変換してください。

```Makefile
STACK_NAME=スタック名
CHANGE_SET_NAME=変更セット名

help: ## Display this help.
	@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n  make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf "  \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

validate: ## Validate the template.
	aws cloudformation validate-template \
	--template-body file://$(STACK_NAME).yml

create: ## Create the stack and wait it.
	aws cloudformation create-change-set \
	--change-set-type CREATE \
	--stack-name $(STACK_NAME) \
	--change-set-name $(CHANGE_SET_NAME) \
	--template-body file://$(STACK_NAME).yml \
	--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM

	aws cloudformation wait change-set-create-complete \
	--stack-name $(STACK_NAME) \
	--change-set-name $(CHANGE_SET_NAME)

	aws cloudformation execute-change-set \
	--stack-name $(STACK_NAME) \
	--change-set-name $(CHANGE_SET_NAME)

	aws cloudformation wait stack-create-complete \
	--stack-name $(STACK_NAME)

update: ## Update the stack and wait it.
	aws cloudformation create-change-set \
	--change-set-type UPDATE \
	--stack-name $(STACK_NAME) \
	--change-set-name $(CHANGE_SET_NAME) \
	--template-body file://$(STACK_NAME).yml \
	--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM

	aws cloudformation wait change-set-create-complete \
	--stack-name $(STACK_NAME) \
	--change-set-name $(CHANGE_SET_NAME)

	aws cloudformation execute-change-set \
	--stack-name $(STACK_NAME) \
	--change-set-name $(CHANGE_SET_NAME)

	aws cloudformation wait stack-update-complete \
	--stack-name $(STACK_NAME)

delete: ## Delete the stack and wait it.
	aws cloudformation delete-stack \
	--stack-name $(STACK_NAME)

	aws cloudformation wait stack-delete-complete \
	--stack-name $(STACK_NAME)
```

# 感想

- はじめてMakefileを書いたので、**上記の品質はとても自信がない**。（改善点のコメントお待ちしております）
  - そもそもMakefileはこういう使い方をするものなのか？
- `aws cloudformation wait`は30秒ごとにチェックする[仕様](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/wait/change-set-create-complete.html)なので、**最低でも30秒待たされるのがイケてない**（シェルで5秒間隔で`describe-stacks`を叩いてチェックするのが良さそう）

# 参考文献
- [AWS CLI Reference](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/index.html)
- [Go言語開発を便利にするMakefileの書き方](https://qiita.com/yoskeoka/items/317a3afab370155b3ae8)
  - ↑Makefile何も分からないマンだったので大変助かりました
- [超小技!! Makefile に help をつけて「こいつ...できる!」と言われたい](https://qiita.com/po3rin/items/7875ef9db5ca994ff762)
PDOクラスのprepareメソッドについて勉強してみた

#PDOのprepareメソッドでSQL文を実行する手順
①DBに接続
②実行したいSQL文をprepareメソッドにセット
③bindValueメソッドを実行して、SQLにパラメーターをセット
④executeメソッドで実際にSQLを実行
⑤返り値を取得

#prepareメソッドとは
変動値を含むSQL文を実行するのに使うPDOクラス内のメソッド。
変動値を含むため、悪意のあるユーザーが変動値を入力する箇所に攻撃をしてきても大丈夫なようにSQLインジェクション対策としてプレースホルダを使って安全にSQL文を割り当てる必要がある。
プレースホルダーの書き方は、変数が入る箇所に「?」または「:(任意の名前)」をつければOK!

```
$sql = 'select * from contacts where id = ?'; 　　　　　//疑問符プレースホルダー
$sql = 'select * from contacts where id = :id'; //名前付きプレースホルダー
```

#bindValueメソッドとは
・・・そもそもバインドって何？
→バインド(bind)とは何かを割り当てるという意味
そのため、bindValue＝割り当てられた値となるので、この場合ではbindValueは変動値のことを表す。

```
//名前付きプレースホルダーの場合
bindValue (指定した任意の名前(:id), 割り当てたい値 [, $PDOデータ型定数] )
//疑問符プレースホルダーの場合
bindValue (1（何個目の「?」か）, 割り当てたい値 [, $PDOデータ型定数] )
```

$PDOデータ型定数（PHPマニュアル）
https://www.php.net/manual/ja/pdo.constants.php
デフォルト値はPDO::PARAM_STR

#executeメソッドとは
executeを直訳すると実行するという意味。
PODクラスのprepareメソッドを使ったSQLを実行するにはexecuteメソッドを使って実行する必要がある。
*queryメソッドは実行までしてくれるメソッドになるため、executeメソッドを使う必要はない！

```
$sql = 'select * from contacts where id = :id'; 
$stmt = $pdo->prepare($sql);
$stmt->bindValue('id', 3, PDO::PARAM_INT);
$stmt->execute();  //ここで初めてSQLが実行される

$result = $stmt->fetchAll();　//返り値を取得
```

#結論
変動値がある場合、prepare⇒bindValue⇒executeでSQL文が実行できる
docker-composeでReactの開発環境作る。

アウトプットを兼ねて、dockerを使ってReactAppを実装しようと思います。

まずはDockerfileとdocker-compose.ymlを用意します。

Dockerfile

```
FROM node:12.18.0-alpine
WORKDIR /usr/src/app
```

```docker-compose.yml
version: '3'
services:
  react:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
     - ./:/usr/src/app
    command: sh -c "cd workplace && yarn start"
    ports:
     - "3000:3000"
    tty: true
```

```
docker-compose build
```
[+] Building 27.4s (6/6) FINISHED
これが表示されたらビルドは成功しています。
続いてcreate-react-appをコンテナ環境で実行できるようにしていきます。
同時にコマンドを実行してReactアプリをworkplaceディレクトリに作成していきます。

```
docker-compose run --rm react sh -c "npm install -g create-react-app && create-react-app workplace"
```

```
docker-compose up -d
```
Creating docker-react-project_react_1 ... done
これが表示されたらコンテナが立ち上がっているのでブラウザからlocalhost:3000
にアクセスしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/1eb28eb1-f361-dae3-ac6d-8b9c11b753bb.png)

Docker-React環境の構築は完了です。
[Laravel] セッションID名を変更する

セッションIDとは、セッション情報にアクセスする際にキーとしての役割を持つクッキーのことです。認証の際に必要になります。

# 結論

`.env` に `SESSION_COOKIE` を追加するだけです。(ここではabcdeという名前にしています)

```
SESSION_COOKIE=abcde
```

# 設定部分


```php:config/session.php
'cookie' => env(
    'SESSION_COOKIE',
    Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
```

コードからわかる通り、`SESSION_COOKIE` の値が優先されます。
`SESSION_COOKIE` が存在しなければ `APP_NAME` が使われます。
【学習メモ】cakePHP3 ＃2

《エレメントの利用》
レイアウトの部分部分を必要に応じて入れ替えたりすることができる。
エレメントはレイアウトの内部にはめ込んで利用するテンプレートです。
これはTemplateフォルダにあるElementというフォルダの中に用意されます。
ここに配置されたエレメントは、レイアウトテンプレート内から次のようにして読み込み表示させることが出来ます。<?=$this->element(エレメント名)?>
またエレメントで利用する値などを渡したい場合は第２引数に連想配列として値を用意します。
<?=$this->element(エレメント名,[キー名=>,キー名=>.・・・])?>
渡された側は、例えば['a'=>123]の場合、$aという変数に123が保管されている。

エレメントの利用は「コントローラからレイアウトへ」、「レイアウトからエレメントへ」といった値の受け渡しが非常に重要になります。
コントローラのsetメソッドとレイアウトのelementメソッドの使い方をしっかりと理解しましょう。
※コントローラのsetメソッドはエレメントの利用に限らずさまざまなシーンで利用される。「コントローラからテンプレートに値を渡す際の基本メソッド」として理解する。

《フォームの利用》
Webアプリケーションの基本はフォームからの送信とその処理です。
フォームはWebの処理を行う際の基本。
⓵フォームを組み込んだページを表示する。
⓶送信先のコントローラで、送信された情報を取り出すなどの必要な情報を処理する。
⓷何らかの結果を表示するような場合にはコントローラからビューへ必要な値を設定する。
⓸ビューテンプレートで⓷によって設定された値を取り出し、必要に応じて画面に表示する。
※送られた情報の処理はコントローラで行い、必要な値の表示はビューで行う。

「$this->request->queryで値を取り出し、setでビューに渡す」という基本がわかっていればフォームの送信はそれほど難しいものでもありません。
※POSTで送った場合は$this->request->data('text1')またはdata['text1']

《エスケープ処理》
$this->set("result", htmlspecialchars($result));
$resultにjavascriptが書かれても、ただのテキストとして画面に表示される
※ショートハンド関数の「h()」でも可。→$this->set("result", h($result));
Serverless Frameworkでevent scheduleの起動時間をステージ毎に切り替える

## きっかけ
dev/prodの２環境をdeployして並行して動かすようにした。
event scheduleの時間起動を`rate: cron(30 /3 * * ? *)`のようにしていたため、２環境ともに同時刻に起動してしまい不都合があったりもした。

## 対応策
以下のようにcronの起動時間の部分を外部ファイルでdev用、prod用にわけて、deployするようにしました。
同じような記事があったため、ほぼパクリです。

```serverless.yml
service: scraping
custom:
  dev: ${file(./dev.yml)}
  prod: ${file(./prod.yml)}
provider:
  name: aws
  runtime: python3.7
  region: ap-northeast-1
  stage: ${opt:stage, 'dev'}
functions:
  func1:
    name: crawler-${self:provider.stage}
    handler: handler.crawler
    events:
      - schedule:
          rate: ${self:custom.${self:provider.stage}.cron}
          enabled: true
          name: sc-crawler-${self:provider.stage}
          input:
            body:
              target: xxxxxxxxx
              url : https://yyyy.zzzzz/xxxxxx
```

devの時間を15分早く起動するようにした。

```dev.yml
  cron: cron(15 /3 * * ? *)
```

```prod.yml
  cron: cron(30 /3 * * ? *)
```

```handler.py
def crawler(event, context):
    url = event['body']['url']

```

こちらは、devのdeploy。`--stage`の指定なしの場合、devがデフォルトとなっています。

```bash
sls deploy -v
```
こちらはprodのdeployです。

```bash
sls deploy -v --stage prod
```

# 参考
- [Serverless Frameworkでevent scheduleをステージ毎に切り替える](https://qiita.com/sayama0402/items/069a8d1ee2a1f259486a)
- [Serverless Frameworkでstage毎に外部ファイルから環境変数を参照させる](https://qiita.com/sayama0402/items/a13610202220896796aa)
RPGツクールMZでゲーム起動時に変数を初期化する方法

ニューゲーム後に一番最初に実行するイベントで変数を初期化する処理を呼び出せば実現できますが、テストプレイ時は「初期位置の設定」で開始位置を頻繁に変えるので毎回そのイベントを呼び出すようなことをしなければならず面倒です。

こちらのプラグインを利用して、ニューゲーム後に変数を初期化するコモンイベントを呼び出すようにすると良さそうです。

https://plugin-mz.fungamemake.com/archives/690
私はSVN脳患者なのか

「SVN脳患者から見たGit」という、Subversion ユーザが Git を理解するのが難しい現象を説明している良記事があります。

https://qiita.com/kaityo256/items/81e7951a1ca2706955a4

私は Git のことがよくわかっていないのですが、私がこの記事の言う「SVN 脳」であるせいでよくわからないのか、という点を考えてみました。

さて、この記事の結論部分にはこうあります。

> で、僕の場合は「コミットをパッチとみなすことができる」という点が一番ひっかかりポイントだったよ、ということです。

> Subversionではブランチ＝タグ＝ディレクトリなんだけど、これは本当にGitのブランチを理解する弊害になるよね・・・。

私がここに引っかかっているかどうかというと、おそらく No です。

> Subversionにとって、そしてSVN脳患者にとってマージとはスナップショット同士の比較であり、２つのディレクトリのdiffをとって、そのdiffをもとにブランチで行った修正を抽出して取り込む作業であり

たしかにこう述べられているように、Subversion ではブランチがディレクトリであり「ディレクトリの diff が取れてしまう」ものです。
しかし私は「ディレクトリの diff を取り込む」という考え方をしません。

![SVN](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699223/d87e3004-3565-8331-decf-7578c8ea44b8.png)


私がこの図における branch-a 全体を trunk にマージしようとしたら、「r10 時点の trunk と r10 時点の branches/branch-a との差分(diff 1)」ではなく、「branches/branch-a における r5 と r10 との差分(diff 2)」をマージしよう、という感覚になります。

したがって私は、ブランチやタグがディレクトリであることによって理解が難しい、というわけではなさそうです。

なぜ私がマージについてこのような感覚を持つようになったのか辿ってみたところ、次のような経験によるものと思われます。

 * CVS を使っていたから
CVS では CVSWeb の Revision Graph を見ることで、ファイルごとの成長（例: [src/sys/conf/newvers.h](https://cvsweb.allbsd.org/cvsweb.cgi/src/sys/conf/newvers.sh)）を確認することができました。また CVS においては「ディレクトリ全体の状態」を表すリビジョンがなかったので、ディレクトリ全体という意識が薄かったのだと思います。
さらに、CVS ではブランチポイントタグを付けてからブランチを切っていたと思います。そのため Subversion を使うようになっても「そのブランチにおける成長の歴史」というものを意識しているのだと思います。

 * FreeBSD の開発でコミット単位でマージするのを見てきたから
FreeBSD では CURRENT から STABLE 開発用のブランチが分岐し、分岐したブランチ全体が CURRENT に合流するということがありません。CURRENT で行われたとある修正が security fix で、それが STABLE にも必要であれば、その修正だけが STABLE にマージされていきます。例を挙げると [FreeBSD-SA-05:21.openssl](https://www.freebsd.org/security/advisories/FreeBSD-SA-05:21.openssl.asc) や [FreeBSD-SA-14:14.openssl](https://www.freebsd.org/security/advisories/FreeBSD-SA-14:14.openssl.asc) のように、必要な差分だけがコミットされていきます。
図で言うと「trunk の r9（r8:9の差分）を branches/branch-a に持ってくる」に相当するマージを見て育ってきたことになります。これは「コミットはパッチである」に通ずる考え方に思えます。

*****
編集履歴
 * 2021/07/21 CvsGraph, FreeBSD-SA の例を追記
 * 2021/07/21 図を修正
debug=Falseとした場合でもDjangoに静的ファイルを参照させる

#はじめに
Djangoでは settings.py で debug=False とした時、各アプリケーションフォルダの下にある static フォルダの画像やCSSが参照されなくなる仕様である。

debug=False、つまり本番環境の場合は ```python manage.py collectstatic``` コマンドで、各アプリの static をフォルダのファイルを1つのフォルダに集め、そのフォルダをWEBサーバで配信する設定とするのが定石のようである。

しかしながら、この状態で WEBサーバを使わずに django の manage.py で起動した場合、集めた static フォルダのファイルは**引き続き参照されない**。

開発中は、**manage.py で本番設定の動きを確認したい** こともあるのでこれは不便だ。

状況の説明が長くなってしまったが本記事はこれを回避するものである。

#環境

- python 3.8
- Django 3.0


# 方法

manage.py と同じフォルダに、各アプリケーションのフォルダの下の静的ファイルを集めた static フォルダがあるという前提で話を進める。

対応方法として、 ```URLのパス /static/``` に対し static フォルダを表示するよう設定すればよい。

具体的には、urls.py に対し以下のように ```re_path(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}), ```を入れてあげればよい。

```プロジェクトのurls.py 

from django.contrib import admin
from django.urls import path, include, re_path
from django.conf import settings
from django.views.static import serve 
 
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include("myqsar_app.urls")),
    re_path(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}), 
]
```

#参考
- https://stackoverflow.com/questions/56352489/what-does-django-staticsettings-static-url-document-root-settings-static-root
Apacheでindex.*しか表示できなかった話

# タイトル通り
初歩の初歩でハマったとはいえ、何をどうすればいいかが全然出てこなかったので自分用にメモです。

環境: Ubuntu 20.04 LTS

## 症状
`http://(接続先IP)/test.html`で`test.html`が取得できない
(index.htmlは取得される)

ディレクトリ構造は
> /var
>   └ /www
> 　└ /html
> 　　├ index.html
> 　　└ test.html

## 解決策
`apache2.conf`に

```config:apache2.conf
<Directory /var/www/html/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>
```

を足してやる。
元々`/var/www/`はデフォルトでconfに書かれているのだが、それだけだと`/html`以下のコンテンツは読み込めないらしい。

というかそもそも最初はApacheのconfファイルの場所が分からず(調べたら`httpd.conf`探せと書いてあって困った)。
初歩の初歩から分かっていなかったが、とりあえずドキュメントルートの指定の仕方は学びました。

おわり
手元にあるGoプロジェクトをビジュアルに読む！


# TL;DR

https://github.com/momotaro98/goviz を`go get`して使えば、以下のような感じで、あなたやあなたの職場のプライベートなGoプロジェクトのパッケージ依存関係が可視化できるようになります。

![isucon9-q.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91562/9025a1f6-3221-d3a6-7d1c-748a12909328.png)

# 前提

この記事は以下記事リスペクトの記事になります。

https://qiita.com/hirokidaichi/items/52fc6286c9e432792a07

上記記事制作者の方が作成した[goviz](https://github.com/hirokidaichi/goviz)というツールが現状(2021年6月19日時点)で長らくメンテナンスされておらず、別の方がフォークしたものをさらにフォークする形で修正をしました。

https://github.com/hirokidaichi/goviz

筆者のフォークしたレポジトリが以下になります。

https://github.com/momotaro98/goviz

既存のgovizは`$GOPATH/src`配下のソースコードしか解析対象にしていなかったので、`go get`はしていないプライベートなGoプロジェクトも解析対象にするように筆者が改修しました。

# 使い方

## インストール

```
go get github.com/momotaro98/goviz
```

or

```
go install github.com/momotaro98/goviz@latest
```

そして別ツールである [graphviz](http://www.graphviz.org) のグラフ生成ツールもインストールしておく必要があります。

```
brew install graphviz
```

## 使う

### Step1: Goプロジェクトがあるディレクトリへ移動する。

__このとき、`go.mod`があるディレクトリへの移動をしてください。__

### Step2: go.modにあるモジュール名を確認

以下はサンプルのプロジェクトです。以下の場合は、`github.com/momotaro98/isucon9-q/webapp/go`になります。

```go.mod
module github.com/momotaro98/isucon9-q/webapp/go

go 1.15

require (
        github.com/go-sql-driver/mysql v1.4.1
        github.com/gorilla/sessions v1.2.0
        github.com/jmoiron/sqlx v1.2.0
        goji.io v2.0.2+incompatible
        golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
)
```

### Step3: go.modがあるディレクトリ上にてエントリーポイントのGoファイルがあるディレクトリを指定して実行

```
goviz -i github.com/momotaro98/isucon9-q/webapp/go | dot -Tpng -o project.png
```

生成された`project.png`が冒頭のスクショの図になります。
videoタグを使った動画再生で、再生位置の記憶とレジューム再生を実現する

# 現在の再生位置の取得と設定

videoタグで再生中の動画の現在の再生位置は、javascriptからcurrentTimeというプロパティを参照することで、取得＆設定することができます。

例えば、下記のようなタグを書いていた場合、動画の再生位置の取得と設定は以下のようなjavascript(jQuery使用)で記述できます。

```video.html
<video id="video" src="..."></video>
```

```video.html
<script>
// 再生位置の取得（単位は秒）
console.log($('#video').get(0).currentTime);

// 再生位置の設定
$('#video').get(0).currentTime = 120;
</script>
```

# 再生位置が更新されたことを検出する

動画の再生中やシークバーで再生位置を変更したときなど、再生位置が更新されたばあい、更新されるたびに timeupdate というイベントが発生します。
このイベントをjavascriptでフックすることで、現在の再生位置をリアルタイムに取得し、それに対して何らかの処理を行うことができるようになります。

```video.html
<script>
$(function() {
  $('#video').on('timeupdate', function() {
    var $(this).currentTime;
    
  });
});
</script>
```

# イベントの発生タイミング
timeUpdateイベントは、再生中はかなり短い間隔で発火します（chrome系ブラウザでは0.2〜0.3秒ごとにイベントが発火していました）。また、再生中、停止中にシーク（スライドバーで動画の再生位置を更新した場合）したときにも即時発火します。

# 再生位置を保存、復元できるようにする
動画の再生位置の保存は、ウェブブラウザ飲みの機能で完結させるのであれば、cookieに保存するのがかんたんかと思います。

jquery cookieを使えば、以下のようなコードで実現できます。

```video.html
<script>
$(function() {
  $('#video').get(0).currentTime = $.cookie("video_play_position");
  $('#video').on('timeupdate', function() {
    // 動画の再生位置を記憶する
    $.cookie("video_play_position", $(this).currentTime, { expires: 7 });
  });
});
</script>
```

情報をcookieに保存しているので、動画再生に使用しているブラウザを途中で変えた場合（例えば、PCで見ていた動画の続きをスマホで見る場合など）などには、このやり方では当然対応できません。

そのようなことをやる場合は、サーバ側にAPIなどを用意し(例えば、https://{hostname}/api/updatePlayTime?video_file_name={video_file_name}&time={time} など）、updateTimeイベント発火時に、動画の再生位置をapi呼び出しを通じてサーバに通知し、サーバ側で最後の再生位置をRDBなどに記憶しておき、ページロード時には最後の再生位置を復元するために、cookieやquery parameterなどで保存している再生位置をクライアントに通知するなどの大雨が必要になります。
【論文紹介】Taste Display that Reproduces Tastes Measured by a Taste Sensor

#論文紹介
論文：Taste Display that Reproduces Tastes Measured by a Taste Sensor
著者：Homei Miyashita
https://dl.acm.org/doi/pdf/10.1145/3379337.3415852


#どんなもの
　味覚センサーで測定した味を再現できる味覚ディスプレイを開発した。5つの基本味を再現した電解質を溶解した5つのジェルにイオントフォレーシス(直流電流を流す方法)を行って、舌に触れるイオンの量を制御した。無味のジェルを加えることで、6つのジェルに流れる電流の合計を一定にして、舌への刺激量を均一にした。味覚センサーの測定値と表示された味のレベルを一致させるキャリブレーションによって、測定された味を再現できた。

#先行研究と比較してすごいところ
　カメラを使って体験そのものを記録・再現することはできる。近年では、ヘッドフォンやヘッドマウントディスプレイのようにあたかもその場にいるかのように仮想的に体験できるようになった。近年は味の記録をする味覚センサーの研究は進んでいるが、味覚を記録・再現するシステムはまだ存在しない。この研究では、味覚を記録・再現する味覚ディスプレイを開発した。
[^1]: 食べることと聞くことが複合的な多感覚体験の中で結びついていること。

#技術や手法のキモ
　5種類の電解水溶液をストローでジェル状に固める。電気を流さずにジェルを舌の上に置くと5つの味を同時に感じることができ、電流を流すことでジェルを個別に弱めることができる。これに加えて
無味のジェルを使って、弱い味を表現させた。電流をコンピュータで細かく制御するシステムを開発した。
　味覚センサーに様々な味を記録して共有し、他の人がその味を端末で体験できるようにするシステム(被験者が映像や音声と一緒に味覚情報を編集できるビデオ編集ソフト)を開発した。


#検証方法
　5つの基本味を示す様々な濃度の電解質水溶液を用意して、それらの味を味覚センサーで測定し、味の強さとそれに対応する電解質水溶液の濃度との関係を表す式を得る。これによって、味覚センサーと味覚ディスプレイの入出力を校正する。

　紅茶にレモンを入れることで苦い紅茶の酸味が増すことを経験してもらうために、紅茶を入れてそこにレモンを加える動画を作成した。それぞれの段階を味覚センサーで測定。
→苦味と旨味のセンサーの数値は味覚ディスプレイの表現範囲に収まっていなかったが、コンテンツを再生すると本物の紅茶の苦味は再現されていないが、苦い紅茶から酸っぱいレモンティーへの酸味の変化は表現できた。

　様々な味覚効果を試作した。まず、5つの基本味のうち最も強い味の成分が味の提示において最大の表現値を生み出すようにするノーマライズ(normalize)効果を作った。full average taste効果、blur効果、sharpen効果などによって、味をより鮮明に表現する。また、5つの基本味の各チャンネルの入れ替えを簡単にして、味の負の反転(苦味、酸味、甘味が混ざったレモンティーに砂糖を混ぜた味を負に反転させると、塩味とうま味が混ざったスープのような味になる) といった効果を生み出した。無味のジェルを使って炭酸の効果を出すことができた。
→酸味が苦手な人には酸味を抑える・塩味が強いのを好む人には強みを強めるといったように個人の好みに合わせて味を調整する「イコライザー」の効果がある。

#議論
　味覚センサーの測定方法では、味覚ディスプレイで表現できる味の範囲に問題があるのでは？(味覚ディスプレイは、原理的に10から0までの値しか生成できない。10未満の入力値は-10にリセットされるが、-10自体が極めて知覚しにくいため、実質的には問題ない。しかし、0以上の強さの味を0にリセットすることは問題になるのでは？)


#気になった論文
　Taste+: Digitally Enhancing Taste Sensations of Food and Beverages(過去の論文)
Ubuntu 20.04にアップグレード後 inkscape がファイル保存時に異常終了する

# 事象

Ubuntu 18.04のときにインストールした inkscape をUbuntu 20.04にアップグレード後に使用したところ、ファイル保存時に異常終了するようになった。

# 環境

動作環境は以下の通り。

```bash
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

$ sudo snap list | grep inkscape
inkscape              1.1-ce6663b3b7-2021-05-25   9090   latest/stable    inkscape*     -
```

# 原因調査

inkscapeを起動してから異常終了するまでのログを確認した。

```bash
$ journalctl -f
...
 6月 19 20:02:05 <HOST_NAME> inkscape[2515855]: Failed to load module "canberra-gtk-module"
 6月 19 20:02:05 <HOST_NAME> inkscape[2515855]: Failed to load module "canberra-gtk-module"
...
 6月 19 20:02:20 <HOST_NAME> inkscape[2515855]: Error creating IO channel for /proc/self/mountinfo: Permission denied (g-file-error-quark, 2)
 6月 19 20:02:20 <HOST_NAME> inkscape[2515855]: Settings schema 'org.gtk.Settings.FileChooser' does not contain a key named 'show-type-column'
```


まず、inkscape起動時(20:02:05)に"canberra-gtk-module"のロードに失敗し、ファイル保存時(20:02:20)に"g-file-error-quark"のマウントに失敗していた。

# 恒久処置

よくわからないので、再インストールしたところ事象が起きなくなった。

```bash
$ sudo snap remove inkscape
$ sudo snap install inkscape
```

# まとめ

inkscapeを再インストールしたら、なおった。
UbuntuにVerilog環境を構築する

UbuntuにVerilogの開発環境を構築するための備忘録メモ

# 必要なアプリケーションのインストール
Verilogのソースから回路図を生成してくれるTKGateがMacでは動作しないため、Ubuntuマシーンに環境構築することに。。。

```bash
sudo apt install -y iverilog gtkwave tkgate
```

# verisimuコマンドの作成
以下の内容を`.bashrc`に追記

```bash
function verisimu() {
    IFS=' '
    filename=$1
    testname=$2
    iverilog ${filename} ${testname}
    vvp a.out
    list=(${filename//./' '})
    vcdname=${list[0]}
    gtkwave ${vcdname}.vcd
}
```

# Reference
* [Verilog HDLで1コマンドでシミュレーション波形を出せる"verisimu"コマンドを実現する](https://qiita.com/y-vectorfield/items/1f426a5044a427329562)
STM32F767と温度,S-5851で液晶温度計 (Mbed)(AQM0802A)


1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

x プログラムは、STM32F303K8と同じ


```c++


#include "mbed.h"

//#define S5851A 0x48
#define ADDR        ((0x48)<<1) //  address
#define ADDR_LCD    (0x7C)      //  address

I2C i2c(I2C_SDA, I2C_SCL); //767 303
//I2C i2c(dp5, dp27); //1114
//I2C i2c(PA_10, PA_9); //010

//10の割り算 0から1028までは、正しい。主に0から999
#define DVI10(n) ((n*205)>>11)

int     tempval;        //温度
char    data_read[6];   //i2cバッファー
int     n10;            //10の桁
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};

int main()
{

    //液晶の初期化
    for(ii=0;ii<11;ii++){
        i2c.write(ADDR_LCD, &INIT_com[ii*2], 2);
        wait_ms(2);
    } //for

    while (1) {

        //液晶のクリア
        i2c.write(ADDR_LCD,INIT_cls,2);
        wait_ms(2);

        //初期化
        //set address 0
        i2c.write(ADDR, "\000", 1); //addres 0

        //温度の読み込み
        // Read temperature register
        i2c.read(ADDR, data_read,1,false);

        //温度の保存
        // Calculate temperature value in Celcius
        tempval =  data_read[0];

        //tempval = 12; //debug

        //計算
        // Calculation temp
        n10 = DVI10(tempval);             //10の桁
        tempval = tempval - ( n10 * 10 ); //1の桁

        //液晶に出力
        // Display result
        data_read[0] = '@';
        data_read[1] = '0' + n10;
        data_read[2] = '0' + tempval;
        //data_read[3] = '\r';
        //data_read[4] = '\n';
        data_read[3] = 0;
        i2c.write(ADDR_LCD, data_read ,3);

        //1秒待つ
        wait_ms(1000);

    }//while

}//main




```

![i2c_lcd_s5851_767.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/84dcf6ff-15dd-027f-cd61-18aa8a9eed44.jpeg)
三角形と線分の交差判定の高速化について

# はじめに

せっかく調べたのでノートです. [Fast Ray-Triangle Intersections by Coordinate Transformation](http://jcgt.org/published/0005/03/03/)を見つけてしまったので.

# 説明
三角形ごとに, 正規化された座標系への変換行列を事前計算しておくことで, 交差判定を高速化しようという提案です.

# 考察
3角形を構成する3点を保存する代わりに, 3次元の線形変換行列を保存する必要があります. 3x4の行列で12要素になります. 論文では1列が必ず定数になることを使って, 3x3の行列と, どの列が定数かのフラグで圧縮できるとあります.

- 元の3点の座標を保存する必要がある場合, 余分なメモリコストを許せるか
- メモリコスト
    - 圧縮版でもフラグは必要
        - フラグはどこかの軸の最下位ビットを犠牲にすれば圧縮できるが, 余計な計算が必要
- SIMDと相性がわるそう
    - 分岐はさせたくない

# 注意点

法線で除算しているため, 面積が0の三角形ではNaNになる. 次の3番目の対処もできると思います.

1. 面積0の三角形を削除する
2. 判定時にNaNのチェックをする
3. 変換行列を交差すると判定しない値にする

# まとめ
特定の環境では価値があるかもしれないので, ノート.
numpy高速化のためのcupyで、GPU関連エラーを解決したときのメモ（備忘録）

##環境
Ubuntu 20.04.1 LTS
GeForce RTX 2070 SUPER
Nvidia ドライバ 455.38
CUDA Version 10.1.243
python 3.7.3
anaconda-navigator 2.0.3
VS code 1.57.1
anaconda上で仮想環境を作り、その中でVS codeを使っています。

##背景
受講中の講座の課題提出において、Kerasなどのライブラリを使わずにnumpy中心で画像認識のディープラーニングモデルを構築する必要がありました。データ水増する予定でしたがCPUのみでは時間がかかりすぎるので、cupyをインストールしてGPUによる高速化を図ることにしました。
デバッグ中、だいたい同じところで下記を含む謎のエラーが大量に出て止まりました。

~~~
cupy_backends.cuda.api.runtime.CUDARuntimeError: cudaErrorIllegalAddress: an illegal memory access was encountered
~~~

原因切り分けに時間がかかりましたが、一度、通ったはずのfowardが後の方でエラーとなることや、NVIDIA-SMIのGPUメモリ使用状況が上限になるとエラーとなっていることがわかり、cupyがGPUのメモリを使いきったことが原因とおおよその見当がつきました。
[numpyを使ったプログラムをGPUで動かす方法](https://blog.mktia.com/gpgpu-with-cupy/#%E6%B3%A8%E6%84%8F%E7%82%B9)　を参考に  cuda.set_allocator を入れたところ、前よりはepocが進むようになりましたが、やはり途中で止まってしまいました。

~~~
import cupy as cp
#以下を追加
# Declare at first
pool = cp.cuda.MemoryPool(cp.cuda.malloc_managed)
cp.cuda.set_allocator(pool.malloc)
~~~


##結論
仮想環境構築時にインストールされているcupyではなく、[https://cupy.dev/](https://cupy.dev/)　を参考に、cupy 8.3 から　cupy-cuda100　に入れ替えました。もしかしたら、単にバージョンの相性が悪かったただけでcupy 9.1　を普通に選んでインストールすれば良かっただけかもしれませんが、無事にnumpyをcupyに置き換えたプログラムが走るようになりました。

学習時は早くなったと実感できるのですが
[Chainer Tutorials : 10_Introduction_to_CuPy.ipynb](https://colab.research.google.com/github/chainer/tutorials/blob/master/ja/10_Introduction_to_CuPy.ipynb#scrollTo=GAL3R4HofKzk)　をローカルで実施した結果は、下記のようになっています。N:10000　の 1.09は微妙です。ちなみに、今にして思えば、cupy入れ替え前では、N:10000のみCPUに負けていたという謎の状況でしたので、それよりは改善しています。


~~~
    N    NumPyでの実行時間 (sec)    CuPy での実行時間 (sec)  高速化倍率
-----  -------------------------  -------------------------  ------------
   10                0.000138521                0.000464439  0.30 x
  100                0.00229764                 0.00128341   1.79 x
 1000                0.0522327                  0.0396926    1.32 x
10000               17.228                     15.8261       1.09 x
~~~




##手順
anaconda上で普通にアンインストール、インストールするだけですが、cupy-cuda100　はcondaでは見つからないので、pipでのインストールになります。

~~~
conda uninstall cupy
（依存関係でダウングレードするファイルが多数あるようで、yes/noを聞いてくるまで結構、時間がかかりりました。）
pip install cupy-cuda100
~~~


conda listの結果（抜粋）

~~~
cudatoolkit               10.0.130                      0  
cudnn                     7.6.5                cuda10.0_0  
cupy-cuda100              9.1.0                    pypi_0    pypi
~~~
Goのfreshで出るエラー inotify_init: too many open files の解決方法

# Goのプロジェクトを、Docker上でfreshでホットリロードさせたかった

```sh
:
app_1    | 10:47:32 watcher     | Watching hoge....
app_1    | 10:47:32 watcher     | Watching fuga......
app_1    | inotify_init: too many open files
```

の流れで落ちました。
freshを切るとエラーが出ないことを確認し、freshのホットリロード用で監視するファイルが多すぎてエラーが出ているようでした。

## 解決方法 1

ファイルの開ける数が、どうも初期設定だと128までの模様。

```sh
$ sudo emacs /etc/sysctl.conf
```

`sysctl.conf`を開いて、`fs.inotify.max_user_instances`を探します。
既に項目があれば、

```
fs.inotify.max_user_instances = 1024
```

に値を置き換えます。
項目が無ければ、追記しましょう。
（私はありませんでした）

最後に、設定ファイルを読み直します。

```sh
$ sudo sysctl -p
$ sudo sysctl -a
```

これで解決しました。

## 解決方法 2

巨大外部ライブラリ等をホットリロード用に監視すると、余裕で1024ファイル超えます。
それらの監視も必要なのであれば、解決方法1のファイル数を増やしましょう。
明らかに監視する必要のないファイルがある場合は、以下のように設定ファイルを置いて監視するファイルを制限しましょう。

`fresh`コマンドを実行するディレクトリに設定ファイルを置きます。

```fresh.conf
root:              ./
tmp_path:          ./tmp
build_name:        api
valid_ext:         .go, .tpl, .tmpl, .html
no_rebuild_ext:    .tpl, .tmpl, .html
ignored:           ./vendor, tmp
build_delay:       600
colors:            1
```

公式の例から引用しています。
その他コンフィグの値は公式リポジトリのREADMEに簡単な例があります。
[gravityblast/fresh](https://github.com/gravityblast/fresh)

## 参考
[issue \#44](https://github.com/gravityblast/fresh/issues/44)
Linux: ダミープロセスの作成方法

シェルスクリプトの単体試験でたまに使用するのでメモしておきます。

実施環境：

```Linux:Linux
[testuser@testhost ~]$ uname -a
Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[testuser@testhost ~]$ echo $SHELL
/bin/bash
```

シェルスクリプトの単体試験等で、たまに特定の文字列を含むダミープロセスを作成したいときがあります。
そのような場合、yesコマンドを使用すると簡単に実現できます。

```Linux:Linux
[testuser@testhost ~]$ ps aux | grep -v grep | grep "test proc"
[testuser@testhost ~]$
[testuser@testhost ~]$ yes test proc >/dev/null 2>&1 &
[1] 2770
[testuser@testhost ~]$ i=$!
[testuser@testhost ~]$ echo $i
2770
[testuser@testhost ~]$ ps aux | grep -v grep | grep "test proc"
testuser     2770 99.7  0.0 217040   828 pts/0    R    21:10   4:42 yes test proc
[testuser@testhost ~]$ kill -9 $i
[testuser@testhost ~]$
[1]+  Killed                 yes test proc > /dev/null 2>&1
[testuser@testhost ~]$ ps aux | grep -v grep | grep "test proc"
[testuser@testhost ~]$
```

yesコマンドは指定した文字列を標準出力に出力し続けるコマンドです。
含みたい文字列を引数に指定し、出力は全て"/dev/null"に捨て、"&"でバックグラウンドで実行しています。
"$!"は実行したコマンドのプロセスIDが格納される変数です。
なお、別窓で実行できるなら、フォアグラウンドで実行し、不要になったらCtrl+Cで停止するでもよいです。
tmuxにリマインダーをやらせる

# 根本的な問題
基本、僕はいつも文字で埋め尽くされた黒い画面を見ています。
そんで、**Googleに登録したTODOリストを見忘れます。**
「クソADHD野郎死ね！」とか思われてるんだと思い、悲しくなります(´；ω；｀)

真面目に仕事して、黒い画面と格闘している時に通知がスマホに来ても無意味なんです。
そして、黒くない画面の通知って雑多な物が多すぎて目に入らないんですよね…。

大事な通知を黒い画面に映したい。だけど、シェルに通知は荷が重いし、
tmuxのセッション毎に別世界な感じなので辛かった。


# tmuxに通知を表示すればいいじゃん！
それだけじゃん！右上に注目。
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139153/f707f086-4645-9788-1b2b-902a9f67989d.png)

(僕のプロンプトは普段からこの恥ずかしい感じのプロンプトなのです。
普段から黒い画面見続けてて、潤いが欲しかったので…。)

# どうしたのか
tmuxはステータスバーにシェルの結果を表示することが出来ます。
このステータスバーは設定によって違うのですが、周期的に更新されます。
なので、例えば```$HOME/.notify```のようなパスのテキストファイルを
常に読みに行くとかそういうことが出来るわけです。
まぁ、ディスクに書き込むのが気持ち悪いなら、RAMディスクなりネット上なりにおけば良いと思います。
ネット上の何かを持ってくるとか、Github経由のdotfilesなら共有的な感じになりますね？

## tmux
.tmux.confは以下のようにしました。

```tmux
set -g status-right '#[fg=colour0]#[bg=colour40]#(cat $HOME/.notify)#[fg=colour40]#[bg=colour0] %a %h-%d %H:%M'
```

## シェルスクリプト側

```bash
notify() {
  if [ -p /dev/stdin ]; then
    if [ "`echo $@`" == "" ]; then 
      ARG=`cat -`
    else
      ARG=$@
    fi
    else
      ARG=$@
  fi
  echo "${ARG}" > $HOME/.notify
}
```

こんな感じにすれば、好きなように通知っぽくtmuxを使えるわけです。
あとは好きなように通知領域を使っちゃえば良いのです。

## リマインダーとして
atコマンドを使えばリマインダーとして使えるなっと思いました。
atコマンド、僕の環境でははじめから使えるわけじゃなかったので、aptでインスコしましたけれどね。

```bash
notify_at () {
  cal
  echo What time? ex: 15:40
  read TIME
  echo What year? ex: 2023
  read YEAR
  if [ -z "$YEAR" ]; then
    YEAR=$(date +%Y)
  fi
  echo What month? ex: 06
  read MONTH
  if [ -z "$MONTH" ]; then
    MONTH=$(printf %02d $(($(date +%m))))
  fi
  echo What day? ex: 14
  read DAY
  if [ -z "$DAY" ]; then
    DAY=$(printf %02d $(($(date +%d))))
  fi
  echo "echo $1> $HOME/.notify" | at $TIME "$MONTH$DAY$YEAR" 
  echo $1 at $TIME $MONTH$DAY$YEAR >> .notify_log
}
```

出力はこんな感じになります。ついでにどんなリマインドをしたのかもメモっておきます。

```
notify_at ウスターソースを買う
     June 2021
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

What time? ex: 15:40
12:00
What year? ex: 2023

What month? ex: 06

What day? ex: 14
17
warning: commands will be executed using /bin/sh
job 11 at Thu Jun 17 12:00:00 2021
```

# えっ、そんだけ？
そんだけです。多分、生活を良くするって、そういう小さい積み重ねです。
[HTML]textareaの拡大/縮小の禁止と、サイズの固定方法

## はじめに
本記事はフォームのテキストエリアの拡大、縮小の禁止とサイズの固定方法について記述した記事です。


## やり方
#### 1. 拡大縮小の禁止
テキストエリアは拡大縮小できるのでユーザー操作でレイアウトが勝手に変わることがあります。その場合は以下のように`resize: none`を指定することで大きさを完全に固定できます。

```
textarea {
  resize: none;
  width:400px;
  height:200px;
}
```

#### 2.横方向のみサイズを固定
横方向のみ固定したい場合は`resize: vertical`を指定します。

```
text{
  resize: vertical;
  width:400px;
  height:200px;
}
```

#### 3.縦方向のみサイズを固定
縦方向のみを固定したい場合は`resize: horizontal`を指定します。

```
text{
  resize: horizontal;
  width:400px;
  height:200px;
}
```

#### 4.最大幅と最小幅を指定する。
リサイズを使用した場合は、`max`系と`min`系を使うことによって最大、最小のサイズを設定できます。

```
textarea {
  resize: auto;
  max-width: 300px;
  max-height: 400px;
  min-width: 300px;
  min-height: 200px;
  width: 300px;
  height: 200px
}
```
SafariおよびWebKitにて、要素に適用されるCSS colorプロパティの値が変化したにも関わらず、直ちにレンダリング結果に反映されない問題を回避

SafariおよびWebKitにて、要素に適用されるCSS colorプロパティの値が変化したにも関わらず、直ちにレンダリング結果に反映されない問題（発生条件不明）を回避:

Workaround for the issue that the rendered result on the latest Safari and WebKit in some cases doesn't reflect the changed CSS color property value that has just been applied to the element:

```css
.YOUR_SELECTOR_FOR_THAT_ELEMENT {
    transition: color 1ms linear 0ms;
}
```
colcon build中にubuntuデスクトップがフリーズするときの対処方法　ROS2


ラズパイなどのメモリの少ないPCでROS2を使っていて、SLAMなどの重いパッケージをcolcon build する際に画面がフリーズすることがあります。

その時の対応方法のメモ。


## MAKEFLAGS環境変数を設定する

colcon build前にMAKEFLAGS環境変数で並列処理する数を指定

例


```bash
cd ~/ros2_ws
MAKEFLAGS=-j1
colcon build
```

## colcon buildのオプションを使用する

colcon buildの--parallel-workersオプションで同時にビルドするパッケージ数を指定

例

```bash
cd ~/ros2_ws
colcon build --parallel-workers 1
```


## メモリのSWAP領域を増やす

https://qiita.com/gitcho/items/d38b77ce746b5de872f0


# 参考

https://github.com/rt-net/raspimouse_ros2_examples/issues/23


colconビルドで便利なオプション

https://qiita.com/seshimaru/items/ed344530ead80ab1733f
React+TypeScriptアプリの作り方

# 目的

React+TypeScriptのサンプルアプリを作って、そこでReact+TypeScriptアプリの書き方を練習したい。

# 環境情報

macOS Catalina 10.15.7

```
$ node -v
v16.3.0

$ npx create-react-app --version
4.0.3
```

## node のバージョンは何にすればいい？

プロダクションアプリケーションでは、アクティブ LTS または メンテナンス LTS リリースのみを使用することがすすめられているけど、今は勉強に使うだけなので、最新版にする。(2021/6/19時点でv16.3.0)

https://nodejs.org/ja/about/releases/

# インストール

```
$ npx create-react-app my-app --template typescript
```

`Happy hacking!` と表示されて完了。

# 実行する

`Happy hacking!` のメッセージの上にあった以下の手順で実行する。

```
$ cd my-app
$ npm start
```

ブラウザが開いてアプリが表示された。
表示されない時でも、実行ログに表示されている`http://localhost:3000`にアクセスすればOK。

# 感想

かんたん！


# 参考

https://qiita.com/sunnyG/items/05c2e9381d6ba2d9fccf

https://create-react-app.dev/docs/adding-typescript/