OmniAICreator/Qiita-1.07M huggingface dataset:
[Rails]バッチ処理を実装出来るエンジニアに俺はなる！

# はじめに
実務でバッチ処理を実装することがあるかと思いますが、右も左も分からず悔しかったので学習したものを備忘録としてまとめようと思います！自分と同じくまだ理解してない人はぜひ参考にしてください！

# バッチ処理とは
バッチ処理とは、アプリケーションに関するデータの参照と更新をソースコードに書かれた仕様に従って実現します。
大量のデータを更新する処理や時間を必要とする処理も取り扱うことができます。

例：情報の一括更新、バックアップの作成...etc

# バッチ処理実装方法
自分の調べた感じで言うと、主に2つの実装方法があるらしいので、どちらがよく使われてることもないと思うので、どちらも紹介したいと思います！

## Rails Taskを用いた実装
1.`lib/tasks`配下にrakeファイルを作成します。
※あるまとまりごとにディレクトリを作成することが多いようです

```bash
$ touch lib/tasks/samples/sample1.rake
```

2.作成したrakeファイルに処理を実装していく。

```lib/tasks/samples/sample1.rake
namespace :samples do
  desc 'サンプルバッチ処理1'
  # config/environment.rbを読み込み、環境ごとの設定を反映してからsample1を実行
  task sample1: :environment do
    # 具体的な処理を実装
  end
end
```

3.タスクが登録されているか確認する。

```bash
$ rails -vT
#=> rails samples:sample1がある
```

4.バッチ処理を実行する。

```bash
$ rails samples:sample1
```

## wheneverを用いた実装
1.wheneverを導入し、`bundle install`を実行する。

```ruby
gem 'whenever', require: false
```

2.`config/application.rb`に以下を追記する。

```config/application.rb
class Application < Rails::Application
...
  # /libファイル以下を自動でロード
  config.autoload_paths += Dir["#{config.root}/lib"]
...
end
```

3.`lib/batch`配下にバッチ処理を記載するファイルを作成する。

```lib/batch/sample.rb
class Batch::Sample
  def self.run
    puts 'サンプルバッチ処理実行！'
  end
end
```

4.処理が問題無く実行できるか動作確認をする。

```bash
$ bundle exec rails r Batch::Sample.run
#=> "サンプルバッチ処理実行！"
```

5.自動で実行するスケジュールを作成するために以下のコマンドでファイルを作成する。

```bash
$ bundle exec wheneverize .
#=> config/schedule.rbが作成される
```

6.`config/schedule.rb`を以下のように修正する。

```config/schedule.rb
# Rails.rootを使用するために必要
require File.expand_path(File.dirname(__FILE__) + "/environment")
# cronを実行する環境変数
rails_env = ENV['RAILS_ENV'] || :development
# cronを実行する環境変数をセット
set :environment, rails_env
# cronのログの吐き出し場所
set :output, "#{Rails.root}/log/cron.log"

# 毎日午前0時に実行
every 1.day, at: '0:00 am' do
  runner "Batch::Sample.run"
end
```

7.cronへ設定を反映させる。

```bash
# cronへ反映する
$ bundle exec whenever --update-crontab
```

8.しっかり反映されているか確認する。

```bash
$ crontab -l
```

### cronとは？
cronとは、Linuxサーバー管理の設定方法の一つです。`「何を」「いつ（頻度）」実行するかを決め、そのルールを書き込みます`。指定したプログラムの動作を予約したり、実行する頻度を細かく調整できるので、自動的に繰り返すことができる。

# 終わりに
実装方法は`どちらでも良い`ので、使いやすい方でいいかと思います。バッチ処理を理解していると強強エンジニアのイメージが個人的にはあるので、スキルを身につけて行きましょう！笑

# 参考
[Ruby on Rails でバッチ処理を実装する]
(https://hiromiick.com/rails-batch-whenever/)

[Railsでバッチ処理してみる]
(https://ccbaxy.xyz/blog/2019/11/30/ruby17/)

[【Rails】whenever によるバッチ処理（runner編）]
(https://qiita.com/syukan3/items/eef3f8929ecb5d6ef6ff)

[Wheneverは導入が超簡単なcrontab管理ライブラリGemです！]
(https://morizyun.github.io/blog/whenever-gem-rails-ruby-capistrano/index.html)
VSCodeでPythonファイルをデバッグ

## VSCodeの拡張機能インストール

以下をインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/a479313d-b59c-d94c-65c6-c3eede732fd5.png)

## デバッグ手順

### インタープリター確認

仮想環境に入っている場合はvenvを選択しているか確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/1303d639-ae2f-d420-dfbd-f3e1632a5b39.png)

### ブレークポイントを設置

止めたいところにブレークポイントを設置。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/ac1a4b5c-0be7-6e78-9860-fa6b3a8fab41.png)

### デバッグ

番号の通り進める。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/11c0254c-0d44-afe4-01f0-ebd3e36eb3be.png)

### ブレックポイントの位置で止まる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/d0b5597d-19d6-9266-8263-281c696685c2.png)

### デバッグでできること

`hello`の中身を確認。
デバッグコンソールに`hello`と打ってエンターを押すと`hello`の中身が確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/53ac404b-7092-b988-8ee8-bed582ec0c60.png)

メソッドを使って動きを確認することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/d6c2216f-6891-71c1-52e8-a6d2d7a7a90e.png)
[備忘] error strings should not be capitalized 対応

```golang
fmt.Errorf("This method is not implemented")
```

って書いたら`error strings should not be capitalized (ST1005)go-staticcheck`っておこられた。

問題は**最初の一文字目が大文字**のところらしい。

```golang
fmt.Errorf("ｔhis method is not implemented")
```

これでなおった。
非同期処理の歴史とasync await/promiseを居酒屋のノリで理解する

#本記事の内容
本記事は、`非同期処理`に関して纏めた記事となります。
また、***検証ツール***(macですとoption + command + I　で起動)を用いることで***どなたでもすぐに実感できる***かと思います。
非同期処理って何？まあなんとなく使えてるしいいや、PromiseとかAsyncとかよくわからんし後でいいや〜、書いてるけど実はあまり意味わかってないんですよね〜、って方向けに書いております。
筆者自身の備忘録的な要素も兼ねておりますので、間違い等ありましたら、お手数ですが、ご指摘いただけますと幸いです。
よろしくお願いします。

#非同期処理とは
通常、プログラムは上から順に処理を実行する。すなわち、一番上に時間のかかる処理を書いていると、その処理より下に書かれている処理に時間がかかってしまい、<font color="red">**何も実行/表示されない**</font color="red">。

(店員：最初に揚げ物のオーダー処理してると、いきなり時間かかっちゃうからお客さん待たせちゃうな...どうしよう？？？)

**バックグラウンドで処理を行う**こととした。

→先に画面を表示させ、データを取得するなど、時間を要する処理に関しては実行され次第、画面に表示させれば良い！
(他のオーダーで先に出せそうなもの先に出しちゃえ！生ビールとトマトときゅうりは先出しちゃえ！)


この様に、処理を一度バックグラウンドに移すことを非同期処理という。
処理のタイミングをずらしてやるイメージ。
（処理１、２、３とあった際に、２は時間がかかる...先に１と３をやっちゃって２は終わったら表示すればいいや！）


#非同期処理をどうやって実現しているのか
コールバック関数で実現した。（他の関数の引数として使用される関数）
以下の例でいうところのconsole.log(1)がコールバック関数。

```javascript
setTimeout(()=>console.log(1),1000);
console.log(2)
//上の２行をデベロッパーツールに書いて、エンターキーを押してみてください。

//以下出力結果
2
undefined
1
```

#地獄の始まり
上記でコールバック関数を利用することによって、非同期処理を行うことができる様になったが、ここで問題点が出てくる。
<font color="red">**バックグラウンドでの処理が増えるほど、記述がややこしくなってしまった...**</font color="red">
例えば、以下の例を考えてほしい。
以下のイメージ。


```javascript
〜〜〜失敗例〜〜〜
setTimeout(()=>console.log(3),1000);
setTimeout(()=>console.log(2),1000);
setTimeout(()=>console.log(1),1000);

//出力結果
3
2
1
//と同じタイミングで出力される。
```

