OmniAICreator/Qiita-1.07M huggingface dataset:
Collectors#toList(), toSet(), toMap()

Collector classを生成する
toList()  streamの各要素としたListをreturnするCollectorを生成
toSet()   streamの各要素としたSetをreturnするCollectorを生成
toMap()   streamの各要素をFunctionで加工したkey, mapをMapとしてreturnするCollectorを生成
```java
class Value {
    int price;
    String name;

    public Value(int price, String name) {
        this.price = price;
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public String toString() {
        return "price:" + price + " name:" + name;
    }
}
public class Outer {
    public static void main(String[] args) {
        List<Value> l = Arrays.asList(
                new Value(1,"andy"),
                new Value(2,"john"),
                new Value(3,"laula"),
                new Value(4,"miki"),
                new Value(5,"sally"));
        Stream<Value> st = l.stream();
        List<Value> l2 = st.collect(Collectors.toList());
        l2.forEach(System.out::println);
        System.out.println("----------------------------");
        st = l.stream();
        Set<Value> s = st.collect(Collectors.toSet());
        s.forEach(System.out::println);
        System.out.println("----------------------------");
        st = l.stream();
        Map<String, Value> mp = st.collect(Collectors.toMap(
                Value::getName,
                b -> b));
        mp.keySet().stream().forEach(System.out::println);
        mp.keySet().stream().forEach(a -> System.out.println(mp.get(a)));
    }
}
```
```
price:1 name:andy
price:2 name:john
price:3 name:laula
price:4 name:miki
price:5 name:sally
----------------------------
price:3 name:laula
price:1 name:andy
price:2 name:john
price:4 name:miki
price:5 name:sally
----------------------------
miki
sally
john
laula
andy
price:4 name:miki
price:5 name:sally
price:2 name:john
price:3 name:laula
price:1 name:andy
```
paizaラーニング レベルアップ問題集 二分探索メニュー応用編 JavaScript 連番

連番 (paizaランク A 相当)

https://paiza.jp/works/mondai/binary_search_advanced/binary_search_advanced__sequential

# 解答例(C++の場合参考)
連番の最大の長さで二分探索する。
正整数列 A = (A_1, A_2, ..., A_N) を先頭から順に見ていく。
cnt は現在見ている連番の長さ,sum はとりだした連番の個数として、
cntがmid以上になったら、とりだす。cntをリセットする。
また、Aの最後の要素でない、かつ、連番でないならば、cntをリセットする。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [n, k] = lines[0].split(" ").map(Number);
const a = lines[1].split(" ").map(Number);

//連番の最大の長さで二分探索
let [left, right] = [1, n + 1];
while (right - left > 1) { //連番の長さは整数なので１以下になれば良い
  const mid = Math.trunc((left + right) / 2);//連番の最大の長さ
 
  //cnt は現在見ている連番の長さ,sum はとりだした連番の個数
  let [cnt, sum] = [0, 0];
  //Aの要素を順番に見ていく
  for (let i = 0; i < n; i++) {
    cnt++;//Aのi要素を見る
    if (cnt >= mid) { //現在見ている連番の長さが最大mid以上になったら、とりだす
      sum++; //とりだす
      cnt = 0; //とりだしたらリセット
    }
    /*今見てる要素が最後なら、リセット、または、次が連番でないなら、リセット
    →今見てる要素が最後でない、かつ、次が連番でないなら、リセット*/
    if (i !== n - 1 && a[i] + 1 !== a[i + 1]) { 
      cnt = 0; //連番カウントリセット
    }
  }
  
  //切り出した数列の個数がK以上なら長く
  if (sum >= k) { 
    left = mid;
  } else { 
    right = mid;
  }
}
console.log(left);
```

# 解答例(Python3の場合参考)
k以上か判定する関数checkを定義。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [n, k] = lines[0].split(" ").map(Number);
const a = lines[1].split(" ").map(Number);

//長さxの連番の合計が K 以上の時は true，小さいときは false を返す
const check = x => {
  let cnt = 0;
  let sum = 0;
  for (let i = 0; i < n; i++) {
    cnt += 1;
    if (cnt >= x) {
      sum += 1;
      cnt = 0;
    }
    if (i !== 1) {
      if (a[i] + 1 !== a[i + 1]) {
        cnt = 0;
      }
    }
  }
  if (sum < k) {
    return false;
  } else {
    return true;
  }
};

//連番の最大の長さで二分探索
//leftは常に条件を満たす，rightは常に条件を満たさない
  let [left, right] = [1, 1 << 47];
while (right - left > 1) { //連番の長さは整数なので１以下になれば良い
  const mid = Math.trunc((left + right) / 2);//連番の最大の長さ
 
  //切り出した数列の個数がK以上か
  if (check(mid)) { 
    left = mid;
  } else { 
    right = mid;
  }
}
console.log(left);
```
自分の書いたコードを自分でレビューする効果的な 3 つの方法【個人開発にも使える】

みなさんは自分の書いたコード、どうやって見直してますか？ :pencil2:

自分で書いたコードの間違いや改善点を見つけ出すのは難しいものです :thinking: 
社内にレビュアーがいればいいですが、いない場合や、個人開発している場合などはなかなか時間が割けないことも・・・
自分自身の知見には限りがありますし、固定観念などが入ってしまうこともあります :cry:

でも、他人の書いたコードの改善点は意外と見つけやすかったりしないでしょうか？
私のつたない経験上ですが、自分のコードよりも明らかに数がたくさん見つかる気がするのです。

ならば **自分の書いたコードが他人の書いたコードに見えればいいんじゃないでしょうか？**
ということで、この記事では自分の書いたコードが他人の書いたコードに見えるために私が実践していることをご紹介します。

:::note info
個人開発などでは、個人の書いたコードをレビューするような C to C のサービスも選択肢に入ってきます。そちらも合わせてご検討ください。
:::

## 1. コードを書いた後、数日空けてからもう一度見る

時間と記憶に対する有名な研究で、「エビングハウスの忘却曲線」というものがあります。
それによれば、人間は学習したときから 1 週間経過すると、約 77 % 忘れてしまうとのこと。

https://keiei-shinri.or.jp/word/%E3%82%A8%E3%83%93%E3%83%B3%E3%82%B0%E3%83%8F%E3%82%A6%E3%82%B9%E3%81%AE%E5%BF%98%E5%8D%B4%E6%9B%B2%E7%B7%9A/

自分でコードを書いてから数日空けると、何を書いたか忘れていることが多いので、ある意味他人です。
他人の視点、新たな視点を持ってコードを見直すことができるかもしれません。

私はこれを **冷凍保存** と呼んでいます :snowflake: 
冷凍した物を忘れても、冷凍したことくらいは覚えておきましょう :fried_shrimp:

## 2. 寝て起きてからもう一度見る

コードを書いたら、個人開発だからと言って直ぐにリリースしたりせず、一旦寝ます。
行き詰ったところで切り上げて寝ます。
で、翌朝起きたらもう一度コードを見ます。

寝ている間に記憶が定着・整理され、翌朝には脳の領域に余裕がある状態でコードを見ることができます！
前の日いくら考えてもわからなかったことが一瞬で解決することもあります！ :star2:

私はこれを **熟成** と呼んでいます :meat_on_bone: 
案件をこなす上でこの方法には幾度となく助けられてきました。

ベテランエンジニアの方の中には、仕事中に寝てこの効果を享受している人もいるんだとか・・・
（ただし、これをマネージャー層に理解してもらうのは非常に難しいので、自己責任でお願いします）

## 3. 別の UI 上で自分の書いたコードを見る

例えば、

いつも使い慣れているエディタではこんな感じの見た目で・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486784/da83e13a-00bc-cfff-614e-5cbbc7bef2dd.png)

GitHub 上ではこんな感じの見た目で・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486784/54bfcf8b-9f27-ccf4-6e56-098c81e48015.png)

背景色や画面の配置、フォントなどが違うと、印象も異なります。
それによって目線の誘導のされ方が変わるかもしれません。

自分でイシューを作成し、プルリクエストを作成し、見てみるのもおすすめです。

私はこれを **イメチェン** と呼んでいます :girl: 
知り合いの女の子がイメチェンしてきたら、今まで気づかなかった良さに気づくこともありますよね！ :laughing: 
そういうことです。

:::note alert
スクリーンショット中のコードは良くないコードです！
あまりジロジロ見ないでください！ :cop: :police_car: 
:::

---

よろしければ参考にしてみてください。
みなさんのコーディングライフに幸多からんことを :pray:
OPTIONSリクエスト

