OmniAICreator/Qiita-1.07M huggingface dataset:
【HTTP/HTTPS】このページってS（HTTPS）ですよね？

ある日、自席で作業をしていると"ある会話"が聞こえてきました。

<b>このページってSですよね？</b>

PJのリーダーがクライアントさんとの打ち合わせを終えて、私の近くの席の上司に打ち合わせの内容を確認をしているようでした。
会話の流れから、このSというのはHTTPSのSだということはすぐに分かりました。
ただHTTPとHTTPSで何が違うのかと考えてみるとHTTPSのほうがセキュリティが強い？しか頭には浮かばずでした。

今回も調べつつにはなりますがまとめてみました。
#こいつらって何者？
こんな機会もなければ調べないと思ったので、まずは何の略称なのかを調べてみました。
HTTP:Hypertext Transfer Protocol （ハイパーテキスト トランスファー プロトコル）
HTTPS：Hypertext Transfer Protocol Secure（ハイパーテキスト トランスファー プロトコル　セキュア）
Secureが末尾にいることからセキュリティ面に強そうな印象を受けます。

話がずれますが、Security(セキュリティ)は分かるけどSecure?だと聞きなれないので調べてみました。
>〔攻撃・危害・損害などを受けないと感じて〕不安のない、恐れる必要のない、安心していられる

ちなみにSecurityはこうでした。
>〔危険などのない〕安全、無事、治安

似ているようで少し違いますね。
脱線しましたが、HTTPとHTTPSの大きな共通点は通信規約（プロトコル）であるということですね。
~~おおっと何となく理解しているシリーズが登場してしまいました。~~
[プロトコルとは（Protocol の本来の意味から技術英語へ）](https://qiita.com/KEINOS/items/cb7f629268b90ef6493d)
プロトコルについて書くのは脱線が止まらなくなる気がしたので、書きながら参考にさせていただいた記事を貼っておきます:clap:
かなりユーモアあふれる記事だったので、プロトコルへの理解が明るい方もそうでない方も是非読んでみてください。
##HTTPとは
HTTPは<b>一般的な通信規格</b>です。
HTMLファイルや画像ファイルをやり取りするときに主に用いられます。
HTTPは<b>ユーザーの情報（アカウント情報やクレジットカード）の入力を求めるようなページ以外</b>で使われていたことが多かったようです。
少し、HTTPSの先取りになりますが、HTTPは通信内容が暗号化されていないためサイバー犯罪の被害にあう可能性があります。
上記のような個人情報に関わるようなページにはNGであることが分かります。



##HTTPSとは
HTTPSはサーバーとの通信を暗号化することにより<b>安全性を高めている通信規格</b>です。
仮にHTTP通信でユーザーの情報の送受信を行ってしまうと、第三者が簡単に読み取ることができてしまいます:imp:
これはセキュリティの観点から見てとても脆弱性があるということに…。
対して、HTTPSを用いて情報を暗号化することで第三者が読み取れたとしても内容の解読ができなくなります。
（正確には難しくなると言ったほうがいいのかもしれません）
これを知った私は全てHTTPSにすることで世の中が平和になるのではないかと思いました:v:
現在、私が携わっている案件も原則HTTPSのページで運用すると伺いました。
近年ではページを問わず、<b>HTTPS化を推進する動き</b>もあります。
[HTTPS をランキング シグナルに使用します](https://webmaster-ja.googleblog.com/2014/08/https-as-ranking-signal.html)
これについては全く知らなかったです。
内容としては、HTTPSのサイトをgoogleの検索エンジンのアルゴリズムの要素として導入しているというものでした。

##証明書を確認してみる
HTTPSのサイトでは証明書を確認することができます。
実際に今編集中のページで確認してみました。
①画面上部のURL横のカギマークをクリック:point_up:
次に証明書をクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567774/a4a2a24d-7d8c-02af-c178-9e5d65ea58b7.png)
②証明書をクリックすると下記のような画面になります。
この証明書は問題ありません。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567774/9d738423-90b8-23b6-6fd2-5ebf4d3da0e3.png)
※HTTPのサイトは以下のようになります。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567774/d1033c66-b5cf-ce90-c7f8-80eb459e010f.png)
毎日のように使っているインターネットですが、このように差を確認できるのは知りませんでした。


#まとめ
仕事中、よく耳にするHTTP/HTTPSでしたが改めて<b>HTTPSはHTTPに比べて安全である</b>ことが確認できました。
~~今となっては1週間に何回かお聞きする機会がありますが、新人の頃は何の暗号だろう？という気持ちでした…~~

