OmniAICreator/Qiita-1.07M huggingface dataset:
docker desktop 2.4.0.0 にupdateしたらdocker imageが見つからない

## 環境

windows 10
Docker Desktop for Windows 2.4.0.0
WSL1, WSL2は使用していない

## 事象

- docker desktopのupdateの通知が来たのでよく確認せずに更新した。  
- Docker DesktopがバックエンドとしてWSL2を使用するようになった（どこかに選択があったかもしれない）。  
- これまで使用してきたdocker imageが見つからなくなって焦る。


## 原因

Docker DesktopがバックエンドとしてWSL2を使用するようになったため。

## 解決

設定の「Use the WSL 2 based engine」のチェックを外す
![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350437/7c861e63-9bde-327a-17f9-b2c77bfff1be.png)
PyCharmでデバック時にコマンドライン引数を指定する方法

- 環境
    - Windows10 Pro バージョン1909
    - PyCharm 2020.2.2 (Community Edition)

1. [Run] > [Edit Configurations]で[Run/Debug Configurations]ダイアログを開く
1. 左のメニューから[Python] > 対象のソースを選択する
1. [Configration]タブ > [Parameters:]に引数にしたい値を入力する
1. [OK]ボタンでダイアログを閉じる
1. 普通にデバック実行(Shift + F9)する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/74b410a4-5561-fcc5-29e7-b60e96cc8665.png)
Mendixでモバイルアプリを開発する（ハイブリッドアプリ）

# はじめに

Mendixのモバイルアプリは、Web、ハイブリッドアプリ、ネイティブアプリが選択できます。

![スクリーンショット 2020-09-30 12.17.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/e146f3a4-0fdf-2541-ba4a-975a80cb9529.png)

<dl>
<dt>レスポンシブWeb</dt>
<dd>MendixのWebアプリケーションを最速でモバイルに展開できます(React JS)</dd>

<dt>PWA</dt>
<dd>アプリストアに依存でずに、シンプルに展開できます。</dd>

<dt>ハイブリッドアプリ</dt>
<dd>既存のWeb機能を活用しながら、アプリを展開できます。PhoneGap/Apache Cordovaをベースにしています</dd>

<dt>ネイティブアプリ</dt>
<dd>最適なユーザーエクスペリエンスとデバイス統合できます(React Native)</dd>

</dl>

ただし、MendixのハイブリッドアプリはPhoneGapビルドを利用していて、PhoneGapビルドがiOS13までしか対応しておらずPhoneGapビルドのサービスも終了してしまうので、ハイブリッドアプリは（特にiOSで）推奨されなくなりました。
PWAは次期Mendix 9から利用できるようになるようです。

これらを目的に合わせて選択して利用することができるのがMendixのメリットの１つです。

# ハイブリッドアプリを作る - 前提

Android向けのハイブリッドアプリを作成しましょう。PhoneGapビルドではなくローカルでビルドします。

以下が必要です、

- AndroidStudio
- NodeJS LTS
- Java JDK 8

# ハイブリッドアプリを作る - Mendixクラウドの操作

Mendix Webの左のペインから「Mobile App」を選択します。
今回はAndroidアプリなので「Select Platform」で「Android」のみチェックを入れて、「Publish for Mobile App Stores」をクリックします。
「App Identifier」はAndroidアプリの識別子です。「-」（ハイフン）が入るとビルド時にエラーになるようです。適宜「-sandbox」などを削除してください。また、アプリの名前、説明も適宜設定してください。

![スクリーンショット 2020-09-30 13.31.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/f4d0b5e4-ae77-289c-4f17-029326cb6d5a.png)

上記のページを下にスクロールしたところ。いくつかオプションがあります。

![スクリーンショット 2020-09-30 13.30.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/6b8748e8-2ef4-f8bc-bbd6-4929a88157c9.png)

![スクリーンショット 2020-09-30 13.31.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/bc1062f2-8bbe-52ca-14c8-3c35f9d6c7d3.png)

「Select the environment to publish」は「Sandbox」のみ選択できます。
スクロールして「Download Customizable Package」をクリックします。ダウンロードして展開します。

![スクリーンショット 2020-09-30 13.32.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/589eed77-2b8e-6f2c-c815-cee9c5bfe5ba.png)

![スクリーンショット 2020-09-30 13.33.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/5a9ac043-7eb3-5898-d141-b866327c6a25.png)

Macの場合、~/Downloads/phonegap フォルダが展開されます。shellで以下のコマンドを実行して、PhoneGap/Apache Cordova環境に必要なライブラリを構築します。

```sh:
npm i
npm run package
npm run platform:android
```

AndroidStudioを起動します。

![スクリーンショット 2020-09-30 14.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/7030a656-b10e-0457-20de-6b47a9b04d62.png)

「Import project (Gradle, Eclipse ADT, etc.)」を選択します。
場所は ~/Downloads/phonegap/build/platforms/android を指定して開きます。

![スクリーンショット 2020-09-30 14.06.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/3a196d55-a9d3-e598-2c26-efaa6bf70617.png)

AndroidStudioを使用した開発の詳細は割愛しますが、私の環境ではビルドの完了に、SDKバージョン28、Gradleのアップデートが必要でした。

![スクリーンショット 2020-09-30 14.53.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751319/7ff844c1-0df7-8f47-e25f-9226791ae2de.png)

# 最後に

詳細はMendixドキュメントを参照してください。
[自分用]ECモールcsv編集

ECモールcsv編集

winならcassava、Macはエクセルとかで開く
作業するシートと保存するシートは分けた方が無難



A1セルに 「アロマキャンドル」が入ってるとする


###■文字列追加

`="SALE! " & $A1`

英字だけ固定

結果：
`SALE! アロマキャンドル`

###■文字列削除


「SALE !」を削除する場合

`=SUBSTITUTE(文字列,検索文字列,置換文字列,対象)`

対象は省力可

`=SUBSTITUTE($A1,"SALE! ","")`

結果：
`アロマキャンドル`


###■長い文字を追加し改行を含めたい場合


`=$A1 & CHAR（キャラクター） & "【もうすぐ在庫が０になります！】"`


結果：
`アロマキャンドル`
`【もうすぐ在庫が０になります！】`



###余談

csvアップするとき、商品IDの列さえ残ってれば他価格とか入れなくてもアップロードできる、と思う。
yahooは＋商品名も必要だったような・・・？
【Rails】Ruby On Railsでのgem管理方法

#1: gemインストールの流れ（詳細は2項目以降を参照）
Gemfileにインストールしたいgemを記述。
bundle installを実行。

```
$ bundle install
```
以上でインストール完了。


#2: インストールに必要なもの

##bundler
gem間の依存関係とバージョン管理を行うツール。

###インストール方法
```tarminal
＄ gem install bundler
```

念のため、インストールが成功しているかバージョン確認を行います。

```
$ bundle -v
```

##Gemfile
インストールするgemを記述するファイル。
インストールしたいgemを列挙します。

```Gemfile
source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.7'  //これがgemに関する記述
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.7'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
```

###Gemのインストール
以下のコマンドで、Gemfileに記述したgemをインストール・アップデートします。

```
$ bundler update
```

##gemバージョンの書き方
Gemfileには、インストールしたいgemを列挙しますが、以下の記述でバージョンの指定等ができます。

###バージョンの指定

```
gem "rails6" //rails6バージョンを指定
gem 'rails6’, '2.*.*' //rails6のさらに細かなバージョンを指定(*)には数字が入る
gem 'rails6’, '>=2.*.*' //rails6の特定のバージョン以上を指定(*)には数字が入る
gem 'rails6’, '~>2.*.*' //rails6の目ざーアップデートを規制(*)には数字が入る
```

##gemfile.lockとは
```bundler install```でgemをインストールすると、```gemfile.lock```というファイルが生成されます。
インストールしたgemのバージョンを記載して保存します。
これにより、環境差でのgemバージョン違いによるエラーの発生を防ぐことができます。
CodeWarでの勉強（ruby）⑥　inject


##この記事について
最近始めたCodewarを通じて学べたことを少しずつアウトプット


##問題
>If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Finish the solution so that it returns the sum of all the multiples of 3 or 5 below the number passed in.
Note: If the number is a multiple of both 3 and 5, only count it once. Also, if a number is negative, return 0(for languages that do have them)


１０未満の数字の内で3と5の倍数の数字を合計して、その値を返すメソッドを作成する。
注意点が数が3と5の両方の倍数である場合（15の倍数）は、１回だけ数えるようにする。


###僕の回答
ほぼほぼFizzBuzzの回答やね。
https://qiita.com/Fendo181/items/425293e8e638d7fd7cea