```javascript
//〜〜〜成功例〜〜〜
setTimeout(()=>{
 console.log('生中お待ち！')
   setTimeout(()=>{
    console.log('トマト！お待ち')
      setTimeout(()=>{
        console.log('ヘイよ唐揚げ！')
　　　　　　　},1000)
  },1000)
},1000)
```
**失敗例**の場合はは、全てが同じタイミングでで処理されてしまう。。。
**成功例**ではうまく処理できているものの、たった三つの処理でこの記述量、、、ネストされててミスしそうだし、、、これがいくつもあると考えると...
（オーダーがこれだからいいものの、もっとオーダーされたらそもそも覚えらんねえ...)

#promiseの発明

連続した非同期書をフラットに書くことができる。
promiseオブジェクトを作る→resolveすると次の処理に行ける→.thenで次の処理を書く。
入れ子にせんで良くなりました！
以下、例です。

```javascript
new Promise (resolve=> resolve('生中お待ち！'))
.then(res=>console.log(res))
// ここでのresは`response`の略。
```

じゃあ、先程の居酒屋での処理を下に記述します。

```javascript
new Promise(resolve=>{
   setTimeout(()=>{
      console.log('生中お待ち！')
       resolve()
    },1000)
   }).then(()=>{
      return new Promise(resolve=>{
        setTimeout(()=>{
         console.log('トマト！お待ち');
         resolve();
        },1000);
       });
     }).then(()=>{
        return new Promise(resolve => {
           setTimeout(() => {
             console.log('ヘイよ唐揚げ！')
             resolve()
          },1000)
       })
      })
```

ネストがなくなり、順番に出てきますけど、、、<font color="red">***全然見にくくない???***</font color="red">
さっきまでは、オーダーを頭で覚えてたけど、今度は紙に書いて順番に並べてもらった！！！！！、、、結局たくさんオーダー貰ったら見にくいよ...
もっといい方法ないかね...???


#aync await
`async`を宣言することによって、関数が非同期処理であることを明示する。

```javascript
func = async () =>{
await log ('生中お待ち！');
await log ('トマト！お待ち');
await log ('ヘイよ唐揚げ！');
};

log=(order)=>{
return new Promise (resolve=>{
   setTimeout(()=>{
        console.log(order);
        resolve();
   },1000)
 });
}
func()

```

同じ処理（皿を出したり、調味料を準備したりはもうあらかじめやっておいて、具体的なオーダーが入ったらその都度やることをやっていく！）
これで一気に見やすく、かつ楽に記述できるようになったのではないだろうか？？？

#最後に
だいぶ分かりにくかったかもしれません。
分かりにくい方は、当記事の内容に関しては多くの方が記事等に残してくださってますので、そちらをご覧になると良いかもしれません。
最後までお付き合いいただき、ありがとうございました.
AWS: デフォルトVPC 削除と新規作成

# はじめに

AWSのアカウント作成時に初めからある`ネットワークのデフォルト設定`について
自己整理のため、記事に残す。



# awsデフォルトのネットワーク設定

ネットワーク構成はデフォルトで`VPCとサブネット以外にも`
`それに付随するネットワークの設定`が作成されている。

詳しくは公式ページに参照されているが、VPCとサブネット以外だと
`・インターネットゲートウェイ`
`・ルートテーブル`
`・ネットワークアクセスコントロールリスト (ACL) `
`・DHCP オプションセット`
と、いい感じに相互関係のあるリソースまとめてくれている。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/default-vpc.html



# デフォルト設定の整理

私の場合、aws教材学習の終了後にリソース整理している時に
一部だけ（インターネットゲートウェイ）を削除していたようで
その後のdocker学習を少し停止させる要因になった。

ポートフォリオには、デフォルトVPCは使わない人が多いかもしれないが
教材学習時にデフォルトVPCを使用する人もいるかもしれない。

そういった時には、
 `１、デフォルトVPCを削除`
 `２、新しくデフォルトVPCを作成`
すると、`リソースが一元的に復活する`ので良いかも。

方法はめちゃくちゃ楽で一瞬で終わる！



# 削除

まずは
・AWSコンソールマネジメントからVPCメニューに移動
・消したい対象のデフォルトVPCを選択
・アクションでVPCの削除を選択

![スクリーンショット 2021-08-31 10.28.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/26089e8f-d74d-0564-0a84-5d52dbd1ef2f.png)


続いて、ポップアップで出てくるメニューで
・デフォルトVPC削除にチェックを入れる
・「デフォルトVPCの削除」と入力する
・削除ボタンを押す

![スクリーンショット 2021-08-31 10.42.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/19c08d27-1c15-7ca0-3732-58b8b7bc9393.png)

これだけで作業が完了！めちゃ楽！



# 参考（デフォルトVPCにリソースが残ってる場合）

消そうと思ったデフォルトVPCにリソース（EC2等）が残っている場合は
「中にリソースが残ってるよ！」とawsが警告文を出してくれる。

![スクリーンショット 2021-08-31 10.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/066880b3-3058-9754-1633-db8b3c9180f7.png)

その場合は要因となっているリソースを先に削除する。
（下記はEC２を削除する事例）

![スクリーンショット 2021-08-31 10.37.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/fb4893f3-78d0-6a7d-35da-841d2d8a4dfb.png)

この処理の後に、デフォルトVPCの削除作業をすれば上手くいく。



# 新規作成

次はデフォルトVPCを新しく作成する。

VPCメニューから存在するVPCを選択しない状態で「デフォルトVPCを作成」をクリックする。

![スクリーンショット 2021-08-31 10.57.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/dcbf70c2-7547-eed8-9d36-ab3bc569f9e3.png)

あとは案内の通りで「デフォルトVPCを作成」をクリックする。

![スクリーンショット 2021-08-31 11.00.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/f34fd9e4-abb9-2ee2-19c2-73e7ecdfe609.png)

これでデフォルトVPCおよび付随するリソースが新規作成される。



# したかった事

個人的にやりたかった事は、docker-machineコマンドを使って
aws上にEC2インスタンスを作成したかった。（教材学習のため）

しかし、下記コマンド入力後に
「Waiting for SSH to be available...」
以降の返答が返ってこず、長時間フリーズしまった。

```言語:ターミナル

% docker-machine create --driver amazonec2 --amazonec2-open-port 8000 --amazonec2-region ap-northeast-1 aws-sandbox

~~返答~~

省略

Waiting for SSH to be available...
↑ 以降フリーズするので、「ctrl + c」で脱出

```

awsのコンソールマネジメント上ではインスタンスの表示を確認するも
ssl通信でエラーが起きているようにしか思えず、原因を探る。

エラー要因は確定できなかったが、docker-machineコマンドには
awsのデフォルトVPCが使われると気がつき、そこからデフォルト設定を見直すと
個別にインターネットゲートウェイやら何やらを消してる…

じゃあ、デフォルトVPC一式をまとめて一括で元に戻す便利な方法ないやろか…で
たどり着いたが下記記事だった。

https://dev.classmethod.jp/articles/tsnote-vpc-delete-default-resources/



# 終わりに

AWSのデフォルトVPCを使うケースも多くないかもしれないので
他の人に役に立つ記事ではないかも。笑

自分としては学習用としてデフォルトVPCはこれからも使っていくつもり。

では、失礼します。
【ローカル環境でのWebhook エンドポイント】Simple Membership + Stripe でサブスク有料会員実装方法。

タイトル通りで、WordPressプラグインのSimple Membershipを利用した、Stripeでサブスク有料会員実装方法。
本番環境ではスムーズに行きそうな設定も、ローカル環境だといろいろややこしい部分があったので備忘録。

#Simple Membership側の設定
管理画面 > WP Membership > 支払い > Create New Button
で有料会員になるための支払いボタンを作る。
基本的にはこの設定方法はいろんな記事があるので、そちらを参考に。
参考：https://hanami-web.tokyo.jp/blog/member/create-stripe-subscription/

##上記記事記載以外の注意点（ローカル・テスト環境）
ローカル環境でテスト決済をしようと思っても、上記記事の通り設定してもエラーが出る。
諸々の解決方法は下記です。
###①「Live Publishable Key」と「Live Secret Key」もテスト用のキーを入れる
APIキーの入力には
・Test Publishable Key
・Test Secret Key
・Live Publishable Key
・Live Secret Key
の4つの入力欄がある。ここで素直に「Live Publishable Key」と「Live Secret Key」に本番用のキーを入れると、テスト商品と紐付けられない。
###②Webhook エンドポイントの設定
ローカル環境のURLはstripeにエンドポイントとして設定できないので、stripe CLIを使ってWebhook エンドポイントを設定する必要がある。
ちなみにエンドポイントを設定しなくても、ボタンの表示→決済成功まではいけるが、該当の決済した会員が有料会員に変更されない（そりゃそう）
これはまず、ターミナルでstripe CLIをインストールする必要がある。
この方法は下記参考。
参考：https://stripe.com/docs/webhooks/test