今回はこちらのサイトを主に参考にしました。
[httpとhttpsの違いとは？今更聞けない「s」の意味](https://ms.repica.jp/column/20191227_http_https/)
[【初心者向け】HTTPとHTTPSの違いって何？](https://qiita.com/cryptobox/items/235a0c5fc872d5757423)
CloudFrontにHTTPセキュリティヘッダーを追加する方法(2021)

### はじめに

[CloudFront](https://aws.amazon.com/jp/cloudfront/) で単純にHTTPヘッダーを追加するようなカスタム方法は、2021/6現在 [Lambda@Edge](https://aws.amazon.com/jp/lambda/edge/) よりも [CloudFront Functions](https://aws.amazon.com/jp/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/) が良さそう。下記のケースで私はFunctionsを使いました。

### セキュリティヘッダー

- [Strict-Transport-Security](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Strict-Transport-Security)
- [Content-Security-Policy](https://developer.mozilla.org/ja/docs/Web/HTTP/CSP)
- [X-Content-Type-Options](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options)
- [X-Frame-Options](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options)
- [X-XSS-Protection](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection)
- [Referrer-Policy](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Referrer-Policy)

そもそものセキュリティ対策ということもあるけど、[Mozilla Observatory](https://observatory.mozilla.org)などのセキュリティスキャナーを通してくれって場合に対応が必要。

### Lambda@Edge

これらのヘッダー群を CloudFront で設定しようと調べると2021/6月現在は Lambda@Edge での実装例が検索上位に掲載される。

たとえば

https://dev.classmethod.jp/articles/cloudfront-lambd-edge-http-security-header/

元記事となるAWSの公式ブログだと

https://aws.amazon.com/jp/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/

いや、これでやろうと思ってた。TerraformでやろうとしたらLambda作ってIAM付与してCloudFrontに紐付けしてと…。

### CloudFront Functions

しかし、よくよく調べると、2021/5に CloudFront Functionsがリリースされていた。こっちでやるほうが簡単で楽だし、今回の用途的に向いてると思う。いや、そもそもCloudFront自身にヘッダー変更する機能があればよいのだが。

やりたいことはAWSのドキュメントにあった、

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-security-headers.html

GitHubにサンプルもある。

日本語でわかりやすいのは

https://dev.classmethod.jp/articles/amazon-cloudfront-functions-release/

### Terraform

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_function

CloudFront Functionsを用意してaws-samplesの[JavaScript](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-security-headers)をベースに置いて(とりあえずサンプル通りでOK)

```hcl
resource "aws_cloudfront_function" "test" {
  name    = "test"
  runtime = "cloudfront-js-1.0"
  comment = "my function"
  publish = true
  code    = file("${path.module}/function.js")
}
```

ディストリビューションに紐付けすれば良し

```hcl
resource "aws_cloudfront_distribution" "example" {
  # 省略
  default_cache_behavior {
    function_association {
      event_type   = "viewer-response"
      function_arn = aws_cloudfront_function.test.arn
    }
  }
  # 省略
}
```
localStorageまとめ

 業務でlocalStorageを取り扱うことがあったのでメモ。

## localStorageとは？
javascript利用することでユーザーのデータをwebブラウザ(ローカル環境)に保存することができる仕組み
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943722/8a1b5a9f-4c07-78c1-a3c4-8dd19a7aff39.png">

## 構文
## localStorage にデータを保存

``` 
localStorage.setItem('key', 'value');
```
key, valueの形で保存できる。連想配列
## localStorage に保存したデータを取得

```
const data = localStorage.getItem('key');
```
keyを指定すれば、dataにvalueが代入される
## localStorage に保存したデータを削除

```
localStorage.removeItem('key')

```
keyを指定すれば、kyeとvaluがセットで消える

## localStorage　の文字数期限


- 保存可能な文字数期限はブラウザ毎に異なっていて、主要なブラウザでは最大5MB

- これは、キー名単位ではなくドメイン単位での文字数制限

## localStorage の有効期限

- 有効期限はない
- ユーザーがブラウザの機能を利用してデータを削除するか、removeItem()やStorage.clear()が実行された場合のみデータが破棄される
【CPU】基本情報技術者試験のためのコンピュータの構成

※この記事は
「栢木先生の基本情報技術者教室」を参考に学んだことをまとめた記事です。

##CPUについて

* CPUとはコンピュータの頭脳であり、**プロセッサ** ともいう
* クロック信号とは一定の間隔で電圧が「高」と「低」を繰り返す信号(クロックパルスともいう)
* クロック周波数とはクロック信号が1秒間に繰り返される回数のこと
* 単位としてはHz(ヘルツ)が使われる
* CPU内部のクロック周波数=内部クロック　 CPUと主記憶などの周辺回路を結ぶ伝送路のクロック周波=外部クロック
* 内部クロック＞外部クロック（速さ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965248/f1017cdf-89c4-0ab5-0bbb-b71610c9f3d7.png)

* **バス** とはCPUや主記憶、キャッシュメモリなどでお互いがデータを送受信するための伝送路のこと
Internet ExplorerEmulatorでWebサイトをテストしてみてください

Internet Explorer は 1995 年に発売され、それ以来、最も人気のあるブラウザーの 1 つであり続けています。

1995年から2013年の間に、InternetExplorerには11の異なるバージョンがありました。 これは、最後の更新が7年以上前にリリースされたことを意味します。 2016年1月、Microsoftは、IE10以前のバージョンのサポートを提供しないことを正式に発表しました。
![Безымянный.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526222/1fb07114-f58d-fb13-d65f-e92f9beae633.png)
サポートがなくても、Internet Explorerの市場カバレッジは28％と非常に大きいです。 普及率が高い他のブラウザはGoogleChromeだけで、市場の35％を占めています。 2019年3月、Microsoftの最高セキュリティ責任者であるChris Jacksonは、最新のブラウザを優先して、IEの使用を絶対に避けてください。 ただし、ジャクソン氏の訴えは平均的なユーザーには聞かれておらず、そのため、企業はそのユーザー層をターゲットにしたい場合に適応する必要があります。

Internet Explorerは最も古いブラウザの1つですが、それでも人々はそれを使用しています

非常に多くのユーザーがまださまざまなバージョンのInternetExplorerを使用しているため、エミュレートは引き続き優先事項です。 Internet Explorerシミュレーターは、より多くのユーザーが製品を利用できるようにするのに役立ちます。多くの企業が依然としてInternetExplorerの使用を余儀なくされているため、IEブラウザのテストも必須です。さまざまな基幹業務ツールは当初、Internet Explorerを念頭に置いて設計されており、Internet Explorerブラウザーのテストを無視すると、企業に深刻な影響を与える可能性があります。

エンタープライズシステムとオフィスイントラネットの青写真は、当時最も人気のあるブラウザで設計されています。それはたまたまInternetExplorerでした。すでにすべてのマシンにインストールされており、完全にサポートされていましたが、他のブラウザに対応する理由はありませんでした。

ただし、廃止されたため、企業が他のブラウザに移行したわけではありません。高いコストと人的資源の要件により、一部のセクターの企業は移行を遅らせる必要があります。製薬会社、ロジスティクス、および大企業は、InternetExplorerで立ち往生しているビジネスのほんの一例です。

Internet Explorerをエミュレートする必要があるのは誰ですか。その理由は何ですか。

このような市場の大きな部分を逃したくない企業は、Internet Explorer をエミュレートする手段に投資する必要があります。 Web サイトが IE のすべてのバージョンに完全に統合されていることを確認しないと、主に世界のあまり進んでいない地域にいるユーザーの適切な使用が危険にさらされます。

Internet Explorer 8をエミュレートするもう1つの主な理由は、古いIEバージョンでヘルスケアおよび製薬会社によって取得されたStudy and ResearchCertificationです。 別のブラウザとオペレーティングシステムの組み合わせにアップグレードする場合は、FDAに新たに認証を要求する必要もあります。

WebテストにInternetExplorerエミュレーターを使用する利点

同じマシンで複数のバージョンの IE を実行するのは困難です。これは、ランタイムバージョンの競合とさまざまなオペレーティングシステムの非互換性が発生するためです。 Internet Explorer エミュレーターのオンライン ソリューションは、開発者の作業負荷を軽減し、ビジネス コストを削減します。

を使用するもう 1 つの利点 [Internet Explorer emulator for Mac] (https://comparium.app/blog/internet-explorer-emulator/) または Windows は、さまざまなバージョンの IE を手間をかけずに切り替えることができるという事実です。 これにより、開発チームの負担が軽減され、より重要なプロジェクトに集中できるようになります。 訪問者を引き付けて会社や製品を紹介したい場合は、クロスブラウザテストに投資する必要があります。 ブラウザー テスト Internet Explorer は、すべてのバージョンでユーザー数が非常に多いため、最初に対象とするブラウザーの 1 つにする必要があります。

Webサイトを再設計したい場合、またはWebサイトへの投資が確実に報われるようにしたい場合は、InternetExplorerだけでなく他のブラウザーでも問題なく動作することを確認する必要があります。 そのため、テスターの大多数は、さまざまなブラウザー、ブラウザーバージョン、およびオペレーティングシステムでWebサイトのパフォーマンスをテストできる強力なアシスタントである[Comparium](https://comparium.app/)などの多用途のソリューションを好みます。

![Безымянный3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526222/e2b9d3ba-bdbc-3895-6759-24e077e2ee23.png)

現在 Comparium はスクリーンショットモードでのIEブラウザテストをサポートしています。 Internet Explorerのエミュレーションに関しては、この機能は将来のアップデートで追加される予定です。
WebPack-DevServerのバグの対応

詳しいことはよくわからないがDevServerでホットリロードできなくなる問題がある模様

# 解決法
configのtargetをwebに書き換える

```js:webpack.config.js

module.exports={
...
target:"web" //ふつうは["web","es5"]とかかな？
...
}

```

けどこの方法だと、ビルドするときに戻さないといけなくなる

# 解決法改
[ドキュメント](https://webpack.js.org/configuration/mode/)によると
オブジェクトの代わりに関数をエクスポートすると、実行時のモードによって
動作を変更できるらしい

```js:webpack.config.js
const config ={
...
}
module.exports = (env, argv) => {
  if (argv.mode !== 'production') {
    config.target = 'web';
  }
  return config;
};
```
これでおそらくは大丈夫と思う
Ruby基礎まとめ② （クラス、インスタンス、継承） 

##はじめに
Progateで学習したRubyの内容を自分なりにまとめておく。

##クラスとインスタンス
「もの」を作る際の「設計図」をクラス、「もの」をインスタンスと呼ぶ

1.　クラスを用意する
2.　クラスからインスタンスを生成する
3.　インスタンスに情報を追加する

```ruby
# 1. クラスの用意
class クラス名
  attr_accessor :シンボル  # この情報のことをインスタンス変数という
  def メソッド名 # インスタンスメソッド
     処理
     #{self.変数名} # インスタンス変数を使うことができる
  end
end

# 2. インスタンスの生成
インスタンス名 = クラス名.new

# 3. インスタンスに情報を追加する
インスタンス.変数名 = 値
```

###インスタンスの初期化
initializeメソッド
`クラス名.new`が実行されると、空のインスタンスが生成される。
initializeメソッドがあれば、自動で呼び出される。

例）

```ruby
class Menu
  attr_accessor :name
  attr_accessor :price

  def initialize(name:, price:) # initializeメソッドに引数を渡す。
    self.name = name
    self.price = price
  end

  def info
    return "#{self.name} #{self.price}円"
  end

  def get_total_price(count)
    total_price = self.price * count
    if count >= 3
      total_price -= 100
    end
    return total_price
  end
end

menu1 = Menu.new(name:"すし", price:1000)
puts menu1.info
```

##ファイルの分割
index.rb(プログラムの実行部分)とmenu.rb(クラスの定義部分)にファイルを分割する。

```ruby:index.rb
require "./menu"  # menu.rbの読み込み
menu1 = Menu.new(name:"pizza", ...)
...
```

```ruby:menu.rb
class menu
  attr_accessor :name
  attr_accessor :price
  ...
end
```

###入力を受け取る
`gets.chomp`を用いることで、コンソールが入力待機状態となる

```ruby
変数 = gets.chomp  # とすると入力された情報を文字列として受け取る
変数 = gets.chomp,to_i  # とすることで、数値に変換することもできる
```

###ファイル分割の例
```ruby:index.rb
require "./menu"

menu1 = Menu.new(name: "ピザ", price: 800)
menu2 = Menu.new(name: "すし", price: 1000)
menu3 = Menu.new(name: "コーラ", price: 300)
menu4 = Menu.new(name: "お茶", price: 200)

menus = [menu1, menu2, menu3, menu4]

index = 0
menus.each do |menu|
  puts "#{index}. #{menu.info}"
  index += 1
end

puts "--------------"
puts "メニューの番号を選択してください"

order = gets.chomp.to_i
selected_menu = menus[order]

puts "選択されたメニュー: #{selected_menu.name}"
puts "個数を入力してください(3つ以上で100円割引)"

count = gets.chomp.to_i
puts "お会計は#{selected_menu.get_total_price(count)}円です"
```

```ruby:menu.rb
class Menu
  attr_accessor :name
  attr_accessor :price

  def initialize(name:, price:)
    self.name = name
    self.price = price
  end

  def info
    return "#{self.name} #{self.price}円"
  end

  def get_total_price(count)
    total_price = self.price * count
    if count >= 3
      total_price -= 100
    end
    return total_price
  end
end
```

##継承
あるクラスを基にして新たなクラスを作ることを「継承」という

```ruby
class 子クラス < 親クラス
  attr_accessor :シンボル # 子クラスにインスタンス変数を追加する
  def　メソッド名 # 子クラスにインスタンスメソッドを追加する
                # 子クラスで親クラスを同じ名前のメソッドを定義すると、子クラスの方が呼び出される(オーバーライド)
     super(シンボル名: 引数) # 親クラスの同名メソッドを呼び出す
     処理
  end
end
```

###クラスメソッド
クラスに対して呼び出すメソッド

```ruby
def クラス名.メソッド名
  処理
end
クラス名.メソッド名 # で呼び出す
```

###インスタンスメソッドの定義
インスタンスに対して呼び出す

```ruby
def メソッド名
```

###継承の例
Menuクラスを継承

```ruby:food.rb
require "./menu" # 親クラスの読み込み

class Food < Menu # 子クラスの定義
  attr_accessor :calorie # 子クラスのインスタンス変数

  def initialize(name:, price:, calorie:) # オーバーライド
    super(name: name, price: price) # 親クラスの同名メソッドを呼び出す
    self.calorie = calorie
  end

  def info # オーバーライド
    return "#{self.name} #{self.price}円 (#{self.calorie}kcal)"
  end

  def calorie_info
    return "#{self.name}は#{self.calorie}kcalです"
  end
end
```


##おわりに
次回はデータベースの基礎についてまとめようと思う。
【備忘録】DockerでPythonのWebアプリケーションをNginx + Gunicorn で起動する


# インストールされているか確認
```
$ docker --version
Docker version 20.10.7, build f0df350

$ docker-compose --version
docker-compose version 1.17.1, build unknown
```

# build
```
$ sudo docker build -t appname:latest .
$ sudo docker-compose up -d
```

# docker-composeでエラー発生
```
$ sudo docker-compose up -d
ERROR: Version in "./docker-compose.yml" is unsupported. You might be seeing this error because you're using the wrong Compose file version. Either specify a supported version (e.g "2.2" or "3.3") and place your service definitions under the `services` key, or omit the `version` key and place your service definitions at the root of the file to use version 1.
For more on the Compose file format versions, see https://docs.docker.com/compose/compose-file/
```

# versionを指定してインストールし直した
```
$ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

$ sudo chmod +x /usr/local/bin/docker-compose

$ sudo docker-compose --version
docker-compose version 1.22.0, build f46880fe
```

# コンテナ起動を確認
```
$ sudo docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS          PORTS                               NAMES
6c2ce238f6df   nginx:1.17.7       "nginx -g 'daemon of…"   11 seconds ago   Up 10 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   nginx
88e4dbc3754e   appname:latest     "gunicorn config.wsg…"   12 seconds ago   Up 10 seconds                                       appname
```

# ログを確認
```
$ sudo docker logs -f appname
[2021-06-14 10:37:38 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2021-06-14 10:37:38 +0000] [1] [INFO] Listening at: unix:/var/run/appname/appname.sock (1)
[2021-06-14 10:37:38 +0000] [1] [INFO] Using worker: sync
[2021-06-14 10:37:38 +0000] [8] [INFO] Booting worker with pid: 8
```

# 参考
- https://qiita.com/str416yb/items/7324b99b9f05b9089b80
- https://qiita.com/nokonoko_1203/items/242367a83c313a5e46bf
- https://awesome-linus.com/2019/03/22/ubuntu-docker-docker-compose-install/#toc_id_6
FastAPIのアプリをAWS Lambdaで動かすためにMangumでラップする

PythonのWebアプリケーション、DjangoやFlaskなどいろんなフレームワークがありますが、最近だとASGIをサポートしたFastAPIの採用例も増えているんじゃないでしょうか？
そんなFastAPIで作ったアプリをサーバレスにデプロイして運用できたら素敵ですよね。
そこで今回はFastAPIで作ったASGIアプリケーションをMangumでラップしてAWS Lambda + API Gatewayで動かしてみようと思います。

# WSGIとASGIについて

DjangoやFlaskなど従来からあるPythonのWebアプリケーションフレームワークは、`WSGI` (Web Server Gateway Interface) という同期インターフェースで作られています。
WebサーバーのGunicornやApacheなどで運用されたり、Lambdaで動かすServerless Frameworkのserverless-wsgiなどがあります。

FastAPIなどの最近のWebアプリケーションフレームワークでは、`ASGI` (Asynchronous Server Gateway Interface) という非同期インターフェースで作られたりサポートされるようになりました。
非同期関数のインターフェースを取り、アプリケーションサーバのUvicornなどで運用されたりします。

# Mangumについて

`Mangum` (https://mangum.io/) とは、ASGIアプリケーションをAWS Lambdaで動かすためのアダプタです。
FastAPIなどで実装したASGIアプリケーションを、Lambda + API Gateway構成でサーバレスにWebアプリケーションとして動かす事ができます。

*※最近Lambda + ALB構成のサポートもリリースされましたが、まだ安定していません。*

# サンプルアプリケーション

FastAPIでアプリケーションを作成します。
下記はAPIサーバーアプリを例にしていますが、htmlやtextを返したりバイナリファイルを返すようなアプリケーションでもokです。

```app.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
    return {"Hello": "World"}
```

# Lambdaハンドラ

上記のASGIアプリケーションをMangumでラップする事で、Lambdaハンドラとして利用できるようになります。

```lambda_handler.py
from mangum import Mangum
from app import app

handler = Mangum(app)
```

デプロイ先のLambda関数でハンドラを `lambda_handler.handler` に設定しておきます。

# API Gateway

REST APIを作成し

```
/ ANY
/{proxy+} ANY
```
の２リソースを作成し、`LAMBDA_PROXY`タイプの統合リクエスト設定でアプリケーションのLambdaに向けます。
これは全てのリクエストを投げてルーティングをLambda側で行うProxy設定です。

ステージをデプロイすれば
`https://***.execute-api.ap-northeast-1.amazonaws.com/dev/`
でFastAPIアプリケーションにアクセスできるようになりました。

## 余談: Lambdaで運用したら、せっかく非同期なASGIが同期的に実行されて意味ないのでは？

**はい、まさにその通りです**。LambdaでわざわざASGIを動かす事自体にメリットは余りありません。ServerlessFrameworkやChaliceなどの方が簡単でシンプルに運用できます。

が、ECSなどへの移植を視野に入れるとプロトタイプ、スモールスタートなプロダクトなどには有用と考えています。
アプリケーション部分は変更せずに移植が可能なため、リリース時やスケール時にASGIが活きてくるからです。くるはず。多分。きたらいいな。
Raspberry PIでPython WEB#2（パラメータの渡し方）

#概要
今回はPythonのパラメータをHTML側に渡す方法について説明いたします。

#事前作業
●次のリンクサイトからRaspberry PIにFlask環境を構築します。
https://qiita.com/neomi/items/ad7e49c443494f1cecf5

#Blueprintについて参照サイト
Blueprintとは、アプリケーションの機能を分割して実装することができます。

●Blueprintを使ったアプリケーションのモジュール化
https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/blueprints.html

●参照内容
・なぜBlueprintsか？
・Blueprintのコンセプト
・最初のBlueprint
・Blueprintの登録
・Blueprintのリソースフォルダ
・静的ファイル
・テンプレート
・URLの構築
・エラー処理（Error Handlers）

#サンプルソース作成
①次はディレクトリの構成です。

~~~bash
# /home/pi/work
pi@raspberrypi:~ $  tree
.
├── app
│   ├── __init__.py
│   ├── main
│   │   └── index.py
│   └── templates
│       └── main
│           └── index.html
└── run.py

4 directories, 4 files
pi@raspberrypi:~ $ 
~~~

②次の４つのファイルを作成します。

~~~bash
# file name : __init__.py
# pwd : /home/pi/work/app/__init__.py
 
from flask import Flask
 
app= Flask(__name__)

# /home/pi/work/app/main/index.pyファイルインポート
from app.main.index import main as main

# Blueprintの登録
app.register_blueprint(main)
~~~

~~~bash
# file name : index.py
# pwd : /home/pi/work/app/main/index.py

from flask import Blueprint, render_template

main= Blueprint('main', __name__, url_prefix='/')

# http://url/main
@main.route('/main')


# index.htmlを参照してtestDataをテンプレートのhtmlDataに設定して表示します。
def index():
      testData = 'test data'

      # /home/pi/work/app/main/templates/main/index.html
      return render_template('/main/index.html', htmlData=testData)
~~~

~~~bash
<!--file name : index.html-->
<!--pwd : /home/pi/work/app/templates/main/index.html-->
<html>
    <head>
    This is Main page Head<br>
    </head>
    <body>
    This is Main Page Body<br>
    test : {{htmlData}}
    </body>
</html>
~~~

~~~bash
# file name : run.py
# pwd : /home/pi/work/run.py
 
from app import app
 
app.run(host='192.168.1.25', port=5000)
~~~

#動作確認
①次のコマンドでアプリを起動します。

~~~bash
pi@raspberry:~/work $ python3 run.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://192.168.1.25:5000/ (Press CTRL+C to quit)
~~~

②ブラウザでパラメータが渡されている内容を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/32542e67-7134-f11e-e435-2d4d210a2897.png)

#参考サイト
・Flask導入〜Blueprint適用メモ
https://qiita.com/shimajiri/items/fb7d1d58de0b0d171c88

#終わりに
テンプレート側のHTMLタグのHead部分がなぜタブのタイトルに表示されない疑問点が出てきました。ふむ。データのパラメータを渡し方はこんな感じですね。
今回のポイントはBlueprintとデータの渡し方のサンプルを確認しました。
次回はデータベースから取得したデータの表示について説明します。
【コンピュータの構成】基本情報技術者試験のためのコンピュータの構成

※この記事は
「栢木先生の基本情報技術者教室」を参考に学んだことをまとめた記事です。

##コンピュータの構成

* コンピュータは5つの装置で構成されている (制御・演算・記憶・入力・出力)
* 制御装置と演算装置を合わせてCPU（中央処理装置）という　　英訳： Central Processing Unit
* データの流れは 入力装置⇨記憶装置⇨出力装置(記憶装置を介し、演算装置や制御装置に処理を投げる場合もある)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965248/0085081d-6643-7586-565d-809c5d0029fd.png)

* **ハードウェア** とは制御・演算・記憶・入力・出力装置など物理的に存在するもの
* **ソフトウェア** とはプログラムやアプリケーションなど「0」と「1」の信号という形で存在するもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965248/8455b714-85cf-70fe-ec66-362161a85caf.png)


* **プログラム記憶方式** とは主記憶装置に記憶されたプログラムをCPUが順に取り出し、解読、実行する方式
* **プログラム格納方式** ともいう
カスタムモジュールの値をテンプレートで使用する

モジュール
選択のフィールドを作成しておく

```
module.choice_comment

```

モジュールIDを確認

```
{% module "module_100000" path="/xxx/modules/setting", label="setting" %}
```

テンプレートファイルでモジュール名を指定してデータを参照
export_to_template_context=True

挙動
レンダリングされるのではなく、テンプレートのコンテキストにエクスポートされる？

```
{% module "module_100000" path="/xxx/modules/setting", label="setting", export_to_template_context=True %}
{% if widget_data.module_100000.choice_comment == 1 %}
  {% global_partial path='./partials/comment.html' %}
{% else %}
  その他の処理
{% endif %}
```

モジュールの名前でも利用可能

```
{% module "my_colors" path="/xxx/modules/my_colors", label="my_colors" %}
{{ widget_data.my_colors.body.color_1 }}
```


すでにページにレンダリングされているモジュールまたはタグからパラメータを取得する場合は、dict内でモジュールにアクセスできます。
しかしデフォルト値は取得できない？

```
// HubL
{{ content.widgets.my_colors.body.color_1 }}
{{ content.widgets.my_colors.body.color_2 }}
```
Seeeduino Xiao で TOPPERS/ASPカーネル : Getting started

Wio TerminalでTOPPERS/ASPカーネルを動作させるライブラリ及び[記事](https://qiita.com/exshonda/items/5ed13c87870dee9b2a56)を公開しています．

Wio Terminalの兄弟の[Seeeduiono Xiao](https://wiki.seeedstudio.com/jp/Seeeduino-XIAO/)を新たにサポートしました．

## Xiao用のArduino環境のインストール

[Seeedのwiki](https://wiki.seeedstudio.com/jp/Seeeduino-XIAO/)を参考に，Arduino環境とライブラリをインストールしてBlinkが動作することを確認します．

なお，ArduinoIDEは1.8.6以上が必要です．

## ハードウェア設定(オプション)

UART経由のコンソールを出力したい場合は，[適当なUSB-UART](https://www.switch-science.com/catalog/1196/)を裏の拡張コネクタの以下のピンに接続します．

| 端子番号 | 機能 |
----|---- 
|  GND | GND | 
|  6   | TXD | 
|  7   | RXD | 



<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106870/ab238bb6-2a19-febe-bbd1-918aca6d1473.jpeg">

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

[ここ](https://github.com/exshonda/Arduino_TOPPERS_ASP/releases/)からv0.2以降のリリースのZIPファイルをダウンロードします．

Arduino IDEを起動して， スケッチ -> ライブラリをインクルード -> .ZIP形式のライブラリをインストール を選択します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106870/02a170ca-0c3d-9767-95c3-f70f5388f2d0.png)

ファイルダイアログが表示されるのでダウンロードしたZIPファイルを指定してインストールします．

## サンプルの実行

ArduinoIDEの ファイル -> スケッチの例 -> ToppersASP -> ToppersASP_Blink  を選択してサンプルを読み込みます．

- XiaoのUSB端子とPCを接続する．
 - マイコンボードに書き込むを選択して書き込む．
- ターミナルエミュレータを接続
 - XiaoのUSB端子によるCOMポート
 - USB UARTによるCOMポート(オプション)
- 実行
 - XiaoのUSB端子によるCOMポート にターミナルエミュレータを接続すると実行が開始される．

## まとめ

XiaoはWio Terminalと比較してメモリは少ないので，スタックサイズ等は注意してください．

## 変更履歴
- 2020/06/14
    - 新規作成
-
全角漢字・かな・半角英字のみ25文字以内の正規表現

## はじめに

Pythonのシステムで名前の入力が妥当か調べる必要があり思いついたコードです。

## コード

```python
import re
# 漢字
p1 = re.compile('[\u2E80-\u2FDF\u3005-\u3007\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\U00020000-\U0002EBEF]*')
# ひらがな
p2 = re.compile('[\u3041-\u309F]*')
# 半角英字
p3 = re.compile('[a-zA-Z]*')
# 文字数1~25
p4 = re.compile('.{1,25}')
# 今回の
p5 = re.compile('[\u2E80-\u2FDF\u3005-\u3007\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\U00020000-\U0002EBEF\u3041-\u309Fa-zA-Z]{1,25}')


if p5.fullmatch('佐藤Michaelしんご'):
    print("ok")
else:
    print("out")
```

## 終わりに

Python楽しい
Chrome Dark Mode

忘れるのでメモ


1. chrome://flags/ へアクセス
1. darkと入力
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/efe159aa-a114-6642-ef53-f92743fa17db.png)  
1. Enabledへ変更
JAVAの基本

##### データ形式
- short  整数  16ビット 最小値 -2^15 最大値 2^15-1
- int    整数　32ビット 最小値 -2^32 最大値 2^32-1
- long   整数　64ビット 最小値 -2^64 最大値 2^64-1
- float  少数　32ビット 最小値 -2^32 最大値 2^32-1
- double 少数　64ビット 最小値 -2^64 最大値 2^64-1

##### データサイズ
| 項目 | 2 | 3 |
|:-:|:-:|:-:|
| bit  |   |   |
|  B |   |   |
| 項目 | 変換 |
|:-:|:-:|
|  bit |   |
|   B|   |
|   KB|   |
|  MB |   |
|  GB |   |
|  TB |   |
|  PB |   |
|  EB |   |
|  ZB |   |
|   |   |

| 項目 | 変換 | 読み方 |
|:-:|:-:|:-:|
|  bit |  - |ビット   |
|  B |   8|  バイト(Byte) |
|  KB |  1024 |  キロバイト |
|  MB |  1024 |  メガバイト |
|  GB |  1024 |  ギガバイト |
|  TB |   1024|  テラバイト |
|  PB |  1024 |  ペタバイト |
|  EB |  1024 |  エクサバイト |
|  ZB |  1024 | ゼタバイト  |
|   |   |   |
参考:https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%AD%E3%83%90%E3%82%A4%E3%83%88
【kotlin】キーボードを閉じる

#■ボタンを押した時のキーボードの閉じ方

``` kotlin
fun onClickButton(view:View) {
    val inputManager = actibity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputManager
    inputManager.hideSoftInputFromWindow(view.WindowToken,InputMethodManager.HIDE_NOT_ALWAYS)
}
```

■actibity.getSystemService(Context.INPUT_METHOD_SERVICEのSystemService)
InputMethodManagerのインスタンスを作るために
as でInputMethodManage型にキャスト


■InputMethodManager
キーボードを閉じるメソッドを持つクラス

■hideSoftInputFromWindow()
タッチでキーボードを閉じる。

第一引数 view.WindowToken
タッチされているwindowを識別

第二引数 InputMethodManager.HIDE_NOT_ALWAYS
キーボードを閉じる。
Rails テストコードの記述

結構テストコードの記述で失敗したので。。。

```spec/factories/items.rb
FactoryBot.define do
  factory :item do
    image { "test_image.png" }
    name { Faker::Name.initials(number: 40) }
    info { Faker::Lorem.sentence }
    category_id { 2 }
    status_id { 2 }
    fee_status_id { 2 }
    prefecture_id { 2 }
    schedule_delivery_id { 2 }
    price { 10000 }
    association :user
    after(:build) do |item|
      item.image.attach(io: File.open("public/images/test_image.png"), filename: "test_image.png")
    end
  end
end
```

結論この形になったのですが、その前はrails cでコンソールを立ち上げて

```
FactoryBot.build(:item)
```

とするとまぁエラーが多発しました。

実際、ActiveHashを使用しているので、

https://qiita.com/Ma_ni_/items/2beff46433c6d115e5bc

これを参考にして記述したのですが、うまくいかず。。。。

結局上記のように若干のパワープレイで記述しました。

いつかはきちんとactivehashを用いてスマートに記述したいですね。
データベースのカラムにjsonデータを保存する時のメリットとデメリット

データベースのカラムにjsonデータを保存する時の注意点などを覚書。

####メリット
　・サブテーブルのデータをjsonとして保存しておけば、テーブル連結が不要になるので、検索が速くなる。

#### デメリット
　・jsonデータの中身をWHERE句などで条件設定したりすることは出来ない。
　　出来ないことは無いかもしれないが、相当ややこしい。

#### まとめ
jsonデータを使用する場合は、あくまで操作する必要のないものに限定し、WHERE句などで条件設定するデータは、jsonには向かない。
素直にテーブル連結した方が良い。

#### 追記
　一応、JSON関数という便利なものもあるようですね。まだ、使用したことは無いのですが、WHERE句などにも使用できるのかな？
[MySQLでJSONを扱う](https://qiita.com/abcb2/items/8affae03caa3e94068b5)
[JSON Functions](https://dev.mysql.com/doc/refman/8.0/en/json-functions.html)
【TidalCycles】0サイクル目から再生する方法

# はじめに

TidalCyclesはシンセや音源を用いてトラックを気軽に作れるためとても便利です。
ただ、個人的には

- 0サイクル目から再生する方法
- サイクル数を表示する方法

が公式ページで明示されていないため、少し使いづらいところがありました。

今回は「**0サイクル目から再生する方法**」について紹介したいと思います。(「サイクル数を表示する方法」については別記事で紹介しています。)

https://qiita.com/mynkit/private/c340506849652030cbb2

:::note info
※バージョン1.8からは、
以下の方法でresetCyclesTo関数を定義できます

```haskell
streamResetCyclesTo s n = streamSetCycle s n

resetCyclesTo n = streamResetCyclesTo tidal (n+1)
```
:::

# サイクル数について

SuperCollier上でSuperDirtを起動してから、TidalCyclesのサイクル数のカウントが始まります(0サイクルスタート)。

```haskell:randompolyrhythm.tidal
d1
  $ every' 8 7 (ply "1 1 1 12" . (|* gain 0.9))
  $ s "{808sd:11*3,808oh*4}"
```
上のコードのように

```haskell
$ every' 8 7 (ply "1 1 1 12" . (|* gain 0.9))
```

と設定すると、8サイクル周期で7サイクル目のときplyエフェクトがかかるわけですが、**「今何サイクル目か？」がわからない**と意図通りのタイミングで音が出せないわけです。

また、**曲の始まりも意図していない位置から再生される**可能性があります。

そこで、Tidalに標準で用意されている`resetCycles`というサイクル数を0に戻す関数を使ってみよう、という発想になりますが、実はこれを実行するとうまくいきません

```haskell:失敗例.tidal
-- 本来d3のシンセの音が1音目に出てほしいのに、出てこない
do
  resetCycles
  d1
    $ every' 8 7 (ply "1 1 1 12" . (|* gain 0.9))
    $ s "{808sd:11*3,808oh*4}"
  d2 $ s "~ 909 ~ 909"
  d3 $ s "superhammond" # n "<d4,e4,a4,cs5>" # sustain 0.2 # voice 1
```

これには[Tidalのissue](https://github.com/tidalcycles/Tidal/issues/453)でも言及されていて、サイクルが0に戻るのと音が再生されるのにレイテンシがあるのが問題で、以下のように`resetCyclesTo`関数を定義してあげるとうまくいくみたいです。

```haskell:実行例.tidal
import qualified Sound.Tidal.Tempo as T

resetCyclesTo n = T.changeTempo (sTempoMV tidal) (\t tempo -> tempo {T.atTime = t, T.atCycle = n})

do
  resetCyclesTo (-0.05)
  d1
    $ every' 8 7 (ply "1 1 1 12" . (|* gain 0.9))
    $ s "{808sd:11*3,808oh*4}"
  d2 $ s "~ 909 ~ 909"
  d3 $ s "superhammond" # n "<d4,e4,a4,cs5>" # sustain 0.2 # voice 1
```

うまくいきました。

開始時に実行したら、直後にresetCyclesTo部分をコメントアウトしてあげるといいです。(でないと、また実行したときに0サイクルに戻ってしまうので)

```haskell:演奏開始後.tidal
import qualified Sound.Tidal.Tempo as T

resetCyclesTo n = T.changeTempo (sTempoMV tidal) (\t tempo -> tempo {T.atTime = t, T.atCycle = n})

do
  -- resetCyclesTo (-0.05)
  d1
    $ every' 8 7 (ply "1 1 1 12" . (|* gain 0.9))
    $ s "{808sd:11*3,808oh*4}"
  d2 $ s "~ 909 ~ 909"
  d3 $ s "superhammond" # n "<d4,e4,a4,cs5>" # sustain 0.2 # voice 1
```
JDKインストール

###### JDKとは？
- JDKとは、Javaで開発を行うために必要なソフトウェアをまとめたパッケージのことだ。

###### JDKがインストールされているか
- JDKがインストールされているかどうかは、以下の操作でコマンドプロンプトを起動して確認することができる。
  * Windows 10の場合 <br>
     ①[スタートメニュー]→[Windows システムツール]→[コマンドプロンプト]<br>
     ②[win + r]→cmd<br>
     ③エクスプローラーで[cmd]<br>
    コマンドプロンプトが起動されたら、以下のコマンドを入力しよう。<br>

```
   javac -version
```

JDKがインストールされて正常に動作している場合は、次のようにインストールされているJDKのバージョンが表示される。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/2d7a854f-6082-2360-2ea9-f4f3ebcbb967.png)
JDKがインストールされていない場合は、次のようなメッセージが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/dc27b64a-37fd-63f0-e431-44cb59ffb738.png)

###### JDKインストールの前の確認
- 32bitか64bitか?
32bitと64bitとでは、使えるメモリの量やHDDの容量が違ってくる。とりあえず、64bitの方が高性能というざっくりとしたイメージで構わない。

パソコンによって32bitか64bitかが違うのだが、これによってインストールするソフトウェアが変わってくる。

この情報は以下の操作でシステム情報を見ると確認できる。

Windows 10の場合
[スタートメニュー]→[Windowsシステムツール]→[コントロールパネル]→[システム]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/803dffbd-e567-d1e6-daab-38335bdbc068.png)
「システムの種類」の項目に「64ビット」と表示されているので、このPCの場合は64ビットOSを使っていることが分かる。「32ビット」と表示されていれば32bitOSだ。
###### JDKをインストールする
- JDKを入手する
 - (Open JDK)https://jdk.java.net/
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/2ac70efc-da3a-e0a0-3f96-52761a7eaf1f.png)
- JDKのインストール
- 環境変数の設定
JDKをインストールしたら、環境変数の設定が必要だ。環境変数とはOSが使用する共通の変数のことで、環境変数にJDKに関する設定を行うことでJavaが正しく動作する。

環境変数には「ユーザー環境変数」と「システム環境変数」の2種類があり、JDKの動作のためには「システム環境変数」を設定することとなる。

設定・追加する環境変数は「Path」と「JAVA_HOME」の2つだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/509bf914-70bb-ec4c-8df4-ead069b30d55.png)
Windows 10の場合
[スタートメニュー]→[Windowsシステムツール]→[コントロールパネル]→[システム]→[システムの詳細設定]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/8c1ada53-fefa-e244-fc76-20d76555633d.png)
「詳細設定」のタブを押し、最下部にある「環境変数」のボタンをクリックしてみよう。設定されている環境変数の一覧が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/e85cea6b-e2eb-b99b-e227-47320d35e210.png)
まずシステム環境変数「Path」の設定をしてみよう。システム環境変数のリストにある「Path」の行をクリックしてから下の「編集」ボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/798948be-5b14-4fa0-c961-72ced3741eac.png)
続いて環境変数「JAVA_HOME」の設定を行う。システム環境変数の欄にJAVA_HOMEがない場合は「新規」ボタンをクリックしよう。既にある場合は、値が正しいかどうかの確認だけで良い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/bd20e4cc-3f72-e56e-95d2-363e71e3d044.png)
コマンドプロンプトを開き、先ほど紹介した方法で確認を行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225536/b494ce2d-045c-935a-bc88-db21714395d8.png)

このようにJavaのバージョンが表示されていればインストールは完了だ。
$git rebaseコマンドの使い方を調べた件(履歴を綺麗にする編)

##はじめに
この記事はGitの扱いに慣れていない方に向けた記事です。
そして私の備忘録にもなっておりますのでどうぞ温かい目で。。。

##この記事を書くに至った経緯
「Gitは難しい！！」
「Gitは簡単だよ！」
人によって意見は分かれますが個人的には「死ぬほど難しい」と思っています。
今回は私が詰まった$git rebaseコマンドについてご説明させていただきたいと思います。

##$git rebaseコマンドとは？
一言で表すのであれば「mergeよりコミット履歴を綺麗にする統合方法」です。

？？？

よくわかりませんね。。。
図を交えつつ解説していきます。

```
feature     　●---●
            /
master ●---●--●---●
```

ここで$git rebase masterを実行してみましょう。
すると

```
feature            　●---●
                   /
master ●---●--●---●
```

このようにコミット履歴を一直線にすることができます。
個人的にはあまり便利とは思わずmergeで良くない？と思っちゃいます。。。
まあ、コミット履歴を綺麗にできるのはコミット履歴の削除や変更も行いやすくなるのはいいかもしれません。

コミット履歴をいじるのでGithubにpushした後にrebaseするとpushできなくなるので気をつけてくださいね！

##終わりに
正直あまり便利には思えないコマンドでした。。。（おそらくど素人だから）
個人開発ならお目にかかる場面は中々ないかもしれませんね。
僕はmergeを使うこととします。。。

次はrebaseコマンドを使用してコミットのやり直しや削除について記事を書いていこうと思いますのでどうぞよろしくお願いいたします！

閲覧いただきありがとうございました！！
OctoberCMSで日本語のFakerを使いたいとき

やりたいことは表題の通り。
pagesの中で使いたい場合は適当なプラグインを作って、Plugin.phpの中のboot()からページへFakerのオブジェクトを渡してあげます。
具体的には、

```bash
composer require fzaninotto/faker
```

まずcomposerでfakerをインストールしたのち、

```php:Plugin.php
use Faker\Factory;
use Event;

public function boot()
{
    Event::listen('cms.page.beforeDisplay', function($controller, $url, $page) {
        $controller->vars['faker'] = Factory::create('ja_JP');
    });
}
```

こうすれば、pagesの中からfakerという名前の変数としてFakerオブジェクトが呼び出せます。
あとは適当に、{{faker.name}}とかで呼べばいい感じのデータが得られると思います。その辺の詳しくはLaravel向けの資料を調べてみましょう。

また、Seederなどの中で呼び出したい場合も同様、Factory::create('ja_JP')でオブジェクトを作り、そこからいろいろ関数を呼べばデータが取り出せます。
OctoberCMS、Laravelベースで作ってくれてるのでこういうときに楽ですね。
プロキシ＋Windows環境でAnsibleを実行する

## はじめに

Ansible は非常に有用な構成管理ツールです

しかし、社内で Ansible を使おうと思ったとき、色々と制約に悩まされてしまいます

- Windows に Ansible がインストールできない
- プロキシ設定が面倒

というわけで、Windowsかつプロキシ環境でAnsibleを実行するためのテンプレートになるリポジトリーを作成しました

https://github.com/RyoWakabayashi/ansible_docker

これをコピーするなりフォークするなりすれば簡単に社内で Ansible が使えます

実行方法はリポジトリーの README を読んでください

## Docker の設定

Windows では Ansible を直接インストールできないため、Docker 上にインストールすることにしました

Docker にしておけば、 Ansible のインストール以外にもプロキシ周りの設定を簡単に定義しておけるからです

Docker の紹介やインストール方法などは他の記事に譲るとして、本記事ではプロキシ周りの設定を紹介します

### ビルド時のプロキシ設定

引数としてプロキシを受け取るようにしておき、 `yum` の設定と環境変数に入れています

```Dockerfile
ARG HTTP_PROXY
ARG HTTPS_PROXY

RUN echo proxy=$HTTP_PROXY >> /etc/yum.conf

ENV http_proxy $HTTP_PROXY
ENV https_proxy $HTTPS_PROXY
```

ビルド実行時に以下のように引数を指定します

```bash
docker-compose build `
  --build-arg HTTP_PROXY=$env:HTTP_PROXY `
  --build-arg HTTPS_PROXY=$env:HTTPS_PROXY
```

これで自分のローカルに設定してあるプロキシがそのまま引き継がれます

### SSH 設定

ssh-config に以下のように Ansible の接続先情報を設定しておき、コンテナ内にコピーしています

```text
Host target-server
  HostName x.x.x.x
  User xxx
```

```Dockerfile
COPY ssh-config /root/.ssh/config
```

### コンテナ起動時の設定

docker-compose.yml でも環境変数からプロキシ設定を渡すように指定すします

```yaml
version: "2.3"

services:
  ansible:
    build: .
    hostname: ansible
    container_name: ansible
    environment:
      - HTTP_PROXY
      - HTTPS_PROXY
    volumes:
      - ./playbooks:/playbooks
    tty: true
```

## Ansible の設定

Playbook の引数に環境変数からプロキシ設定を渡します

```yaml
- name: docker
  hosts: target-servers
  become: yes
  vars:
    http_proxy: "{{ lookup('env', 'HTTP_PROXY') }}"
  roles:
    - common
```

以下のように引数の値を指定することでプロキシが引き継がれます

```yaml
- name: Add proxy setting to yum config
  lineinfile:
    dest: /etc/yum.conf
    line: "proxy={{http_proxy}}"
```
ベイズの定理と利用できる具体例

# はじめに
ベイズの定理について条件付き確率から順を追って説明する。また、理解の助けとなると考えられる具体的な例を２つ紹介する。

# 確率
この記事では確率を以下のように書く。

- 事象Aが起きる確率を$P(A)$
- 事象Aと事象Bが起きる確率を$P(A\cap B)$
- 事象Aまたは事象Bが起きる確率を$P(A\cup B)$

# 条件付き確率
ベイズの定理を説明する前に条件付き確率について説明する。条件付き確率とは事象Bが起きたという条件下で事象Aが起きる確率のことを指す。この確率は一般的に$P(A\| B)$と書かれる。式で表すと以下のようになる。
$$
P(A\|B) = \frac{P(A\cap B)}{P(B)}
$$
これは以下の弁図で考えると、青で囲まれた部分を緑色の部分で割った式である。
![iOS の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/1afc1287-3410-b8a7-c752-47f7891ea81a.png)


# ベイズの定理
事象Bが起きたという条件の下で事象Aが起きる確率は
$$
P(A\|B) = \frac{P(A\cap B)}{P(B)}
$$
でかけることを先ほど確認した。この逆(事象Aが起きたという条件の下で事象Bが起きる)の確率も同様に
$$
P(B\|A) = \frac{P(A\cap B)}{P(A)}
$$
と書くことができる。また、これを変形して$P(A\|B)$を用いて書こうとすれば以下のようになる。
$$
P(B\|A) = \frac{P(A\|B)P(B)}{P(A)}
$$
この式をベイズの定理と呼ぶ。事象Bが原因で事象Aが起きるという「原因->結果」の関係があるとき、$P(B\|A)$は結果が事象Aとわかっている時に原因として事象Bが起きる確率である(説明がわかり辛いので具体例をのちに紹介する)。この確率は直感的に求めるのが難しいが、左辺を見ると$P(A\|B),P(A),P(B)$のように直感的にわかる式で構成されているのでそれらの組み合わせて求めることができるという利点がある。直感的というのは現実の流れのような順番で考えられる確率のことを言った。
## 例1
ベイズの定理のわかりやすい例としてよく、病気の検査が使われるのでそれを採用して紹介する(PCR検査にも当てはまるホットな話題ということもある)。
罹患率が0.01%の病気で、検査の判定は以下のようなものを考える。

||陽性|陰性|
|-|-|-|
|罹患|95%|5%|
|非罹患|20%|80%|
確率表記として

- 罹患している確率を$P(B_1)=0.0001$
- 罹患していない確率を$P(B_2)=0.9999$
- 陽性である確率を$P(A_1)=0.95\times 0.0001 + 0.20\times 0.9999=0.200075$
- 陰性である確率を$P(A_2)=0.05\times 0.0001 + 0.80\times 0.9999=0.799925$

と書く。理想的な病気の検査では罹患したことが原因となって検査で陽性という結果がでる。罹患したことで検査で陽性がでる確率は表から$P(A_1\|B_1)=0.95$である。これをもとに陽性と判定された人のうち実際に罹患している確率を求めることができる。その確率は$P(B_1\|A_1)$であるのでベイズの定理を使って$P(B_1\|A_1)=\frac{P(A_1\|B_1)P(B_1)}{P(A_1)}=0.00047482$となる。この例では罹患している人が陽性と出る確率(真陽性率)が高いので検査がもっともらしいものに感じるが、計算すると陽性と出ても0.05%しか実際に罹患していないことがわかる(再検査の重要性)。ここで出てきた数値は適当に設定したものである。

## 例2
ベイズの定理が有効な場面として有効な場面としてモンティ・ホール問題がある。問題の設定は以下のようなものである。

- 当たりが入った箱1つとハズレが入った箱を2つ準備する
- ３つの箱から一つを選ぶ。箱の見た目は全て同じで当たりである確率は$\frac{1}{3}$である。
- 残った二つの箱のうち一つを指定してそれがハズレという情報を与える。
- その後箱をもう一度選ぶチャンスを与えると、最初選んだ箱が当たりである確率が$\frac{1}{3}$、残った箱に当たりである確率が$\frac{2}{3}$となる。

これは直感的に残った箱二つの箱から選ぶので確率は$\frac{1}{2}$や、三つのうち一つを選んでいるので選び直したとしても$\frac{1}{3}$と考える人が多いが、選び変えた時の確率は$\frac{2}{3}$であるというパラドックスとして有名である。
この例ではハズレという情報が開示された(原因)下で、選んだ箱が当たりである確率(結果)を求める。箱1を選ぶ確率を$P(A_1)$、箱2を公開する確率を$P(B_2)$と書くとする。選んだ箱が当たりである確率は定義より$\frac{1}{3}$、箱1を選んでいた場合は箱2または箱3を公開する選択肢しかないので箱2を公開する確率は$\frac{1}{2}$である。箱1を選び、それが当たりの場合を考える。この場合$P(B_2|A_1)=P(B_3|A_1)=\frac{1}{2}$となる。箱2が当たりの時は$P(B_2\|A_1)=0, P(B_3\|A_1)=1$となる。箱3が当たりの時も同様。箱1,2,3には区別がないので、入れ替えた値は変わらない。
箱2を開示した下で最初に選んだ箱1が当たりの確率$P(A_1\|B_2)$求める。ベイズの定理より
$$
P(A_1\|B_2)=\frac{P(B_2\|A_1)P(A_1)}{P(B_2)}
$$
となる。このとき、$P(B_2\|A_1)=\frac{1}{2},P(A_1)=\frac{1}{3},P(B_2)=\frac{1}{2}$より、$P(A_1\|B_2)=\frac{1}{3}$となる。次に最初に箱1を選び、箱２を開示した下で箱3が当たりである確率$P(A_1\|B_2)$を求める。先程同様にベイズの定理より
$$
P(A_1\|B_2)=\frac{P(B_2\|A_1)P(A_1)}{P(B_2)}
$$
となる。先程同様に$P(B_2\|A_1)=1,P(A_1)=\frac{1}{3},P(B_2)=\frac{1}{2}$より$P(A_1\|B_2)=\frac{2}{3}$となる。
これより、箱を選び直した時の確率が$\frac{2}{3}$となることが示された。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/6041ba6a-aee0-14c7-64ab-97e0606624ca.png)
Jetson用のビルド済みPySide2を公開しました。

