OmniAICreator/Qiita-1.07M huggingface dataset:
使用しているRHELの CVE情報を確認する (Red Hat Insight に登録する)

0.はじめに

この記事は、[こちらの記事](https://qiita.com/Yuhkih/items/a976dde5f150aac1ff9a)に書いている手順で、`REHL`(Red Hat Enterprise Linux) を、`Subscription-Manager`というツールを使って、サブスクリプション登録している事が前提になります。

`Red Hat Insight`は、`Red Hat`のクラウド上のポータルから、自分が使用している`RHEL`の`CVE`情報や`Patch`の情報を提供する`SaaS`サービスです。

`Insight`は、[こちらの解説](https://www.redhat.com/cms/managed-files/ma-insights-frequently-asked-questions-f23939pr-202006-en.pdf)によると、`RHEL`6.4以降のサブスクリプションに含まれている機能との事で、無料で使用できます。

ここでは、`Red Hat Insight`を自分の使っている`RHEL`の`CVE`情報を確認するために使用しますが、もっと細かい使い方については、以下のようなブログ記事がありました。
https://rheb.hatenablog.com/entry/insights

# 1. Red Hat Insight に登録する。

[Customer Portal (cloud.redhat.com)](https://cloud.redhat.com) に、ログインします。

左サイドのメニューから「`Register Systems`」というのを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/4efd9718-ee85-171e-9a89-e76a9db0c56b.png)

そうすると、`RHELのバージョン教えて～`とか、`システムはどう管理しているの？(Subscription Managerで登録したの？)` みたいな質問をされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/27eda66c-c7cd-f27b-362d-793f54b59793.png)

私の場合は、`RHEL`8.3 を `Subscription Manager`のコマンドを使って `RHEL`の `Console` から登録したので、そのように選んでいくと、以下のコマンドを実行するだけで、`Red Hat Insight`に登録できる事になりました。

```
insights-client --register
```

このコマンドを`root`で`RHEL`の`Console`上で実行して、`Red Hat Insight`への登録は完了です。

`Subscription Manager`で既に`RHEL`を登録しているのであれば、`Insight`を使用するには、このコマンドだけでOKです。

# 2. CVE情報を確認する

`Red Hat Insight`への登録だけで、自分が使用している`RHEL`がどのような`CVE`にヒットしているかがわかるようになります。

[Customer Portal (cloud.redhat.com)](https://cloud.redhat.com) に、ログインして、`Dashboard`をメニューから選択すると、以下のように`Red Hat Insight`に登録した`RHEL`の`CVE`情報の一覧を見る事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/d4e0b748-c7da-c44d-7914-836ac86ed065.png)
ダッシュボードの情報をみると、私の`RHEL`8.3は、16の`CVE`を含んでおり、そのうち1つが悪用方法が出回っている(`known exploit`がある)との事でした。

以下の画面を見ると、CVE情報だけでなく、適用できる`Patch`の情報なども表示してくれているので、使いこなせば便利そうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/36ae3b03-a01f-e1a9-af43-9d3ed59f3918.png)
ラムダ式で生成される関数を初学者がざっくり理解するための記事

初学者が躓きやすいラムダ関数（無名関数）、高階関数、コールバック関数あたりのまとめ①

ラムダ関数とは
--
ラムダ式とは関数を入力として受け取り、出力できる関数式のことを指す

ラムダ関数別名
--
ラムダ関数は関数リテラル（匿名関数、無名関数）と言われている。

通常の関数とラムダ関数の大まかな違い
---
通常関数は`function`で定義されることで、メモリアドレスの中にある読み取り専用のコードセグメントに格納される
それに対してラムダ式で生成される関数のことをラムダ関数という。
ラムダ式によって作られた無名関数はオブジェクトをつくる。
そのオブジェクトを通常の関数と同様に呼び出すことも可能。
例

```javascript
let ramuda = function(){return "ラムダ"}
```

上の関数をコンソールログするとわかりやすい。

①

```javascript 
console.log(ramuda)
```

→`[Function ramuda]`みたいなのが出てくる



②

```javascript
console.log(ramuda())
```

→ラムダがでてくる

ラムダ関数と通常の関数の保存先
--
通常の関数　

```javascript
function tujou() { return "通常"}
```
　→　コードセグメントに格納されどこからでも呼び出し可能

ラムダ式でつくられた無名関数

```javascript
funtion () {return "ラムダ"}
```
　→　どこにも保存されていないのでガベージコレクタによって削除される。

そのため

```javascript
let ramuda = function(){return "ラムダ"}
```

と書けば変数に保存されるので呼び出し可能なオブジェクトになる。

コールバック関数、高階関数
--
高階関数は一言で言えば引数に関数があり、戻り値を出力する関数のこと
例

```javascript
function kokai(f) {f() + "高階関数だよ"}
```

的なやつ。
上述の無名関数を引数に入れて使ってみる。

```javascript
function kokai(function(){return "初学者には難しすぎる！"})
```

これをコンソールすると
「初学者には難しすぎる高階関数だよ」
がでてくる。
＊注意点
引数には無名関数しか入れてはいけない感じが出てるが通常の関数も入力できる

高階関数の次はコールバック。
コールバック関数とは関数Xが入力として渡されて、その受け取った関数Xがもともとの関数Aが実行されている中で呼び出される関数のこと。

そもそもコールバック関数には
①同期的に実行されるもの→中で行われる関数Xがもともとの関数Aの実行中に終わる
②非同期的に実行されるもの→中で行われる関数Xの終了をもともとの関数Aはまたない
の２種類ある。
①は今まで見てきた無名関数のこと
②の例

```javascript
function callback(f,s) { 
 console.log("一番最初")
 setTimeout(f,s)
 console.log("二番目")
}

console.log(callback(function(){console.log("最後にくるよ")},2000);
```

コンソールには
一番最初→二番目→最後にくるよ
の順番で出力されます。

ただ、非同期で実行される関数はデータの流れがわかりにくくなり、コードの実行の流れがわかりにくくなる可能性がある。（処理がうまく同期していないとすぐに制御不能になるらしい、、ここらへんの理解が微妙）

だからこそ言語によってはプロミスオブジェクトや`async`,`await`で強制的に同期化している


明日は、今日の内容に基づいて、ラムダクロージャーや`map`,`filter`,`reduce`関数についてアウトプットしたい。
Macのローカル環境にて、Bitcoinのテストネットで送金を体験する

# はじめに
環境設定は[Macにbitcoindとbitcoin-cliをインストールして、Bitcoinの環境を構築する](https://qiita.com/miyabiz/items/b7b7219d795e8912bdc0)を参照。

今回はbitcoindとbitcoin-cliを使って、Regression Testネット環境にてBitcoinの送金を行います。


# 手順
1.  RPCサーバーを起動する

    ```
    mkdir ~/bitcoin-test && echo 'fallbackfee=0.0002' > ~/bitcoin-test/v
    bitcoind -regtest -daemon -conf=~/bitcoin-test/bitcoin.conf
    bitcoin-cli -version
    ```
    ※ 0.20.0以降は、bitcoin.confにfallbackfeeを指定しないと途中でエラーとなります。

1.  regtestの設定ファイルを確認する

    ```
    ll ~/Library/Application\ Support/Bitcoin/regtest
    ```

    ※ これからコマンドを実行した設定内容は全てこのディレクトリに格納されます。
    ※ 途中で失敗した場合は、```bitcoin-cli -regtest stop```を実行して、RPCサーバーを停止します。 ```rm -rf ~/Library/Application\ Support/Bitcoin/regtest```にて設定を内容を削除後、最初からやり直してください。

1.  ブロックチェーンの情報を確認する

    ```
    bitcoin-cli -regtest getblockchaininfo
    ```

1.  ```my_wallet``` というウォレットを作成する

    ```
    bitcoin-cli -regtest createwallet my_wallet
    ```
1.  ウォレットの情報を確認する

    ```
    bitcoin-cli -regtest getwalletinfo
    ```
1.  ウォレットに```user1```というユーザーを作成する

    ```
    $ bitcoin-cli -regtest getnewaddress user1
    <user1のアドレス>
    ```
    ※　```<user1のアドレス>```が発行される


1.  ウォレットに```user1```が作成されていることを確認する

    ```
    [
      "user1"
    ]
    ```


1.  ```user1``` の残高を確認する


    ```
    $ bitcoin-cli -regtest getbalance
    0.00000000
    ```

1.  ```user1``` で101回マイニングする


    ```
    bitcoin-cli -regtest generatetoaddress 101 <user1のアドレス>
    ```
    ※　Regression Testネット環境は100回を超えないと報酬が発生しない。

1.  再度、```user1``` の残高を確認する


    ```
    $ bitcoin-cli -regtest getbalance
    ５0.00000000
    ```

1.  送金先として、ウォレットに```user2```というユーザーを作成する

    ```
    $ bitcoin-cli -regtest getnewaddress user2
    <user2のアドレス>
    ```
    ※　```<user2のアドレス>```が発行される

1.  ウォレットに```user2```が作成されていることを確認する

    ```
    [
      "user1",
      "user2"
    ]
    ```

1.  ```user1``` から```user2```に10BTC送金する

    ```
    bitcoin-cli -regtest sendtoaddress <user2のアドレス> 10.0
    ```

1.  再度、```user1``` の残高を確認する


    ```
    $ bitcoin-cli -regtest getbalance
    49.99997180
    ```
    ※　マイニングで新しいブロックが生成されていないため、送金情報が反映されていないが、手数料が引かれている。

1.  ```user2``` の残高を確認する


    ```
    $ bitcoin-cli -regtest getreceivedbyaddress <user2のアドレス>
    00.00000000
    ```
    ※　マイニングで新しいブロックが生成されていないため、送金情報が反映されていない。

1.  ```user1``` でマイニングする


    ```
    $ bitcoin-cli -regtest generatetoaddress 1 <user1のアドレス>
    <送金ブロックのID>
    ```

1.  ```user2``` の残高を確認する


    ```
    $ bitcoin-cli -regtest getreceivedbyaddress <user2のアドレス>
    10.00000000
    ```

1.  送金ブロックの情報を確認する


    ```
    bitcoin-cli -regtest getblock　<送金ブロックのID>
    ```
    ※　```tx```に送金したトランザクションが記録されている

1.  送金トランザクションの情報を確認する


    ```
    bitcoin-cli -regtest gettransaction　<送金トランザクションのID>
    ```
    ※　<送金トランザクションのID>は、```tx```に送金したトランザクションが記録されているIDを設定する

1.  RPCサーバーを停止する


    ```
    bitcoin-cli -regtest stop
    ```
室内の二酸化炭素濃度をポータルで表示

家の二酸化炭素濃度をGoogle Data Portalでモニタリングできるようにしました。

![portal_co2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/c68e5e9f-2db7-665b-01f8-98463ff95b84.png)


#### 前提
* Google Data Portalにベースとなるレポートがあること (詳細は以下ページ参照)

https://qiita.com/tosshie/private/bc43114d42e05bc3afcb

* Google SpreadSheet に二酸化炭素濃度がリアルタイムに更新されていること (詳細は以下ページ参照)

https://qiita.com/tosshie/items/fe79368c6ef75df3736c

#### Google SpreadSheet側の設定
* 最新データのみを表示するシートを作成 (詳細は以下ページ参照)
    * Google Data Portalの仕様で、スコアカードを使う場合は"合計"とか"平均値"とかしか表示できないので、最新値だけのシートを作ります
   
https://qiita.com/tosshie/private/740515ba66116bf56e84

#### Google Data Portal側の設定
* Google Data Portalを開きベースとなるレポートを表示
* 右上の編集ボタン
* メニューのデータを追加 → Google SpreadSheetから最新データのみを表示するシートを選択 → 追加 → レポートに追加
* メニューのリソース → 追加済みのデータソースの管理 → 追加したものの編集ボタンをクリック
* 値を以下のように変更し完了ボタンを押す → 閉じる
    * co2データ
        * タイプ: 数値
        * デフォルトの集計: なし
    * 日付データ
        * タイプ: 日付、時、分
        * デフォルトの集計: なし
* グラフを追加 → スコアカード → 配置
* スコアカードのメニュー（右側に出ているプロパティ的な部分）を変更
    * データソース: 追加したシートを選択
    * 期間のディメンション: 不要（値が入っていたら削除）
    * 指標: co2データを選択
* 複数場所のco2のグラフが必要な場合はこれを繰り返して作成


#### 色指定
* CO2濃度が高いときに色が変わるようにしています。
    * CO2濃度が0-999: 背景色と同じグレー
    * CO2濃度が1000-1499: 緑
    * CO2濃度が1500-1999: オレンジ
    * CO2濃度が2000以上: 赤


* スコアカードのメニューからスタイルタブを選択
* 背景色を指定（私はテーマとレイアウトでエッジを選んでいるのでグレーにしています）
* 条件付き書式を設定（追加ボタンをクリック）
    * 1. 色のタイプ: 単一色
    * 2. 書式ルール: 値、次の値以上、1000
    * 3. 色とスタイル: 背景色を緑に設定
    * 保存して新たに追加
    * 1. 色のタイプ: 単一色
    * 2. 書式ルール: 値、次の値以上、1500
    * 3. 色とスタイル: 背景色をオレンジに設定
    * 保存して新たに追加
    * 1. 色のタイプ: 単一色
    * 2. 書式ルール: 値、次の値以上、2000
    * 3. 色とスタイル: 背景色を赤に設定
    * 保存

こんな感じに表示されます↓

![co2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/a7823e9e-e175-d08c-be66-21ac81afab91.png)

![co2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/5084df61-45e4-28b2-573b-b7bed302ff80.png)


------------------------
2021年3月から始めたスマートホーム化はこちらに一覧化しています（2021年7月時点）

https://qiita.com/tosshie/items/82dcc6405925b12d2fd1
クソWebアプリをBootstrapを導入したりして改修しました。１

# 前書き
久々の投稿です。
[今回のWebアプリ](https://hoshizima.com/sub/2DVtuber/web/)
[前回：リアル「クソ」WebアプリIWannaBeTheUNCHI](https://qiita.com/hoshizima/items/b8df9fb0afc06cc44c60)
最初アクセスすると特段案内もなくまっさら…
<img width="300" alt="73f5e488-e262-ac68-d066-93ba5932f6d5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482410/73f5e488-e262-ac68-d066-93ba5932f6d5.png">
突如映し出される自身の顔輪郭と💩
<img width="300" alt="2dd7c850-e7bd-6beb-53c3-71f11d9d88a5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482410/2dd7c850-e7bd-6beb-53c3-71f11d9d88a5.png">
という感じでした。
それを、↓画像のように改修しましたので、その中での気づきについてまとめる記事です。
<img width="300" alt="cbad3320-6006-8e9e-9e6a-c1b59b994c1f.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482410/cbad3320-6006-8e9e-9e6a-c1b59b994c1f.png">
<img width="300" alt="97848c03-efa9-2aa6-f4b8-821b05337c5f.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482410/97848c03-efa9-2aa6-f4b8-821b05337c5f.png">
# ユーザビリティの改善
以前の私はサービスの「当たり前」ができていませんでした。
あくまでも「サービス」であり、広告を貼っているのだから、ユーザーに使ってもらうことを第一に考えるべきです。
方法は様々ですが、**どうやって使うのか**とか今**アプリケーションの状態がどうなっているのか**をユーザーに知ってもらう必要があります。
サービスを名乗るのであれば絶対になんのガイドもない真っ白ページに誘導するなんてことはしてはいけません。（戒めろん）
## エンジニアでないユーザーでもわかりやすいように
自分が端くれとは言え、エンジニアであるためメッセージが難しくなりがちです。画面のメッセージやガイドはなるべくこのアプリケーションを開いた人に**どうしてほしいのか**、どうすると**結果どうなるのか**という部分を伝えるようにすべきだと考えています。**過程や方法なぞどうでもよいのだァー!**
今回であれば、とにかく**💩にあなたの顔の輪郭線を書いて表情を映すことができればよかろうなのだァァァァッ!!**
なので、「カメラで顔を映して確認しながら顔を真ん中に移してね」というような文言を採用しました。
こんなシンプルなアプリではそりゃそうじゃと思われますが、いくら複雑になっても忘れてはいけない意識なのかなと感じました。
# 利用されているサービスではないが…
今後も改修を続けていきたいと考えています。
利用していただくことは一つの目標ですが、あくまでも自身がコードを書いて物を作ることをメインの目的として開発していきたいと思っています。
多分、初学者はそれくらいの**気負わずに開発を継続することが大切**なのかなと思います。

# Bootstrapの利用とpositionの難しさ（この項は余談）
Bootstrapを一応採用しました。ほとんど使いこなせていないこともありますし、優秀な記事はたくさんありますので、導入方法などは紹介しません。
多くの記事でありましたが、私もしっかり読んでおらず詰まった部分で、**グリッドシステムを使いたいならcontainerちゃんと使え。**必須だと書いてあります↓
[BootstrapDocument](https://getbootstrap.jp/docs/5.0/layout/containers/)
このことだけは伝えたかった。
自身のページではまだcontainerを使ってrowをいくつか作っているだけですが、レスポンシブと言えるかわかりませんが、スマホで開くとスマホサイズ用にサイズが調整されるようになりました。今後、サイドバーを実装する際に便利そうだなと感じました。
また、ＣＳＳをしっかりと理解する良い機会になりました。（positionの指定についてよく理解していなかったこちらは別記事でまとめてみたいと考えています。)
【Ruby on Rails】アソシエーション先での検索方法

Railsに触れて3ヶ月、忘れないようにメモしときます。

### **環境**
ruby 2.6.3
Rails 6.0.1

### 前提

`Authorモデル` has_many  `Bookモデル`

`Bookモデル`  has_many `Chapterモデル`

## アソシエーション先で検索

例） `title` という名前の本( `Book` )を書いた人( `Author` )を検索

```ruby
matched_authors = Author.includes(:books).where(books: { name :title })
```

## アソシエーション先でキーワード検索

例） `keyword` という言葉を含む名前の本( `Book` )を書いた人( `Author` )を検索

```ruby
matched_authors = Author.includes(:books).where('books.name LIKE ?', "%#{keyword}%")
```

where句の第1引数のSQL文の `?`  を 第2引数で置き換えて検索してくれます。

書き方いろいろあると思います。

もっと良い方法があればコメントで教えていただけると嬉しいです。

---

他にも `where` の使い方 [参考先](https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-where)

---

### ちなみに...

**アソシエーション**と**リレーション**、似ていますが

アソシエーション ⇒ モデルの関係性

リレーション ⇒ DBテーブルの関係性

を言うみたいです。
Compute Engine から Python でスプレッドシートを参照したい

# これは
`Compute Engine` のVMインスタンスからサービスアカウントキーを使用せずに `Python` を用いてスプレッドシートにアクセスするための備忘録。  

## 前提
GCPプロジェクト、ComputeEngineインスタンスは作成済みとする。

## 手順
### 1. 連携に必要なAPIを有効にする
以下のAPIを有効にする。
-　Google Drive API
-　Google Sheets API

### 2. ComputeEngineにアクセススコープを付与する
まず、インスタンスを停止する。
次に、Cloud Shellから以下のコマンドを実行する。  

```
$ gcloud beta compute instances set-scopes \
projects/{プロジェクトID}/zones/{VMインスタンスのゾーン}/instances/{VMインスタンス名} \
--scopes default,https://www.googleapis.com/auth/spreadsheets.readonly
```

### 3. Pythonスクリプト作成
```
あとで書きます。
```

## 参考にさせていただいた記事
https://qiita.com/Sekky0905/items/e1ae602a1a2a4edb17df
https://stackoverflow.com/questions/64937670/accessing-google-sheets-api-from-google-compute-engine-python
https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances?hl=ja
残プロ　第-34回　~pythonでcpu使用率を確認する~

# subprocess.runを使う

subprocess.runでプロセス実行し，cpu使用率の取得を行います．
text=Trueを指定することで文字化けしなくなります．

~~~ python:
import subprocess

cmdline = "typeperf -sc 1 \"\\processor(_Total)\\% Processor Time\" \"\\Memory\\Available MBytes\"";

output = subprocess.run(cmdline, shell=True, stdout=subprocess.PIPE, text=True)
print(output.stdout)
~~~

なお，今回はWindowsのコマンドプロンプトを想定しています．
MacやLinuxの場合はcmdlineの値を適宜変更してください．
ガベージコレクションとは。

#【ガベージコレクションとは。】

理解が浅かったので学習することにしました。
簡単にまとめました。

##ガベージコレクション（GC）

>ガベージコレクションとは、コンピュータプログラムの実行環境などが備える機能の一つで、実行中のプログラムが占有していたメモリ領域のうち不要になったものを自動的に解放し、空き領域として再利用できるようにするもの。

>（IT用語辞典 e-Words）

##プログラムの動作の流れ

プログラム処理は、必要な情報をメモリ上に書き込み、その読み込んだ情報をもとにして、処理を実行している。

その後、処理が終了すると読み込まれた情報は不要になる。
　→ メモリにゴミが残されている。

このメモリに残されたゴミを掃除してくれるものが、**ガベージコレクション**。

Javaでは、プログラムが確保したメモリ領域の不要になった箇所を開放してくれる機能が標準搭載されている。
　→ **メモリを管理**する必要がない。

##簡単にまとめ。

Javaでは、ガベージコレクションが標準されていることによって、作成したインスタンスのメモリ管理の後処理を気にしないでプログラム開発ができる。

ガベージコレクションが採用されていないプログラミング言語では、ソースコードで明示的にメモリを管理する必要がある。

##参考

[5分で分かるガベージコレクションの仕組み](https://geechs-job.com/tips/details/35)

ありがとうございました。
オゾン発生器を Hack

中国製の安いオゾン発生器。

![IMG_20210705_125058_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/31084679-0403-8d3f-4d1c-465bac28d650.jpeg)

「12V10G臭氧发生器汽车载消毒机杀菌除甲醛净化空气车辆家用臭氧机」

となっていて、スペックは大体以下のような感じ(推測含)。

- 電源 12V 
- 消費電力 70W 
- 高圧出力 3.5KV  16kHz
- オゾン生成能力  10g/h 

今回使用したのは 放電板が 2枚ある 10g/h タイプ。
 
放電板1 枚で 5g ということらしい。


これがかなり強力で、10ppm 程度にしたいのだが狭い空間だとあっという間に 10ppm を突破してしまう。ちゃんと制御したい。



# 調査

分解してみました。


![IMG_20210705_222241.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/cede532b-271f-d02f-e87f-b9c672e1fad5.jpeg)


![IMG_20210705_182113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/54d0603d-6f9f-3766-c95f-0ddfb9525bb6.jpeg)

回路図を起こしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d2ba2933-8fbc-a260-a1d2-3ecdc40c3f85.png)

# 制御する

オゾン濃度によって、運転制御をしたい。

割と大きな電解コンデンサーが入っているので、12VのON/OFFをするとコンデンサの充電のために何秒かラグがありました。もっとレスポンス良くできないかな？

さて、回路図の一番右下のポテンショメーターでは、発振周波数を制御しているようです。
この写真では、青い部品がポテンショメーターです。

![IMG_20210705_222347.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e862b241-0bf7-71fb-31ba-bfd8c67d6f36.jpeg)

裏側。


![IMG_20210705_182132.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/74255f47-12ee-d0e4-371f-1ed57a76eb0e.jpeg)

ここから GND と 信号線を引き出しました。


今回は、GND (黒)と 信号線(青) で接続しました。しかしながら放電板から相当なレベルでノイズが放射されているので、同軸ケーブルなどを使うのが望ましいでしょう。。

![IMG_20210705_232035.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/659c3123-5418-d415-6170-38ca95de6bda.jpeg)


この電圧を測ってみると約3Vです。ここをGNDにすると出力が止まりました。応答遅延も1秒以内です。

ESP32に接続して、以下のスケッチで1秒おきの運転ができました。

```

void setup() {
  Serial.begin(115200);
  pinMode(19, OUTPUT);
}

void loop() {
  pinMode(19, OUTPUT);
  digitalWrite(19, LOW);
  Serial.println("ON");
  delay(1000);
  pinMode(19,INPUT);
  Serial.println("OFF");
  delay(1000);
}
```
Laravel7でセッションタイムアウト時間を変更する

#前置き
セッションタイムアウトに関する処理を行う際に時間変更する方法を調べたため、自分用に残します。

#前提条件

```
Laravel 7
php 7.4
```

#結論
調べた際に以下の2つの方法がありました。

###方法①：.envファイルのSESSION_LIFETIMEの値を変更する
.envファイルの真ん中あたりに書いてあるSESSION_LIFETIME=120の値を任意の値に変更する。
（デフォルトでは120になっているため、変更しない場合は2時間でセッションタイムアウトになります。）

```
SESSION_LIFETIME=任意の数値
```

変更後に以下のコマンドを実行する。
※キャッシュ系のコマンドであるため、要確認を行うこと

```php
php artisan config:cache
```

***
###方法②：config/session.phpファイルの'lifetime'を変更する
config/session.phpファイルに記載されている'lifetime' => env('SESSION_LIFETIME', 120)を任意の値に変更する。
（デフォルトでは120になっているため、変更しない場合は2時間でセッションタイムアウトになります。）

```php:config/session.php
'lifetime' => env('SESSION_LIFETIME', 任意の値)
```

変更後は、方法①と同様にphp artisan config:cacheを実行する。

#参考・引用元
大変参考にさせていただきました。ありがとうございます。
https://teratail.com/questions/254235
1週間RealmSwiftを勉強してわかった事 Part3

#今回の内容

* CRUDのR(Read)➡️Realmに保存しているデータを<font color="Red">取得</font>する　
* CRUDのU(Update)➡️Realmに保存しているデータを<font color="Red">更新</font>する

#Realmからデータを取得する(Read)
1.`import RealmSwift `をimportしてなければ、記述しましょう。(エラーが<font color="Red">Could not build Objective-C module 'RealmSwift'</font>と表示されたらXcodeの左上の▶️(Ranボタン)でBuildして下さい)

```Swift:Modelファイル
import RealmSwift 
```

2.`do{}catch{}`を用意する。(これで`try`の後の関数で<font color="Red">Error</font>が出ても、アプリが落ちないので`catch{}`内の処理が呼ばれます)

3.`do{}`の`{}`内で、`Realm()`をインスタンス化します。➡️`let realm = try Realm()`のことです。

注：`class RealmDatas:Object{}`を作成した事を仮定して説明を進めます。

4.`do{}`の`{}`内で、`realm.objects(RealmDatas.self)`を使用してRealmに保存してあるRealmDatasのデータを全件取得します。取得時は<font color="Red">配列</font>の状態で取得されます。

```Swift:Modelファイル
import RealmSwift 

do{
            let realm = try Realm() //インスタンス化
            let readRealmData = realm.objects(RealmDatas.self)
            
        }catch{
            
            print("!!!ERROE!!!")
            
        }
```

練習で作ったカレンダーメモアプリで書いたfilterを使ったメソッドもコードだけ載せておきます。(誰もいないと思いますが説明が欲しい方はコメントまでお願いします)

```Swift:Modelファイル 
 var realmReadDatas:[[String:String]] = [] //Realmから取得したデータを入れる為に用意

 func filterReadRealm(selectDate:String){
        
        do {
            let realm = try Realm()
            self.realmReadDatas = []
            
            for filterData in realm.objects(RealmDataSets.self).filter(NSPredicate(format: "realmDay == %@", selectDate)) {
                
                self.realmReadDatas.append(["day":filterData.realmDay,"who":filterData.realmWho,"event":filterData.realmEvent])
                
            }

        }catch{
         //エラー後の処理など
        }
        
    }
```

#Realmのデータを更新する(Update)

1.`import RealmSwift `をimportしてなければ、記述しましょう。(エラーが<font color="Red">Could not build Objective-C module 'RealmSwift'</font>と表示されたらXcodeの左上の▶️(Ranボタン)でBuildして下さい)

```Swift:Modelファイル
import RealmSwift 
```
2.`do{}catch{}`を用意する。(これで`try`の後の関数で<font color="Red">Error</font>が出ても、アプリが落ちないので`catch{}`内の処理が呼ばれます)

3.`do{}`の`{}`内で、`Realm()`をインスタンス化します。➡️`let realm = try Realm()`のことです。
 
4.`realm.objects(RealmDataSets.self)`を使用してRealmに保存してあるRealmDataSetsのデータを全件取得します。

注：`class RealmDatas:Object{}`を作成した事を仮定して説明を進めます。

5.`try realm.write({})`で<font color="Red">writeトランザクション</font>を作成します。

6.`try realm.write({})`内で、更新したい値が入ったを`readRealm[Index番号].RealmDataSetsで宣言したプロパティ名 =`などで指定をして,そこに`新しい値 `を入れる事で更新される。


```Swift:Modelファイル
do{
            let realm = try Realm()
            let readRealm = realm.objects(RealmDataSets.self)
            
            try realm.write({ //writeトランザクション　ここから
                
                    readRealm[Index番号].RealmDataSetsで宣言したプロパティ名 = 新しい値 

             }) //writeトランザクション　ここまで
            
        }catch{
            //エラー後の処理など   
        }
```

#今回はここまで
* 次回
 * CRUDのD(Delete) について書きます　 

読んでみて間違っている部分などがありましたら、コメントで指摘して頂けると嬉しいです。
ドラッグ＆ドロップエリアのHubLタグ


# 原則

・dnd_areaで囲う必要がある
・class名を指定できるのはdnd_areaのみ
・dnd_areaの内側に記述したHTMLは無視される。外側に記述したHTMLは反映される
・dnd_area内でif文は利用できない。



## 最小構成

```
dnd_area
	dnd_section

```


## いくつかのパターン

```
dnd_area
	dnd_section
	dnd_section
	dnd_section

```



```
dnd_area
	dnd_section
		dnd_column
		dnd_column

```

```
dnd_area
	dnd_section
		dnd_column
			dnd_row
				dnd_module
		dnd_column
			dnd_row
				dnd_module

```



### dnd_areaも複数使える

```
dnd_area
	dnd_section

dnd_area
	dnd_section

dnd_area
	dnd_section

```
Chrome使用中に通知を行う拡張機能の作成

こんにちは take-2405 です。

最近Chrome Extensionを作成したのでその件についてお話していきたいと思います。

**今回僕が作成した拡張機能はユーザーがブラウザを使用している際に通知を行う拡張機能です。**  

### 作成したシステムの概要

![スクリーンショット 2021-07-05 232201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416512/3f534873-b568-8013-fcf4-739c942ee3d5.png)


1. Chrome上の特定の動作をきっかけにExtensionからAPIにリクエストを送信します。
1. APIはリクエストが届いた際にリクエストを送ってきたユーザーの通知があるかどうか確認するためにDBに問い合わせます。
1. DBをAPIから送られてきたクエリに従い対象のデータ(通知)があるがどうかを確認し結果をAPIに返します。
1. APIはDBから帰ってきた値を確認しエラーがなければクライアント(Extension)にレスポンスを返します。
1. (図には書いてませんが)ExtensionはAPIから帰ってきたレスポンスを受け取り通知があればユーザーに通知します。

### 動作

![スクリーンショット 2021-07-04 053255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416512/f73f3728-1205-34ba-1d87-775dbb6e30d9.png)

![スクリーンショット 2021-07-04 053312.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416512/73c465aa-1954-01a8-c31b-a6a3d804110f.png)


# 本題

いよいよ本題に入りましょう。
拡張機能の基本的な部分は以前記事に書かせていただいたのでこの記事の前に読むことをお勧めします。
https://qiita.com/QT21-004-2_HCB/items/8efc84c10d30dc503422

拡張機能を作成するにあたり重要だったのは以下の2点です。  

1. バッジ(拡張機能のアイコンに表示される文字)
1. ポップアップ(アイコンクリック時に表示されるもの)

### 1.バッジ

バッジとは拡張機能のアイコンに表示される文字のことです。先ほどの写真では赤い四角の中に「通知」という白い文字が表示されていました。これがバッジです。

バッジを表示するためには「Event / Background Page」に下記の処理を追記する必要があります。

```event.js
 chrome.browserAction.setBadgeText({ "text": "ここに文字列" })
 chrome.browserAction.setBadgeBackgroundColor({ color: [255, 0, 0, 100] });
```

ざっと説明すると上記の２行でバッジを表示することができます。
まず１行目のコードがバッジに表示する文字列を指定します。(注意：標示できる文字列は４文字まで)
続いて２行目のコードでバッジの背景色を指定しています。

今回僕が作成した拡張機能はAPIからのレスポンスによってバッジの表示・非表示を切り替えることでユーザーへの通知を行っていました。

### 2．ポップアップ

##### Manifest

拡張機能のアイコンをクリックした際に表示されるものがポップアップです。

まずポップアップの表示を行うためにはmanifestのブラウザアクションにポップアップを追加します。

```manifest.json
"browser_action": {
        "default_title": "sample",
        "default_popup": "./popup/popup.html"
    }
```

- default_title：拡張機能の名前
- default_popup：ポップアップを表示するためのhtmlへのファイルパスを指定

###### ポップアップ内容(html)

```./popup/popup.html
<html>
<head>
    <title>Test</title>
</head>
<body>
    <h1>sample</h1>
</body>
</html>
```

これでおそらくアイコンクリック時にポップアップが表示されると思います。


**ここからはお好みでですが、CSS JSを書くことで動的な挙動が可能です。
またポップアップ部分と「Content Script」or「Event / Background Page」間のデータやり取りが可能です。**

つまり発想次第でいろいろな拡張機能が作成できそうですよね？


データのやり取りに関しては別の記事として書いているのでぜひ
https://qiita.com/QT21-004-2_HCB/items/3bdc94c3cf83720e9da4

今回僕が作成した拡張機能では通知が発生した際に(ポップアップに)通知内容を表示しました。ユーザーがアイコンをクリックし、ポップアップを表示した時点で通知を確認したとみなしバックグラウンドへ変数を渡し通知を削除する関数を起動しました。説明下手ですいません、、、
Java 配列とリスト

#【Java 配列とリスト】

面接選考の際にこれらの理解をうまく言語化できなかった。
再度学び直して、備忘録として残します。

**配列は、扱うデータが決まっている時に適し、
リストは、柔軟にデータを扱いたいときに適している。**

##配列

インデックスを用いて、複数のデータを管理する。
配列は、宣言時に要素数を決めておく必要がある。
　→ あとから要素数を増減できない。

配列のデータの保持の仕方は、宣言時にメモリの連続した領域を確保している。

**要素数の増減やデータの挿入や入れ替えが容易。
リンクの追加や削除、リンク先の変更をおこなうのみ。**

>インデックスとは、索引、見出し、添字、指数などの意味を持つ英単語。ITの分野では、書籍の巻末の索引のように、多数のものの中から特定の対象をすばやく見つけ出すため識別情報や、整列された所在情報の一覧などを指すことが多い。

>（IT用語辞典 e-Words）

##リスト

オブジェクト管理に要素番号を用いる。
リストは、生成時にデフォルトの要素数を指定する必要がない。
　→ あとから要素数を自由に追加・削除できる。

リストのデータの保持の仕方は、新たな要素を追加されるたびにメモリの領域を確保する。

**はじめに領域を確保しているため、要素数の増減は不可。
要素を入れ替える時は、ある要素を削除して、別の要素を移動させてから、さっき削除した要素を空いた箇所に入れ直す。**

##要素の検索について

配列では、インデックスを指定すれば直接要素を参照可能であり、どの要素に対しても同時間でアクセスが可能。
　→ 何度もランダムな要素にアクセスするような場合に適している。
　→ 要素の入れ替えが多かったり、後から追加したりするには適さない。

リストでは、ランダムな要素を検索する時は端の要素からリンクをたどる必要があるので少し時間がかかる。
　→　頻繁な要素の入れ替えや要素の追加や削除がある時に適している。

##参考

[どう違うの？JavaにおけるListと配列の違いと使い分け](https://www.kenschool.jp/blog/?p=5308)

ありがとうございました。
docker-compose コマンドでstartappを実施

##概要
・Dockerに慣れるため、djangoの環境構築を実施した時に失敗したこと調べたことを記載。

##状況
Djangoの環境構築を実施。Dockerfileとdoocker-compose.ymlを以下のように記載。

```Dockerfile.
FROM python:3.8-alpine

ENV PYTHONUNBUFFERED 1

RUN mkdir /code
WORKDIR /code

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

ADD . /code/
```

```docker-compose.yml
version: '3' 
services:
  web:  
    build: .  
    volumes:
      - .:/code  
    ports:
      - "8000:8000"
    command: python manage.py runserver 0.0.0.0:8000
```

その後、django-admin startprojectを実施して下記コマンドを実施するも
「Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"manage.py\": executable file not found in $PATH": unknown」のエラー。

```実施コマンド.
docker-compose run python manage.py startapp app名
```

##解決策
```正しいコマンド.
docker-compose run web python manage.py startapp app名
```
runコマンドを実施するときは、ymlの「services:」で定義したもので実施する必要があった。
(今回で言うとweb)
参考 : https://docs.docker.jp/compose/reference/run.html

##メリット
こうすることでDockerfileに記載のある「python3.8」でmanage.pyのstartappを実施してくれる。
そのためDocker のホストのコンピューターにpythonのインストールの必要がなくなるため、開発環境に左右されずに同じ結果を保証しやすくなる。(pythonが自動or手動更新されて急にコマンドでエラーが出ることがなくなる)

参考:https://teratail.com/questions/275283

認識違いがあればコメントお願いします。
[Chrome Extension]スクリプト間のデータ受け渡し

こんにちは Takeです。

Chrome Extensionを作成するにあたり主なパーツが以下の３つです。

- Content Script
- Event/Background Page
- Popup 

今回はこの３つの間のデータ受け渡しについてメモ程度に書きます。

※あくまで例であって作成する拡張機能の内容によってケースバイケースです。

### 1 Content → Event/Background Page
今回は例として開いているページのURLを取得しEvent/Background Pageへ渡します。

**データを渡す側**

```content.js
const getPageTitle = function () {
    var url = location.href;
    return url
}

chrome.runtime.sendMessage(getPageTitle(), function (response) {
    return true;
})
```

**データを受け取る側**

```event.js
hrome.runtime.onMessage.addListener(function (info,sendResponse) {
    console.log(info)
}
```

### 2 Event/Background Page → Popup

**データを渡す側**

```event.js
var value = "sample";
```

**データを受け取る側**

```popup.js
  console.log(chrome.extension.getBackgroundPage().value)
```

### 3 Popup → Content


**データを渡す側**

```popup.js
const SampleFunc = function () {
  return "Sample";
}

chrome.runtime.sendMessage(SampleFunc(), function (response) {
})
```

**データを受け取る側**

```content.js
  chrome.runtime.onMessage.addListener(function (message) {
    console.log(message);
    return true;
});
```
EVE-NG Linuxノード接続をTelnetに変更する

EVE-NGにインストールしたLinuxノードの接続方法をTelnetへ設定変更した時のメモです。

---

## 環境
EVE公式サイトにリンクされている Linux image pack の **linux-centos-8.tar.gz** を使用しました。また、Centos8アップデートに備えてIFにアドレスを設定、外部ネットワーク（Cloud0）を配置の上、インターネットに接続しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534103/d6248ecd-c3c8-c38f-4158-4835e92a92e6.png)

## 基本的な設定
ノードOSに対して設定します。
※EVE-NGサーバに設定しないように要注意
※うまくいかない場合は下記詳細のとおりgrub設定ファイルを編集

```
# sed -i 's/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="console=ttyS0,115200 console=tty0"/' /etc/default/grub

# update-grub
```

##EVE公式サイトから配布されている linux-centos-8 の場合
###1-1. grub設定
/boot/grub2/grub.cfgを直接編集することはNGのため、その元になる/etc/default/grubを編集します。変更箇所はカーネルに渡すブートオプション `GRUB_CMDLINE_LINUX=` のパラメータです。（ファイル編集前に必ずバックアップを実行）

```file:/etc/default/grub
[user@CentOS-8 ~]$ sudo vi /etc/default/grub
[sudo] password for user:
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="console=ttyS0,115200 console=tty0 crashkernel=auto rd.lvm.l"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
```
<br>

###1-2. 設定反映
編集した/etc/default/grubの設定内容を/boot/grub2/grub.cfgへ反映させます。
※OS/ver.によっては `update-grub` または `update-grub2`

```command:grub2-mkconfig
[user@CentOS-8 ~]$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
[sudo] password for user:
Generating grub configuration file ...
done
```
<br>

###1-3. ノード接続方法の変更
ノードをシャットダウンさせ、Console設定を [vnc] から [telnet] に変更、保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534103/87f5bda1-a125-b7eb-9688-7c41734d832a.png)
<br>

###1-4. 起動確認
ノードをスタートさせ、ノードアイコン左クリック、Telnet接続してOS起動できることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534103/abec15c7-6130-c7e3-8db0-d32148b3d77f.png)
Macにbitcoindとbitcoin-cliをインストールして、Bitcoinの環境を構築する

# はじめに
Macにbitcoindとbitcoin-cliをインストールする
ソースは[GitHub](https://github.com/bitcoin/bitcoin)に公開されている。
```master```ブランチではなく、最新のtagからソースをpullすることを推奨します。

今回は、```v0.21.1```が最新バージョンです(2021/6現在)。

- BitcoinのAPIは```JSON-RPC```で定義されている。
 - [Bitcoin Core RPC](https://bitcoincore.org/en/doc/)
 - [RPC API Reference](https://developer.bitcoin.org/reference/rpc/)   
- ```bitcoindは```、RPCサーバーとして動作するエンドポイントである。
- ```bitcoin-cli```はコマンドラインからbitcoindを操作するツールである。

# 手順
1.  Macのコマンドラインツールをインストールする

    ```
    xcode-select --install
    ```

1.  依存ライブラリをインストールする

    ```
    brew install automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf python qt libevent qrencode
    ```

2.  gitからソースをpullする

    ```
    git clone https://github.com/bitcoin/bitcoin.git -b v0.21.1
    ```

3.  ビルド・インストールを実行する

    ```
    ./autogen.sh
    ./configure
    make -j8
    sudo make install -j8
    ```

    ※ makeおよびmake installは```-j ${コア数 x 2}```オプションにてジョブ数の指定ができ、高速化が可能。

4.  バージョンを確認する

    ```
    $ bitcoind -version
    Bitcoin Core version v0.21.1
    Copyright (C) 2009-2020 The Bitcoin Core developers
    ```


# 参考
- [MacにBitcoindをインストールしてテスト送金をしてみる](https://qiita.com/ryo-ohnishi/items/f7404c7e71358f8c8e16)
pandasで列同士の値を比較して新たなフラグ列を作る

#A列の値とB列の値を比較し、その大小関係を0/1で表す

```python
import pandas as pd

df_t = pd.DataFrame({'登録日': ['2021-04-11','2021-06-09','2021-08-15','2021-08-18','2021-09-02','2021-09-10']
                    ,'商品名': ['A', 'B', 'B','C', 'C', 'A'] 
                    ,'配送先': ['東京', '愛知', '兵庫','宮城', '大阪', '静岡']
                    ,'基準日': ['2021-05-11','2021-08-11','2021-08-11','2021-09-02','2021-09-02','2021-05-11']
                    })

print(df_t)
#      登録日    商品名 配送先  基準日
# 0  2021-04-11   A   東京  2021-05-11
# 1  2021-06-09   B   愛知  2021-08-11
# 2  2021-08-15   B   兵庫  2021-08-11
# 3  2021-08-18   C   宮城  2021-09-02
# 4  2021-09-02   C   大阪  2021-09-02
# 5  2021-09-10   A   静岡  2021-05-11
```

例えば上のように、商品ごとの売上記録があるとします。
そして、データの「登録日」が「基準日」より前の記録は何件あるか？ということが知りたいとします。
そんな時は、両方の列を比較し、

・ 登録日が基準日よりも前なら1
・ 後なら0

を格納する列(例:'flg')を新たに作り、その列の合計を取得すればいいです。(もっとスマートなやり方があるかもですが)
このflg列を作るコードは以下。

```python
df_t.loc[df_t['登録日'] < df_t['基準日'], 'flg'] = 1
df_t.loc[df_t['登録日'] >= df_t['基準日'], 'flg'] = 0
df_t
```
結果：

	|登録日|	商品名|	配送先|	基準日|	flg
|:-:|:-:|:-:|:-:|:-:|:-:|
0|	2021-04-11|	A|	東京|	2021-05-11|	1.0
1|	2021-06-09|	B|	愛知|	2021-08-11|	1.0
2|	2021-08-15|	B|	兵庫|	2021-08-11|	0.0
3|	2021-08-18|	C|	宮城|	2021-09-02|	1.0
4|	2021-09-02|	C|	大阪|	2021-09-02|	0.0
5|	2021-09-10|	A|	静岡|	2021-05-11|	0.0

「登録日」が「基準日」より前の記録件数は

```python
df_t['flg'].sum()
# 3.0
```
#追記：
ありがたいことにコメントをいただいたのですが、

```python
df_t.assign(flg=df_t['登録日'] < df_t['基準日'])
```
や

```python
df_t.eval('flg = 登録日 < 基準日')
```

といったコードでもflg列は作れます。この場合、

	|登録日|	商品名|	配送先|	基準日|	flg
|:-:|:-:|:-:|:-:|:-:|:-:|
0|	2021-04-11|	A|	東京|	2021-05-11|	True
1|	2021-06-09|	B|	愛知|	2021-08-11|	True
2|	2021-08-15|	B|	兵庫|	2021-08-11|	False
3|	2021-08-18|	C|	宮城|	2021-09-02|	True
4|	2021-09-02|	C|	大阪|	2021-09-02|	False
5|	2021-09-10|	A|	静岡|	2021-05-11|	False

というように、flg列は1/0ではなく True/Falseになりますが、この場合でも

```python
df_t['flg'].sum()
# 3.0
```

を実行してもきちんと和がでます。"1/0　と True/Falseは等価"ということは知りませんでした。
お恥ずかしい..
Pythonで特定の文字列で挟まれた文字列を取得する方法

## はじめに
Pythonでデータ分析をするときに使いたかったのですが，調べてもあまり出てこなかったのでメモです。

## 実装
Pythonの正規表現を用いて実装します。

```python
import re
origin_str = "ABCDEFG"
# ABとFGで挟まれた文字列を取得する
new_str = re.search(r'AB(.+)FG',origin_str).group(1)
print(new_str)
>>> CDE
```
最後のgroup()で，挟む文字列自身(今回ではABとFG)を含むかどうかを選択できます

```python
# group(0)  挟む文字列自身を含む
str1 = re.search(r'AB(.+)FG',origin_str).group(0)
# group(1)  挟む文字列自身を含まない
str2 = re.search(r'AB(.+)FG',origin_str).group(1)
print(str1)
>>> ABCDEFG
print(str2)
>>> CDE
```

## おわりに
ログファイルを解析するスクリプト等を作るときに役立ちました。
Android Studio使ってFlutter開発のコツ

![0_s7vGN34hz5jJUYTm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/a6bd7cda-463f-7531-2987-cd144a900d14.png)
- ショートカット
- 自動補完
- フォーマットの自動化
- コードの抽出

## ショートカット

Android Studio + Macの例:


#### widgetを作る: dartファイルにstf、もしくはstlを入力後 + return
![F57600F1-D8F7-42CD-9202-84E6D729ADED_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/8ef58613-9ec7-dee1-c2f9-b01978d9d184.jpeg)

#### コード修正: option + return
![1FE02787-DA56-40B5-B12B-6C6E14AF563C_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/72708382-b512-a03c-96eb-9d11affbd00e.jpeg)

#### 親Widgetの追加: option + return
![1BEE6E00-5908-479E-945F-C5DEC3A06250_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/8c34f7e2-bb61-32a3-fc86-c3615bfddc11.jpeg)

#### 最近開いたファイル一覧: command + E

![A9AAC919-DD5D-4F25-BD32-76FE1C2984A0_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/19814948-8bf9-3aad-7990-c38271ea7fa4.jpeg)

>Windowsの場合は、commandをCtrl、optionをAltに置き換えて使ってください。

## 自動補完
Android StudioのPluginの中で`Flutter Snippets`を検索してインストール:

![6E94EF31-30E5-4D85-A366-91F1EAF06BC9.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/b0151215-44bf-44d1-f5c9-037275ab94af.jpeg)

インストール後、Android Studioはメジャーなコード補完やってくれます。

[Flutter Snippets使用説明](https://github.com/georgeherby/flutter-snippets/blob/master/README.md)

## フォーマットの自動化

`Android Studio` -> `Preferences`->`Languages&Frameworks`->`Flutter`を開いていき
`Format Code on Save`にチェックを入れて、また`Organize imports on save`にチェック入れれば、使われてないimportを自動削除してくれます。
![6D4DE2C4-EE3C-4E5D-A571-986D71033607.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/bcaf2811-231f-7e29-f60c-f1eb081d149f.jpeg)

## コードの抽出
複雑そうなwidgetでダブルクリック、`Refactor`->`Extract Method`、ネーミングしたら自動的に関数化してくれます。
![5AEF9786-6667-42AA-8C2A-B74789EC9A4B.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/36973499-d57a-8b0c-1de3-9a5aafaf4cae.jpeg)
[解決済み] php:*-alpine のdocker buildで、`make: /bin/sh: Operation not permitted` エラーが発生する

## はじめに（何が問題か）
以下のような`Dockerfile`をビルドすると、

```Dockerfile
FROM php:7.4-cli-alpine

RUN set -ex \
  && apk --no-cache add \
    autoconf gcc g++ make libzip-dev git

RUN docker-php-ext-install zip pdo pdo_mysql opcache
```

以下のようなエラーが発生して失敗するようになりました。

```
creating libtool
appending configuration tag "CXX" to libtool
configure: patching config.h.in
configure: creating ./config.status
config.status: creating config.h
/bin/sh /usr/src/php/ext/zip/libtool --mode=compile cc  -I. -I/usr/src/php/ext/zip -DPHP_ATOM_INC -I/usr/src/php/ext/zip/include -I/usr/src/php/ext/zip/main -I/usr/src/php/ext/zip -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib  -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H  -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64   -c /usr/src/php/ext/zip/php_zip.c -o php_zip.lo 
make: /bin/sh: Operation not permitted
make: *** [Makefile:192: php_zip.lo] Error 127
The command '/bin/sh -c docker-php-ext-install zip pdo pdo_mysql opcache' returned a non-zero code: 2
```

## 原因
以下の記事にもありますが、`alpine3.14`で問題があったようです。

- [alpine3.14でdocker build失敗した話](https://qiita.com/Ohtak/items/ce2448cadc873b392485)
- [Docker PHP 7.4 alpine build (php:7.4-cli-alpine) fails src/php7/igbinary.lo Error 127 (/bin/sh: Operation not permitted) · Issue #333 · igbinary/igbinary](https://github.com/igbinary/igbinary/issues/333)

`2021-06-30`頃に下記のプルリクがマージされ、`alpine`の`latest`が`3.14`となり、エラーが発生していた模様です。

- [Add Alpine 3.14 by J0WI · Pull Request #1166 · docker-library/php](https://github.com/docker-library/php/pull/1166)

## 回避策
前述の`issue`にも記載がありますが、下記のように`alpine3.13` を明示することでエラーを回避できます。

```Dockerfile
FROM php:7.4-cli-alpine3.13
```

## おわりに
`alpine`以外の例えば、`php:7.4-fpm`とかではエラーが出ていなかったので、`alpine`固有の問題だと睨んでググりましたが、予想的中しました。 　
同じ問題にハマっている方の手助けになれれば幸いです。 　
ではでは。
エラー Exception: DateTime::__construct(): Failed to parse time string ～でLaradockの人はコンテナのTZの確認をした方が良い話

タイトルがすべてです。
こんなエラーがでた

```
Exception: DateTime::__construct(): Failed to parse time string (release_start) at position 0 (w): The timezone could not be found in the database
```

解決策を検索…

参考URL：[https://www.out48.com/archives/1849/](https://www.out48.com/archives/1849/)

## **修正方法**

①**php.ini**の内容を以下に書き換える。

```
date.timezone = Asia/Tokyo
```

②**date_default_timezone_set()**関数を事前に呼び出す。

```
date_default_timezone_set('Asia/Tokyo');
```

普通の解決方法であれば①だなあとapp内に確認しにいったら、設定はされているがエラーがでていた。
②をやってみたらできた。でも「①で解決したいんだ！」と調べていたらこちらにたどり着きました。

## laradockのコンテナはデフォルトでUCT

この差異が今回のエラーの原因では？と思い確認してみました。

公式：[https://laradock.io/documentation/#Change-the-timezone](https://laradock.io/documentation/#Change-the-timezone)

まずコンテナ内で確認。

```
laradock@245dec687749:/var/www$ date
Thu 01 Jul 2021 02:05:46 AM UTC
```

UCTでした。

docker-composeを変更する。

laradock/docker-compose.yml

```
workspace:
      build:
        context: ./workspace
        args:
					(省略)
          - TZ=Asia/Tokyo
```

再ビルドする

```
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Starting laradock_mysql_1            ... done
Starting laradock_docker-in-docker_1 ... done
Recreating laradock_workspace_1      ... done
Recreating laradock_php-fpm_1        ... done
Recreating laradock_nginx_1          ... done

$ docker-compose exec --user=laradock workspace bash
laradock@b55f23b3c40c:/var/www$ date
Thu 01 Jul 2021 11:18:27 AM JST
laradock@b55f23b3c40c:/var/www$
```

再度確認するとJSTになっていました。

そしてエラーも解決しました。

## 結論

Exception: DateTime::__construct(): Failed to parse time string が出るかつ、Laradock使用の人は、今後の予期せぬエラーを防ぐためにコンテナのTZの確認をした方が良いよというお話でした。
AtCoderログ：0007 - ABC 208 A

# 問題

https://atcoder.jp/contests/abc208/tasks/abc208_a

## 問題文
> $1,2,\dots,6$ の出目がある $6$ 面サイコロを $A$ 回振ったとき、出た目の合計が $B$ になることはありますか？

## 制約
> ・$1 \le A \le 100$
> ・$1 \le B \le 1000$
> ・$A,B$ は整数である。

# 回答
## 回答1 (AC)
サイコロを $1$ 回振ったときの出目は $1$ 以上 $6$ 以下なので、$A$ 回振ったときの出目は $A$ 以上 $6A$ 以下となります。従って、サイコロを振る回数を a 回、出目の合計を b とするとき、b が出目の合計としてあり得るための条件は a<=b かつ b<=6*a となり、これを判定すれば良いことがわかります。コードは以下のようになり、無事、ACとなりました。なお、私が ABC 208 に参加したときの[提出コード](https://atcoder.jp/contests/abc208/submissions/23955386)も同じ方針で作成しました。

```C++:abc208a.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int a, b;
  cin >> a >> b;
  
  if ( a<=b and b<=6*a ) {
    cout << "Yes" << endl;
  } else {
    cout << "No" << endl;
  }
}
```

## おまけ
$B$ が出目の合計値としてふさわしいとき、具体的な目の出方(の一例)を求めます。サイコロは $A$ 回振ったので、$B$ を $A$ で割った商を $q$, 余りを $r$ とおく (つまり $B=Aq+r~(0 \le r <A)$ ) とおくと、毎回の目を $q$ とすると合計値は $r$ だけ不足します。そこで、目 $q+1$ が $r$ 回、目 $q$ が $A-r$ 回出れば、出目の合計は $(q+1)r+q(A-r)=qr+r+qA-qr=r+qA=B$ となります。
例えば $A=4, B=23$ の場合、$23=4\times5+3$ なので、$q=5, r=3$ であり、$5, 5, 5, 4, 4$ という出目のパターンを得ることができます。

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc208/tasks/abc208_a/editorial) → [公式解説](https://atcoder.jp/contests/abc208/editorial/2186)
回答と同じ方針でした。

# リンク
## ABC 208 関連情報
- [AtCoderログ：0006 - ABC 208 に参加しました](https://qiita.com/RoadLynton/items/029fb11fa9b5bbfd95ce)
- [AtCoderログ：0008 - ABC 208 B](https://qiita.com/RoadLynton/items/a918cc88a954c325920b)
- [AtCoderログ：0009 - ABC 208 C](https://qiita.com/RoadLynton/items/7e7a580ae843e60f8b2f)

## 前後の記事
- 前の記事 → [AtCoderログ：0006 - ABC 208 に参加しました](https://qiita.com/RoadLynton/items/029fb11fa9b5bbfd95ce)
- 次の記事 → [AtCoderログ：0008 - ABC 208 B](https://qiita.com/RoadLynton/items/a918cc88a954c325920b)
AtCoderログ：0006 - ABC 208 に参加しました

この記事は 2021年07月04日(日)21:00-22:40 に開催された [AtCoder Beginner Contest 208 (ABC 208)](https://atcoder.jp/contests/abc208) に参加した記録です。

https://atcoder.jp/contests/abc208

#  結果
- 得点：600
- 時間：53:43 (= 48:43 + 05:00 × 1)
- 順位：4776 / 8444
- パフォーマンス：466　
- レーティング：23 (初参加, 暫定)
- 段級位：14級

![abc208.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/369855cc-0573-fc6d-6b54-6ec17efaeff3.png)

# 詳細
|問題|得点|時間|提出コード|復習|
|:--:|:--:|:--:|:--:|:--:|
|[ABC 208 A](https://atcoder.jp/contests/abc208/tasks/abc208_a)|100|04:19|[○](https://atcoder.jp/contests/abc208/submissions/23955386)|[AtCoderログ：0007](https://qiita.com/RoadLynton/items/ea6a30e973f6af51831c)|
|[ABC 208 B](https://atcoder.jp/contests/abc208/tasks/abc208_b)|200|16:00|[○](https://atcoder.jp/contests/abc208/submissions/23966193)|[AtCoderログ：0008](https://qiita.com/RoadLynton/items/a918cc88a954c325920b)|
|[ABC 208 C](https://atcoder.jp/contests/abc208/tasks/abc208_c)|300|48:43 (1)|[○](https://atcoder.jp/contests/abc208/submissions/23978751)|[AtCoderログ：0009](https://qiita.com/RoadLynton/items/7e7a580ae843e60f8b2f)|
|[ABC 208 D](https://atcoder.jp/contests/abc208/tasks/abc208_d)|400|---|---|---|
|[ABC 208 E](https://atcoder.jp/contests/abc208/tasks/abc208_e)|500|---|---|---|
|[ABC 208 F](https://atcoder.jp/contests/abc208/tasks/abc208_f)|600|---|---|---|

# 感想
- 初めての参加でしたが、A, B, C を解くことができました。まずまずの結果だったと思っています。
- A は、一瞬、難しいように感じたのですが、終わってみれば簡単でした。何で難しいと思ったんだろうか。
- B もちょっと考えてしまいましたが、硬貨の枚数が100枚と潤沢だったため、素直に考えれば良かったのでした。
- C は国民IDから番号への逆引きをどうやって実装するかに悩んでしまい、C++ の map を調べながらコーディングしたため、かなりの時間を使ってしまいました。
- D 以降は全く歯が立たなかったのですが、解答例を読んでも理解できませんでした。
- 当面は A, B, C を完答した上で、D に解答できることを目指していきたいです。

# リンク
## ABC 208 関連情報
- [AtCoderログ：0007 - ABC 208 A](https://qiita.com/RoadLynton/items/ea6a30e973f6af51831c)
- [AtCoderログ：0008 - ABC 208 B](https://qiita.com/RoadLynton/items/a918cc88a954c325920b)
- [AtCoderログ：0009 - ABC 208 C](https://qiita.com/RoadLynton/items/7e7a580ae843e60f8b2f)

## 前後の記事
- 前の記事 → [AtCoderログ：0005 - ABC 157 A](https://qiita.com/RoadLynton/items/a5e26129389ea71f06c6)
- 次の記事 → [AtCoderログ：0007 - ABC 208 A](https://qiita.com/RoadLynton/items/ea6a30e973f6af51831c)
linux chownコマンドでファイルのオーナーとグループを変更する

# 目的

- linuxにてターミナルでファイルやディレクトリのオーナーとグループを変更する方法をメモ的にまとめる

# 方法

- 下記コマンドを実行する。（グループ名は設定しなくてもOK）

    ```terminal
    $ sudo chown オーナー名:グループ名 ファイル名
    ```
[Rails]hidden_field_tag とf.hidden_fieldの違い

#はじめに
Railsを使っていて`hidden_field`と`hiddn_field_tag`の違いについて学んだので備忘録として残しておきます

```
<%= hidden_field_tag :message, @user.message %>
<%= f.hidden_field_tag :message, :value => @user.message %>
```

## 環境
ruby 2.6.3
rails 6.0.3

## 本題
コントローラーで保持しているパラメータ(user_idなど)を次のアクションに渡したいときに使うのが`hidden_field`と`hiddn_field_tag`ですがこの２つは使い勝手が少し変わります。

####1. hidden_field_tag 

```
<%= hidden_field_tag :message, @user.message %>
```

上記のコードではmessageというパラメータに@user.massageの情報を渡します。
サーバーで送ったパラメータを確認すると以下のようになっています。

```
Parameters: {"authenticity_token"=>"jLrZNeJ+oz7RT6sKuiHe/LoEdcY6hWx9zmx3mx6xXpzhxbh0VtgiVk0c2mMfi3654mkAB1mQTVkwH0lm5KO8Kw==","message"=>"hello", "commit"=>"メッセージ"}
```

`"message"=>"hello"`のようにパラメータが送られているのがわかります。
この受け取ったパラメータを利用したいは`params[:message]`のようにすると中身を参照できます。

####2. f.hidden_field
`f.hidden_field`の場合は書き方が少し特殊になります。

```
 <%= form.hidden_field :message, value: @user.message %>
```
上記のように`value`の続きに渡したい要素を指定します。

サーバーに送られたパラメータを確認すると以下のようになっています。

```
Parameters: {"authenticity_token"=>"jLrZNeJ+oz7RT6sKuiHe/LoEdcY6hWx9zmx3mx6xXpzhxbh0VtgiVk0c2mMfi3654mkAB1mQTVkwH0lm5KO8Kw==","users"=>{"message"=>"hello"}, "commit"=>"メッセージ"}
```
`"users"=>{"message"=>"hello"}`のようにパラメータが送られています。
このパラメータを利用したい場合は`params[:user][:message]`のように記述することで利用できます。

##参考

https://api.rubyonrails.org/
こんなパスワード変更画面は嫌だ

ここ数日、自分が管理している多数のアカウントの整理をしていまして、（本当はよくないことですが）使い回してるパスワードがわりとあったので、そういったパスワードを撲滅すべく変更をしては1Passwordに反映するということを繰り返していました。
そんな中で出会ったこれは嫌だなというパスワード変更画面を紹介したいと思います。

1. 画面構成が複雑でパスワード変更画面にたどり着けない。
1. パスワード変更機能がなく、「変更及び再発行を希望される際は、再度新規登録をお願いいたします」と促される。
1. パスワードリセット機能（パスワードを忘れた方はこちら）がパスワード変更機能を担っているが、そんな説明がどこにもないので気づかない。
1. パスワードリセット機能もない。
1. 最大文字数が「6文字以内」と短い。
1. 「6文字以上で入力してください」と書かれているので試しに6文字で登録しようとすると「8文字以上で入力してください」とエラーになる。（placeholder属性の説明とエラーメッセージの説明が異なる）
1. 「8文字以上で入力してください」と書かれているので32文字で登録しようとすると「20文字以内で入力してください」とエラーになる。（入力可能な最大文字数が事前にわからない）
1. 「8文字以上で入力してください」と書かれているので8文字以上で英数字に記号も混ぜて登録しようとすると「記号は入力できません」とエラーになる。（入力可能な文字種別が事前にわからない）
1. 「英数字で入力してください」と書かれているが実は記号も入力可能。（入力可能な文字種別が事前にわからない）
1. 32文字で入力して特にエラーも発生せず変更が完了したと思ったら、入力欄に「maxlength="20"」が設定されていて1Passwordに保存したパスワードと文字長が異なりログインできなくなる。
1. パスワード変更画面では「maxlength="40"」が設定されていて32文字で入力して特にエラーも発生せず変更が完了したと思ったら、ログイン画面の入力欄に「maxlength="30"」が設定されていてログインできなくなる。（変更画面とログイン画面のmaxlengthの値が異なる）
1. 変更ボタンを押すと「利用できない文字があります」と表示され、どの文字が利用不可なのかがわからない。（入力可能な文字種別が事前にわからない）
1. 変更ボタンを押すと「ご登録のメールアドレスに確認のメールを送りました」と表示されるがメールが届かずパスワード変更が完了しない。
1. パスワード入力欄に並んでパスワード確認入力欄があり、パスワード確認入力欄だけコピペできないように制御されている。
1. 記号入力可能なパスワード入力欄に「,」を含むパスワード文字列を入力すると、パスワード入力欄とパスワード確認入力欄の値が一致していても「パスワードが一致しません」と表示され、なぜ一致していないのかがわからない。
enumerate

#enumerate関数
enumerateはリストの要素と添字を取り出すことができる。
繰り返し文などで使う。

for 変数１、変数２　in enumerate(リスト名)：
変数1には１添字、変数２には要素が入る。
例

```python
sample_list = ['アメリカ','イギリス','中国','日本']

for num,name in enumerate(sample_list):
  print(str(num) + name)
```

実行結果

```python
0アメリカ
1イギリス
2中国
3日本
```
【Rails】セレクトボックスの設置の仕方

####My Profile
プログラミング学習歴②ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。　



#対象者
　
・セレクトボックスを表示させたい方

#手順目次
1.select_tagを入力する

2.options_for_selectも入力する


#実際の手順と実例
###1.select_tagを入力する

そもそもselect_tagとは選択をする項目表示のメソッドです。

`````
select_tag "name" , options_for_select({}) 
`````

このように書きます。
name部分がparams ->値を拾うための文字列が入ります。

次でoptions_for_selectについて説明します


###2.options_for_selectも入力する

上記のメソッドもいれると、、、、、

````````
<%= select_tag "model", options_for_select({ "---Please choose---" => "" , "User" => "user" , "Book" => "book"})%>
`````````

選択項目の数をどんどん増やせるのでおすすめです！！
PhpSpreadsheetでセルにパーセンテージの書式設定をしたい

タイトルのとおり。少しハマったので備忘録と、困ってる人が他にもいたら。
PHP`8.0.8`, PhpSpreadsheetのバージョンは`1.18`です。

## はじめに

`->setCellValue()`すれば値の書き込みはできるんですが、デフォルトではすべてが文字列として埋め込まれるので、例えばstringの`5.5%`を埋め込むと、こういう警告が出ます。
![スクリーンショット 2021-07-05 21.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854172/43401c9b-5832-d668-cb97-c13a24b888ea.png)

これを抑制するため、書式設定しつつ値を書き込みたい。

## 結論

どう書けばいいのかだけを知りたい方へ。
セルの場合はこう。
`setCellValue()`の第2引数は`* 100`とかせず、小数のまま渡しましょう。

```php
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

class ExcelService {
    public function writePercentageInSheet(Worksheet $sheet): void
    {
        $sheet->getStyle('A1')
            ->getNumberFormat()
            ->setFormatCode(NumberFormat::FORMAT_PERCENTAGE_00); // 0.00%
        $sheet->setCellValue('A1', 0.582); // 58.2%
    }
}
```

公式ドキュメントにもレシピがあった。解決後に気づいた。
https://phpspreadsheet.readthedocs.io/en/latest/topics/recipes/#number-formats

## 何をしてるのか

コードの意味を理解したい人へ。

![スクリーンショット 2021-07-05 20.55.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854172/1b235de9-92f1-6b81-80c7-59d029336ee7.png)

↑のようなユーザー定義の書式設定をコードでやっている感じ。セルを右クリックして「セルの書式設定」で出てくるやつですね。
`getNumberFormat()`でセルの書式設定オブジェクトを取得し、`setFormatCode()`で設定する。
`PhpOffice\PhpSpreadsheet\Style\NumberFormat`クラスに定義されてるコードはあくまでプリセットなので、自由にコードを設定できるはず。たぶん。

https://support.microsoft.com/ja-jp/topic/excel-%E3%81%AE%E3%82%BB%E3%83%AB%E3%81%AE%E8%A1%A8%E7%A4%BA%E5%BD%A2%E5%BC%8F%E3%81%A7-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%AE%9A%E7%BE%A9-%E3%81%AB%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D%E3%82%8B%E6%9B%B8%E5%BC%8F%E8%A8%98%E5%8F%B7%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-979767bb-6635-c0f5-5e7f-32c69715ccfa

あんま凝りすぎると正規表現みたいに秘伝のタレ化しそうなので、なるべく`NumberFormat`クラスの定数で済ませましょう。

https://github.com/PHPOffice/PhpSpreadsheet/blob/master/src/PhpSpreadsheet/Style/NumberFormat.php

## 参考

この記事のおかげで`getNumberFormat()`や`setFormatCode()`の存在に気づけました。あざす！

https://ariarijp.hatenablog.com/entry/2017/08/24/093000

## さいごに

Excelはつらい。
[Jest useFakeTimers] setTimeout＋Promiseをテストする

あれは遥か太古、時間にすればおよそ数時間前のこと。

私は宗教上の理由でsetTimeoutとpromiseを組み合わせて使う事になったのだが、テストがうまく書けなくて詰んでいた。

まさかJestに問題があるとは思わず、自分のコードの粗探しを必死に行ったものの、見つからないどころか画面で確認したら正しく動いていた。

ググってみるとこんな[Issue](https://github.com/facebook/jest/issues/7151)が見つかり、一度は諦めたが、テストが書けないのがツラすぎて再挑戦した。

そして[Stack Overflow](https://stackoverflow.com/questions/52177631/jest-timer-and-promise-dont-work-well-settimeout-and-async-function?noredirect=1&lq=1)にて神を見た。

神は「`await Promise.resolve();`あれ」と言われた。すると動いた。

```js
jest.useFakeTimers();

describe('FakeTimers with Promise', () => {
  it('does not work', () => {
    let called1 = false;
    let called2 = false;
    setTimeout(async () => {
      called1 = true;
      await Promise.resolve();
      called2 = true;
    }, 0);

    jest.runAllTimers();

    // なんと、called1しかtrueではない。
    expect(called1).toBeTruthy();
    expect(called2).toBeFalsy();
  });

  it('will work', async () => {
    let called1 = false;
    let called2 = false;
    setTimeout(async () => {
      called1 = true;
      await Promise.resolve();
      called2 = true;
    }, 0);

    jest.runAllTimers();

    // ここが味噌。
    await Promise.resolve();

    // どちらもtrueになっている。
    expect(called1).toBeTruthy();
    expect(called2).toBeTruthy();
  });
});
```

あーめｎ
Copilotが色々物議を醸しているのでまとめてみた

#プログラマーの声はこちらから


http://techtweetrank.short-tips.info/page/github/data_loading.html


いろんな意見が転がっていて面白かった。
githubのランキングのはずなのになぜかcopilotが中心で面白い笑


#追加

あまりにも人気だったので専用タグを作りました。

http://techtweetrank.short-tips.info/page/copilot/ranking.html