```ruby
def solution(number)
 i = 1
 nums_array = []
 number -= 1
 number.times do
   nums_array << i
   i += 1
 end
  
 sum = 0
 nums_array.each do |num|
   if num % 3 == 0 && num % 5 == 0
     sum += num
   elsif num % 3 == 0
     sum += num
   elsif num % 5 == 0
     sum += num
   end
 end
 sum
end
```


###ベストプラクティス

「なるほど〜」と「なにこれ？」が混在している。

```ruby
def solution(number)
  (1...number).select {|i| i%3==0 || i%5==0}.inject(:+)
end
```


###なるほど〜
####**`(1...number)`**
問題文にある通り、**10未満の数字**で該当の倍数を探して行くんだから、最後の数字は含まない`1...10`という風にしてあげている。ちなみに最後の数字も含みたい場合は`1..10`とコンマの数を2つにする。

####**`select {|i| i%3==0 || i%5==0}`**
selectで各要素をブロックで評価して、３の倍数もしくは５の倍数である要素を抽出している。
これだけ15の倍数で合っても２回カウントされることはない。


###なにこれ？

####`inject(:+)`
injectはeachやmapと同じように繰り返しを行うメソッドとのこと。つまり、３の倍数もしくは５の倍数である要素を抽出した結果を順番に足し算をする処理しようとしている。よく使われるのは繰り返し計算を行うことみたい。

#####基本的な使い方
https://blog.toshimaru.net/ruby-inject/

```ruby
配列オブジェクト.inject {|初期値, 要素| ブロック処理 }

array = 1..6
array.inject (0){ |sum,num| p sum+=num}

=>1
3
6
10
15
21

#inject(0)の0はsumの初期値を設定。
#ただ、injectのデフォルト引数設定は0なので下記のように省略することが可能
#numはarrayの要素
```

####今回の`inject(:+)`は何者？

シンボルで演算子を渡してやると以下のように省略して書くことができる便利なやつ。

```ruby
array = 1..10
array.inject　{|sum,num|  sum+=num}

=> 55

#省略して書いても同じ結果
array = 1..10
array.inject(:+)

=> 55
```

###まとめ
これまでは`eachメソッド`を使用してそのブロック内で計算しようとしていたけど、今後繰り返し処理で計算するときはinjectメソッドを使用します！！！
ホットスペアとホットスワップの違い


## 勉強前イメージ

ホットスワップ？ホットスペア？
どっちも勝手に予備系のHDDに自動的に切り替わることじゃないの？

## 調査

### ホットスワップ

ホットスワップは、`ホットプラグ`、日本語では活線挿抜(かっせんそうばつ)とも言われている。
HDDや電源、ファン等をシステムが通電された状態(電源を入れた状態)のまま取り外して交換することが出来る

一般的に通電された状態(電源を入れた状態)の回路では、いきなり配線などを切り離すと故障することがある。
そのため、ホットスワップ対応のシステムは故障しないように対策がされている。

### ホットスペア

ホットスペアは、`ホットスタンバイ`とも言われている。
RAID構成内に予備のHDDを通電された状態で待機させておくこと。
HDDに障害が発生した場合に、自動で予備のHDDを使ってRAIDの再構築(リビルド)が行われる。

ホットスペアを利用するには、ホットスペアを対応しているRAIDコントローラーを利用し
利用可能な状態に設定する必要があります。

RAIDを利用し耐障害性を高めているシステムでは、ホットスペアの実装が多く見える。

### ホットスワップとホットスペアの区別

電源を入れたままHDD・電源・ファンの取り外し出来るのが `ホットスワップ`
RAID内に予備のHDDを待機させておくのが `ホットスペア`

RAIDで構成しているシステムで
1. HDD1台故障 → `ホットスペア` が使われる
2. 故障したHDDの修理 → `ホットスワップ` の機能でオンラインで交換できる

## 勉強後のイメージ

勉強前の↓のイメージは、ホットスペアのことを言っていました。
> どっちも勝手に予備系のHDDに自動的に切り替わることじゃないの？

オンラインでHDDの修理を出来るのは、ホットスワップのおかげ。

## 参考