ステップ3の「イベントをお客様のサーバに転送する」で、
```stripe listen --forward-to 管理画面でのサブスクボタン作成時に表示されたエンドポイント```
とするとターミナル上でイベントをリッスンできる。
リッスンしながら、ブラウザで決済をすると無事に該当の会員が有料会員に変更されているかと思います。
Herokuへデプロイしたときのメモ

# はじめに
本記事はRailsチュートリアル第6版の復習用としてHerokuへのデプロイ方法をまとめました。


#デプロイ方法


復習用として、RailsでつくったアプリをHerokuを用いてデプロイする方法を記述しております。
(*Herokuアカウントは作成したものとしてデプロイ方法を記述しております)

①まず、Gemfileには以下のように記述しましょう。

```
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails',      '6.0.3'
gem 'puma',       '4.3.6'
gem 'sass-rails', '5.1.0'
gem 'webpacker',  '4.0.7'
gem 'turbolinks', '5.2.0'
gem 'jbuilder',   '2.9.1'
gem 'bootsnap',   '1.4.5', require: false

group :development, :test do
  gem 'sqlite3', '1.4.1'
  gem 'byebug',  '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'web-console',           '4.0.1'
  gem 'listen',                '3.1.5'
  gem 'spring',                '2.1.0'
  gem 'spring-watcher-listen', '2.0.1'
end

group :test do
  gem 'capybara',           '3.28.0'
  gem 'selenium-webdriver', '3.142.4'
  gem 'webdrivers',         '4.1.2'
end

group :production do
  gem 'pg', '1.1.4'
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]


```
HerokuではPostgreSQLデータベースを使います。そのため、本番環境(production)では、'pg' gem　をインストールします。
また、HerokuはSQliteをサポートしていないため、
本番環境では'sqlite3' gemが導入されないようにしましょう。

②これでGemfileの準備はokです。本番用以外のgemをインストールしましょう。

```
$ bundle install --without production
```
③本番環境へのデプロイ用に、コミットを行います。

```
$ git commit -a -m "コミット内容"
```

④Herokuをインストールしましょう。

```
$ source <(curl -sL https://cdn.learnenough.com/heroku_install)
```

⑤Herokuにログインしましょう

```
$ heroku login --interactive
```
⑤Herokuに新しいアプリケーションを作成しましょう！

```
$ heroku create
```
⑥HerokuにGitのリポジトリをプッシュしましょう。（少々時間がかかります）

```
$ git push heroku main
```

お疲れさまでした！これでHerokuへのデプロイは完了しました！
関数やメソッドの引数の数を調べて、必須項目以外をnullで埋める際のtips

```php
class Hoge
{
    // 引数が多い
    public function getHogehoge(int $id, ?int $arg1, ?int $arg2, ?int $arg3, ?int $arg4, ?int $arg5)
    {
        return 'hogehoge';
    }
}
```

こんな引数が多いメソッド（しかも引数の数はたまに変わる）を使う際、`$id`だけ使い、それ以外nullで埋める場合の備忘録
そもそも引数をどうにかしろという言葉はぐっと堪えて下さい。。。

# 対応
```php
// 関数の構造を格納
$refl = new \ReflectionClass("Hoge(HogeクラスのあるPath)");
// getHogehogeの引数の数を取得
$arg_num = $refl->getMethod("getHogehoge")->getNumberOfParameters();

$hoge = new Hoge();
// array_fillでnullを$arg_num - 1個分埋める
$products = $hoge->getHogehoge(1, ...array_fill(0, $arg_num - 1, null));
```
## 参考
https://www.php.net/manual/ja/class.reflectionclass.php
機械学習における不均衡データ対策

#機械学習における不均衡データ対策について

機械学習における不均衡データとは，クラスごとのデータ数が均一でない場合のデータである．
例えば，Aクラスが99件，Bクラスが1件の場合，すべて，Aクラスと予測すれば，100件中99件が正解となりAcurracyは0.99と一見高性能であるが，Bクラスを予測することは難しい．
少数のクラスをきちんと予測することができるように不均衡データを扱う際には，対策を行わなければならない．

|  |実際のAクラス  |実際のBクラス  |
|---|---|---|
|予測したAクラス|99  |1  |
|予測したBクラス|1  |0  |

#対策の種類
- サンプリング
- 異常検知問題として解決
- コスト考慮型学習
- 不均衡データに対応した損失関数の使用

#サンプリング

不均衡データ対策として，簡単に行えるのはサンプリングである．
サンプリングには二種類あり，多数のクラスに合わせるオーバーサンプリングと少数のクラスに合わせるアンダーサンプリングがある．
しかし，単純にサンプリングを行うとオーバーサンプリングでは，少数のクラスの重複が発生し過学習につながる可能性がある．
また，アンダーサンプリングでは，多数クラスの重要な特徴量を取りこぼす可能性がある．

オーバーサンプリングで代表的なものとしてSMOTEがある．
SMOTEは図のように新しいベクトルを同じクラスタの2点間から内挿を取って作成するという手法である．

```math
r1 = X1 + d \times gap
```

<center>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189046/ad1b25d9-0772-3fab-9979-6b5cd86520c1.png">
</center>

#異常検知問題として解決

データの不均衡が極端な場合には，異常検知を考える．
データの分布を分析し，その分布を通常とし，逸脱した値を異常値として，クラスを分ける．

1 class SVM，Isolation Forestsといったアルゴリズムがある．

ただし，下記のように分布が重なるような場合には使用することができない．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189046/41cec934-dccf-8d60-c30f-bbbc6e5d1311.png)



#コスト考慮型学習

機械学習では，誤分類を等しく扱うことが多い．
これを不均衡データに適用すると，

そこで，コスト考慮型学習では，データ数の少ないクラスの誤分類のペナルティを大きくすることにより，再現率を向上させる効果が期待できる．

XGBoostなどのアルゴリズムがある．


#不均衡データに対応した損失関数の使用

深層学習では，損失関数の定義を変更することで，不均衡データ対策を行うことが可能．

例えば，Focal Loss関数は，
正解に近い予測値の場合はそれ以上学習する事を抑えることになり、不正解なデータに対する学習をより進める性質がある．

他にClass-Balanced LossやAffinity lossといった損失関数がある．
[iOS] [Swift] WKWebViewでtarget=“_blank”に対応する

## デリゲートを埋め込む

**WKUIDelegate** を埋め込む

```swift
class MyViewController: WKNavigationDelegate, WKUIDelegate {
}
```

**_webview.uiDelegate** をセットする

```swift
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.webView.uiDelegate = self
        self.webView.navigationDelegate = self
    }
```

## webView:createWebViewWithConfiguration:メソッドを実装

対象URL（target=“_blank”）をSafariで開く

```swift
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        if navigationAction.targetFrame == nil {
            if  let url = navigationAction.request.url {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        }
        return nil
    }
```