# 概要
PySide2をJetsonに入れようとした際に、pip等ではPySide2が入らなかったので、ソースコードからビルドしてみました。
ついでにビルド済みのwhlイメージを公開しました。

# 環境
- SBC:Jetson Nano / Jetson NXでのみ動作確認
- OS: Jetpack 4.5.1
- PySide2Version: 5.9

# インストール
```
git clone https://github.com/hiroyuki-s1/PySide2InstallForJetson
cd PySide2InstallForJetson/dist
pip3 install --user PySide2-5.9.0a1-5.9.5-cp36-cp36m-linux_aarch64.whl
```
ソースコードからビルドしようとするとかなり時間がかかるので、もしければ使ってください。

# 参考
https://forums.developer.nvidia.com/t/how-to-install-pyside2-jetson-nano/78677/3
プロセスビルダーで組んだプロセスをフローで表示する

ここ最近、フローのアップデートは頻繁に入る一方で、プロセスビルダーにはアップデートが全くないあたり、Salesforceはプロセスビルダーを過去のものにしようとしているのが、見て取れます。

プロセスビルダーで作ったプロセスをフローに置き換える必要性もあるかなと思いますが、そんなときにもしかしたら役に立つかもしれないと思ったことを、備忘録的に書き残しておきます。

取引先に「商談成立数」を数値項目で用意します。~~（実際にこういうの用意するときは積み上げ集計で用意するけど）~~
取引先Aの商談が成立すると取引先Aの商談成立数が1増える、こんなプロセスをサクッと組んでおきました。![bandicam 2021-06-14 17-32-59-065.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/75f07a4c-411a-f5dc-3f09-142d8acb1545.jpeg)