- [RAIDの「ホットスワップ」と「ホットスペア」](https://note.cman.jp/server/raid/hs/)
- [RAIDの基礎知識](https://www.systemworks.co.jp/term_raid.php)
「もっとプログラム脳を鍛える数学パズル」_Q39 (code:Ruby) -> Rust

[「もっとプログラマ脳を鍛える数学パズル」](https://www.shoeisha.co.jp/book/detail/9784798153612)をRustで書き直すのは、ボケ防止にちょうど良いかもしれない、と思った。

# Q39:隣り合うと消えちゃうんです

中級問題。このくらいになると、解答コードが何やってるのかも考えないと、分からなくなる。

## Ruby

```ruby:q39_1.rb
N = 11

@memo = {[0,0,0] => 1}
def pair(unused, onetime, neighbor)
    if @memo[[unused, onetime, neighbor]]
        return @memo[[unused, onetime, neighbor]]
    end
    cnt = 0
    if unused > 0
        cnt += pair(unused - 1, onetime + neighbor, 1)
    end
    if onetime > 0
        cnt += onetime * pair(unused, onetime - 1 + neighbor, 0)
    end
    @memo[[unused, onetime, neighbor]] = cnt
end

puts pair(N, 0, 0)
```

## Rust

```rust:main.rs
use std::collections::HashMap;

fn main() {
    let number_of_colors = 11;
    let mut q39 = Q39::new();
    println!("{}", q39.pair(number_of_colors, 0, 0));
}

struct Q39 {
    memo: HashMap<(i64, i64, i64), i64>,
}

impl Q39 {
    pub fn new() -> Q39 {
        let mut new_instance = Q39 {
            memo: HashMap::new(),
        };
        new_instance.memo.insert((0, 0, 0), 1);
        return new_instance;
    }
    pub fn pair(&mut self, unused: i64, onetime: i64, neighbor: i64) -> i64 {
        match &self.memo.get(&(unused, onetime, neighbor)) {
            Some(v) => return **v,
            _ => {
                let mut count = 0;
                if unused > 0 {
                    count += &self.pair(unused - 1, onetime + neighbor, 1);
                }
                if onetime > 0 {
                    count += onetime * &self.pair(unused, onetime - 1 + neighbor, 0);
                }
                &self.memo.insert((unused, onetime, neighbor), count);
                return count;
            }
        }
    }
}

```

`(0,0,0) = 1`は、初期値なので`new()`で設定する。
TF-IDF特徴量

某案件で使ったので、まとめておきます。

文書群Dにおける単語tjの出てくる確率を
pj=(tjが出てくる文書数）/文書数N
とみなすと情報量は
-log(pj)     (a)

これは全てのDに出現したらp=1で 0になるし、めったに出ないと(1/1000とか）ならlog1000とデカくなる。
単語情報量ベクトルと呼ぶことにする。

idfはドキュメントiに単語jが何％出てきたかで重み付ける
tf_ij= ドキュメントiにおける単語jの出現頻度/ドキュメントiの単語数  (b)
仮に単語jが100%なら１。

tfidf_ijは 単語の情報量をbに従って分配したもので、
(this,is,iijima)
の情報量が
(0.2,0.2,10)=w
と計算できたとして、（iijimaはレアなので高くなる）
文書iの出現割合が
(0.3,0.5,0.2)=dp
だとしたら
tf_idf_ij=w_j*dp_j
となる
tfidf_ij = a*b
=-log(pj)*ドキュメントiにおける単語jの出現頻度/ドキュメントiの単語数 
のドキュメント数*単語数の行列となる。
◯を成分ごとの積（アダマール積）として
各文書の単語の出現割合を横にとった行列◯単語情報量横ベクトルを縦に積んだ行列
とも計算できる。
PostgreSQLで「could not connect to server」が出て接続できないときの対応

# 問題
PostgreSQLを接続する時に、下記のエラーが出て困ったため、対応を書いておきます。
>psql: could not connect to server: Connection refused Is the server running on host "localhost" and accepting TCP/IP connections on port 5432?

私の環境は下記の様になっています。

- Windows10 64bit
- PostgreSQL Ver.10.10

# 解決策
私の環境では、PostgreSQLを再起動すれば解決しました。
ただ、再起動の仕方が「スタートメニュー」->「コンピューターの管理」からPostgreSQLを再起動するやり方だと上手くいきませんでした。

コマンドプロンプトから再起動するやり方だと上手くいきました。
>pg_ctl restart -D "C:\Program Files\PostgreSQL\10\data"

上記のパスは、自身のインストールフォルダ、PostgreSQLのバージョンに合わせて変更してください。
コマンドプロンプトは、管理者として実行する必要があります。

下記のような実行結果例が返ってくると思います。
>サーバ停止処理の完了を待っています....完了
サーバは停止しました
サーバの起動完了を待っています....2019-11-27 02:23:00.130 JST [4728] LOG:  IPv6アドレス"::"、ポート5432で待ち受けています
2019-11-27 02:23:00.130 JST [4728] LOG:  IPv4アドレス"0.0.0.0"、ポート5432で待ち受けています
2019-11-27 02:23:00.149 JST [4728] LOG:  ログ出力をログ収集プロセスにリダイレクトしています
2019-11-27 02:23:00.149 JST [4728] ヒント:  ここからのログ出力はディレクトリ"log"に現れます。
完了
サーバ起動完了

どうやらPostgreSQLを正常に終了しないと、postmaster.pidが残ってしまい起動に失敗するようです。
私は再起動で解決しましたが、解決しない場合、postmaster.pidを削除してから再起動すると良いそうです。
`C:\Program Files\PostgreSQL\10\data\postmaster.pid`にあります。
上記のパスは、自身のインストールフォルダ、PostgreSQLのバージョンに合わせて変更してください。

他にも、下記の理由により同じエラーが生じることがあるそうです。

- ポート5432が空いていなかった
- postgresql.confの設定が足りず他のホストのアクセスを受け付けていなかった
- pg_hba.confの設定がされていなかった

対応方法は、[psql: could not connect to server: Connection refused Is the server running on host "hoge" and accepting TCP/IP connections on port 5432? · DQNEO日記](http://dqn.sakusakutto.jp/2013/03/psql_could_not_connect_to_server_connection_refused.html) が詳しいです。

# 参考文献
[PostgreSQL pg_ctlコマンドで起動、停止、起動確認する Windows - Sierエンジニアのブログ](https://khid.net/2019/11/postgresql-pg-ctl-command-start-stop-status-windows/)  
[PostgreSQLに接続できず困った - Qiita](https://qiita.com/waro_a2606/items/0b0957066241887530d4)
react-navigation v5でuseNavigationを楽にMockする

やり方としては本物の `import { NavigationContainer } from '@react-navigation/native'` などを使ってテスト対象をwrapする方法もあるが、それは幾つか記事があったので省略。リンクはこちら。

[Testing your react-navigation v5 hooks | by Daria Rucka | Medium](https://medium.com/@dariaruckaolszaska/testing-your-react-navigation-5-hooks-b8b8f745e5b6)
[react-navigation v5 の useNavigation を含んだ custom hooks のテスト - Qiita](https://qiita.com/Naturalclar/items/07f99e5137738f7c60b1)

上の方法の場合、jest内で `component.root` を取得するとwrapperがrootになり、既存のテストを書き直す感じになってしまい面倒な感じになってしまった。

単にuseNavigationをmockする方法を取った所、割と楽だったので共有します。

## 基本的なやりかた

```js

const mockNavigate = jest.fn()

jest.mock('@react-navigation/native', () => {
  return {
    ...jest.requireActual('@react-navigation/native'),
    useNavigation: () => ({
      navigation: mockNavigate
    }),
  }
})

//... inside spec

expect(mockNavigate).toBeCalled() // などなど
```

個別のテストファイルでこれらを毎回記述するのも面倒なので、`jest-setup` に記述した。

## jestのglobalに入れるやりかた

package.json

```json
  "jest": {
    ...
    "setupFiles": [
      "<rootDir>/jest-setup.js"
    ],
    "setupFilesAfterEnv": [
      "<rootDir>/jest-env-setup.js"
    ],
    ...
```

jest-setup.js

```js
const mockedNavigation = {
  navigate: jest.fn(),
  goBack: jest.fn(),
  push: jest.fn(),
  addListener: jest.fn(),
}

global.mockedNavigation = mockedNavigation

jest.mock('@react-navigation/native', () => {
  return {
    ...jest.requireActual('@react-navigation/native'),
    useNavigation: () => ({
      ...mockedNavigation
    }),
  }
})
```

jest-env-setup.js

```js
beforeEach(()=>{
  Object.keys(global.mockedNavigation).forEach(key => {
    global.mockedNavigation[key].mockClear()
  })
})
```

このセットアップをしておくと、テスト実行時には `expect(mockedNavigation.push).toBeCalled()`とか出来て楽です。

参考：[jestjs - How to mock useNavigation hook in react-navigation 5.0 for jest test? - Stack Overflow](https://stackoverflow.com/questions/61781274/how-to-mock-usenavigation-hook-in-react-navigation-5-0-for-jest-test)
IBM Cloud Security and Compliance Center(SCC)のcollectorがinactiveになった時の対処方法

#問題

SCCのcollectorをしばらく放置していたら、ステータスがinactiveになってしまっていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/29edb864-185d-01cc-dc9a-53585dcf88b1.png)


#解決方法
[Docsに記載](https://cloud.ibm.com/docs/security-compliance?topic=security-compliance-gettinghelp#collector-inactive)されていた。collectorがSCCと通信できなくなるとInActiveになってしまうらしい。dockerを再起動すれば解決するようだ。

```
[root@collector ~]# docker ps
CONTAINER ID        IMAGE                                                   COMMAND                  CREATED             STATUS              PORTS               NAMES
03c01c384276        icr.io/posture-management/compliance-collector:0.0.1    "sh -c '/usr/local/b…"   12 days ago         Up 12 days                              ASAP-syasudacollector4
37d527bcf39a        icr.io/posture-management/compliance-watchtower:0.0.1   "/watchtower --clean…"   12 days ago         Up 12 days                              watch-collectors


[root@collector ~]# systemctl restart docker


[root@collector ~]# docker ps
CONTAINER ID        IMAGE                                                   COMMAND                  CREATED             STATUS              PORTS               NAMES
03c01c384276        icr.io/posture-management/compliance-collector:0.0.1    "sh -c '/usr/local/b…"   12 days ago         Up 23 seconds                           ASAP-syasudacollector4
37d527bcf39a        icr.io/posture-management/compliance-watchtower:0.0.1   "/watchtower --clean…"   12 days ago         Up 23 seconds                           watch-collectors
```

StatusがActiveに戻った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/66a03a2f-144e-7fca-ee8f-f6ccb1bc0bd0.png)
WSL2でsystemdを使えるようにした話

## Genieを用いた方法
### (古いため、下記にある公式対応のSystemdの話へどうぞ)
筆者環境: WSL2上のUbuntu-20.04 LTS (Windows 10 Home)

WSLを利用していたら、たまに見かけるこのエラー
```System has not been booted with systemd as init system (PID 1)```

どうも、原因はWSLでsystemdが使えないからみたいですね。
じゃあ、使えるようにしましょう。

先人の知恵は素晴らしいもので、Genieというリポジトリでsystemdを使えるようにできます。
https://github.com/arkane-systems/genie

コマンドの流れです

``` bash
$ sudo apt install daemonize
$ sudo apt-get install -y gpg
$ wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o microsoft.asc.gpg
$ sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
$ wget https://packages.microsoft.com/config/ubuntu/20.04/prod.list
$ sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
$ sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
$ sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
$ sudo apt-get update; \
  > sudo apt-get install -y apt-transport-https && \
  > sudo apt-get update && \
  > sudo apt-get install -y dotnet-sdk-3.1
```
genieをセットアップするために必要なdotnetのSDKをインストールしました。

次に、genie本体をインストールします。

``` bash
$ curl -s https://packagecloud.io/install/repositories/arkane-systems/wsl-translinux/script.deb.sh | sudo bash
$ mkdir /etc/apt/sources.list.d
$ touch /etc/apt/sources.list.d/wsl-translinux.list
$ sudo vim /etc/apt/sources.list.d/wsl-translinux.list
```
vimで```deb [trusted=yes] https://wsl-translinux.arkane-systems.net/apt/ /```を追記しておきましょう。
追記を忘れるとアップデート時に```429 Too Many Requests```が発生します。

```bash
$ sudo apt install -y systemd-genie
```
インストールが無事に終わったら

```bash
$ genie -s
```
で実行しましょう。
アップデート時にエラーが出るのが気持ち悪いという方は```sudo rm -rf /etc/apt/sources.list.d/wsl-translinux.list```で解決できます。

最後に.bashrcか.bash_profileに

```bash
if [ "`ps -eo pid,cmd | grep systemd | grep -v grep | sort -n -k 1 | awk 'NR==1 { print $1 }'`" != "1" ]; then
  genie -s
fi
```
を書き込んでおけば、シェル起動時にgenieも起動してくれます。

```bash
ps aux
```
で```systemd+```のプロセスが動いていれば大丈夫です。

お疲れ様でした。

## WSL公式がSystemdをサポートしました (2021年9月更新)

記事を書いて2年ほど経ったある日、こんな記事が出てきました。

https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/

...自分がやった方法必要なくなったのでは？ということで、更新をかけておきます。

公式対応のSystemdを用いるためには、まずバージョン確認が必要です。

```
wsl --version
```

バージョンが 0.67.6 以上であれば、利用可能になっています。
Windows Insiderの対象ならすぐに使えますが、しばらく待てば全ての人が使えるようになるはずです...

バージョンに問題がなさそうであれば、wsl.confファイルに設定を追加します

```
# 公式ドキュメントでは nano を使っていますが、nanoは宗教上ちょっと...
sudo vim /etc/wsl.conf
```

追加する内容は下記の通りです。
```
[boot]
systemd=true
```

設定を追加した後はPowerShell等で `wsl.exe --shutdown` を実行し、WSLを再起動します。

その後、WSLで`systemctl list-unit-files --type=service` を実行し、Systemd が動いているのが確認できれば終了です。

お疲れさまでした。
Rubyを使うための rbenvのコマンド


前回の記事でrbenvについて細かく書きたいので
少し内容を引き継いで書きます。

# brewのインストールなど
rbenvを使う前提としてbrewのインストールかアップデートをしてください
インストールはこちらの[公式ベージから](https://brew.sh/index_ja)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754121/2f4a4d08-d0b5-2128-d7aa-b7d56c2d183b.png)

下の方にあるインストール下のコマンドを
ターミナルで打ち込みます。

すでにインストール済みなら
こちらのコマンドで更新とアップグレードしてください

```bash
brew update && brew upgrade
```

# rbenvコマンド

```bash
rbenv versions
# rubyのバージョン確認

rbenv install -l
# インストールできるrubyバージョン一覧
# なおbrewの更新で一覧は変わります。

rbenv install 2.6.6
# 仮に2.6.6をインストーしたい時はこれ

rbenv local 2.1.5
# 使うバージョンの変更(カレントディレクトリで使うバージョン)、これ重要

rbenv rehash
# 更新

rbenv global バージョン
# デフォルトで利用するバージョンを指定

```
railsのエラーLibrary not loaded　

久々に使おうしたらエラーが頻発したので
記録を投稿します。

# エラー内容

```bash
rails --version
```
上記のコマンドでバージョン確認したら
下記のようなエラーがでできました。

```
Library not loaded: /usr/local/opt ~
```

# エラーへの対応

色々調べた結果
下記のコマンドを試して見ました

```bash
brew update && brew upgrade

brew reinstall openssl
```

解決せずrubyのバージョンを変えることを試して見ました。

```bash
rbenv versions
# rubyのバージョン確認

rbenv install -l
# インストールできるrubyバージョン一覧
# なおbrewの更新で一覧は変わります。

rbenv install 2.6.6
# 仮に2.6.6をインストーしたい時はこれ

rbenv local 2.1.5
# 使うバージョンの変更、これ重要
```

とりあえずこれでエラーは解決しました。
以前brewの更新したのが原因のようでした。
合計行を含んだHTMLテーブルをソートする

# はじめに

・以前、JavaScriptで、DBにためている自分のQiitaのデータ（QiitaAPIにて取得）を「2軸グラフ」と「テーブル」に表示してみる、というを実施しました。（Qiita：[Chart.jsを使用して複数軸のグラフを表示する(Javascript)](https://qiita.com/yoshi_yast/items/f4557cb48a13f198d42a)）

・記事やデータもたまってきましたので、そこで作成していたテーブルをソートできるような機能をつけたいと思いました。

# 作成サイト
[作成サイトはこちら](https://anotherskyjp.site/devapps/otherpg/03_qiita_graph/js_qiita_data_get_graph.html)

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/c0a4f5cd-825c-0d1c-429d-bd5b4a05841b.png)

「Views」でソートした画面

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/ed69aec9-ec40-9776-ebf4-11e60f6b4941.png)

# ポイント

### ①Sorttableの使い方

基本は、以下のサイトを参考にさせていただきました。感謝。

https://qiita.com/riversun/items/8c59353af4f16264aedd


### ②テーブルデータの中に、HTMLタグも書ける

・テーブルデータにLINK設定などをしたいときは、どうするのか？と思っていたのですが、htmlのタグを書けばできることがわかりました。

~~~sample.js
  //データ設定箇所
  var outdata = [];
  for(var i = 0; i < qiitadata.length; i++){

  // 本日日付になったら、格納処理
  if(qiitadata[i].setdate == hyphendate){

    var data = {
      no: (maxno + 1 - Number(qiitadata[i].no)),
      // タグも書ける
      title: '<a href="' + qiitadata[i].url + '" target="_blank">' + qiitadata[i].title + '</a>',
      views: Number(qiitadata[i].views),
      likes: Number(qiitadata[i].likes),
      stocks: Number(qiitadata[i].stocks),
      plike: Number(qiitadata[i].per_like),
      pstock: Number(qiitadata[i].per_stock),
    };

    outdata.push(data);

    // 合計の計算（カウントアップ）
    sum_view += Number(qiitadata[i].views);
    sum_like += Number(qiitadata[i].likes);
    sum_stock += Number(qiitadata[i].stocks);
  };
};
~~~


### ③合計行を含んだHTMLテーブルをソートするには

・テーブルに合計行がある場合は、合計行も一緒にソートされては具合が悪いです。どうすればいいのかよくわかりませんでしたが、いろいろ調べて試した結果、`<tfoot></tfoot>`の中にデータを出せば、合計行はソートされないことがわかりました。

~~~sample.html
      <div class="container">
        <!-- テーブルヘッダ部分 -->
        <div id="result1"></div>
        <!-- テーブル部分 -->
        <div class="table sortable-table">
          <table id="outTable">
            <thead class="thead-light">
              <tr>
                <th scope="col" data-id="no">No</th>
                <th scope="col" data-id="title">タイトル</th>
                <th scope="col" data-id="views" sortable>VIEWS</th>
                <th scope="col" data-id="likes" sortable>LIKES</th>
                <th scope="col" data-id="stocks" sortable>STOCKS</th>
                <th scope="col" data-id="plike" sortable>LIKE率</th>
                <th scope="col" data-id="pstock" sortable>STOCK率</th>
              </tr>
            </thead>
            <!-- 合計行部分 -->
            <tfoot id="result2"></tfoot>
          </table>
        </div>
      </div>
~~~

# まとめ
- HTMLのテーブルでソートを簡単に実施することができました。
- 合計行もソートに含めないやり方にモヤモヤしていたのですが簡単にできることがわかったのが、一番の発見でした。
AWS CLIでのドメイン移管について

# 初めに
Route53で管理しているドメインをAWS CLIで別AWSアカウントへ移管が出来るようになっていた(以前はサポート経由限定だったはず)ので、AWS CLIで別アカウントに移管しようとしたところ、`Could not connect to the endpoint URL: "https://route53domains.ap-northeast-1.amazonaws.com/"`というエラーで詰まったので、その解決方法です。

# 注意点
- AWS CLIでドメイン移管する場合、**AWS CLI v2 2.0.9以上**で実施してください(バージョンが低いとtransfer-domain-toanother-aws-accoutオプションが未実装なため)
    - [AWS CLI V2 インストール方法](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html)
- 適切な権限が付与してあるIAMユーザーで操作してください(私はAdministrator権限が付与してあるIAMユーザーで操作しました)
- AWS CLIの基本設定(aws cofigure)は済んでいる前提です。
    - [AWS CLI 基本設定方法(公式ドキュメント)](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html)

# エラー解決方法
`--region=us-east-1`を付与しましょう。

コマンド例

```sh
$ aws route53domains transfer-domain-to-another-aws-account --domain-name `移管ドメイン` --account-id `移管先AWSアカウントID` --region=us-east-1
```

### エラー時リクエスト/レスポンス

```sh
$ aws route53domains transfer-domain-to-another-aws-account --domain-name `移管ドメイン` --account-id `移管先AWSアカウントID`
Could not connect to the endpoint URL: "https://route53domains.ap-northeast-1.amazonaws.com/"
```

### 成功時リクエスト/レスポンス
`--region=us-east-1`を付与した場合

```sh
$ aws route53domains transfer-domain-to-another-aws-account --domain-name `移管ドメイン` --account-id `移管先AWSアカウントID` --region=us-east-1
{
    "OperationId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Password": "xxxxxxxxxxxxxxxxxxxx"
}
```


# 参考

### 移管先アカウントでの承認リクエスト/レスポンス

```sh
$ aws route53domains accept-domain-transfer-from-another-aws-account --domain-name `移管ドメイン` --password '`移管元で出力されたパスワード`' --region=us-east-1
{
    "OperationId": "xxxxxxx"
}
```

### なぜエラーになったのか？

nslookupで`route53domains.ap-northeast-1.amazonaws.com`の名前解決をしようとしたところ、解決できなかったので、ap-northeast-1には上記のエンドポイントが無いと思われます(2020/10/1時点)

#### ap-northeast-1のエンドポイント名前解決
```sh
$ nslookup route53domains.ap-northeast-1.amazonaws.com
*** dns.google が route53domains.ap-northeast-1.amazonaws.com を見つけられません: Non-existent domain
サーバー:  dns.google
Address:  8.8.8.8
```

#### us-east-1のエンドポイント名前解決
```sh
$ nslookup route53domains.us-east-1.amazonaws.com
権限のない回答:
サーバー:  speedwifi-next.home
Address:  fe80::8abf:e4ff:feb1:5c0e

名前:    route53domains.us-east-1.amazonaws.com
Address:  54.239.29.152
```

# 参考ドキュメント
[AWS公式 ドメイン移管方法](https://aws.amazon.com/jp/premiumsupport/knowledge-center/route-53-transfer-domain-other-account/)
[AWS CLI transfer-domain-to-another-aws-account](https://docs.aws.amazon.com/cli/latest/reference/route53domains/transfer-domain-to-another-aws-account.html)
[AWS CLI accept-domain-transfer-from-another-aws-account](https://docs.aws.amazon.com/cli/latest/reference/route53domains/accept-domain-transfer-from-another-aws-account.html)
プロファイルに設定しているIPアドレスの設定をレポートする方法

はやり、普通にレポートではできないようです。
 Workbenchを使ってメタ情報を抜くとのことです。

**質問**
Report on all profiles with or with out IP restrictions
https://trailblazers.salesforce.com/answers?id=9064S000000DBmk
IP 制限がある、またはないすべてのプロファイルを特定する必要があります。これは、ワークベンチまたはその他のツールを介して可能ですか?

**回答**
https://salesforce.stackexchange.com/questions/271311/reporting-on-profile-and-login-ip-range

その種のデータは、通常のレポートではアクセスできません。ただし、それらすべてを簡単に表示する方法が必要な場合は、次の package.xml を Workbench またはその他のツールで使用できます (これにより、組織からすべてのプロファイルがエクスポートされます)。

```
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>Profile</name>
    </types>
    <version>46.0</version>
</Package>
```

次に、返された結果ファイルをメモ帳またはその他のテキスト エディター (プロファイルごとに 1 つのファイル) で表示すると、プロファイルにログイン IP 範囲がある場合、ファイルの上部に次の形式で表示されます。

```
<loginIpRanges>
    <endAddress>255.255.255.255</endAddress>
    <startAddress>0.0.0.0</startAddress>
</loginIpRanges>
```
nuxtのローカル環境構築メモ

個人的メモ

## 前提条件
yarnを使用する。


#### セットアップ
```
$ yarn create nuxt-app アプリケーション名
```


#### 設定
1. Project name -> **任意の名前**
2. Programming language -> **javascript or TypeScriptを選択**
3. Package manager -> **Yarn or Npmを選択**
4. UI framework -> **Elementやvuetify.jsなど複数あるのでお好みまたはNoneを選択**
5. Nuxt.js modules -> **Axios,Progressive Web App (PWA),Contentなどを選択、何も選択しない場合はEnterで進む**
6. Linting tools -> **ESLint,Prettier,StyleLintを選択する。**
7. Testing framework -> **何も選択しない場合はNone**
8. Rendering mode -> **SSRかSPAを選択する。(SPAは実装が簡単)**
9. Deployment target -> **Serverか、Staticを選択**
10. Development tools ->**jsconfig.json を設定しておくと、VS Codeで開発する際に正しくシンタックスエラーやハイライトが出るようになります。Semantic Pull Requests はGitのcommitメッセージとPull Requestにおけるタイトルの付け方をチェックしてくれます。**
11. 


#### アプリを起動する
```
$ cd hoge
$ yarn dev
```

アプリが立ち上がったらlocalhost:3000にアクセスする。

#### SCSSを使用できるようにする。
```
$ yarn add -D node-sass sass-loader
nuxtプロジェクトで、インストールしたPrettier,eslintの使用方法


個人的なメモ


#### eslintによるコードの整形はデフォルトでは使用できないので、package.jsonのscripts{}の中に一行追加する。
```js
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "lint:style": "stylelint **/*.{vue,css} --ignore-path .gitignore",
    "lint": "yarn lint:js && yarn lint:style",
    // ここに一行追加
    "lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
  },
```
  
これで、`yarn lintfix`で規約に反した全てのコードを整形してくれる。
TWELITE に時間のかかる処理を記述

「電子ペーパーを TWELITE に接続する」
https://qiita.com/nanbuwks/items/be4f8125b686079e74d6
において、チェッカーを表示させました。

これは cbAppColdStart 内に記述し、起動時1度のみ描画処理を行いました。

今回は、任意のタイミングで描画してみます。

# ePaper のタイミング

ePaper の描画は秒単位で時間がかかります。先のコードは描画が終わるまで処理が帰ってこないように作っているため、そのまま使うとタイミング的な問題が発生しそうです。


# TWELITEの作法

「TWENET 動作フロー」
https://sdk.twelite.info/tweliet-net-api-jie-shuo/twenet-fur

によると、


- cbAppColdStart

以外のハンドラとして、

- cbAppWarmStart
- cbToCoNet_vMain
- cbToCoNet_vRxEvent
- cbToCoNet_vTxEvent
- cbToCoNet_vNwkEvent
- cbToCoNet_vHwEvent
- cbToCoNet_u8HwInt

があります。このうち、

- cbAppWarmStart

はスリープ復帰時に呼び出されます。



- cbToCoNet_vRxEvent
- cbToCoNet_vTxEvent
- cbToCoNet_vNwkEvent
 
は無線通信時に呼び出されます。

- cbToCoNet_vHwEvent
- cbToCoNet_u8HwInt

はタイマーなどのハードウェア割り込みから呼び出されます。

- cbToCoNet_vMain

は cbToCoNet_vRxEvent や cbToCoNet_vHwEvent などの処理が終わった後に呼び出されます。


これらの呼び出しトリガはFIFOバッファに格納されているのである程度タイミングを乱すような処理をこれらに書いてもなんとかなりそうですが・・・

 「TWELIET NET API 解説」-「TWENET 動作フロー」-「メインループフロー」
 https://sdk.twelite.info/tweliet-net-api-jie-shuo/twenet-fur/meinrpufur

 において、
 「各コールバック関数で相対的に長い時間のかかる処理を行うと、他の処理が滞るため各処理は簡潔にとどめる。」
 とあります。

確かに上記の cbToCoNet_****Event のほとんどは割り込みハンドラなのですが、cbToCoNet_vHwEvent だけについては
>  ペリフェラルの割り込み処理の遅延実行部。割り込み処理後に呼び出されます

とあり、ここには時間のかかる処理を置いても大丈夫ぽいです。

cf., https://sdk.twelite.info/twelite-net-api-rifurensu/krubakku


同様に、 cbToCoNet_vMain も時間のかかる処理を置けるかな？ と思いましたが、
「電子ペーパーを TWELITE に接続する」
https://qiita.com/nanbuwks/items/be4f8125b686079e74d6
のコードに  cbToCoNet_vMain に処理を書いても実行して無さそうでした。

ということで今回は  cbToCoNet_vHwEvent 内に処理を置いてみました。

なお、上記以外の方法についてもあるようだが未検証。
cf.,ToCoNet SDK マニュアル
https://mono-wireless.com/download/SDK/TWESDK_201404/ToCoNet_SDK_manual_20140404.pdf
95ページ 「システム組込イベント」
> cbToCoNet_vRxEvent()

# 実行内容

1分ごとに e-Paper の描画を変更します。

 cbToCoNet_vHwEvent
は何種類かのトリガにより呼び出されますが、

```

	case E_AHI_DEVICE_TIMER0:
```

において、タイマーでの定期呼び出しによる処理を書くことができます。
この定期呼び出しは 64回 / 秒 の呼び出しとなっているようです。

グローバル変数 epaperstatus : 
- 2 未処理
- 1 処理中
- 0 処理完了

グローバル変数 epaperremaincount : 
- カウントダウンを秒数で格納

として、残り時間を分単位で表示するようにしました。

```

// epaper処理
static int epapertimer0count=0;
epapertimer0count++;
if ( 0 != epaperremaincount &&  2 == epaperstatus ){
		epaperstatus=1;
		ePaperDispMin((epaperremaincount +59 )/ 60 );
		epaperstatus=0;
}
if (0 == ( epapertimer0count % 64 ) ){  // 1秒おき
	epaperremaincount--;
	if (  0 == epaperremaincount % 60 ){ // 1分おき
		if (( 0 <= epaperremaincount ) && (0 == epaperstatus)) { // カウントが0以上でなおかつ処理中でなければ
			epaperstatus=1;
			// ePaper書き込み
			ePaperInit();
			ePaperDispMin((epaperremaincount +59) / 60 );
			epaperstatus=0;
		}
	}
} 
```

うまくいきました。

![IMG_20200930_141303405 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/390a6049-84b5-7648-c78f-98481b00c72d.jpeg)
マイクロフレームワークを使った設計案（プログラマー視点からユーザー視点へ）

# 1. webのマイクロフレームワーク採用と設計の課題

　最近は、10年前とは異なり、フロントはJavascript/Typescriptで開発して、サーバサイドはAPIに特化することが増えてきました。

　画面（ビュー）を作らないので、PythonのFlask、PHPのSlimなど有名なマイクロフレームワークでも十分対応できると思います。
　特に、Flask、Slimのルーティング処理は、GoやRustの有名なWebフレームワークでも同じような設計がされています。
（METHODに応じて、関数を割り当てていくスタイル）

　では、マイクロフレームワークでAPIを作ってみようとすると、「アーキテクチャ（構造）設計」という問題が出てきます。
　RailsやLaravelのようなフルスタックは、MVCを含め、ある程度アーキテクチャは設計されていて、そこに従ってモジュールを配置していきます。

　ただ、マイクロフレームワークはそのあたりの縛りがないので、よく言えば「自由に」、悪く言えば「無秩序に」モジュールを配置できます。

　ある程度、設計に慣れている人ならフルスタックフレームワークに則ったり、プロジェクトに合わせた設計ができるかもしれないですが、なれていないと色々悩みがあります。

　悩むぐらいならフルスタックでいいのではという意見も意味があると思います。
　とはいえ、マイクロフレームワークで設計する簡単な指針をメモ程度に記載します。

# 2. 有名な手法を踏襲しつつ、無駄を省く

　設計をするときプログラマーが直感的に読めるものが望ましいと思います。
　直感的といっても、ある程度、「専門家」であることを前提としていますので、プログラマーとしての「知見」を期待したものでよいと思います。
　
　MVC、ドメイン駆動、コンポーネント指向、RESTful、テスト駆動、アスペクト指向、DI（依存性注入）、クリーンアーキテクチャ、などなどそれらの要素を踏まえつつ、それでいながら、マイクロフレームワークなのでできるだけライトにモジュールのレイアウトをしたいと思います。


# 3. 階層を分ける

　モジュールの階層（ディレクトリ・パッケージ）を以下の4つに分けます。その際に、プログラマー視点（内部設計）とユーザー視点（外部設計）を意識するのがよいと思います。


## (1) 汎用ライブラリ

　プロジェクトに特化しない、プログラム一般における便利ツール。文字列、日付、配列の操作など。
プロジェクトをまたいで利用できるぐらいの粒度で作成する。

## (2) ミドルウェア

　ユーザー視点ではなく、プログラマー視点でプロジェクトに特化した汎用ライブラリを組み合わせたモジュールを配置。
　たとえば、認証処理、ファイルやDB周りでプロジェクトでよく行う処理。
　プロジェクト固有の設定情報などを絡めてもよい。

## (3) ドメイン

　ユーザー視点でパッケージ分けをしていく。
　RESTfulの視点であれば、テーブル名と同じようなユーザーが分かる名称でパッケージ名を付けていく。
　マスタ情報やプロジェクト固有の定義情報などもここに配置。
　Railsでいえば、Modelの情報がここに配置される。

## (4) UI（ユーザーインターフェース）：実行起点

　ここは、ユーザーが利用するインターフェースに応じてパッケージを分けるといいと思います。
　たとえば、API、CLIなど。
　Controller的な振る舞いをします。入力を受けて、ドメインの処理を呼び出す。
　ここに具体的な処理実装は記載しません、ドメインの処理を呼び出すだけ。

# 4. パッケージ、ソースファイルを細かく分ける

## パッケージ名は処理対象・関心事にする

　よく「FatClass」、クラスの肥大化ということがいわれ、一つのソースにいろいろな処理を詰め込み、可読性の低下、機能の共通化の阻害、修正の困難化を招くことがあります。

　また、「-Utils」、「-Helpers」などと一つのソース・クラスに処理を詰め込み、上記の問題を引き起こすことがあります。

　まず、オブジェクト指向に従い、処理する対象や関心・テーマでパッケージから順番に細かく分けていくのがよいと思います。

　たとえば、汎用ライブラリに配置する「文字列」の処理であれば、「StringUtils」というクラスファイルをつくるのではなく、「string」というパッケージ名をつくる。
　そして、各処理ごとにクラス名を分けた方が読みやすくなります。

```sh:package

util -
      | 
       - string
               |
                - splitter.xx
                - checker.xx
                - editor.xx
````

汎用ライブラリのパッケージ分けは、言語の標準ライブラリを参考にして分ければいいと思います。

## ドメインやUIでは処理対象・関心事はユーザー視点のものを上位に置く

　処理対象・関心事をパッケージ名にするにしても、立場・視点によってその上下の位置が変わります。

　汎用ライブラリやミドルウェアでは、プログラマー視点の関心事を上位に持ってきます。
　一方、ドメインやUIにおいては、ユーザーの関心事を上位に持ってきます。

```sh:layout

# 汎用・ミドル

db - selector.xx

# ドメイン・UI

product - selector.xx
product - db - selector.xx 
        - csv - selector.xx

```

# さいごに

　以上、マイクロフレームワークを使う際の簡単なアーキテクチャ、モジュールわけです。
　その他色々技巧的なことをしたいのであれば、素直にフルスタックのフレームワークを使えばよい気がします。
　
　とはいえ、ある程度のモジュール分けをしておかないと、処理の共通化、修正が大変になってきます。

　その参考になればと思います。

# 備考：内部設計と外部設計

　プログラムをしていると内部設計（詳細設計）と外部設計（基本設計）をすると思います。
　内部設計はプログラマー視点の設計。
　外部設計はユーザー視点の設計。
　
　本投稿で扱ったドメインやUI部分は外部設計に即して設計することになると思います。
　そして、外部設計はプロジェクト固有なもののため省くこともできません。
　外部設計はとても大切な過程になります。

　一方、内部設計は広範囲で多岐にわたったり、OSSなど外部のライブラリを使うことになります。
　外部のライブラリを使うとすれば、ここはある程度省くことができます。外部ライブラリのリファレンスが設計書の一部になるでしょう。
　
　設計作業を行う上で大切なのは、外部設計で、内部設計はできるだけ外部のライブラリをつかったり、汎用的にしてドキュメントもプロジェクトで共有するのがよいと思います。
NavMesh の AgentTypeID が直観的じゃない件について

Unity で利用できる NavMesh では、異なるパラメータを持つ Agent を作成できます。Inspector で AgentType が選択できるときは、分かりやすい名前で表示されるのですが、スクリプト内では AgentType は名前では指定できず、その代わりに AgentTypeID を利用する必要があります。この AgentTypeID が少しトリッキーで躓いたので、その腹いせに記事を書きます。

# 問題点
ことは NavMesh の公式拡張である [NavMeshComponents](https://github.com/Unity-Technologies/NavMeshComponents) のサンプルを触っていたときに起こりました。
`Examples/Scenes/5_sliding_window_terrain` というシーンは、 `NavMeshBuilder` クラスを使うことで Agent の周囲にランタイムに動的に NavMesh を作成できる例を示していたのですが、 AgentType が `Humanoid` の Agent しか存在しなかったので、ここに新しい AgentType を追加したらどうなるんだろうという気持ちになり、試してみることにしました。

AgentTypes は見た目的にすごく Enum 然としています。実際デフォルトで設定されている `Humanoid` という AgentType に対応する ID は `0` でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252487/f9f41b21-3136-76c4-c91b-c49745b9bfaf.png)

```Examples/Scripts/LocalNavMeshBuilder.cs
// 60行目
var defaultBuildSettings = NavMesh.GetSettingsByID(0);
```

なので、`Humanoid` の下にある `Ogre` に対応する ID は一つインクリメントされて `1` になるものだと思いますよね。そこで、上述のスクリプトの ID を `1` に書き換えて、シーン内の Agent を Orge に設定したのですが、 `Failed to create agent because it is not close enough to the NavMesh` という警告が出て正常に動作しませんでした。

調べてみた結果、どうやら `Ogre` に対応する NavMesh が正しく作成されていないことが分かり、 `Ogre` に対応する AgentTypeID が `1` じゃないのかも、と気づきました。

# 対応する AgentTypeID の取得方法
色々試してみたのですが、最終的に以下の方法で AgentType に対応する ID が分かります。辞書型に保存することで、AgentType の名前からいつでも ID が取得できるようにしました。
（回りくどい書き方になっているのはちょうどいい API がなかったからです）

```c#
Dictionary<string, int> agentTypeIdDict = new private Dictionary<string, int>(); 
for (var i = 0; i < NavMesh.GetSettingsCount(); i++)
{
    var id = NavMesh.GetSettingsByIndex(i).agentTypeID;
    var name = NavMesh.GetSettingsNameFromID(id);
    agentTypeIdDict.Add(name, id);
}
```
ここで取得できた ID を指定したところ、警告が消え、 `Ogre` Agent も正しく動作しました。

# 最後に
結果的に自分の環境では、 `Ogre` に対応する ID は `-1372625422` でした！全然予想と違いましたね！！！！！
【GAS】明日の予定をGoogle Calendarから取得し、LINEに自動で通知する

# あれ、今日ミーティング入ってた！！あぶねー！！

↑これ、ありませんか？

**実は私はちょいちょいあるんです。**

幸いなことに今まで予定すっぽかした、大幅に遅れた、ということはないのですが、別の作業に集中している時に、ふとスケジュール表見て、「やべ！！！」と思うことがあります。本当にヒヤヒヤもんです。

ついつい手中している仕事があると、スケジュール確認を忘れがちです。


ですが、**それを繰り返していると、いつかとんでもないミスをするような気がします。**氷山の一角ってやつですね。**ヒヤリハットで止まっているうちに再発防止策を打たなければなりません。**

そこで考え出した仕組みは、前日の夜に、手帳代わりに使っているgoogleカレンダーの翌日の予定をLINEに通知してくれる仕組みです。

# できました！

こんな感じで、夜に翌日のスケジュールが届きます！

![image35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664861/c38baea1-f773-7f0c-9bdf-dd16351c83a0.png)



# だけど、実は結構ハマりました

以下２つの記事を参考にさせていただきました。

[【GAS】Googleカレンダーの予定をLINEで受け取る](https://qiita.com/ikei/items/8c837444dcab6c0e4629)

[LINE Notify + GoogleAppsScript + Googleカレンダーで明日の予定を絶対忘れない](https://qiita.com/imajoriri/items/e211547438967827661f)

基本は上の２つの記事を参考にしていただければと思いますが、
わたしは、これらの記事遠りにやって、動かず。
特にエラーは出ないものの、LINEには通知してくれない。

色々調べてみたものの、わからず。。

なぜだ？？


# ポイントは、最初の「実行」のタイミング、かもしれない

明確に原因はわかっていないものの、おそらくこれかなと思っているものが、最初の「実行」のタイミング。

最初、別のことを試そうとしていて、その時に、必ず最初に聞かれる実行許可を求められました。その時に、以下のような画面が出てくるのですが、その時、**求められた許可が違った**ような気がします。

[![Image from Gyazo](https://i.gyazo.com/91745704e9638e19f1d4e48ede96cb8e.png)](https://gyazo.com/91745704e9638e19f1d4e48ede96cb8e)

つまり、許可がされていないことを、実行しようとして、うまくいかなかったんじゃないかと思っています。

しかし、新しいコードに書き換えても、特に許可を求める画面は出てこない。やり方はあるんでしょうが、私にとっては自動で出てくれないと対処できない。


なので、**新しいプロジェクトを作り直すところから始めたら、無事できました。**


# これでスケジュールを忘れない

通知を自動でしてくれれば、スケジュールを失念していた、ということはなくなるでしょう。これで一つ不安が減りました。
swift FAB可愛いアニメーション作った！

簡単にフローティングアクションボタンのアニメーションを作ってみました！

twitterにアニメーションの動画のしてます


SpringMotionとanimationで動かしてます。
コードの簡略化など助かる情報あれば教えてください🙏


```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
var  counter = 0
    @IBOutlet weak var TextView: UITextView!


    @IBOutlet weak var pencilButton: UIButton!
    
    @IBOutlet weak var eraserButton: UIButton!
    
    @IBOutlet weak var boldButton: UIButton!
    
    @IBAction func FAB(_ sender: UIButton) {
        sender.touched()
        
    counter = counter + 1

        
        //１回目押した時の処理
        if counter == 1{
            
        
        UIView.animate(withDuration: 0.4, animations: {self.pencilButton.frame.origin.x -= 100}, completion: nil)
          UIView.animate(withDuration: 0.4, animations: {self.eraserButton.frame.origin.x -= 200}, completion: nil)
        UIView.animate(withDuration: 0.4, animations: {self.boldButton.frame.origin.x -= 300}, completion: nil)    }
        else if counter == 2{
            UIView.animate(withDuration: 0.1, animations: {self.pencilButton.frame.origin.x += 100}, completion: nil)
              UIView.animate(withDuration: 0.1, animations: {self.eraserButton.frame.origin.x += 200}, completion: nil)
            UIView.animate(withDuration: 0.1, animations: {self.boldButton.frame.origin.x += 300}, completion: nil)
            
            counter = 0
        }
        
        
        
    }
    
    
    
    
    override func viewDidLoad() {
        
    
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


}
```
Buttonを何回押すかで違うアニメーション（出る、戻る）
を実装したかったのでtapCountをつけました。


FABのアニメーションはFileを作りメゾッドを呼び出すだけの形にしました。

位置にアニメーションを加えるメゾッドとは違い、
位置を変えずポップするだけのアニメーションなので他のボタンにも使える
なので呼び出すだけの形にした方が便利です。

```swift:file.swift
import Foundation
import UIKit

extension UIButton {
    
    func touched() {
    let touch = CASpringAnimation(keyPath: "transform.scale")
        //時間
        touch.duration = 0.5
        //元のサイズ
        touch.fromValue = 1.0
        //後のサイズ
        touch.toValue = 1.1
        //animationを一回繰り返す
        touch.autoreverses = true
        //そのアニメーションを何回繰り返すのか
        touch.repeatCount = 1
        
        touch.initialVelocity = 2.0
        
        
        touch.damping = 1.0
        
        layer.add(touch, forKey: nil)
        
    }
    
    
    
    
    
}
```


こうした方がいいよって提案あれば教えてください〜

それでは👋
Java/IntelliJ/Gradle で HelloWorld を行う

#環境
* Windows10
* Java8
* IntelliJ IDEA
* Gradle

#Project を作成する
File > New > Project で、Gradle/Java を選び、Next を押下します。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534222/628568c3-2ef3-70da-ab97-36c06a09a6d7.png)

Name に任意に入力します。(ef.SpringBootSample)
GroupId と ArtifactId を設定します。(今回はデフォルトです)
最後に Finish を押下すると Project が作成されます。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534222/93f7f9e2-5250-03d8-38d2-ac75e2bfac94.png)

#HelloWorld を行う
左側にある Project ペインのルートプロジェクトを右クリックし、
New > Directory より、src > main > java を選択し、Enter キーを押下するとフォルダが作成されます。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534222/b7b8de0c-7e5f-afa3-fdc4-d239333413cf.png)

作成した java フォルダを右クリックし、New > Packageより、
org.example と入力し、Enter キーを押下します。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534222/83b376a8-a5ed-c781-1d86-530cd285578b.png)

さらに、example フォルダを右クリックし、New > Classより、
Class が選択された状態で Main と入力し、Enter キーを押下します。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534222/194fb90f-2faa-4c92-b544-151fe2bc7715.png)

作成したクラスに以下を記載します。

```Main.java
package org.example;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
```

Main.main() を実行します。

```
4:33:31: Executing task 'Main.main()'...

> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes

> Task :Main.main()
Hello World
```

これで IntelliJ で Java コードが書けるようになりました。
ツイートのいいねをEvernoteに自動で保存できるようにした

# IFTTTを使えば自動化が簡単

IFTTT使えると本当に便利。
今回は、twitterのいいねを押した記事を、自動でEvernoteに保存されるようにしました。

用途としては、
**・単純にあとで見返したいtweetを保存する
・自分がどんなtweetにいいねを押すのか分析する**

そんなところかなと思います。

私の場合は、どちらかというと後者の目的で使うつもりです。

# こんな感じで保存されていきます

[![Image from Gyazo](https://i.gyazo.com/a98b0f09cc4ed11a01519059ad89d7f4.png)](https://gyazo.com/a98b0f09cc4ed11a01519059ad89d7f4)


# 設定の仕方は、とっても簡単です。

IFTTTの公式サイト右上のExploreより入り、

[![Image from Gyazo](https://i.gyazo.com/ea5d8b6892e6ac03fbefbe24770628e8.png)](https://gyazo.com/ea5d8b6892e6ac03fbefbe24770628e8)

この[Save your favorite tweeets in an Evernote notebook]を選択してください。

すると、いとも簡単に、Evernoteにfavoriteのノートブックができ、そこに自動で保存されていきます。


ぜひ使ってみてください。
iOS アプリがバックに移行するイベントをView側で取得

AppDelegateでアプリのフォアグランドやバックへの移動のコールバックを取得できます。
swiftuiなどのviewやViewController側でそのコールバックを取得するためには、NotificationCenterでオブザーバを設定しキャッチします。

didEnterBackgroundNotificationでバックへの移動のコールバックを取得できます
ここら辺の一覧はドキュメントを参考
https://developer.apple.com/documentation/uikit/uiapplication/1623071-didenterbackgroundnotification
その他のコールバックは「Responding to App Life-Cycle Events」を参照

            NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: nil) { _ in
                // do something
            }
サーボをPWMで操作する(M5Stack)

サーボのライブラリを使わずPWMで角度を指定して操作します

サーボが安定しないときはM5Stackの5Vじゃなくて外部電源に繋ぐようにするといいかもしれません


M5Stackの左右ボタンを押すと10度ずつ回転、
中ボタンを押すとセンターにリセットされます

こちらを参考にしました

ESP32 でサーボモーターを動かしてみた：息子と一緒に Makers：So-netブログ
https://makers-with-myson.blog.ss-blog.jp/2017-11-26

```cpp
// (26/1024)*20ms ≒ 0.5 ms  (-90°)
int minimum = 26;
// (123/1024)*20ms ≒ 2.4 ms (+90°)
int maximum = 123;

int deg = 0;

void servo(int degree) {
  ledcWrite(SERVO_CH_0, map(degree, -90, 90, minimum, maximum));
  delay(200);
  ledcWrite(SERVO_CH_0, 0);
}
```

minimum,maximumはpwmのパルスの長さで-90度と90度に対応します

関数は角度をdegreeで入力、map()でminimam,maximumに変換してPWMを出力します

M5Stackライブラリ依存の部分を外せば普通のESP32でも使えます

```cpp
#include <M5Stack.h>

#define SERVO_PIN_0        16
#define SERVO_CH_0        0

// (26/1024)*20ms ≒ 0.5 ms  (-90°)
int minimum = 26;
// (123/1024)*20ms ≒ 2.4 ms (+90°)
int maximum = 123;

int deg = 0;

void servo(int degree) {
  ledcWrite(SERVO_CH_0, map(degree, -90, 90, minimum, maximum));
  delay(200);
  ledcWrite(SERVO_CH_0, 0);

  drawScreen();
}

void drawScreen() {
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.printf("%d", deg);
  M5.Lcd.setCursor(0, 240 - 18);
  M5.Lcd.print("    +        0       -");
}

void setup() {

  M5.begin();
  dacWrite(25, 0); //　ノイズ対策

  ledcSetup(SERVO_CH_0, 50, 10);
  ledcAttachPin(SERVO_PIN_0, SERVO_CH_0);

  M5.Lcd.setTextSize(2);
  M5.Lcd.setBrightness(40);
  drawScreen();
}

void loop() {

  M5.update();

  if ( M5.BtnA.wasPressed() ) {
    if (deg < 90) {
      deg += 10;
    }
    servo(deg);
  }
  if ( M5.BtnB.wasPressed() ) {
    deg = 0;
    servo(deg);
  }
  if ( M5.BtnC.wasPressed() ) {
    if (-90 < deg) {
      deg -= 10;
    }
    servo(deg);
  }
  delay(1);
}
```
Docker上でAWS CLI を実行する

予め[Docker](https://docs.docker.com/get-docker/)をインストールしておく。

```shell
docker -v
```
インストールできていればバージョンが表示される。

適切なポリシーをアタッチした[IAM（Identity and Access Management）ユーザーを作成](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)する。（AWS（Amazon Web Services）アクセスの種類は`プログラムによるアクセス`）

`~/.aws/credentials`を作成し、

```shell
mkdir ~/.aws/ && touch $_/credentials
```

アクセスキーIDとシークレットアクセスキーを記載する。

```vim:~/.aws/credentials
[default]
aws_access_key_id = アクセスキーID
aws_secret_access_key = シークレットアクセスキー
```
`s3 ls` コマンドを実行することで Amazon S3 (Simple Storage Service) でバケットを一覧表示ができるか確かめる。

```shell
docker run --rm -ti -v ~/.aws:/root/.aws amazon/aws-cli s3 ls
```
`alias` を作成することでDockerコマンドを短縮できる。

```shell
alias aws='docker run --rm -ti -v ~/.aws:/root/.aws amazon/aws-cli'
```
同じく `s3 ls` コマンドが実行できるか確かめる。

```shell
aws s3 ls
```
---

- [公式 AWS CLI バージョン 2 Docker イメージの使用](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-docker.html)
Linux Mint20 初期設定

Linux Mint 21.1 導入後に実施する作業の覚書

# 初期設定

## ホームディレクトリの英語化

```
LANG=C xdg-user-dirs-gtk-update
```

## 日本語入力の設定

```
sudo apt install fcitx-mozc --install-recommends
im-config -n fcitx
```

## ターミナルのカレントディレクトリの表示を省略形にする

/.bashrcでPS1の値を設定している箇所を編集する（working directoryを表すwを大文字にする）

~/.bashrc
``` bash
if [ "$color_prompt" = yes ]; then
#    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
     PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\W\[\033[00m\]\$ '
else
#    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\W\$ '
fi
```

## 時計の調整

### Windows とLinux の時計のズレを修正

```bash
timedatectl set-local-rtc 1
```

# Chrome を導入
- インターネットからchromeのdebパッケージをダウンロード
- インストール

# VLC Media Player を導入
ソフトウェアの管理からFlatPakのVLCを導入

# podman のインストール

``` sh
sudo apt install podman podman-toolbox podman-compose  podman-remote 
```

# ~~Docker, Docker Compose を導入~~

podmanに変更

``` sh
sudo apt install docker.io docker-compose docker-buildx
```

## Docker hub へのログイン

```sh
sudo docker login -u [ユーザー名] -p [パスワード]
```

# Visual Studio Code を導入

- インターネットからUbuntu版はダウンロード（debパッケージ）
- インストール

# Virtual Box を導入

- インターネットからLinux 64bit版のdebファイルをダウンロード
- インストール

# VMware Workstation Player を導入

- インターネットからLinux 64bit版をダウンロード
- .bundle に実行権限を付与
- コマンドラインで実行
- SecureBootでの設定
    - ※参照URL
        - https://kb.vmware.com/s/article/2146460?lang=ja
        - https://qiita.com/m-tmatma/items/a1853bb3a1ce04dec74f

# Kdenlive を導入

ソフトウェアの管理からFlatPakのKdenliveを導入

# remminaのインストール

remmina-plugin-rdpをインストール
※Flathubじゃない方をインストール
（Flathubのは日本語が文字化けした）

# Discordのインストール

flathub のページで検索してインストール

# GitKrakenのインストール

flathub のページで検索してインストール

# fsearchのインストール

ソフトウェアマネージャーから検索してflatpakからのインストール

# LibreOfficeをほぼ最新にする

```
sudo add-apt-repository ppa:libreoffice/ppa
sudo apt update && sudo apt upgrade -y
```

# タッチパッドON・OFF切り替え

https://toufulog.com/archives/240
[Rails] ビューにparamsの中身が全表示されてしまう問題

Qiita初投稿です。

現在、Ruby on RailsでECサイトの作成をしています。
商品一覧表示にする際に、以下のようにparamsの中身（？）がビューの下部にずらっと表示されてしまう現象が起こりました。

```
ビューの下部にこのように表示されてしまう

#<Item id: 5, title: "あああ", artist: "あああ", text: "あああ", genre_id: 15, country: "JP", format_id: 2, status_id: 2, price: 500, stock: 1, created_at: "2020-09-30 15:55:20", updated_at: "2020-09-30 15:55:20">,# <Item id: 4, title: "いいい", artist: "いいい", text: "いいい", genre_id: 13, country: "JP", format_id: 2, status_id: 2, price: 5000, stock: 1, created_at: "2020-09-30 15:32:51", updated_at: "2020-09-30 15:32:51">,

以下略
```

```ruby
#app/views/items/index.html.erb

<%= render "shared/header" %>
<div class="main-wrapper">
  <div class="item-wrapper">
    <%= @items.each do |item| %>
      <div class="item">
        <div class="item-image-content">
          <%= image_tag item.image, class:"item-image" %>
        </div>
        <div class="item-format">
          <%= item.format.name %>
        </div>
        <div class="item-artist">
          <%= item.artist %>
        </div>
        <div class="item-title">
          <%= item.title %>
        </div>
        <div class="item-price">
          <%= item.price %>円(税込み)
        </div>
      </div>
    <% end %>
  </div>
</div>
```



はじめはタグの閉じ忘れかと思いましたがどうやら違うようです。


実はとても単純なミスでした。

```
<%= @items.each do |item| %>
```

ビューに実際に表示しないのに、<%= %>とイコールをつけてしまっていました。


```
<% @items.each do |item| %>
```

 =を外すとずらっと表示されていたparamsの中身はなくなりました。
ビューに表示しないものに = をつけてしまうと、このようなことになるんだなという新たな学びでした。