## はじめに
httpリクエストには8つのメソッドがある。
![RFC7231 ４章](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877395/fe62f700-ab82-e014-789e-de4876f9e4e4.png)
※[RFC7231 ４章](https://httpwg.org/specs/rfc7231.html#methods)より
※リクエストメソッド自体はRFC2616 5章で定義→RFC7231 ４章で改訂→RFC9110 9章で改訂されている。

日頃自分たちで実装するのはGET,POST,PUT,DELETEたまにHEADくらい。

自分はCONNECT, OPTIONS, TRACEあたり使ったことない。
なんとなく眺めていて、 _OPTIONSちょっとおもろいな_ と思ったので叩いてみるなどした。

## なにもの？
[RFC9110 9.3.7](https://www.rfc-editor.org/rfc/rfc9110#section-9.3.7) で定義されている。

> The OPTIONS method requests information about the communication options available for the target resource, at either the origin server or an intervening intermediary. This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action.

ざっくりいうと
* どういう通信オプションを使ってリクエストを投げれるのかの情報を知れるよ
* 情報を知るだけで、リソースへの操作はしないよ

というもの。

## 叩いてみる
```bash
$ curl -v -X OPTIONS http://example.com
*   Trying 93.184.216.34...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 80 (#0)
> OPTIONS / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Allow: OPTIONS, GET, HEAD, POST
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Sat, 28 Jan 2023 09:09:35 GMT
< Expires: Sat, 04 Feb 2023 09:09:35 GMT
< Server: EOS (vny/044E)
< Content-Length: 0
< 
* Connection #0 to host example.com left intact
* Closing connection 0
```

レスポンス内容を見てみると、`Allow: OPTIONS, GET, HEAD, POST`とあるので
`http://example.com` というリソースに対しては `OPTIONS, GET, HEAD, POST` の4種類だけが許されてることがわかる。

## 実装する
Springだと [RequestMethod.OPTIONS](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMethod.html#OPTIONS) があるので、それを指定すればOK。
```java
@RequestMapping(path = "hoge/", method = {RequestMethod.GET, RequestMethod.OPTIONS})
```

ただし特にレスポンス内容をカスタムしたいわけじゃない場合は `@RequestMapping` やそのショートカットになるアノテーションをつけていればデフォルトで有効になる。
※ [DispatcherServletがデフォルトで処理します](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMethod.html) とのこと

## つかいどころ
### API実装側としては
自チームでは、API仕様をクライアント側と具体的に整合するし、仕様書も用意するのであまり使うことはないかも。
適切にAPI仕様書を公開しているならあまり必要になることは無さそうだけど、クライアント側との距離がちょっと遠いなら実装してもいいかもしれない。

### API利用側としては
* 誤ったリクエストを投げるのがとても怖い場合
* 仕様書が不十分なAPIを叩かざるを得なくなった場合

とかだろうか？

どうしてもOPTIONSが使いたくなる場面はあんまり想像がつかない。

## refs
* [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#section-9.3.7)
* [RFC9110日本語訳](https://triple-underscore.github.io/http-semantics2-ja.html#OPTIONS)
* [MDNのドキュメントわかりやすい](https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/OPTIONS)
AWS未経験者がアソシエイト3冠＋CLFを取得した話（CLF編)

# 初めに

初めまして。インフラエンジニアとして働いていますcoffee_cafe と申します。今後、QiitaにAWS認定資格であるSAA、SOA、DVA、CLFを受験した際の勉強方法や感想を投稿していこうと思います。

初回はクラウドプラクティショナー(CLF)編です。これからCLFを受験する方の参考になれば幸いです。

# クラウドプラクティショナー(CLF)について

![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121544/215610c7-9ad0-c1f2-85db-ebd1a0111be2.jpeg)
[画像引用元：AWS公式サイト](https://aws.amazon.com/jp/certification/)

クラウドプラクティショナーはAWS認定資格の1つです。AWSの基礎的な知識を習得するための資格であり、言わばAWS認定資格の登龍門です。AWSを体系的に学習していくにはまずはこの資格から、という感じですね。

# 受験前の状態
AWSって何それ？ EC2?? S3は名前だけ聞いたことあるけど・・・といった程度の知識レベルで完全にAWSド素人でした。
AZ-900は取得済みだったので、クラウドとは何ぞや？というところや、SaaS・PaaS・IaaS辺りの違いは多少把握していました。

# 勉強期間
約2週間ほど　業務終了後と休日を使い短期集中で取り組みました。

# 学習方法
## 1週間目

最初の1週間は以下テキストを2周ほど読み込み。サービス名と概要を頭に叩き込みました。

[AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B-ebook/dp/B07QX45RXM/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC&qid=1674988635&sr=8-1)

## 2週間目

Udemyの下記問題集をひたすら解きました。

[この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（8回分520問）](https://www.udemy.com/course/aws-4260/)

問題集のレビューを参考に模擬試験基本レベルが正答率9割、模擬試験本番①~③レベルが正答率8割となるまで繰り返しました。この正答率が達成できるようになれば合格ラインです。

模擬問題（応用レベル)はSAA準拠の難易度で、このレベルの問題は実際には出題されないのでスキップしておいても大丈夫です。

# 受験結果
スコア799点で合格することができました。
![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121544/adc23a38-31ef-ea0a-9c19-20311308693d.jpeg)

# 感想
・CLFの学習を通じて、AWSの主要サービスとその用途を把握することができた。
→AWSを学んでいく上での最初の取っ掛かりとして非常にお勧めできる資格だと感じた。
・責任共有モデルやAWSのメリット周りの問題が予想以上に出題された。
　→この辺の理解が浅いと失う得点が多いので要注意かも。
・日本語訳が怪しい問題も多かった・・・
・Udemyの教材にあるような、重箱の隅をつくような問題は以外と少なかった。
　→逆に言うとUdemyがほぼ解けるようになれば合格は確実と言える。

# 最後に
次回はSAAの受験記を投稿する予定です。最後までお読みいただきありがとうございました。
L3機器のパケット送信の動き


L3機器のパケット送信の動きについて分かりやすい説明を見つけたのでメモ。


1.到着したパケットから宛先IPアドレスを読む
2.ルーティングテーブルを検索し、ネクストホップのIPアドレスを知る
3.ネクストホップへ到達するためのレイヤ2アドレスを調べる
4.EthernetであればARPテーブルを参照して調べる。もしARPテーブルに載っていなければ、ARPパケットを飛ばして目的のMACアドレスを取得する。
5.パケットのL2ヘッダをネクストホップ宛てに書き換える
6.Ethernetであれば宛先と送信元のMACアドレスを書き換える、等。
7.ネクストホップ向けのインターフェースからパケットを出力する

IPパケットが到着するたびに、この動作を繰り返すわけです。


参考
https://gihyo.jp/admin/serial/01/net_prac_tech/0008
そのWEBアプリは、キーボード操作を考慮していますか？

## これは何の記事？
筆者が[Web Content Accessibility Guidelines(WCAG) 2.1 の解説書](https://waic.jp/docs/WCAG21/Understanding/)を読んで、
学びとなったことを残す記事です。
誤りなどありましたら(優しめに)ご指摘いただけますと幸いです。


:::note info
__WCAG__  :
 WEBコンテンツを、よりアクセシブルにするための広範囲にわたる推奨事項をまとめたガイドライン。
W3Cの Web Accessibility Initiative (WAI) の活動の一環として作成されている。
:::

## そのWEBアプリは、キーボード操作を考慮していますか？
「いや、うちのアプリは基本マウス利用だし...」
「キーボード操作ばっかりするような、PCに詳しい人に向けたシステムじゃないから...」
上記のような思考から、キーボード操作の考慮は後回しにされがち...
ですが、アクセシビリティの観点からみると、キーボード入力はとても大事なんです。

参照先：[ガイドライン 2.1: キーボード操作可能を理解する](https://waic.jp/docs/WCAG21/Understanding/keyboard-accessible.html)

## キーボード操作を考慮することはなぜ大事？
* __キーボード入力というのは、キーボードでのみ行われるものではない__ から。
* (いわゆる一般的な入力方法とは異なる)  __様々な支援技術は「キーボードの入力」機能を実現する__ ものであるから。
    > コンテンツがキーボード又は代替キーボードで操作できるとき、(目と手の協調運動を必要とするマウスのようなデバイスを使用できない) 全盲の人にも、代替キーボード又はキーボードエミュレータの機能を果たす入力デバイスを使用しなければならない人にも操作できる。
* そのため、__キーボード操作に対応していないアプリは、何らかの理由で一般的な入力方法を利用できない人々をユーザーから除外している__ ことになるから。

## 考慮するって言っても..具体的には？
例えば、以下の点を満たせているかを確認する。
* __コンテンツのすべての機能は、キーボードインタフェースを通じて操作可能？__
    * 例えば、ドラッグ&ドロップ機能が使われているサイトならば、それはキーボード操作でも実現できるだろうか？（切り取り&貼り付けなど）
        * 以下語学学習サイトでは、選択肢を回答欄へドラッグ&ドロップする代わりに、選択肢上でEnterを押すことで上から順に回答欄へはめられる([Deutsche Welle](https://learngerman.dw.com/en/learn-german/s-9528))
        * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/80125155-b262-1dff-0a05-9388d5ce5b3f.png)

        
* __キーボードだけを用いて特定のコンポーネントからフォーカスを外すことが可能？__
    * 例えば、モーダルウィンドウが表示された場合、ちゃんとそのモーダル内にフォーカスが「閉じ込められる」状態になっているか？（裏に隠れた画面でのみフォーカス移動できても意味がない）
        * 以下例では、いくらTabを押しても「×」と「翻訳設定」にのみフォーカスが移動可能である（[airbnb](https://www.airbnb.jp/))
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/2a1f67b4-f321-5b1e-0197-ec53159a1b94.png)

* __独自の単一キーを利用したキーボードショートカットを割り当てている場合は、それを利用しないことが選択できるか？__
    * 音声入力を利用している場合、単一キーでは誤った操作が行われやすくなる（普通の会話に反応してしまうなど）
    * より具体的には、以下の3つのいずれかを満たすことで誤操作の可能性を低減させているか？
        * ショートカットを解除できる
        * 任意のショートカットを再割り当てできる
        * そのショートカットをフォーカス中にのみ有効にできる
            * 例えば、リストボックスやドロップダウンメニューはフォーカス中にのみ操作可能になる
        * 以下はショートカットの有効無効を選択できる例(Gmail)
        ![8D817C68-1D7B-4C59-8AF3-DD3C4008B8D4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771526/085c3e05-0c0a-720c-c2ca-234c4a651135.jpeg)



## 終わりに
たかがキーボード操作..ではなく、ある人にとっては唯一の操作方法である、ということを忘れずに開発していきたいですね
Gitとは・・・？

 # はじめに
今回の記事では、表題にある通り「Git」の概要について触れていこうと思います。

 # Gitとは・・・？
Gitとはバージョン管理をするためのツールです。

 # バージョン管理とは・・・？
バージョン管理とは新規作成・変更情報を管理することです。新規作成したときの日時などを管理してくれます。このバージョン管理というのがとても優れモノなのです！

 # バージョン管理をすると？
会社では、複数人でプログラムを組んだり、修正したり、削除したり・・・とにかく、いろいろな人がいろいろなことをします。そんな時、だれがどんなことをやったのか管理しておくと便利ですよね。例えば、動いていたプログラムが動かなくなっているとき、バージョン管理をしていなければどこでエラーが起きて、どうしたら以前と同様の動きをしてくれるのか該当箇所を探して、修正して・・・ということをしなくてはいけません。そんな時に、バージョン管理をしていれば正常に動作しているプログラムまで戻ることができるのです！つまり、動いていたプログラムが変更などで動かなくなってしまったとき、すぐに動いていたプログラムに戻すことができます！

 # それだけじゃない
修正したプログラムを修正前のプログラムに戻せるので、とても安心して手を加えることができますよね。そして、間違えて削除してしまったプログラムを元に戻したりすることができます。そのため、複数人で開発をする場面ではこのバージョン管理は欠かせないものです。そして、Gitというのは今最も使われているツールです。

 # 最後に
まだまだ勉強途中なので本当に概要しか記載していませんが、これからさらに詳しい記事を投稿していこうと思います。(余裕があれば・・・)
jotaiを触ってみての良いところ/困ってること個人的メモ


# Jotaiとは

[Jotai, primitive and flexible state management for React](https://jotai.org/)

React用の状態管理ライブラリ。

# いいところ

## 1. 状態キャッシュと依存計算の最適化

ReactでいうuseMemoやuseEffectの第二引数のように、依存関係となる変数を明示した上で計算結果のキャッシュ(/computed property)を構築することができる。

具体的には、以下のようにgetter , setter に独自の記法が採用されている。

```tsx
// 基準値
const sampleAtom = atom<number>(0)
const sampleAtom2 = atom<number>(2)

// get
// sampleAtomやsampleAtom2の情報が変わらない限り再計算されない
const getSampleAtom = atom<number>(get => {
  if (get(sampleAtom) > 2.0 ) {
    return get(sampleAtom2) 
  }
  return get(sampleAtom)
})

// set
// 様々なルールが指定できる
const setSampleAtomByValue = atom<null , number /*imput */>(null , (get , set , val)=>{
  if (get(getSampleAtom) < val ) {
    set(sampleAtom , val)
    return
  }
  set(sampleAtom , get(sampleAtom2))
})

//便宜上変数を分けているが、両方記載することも可能。

```


特にgetterの場合、get引数で取得する値がJotaiの管理化=atomである場合に、それらが依存関係にあるとみなされ、依存先の状態が変化するまでは再計算を防ぐことができる。

また、これらの計算はReactのRenderフェーズに依存せずに連鎖的に依存に応じた各種計算ができるため、チラつき等の軽減にも役立つかもしれない。

## 2. setとgetの分離による最適化

React側から使うときは大抵の場合、

`useAtom(get/set)` , `useAtomValue(get)` , `useSetAtom(set)`

あたりを使うことになる。`useAtomValue` , `useSetAtom` をうまく使うと、値を入れ込みたいコンポーネントと値を表示したいコンポーネントでそれぞれに仮想DOMの再計算を防ぐことができる。

下記の例では、セッターのみを持つ`Sample2Tsx`は再計算されない。

```tsx

// 表示用
export const SampleAtomTsx = ()=> {
  const val = useAtomValue(sampleAtom)

  return (
    <div>
      {val}
    </div>
  )
}

// 入力用
const Sample2Tsx = ()=> {
  const setVal = useSetAtom(sampleAtom)

  return (
    <div>
      <button onClick={() => setVal(prev => prev+1)} >+</button>
    </div>
  )
}

const App = ()=> {
  return (
    <>
      <SampleAtomTsx />
      <Sample2Tsx />
    </>
  )
}
```

## 3. Providerレスで雑に使える

上記例に見るようにいらない。便利。

# 難しいところ

大域オブジェクトというよりは、細かく値を扱う/ 影響を持つコンポーネントを分離することによって再計算を防ぐための真価を発揮する。

だがこの **「細かく扱う」** というところに実際どうしたらいいの?という悩みが発生している。
jotaiというよりはjotaiによって「できるようになること」をキレイに活かすためにどうしたらいいんだ？という類の悩みだが…。

## 1. APIが自由すぎて、jotaiを知らないと扱えるか謎

```tsx
export const useSampleAtom = ()=> {
  const getSample = useAtomValue(sampleAtom)
  const setSample  = useSetAtom(setSampleAtom)

  return {
    getSample,
    setSample,
  }
}
```

`useAtom , useSetAtom , useAtomValue` を使い手に意識させたくなくてたとえばこんな隠蔽をしたとしよう。

これだとsetSampleを使ったときにはgetSampleも必ず動いちゃう(仮想DOMが走っちゃう)ので、jotaiの良いところをうまく活かせない気もしていてうまくない。

## 2. 細かくは扱えるが…そんなに最適化って要るんだっけ

大域オブジェクトというよりは、細かく値を扱うことによって真価を発揮するが、最適化のためにあちこちのコンポーネントがそれぞれ個別のStore的なものにアクセスすると、治安が悪くなるという話がある。

これももちろんjotaiのせいでなく、「jotaiによってできるようになったこと」に対する悩みである。

大抵の場合はめちゃめちゃ最適化しなくても、そこそこでかい単位のオブジェクトベースで管理しちゃっていいかな、と思ってはいる。

```tsx
export type State = {
  offset: number;
  zoom: number;
  zoomMax: number;
  x: number;
  y: number;
};

const stateAtoms = atom<State>({
  offset: 0,
  zoom: 0,
  zoomMax: 100,
  x: 0,
  y: 100,
});
```

## 3. 一部APIの変更が予定されている

https://jotai.org/docs/guides/migrating-to-v2-api
...らしい。
Python 3 エンジニア認定データ分析試験に合格したので勉強方法とかをまとめる

Python 3 エンジニア認定データ分析試験を受験して合格しました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1098117/2053c48c-de37-8dde-0768-92aba42e5521.png)

何番煎じかという感じですが勉強方法をまとめてきます。

# 前提スペック
* 10年以上前に大学の工学系の学部に通っていて、数学は好きな科目だった
* 5年ぐらい前に会社の研修で統計値の勉強を少しだけした
    * 数学関連知識はなんとなく思い出せばわかる、という感じ
* 12月にPython 3 エンジニア認定基礎試験を受験して合格済
    * pythonの文法問題はだいたい解ける、という感じ
# 試験までにやったこと
## 試験2週間前
1. 受験するぞ！と思い、受験申し込みをする
    * 日が決まってたほうが気合が入るので……
2. 公式の教科書である [Pythonによるあたらしいデータ分析の教科書 第2版](https://amzn.asia/d/8X2cWE3) はすでに購入していたので、そちらにぱらぱらと目を通す
3. [DIVE INTO EXAM](https://diver.diveintocode.jp/dive_into_exam)で模擬試験を解く(DIVE INTO EXAMは会員登録必須です)
4. 模擬試験で間違えたところを、[Pythonによるあたらしいデータ分析の教科書 第2版](https://amzn.asia/d/8X2cWE3) で読んで正しい答えを見たり、実際にコードを動かしてみたりする
5. 3～4をひたすら繰り返す
## 試験3日前
1. [PRIME STUDY](https://study.prime-strategy.co.jp/) の模擬試験を解く(3つ試験があるうちの第1回を受験)
2. ↑の模擬試験を受けた後に解説&解説動画があることを知り、[解説動画](https://youtu.be/ErkqmUoS4Dk) を一通り見る
    * この解説動画がすっっっっっっっごく良くて、めちゃくちゃオススメしたいものです
    * 良かった点は教科書を読むだけだと理解しにくかった、データ分析の各概念や、scikit-learnの使い方などが動画によってわかりやすくまとめられており、理解が深まりました
    * この動画を見ながら教科書の重要なところにマーカーをしています
3. [PRIME STUDY](https://study.prime-strategy.co.jp/) の模擬試験 第2回、第3回を受験
## 試験前日から当日
1. scikit-learnの[解説動画](https://youtu.be/ErkqmUoS4Dk) だけもう一度見返す
2. [PRIME STUDY](https://study.prime-strategy.co.jp/) の模擬試験 第2回、第3回をもう1度解く
3. [DIVE INTO EXAM](https://diver.diveintocode.jp/dive_into_exam)の模擬試験を何度か受験する
## 試験直前
1. 教科書のマーカーしたところを重点的に最後のおさらい
2. ↑の見返しをしてももう少し時間があったので、[PRIME STUDY](https://study.prime-strategy.co.jp/) の模擬試験解説ページを見返す
# 受験した所感
* データ分析の各概念や、scikit-learnの使い方がいまいち頭に入ってこなかったのですが、[PRIME STUDY](https://study.prime-strategy.co.jp/) さんの [解説動画](https://youtu.be/ErkqmUoS4Dk) に本当助けられました
* 大学の時使えていたら、研究室での実験結果まとめとかにめちゃくちゃ活用できたなー
* データ分析楽しい……！！

以上！
No.2 マトリックス（列がグループ化された表）を追加する

# マトリックス（列がグループ化された表）を追加
**1．ビルドから「マトリックス」を選択
2．右側のデータの「テーブル」を展開し、マトリックスで表示したい項目を選択する（今回は「月毎」の「売上」を確認する）**
**3．表示されたビジュアルを確認する**
![作成1ezgif-5-758e519fb1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/5bfe6287-d310-238a-bec9-84099c38583c.gif)
**4．列に「支社名」を追加する**
グループ化されている「月毎」を基準にして、各支社の売上が確認できます
![作成2ezgif-5-540fd27b29.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/de070d2b-e864-b29a-6de8-d6f8b122afd0.gif)
**5．グループされている値を展開する**
グループ化されている列の値を展開すると、細かい値の内訳が確認できます（＋ボタンで展開）
![作成3ezgif-5-d7ecad15b0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/b6fd7b3b-3e1b-4a79-5621-f714fa5ed1a5.gif)


# マトリックスの編集
**1．ビジュアルの書式設定を選択
2．値からテキストの文字を大きくしたり、総計値をわかりやすく色を変化させる事ができます**
![編集ezgif-5-489cc50309.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/1e902c1a-4d3d-9a6c-f776-f8778d2c8fdc.gif)

**3．グルーピングを変更する際は、列をドラッグ＆ドロップで入れ替える事変更可能**
ex.)商品毎をベースに各四半期毎の各支店の売上を確認
![スクリーンショット 2023-01-30 17.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/a03adee2-29cd-1d9b-56b7-338ae08b0c6c.png)


# マトリックスの利用シーン
・テーブルだと行数が多く、表示が細かすぎる場合にグループ化する事で大まかな傾向や詳細が確認できる

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
【Rails】制限時間機能を実装してみた。（解説付き）

## 1.バージョンを確認しましょう!

Rails 5.1.6
ruby 2.7.2p112

## 2.完成イメージ

投稿に制限時間を設定し、何かしらの処理をつける機能です。
今回は **「投稿（タスク）を設定し、制限時間を超えると通知が来る機能」** を実装する準備段階です。

## 3.実装の大きな流れ

>１．投稿モデル（Tweet）に、制限時間を保存するカラムを追加する。
>２．投稿を保存するときに、制限時間と現在時刻を比較して、制限時間が過ぎていないかをチェックするアルゴリズムを記入する。
>３．制限時間が過ぎている場合はエラーを返し、投稿を保存しない設定を仕込む。

ちなみに本記事はこのような目次で進んで行きます！
一緒に楽しんでいきましょう ᕙ( ˙꒳​˙ )ᕗ

## 4. モデルに、制限時間を保存するカラムを追加しよう。

```ターミナル
$ rails generate migration AddLimitTimeToTweets limit_time:datetime
$ rails db:migrate
```

tweetsテーブルに、**limit_time**というカラムを追加しました。
データ型は日時の保存に適している**datetime**型を採用しています。

多分マイグレーションファイルはこんな感じ。（一例）

```~~_create_groups.rb
class AddLimitTimeToTweets < ActiveRecord::Migration[6.1]
  def change
    add_column :tweets, :limit_time, :datetime
  end
end

```

# 5.アルゴリズムを仕込む。

制限時間についてのアルゴリズムを仕込みましょう。
この記述がないと、現在時間よりも以前の時間で制限を設けることができ、サイトとして破綻してしまいます。

下記のモデルをこんな感じで編集していきましょう ᕙ( ˙꒳​˙ )ᕗ

```app/models/tweet.rb
class Tweet < ApplicationRecord

  #追加

  validate :check_limit_time, on: :create
  validate :check_limit_time, on: :update

  private
  def check_limit_time
    if limit_time.present? && limit_time < Time.now
      errors.add(:limit_time, "制限時間を過ぎています")
    end
  end
end
```

コードの確認を初めます。先に`private`の中身から。

**1)  `if limit_time.present? && limit_time < Time.now`の説明** 

まず`check_limit_time`というメソッドを作っています。これはどんな処理でしょうか。
`if A && B`は、**AかつBの条件が成り立つ際に処理を実行しますという条件分岐文**です。

この場合、Aは`limit_time.present?`ですね。
これは、`limit_time`という変数が存在するかどうかを確認するコードです。

Bは、`limit_time < Time.now`です。
今の時間よりも、以前の場合ということですね。

つまり、現在は1月23日10:00なのに、1月23日8:00に制限を設定してしまったというようなイメージです。
論理的に破綻していますね。
　
　


**2)  `errors.add(:limit_time, "制限時間を過ぎています")`の説明** 

このような場合には、` errors.add(:limit_time, "制限時間を過ぎています")`という処理を実行します。これは「制限時間を過ぎています」という警告を表示するコードですね。
　
　


**3)  `validates`の説明** 

Validatesは、データベースに保存する前に、入力されたデータが正しいかどうかをチェックする機能です。 
例えば、以下のように、emailカラムが必須であることをチェックする検証を追加することができます。


```app/models/user.rb
class User < ApplicationRecord
  validates :email, presence: true
end
```

validationによって入力されたデータが正しくない場合は、保存されず、エラーを返すことができます。よって、データベースに不正なデータが保存されないようにすることができ、アプリケーションの信頼性を高めることができます。

今回は「投稿作成時」と、「投稿更新時」に確認を行いたいので、それぞれにcreateとupdateを仕込んでいます。


# 6.制限時間と現在時刻を比較して、タイムリミットを表示させる。

Viewファイルに下記のコードを追加しましょう✊

```app/views/tweets/show.html.erb
  <% if @tweet.limit_time.present? && @tweet.limit_time > Time.now %>
      <div class="timer">
        <%= distance_of_time_in_words(@tweet.limit_time, Time.now) %>
      </div>
  <% end %>
```
ここでのif文は先ほどと同様のものです。割愛しますね。

ここでは`distance_of_time_in_words`というメソッドを使っています。
これは第一引数（`@tweet.limit_time`）と、
第二引数（`Time.now`）の時刻の間隔を、「xx分前」や「yy時間前」といった文字列に変換するものです。

ここで計算が行われることで、◯◯分前という表示を出すことに成功しました。


# 7.まとめ 
そこまで複雑な機能設計はないので、もっと複雑なものを実装次第Qiitaに取り入れようと思っております。
タイマーかっこいい感じで表示したいなあ。少しがんばります。
【TypeScript/Express/multer】requestからファイル情報を読み取る方法

Expressとmulterを使ってポストデータを受け取ろうとした時に発生したエラーの対処法です。
エラー内容は下記。
```
Property 'file' does not exist on type 'Request<{}, any, any, ParsedQs, Record<string, any>>'.
```
### 【対処法】multerの@typesパッケージを追加する

```
npm install --save @types/multer
```

### 【原因】

ファイルの受信はコンパイル後に行われるため、TypeScriptではrequest後のプロパティの有無を推測できない。

### 【参考】

https://github.com/expressjs/multer/issues/343
esp-idf: https_request の使い方

esp-idf/examples/protocols/https_request のプログラムを改造します。
M5Stack Core2 で動作確認をしました。
次のサイトにアクセスする例です。
>https://ekzemplaro.org/test_dir/

## プログラム

プロジェクトのコピー

```bash
cd ~/esp
cp -r esp-idf/examples/protocols/https_request .
```

http_request/sdkconfig を作成

```bash
idf.py build
```

変更する場所

```text:https_request/sdkconfig
（省略）
CONFIG_EXAMPLE_WIFI_SSID="****"
CONFIG_EXAMPLE_WIFI_PASSWORD="****"
（省略）
```

```c:https_request/main/https_request_example_main.c
（省略）
#define WEB_SERVER "ekzemplaro.org"
#define WEB_PORT "443"
#define WEB_URL "https://ekzemplaro.org/test_dir/"
（省略）
```

## コンパイル、実行

```bash
idf.py -p /dev/ttyUSB0 flash
```

## 実行結果

```text
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Mon, 30 Jan 2023 08:09:22 GMT
Content-Type: text/html
Content-Length: 993
Last-Modified: Fri, 30 Sep 2022 01:56:22 GMT
Connection: keep-alive
ETag: "63364cc6-3e1"
Accept-Ranges: bytes

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@ekzemplaro" />
<meta property="og:url" content="https://ekzemplaro.org/test_dir/" />
<meta property="og:title" content="テス�
��のページ" />
<meta property="og:description" content="サーバーのテスト" />
<meta property="og:image" content="https://ekzemplaro.org/png/linux_logo.png" />
<title>テストコーナー</title>
</head>
<body>
<h2>テストのページ</h2>
<blockquote>
AAA<br />
BBB<br />
CCC<p />
</blockquote>
<a href="test_a001.php">test_a001.php</a><p />
<a href="test_a002.php">test_a002.php</a><p />
<a href="test_a003.php">test_a003.php</a><p />
<a href="test_a004.php">test_a004.php</a><p />
<p />
<a href=
"php/">PHP のテスト</a><p />
<a href="python/">python のテスト</a><p />
<a href="ruby/">Ruby のテスト</a><p />
<a href="perl/">perl のテスト</a><p />
Sep/30/2022 AM 09:42<br />
</body>
</html>
```
【Docker】buildにしたとき、 no space left on deviceと表示されたときのの対処法

<h2>症状</h2>
ローカル環境(windows)でdocker-compose buildしたときに、下記のエラーが発生しました。
翻訳すると「準備に失敗しました。デバイスに空き容量がありません」でした。

```terminal:error
failed to prepare cslvr0kis3s5dt57xl2n7g82g: symlink ../cslvr0kis3s5dt57xl2n7g82g/diff /var/lib/docker/overlay2/l/HHWE2YMR7PAS2NZRQMOLKINYPI: no space left on device
ERROR: Service 'api' failed to build : Build failed
```

「docker system df」コマンドでDockerの使用量を確認すると、100%になってました。
Imagesが大量にあるようです。

```terminal:docker system df
docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          88        0         78.61GB   78.61GB (100%)
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     652       0         14.54GB   14.54GB
```

Dockerデスクトップでも確認。確かに、Imagesにたくさんデータがあることが確認できます。(右のスクロールバーの大きさ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/e3dabce7-107b-0896-79bf-31cdcbcb0c4e.png)


<h2>解決策</h2>
Dockerデスクトップでイメージを削除したら、解決しました。
右上のCleanup...からImageをすべて削除。(使用しているものがあればそれを残す。今回はなし)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/8608dc66-6e6e-0ff6-7a3f-c99065011a90.png)

imageも0になっていることが確認でき、ビルドできるようになりました。

```terminal:docker system df
docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     652       0         88.73GB   88.73GB
```

<h2>参考</h2>

https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/system_df/

https://www.techback.info/docker-compose-error-response-from-daemon-error-creating-overlay-mount-to-no-space-left-on-device/
No.1 テーブル（表）を追加する

# テーブル（表）を追加
**1．ビルドから「テーブル」を選択
2．右側のデータの「テーブル」を展開し、テーブルで表示したい項目を選択する（今回は「商品毎」の「売上」を確認する）**
**3．表示されたビジュアルを確認する**
![作成ezgif-5-af953199d0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/e08ee3de-fe91-9b7d-1b0c-e504ab573234.gif)

# テーブルの編集
**1．ビジュアルの書式設定を選択
2．値からテキストの文字を大きくできる**
![編集ezgif-5-2cd1216cf6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/c9f18b03-7e37-22bd-5618-189fc600f5b1.gif)
**3．テーブルは列をドラッグ＆ドロップで入れ替える事で、順番を変更可能**
![編集2ezgif-5-c6f3770a2e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/87275eb5-aea9-f909-9756-0eb721aaf7d0.gif)


# 表グラフの利用シーン
・データの詳細を確認する
・他のグラフと組み合わせた使い方
ex.)円グラフで特定の支店を絞り込んだ時に、同じく表もフィルタリングされて内訳が確認できる

・フィルタリングをしていない状態
![スクリーンショット 2023-01-30 16.50.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/be712e87-ac29-3b1d-0a45-361c08150da3.png)

・フィルタリングをした状態　→　表も動的に値が変化し、支社毎の内訳が確認できる

![スクリーンショット 2023-01-30 16.50.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/dfda12bc-6d33-c895-1dcc-d83ac9a35ce9.png)

このような形でテーブルを使う事でグラフも見ながら数字の確認を行う事が可能です。

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
AWS lambdaでEmacs key bindingを使う

# きっかけ
MacBookでAWS Lambdaでコーディング中

 「下の行に移動しよう。`ctrl` + `N`を連打っと。」

（新しいファイルが大量に作成された）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950855/3a93d02b-0e68-2d3b-2c0c-4de1b1ebfd55.png)

「おいいぃぃぃぃい！！！！」

# やったこと
LambdaのPreferenceを起動
- 歯車アイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950855/2be1ced5-f8bf-e699-966c-3512e5ffdbd9.png)


画像のように「Emacs」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950855/2e06a217-279f-3e97-fd6b-ed89861674b4.png)

やったね！

# 終わりに
これを知らずに2週間ほどLambdaでコーディングしてました。とほほ。
Mac build fail 'GL/glut.h' file not found

# 使用環境 
- M1 MacBook(2020)
- Xcode Version 14.2 (14C18)

# エラーと解決策
本記事では、OpenGLにおいてC言語で記述していた際に、 
```
'GL/glut.h' file not found
```
というエラーを吐かれたので、それへの対処方方について記述する。
このエラーへの対処方法は非常にシンプルで、
```#include <GL/glut.h>```を、```#include <GLUT/glut.h>```に直すだけである。このエラーについて調べてみると、C++でも同様の現象が起きているようである。

# 参考文献 
[OpenGL C++ on Mac build fail 'GL/glut.h' file not found](
https://stackoverflow.com/questions/27952029/opengl-c-on-mac-build-fail-gl-glut-h-file-not-found)
esp-idf: http_request の使い方

esp-idf/examples/protocols/http_request のプログラムを改造します。
M5Stack Core2 で動作確認をしました。
次のサイトにアクセスする例です。
>http://httpbin.org/get

## プログラム

プログラムのコピー

```bash
cd ~/esp
cp -r esp-idf/examples/protocols/http_request .
```

http_request/sdkconfig を作成

```bash
idf.py build
```

変更する場所

```text:http_request/sdkconfig
（省略）
CONFIG_EXAMPLE_WIFI_SSID="****"
CONFIG_EXAMPLE_WIFI_PASSWORD="****"
（省略）
```

```c:http_request/main/http_request_example_main.c
（省略）
#define WEB_SERVER "httpbin.org"
#define WEB_PORT "80"
#define WEB_PATH "/get"
（省略）
```

## コンパイル、実行

```bash
idf.py -p /dev/ttyUSB0 flash
```

## 実行結果

```text
HTTP/1.1 200 OK
Date: Mon, 30 Jan 2023 07:44:44 GMT
Content-Type: application/json
Content-Length: 239
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "args": {}, 
  "headers": {
    "Host": "httpbin.org", 
    "User-Agent": "esp-idf/1.0 esp32", 
    "X-Amzn-Trace-Id": "Root=1-63d7756c-3c33c51147890fc74b272b72"
  }, 
  "origin": "219.126.136.17", 
  "url": "http://httpbin.org/get"
}
```

## 確認したバージョン

```text
$ idf.py --version
ESP-IDF v5.4-dev-3201-g46acfdce96
```
設計でJavaGoldは役に立つのか

最近寒くなり、ますますインドアが加速している福岡在中のSEです:snowflake:

２月から新規プロジェクトが始まるのですが、今回はオンラインの新規画面数が多いため
一足先に要件確認と、基本設計を少しずつ手を付け始めてます。

JavaGoldを去年取得しましたが、製造でしかまだ実践できていなかったので
今回は、**システム設計**でどこまで活かせたかを話したいと思っています。

設計で役に立ったこと
**１**:apple: **セキュリティコーディング**
**２**:apple: **共通部品の検討**
**３**:apple: **製造工数の算出**

***

### 1:apple:セキュリティ対策
「[現場で活きる！Java Gold](https://qiita.com/puellana/items/ce32d93952b4cf3a1ff4 "現場で活きる！Java Gold")」でもお話しましたが、製造の経験が浅かったとき、十分にセキュリティ面を考慮したコーディングすることが出来ていませんでした...:confused:
　それはJavaアプリケーションにおけるセキュアコーディングについて具体的に何を気を付けたらよいのか、それはどこから学べばいいのか分からなかったからです。

JavaGoldを学ぶことで実務に活かせた知識
①**整数オーバーフロー攻撃への対応**
② **機密情報の扱い**
③**DoS攻撃対策**

新規画面を製造するにあたって、今までにない機能を追加する箇所がありました。
　つまり、新規機能に対するセキュリティの検討が必要でした。

もともとシステム側で講じているセキュリティを理解した上でどのタイミングでどのような対策を取るべきなのかを設計の時点で記載しておけば、より仕様の意図を理解した製造をチーム全員が同じ認識で行えると思いました。

具体的なJava側でのセキュリティ対策ってどんなものがあるのか興味を持った方は、
ぜひ上記①～③を調べてみてください！



### 2:apple:共通部品の検討
今回追加する画面のロジックでは、新規画面共通する処理がいくつかありました。
(例えば、取得したコードが何のデータの主キーかを判別する等)


それをそれぞれの製造担当者がコーディングするよりも、JavaがもつストリームAPIを使った共通部品を作れば、より可読性と保守性が上がるのでは、と考えれるようになりました。

これはJavaGoldの資格範囲である「**ストリームAPI**」という存在を知っていたからだと思います。
IF文やFor文を使うよりも速く正確な機能であるため、処理を共通化できる手段があることは
プロジェクト全体の工数削減にもつながると実感しました！



### 3:apple:製造工数の算出
今回オンライン画面と機能がメインとなるプロジェクトだったので、新規で増員すべき人員をどれほど確保すべきか検討する必要があったきに役立ちました。私の一画面製造工数を参考に人員の確保をして頂いたからです。

資格を取得することで、客観的に以下のことが分かるため、
工数の算出に合わせたとそれに合わせた人員の確保がスムーズにできました。
「**Java Silver**」取得者 ＝ 言語の理解は十分　つまり、**コーディングでのバグ発生数が少なくなる**
「**Java Gold**」取得者 = 仕様の意図を理解して実装・提案できる　
　　　　　　　　　　つまり、**コーディング以外のプラスアルファを求めることが可能（即戦力）**

今回はプロジェクト期間も短い中、かなり厳しい状況ですが、
やはり資格をもっているということで、客観的に自身の能力を証明することができるため、タスク分けや、事前の工数の算出にも不要な時間を削減することにつながったと思います。
それに正確な工数が分かれば、稼働の調整ができるため、期日前に高稼働にならずに済みそうです...!!



## 最後に
プログラミング言語についての深い理解は、設計の際の思考の幅を広げることにつながり、
今まででは指示を受けて消化するだけだった作業に対して、よりよくなるような**提案**ができるようになりました:clap_tone1:！
新たなステップに到達することが出来たと思います。（脱！指示待ち人間:beginner:）

まだタスクを振られて消化するだけではなく、そのタスク自体がもたらすシステムへの影響を
踏まえた検討・提案ができたら最高ですね...！

ここまで読んで頂きありがとうございました！
これを読んでくれた方の勉強の励みになれたら嬉しいです！:blush:
ではまた！！
Firestoreでドキュメントに一括で書き込む（500件を超える場合にも対応）

# batch処理で一括書き込みできる
Firestore の batch write を使用することで、500件ずつのドキュメントの更新を行うことができます。以下は Node.js でのサンプルコードです。
```javascript
const admin = require('firebase-admin');

admin.initializeApp();
const firestore = admin.firestore();

async function updateDocuments(collectionName, batchSize = 500) {
  const collectionRef = firestore.collection(collectionName);
  const query = collectionRef.orderBy('timestamp').limit(batchSize);
  const documents = await query.get();
  
  let batch = firestore.batch();
  documents.forEach(document => {
    batch.update(document.ref, { isProcessed: true });
  });
  
  return batch.commit();
}
```
# 500件を超える場合もbatch処理の繰り返し
Firestore の batch write は一度に最大 500 件までのドキュメントを更新することができます。500 件を超えるドキュメントの更新を行いたい場合は、複数の batch write を繰り返すことで対応することができます。以下は Node.js でのサンプルコードです。
```javascript
const admin = require('firebase-admin');

admin.initializeApp();
const firestore = admin.firestore();

async function updateDocuments(collectionName, batchSize = 500) {
  const collectionRef = firestore.collection(collectionName);
  let query = collectionRef.orderBy('timestamp').limit(batchSize);
  let documents = await query.get();

  while (documents.size > 0) {
    let batch = firestore.batch();
    documents.forEach(document => {
      batch.update(document.ref, { isProcessed: true });
    });

    await batch.commit();

    // 次の batch 取得用に query の条件を更新
    query = collectionRef.orderBy('timestamp')
      .startAfter(documents.docs[documents.docs.length - 1])
      .limit(batchSize);
    documents = await query.get();
  }
}
```
timestamp順にbatch writeを使用して500件以上のドキュメントを一括で更新することができます。

# サブコレクションのドキュメントを更新する
Firebase Admin SDKで実際にFirestoreのドキュメントを一括更新してみます。
チーム（teams）コレクションのサブコレクション（memberships）のドキュメントを一括更新します。
```javascript
const admin = require("firebase-admin");
const serviceAccount = require("./hoge.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

async function main() {
    console.log("***処理開始***メンバーシップにfooを追加する");

    //チームを取得
    const teamCol = await admin.firestore().collection("teams").get();
    teamCol.forEach(async team => {
        //メンバーシップを取得
        let membershipCol = team.ref.collection("memberships");
        let query = membershipCol.limit(500);
        let documents = await query.get();

        while (documents.size > 0) {
            let batch = admin.firestore().batch();
            
            documents.forEach(document => {
                batch.update(document.ref, {
                    foo: "hoge"
                });
            });

            await batch.commit();

            query = membershipCol.startAfter(documents.docs[documents.docs.length -1]).limit(500);
            documents = await query.get();
        }
    });

    console.log("***処理終了***メンバーシップにfooを追加する");
}

main().then();
```
【JavaScript】文字列への変数の埋め込み

「\`」(バッククォート)を使うと、簡単に文字列に変数を埋め込むことができる。
「\`」で括った文字列の中に、${[変数名]}の形で変数名を書けばよい。
クラスのメンバ、数式なども指定することが可能。改行もそのまま反映される。

```JavaScript:sample
class myClass{
  constructor(argName, argAge, argHeight){
    this.name = argName;
    this.age = argAge;
    this.height = argHeight;
  }
}

var hello = 'こんにちは';
var person = new myClass('penguin', 7, 62);

console.log(`「${hello}！」`);
console.log(`「私は、${person.name}（${person.age}）です」`); // クラスのメンバ
console.log(`「大きさは${person.height/100}mです」`); // 数式
console.log(`「アジは大好きですが、
サバは苦手です」`); // 改行

// 出力結果▽
//「こんにちは！」
//「私は、penguin（7）です」
//「大きさは0.62mです」
//「アジは大好きですが、
// サバは苦手です」
```
今まで"「私は、" +name+ "（" +age+ "）です」"のように+での結合を使っていた部分がだいぶスマートになる。
【JavaScript】ESLintの設定を読み解く①

## 目的
ESLintの設定をカスタマイズして利用する方法を調べる。

## 背景
TypeScriptのプロジェクトをVSCodeで編集している。
コーディングルール統一のために"Lint"というものが入っているらしいが、
今のままでは全面エラーで真っ赤になるため、諸々設定の変更が必要とのこと。
ライブラリの導入までは先行メンバが実施してくれているので、今回はカスタマイズ方法がわかればよい。

## Lint(ESLint)とは何か
>lintとは、コンピュータプログラムなどのソースコードを読み込んで内容を分析し、問題点を指摘してくれる静的解析ツール。
https://e-words.jp/w/lint.html

ふーん。lintにも種類があるようだが、今導入されているのはESLintというツールで、
.eslintrc.jsの記述をいじればコードチェックルールをカスタマイズできる模様。

## 現状分析
リポジトリにあった.eslint.jsはこうだ。

```js:.eslint.js
module.exports = {
  root: true,
  env: {
    'googleappsscript/googleappsscript': true,
  },
  globals: {  // ここに定義したものはグローバル変数なのでチェックしなくていい(orその逆)
    Underscore: true,
    Moment: true
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    sourceType: 'module',
  },
  plugins: [
    'googleappsscript',
    '@typescript-eslint',
    'prettier',
  ],
  extends: [  // ここに定義した外部の設定を流用する
    'standard',
    'prettier',            // prettierの設定を使う（★１）
    'eslint:recommended',  // eslintのおススメ設定を使う（★２）
  ],
  rules: {
    'prettier/prettier':   // prettierのデフォルトルールを上書き（★３）
    ['error', {            // 以下のルールに反する場合エラー
      useTabs: false,      // タブは使わないこと
    }],
    'no-var': 'error',     // 変数宣言時varを使わず、const/letを使うこと
    "@typescript-eslint/naming-convention": // 命名規則の設定（★４）
    ["error",                               // 以下に反する場合エラー
       {                                    // ルール①
        "selector": "class",                // チェック対象：class
        "format": ["PascalCase"],           // フォーマット：頭大文字、アンスコなし
        "custom": {                         // 細かい設定：
          "regex": "send|start|find",       //   正規表現
          "match": false                    //   ↑に該当してはいけない
        }
      }
    ]
  }
}
```

* prettierの設定を使う（★１）
prettierはソースのフォーマッタ。ソースの見た目の部分をきれいにしてくれる機能を持っている。
見た目の部分のルール作りはprettierの設定に従う、ということ。

* eslintのおススメ設定を使う（★２）
ここではeslintにはおすすめのルール設定があり、それが適用されているようだ。
rulesのところに逐一どのルールを適用する/しないを定義してもいいが、[大変らしい](https://qiita.com/khsk/items/0f200fc3a4a3542efa90)。
なお、extendsに定義されたルール同士が競合する場合、後に書いたものが優先される。

* prettierのデフォルトルールを上書き（★３）
prettierのルールが適用されるが、ここでprettierのルールのカスタマイズができる。
別途.prettierrc.jsというファイルを用意してそこに書くことも可能。

* 命名規則の設定（★４）
変数はこう、関数はこう、クラスはこう、みたいに対象ごとに命名規則を定義できる。
ただし、これはエラー、これは警告、という風な定義の仕方はできない模様。
(https://stackoverflow.com/questions/62903691/typescript-eslint-naming-convention-how-to-mix-error-and-warn-rules)


## チェックしてみる
### コマンドによるチェック
```:コマンド
npx eslint [--fix] [対象ソース]
```
ターミナルで上のコマンドを実行すると、エラーの場所と内容がずらずら出力される。
--fixがあると、自動修正できるものは自動で修正される。


### エディタに赤線で表示させる
プラグインが必要。
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
↑をVSCodeに適用すると、ルール違反の部分はエディタ上赤線がでるようになった！

### 結果
ルールの方はタブ幅2スペースを期待していたり、
改行コードにLFを期待していたりで全面的に真っ赤になってしまった！
ここから不必要なルールの無効化・調整を行っていく。

## 対応中の課題
* prettierが変な改行を入れてくる…
* 他ファイルに定義されているクラスが軒並みno-undef…全部globalに書くしかない？
* 特定のルールだけfixさせたいが「error  Parsing error: The keyword 'class' is reserved」に阻まれる
サンプル時間が一定でない信号のフーリエ変換を近似的に得る(Python)


# TL;DR

- サンプル時間が一定でない信号のフーリエ変換を簡易的に行う
    - scipyのinterp1dで固定サンプルの信号へと変換
    - あとは通常通りnumpyのfft
- **ちゃんとした解析をしたい場合は[PyNuFFT](https://github.com/jyhmiinlin/pynufft)とかを使いましょう**（きちんとした理論があります。）


## 依存パッケージ

numpy, scipy, matplotlibを使います。

```py
from scipy import interpolate
import numpy as np
import matplotlib.pyplot as plt
```

## 0. Test用データ作成

既にデータがある人はSkipしてOK。  
ここではrandomとcumsumを使って適当なランダムサンプリング時間の信号を作成します。


```py
# randomなサンプル時刻を作成 200点数
dx = np.random.rand(200)/20 # 0~1の乱数/20≒期待値的には40Hzくらいの信号
x = np.cumsum(dx)

# 正弦波信号とする
f = 3. # hz
y = np.sin(2*np.pi*f*x)

# Plot
plt.plot(x,y)
```

ちょっと気持ち歪んでるかな？くらいの信号になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188863/d91d56df-3285-6fb5-f537-511f1f2da862.png)


これのサンプル時間を可視化すると下記のような感じ。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188863/da9b0092-8ba5-ae40-4d68-b0cb7a40a8a8.png)


## 1. scipy.interpolateを使って固定サンプルの信号に変換

x軸を固定サンプル時間にしてそこのyにあたる量を元の信号から補間をします。  
下記のコードではわかりやすさのためにサンプル時刻や時刻の範囲に固定値を使ってますが、本当は元の信号から抜き出して来たほうが良いです。


```py
# 新しい時系列の設定
new_sampling_freq = 30. # resampling後のFreq
new_dt = 1./new_sampling_freq
time = np.arange(0,4,new_dt) # 0s-4sまでの固定サンプル時刻


# 補間
func = interpolate.interp1d(x, y, "cubic", fill_value="extrapolate") # f(x)を作成, cubic補間

new_y = func(time)

# 
plt.plot(time, new_y)

```

サンプリングが揃うので見た目もちょっと揃います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188863/62cae578-2efd-8043-533c-09cb25bbb3fe.png)


## 2. （numpyで）FFT


scipyでFFTしても良いですが、numpy版に良さげな記事があったのでそれに準拠しておきます。

https://qiita.com/chnokrn/items/57c89382942778a20e7f#1-%E3%83%95%E3%83%BC%E3%83%AA%E3%82%A8%E5%A4%89%E6%8F%9B


```py
# fft
N = len(new_y)
fft_freq = np.fft.fftfreq(N, d=new_dt)
y_fft = np.fft.fft(new_y)
fft_amp = abs(y_fft/(N/2))

# plot
plt.plot(fft_freq[1:int(N/2)], fft_amp[1:int(N/2)]) # A-f グラフのプロット
plt.xscale("log") # 横軸を対数軸にセット
plt.grid()
```

もともと設定していた3Hzの信号がしっかり検出できているのがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188863/fb591b87-e937-1035-af86-f15d98d0fe5f.png)


## 関数化まとめ

ということで一連の流れを関数化するとこんな感じになります。

```py

"""
from scipy import interpolate
import numpy as np
import matplotlib.pyplot as plt
"""


def approx_nufft(x, y):
  if not len(x) == len(y):
    print("length of x and y must be the same.")
    return 
  N_ = len(x)
  max_x, min_x = max(x), min(x)
  mean_dx = (max_x - min_x) /N_
  
  # 1. interpolatoin
  x_new = np.arange(min_x, max_x, mean_dx)
  f_new = interpolate.interp1d(x, y, "cubic", fill_value="extrapolate")
  y_new = f_new(x_new)

  # 2. FFT
  N = len(x_new)
  fft_freq = np.fft.fftfreq(N, d=mean_dx)
  y_fft = np.fft.fft(y_new)
  fft_amp = abs(y_fft/(N/2))

  # plot
  plt.plot(fft_freq[1:int(N/2)], fft_amp[1:int(N/2)]) # A-f グラフのプロット
  plt.xscale("log") # 横軸を対数軸にセット
  plt.grid()
  plt.xlabel("Freq [Hz]")

# test
approx_nufft(x,y)

```


## 補足（？）

上記関数では自動でリサンプリングの粗さを設定していますがサンプルの粗さによっては下記のようにちょっとFFTの結果が理想的でなくなる場合もあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188863/eca3824c-9805-c1c1-abe2-23af91a13182.png)
stream Collector interface

Collector sample

accumlator　process本体
finisher  中間値→return値
supplier  中間値のインスタンス生成

# なぜこんなものをつくったのか
supplier, accumlator, finisherを一つのメソッドに書くと
accumlatorは、for/whileを書かざるを得なくなる、これでは、streamメリットが減る。
そのため、作者はaccumlatorを切り出し、collector側で回すようにした。
様々な処理にも耐えうるようその他の機能を切り出しメソッドに用意した。
各メソッドはfunctional interfaceを強制させることにより記載を標準化。

以下はstring arrayを,区切りで連結するサンプル
```java
class SampleCollector implements Collector<String, StringBuilder, String> {
    @Override
    public Supplier<StringBuilder> supplier() {
        return StringBuilder::new;
    }

    @Override
    public BiConsumer<StringBuilder, String> accumulator() {
        return (builder, str) -> {
            if (builder.length() != 0) {
                builder.append(",");
            }
            builder.append(str);
        };
    }

    @Override
    public BinaryOperator<StringBuilder> combiner() {
        return (a,b) -> {
            if (a.length() != 0) {
                a.append(",");
            }
            a.append(b);
            return a;
        };
    }

    @Override
    public Function<StringBuilder, String> finisher() {
        return builder -> builder.toString();
    }

    @Override
    public Set<Characteristics> characteristics() {
        return EnumSet.noneOf(Characteristics.class);
//        return EnumSet.of(Characteristics.CONCURRENT);
    }
    
}
public class Outer {
    public static void main(String[] args) {
        List<String> l = Arrays.asList("1","2","3","4","5");
        Stream<String> st = l.parallelStream();
        String str = st.collect(new SampleCollector());
        System.out.println(str);
    }
}
```
```
1,2,3,4,5
```
数値がどうかを検証する

# 2.9 numericality
このヘルパーは、```属性に数値のみが使われていることを検証```します。デフォルトでは、```整数値または浮動小数点数値にマッチ```します。これらの```冒頭に符号がある場合もマッチ```します。
```:only_integer```をtrueに設定すると、属性の値に対するバリデーションで以下の正規表現が使われます。
```
/\A[+-]?\d+\z/
```
それ以外の場合は、Floatを用いる数値の変換を試みます。Floatは、カラムの精度または15を用いてBigDecimalにキャストされます。
```rb
class Player < ApplicationRecord
  validates :points, numericality: true
  validates :games_played, numericality: { only_integer: true }
end
```
:only_integerのデフォルトのエラーメッセージは「must be an integer」です。

このヘルパーでは、:only_integer以外にも以下のオプションで値の制約を指定できます。

```:greater_than```: 指定の値よりも大きくなければならないことを指定します。デフォルトのエラーメッセージは「must be greater than %{count}」です。
```:greater_than_or_equal_to```: 指定の値と等しいか、それよりも大きくなければならないことを指定します。デフォルトのエラーメッセージは「must be greater than or equal to %{count}」です。
```:equal_to```: 指定の値と等しくなければならないことを示します。デフォルトのエラーメッセージは「must be equal to %{count}」です。
```:less_than```: 指定の値よりも小さくなければならないことを指定します。デフォルトのエラーメッセージは「must be less than %{count}」です。
```:less_than_or_equal_to```: 指定の値と等しいか、それよりも小さくなければならないことを指定します。デフォルトのエラーメッセージは「must be less than or equal to %{count}」です。
```:other_than```: 指定の値以外の値でなければならないことを指定します。デフォルトのエラーメッセージは「must be other than %{count}」です。
```:in```:渡された範囲に値が含まれていなければならないことを指定します。デフォルトのエラーメッセージは「must be in %{count}」です。
```:odd```: trueの場合は奇数でなければなりません。デフォルトのエラーメッセージは「must be odd」です。
```:even```: trueの場合は偶数でなければなりません。デフォルトのエラーメッセージは「must be even」です。
```デフォルトでは、numericalityのnil値は許容されません。```
```allow_nil: trueオプションでnil値を許可できます。```

デフォルトのエラーメッセージは「```is not a number```」です。

# 出典
https://railsguides.jp/active_record_validations.html#:~:text=2.9%20numericality,a%20number%E3%80%8D%E3%81%A7%E3%81%99%E3%80%82

# 感想
数字だけのバリデーションがあるのか。
他にも色々なヘルパーが使えるらしい。
これらの存在があることだけでも覚えておこう。
先で使えるかも知れない。
AccessのVBAでユーザー名やPC名をとにかく簡単に取得

# 概要

『実行ユーザー名』や『実行PC名』はテーブルのカラムやログなどに記録することが多い。
（例外発生時のトレースとかいろいろで使う）

とにかく簡単に（コーディング量少なく）取得したい。

# やり方

```Environ()``` という『環境変数の値を取得する関数』がある。

```vb:実行ユーザー名取得
Environ("USERNAME")
```

```vb:実行PC名取得
Environ("COMPUTERNAME")
```

# 蛇足

「環境変数ってなんぞ？」って時は下記。

https://qiita.com/waokitsune/items/9334cd1b4e2fec87924a

# バージョン

Windows 10 Pro 22H2 OSビルド 19045.2546
Microsoft Access for Microsoft 365 MSO (バージョン 2212 ビルド 16.0.15928.20196) 32 ビット
ReactのReact.memo、useCallback、useMemoについてまとめてみた

ReactのhooksのReact.memo、useCallback、useMemoの3つに
触れる機会があったのでまとめてみました。


- useCallback(関数をメモ化する)(メモ化→キャッシュに保存する)
```
const handleClick = useCallback(() => {
+    setCountHeavy(countHeavy + 1);
+  }, [countHeavy]);
```
countHeavyが変更されない限りhandleClick 関数は実行されない

-  useMemo(値をメモ化する)

countHeavyが変更されない限りwhile文は実行されない
```
const handleClick = usememo(() => {
+    while(i < 1000000) {
        i++;
     }
+  }, [countHeavy]);
```
countHeavyが変更されない限りhandleClick 関数は実行されない


- React.memo(コンポーネントをメモ化する、propsが変更されたら実行)
```
import React, { useState } from "react";

const Child = React.memo(props => {
console.log("render Child");
return <p>Child: {props.count}</p>;
});
```

3つともキャッシュする内容が違うだけで概念は同じ。
・useCallback=関数をメモ化する
・useMemo=値をメモ化する
・React.memo=コンポーネントをメモ化する
定義した値かどうかを検証する

# 2.7 inclusion
このヘルパーは、```指定の集合に属性の値が含まれているか```どうかを検証します。集合には任意のenumerableオブジェクトが使えます。
```rb
class Coffee < ApplicationRecord
  validates :size, inclusion: { in: %w(small medium large),
message: "%{value} のサイズは無効です" }
end
```
inclusionヘルパーには:inオプションがあり、受け付ける値の集合を指定します。```:inオプションには:withinというエイリアスもあり、好みに応じてどちらでも使えます。```
上の例では、属性の値をインクルードする方法を示すために:messageオプションも使っています。完全なオプションについては、:messageのドキュメントを参照してください。

このヘルパーのデフォルトのエラーメッセージは```「is not included in the list」```です。

# 出典
https://railsguides.jp/active_record_validations.html#:~:text=2.7%20inclusion,the%20list%E3%80%8D%E3%81%A7%E3%81%99%E3%80%82

その属性が持つ値が```inclusion内で定義した値に含まれているか```を検証します。

# 出典
https://kossy-web-engineer.hatenablog.com/entry/2019/06/26/211720

# 感想
求めていたバリデーションヘルパーがあってよかった。
また公式では理解が自分ではできなかったので２番目の記事も読めたことで理解が深まった。
ありがたい。