ここで、オブジェクトマネージャーから先ほど使用した商談成立数の項目の詳細ページにいきます。
![タイトルなし1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/88b7cde2-bf96-d9ed-0265-bb48e37022e3.png)

ん？一番上の奴、プロセスビルダーで作成したのに、参照の種類が「Flow」となっています。
ここで、一番上のフロー変換テストをクリックすると…![タイトルなし3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/c3fff8d3-2cff-d0b4-91c1-6f0f93aebd3d.png)

Flow Builderの画面で表示されました。表示されたものは要素がめっちゃくちゃな配置になっています。
少し配置を整えてみたのですが、見た感じはプロセスで組んだものそのままフローになった…という感じだと思います。

一回このフローを保存してみます。
![タイトルなし4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/c2914df8-bf66-4548-aded-1386e6b7963f.png)

…エラーを吐かれました。保存出来たら、元となったプロセスはどうなったかとかを見てみたかったのですが…
エラーの内容は要調査です。ちょっと意味がよく分からない…

保存できなかったので確信は持てませんが、おそらくこのフローの種別は「自動起動フロー（トリガーなし）」になってると思います。
エラーを修正して保存できたとしても、この種別では実用性は皆無と言えるかもしれませんね...

1からレコードトリガーフローで組み直した方が早いまであるかもしれませんね。
Puppeteerを使ってみた