[参考](https://stackoverflow.com/a/41116379)
[Java基礎②]西暦から平成を出す　自動的に現在の年を取得(import java.util.Calendar)

<h2>初めに</h2>
Java学習開始２日目です。
今回は、西暦から平成を出すプログラムを作成しました。

```
public class Main {
	public static void main(String[] args) {
        int seireki = 2015;
        System.out.print("西暦" + seireki + "年は");
        int heisei = seireki - 1988;
        System.out.print("平成" + heisei + "年です");
	}
}
```
「system.out.print」で改行されないようにしています。

<h2>自動的に現在の年を取得</h2>

以下のCalendarの使用方法については理解できていませんが、
以下のように記述することで、自動的に現在の年を取得できるそうです。

```
import java.util.Calendar;
public class Main {
	public static void main(String[] args) {
	    Calendar calendar = Calendar.getInstance();
        // int seireki = 2015;
        int seireki = calendar.get(Calendar.YEAR);
        System.out.print("西暦" + seireki + "年は");
        int heisei = seireki - 1988;
        System.out.print("平成" + heisei + "年です");
	}
}
```

import java.util.Calendar; 
ここでプログラミング上の部品を組み込めるそうです。
Mac miniからMac miniに乗り換えた際の備忘録

かなり雑なメモですが、初めて引越しをしたので一応備忘録。

備え付けの移行アプリやTimemachineを使って完全にバックアップから再現する方法（HD必要）や、ケーブルで接続して直接移行する方法もありましたが、今回はPC内の整理を兼ねて、必要なファイルをコピーしたり、再インストールする形で移行しました。
あとデータ移行に使うケーブルが5千円くらいしたという理由もあった気がします。

基本的に旧Mac miniにあるファイルの移行は、パブリックフォルダを共有して行いました。（サイズの大きさと時間が単純に比例しているわけでもなさそうだったけど、とりあえず数百MB以上のファイルは数十分〜数時間かかると思った方が良さそうです）
http://tokyo.secret.jp/macs/share_mac.html

## 移行準備

1. LaunchPadのスクショを取っておく
2. Apple IDのログイン情報を確認する
3. chromeブラウザはGsuiteアカウントで同期設定されていることを確認
2. FTPソフト(今回はFilezilla)の設定をエクスポート
3. Visual studio Codeの設定をプラグイン「setting sync」でGit hub上に上げる
4. 開発用ディレクトリで今までGithubで管理していなかったものがあればGithubにプロジェクトを作りpush
6. `npm ls  -g --depth=0`でnodeのバージョンとグローバルインストールしたnpmを確認し、メモしておく
7. Office365のログイン情報を確認
8. メモ帳アプリも移行したい場合はiCloudかGsuiteアカウントと同期しておく


## 移行後作業

1. LaunchPadのスクショを元にアプリをダウンロード、必要なものはログイン
2. chromeをDLし、Gsuiteアカウントでログイン同期
3. Publicフォルダを同期して、Finder右上の「画面を同期」を使いつつ、旧PCから必要なファイルを移行する。
5. 「./Library/font」ディレクトリ内も移行を忘れずに
6. .bashrcファイルを移行したら、コマンドエイリアスの設定をする(下記に詳細あり)
7. ディレクトリを引っ越ししてきたら、前回と同じ手順でDockerでwordpressを立ち上げる
8. Adobe系は公式サイトからクリエイティブクラウドをDLしてログイン後、必要なソフトをそこからインストール
9. Office365もMicrosoftのサイトにログインして、そこからインストール
10. メールクライアントとGmailを連携


#### エイリアスの設定

1. .bashrcファイルをルートディレクトリに配置
2. ディレクトリ移動などのコマンドでパスが変わっているものは修正
2. .zshrcファイルを作成して、`source ~/.bashrc`と記載
これで毎回ターミナルを立ち上げた時にエイリアスが読み込まれる。

3の手順を.bashrc_profileファイルに記載と説明している記事もあるが、今(Catalinaかららしい)はMacのターミナルは.zshrcがデフォルトのログインシェルになったため、.zshrcがある場合は.bashrc_profileは読み込まれないので注意。
あと今.bashrcファイルにエイリアスを書く必要性も多分ないですが、ファイルをコピペで済むのでそうしています。

参考：https://qiita.com/terufumi1122/items/1bbb1cf96e376e30e9fc


## 移行済の前PC
今回は一回全てフォーマットするという話だったので、
とりあえずSlackやブラウザなどだけログアウトしてフォーマットしてもらいました。

## クリーンインストール手順

大まかな手順としては以下のように行う。　https://estpolis.com/2019/12/64327.html
1. macOSのアップデート
2. データのバックアップ
3. 「macを探す」の無効化
4. ストレージの削除
5. macOSの再インストール
6. データやアプリの復元

- macOSのアップデート

    Apple メニュー から「システム環境設定」を選択し、「ソフトウェアアップデート」をクリックして、アップデートがないか確認します。
    アップデートがある場合は、「今すぐアップデート」ボタンをクリックしてインストールしてください。または、「詳細」をクリックして、各アップデートの詳しい情報を参照し、インストールする特定のアップデートを選択します。

- データのバックアップ

    今回は行いませんでしたが、必要であればデータのバックアップを行います。
    内蔵ストレージは削除されるので、外付けHDDやiCloudにデータをバックアップしてください。

- 「macを探す」の無効化

    > Apple T2チップを搭載するMacの場合、「Macを探す」を予め無効化しておかなければエラー番号「-1008F」が表示され、OSをダウンロードできなくなる
    https://gori.me/mac/mac-tips/105061

とのことなので、該当する場合は無効化します。macを使わなくなる場合にはiCloudなども解除する必要があります。

- ストレージの削除

    - ここで電源を落とし、再びmacを起動します。このとき、macOSユーティリティを起動するため、「command（windowsのキーボードの場合はwindowsキー） + R」のキーを押したまま電源ボタンを押します。
    - macOSユーティリティが起動したらディスクユーティリティを選択し、ストレージを削除します。このとき、「macOS Base System」を削除しないように注意してください（おそらく再インストールが面倒になります）。

- macOSの再インストール

    ディスクユーティリティを終了し、「macOSの再インストール」を選択します。このとき、インストール先は内蔵の「Macintosh HD」を選択します。

- データやアプリの復元

    再インストールの完了後、必要なデータなどの復元を行います。
python3でコーディングテストに受かるための自分メモ[8/31] (標準入出力について)

##python3で標準入力をキャッチする
標準出力するのはprint文
では入力をキャッチするのは
```input_line = input()```
で取得することができるらしい。
もちろんキャッチした型はstring型。
複数行キャッチしたい場合は、
2行書いたら1行ずつキャッチすることができた。
###文字列操作について詳しく調べてみる。
#####string.strip()
文字列の前後の空白を取り除くことができるらしい。
改行文字なども取り除かれる。
取り除きたいものを指定すれば取り除くことができる。
lstripとrstripはleftとrightの略で指定した方の空白を取り除く。
#####string.replace()
引数を二つ取り、第一引数で指定したものを、第二引数で指定したもので置き換えることができる。
#####string.split()
文字列を空白で区切り、配列で取得する。
#####string[3:7]（スライス）
先頭3文字目から7文字目を取得することができる。


###ついでにファイル操作も
#####open
ファイルオープン
```f = open(path)```
#####close
```f.close() ```
#####read()
```s = f.read()```
ファイルも中身も文字列として取得することができる
#####readlines()
``` l = f.readline()```
ファイルの中身を1行ずつ取得することができる
``` l = f.readlines()```
ファイル全体を行ごとの文字列の配列として取得することができる。
#####mode=w
ファイルが存在すれば書き込みができ、存在しなければ新規作成することができる。
``` open(path, mode='w') ```
#####write()
```f.write(string) ```
ファイルに書き込みを行うことができる。


###print文について
pythonのprint文はでdefaultで改行文字が付いている。
よって改行したくない場合は
print文の第二引数で
```print(string, end="") ```
endに空文字を指定することで可能
【Git/Github 初心者】草を生やす~コントリビューション~

##草を生やして記録を残そう
今回はコントリビューションの仕方を書いていきます。
Gitで設定をすることで、Github上で作業した記録を残していくことができます。
⚠︎Githubで公開鍵の登録、接続をしている前提で進めていきます。

##設定の仕方
ターミナルに下記コマンドを入力します。

```terminal.
$ git config --global user.name "Githubのユーザ名"
$ git config --global user.email "Githubに登録したメールアドレス"
```

以上です。
これでpushすると草が生えます。

##余談
チーム開発などでブランチを切っている場合など、デフォルトブランチにいない場合草が生えません。
デフォルトのブランチを自分の作業ブランチに切り替えたり、デフォルトブランチにマージすると反映されます。

#####おわり
Mini-PCにFedoraを入れてリモート開発環境を構築する

# MiniServerにFedoraを入れて、リモート開発環境を構築する

## きっかけ
移動中や外からでも開発できる環境を整備しようと思っていたところ、
ビックカメラで激安のパソコンが販売されていたので、ポチって見ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/2f872076-5d18-1dfa-6003-b596da1bc6d0.png)

RaspberryPiでもよかったのですが、ラズパイよりも安く
CPUがArmではなく、Intelという部分が購入の決め手になりました。

## スペック
ラズパイに比べて非力ですが、ミニサーバとしては十分かな

| |Mini-PC|RaspberyPi|
|---|---|---|
|CPU|Intel D2700(2core/4thread)|ARM(4core/4thread)|
|RAM|2GB|4GB|
|Disk|320GB|(microSD)|

## Fedora (Server)をインストール
Language：English
Keyboard:Japanese
Disk:　Local Standard Disk全体を選択
Network: Ethernet(ens1)が有効になっていることを確認
Timezone:Asia/Tokyo
Installation Source : default
Software Selection : Minimal Install - Standard

## パッケージ更新
```
[user@fedora ~]$sudo dnf -y update
・・・・
Complete!
[user@fedora ~]$
```

## Code-Server インストール
```
[user@fedora ~]$curl -fOL https://github.com/cdr/code-server/releases/download/v3.11.1/code-server-3.11.1-amd64.rpm
[user@fedora ~]$sudo rpm -i ./code-server-3.11.1-amd64.rpm
[user@fedora ~]$sudo sytemctl enable --now code-server@user
[user@fedora ~]$sudo firewall-cmd --premanent --add-port=8080/tcp
success
[user@fedora ~]$sudo firewall-cmd --reload
success
[user@fedora ~]$
```

## 接続確認
http://[Mini-PCのIP]:8080
パスワードは`.config/code-server/config.yaml`に記載されています。
Linux（bash）dateコマンドチートシート

dateコマンドに関するチートシート

| やりたいこと・フォーマット     |コマンド                  |
|----------|--------------------------|
|yyyy-mm-dd  | ```date "+%Y-%m-%d"```         |
|yyyy-mm-dd HH:MM:SS  | ```date "+%Y-%m-%d %H:%M:%S"```         |
|yyyy-mm-dd HH:MM:SS＋ナノ秒  | ```date "+%Y-%m-%d %H:%M:%S.%N"```         |
|30日後  | ```date "+%Y-%m-%d" -d "30 days"```         |
|30日前  | ```date "+%Y-%m-%d" -d "30 days ago"```         |
|特定日の30日後  | ```date "+%Y-%m-%d" -d "30 days 2021-02-28"```         |
|特定日の30日前  | ```date "+%Y-%m-%d" -d "30 days ago  2021-02-28"```         |
|UNIX時間|```date "+%s"```|
|UNIX時間を日付に|```date "+%Y-%m-%d %H:%M:%S" -d "@1630378862"```|
Eclipse と Github を連携する方法 ～ パーソナルアクセストークン の 使用方法 ～

# 2021/8/13以降、Eclipse から Github を使う方法　

Githubは **2021/8/13** 以降、[パスワード認証でGit操作ができなくなり](https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/)ました。

これにともない Eclipse の Gitクライアント(EGit) でパスワード認証をしていた場合は、パーソナルアクセストークンを利用したものに変更する必要があります。

- 環境： **Eclipse 2021-06**

## Github でパーソナルアクセストークンを発効する

- メニュー > **Settings** を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/e6c5c375-df0f-ccbb-0cba-01c5bfc75d07.png)


- **Developer settings** を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/0a0b0076-fb60-d8b3-ce4d-9b94dc9bcccd.png)

- **Personal access tokens** を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/610116c3-8baf-1b63-1f1a-87ec03d0c70c.png)

- **Generate new token** をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/4d7b002b-a6f6-df51-1aa1-57fc0772b5a3.png)


- 必要項目を入力する
 - Note:パーソナルアクセストークンの利用用途を記述
 - Expiration:パーソナルアクセストークンの利用期限を設定
 - Select scopes:このパーソナルアクセストークンがもつ権限をセット。Eclipseからリポジトリ操作を行いたいので **repo** に「✔」をいれる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/7e54256c-b303-9631-2e51-10565b0b9138.png)

- **Generate token**をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/52946f1a-41eb-b3bd-e350-1eb399672cd9.png)


- 生成されたパーソナルアクセストークンをメモする

生成されたアクセストークンは<font color="red">**1度きりしか表示されない**</font>ので、Eclipseに設定する前に一時的にメモしておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/65aa7120-65a5-7897-8802-07f07b9446c7.png)

これでパーソナルアクセストークン生成はおしまい

## EclipseからパーソナルアクセストークンをつかったGithub連携を行う

ここでは、認証が必要な private なプロジェクトをインポートする例でみていく

- File > import を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/bb64b67a-8973-635e-ae2a-9d788b0c21a4.png)

- **Git > Projects from Git** を選択
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/c75d2c1a-750d-cb5d-4904-ecc2ee30d699.png)

- GithubにあるプロジェクトをクローンしてEclipseで編集したいの**Clone URI** を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/ff3dc924-0097-80ae-b5c0-60178b9f1ba3.png)

- GithubにあるプロジェクトのURIを入力したあと**Authentication**に User と Password の入力をする
 - User には Githubのユーザー名を入力
 - Password には、**先ほど生成したパーソナルアクセストークン**を入力する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/cad71998-2de8-dc86-f178-a3b55d164267.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/b5f7e4ac-1b12-8bd5-b06f-2c972f321fcd.png)

- 無事認証が成功した。（あとは画面に従ってインポートを終了する）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/66ef335d-7b37-7f6c-f6d6-129536675bff.png)

# まとめ

- Githubはパスワード認証が廃止になった
- Eclipseのような外部クライアントからGithubリポジトリを操作したい場合は、権限をつけてパーソナルアクセストークンを生成する必要がある
- EclipseからGithubを使う場合には、Git(EGit)の設定画面で User には**Githubのユーザー名**、 Passwordには **Githubで生成したパーソナルアクセストークン**をセットする
クロスドメインになるバックエンドAPIサーバのFlask実装例

## 実現したいこと
下記Flask部分の実装例を示す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/1e0c93f8-de82-1782-dbd9-3d6c047af937.png)


## 環境
- python 3.9.6
- flask==2.0.1
- flask-cors==3.0.10
- flask-login==0.5.0


## 実装例
**API要件**

- ログインしたらペットが参照できる
- ログインしていなければペットが参照できない


```python:app.py
#!/usr/bin/env python3
from datetime import timedelta
from flask import Flask, jsonify, request
import flask_cors
import flask_login

app = Flask(__name__)
login_manager = flask_login.LoginManager()
login_manager.init_app(app)
origins = ["https://AAA.com"]
flask_cors.CORS(
    app,
    # Cookieとクレデンシャルをドメイン間で送信できる
    supports_credentials=True,
    # フロントエンドのドメインを指定
    origins=origins,
)

app.config.update(
    SECRET_KEY="key",
    # セッションの有効期限1日
    PERMANENT_SESSION_LIFETIME=timedelta(days=1),
    # @flask_login.login_requiredのhttp通信を拒否する
    SESSION_COOKIE_SECURE=True,
    # JavaScriptがCookieへアクセスできなくする
    SESSION_COOKIE_HTTPONLY=True,
    # クロスドメインのバックエンド⇨クライアントでSet-Cookieを返す
    # Secure属性を付けないとNoneにできない
    SESSION_COOKIE_SAMESITE="None",
)


class User(flask_login.UserMixin):
    def __init__(self, user_id):
        self.id = user_id


@login_manager.user_loader
def user_loader(user_id):
    return User(user_id)


@app.route("/login", methods=["POST"])
def login():
    # formからのCSRF対策でoriginヘッダーをチェックする
    if request.headers.get("origin") not in origins:
        return jsonify({"message": "Unauthorized"}), 401

    # 簡易的なログイン処理
    if request.json["user_id"] == "qiita" and request.json["password"] == "1234":
        flask_login.login_user(User(request.json["user_id"]))
        return jsonify({"message": "Logined"})
    else:
        # 前のセッションが残らないようにログアウトする
        flask_login.logout_user()
        return jsonify({"message": "Bad Login"}), 401


@app.route("/pets", methods=["GET"])
# sessionが有効なときにアクセスできる処理
@flask_login.login_required
def pets():
    if request.headers.get("origin") not in origins:
        return jsonify({"message": "Unauthorized"}), 401

    return jsonify({"pets": [{"name": "dog"}]})


@app.route("/logout", methods=["POST"])
@flask_login.login_required
def logout():
    if request.headers.get("origin") not in origins:
        return jsonify({"message": "Unauthorized"}), 401

    flask_login.logout_user()
    return jsonify({"message": "Logouted"})


# sessionが有効でないときの処理
@login_manager.unauthorized_handler
def unauthorized_handler():
    return jsonify({"message": "Unauthorized"}), 401
```


## 参考
フロントエンド側ではクロスドメインでCookieを送信できるようにするため、
HTTPリクエストに"Access-Control-Allow-Credentials: true"ヘッダーを付与する
環境センサーのデータをスマホでモニタリングする(Flutter) - データ蓄積編 -

## 概要  
* 新型コロナの影響で環境センシングデバイス、可視化ツールの需要が高まっている。
* 前回「IoT-DX-Kit」を使って、スマホのFlutterアプリ上で気温、湿度を可視化してみた。
* 今回はクラウド(AWS)上にデータ蓄積を行う。
* EC2インスタンスやRDB、S3を使わない方法を試してみた。

AWSのCloudWatchにデータが温湿度データが蓄積されている様子
![スクリーンショット 2021-08-31 9.08.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/a820c19d-532d-8e0d-9b3d-1814ba52f704.png)