株式会社ココロファン - エンジニアリング事業部所属のhazamaです。

サイト制作・運用業務をメインに行っています。
業務の一環でサイトのスクリーンショットを取得することがあるのですが、便利なものがないか探しているうちに
「Puppeteer（パペティア）」というものを見つけたので、早速試してみようと思います。
##Puppeteerとは
>Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

参考：https://github.com/puppeteer/puppeteer

とまぁ、こんな感じの説明があるのですが、
「ChromeまたはChromiumを制御できるAPIを提供するGoogle製Node.jsライブラリ」ということらしいです。
##環境
- Windows 10 Home
- Node.js v16.2.0
- npm 7.13.0
- Puppeteer 10.0.0


##使用準備
###Node.jsをインストールする
インストールは[こちら](https://nodejs.org/ja/)から
###作業場所を準備する
続いて作業場所を準備します。
適当な場所で構わないので作業ディレクトリを作成します。

```powershell
$ mkdir screenshot
```
###package.jsonを作成する
作成時、本来は設定する際に色々聞かれますが、今回は特に設定なくても問題ないので次のコマンドで作成します。

```powershell
$ npm init -y
```
###Puppeteerのインストール
package.jsonが作成できたら、いよいよPuppeteerのインストールです。

```powershell
$ npm install puppeteer
```
###jsファイルの作成
Puppeteerのインストール後、起動させるためのjsファイルを作成します。

```powershell
$ touch screenshot.js
```
jsファイルの中身は次のように記述します。
ちなみにこの記述はPuppeteerが[Git hub](https://github.com/puppeteer/puppeteer)にソースコードをあげており、そちらに記載されているものをそのまま使用しています。

```js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com'); //スクリーンショットを取りたいURLを記述
  await page.screenshot({ path: 'example.png' }); //スクリーンショットのファイル名を記述

  await browser.close();
})();
```
上記を実行するとザックリこんな感じのことをしています。

* Chromiumを起動
* 指定したURLに移動
* 指定したファイル名でスクリーンショットを保存
* Chromiumを閉じる

jsの記述が終わったらコマンドラインで実行してください。

```powershell
$ node screenshot.js
```
##実際に動かしてみる
試しにgoogleのスクリーンショットを取得してみようと思います。
まずは先程のjsでURL部分を変えます。保存される時の名前もわかりやすくしておきましょう。

```js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://www.google.com/'); //←googleのURLを記述
  await page.screenshot({ path: 'screen_google.png' }); //←保存時のファイル名

  await browser.close();
})();
```
次にjsがあるディレクトリまで移動してコマンドラインで実行します。

```powershell
//screenshotディレクトリまで移動
$ cd C:\Users\ユーザ名\Desktop\screenshot

//screenshot.jsを実行
$ node screenshot.js
```
実行するとコマンドラインでは特に何も起きていませんが、screenshotのディレクトリを見ると
「screen_google.png」で保存されていました！
![スクリーンショット_保存.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1256886/a1d38378-03fc-161b-69a7-44c975e5466d.png)

##最後に
Node.jsのライブラリと聞いて敷居が高いかなと思っていましたが、意外とすんなり導入できました。
スクリーンショットを取るにあたって、今はchromeの拡張機能やフリーのソフトでも性能のいいものがありますが、puppeteerは差分を比較するなどの機能もあるみたいなので、今後研究を重ねたいと思います。
GitHub Flowとは？

##はじめに
この記事はGitの扱いに慣れていない方に向けた記事です。
そして私の備忘録にもなっておりますのでどうぞ温かい目で。。。

##この記事を書くに至った経緯
最近はgithubに関する記事を多く書かせていただいております新卒エンジニアです。
前回「git fetch」を知らなかったことを述べさせていただきましたがやはりまだまだ勉強不足だったことはどんどん見つかります。
先日、私がアサインされた案件で「GitHub FlowやGitLab Flowわかるよね？」とPMの方からご質問されました。

私「すみません、わかりません...」

苦笑いのPMの方。学生時代、そして新卒の研修で何をやってきたんだと思われても仕方ありません。
そこでお恥ずかしながら今回gitの学習のお時間をいただき、同時にGit運用のワークフローも学習し理解して参りましたので今回はGithub Flowのご説明と考察を述べていこうと思います！

##GitGub Flowとは
一言で表すのであれば「マスターからブランチ切って各々開発してマスターにマージする！」

はい、これだけ。。。

もうこれ以上に言うことがないくらいに簡単なことだったんですね。。。笑
そりゃ知らないと言われたらびっくりするのも無理はない。。。

より具体的に説明していきます。

![スクリーンショット 2021-06-14 17.42.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1634459/d146f281-f6d2-88d2-4a3a-ceb23d62f634.png)

簡単に図示してみました。マスターブランチからfeatureブランチが２つある場合のワークフローですね。

まず、GitHub Flowの場合のマスターブランチはいつでも最新、そしてデプロイ可能にしておく必要があります。そのためにはマスターブランチから各々開発ブランチを作成し、実装を終えたのちにmasterへマージする。この手順だとmasterは常にデプロイ可能な状態になりますね！

##考察
いつもやってることがGitHub Flowだと言うことに気がついた時は少し情けない気分になりました。。。笑
しかし何度見てもこのブランチという機能はよく考えられたものだと実感させられます。
私も学生時代に戻れるのならコーディングもですがGitであったりCircleCIなどコーディング以外のことを学習する時間をとっておけばよかったと思います。

まだまだ新人なものでこの記事にも誤りがあるかもしれませんがそこはご容赦いただけると幸いです。
最後まで読んでいただきありがとうございました！！
待機モーションに表情を変化させよう！

#UnityのAvater Mask と　Animationで表情の変化をさせる方法。

今回はUnityのAnimation遷移で待機モーションの表情を変化させてみたいと思います。

###Animator の設定

まず、Animatoar Windowの**+**ボタンを押して、Layerを追加し、名前を Face Layer としてください。

このときに歯車アイコンを押して Face Layerのweight を **1**にします。

つぎにAnimation Clipを2つ作成し、Face LayerにDrag&Dropしてください。

今回のAnimation Clipは Fun　と Joy の２つの表情の変化をさせます。

アニメーションクリップを配置したら、写真のようにTranslationを貼ってください。

![スクリーンショット 2021-06-14 173927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/3609acec-b757-26d0-6844-92eb7db34fbb.png)

parameterに Int型のParamterを設定し、名前を**expression**にします。

 つぎに、各ノードのConditionsについて、設定します。

| 根元のノード|先のノード| Conditions|
|--|--|--|
| Waiting | Fun | expression Equals 1 |
| Waiting | Joy | expression Equals 2 |
| Fun| Waiting | expression Equals 0 |
| Joy | Waiting| expression Equals 0|
| Fun| Joy | expression Equals 2 |
| Joy | Fun| expression Equals 1|

また、このときにすべてのTranslationについて、HasExitTimeのチェックマークを外してください。

###Avater Maskの設定

次にAvater Maskを設定します。

写真のように全身真っ赤なAvater Maskを Project > 右クリック > Create > Avater Maskから作成してください。

![スクリーンショット 2021-06-14 172454.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353403/b1baab3e-ac1a-53b8-c664-a6135804d242.png)

これを Face LayerのAvater Maskに設定します。

###Animation Clipの設定。

基本的にボーンはすべて動かないので、表情の変化だけさせたAnimation Clipを用意してください。

今回はAnimation中でずっと、微笑んでる(Fun)か、笑っている(Joy)表情にしています。

###Scriptの設定。

WaitingのAdd Behaviorを押して、スクリプトを追加してください。

こんかいは、ExpressionChange.csを作成します。

```
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        var num = Random.Range(0, 3);
        animator.SetInteger("expression", num);
        Debug.Log(num);
    }
```

ExpressionChange.csのOnStateEnterを以下のように書き換えてください。

以上で設定は完了です。

これでAvater Maskを使って、表情を動的に変化させることができました。
Railsのsass-railsインストール時にg++エラーが出る


railsでsass-railsというgemをインストールする際、エラーが発生したので解決方法を残しておきます

# 環境

- Amazon Linux 2
- rails5.2.6

# エラーの内容

どうやら依存しているsassというgemのインストール時にg++コマンドがなくてエラーになっている

```
Building native extensions. This could take a while...
ERROR:  Error installing sassc:
	ERROR: Failed to build gem native extension.

    current directory: /root/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/sassc-2.4.0/ext
/root/.rbenv/versions/2.6.1/bin/ruby -I /root/.rbenv/versions/2.6.1/lib/ruby/2.6.0 -r ./siteconf20210614-11958-gcrsst.rb extconf.rb
creating Makefile

current directory: /root/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/sassc-2.4.0/ext
make "DESTDIR=" clean

current directory: /root/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/sassc-2.4.0/ext
make "DESTDIR="
compiling ./libsass/src/ast.cpp
make: g++: コマンドが見つかりませんでした
make: *** [ast.o] エラー 127

make failed, exit code 2

Gem files will remain installed in /root/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/sassc-2.4.0 for inspection.
Results logged to /root/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/extensions/x86_64-linux/2.6.0-static/sassc-2.4.0/gem_make.out
```

# 解決方法

- `yum install -y gcc-c++`を実行
- `g++ --version`で確認

# おまけ

- gccとは「GNU Compiler Collection」の略でGNUが開発しているコンパイラ群のこと
- g++とは、gccの中のc++コンパイラのこと
Amazonの偽レビューを見破る拡張機能があるらしい

#Amazonの偽レビュー
皆さんは、通販サイトAmazonを使いますか？
私はよく利用しています。

買い物をするとき、買うか買わないかの判断基準としてレビューを参考にすることがあるのですが、そのレビューがどうやらその商品の評価を上げるために実際の評価とは異なる評価をする人もいるようですね。

偽レビューがあると知ってしまうと、レビュー機能そのものが信用できなくなっていまいます。

そんな偽レビューを見破る機能があると最近知りました。
<b>Fakespot</b>というらしいです。

Fakespotはレビューの中のどのくらいの割合が偽レビューなのか見破れるツールのようです。

実際試してみたところ、半分は偽レビューという商品もありました・・・

気になっている商品の評価が高い安心してしまいます。
全ての商品に偽レビューがついてるわけではないと思いますし、ちゃんとした商品で純粋に評価の高い商品もあると思います。

レビューを判断基準にしている方などはぜひ<b>Fakespot</b>を使ってみてはいかがでしょうか。
Keynoteプレゼンテーションに落書きできるアプリ

#目的
* macOSのプレゼンテーションソフト Keynote でプレゼンテーションしている最中（プレゼンテーションモード）に画面に落書きできるアプリを知りたい。
    * Keynote のプレゼンテーションモードに対応していないアプリが（かなり）多いので注意が必要。
* 液晶ペンタブレットを使って書き込む。
    * Wacom Cintiq 16 FHD
    * XP-Pen Artist12

#結論 (2021.6.14.現在、macOS 11.4)
## [DemoPro](http://www.demoproapp.com)
* 現在使っているのがこれ。
* ちょっとした書き込みができれば十分であれば、もっともシンプル。
* メニューバー常駐で邪魔にならず、簡単なショートカットキーコンビネーションで呼び出せる。
* 以下のショートカットくらいを覚えておけば使える
    * `Ctrl + S` フリーハンドで書き込み開始／終了
    * `Ctrl + X` 全部消してプレゼンに戻る
* Keynoteのプレゼンテーションモードでも、特別な操作は不要で、ふつうにショートカットで書き込みを始められる。
* 自分の環境や操作のクセなど、個人差があると思うが、プレゼンテーションモードの解除などのトラブルが起こりにくい印象。
* Cintiq 16, Artist12で問題なく動作

## [Deskscribble](https://www.deskscribbleapp.com)
* DemoProを見つけるまで１年くらい使ってたのがこれ。
* 画面左上に一固定のパレットが表示される（非表示にもできるが、ショートカットだけで使いこなすのはかなりマニアック）。
* 半透明のハイライト色など、DemoProよりやれることが多い。線の太さの変更なんかもDemoProよりやりやすい。
* Keynoteのプレゼンテーションモードに対応しているが、使用中に解除されてしまうこともしばしば。
    * プレゼンテーションモードで使用するためには、KeynoteとDeskscribbleを順序だてて操作する必要があり、けっこう面倒。１年間、90分間のオンライン授業で20〜30回くらい使用したが、「もう慣れた。サクサク」という状態にはならなかった（プレゼンテーションモードが意図せず解除されたりしても、焦らず対応できる程度には慣れた）。
* Cintiq 16では問題なく動作するが、Artist12ではプレゼンテーションモードを維持しながら利用できなかった（探究不足かもしれない）。

##メモ
* 使えそうなものは高価すぎない有料アプリを含め、片っ端から試し本番で使えると判断して、実際に授業で使ったのはこの２つだけ。
    * iPadのSide Carも2020年春時点のものを試したが、Side Carにディレイがあり、Zoom, Webexなどでの配信にまたディレイがあるので、実用的でないと判断した。
        * オンライン授業中は２系統から接続して、１系統で「講師として」プレゼンし、もう１系統は「受け手として」共有されるプレゼンを見ており、どの程度のディレイが出ているのか確かめながら講義をしている（声も遅れるので「受け手」画面に合わせても意味はない。あくまでも確認用）。