## 用意するもの
* IoT-DX-Kit マイコンボード
* DHT22 温湿度センサー
* AWSアカウント

## 環境構築
(1)Flutterをインストール
　https://www.arduino.cc/en/main/software
(2)Flutter Blueをインストール
　https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library
(3)AWSアカウントを作成

## 構成
APIサーバーを作らず、API Gateway宛に届いたPOSTデータを契機にLambdaがCloudWatchに書き込むようにする
![スクリーンショット 2021-08-31 9.25.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/80372725-632e-a72d-7a8d-d76ce311e14a.png)

## プログラミング
Lambdaにて、POSTされたデータをCloudWatchに書き出すスクリプトを書いておく
LambdaはデフォルトでCloudWatch Logにログを書き出すようになっているのでIAM設定の必要はなし  

名前：(任意)
ランタイム：Node.js 14.x
アクセス権限：AWS ポリシーテンプレートから新しいロールを作成
ロール名：（任意）

![スクリーンショット 2021-08-31 9.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/14d38987-536d-b120-7691-37ff9f651745.png)
テストイベントの作成」からテストを作って、実行後ステータス200で正常終了することを確認する

```js:index.js
exports.handler = (event, context, callback) => {
    console.log("callback response " + JSON.stringify(event['body-json']));
    callback(null, {"message":"Received!"});
};
```
API GatewayでAPIリソース(/reciever)を追加する
![スクリーンショット 2021-08-31 9.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/b0d095aa-1931-083f-0ddb-a70168c550a6.png)

Flutter側で、API Gatewayより発行されたURLにに温湿度データをPOSTする処理を追加する
API Gatewayでは、`x-api-key` ヘッダーでアクセス制限をかけておく

```Dart:lib/utils/little_endian_extractor.dart
Future<void> sendjson(data) async {
  final url =
      "https://abcabcabc.execute-api.ap-northeast-1.amazonaws.com/test-receiver-999-105/receiver";
  Map requestBody = {
    "temperture": (data.getInt8(0) + data.getInt8(1) / 100),
    "humidity": (data.getInt8(2) + data.getInt8(3) / 100),
    "datetime": DateTime.now().toString()
  };
  String body = json.encode(requestBody);
  print(body);
  http.Response response =
      await http.post(Uri.parse(url), body: body, headers: {
    "Content-Type": "application/json",
    "x-api-key": "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
  });
  var res = json.decode(response.body);
  print(res);
}
```

## 検証 

CloudWatchでデータが蓄積されている様子
![スクリーンショット 2021-08-31 10.02.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/9c414e65-ea12-e35f-e195-2992e6d7adbd.png)

ダッシュボードからウィジェットを追加すればグラフ表示も可能

![スクリーンショット 2021-08-31 10.07.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/fed98fa3-9441-a8a7-4486-19de7c321dc7.png)
ダッシュボードの設定
![スクリーンショット 2021-08-31 10.09.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/ba2d2ad4-d2d8-9f33-f39b-1962dbde875f.png)

## 次回に向けて
* 蓄積したデータを他のAWSサービスを利用して分析に使うことを考えてみる
M5Stack Core2 で日本語表示

![IMG_20210831_100055.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f40faa58-a6c5-6a45-fd0d-fcf1f5c2c74f.jpeg)

```text:display02/display02.ino
// ---------------------------------------------------------------
/*
	display02.ino
	
						Aug/31/2021
*/
// ---------------------------------------------------------------
#include <M5Core2.h>
#include "CUF_24px.h"

// ---------------------------------------------------------------
void setup()
{
  M5.begin();
  M5.Lcd.setFreeFont(&unicode_24px);
  M5.Lcd.setTextDatum(TC_DATUM);
}

// ---------------------------------------------------------------
void loop()
{
  M5.Lcd.fillScreen(0);
  M5.Lcd.drawString("壁にかかった鏡や、鏡", 160, 60, 1);
  delay(2000);
  M5.Lcd.drawString("国一番の、美人は誰じゃ", 160, 90, 1);  
  delay(4000);
  
  M5.Lcd.fillScreen(0);
  M5.Lcd.drawString("ああ、おきさま、あなたさまこそ", 160, 120, 1);
  delay(2000);
  M5.Lcd.drawString("国一番の、ごきりょうよし", 160, 160, 1);
  delay(4000);

// ---------------------------------------------------------------
}
```

CUF_24px.h
はこちらにあります。
[M5Core2/examples/Advanced/Display/Display_Unicode/](https://github.com/m5stack/M5Core2/tree/master/examples/Advanced/Display/Display_Unicode)


Arduino 1.8.19 で表示した様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/e677a0d0-2ee5-b88c-a9a8-cb2547a51dfd.png)
Excel VBA 指定したRange範囲をCollectionに注入する

##関数 makeColl(arg1,arg2)as Collection
第一、第二引数にRange(arg)のarg部分をString型で指定することで、指定範囲の要素が注入されたcollectionオブジェクトを返す。
【使用例】
Dim coll as new Collection
Set coll =makeColl("A1","A5")
##関数 cCelltoRange(rowN ,colN)as Range

第一、第二引数にlong型で行,列を指定することで、Rangeオブジェクトを返す。
【使用例】
Dim coll as new Collection
Set coll =makeColl(cCelltoRange(1,1),cCelltoRange(5,1))


```
Option Explicit
Sub main()
Dim targetCellName1 As String
Dim targetCellName2 As String
Dim str As Variant
Dim targetColl As Collection
Set targetColl = New Collection
  targetCellName1 = InputBox("", "範囲セル１を指定")
    If checkCellValue(targetCellName1) = False Then
        MsgBox "無効なセル範囲"
        End
    End If
  
  targetCellName2 = InputBox("", "範囲セル2を指定")
    If checkCellValue(targetCellName2) = False Then
        MsgBox "無効なセル範囲"
        End
    End If
  
  Set targetColl = makeColl(targetCellName1, targetCellName2)
    For Each str In targetColl
      MsgBox (str)
    Next

End Sub
```

```
Function makeColl(arg1 As String, arg2 As String) As Collection
  'argにrange範囲を指定し、collectionで返す
  '「【arg1 例】B2」「【arg2 例】B4」→B2:B4
  
Dim coll As Collection
  Dim targetRange As Range
  Dim item As Variant
  Set coll = New Collection
  
  Set targetRange = Range(arg1 & ":" & arg2 )
    For Each item In targetRange
      coll.Add (item)
    Next
  
  Set makeColl = coll
End Function
```

```
Function cCelltoRange(rowN As Long, colN As Long) As Range
  '行、列番号を指定でRangeオブジェクトを返す
  Set cCelltoRange = Range(Cells(rowN, colN).Address)
End Function
```

```
Function checkCellValue(str As String) As Boolean
'要参照設定 Microsoft VBScript Regular Expressions 5.5
  Dim reg As New RegExp
    With reg
      .IgnoreCase = False
      .Pattern = "[A-Z]+[1-9]+\d*"
    End With
  checkCellValue = reg.test(str)
End Function
```
include_pathで外部モジュールを呼び出せるようにする *LaraDock環境*

# include_pathってなんやねん

PHPを使い始めてもうすぐ三か月がたちます。ようやく赤ちゃんから小学生くらいには成長したのではないかというところで、業務でドはまりしたことがありました。何がしたかったかというと、ダウンロードしてきた外部モジュールをそのまま開発環境に置いて、Controllerとかから外部モジュールを呼び出したかったわけです。でもまぁこれが思ったよりうまくいかなかったので覚書として。

## 状況説明

簡単にですがディレクトリ構造を再現してみました。外部モジュール内にあるphpファイルを`sampleController.php`で呼び出すことが目標です。

```
app
├─Http
|　└─Controllers
|        └─sampleController.php
├─Models   
└─外部モジュール
   └─packageQ
      ├─A
      | └─A.php
      ├─B
      | └─callA.php
      └─C
        └─callAB.php
```

```A.php
<?php

class A
{
    public function hoge() {
        echo 'Aだよ';
    }
}

```


```callA.php
<?php
require_once 'packageQ/A/A.php';

class callA
{
    public function hoge2() {
        echo 'Bだよ';
        echo 'Aを呼ぶよ';

        hoge();  
        // Aだよ
    }
}

```


```callAB.php
<?php

require_once 'packageQ/A/a.php';
require_once 'packageQ/B/callA.php';

class callAB
{
    public function hoge3() {
        echo 'ABだよ';
        echo 'A, Bを呼ぶよ';

        hoge();  
        // Aだよ

        hoge2();  
        // Bだよ;
        // Aを呼ぶよ;
        // Aだよ
    }
}

```

## タイトル回収

include_pathはいわゆるPHP内の環境変数です。include_pathは`require`とか`include`を使って外部のphpファイルを呼び出すときに使います。この記事がわかりやすかったので是非参考にしてください。

https://qiita.com/awesam86/items/3fa28e23c95ca74caddc

さて、これら外部のphpファイルを読み込むには読み込みたいファイルのpathを指定する必要があります。pathの指定は絶対パスで相対パスでもどちらでも構いません。ちなみに相対パスよりも絶対パスのほうが実効速度が速くなるらしいです。

http://dqn.sakusakutto.jp/2013/05/php_require_once_include_once_include_path.html

ここではまりポイントが2つ現れます。一つずつ見ていきましょう。

###  dockerを使っているのに、パスの指定をPC上のパスを指定していた
dockerでlaravelを使うときapp以下をvolumesで/var/www/とかに流しておくと思います。この時include_pathは $/var/www/app/hogehoge$ という風になるはずです。なのに、私はずっとvscode上で絶対パスを取得していて、「おかしいなぁ、動かないなぁ」と考えていました。

### include_pathの設定はunixとwindowsの二つがある
include_pathはphp.ini内で設定されています。laradockだとphp{version}.iniです。見出しにもあるように実行環境？がどんなos動いているかによってパスの指定が異なります。私はwindowsを使っていますが、docker内で実行するのが前提なので、パスはunixの部分を修正する必要があります。

以上2点がinclude_pathについての、はまりポイントです。

きっと初歩的な間違いなんだろうな、、、

# composerのclassmap

さて、ここまでくるともうほとんどやることはcomposerさんがやってくれます。composerさんはすごくてclassmapというところに、laravel内で読み込みたいファイル or ディレクトリを書き込むと、名前空間と書き込んだファイルやディレクトリのパスを紐づけてくれます。
なので今回の場合、__"外部モジュール/packageQ"__ とかいう感じでcomposer.jasonに書き込み、composer dump-autoloadまで行います。あとは、コントローラーで __use 名前空間__ で所望のphpファイルが呼び出せるということです。

どうしても、class not found　になるときは __autoload_classmap.php__ を一度確認してみるといいかもしれません。ファイルの中身は実際に見ていただくとわかるのですが、キーが名前空間で値がパスになっています。エディタの検索(vscodeだと ctrl+F)とか使ってファイル名から名前空間を探し出すといいと思います。私も今回これで切り抜けました。

追記
似たようなことを書いている人を見つけました。

https://qiita.com/niiyz/items/5b83ef5255a1ec64d9d6


# コントローラーからrequireで呼び出せない？
外部モジュールをコントローラーから呼び出すのに、composerを使って名前空間を設定したのですが、別にrequireとか使ってもいいわけです。手間とか考えるとcomposerが楽だよねって話なだけで。余談ですが、私はなぜかコントローラーからはrequireで外部モジュールを呼び出せなかったです。include_pathの設定がおかしいのが原因だと思いますが、composerが楽ちんなので深くは考えないことにしました。
font-sizeの単位(px, %, em, rem, vw)

# はじめに
`font-size`の指定にいくつか単位があるので、それぞれの役割・使うタイミングを簡単ではありますがまとめました。


# font-sizeの単位

## px
`絶対的`な値を指定。
どんな画面サイズでも設定したfont-sizeとなる。
数値が大きくなればなるほど文字は大きくなる。

## ％
親要素に対して相対的な値を指定。
オブジェクトのレイアウトなどにも使用される。

## em
親要素に対して相対的な値を指定。
`%`と似ているが、`em`は基本的に`文字`のサイズ指定に使うことが多い。

```:【例】
親：１０px に対して 0.5em と指定 → 5px のフォントサイズとなる

.parent {
   font-size : 10px;

   .child {
     font-size : 0.5em;
    }
}
```

親の`px`を変更するだけで、現在の比率を変えずにfont-sizeを変更することができる。

## rem
常にhtmlに対して相対的な値を指定。
`%` `em` と違い、htmlの値だけを見ていればいい。
htmlでfont-sizeが指定していなければ、デフォルトで`16px`となる。
`○rem → htmlのfont-sizeの○倍の大きさ`

```:【例】htmlのfont-sizeがデフォルト値(16px)の時
1rem → 16px
2rem → 36px
0.5rem → 8px
```

## vw
表示領域の幅に対する割合。
ビューポートの幅に合わせてfont-sizeの値を指定できる。

```:【例】
font-sizeを 10vw と指定　→ ビューポートの幅に対して 10% のフォントサイズとなる
```

https://qiita.com/katsunory/items/3bede89cee8e2ded8426

# おわり
適切なfont-sizeはSEOの面でも重要！
→ PCでは適切な文字サイズでも、モバイルで小さすぎたらダメ（モバイルフレンドリーではないと判定される）

細かいことだと感じますが、ここをしっかり考えれるようになりたいです。
【備忘メモ】Eclipseで日本語文字が文字化けしたときの対処法

Eclipseで日本語文字が文字化けする場合、ワークスペースの文字コードをMS932（デフォルト）からUTF-8に変更する。

ウインドウ(W)>設定(P)から設定画面を開く。

ワークスペースメニューの「テキスト・ファイル・エンコード」で
その他のプルダウンから「UTF-8」を選択する。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879666/47ab44a3-e776-437e-d11a-38e2612ca002.png)




適用して閉じる。



以上
Swift frame bounds

Swiftでよく使用するframeとboundsの違いがわからなくて調べたのでメモ
--

両者ともUIViewが保持しているプロパティで```CGRect型(四角形の寸法を返す構造体）```になる


一言で言えば何を基準にしているか？ということ

・```frame```→Viewの要素自身を基準とした大きさ、座標
・```bounds```→UIViewを基準とした大きさ、座標

補足
・```center```はframeと同様にViewの要素自身を基準として中央の座標を返す。
Docker 使用者が AWS EC2 を立てたらまずやること(Amazon Linux 2)

Docker 使用者が AWS を使う場合は ECS や Fargate、EKS を使うことが多いですが、EC2を使う場合も多いかと思います。
本記事ではAWS EC2で直接 Docker や Docker Compose を使うためにまずやることを紹介(メモ)します。OSは Amazon Linux 2、ログインしたユーザはec2-userの想定です。

### まず yum update

EC2 を立てたらまずは yum updateを行い、再起動します。

```
sudo -i yum -y update
sudo -i reboot
```

### Postfixを止める

デフォルトで Postfix が上がっているので、止めておきます。
また、再起動時に Postfix が自動で上がらないよう、disableにします。

```
sudo -i systemctl stop postfix
sudo -i systemctl disable postfix
```

### Dockerをインストール

次は、Dockerをインストールし、立ち上げます。
yqとjqも良く使うので合わせてインストールしておきます。


```
sudo -i yum install -y docker jq yq
sudo -i systemctl start docker
sudo -i systemctl enable docker
```

Dockerがちゃんとインストールされたか、バージョン表示で確認します。

```
sudo -i docker version
```

### ec2-userにDockerの実行権限を与える

ec2-userでDockerを実行したいので、usermodを行います。

```
sudo -i usermod -a -G docker ec2-user
```

一度ログアウトして再度ログインします。
ec2-userでDockerが実行出来るかを確認します。

```
docker version
```

### AWS CLIをインストール

AWS CLIもよく使うのでインストールします。

```
sudo -i curl curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
sudo -i unzip awscliv2.zip
sudo -i ./aws/install
aws --version    
```


### Docker Compose をインストール

Docker Composeを使いたい場合は、Docker Composeをインストールします。

```
sudo -i curl -L https://github.com/docker/compose/releases/download/[インストールしたいバージョン]/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo -i chmod +x /usr/local/bin/docker-compose
docker-compose --version
```

これでAWS EC2でDocker及びDocker Composeを使う準備が出来ました。
docker ダウンロードエラー 解決策　（記録）

wsl 2 installation is incomplete. 失敗


エラー「WSL 2 installation is incomplete.」が表示された場合
* Windows再起動後に、以下のエラー内容が表示されたら、以下の対象方法を行う


【対象方法】
* 以下をダウンロード（wsl_update_x64.msi）して、インストールする。
　⇒ インストール後に、Docker を再起動する
　⇒ Docker Desktop is runningが表示されたらOK
https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
SFDXのエラー関係(環境設定)


# sfdx: No such file or directory /Users/myusername/.local/share/sfdx/client/bin/../7.110.0-85b006b/bin/sfdx: No such file or directory

削除するような感じです。

[sfdx: No such file or directory](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Brhw4)
返り値のない関数の実行をXCTest内で検知したい

例えばこのような関数があるとします。

```
class A {
    func test (num : Int) {
        if num < 10 {
            printTest()
        }
    }
    
    func printTest () {
        print("test")
    }
}
```


このような関数があった場合に、test(num : Int)をどうテストしようかな、と考えます。

検証したいケースは以下の2つ。

1. num < 10の時に、printTestが実行されていること。
1. num >= 10の時に、printTestが実行されていないこと。

# 悩んだこと
- printTestが実行されたことってどうやって検証するんや・・
- 実際にprintTestの中身で行われていることを検証すればいいが、それは関数testとは別のところでやってるから検証しなくてもいい（中でやってることは関係ない！　コールしていることさえわかればいい！）
- テストのために返り値Boolつけるとか絶対やりたくねぇ・・
- （似てるが）テストのために関数の中身ごちゃごちゃ変えるとかそんなにしたくねぇ・・
- Cuckooの導入でつまづいた

# 解決方法


```
class A {
    
    func test (num : Int) {
        if num < 10 {
            printTest()
        }
    }
    
    func printTest () {
        print("test")
    }
}


class FakeA : A {

    var printTestCount = 0
    override func printTest () {
        printTestCount += 1
        super.printTest()   // 親クラスの関数を実行をする
    }
    
}


--XCTest--
func test_A_numが10未満_printTestが実行されていること() throws {
    // 準備
    let A = FakeA()
    
    // 実行
    A.test(num: 9)
    
    // 検証
    XCTAssertEqual(A.printTestCount, 1)
}

func test_A_numが10以上_printTestが実行されていないこと() throws {
    // 準備
    let A = FakeA()
    
    // 実行
    A.test(num: 11)
    
    // 検証
    XCTAssertEqual(A.printTestCount, 0)
}


```

# 懸念点
- 実際にprintTest(内部の関数)を実行することによって、test(テスト対象の関数)にて検証したい数値に影響が出る可能性がある。
    - そうならない設計がベストではある。
    - 関数実行のみを検証するのであれば、printTestの中身にてsuper.printTest()を実行しなければいいだけではある。
        - だが、それではテストごとにFakeクラスを作成する必要があり非常に面倒
- いちいちFakeクラスを作るのがめんどくさい。
- privateメソッドの時とかのことはあんまり考えていない。（finalとかしちゃうとこれ使えないか）

ベストソリューションとは思っていないので、懸念漏れ/他のやり方等あればご指摘いただけるととっても嬉しいです。
osを作る その8

#概要

osを作る。
freertosを使ってみた。
arduino unoでlcd keypadに、時計を表示してみた。

#サンプルコード

タスクは、３本。

```
#include "Arduino_FreeRTOS.h"
#include "queue.h"
#include <LiquidCrystal.h>
#include "Time.h"

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

QueueHandle_t integerQueue;

void TaskAnalogRead(void * pvParameters) {
	(void) pvParameters;
	for ( ; ; )
	{
		int sensorValue = analogRead(A0);
		xQueueSend(integerQueue, &sensorValue, portMAX_DELAY);
		vTaskDelay(20);
	}
}
void TaskControl(void * pvParameters) {
	(void) pvParameters;
	int valueFromQueue = 0;
	int v = 0;
	for ( ; ; )
	{
		if (xQueueReceive(integerQueue, &valueFromQueue, portMAX_DELAY) == pdPASS)
		{
			lcd.setCursor(0, 1);
			if (valueFromQueue > 1000)
			{
				lcd.print("5");
			}
			if (valueFromQueue < 50)
			{
				lcd.print("0");
				setTime(hour(), minute(), 0, day(), month(), year());
			}
			else if (valueFromQueue < 250)
			{
				lcd.print("1");
				v = minute();
				v++;
				if (v > 59) v = 59;
				setTime(hour(), v, 0, day(), month(), year());
			}
			else if (valueFromQueue < 450)
			{
				lcd.print("2");
				v = minute();
				v--;
				if (v < 0) v = 0;
				setTime(hour(), v, 0, day(), month(), year());
			}
			else if (valueFromQueue < 650)
			{
				lcd.print("3");
				v = hour();
				v--;
				if (v < 0) v = 0;
				setTime(v, minute(), 0, day(), month(), year());
			}
			else if (valueFromQueue < 850)
			{
				lcd.print("4");
				v = hour();
				v++;
				if (v > 23) v = 23;
				setTime(v, minute(), 0, day(), month(), year());
			}
		}
	}
}
void TaskClock(void * pvParameters) {
	(void) pvParameters;
	for ( ; ; )
	{
		lcd.setCursor(0, 0);
		lcd.print(hour());
		lcd.print(":");
		lcd.print(minute());
		lcd.print(":");
		lcd.print(second());
		lcd.print(" ");
		vTaskDelay(10);
	}
}
void setup() {
	setTime(19, 50, 0, 8, 7, 2021);
	lcd.begin(16, 2);
	integerQueue = xQueueCreate(10,sizeof(int));
	if (integerQueue != NULL)
	{
		xTaskCreate(TaskControl, "Control", 128, NULL, 2, NULL);
		xTaskCreate(TaskAnalogRead, "AnalogRead", 128, NULL, 1, NULL);
	}
	xTaskCreate(TaskClock, "Clock", 128, NULL, 0, NULL);
}
void loop() {
}





```

#結論

freertosは、タスクからタスクを作って、実行は、できない。

以上。
Tailwind CSSで@tailwind記述時にVS Codeでエラーが出るときの対処法

※2021/08/31時点に確認できた動作になります。


## 使用環境
・MacOS BigSur（11.5.2）
・VScode（1.59.1）
・Node.js   (16.8.0）
・yarn  (1.22.11)

## はじめに

現在、Next.jsとTypeScript、そしてTailwindCSSでプロジェクトを作成しています。

```bash
yarn create next-app --ts my-app[アプリ名]
cd my-app[アプリ名]
yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest
yarn tailwindcss init -p
```

その際Tailwind CSSのセットアップで公式や他の記事を参考にしながらやっていると、タイトルのように@tailwindでimport時にエラーが表示されました。

styles/globals.css

```bash
@tailwind base;
@tailwind components;
@tailwind utilities;
```

これを記述したところで、

`Unknown at rule @tailwindcss(unknownAtRules)`
というエラー表示が出ています。

![スクリーンショット 2021-08-31 5.10.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711874/a4cebdd6-30c9-e825-6555-40e6e1b75d03.png)

これでも一応locallhost::3000のブラウザには反映されているみたいですが、ちょっと気持ち悪いのと後々問題があると嫌なのでこのエラー表示が出ない様にしたいです。

今回はその解決方法をまとめます。

## 解決策

結論から言うと、Workaround的な方法ですが今確認できているもので**2つ**あります。

① [公式doc][0]  の通りに設定

先程のstyles/globals.cssの記述を以下に書き換えます。

```bash
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
```

② VS Codeの[PostCSS Language Support][1]の拡張機能を導入する

こちらは[Stackoverflow][1]を参考にしたやり方です。
![スクリーンショット 2021-08-31 5.11.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711874/144f617f-8f98-c9d7-1c1d-5084feeb122c.png)
導入すると、＠tailwind部分の先程のエラーが消えているはずです。

ブラウザの方にも反映されています。

## 最後に

今のところ問題ないので、実験的にPostCSS Language Supportを使っていますが、おすすめは公式の方法です。

公式や他の記事通りにやってみて、どうして＠tailwindが使えないのか疑問点が残るところです。

公式には、

> If you’re using postcss-import (or a tool that uses it under the hood, such as Webpacker for Rails), use our imports instead of the @tailwind directive to avoid issues when importing any of your own additional files:

と書いてありました。
おそらくですが、自分はRailsを以前触っていたことがあったのでここに書いてあるWebpacker for Railsが干渉しているのではないかと思われます。

上にも書きましたが、Workaround感が拭い去りきれません。
これで後々エラーにぶつかったりしたら、Webpacker for Railsあたりを調べたり、そもそもの設定部分を見直したりする様にしていきます。

---

## 参考資料

- Tailwind CSS 公式 [Installation][0]
- Stackoverflow [How to add a @tailwind CSS rule to css checker][1]

[0]:https://tailwindcss.com/docs/installation
[1]:https://stackoverflow.com/questions/47607602/how-to-add-a-tailwind-css-rule-to-css-checker