OmniAICreator/Qiita-1.07M huggingface dataset:
お母さんでもわかるNext.js✖️React

## そもそもNext.jsとは
Reactベースのフレームワーク。

## Next.js と Create React Appとの違いは？

代表的な違い
・Nextにはサーバー機能がある
・NextにはURLルーティングがある。→ファイルに合わせてURJ¥L生成をしてくれる
・Nextは画像、レンダリング(SSRとか)を最適化してくれる
・Nextには「ゼロコンフィグ機能」→webpack等のパッケージインストール、設定の必要がない。
・Reactの方が他フレームワークに組み込みやすい

## CSR(SPA)、SSR、SG、ISRについて
・CSR(SPA)
クライアント側でレンダリングを行う方法。
最初にブラウザへからのHTMLを渡し、ページ全体をJSで生成しています。
一度読み込んでしまえば、ページ遷移のたびにサーバーへのリクエストが発生しないため高速で動作させることが可能。
ただ問題点がいくつかあり、JSのサイズが膨大になると初期表示の読み込みに時間がかかったり、表示速度はクライアント側に依存するためスペック次第で表示速度が変わる。

・SSR
CSRの問題を解決するために、レンダリングをサーバー側で行い、動的なHTMLを生成してからクライアントに渡す方法ができた。それがSSR。（CSRの作業をサーバー側でやっちゃえって感じ！）
でかいJSを送信しなくて済むが、今度はサーバー側の負担が問題になる。

・SG
SSRの問題を解決するために事前に静的なHTMLを生成しておこう。というのがSG。
負担は減ったが、頻繁に更新されるサイトには不向き。何故ならデプロイ時に静的HTMLを作成するのだが、デプロイ後にページの内容を動的に変更しづらいため。

・ISR
SGの問題を解決るすために、「SSR」と「SG」のいいとこ取りをしたのがISR。
SSRのようにリクエストに応じて動的なHTMLを作成するが、実際にクライアントに渡すのは既に作成済み(一つ前)の静的なHTML。
そのためSGと同じレベルでレスポできる。

**・ルーティング**
pagesディレクトリ内の各Reactコンポーネントは、そのURLパスに対応するルートとして扱われます。
※また、Next.jsは、ルーティングの一部としてパラメータを指定するできる動的ルーティングをサポートしています。

**・APIルート**
サーバーサイドの処理を簡単に実行でき、クライアントとサーバーの間の通信をスムーズに行うことができるもの。
Next.jsのpages/apiディレクトリ内に作成されるJavaScriptファイルによって定義されている。
	
## 各フォルダについて
・`.next`
next.jsを動かすためのファイル。
webpackと同じように（srcディレクトリの中をwebpackを使用してコンパイルし、distファイルの中にコンパイル後のファイルを配置）、`pages,public,styles`などを.nextファイルにコンパイルして動かしている。
**※「webpackと同じように」というか、裏でしっかり動いてます。**

・`node_modules,package.json,yarn.lock`
``` package.json
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
```
`"dev": "next dev"` →基本ここで開発をスタート
`"build": "next build"`→本番環境を確認したいときに、この2行を実行する
`"start": "next start"`

・`pages`
ファイルシステムルーティングの最も重要なところ。ようは、表示させるページが入ってるよ！！

・`public`
画像やアイコンなどの静的なもんのが入っているファイル
neosでlogix その119

# 概要
neosでlogixやってみる。
neoscheckbox、使ってみた。

# 写真

![2023-04-29 21.46.16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/45f979be-1747-391a-4228-96ba680fd32c.jpeg)

# 手順
- devtoolを装着
- 新規作成>オブジェクト>checkboxをスポーン
- インスペクターを表示
- logixtoolを装着
- neoscheckboxのインターフェースを取り出す
- ischeckedのvalueを取り出す



以上。
GPT-4のAPIが使えるようになったのでChatGPTのクローンアプリを試してみる

# はじめに
ようやく私もOpenAIのAPIでGPT-4が扱えるようになり使い込んでいきたいと思うが、まずは、普段使っているChatGPTをAPIを使ったアプリに置き換えて、ChatGPT Plusの利用料を削減できないか考えてみた。

調べてみると、ChatGPTのクローンアプリが既にいくつか存在しているようで、今回は、その中でもクオリティが高く、置き換えるのには良さそうな以下のクローンアプリを試しに使うこととした。

https://github.com/danny-avila/chatgpt-clone

# 免責事項
本記事でChatGPTのクローンアプリについて紹介しますが、ChatGPTからの移行を推奨するものではありません。あくまでOpenAIのAPIの活用の一例として紹介しており、個人利用の範囲で使うことを想定しています。

# 構成
このchatgpt-cloneは、主に3つの要素で成り立っている。

- 本体となるアプリケーション部分 （Node.js製)
- データベース (MongoDB)
- 全文検索用のエンジン (MeileSearch)


# Setup
まずは、`.env`ファイルを用意する。

```sh
cp api/.env.example api/.env
```

`.env`ファイル内にOpenAIのAPI Keyを設定する。

```
OPENAI_KEY=xxxxxxxxxxx
```

# 実行
今回はDockerで立ち上げた。

```sh
docker compose up -d
```

立ち上がったらブラウザでアクセス。デフォルトではポート番号は3080。

```http
http://localhost:3080
```

# 使ってみる

以下は実際の画面。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/78329948-3cb1-1398-6d46-e30079dcf5b2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/526b84a8-425d-fb59-5c86-bf7f01b78bd5.png)

見ての通り再現度は非常に高く、快適に利用できた (モバイルも対応している様子)。


さらにはChatGPTにはない機能もいくつか持っている (2023/04/30現在)。

例えば、初期条件とするプロンプトや各種パラメータを変更してプリセットとして登録可能となっていたり、会話の全文検索機能や会話の出力機能なども備わっている。もちろん本家もPlugin機能を持っているので、今後はこのあたりのことも可能になるかもしれない。

以下は、プリセットの設定画面、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/7f3a289a-1df3-eb9d-f159-00f596ad83c1.png)


他の良い点として、やはり料金面については、ローカル上で利用する範囲では基本的にOpenAIのAPI利用量 (従量課金) のみであるため格安でGPT-4を使ったチャットを体験できる。また、これはAPIの利点であるが、時間内のリクエスト制限もChatGPT Plusのように厳しくないため、いくらでも質問可能になったのもとても良かった。

# まとめ
OpenAIのAPIを活用したサービスが数多くうまれている中でこのようなChatGPTのクローンアプリもいくつか誕生している。今後はChatGPTから派生して、さまざまな系統のチャットアプリができていきそうだと感じた。
他にもAPI Keyさえあれば使えるGPT関連のアプリは存在しているので、いろいろと試して、今後の創作に繋がればと思う。
標準エラー出力を標準出力へリダイレクト（＆合流）

こんにちは。
標準エラー出力のリダイレクト ```2>&1``` を調べました[^1] [^2]。
* 『標準エラー出力の割当先を、「規定の標準出力割当て先」へ合流とする』ことになります。

### 動作例 ###
```console
$ function test_output() { perl -e 'print "1\n"; warn "2\n2\n";'; }; test_output
1
2
2
$ test_output 2>&1 | wc -l
       3
$ test_output 1>/dev/null 2>&1 | wc -l
       0
$ test_output 2>&1 1>/dev/null | wc -l
       2
$ test_output 1>temp.txt 2>&1; cat temp.txt 
2
2
1
```

### 文法説明 ###
#### file descriptor _(FD)_ ####

* ```1```：標準出力
* ```2```：標準エラー出力


#### 出力割当て先 ####

* 画面：デフォルト
* ファイル：書込み
* ```/dev/null```：捨てる

#### 出力リダイレクト（規定の出力割当て先を変更） ####

* ```>```：上書き型
* ```>>```：追加書き型

#### 出力リダイレクト＆合流割当て ####

* ```>&```_FD_
  * ```>&1```：標準出力割当先へ




### 合流とはならない例 ###

```console
$ test_output 1>temp.txt 2>temp.txt; cat temp.txt
$ test_output 2>temp.txt 1>temp.txt; cat temp.txt
1
2
$
```

[^1]: 参考：「[>/dev/null 2>&1は順序が逆だとダメ](https://qiita.com/ryskiwt/items/d4e7846fd47364a2a4e2)」
[^2]: 参考：「[いい加減覚えよう。 `command > /dev/null 2>&1`の意味](https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea)」
NeurIPS2022の枝刈り論文 (1)

# 概要

この記事では、[NeurIPS2022](https://nips.cc/)の枝刈り論文を紹介します。[^1]

[^1]: 画像や数式は論文から引用しています。

# Structural Pruning via Latency-Saliency Knapsack

https://openreview.net/forum?id=cUOR-_VsavA

- 概要：Hardware-awareなstructured枝刈りの改良
- 研究機関：NVIDIA
- 新規性：Hardware-awareな枝刈りを組合せ最適化として解く方法を提案
- キモ：
  レイヤ毎に重要度とレイテンシを推定して、制約下でナップサック問題で最適化する。
  重要度はロスのテイラー展開の1次の係数とBatchNormalizationの$\gamma, \beta$で測る。
  Neuron Groupingで高速化する。
- 評価：ResNet50, MobileNet等で実験した。


# SAViT: Structure-Aware Vision Transformer Pruning via Collaborative Optimization

https://openreview.net/forum?id=w5DacXWzQ-Q

- 概要：ViTの枝刈り。
- 新規性：要素間の構造も考慮して枝刈りする。
- キモ：パラメータの巨大Hessianをパラメータの種類毎に分割して、それぞれの種類でHessianと相互作用を測る
- 評価：DeiTやSwin-Transformer等で、ImageNet・COCO評価した。


# Advancing Model Pruning via Bi-level Optimization 

https://openreview.net/forum?id=t6O08FxvtBY

- 概要：BiP. 枝刈りの新しいアルゴリズム
- 研究機関：IBM
- 新規性：枝刈りをBi-level Optimization (BLO) と考えて解くアルゴリズムを提案した。
- キモ：BLOとして定式化する((1)式)
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/0324bb50-522e-b66d-44d2-36322560bce9.png)
  BLOの解き方で最適化する。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/423fde06-bfb3-b991-6593-a3dc91175ac4.png)
- 評価：CIFAR, ResNetで実験した。


# On Measuring Excess Capacity in Neural Networks

https://openreview.net/forum?id=l2CVt1ySC2Q

- 概要：DNNの余剰能力の測定と枝刈りの考察
- 新規性：Rademacher complexityを使って枝刈りでどこまで刈れるかの考察・実験をした。
- キモ：実験により2つの知見を見出した。
  1. かなり刈っても精度維持できる。
  2. タスクが違っても刈れる量のオーダは同じくらいである。
- 評価：ResNet-18, CIFAR, Tiny-ImageNetで実験した。


# Rare Gems: Finding Lottery Tickets at Initialization

https://openreview.net/forum?id=Jpxd93u2vK-

- 概要：Gem-Miner. 当たりくじを見つける方法
- 新規性：当たりくじを探す方法で、従来は収束しない可能性がある課題を解決する。
- キモ：[強い宝くじ仮説論文](https://qiita.com/kyad/items/1f5520a7cc268e979893#%E5%AE%9D%E3%81%8F%E3%81%98%E4%BB%AE%E8%AA%AC%E3%81%AE%E5%BE%A9%E7%BF%92)のedge-popupアルゴリズムに、正則化とfreezingを入れたアルゴリズム
- 評価：CIFAR-10, ResNet, MobileNet等でIMPなどと比較した。
統計検定準一級までの道のり[更新中]

## 前提
~~2023年9月に受験予定~~
2025年5月下旬に受験予定（大分サボっていました汗）

- 頭の整理のために殴り書きしています。いつか綺麗にはするつもりです（適当）
- 内容の妥当性は担保できないのでご注意ください。


## 各章について

### 第13章　ノンパラメトリック法

- 2級までは母集団の分布を仮定して検定を行っていたが，母集団の分布が分からない場合に検定を行いたい場合もある。その場合の手法を学ぶ。

1.ウィルコクソンの順位和検定
A群とB群の順位和を計算し，その値からp値を求め，検定を行う。p値を求めるときは，コンビネーションを使って求めることが（準一級では多そう？）

2.並べ替え検定
あとで記載

### 第14章　マルコフ連鎖

1. 定常分布

長い時間の後，状態確率は，πに収束することがある（条件はあとで確認したい）

そのπを求める問題が多い？その場合は，以下の行列を解けば良い。

```
π = πA 
```

### 20章　分散分析と実験計画法

1. 1元配置
2. （1元配置）乱解法 
3. 直行表

### 21章　標本調査法

非復元抽出の場合や，層化抽出法の場合の，分散がどうなるかを学ぶ
層化抽出法は，無作為抽出法より分散が小さくなるのもポイント

1. 非復元抽出

    ```
    V[x̄]= ((N-n)/(N-1)) * (1/n) * σ^2 
    ```

    ```
    (N-n)/(N-1) # 有限修正項
    ````

2. 層化抽出法

各層から抽出する標本の大きさの決め方にもいくつか種類がある

 - 比例配分法
     - 母集団の大きさに比例して決める
 - 等配分法
     - 標本の大きさが全て等しくする
 - ネイマン配分法
     - 推定量の分散を最小にするような標本配分法
     - 層の大きさと層内標準偏差を加味して計算する
     - 母集団の大きさは既知な場合が多いが，標準偏差は未知である場合が多いので，過去の調査での標準偏差などから引用することがある

### 22章 主成分分析

### 23章 判別分析

1.
2.
3.SVM

### 24章 クラスター分析

1.最短距離法、最長距離法
    - 両方とも一番近い距離のクラスタをまとめていく方法
    - "最短"距離、"最長"距離は、クラスタまとめ後にクラスタ内のどのデータを使うかに関わってくる
    - 最短距離法は、1つのずつクラスタに融合していくので、鎖効果が起きやすい
    - 両者との外れ値の影響を受けやすいので注意
    - 
2. ウォード法

（後ほど記載）

3. K-MEANS

（割愛）

### 25章 因子分析・グラフィカルモデル




# 注意
イメージや裏付けを取らず記載しているので内容の妥当性は担保していません

# 参考リンク

まとめのサイト

https://zenn.dev/dlbsabu/articles/5300da50921070

時系列の勉強

https://syleir.hatenablog.com/entry/2021/12/14/195144
X-NUCLEO-GFX01M1の十字KEYで遊ぶ(STM32G071)



目的
ついていたから十字キーのテスト

![o_cop476.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/37fa747b-5966-b979-4b71-d91fcd77a952.jpeg)

![o_cop477.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4f9efdd8-d39f-4b75-fe61-e1fa11e1895a.jpeg)

![o_cop478.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/744973a5-5b28-3319-86f9-96f377239476.jpeg)



```c++



//X_NUCLEO_GFX01M1_JOYKEY_071


//初期化
void setup() {

  // シリアルの初期化
  Serial.begin(9600);
  Serial.println("START");

  //ポートの設定
  pinMode(PC9  ,INPUT); // LEFT
  pinMode(PC11 ,INPUT); // RIGHT
  pinMode(PC12 ,INPUT); // UP
  pinMode(PC10 ,INPUT); // DOWN
  pinMode(PC8  ,INPUT); // CENTER


} //setup


//メインループ
void loop() {


  if(digitalRead(PC9)  == 0) {Serial.print("LEFT.");}
  if(digitalRead(PC11) == 0) {Serial.print("RIGHT.");}
  if(digitalRead(PC12) == 0) {Serial.print("UP.");}
  if(digitalRead(PC10) == 0) {Serial.print("DOWN.");}
  if(digitalRead(PC8)  == 0) {Serial.print("CENTER.");}


  delay(500);        // 0.5秒待つ

} //loop




```
Windowsでシンボリックリンクを使ってプロダクトのバージョンを切り替えられるようにする

## TL;DR

シンボリックを使ってプロダクト(たとえばjdk17.0.7とかjdk17.0.6とか)を切り替えるようにして、パスを通す箇所をシンボリックリンク(この例ではPATHやJAVA_HOMEを`jdk_current`みたいなシンボリックリンク)にしとくと、バージョンアップ時に環境変数などを書き換えまくらなくて済むようになるよ。

## やってみる

### シンボリックリンクを貼る

jdkが入ってるフォルダーに移動して、`New-Item`でシンボリックリンクを張る。

```powershell
New-Item -ItemType SymbolicLink -Path "E:\PROGRAM\Amazon Corretto\jdk_current" `
  -Target ".\jdk17.0.7_7"
```

### 環境変数を設定する(一例)

`sysdm.cpl`とかを叩いて、シンボリックリンクをパスをした設定を環境変数等に追加する。リブートするなどして環境変数をうまく読み込ませる。
以下では`JAVA_HOME`しか書いていないけど、`PATH`も追加した。

![env_java_home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/8243bee8-f319-cc09-5112-9ba806e10e04.png)

### 確認する

Symbolic linkの確認

```powershell
PS E:\PROGRAM\Amazon Corretto> Get-ChildItem | Select-Object FullName, LinkType

FullName                                LinkType
--------                                --------
E:\PROGRAM\Amazon Corretto\jdk_current  SymbolicLink
E:\PROGRAM\Amazon Corretto\jdk1.8.0_222
E:\PROGRAM\Amazon Corretto\jdk17.0.7_7
E:\PROGRAM\Amazon Corretto\jre8
```
```powershell
PS E:\PROGRAM\Amazon Corretto> Get-ChildItem .

    Directory: E:\PROGRAM\Amazon Corretto

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
l----          2023/04/30     0:47                jdk_current -> .\jdk17.0.7_7
d----          2019/08/29    23:01                jdk1.8.0_222
d----          2023/04/30     0:34                jdk17.0.7_7
d----          2019/08/29    23:01                jre8

PS E:\PROGRAM\Amazon Corretto>
```

javaコマンドの確認

```powershell
PS E:\PROGRAM\Amazon Corretto> java -version
openjdk version "17.0.7" 2023-04-18 LTS
OpenJDK Runtime Environment Corretto-17.0.7.7.1 (build 17.0.7+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.7.7.1 (build 17.0.7+7-LTS, mixed mode, sharing)
```

## 今後

新しいJDKをインストールしたら、このシンボリックリンクを新しいJDKのパスに書き換えれば引き続き使い続けられる、という算段。
迷路　あるいは　カリグラム的プログラム

迷路を出力するプログラムを Rust で書いてみました。

```rust
use rand::seq::SliceRandom;struct M{w:usize,h:usize,
r:Vec<R>}impl M{fn new(w:usize,h:usize)->Self{let r:
Vec<            R>=             vec!            [];M
{w,h            ,r}}            fn b(           &mut
self    ){if    self.   r.len   ()>0    {self.r=vec!
[];}    let     mut     ws:     Vec<    (usize,usize,
bool    )>=             vec!            [];     for
rid     in 0            ..self          .w*     self
.h{     self.r.push(R::new(     rid));if rid%   self
.w<     self.w-1{ws.push((      rid,rid+1,true  ));}
if      rid/    self            .w<     self    .h-1
{ws.    push(   (rid,           rid+    self    .w,
false));}}      let     mut     rng=    rand      ::
thread_rng()    ;ws.  shuffle   (&mut   rng);   for(
rid1,           rid2,   v)in    ws{let          aid1
=self           .r[     rid1]   .aid            ;let
aid2=self.r[    rid2].aid;if   aid1==  aid2{continue
;}if aid1<      aid2{self.u(    aid2,   aid1);}else{
self                            .u(             aid1,
aid2                            );}            if v{
self.   r[rid1].e=false;}else   {self   .r[rid1].s=
false   ;}}}fn u(&mut self,     aid1:   usize,aid2:
usize   ){for                                   i in
0..     self.w                                 *self
.h{if self.r[i].aid==aid1{self.r[i].aid=aid2;}}}fn p
(&self){println!("{}+","+-".repeat(self.w));for i in


 0..   self       .h{         print!("|"  );for j in
 0..   self       .w{             print!  (" {}"
 ,if   self      .r[i*            self    .w+j
 ].e  {"|"}      else{           " "})    ;}print!
 ( "\n+" );     for j in        0..self   .w{print!
 ("{}+" ,if    self.r[i*      self        .w+j
 ].s{    "-"}  else  {" "}    );}println!  ("");}}
}struct R{aid :usize,e:bool, s:bool,}impl R{fn new(aid

  :usize)->Self{Self{aid:aid,e:true,s:true,}}}fn main(){
        let mut m=M::new(20,20);m.b();m.p()}
```

プログラム書くよりもバナー作る方がめんどくさかった。

AKAMAI Tシャツに対抗してこれでTシャツ作るか！
Raspberrypi＋GobotとタクトスイッチボタンでLチカ

前回の記事に続き、GoBotをつかってLチカをやってみたので備忘録。前回の記事は下記掲載。

https://qiita.com/hskm07/items/0760320aeb4837be8081

## 準備

* Raspberrypi3 model b+

## 今回やったこと

ボタンを押したらLEDが点灯するという、Raspberrypi初心者にあるあるな例をGobotでやってみます。

### 配線図

raspberrypiとLEDとボタンの配線図です。

| 内容 | 接続先 |
| :--- | :---- |
| タクトスイッチ上の足 | 1番ピン(3.3v) |
| タクトスイッチの下の足 | 抵抗を経由して14番ピン(GND)、12番ピン(Port18)
| LEDのカソード(マイナス) | 34番(GND) |
| LEDのアノード(プラス) | 抵抗を経由して40番ピン(Port21) |

![layout_raspi_button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1024959/3c32e4ec-b3d8-3a5e-b55e-28fe85021898.png)



### ソースコード

`main.go`を以下のように変更します。

> 参考：<https://gobot.io/documentation/examples/raspi_button/>

```go
package main

import (
	"fmt"

	"gobot.io/x/gobot"
	"gobot.io/x/gobot/drivers/gpio"
	"gobot.io/x/gobot/platforms/raspi"
)

func main() {
	adaptor := raspi.NewAdaptor()
	button := gpio.NewButtonDriver(adaptor, "12")
	led := gpio.NewLedDriver(adaptor, "40")

	work := func() {
		button.On(gpio.ButtonPush, func(data interface{}) {
			fmt.Println("Button Pressed")
			led.On()
		})

		button.On(gpio.ButtonRelease, func(data interface{}) {
			fmt.Println("Button Released")
			led.Off()
		})
	}

	robot := gobot.NewRobot("ButtonBot",
		[]gobot.Connection{adaptor},
		[]gobot.Device{button, led},
		work,
	)

	robot.Start()
}

```

### 動作

それでは、Lチカさせてみましょう。

```bash
$ go run main.go
>>>2023/04/30 00:12:13 Initializing connections...
>>>2023/04/30 00:12:13 Initializing connection RaspberryPi-6ACB3C4D ...
>>>2023/04/30 00:12:13 Initializing devices...
>>>2023/04/30 00:12:13 Initializing device Button-70F89516 ...
>>>2023/04/30 00:12:13 Initializing device LED-2EA9178A ...
>>>2023/04/30 00:12:13 Robot ButtonBot initialized.
>>>2023/04/30 00:12:13 Starting Robot ButtonBot ...
>>>2023/04/30 00:12:13 Starting connections...
>>>2023/04/30 00:12:13 Starting connection RaspberryPi-6ACB3C4D...
>>>2023/04/30 00:12:13 Starting devices...
>>>2023/04/30 00:12:13 Starting device Button-70F89516 on pin 12...
>>>2023/04/30 00:12:13 Starting device LED-2EA9178A on pin 40...
>>>2023/04/30 00:12:13 Starting work...
>>>Button Pressed
>>>Button Released
>>>Button Pressed
>>>Button Released
>>>...
```

タクトスイッチを押すとLEDが点滅し、コンソールにはボタンを押すと、`Button Pressed`と表示され、ボタンを話すと`Button Released`が表示されます。

## おわりに

引き続き、Gobotを使って楽しいラズパイライフを送ろうと思います。
マックのpython3でslugifyを既にインストールしているのに、スクリプトでimportしてもModuleNotFoundErrorが出てしまう件 

[python-slugify 8.0.1](https://pypi.org/project/python-slugify/)、[awesome-slugify
](https://pypi.org/project/awesome-slugify/)、[unicode-slugify](https://pypi.org/project/unicode-slugify/)と、それぞれ試してみましたが、どれもこれも「モジュール見つかりません」エラーがでて動かない。

```
from slugify import slugify
ModuleNotFoundError: No module named 'slugify'
```

モジュールのインストール自体は正常に行われているようだ。

```
% pip show unicode-slugify
Name: unicode-slugify
Version: 0.1.5
Summary: A slug generator that turns strings into unicode slugs.
Home-page: http://github.com/mozilla/unicode-slugify
Author: Jeff Balogh, Dave Dash
Author-email: jbalogh@mozilla.com, dd@mozilla.com
License: BSD
Location: /opt/homebrew/lib/python3.11/site-packages
Requires: six, unidecode
Required-by: 
```

ダメ元で[conda forge](https://anaconda.org/conda-forge/python-slugify)からインストールしてみたら動いた

```
% conda install -c conda-forge python-slugify

Retrieving notices: ...working... done
Collecting package metadata (current_repodata.json): done
Solving environment: - 
The environment is inconsistent, please check the package plan carefully
The following packages are causing the inconsistency:

  - conda-forge/osx-arm64::ipython==7.31.1=py38h10201cd_0
  - conda-forge/osx-arm64::scipy==1.7.3=py38hd0c9ec0_0
以下省略
```

頼んでないものまで延々とアプデされたりしたので驚いたけど、何かわからないけど凄く動いていて効き目がありそうな感触だけは凄い。１分くらいでインストールが無事終了。

```
from slugify import slugify
print(slugify('aads AAda asd as'))
```

出力結果：

```
aads-aada-asd-as
```

環境：

- M1 Mac
- Python 3.8.12
RustでExcelのウィンドウ枠を固定する

フリーランスエンジニアとして活動していて、現在携わっている案件ではRustとTauriを使ってExcelファイルを出力するデスクトップアプリを開発しています。先日、顧客から出力するExcelファイルで1行目を固定して常に表示するようにしたいという要望があり、RustでExcelのウィンドウ枠を固定する方法を調べました。

RustでExcelファイルを書き込むためのライブラリはいくつかありますが、ウィンドウ枠を固定できたのが「[xlsxwriter-rs](https://docs.rs/crate/xlsxwriter/0.6.0)」だった（他にもあるかもしれませんが）ので、今回は「xlsxwriter-rs」を使用します。

xlsxwriter-rsでExcelのウィンドウ枠を固定するには`freeze_panes`メソッドを使用します。第一引数に固定する行番号、第二引数には固定する列番号を渡します。固定しない場合は`0`を指定します。

> pub fn freeze_panes(&mut self, row: WorksheetRow, col: WorksheetCol)
>> The Worksheet::freeze_panes function can be used to divide a worksheet into horizontal or vertical regions known as panes and to “freeze” these panes so that the splitter bars are not visible.
>> The parameters row and col are used to specify the location of the split. It should be noted that the split is specified at the top or left of a cell and that the function uses zero based indexing. Therefore to freeze the first row of a worksheet it is necessary to specify the split at row 2 (which is 1 as the zero-based index).
>> You can set one of the row and col parameters as zero if you do not want either a vertical or horizontal split.

https://docs.rs/xlsxwriter/0.6.0/xlsxwriter/worksheet/struct.Worksheet.html#method.freeze_panes

`freeze_panes`メソッドを使用して1行目と1列目でウィンドウ枠を固定するサンプルコードを載せます。

```Rust:Rust
use std::path::Path;
use rust_xlsxwriter::Workbook;

let mut book = Workbook::new();
let sheet = book.add_worksheet();
sheet.set_freeze_panes(1, 1)?;
sheet.write_string(0, 0, "Header1")?;
sheet.write_string(0, 1, "Header2")?;
for i in 1..101 {
    sheet.write_number(i as u32, 0, i as f64)?;
    sheet.write_number(i as u32, 1, (i * 2) as f64)?;
}
book.save(Path::new("test.xlsx"))?;
```

![スクリーンショット 2023-04-30 0.27.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/5d7f4743-2307-05c2-00ba-9345ed6103cd.png)


↑のスクリーンショットではちょっと分かりづらいですが、無事RustでもExcelのウィンドウ枠の固定が実現できました。
TextMesh Pro　すべての日本語フォントをUnicode Rangeで作ってみよう

TextMesh Proは素晴らしいですよね。
高解像度で、いろんな見た目にすることができますから。
ですが、ひとつ欠点があります。
それは、日本語フォントを作るためのプリセットがないことです。
英語であればASCIIを選択して作成すればいいのに日本語はない。
というか、英語のほかは全くないという状況であります。
そこで自分なりにUnicodeを調査して、CustomRangeにコピペすれば簡単にフォントを作れるようにと記録を残そうと思いました。

#Unicodeの公式サイトがあるじゃんか
UnicodeだってASCIIとだいたい同じ仕組みなんですから一覧表があるだろうと考えました。
Wikipediaで調べてみると関連リンクに公式サイトがありました。
ユニコードコロシアムです。
https://home.unicode.org/
さて、問題は一覧表です。きっとどこかにあるだろうと探してみるとありました。

赤い丸で囲ったところです。
![CodeCharts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87165/8f00b26d-0e85-05c5-221b-506339f218aa.png)

ここです！ここ！このリンクの中には世界中のUnicodeが詰まってした。
https://www.unicode.org/charts/

見てください！画面に収まりきらないほどのおびただしい数のUnicodeを！
※正確にはUnicodeの一覧ではなくて、文字コードの一覧が記載されているPDFファイルのリンクの一覧になります。
![2023-04-30 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87165/98b81ae4-f2c5-c177-376a-6be017131b8d.png)


#CustomRangeはどこに書いてあるの？

さきほどの一覧の、このへんの適当なリンクのPDFファイルの一番上に書いてあります。
右端の２段目の項目ですね。この項目に日本語関連のファイルがあります。
![2023-04-30 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87165/083d06c8-126b-65f7-3d07-9d3fe5a6a5fe.png)


いろいろと見てみると以下がわかります
ASCII：0000–007F
ひらがな：3040–309F
カタカナ：30A0–30FF
半角ｶﾀｶﾅ：FF00–FFEF
CJK統合漢字：4E00-9FEF

これをコピペして貼り付けます
0000–007F,3040–309F,30A0–30FF,FF00–FFEF,4E00–9FFF

そして、Generate Font Atlas を押します。
あとは、待つだけです。
dockerfile_inlineでcompose.yamlにDockerfileをインラインで書く

# 概要
先日出たDocker Compose v2.17.3から `dockerfile_inline` という構文で `compose.yaml` にDockerfileをインラインで書けるようになりました。これのなにがうれしいかというと、メインのアプリケーションではなく周辺のミドルウェアなどでDockerfile書くほどでもないんだけど、ちょっとだけカスタマイズしたいみたいなのが書きやすくなる。

https://github.com/compose-spec/compose-spec/pull/315

※厳密に言うと `dockerfile_inline` という構文自体はcompose v2.17.0から追加されましたが、初期実装は[バグ](https://github.com/docker/compose/issues/10456)があり機能してなかったので、実質まともに使えるようになったのはv2.17.3からです。

# 環境

本稿執筆時点の最新版のDocker Desktop for Mac v4.19.0にバンドルされてるcomposeがv2.17.3だったので、とりあえず最新に上げて試します。

```
$ docker compose version
Docker Compose version v2.17.3

$ docker version
Client:
 Cloud integration: v1.0.31
 Version:           23.0.5
 API version:       1.42
 Go version:        go1.19.8
 Git commit:        bc4487a
 Built:             Wed Apr 26 16:12:52 2023
 OS/Arch:           darwin/arm64
 Context:           default

Server: Docker Desktop 4.19.0 (106363)
 Engine:
  Version:          23.0.5
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.8
  Git commit:       94d3ad6
  Built:            Wed Apr 26 16:17:14 2023
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.20
  GitCommit:        2806fc1057397dbaeefbea0e4e17bddfbd388f38
 runc:
  Version:          1.1.5
  GitCommit:        v1.1.5-0-gf19387a
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

本題と関係ないですが、Docker Desktop v4.19.0 からDocker Engineがついにv20.10系からv23.0系になりました。やったね。
https://docs.docker.com/desktop/release-notes/#4190

# やってみた

公式ドキュメントはこちら
https://docs.docker.com/compose/compose-file/build/#dockerfile_inline

試しに適当なalpineのベースイメージにcurlを追加してみる。

```compose.yaml
services:
  curl:
    build:
      context: .
      dockerfile_inline: |
        FROM alpine
        RUN apk --no-cache add curl
        ENTRYPOINT ["curl"]
```

ビルド

```
$ docker compose build
```

実行

```
$ docker compose run --rm curl -sI https://google.com | head -1
HTTP/2 301
```

よさそう。

別にDockerfile書くのと機能的には変わらないんですが、 `compose.yaml` 1枚に書けると、シュッとコピペしやすくなるのもうれしい気がする。

# 余談

compose v2から `docker-compose` コマンドは `docker compose` になっており、ファイル名は `compose.yaml` が公式に推奨されています。

https://docs.docker.com/compose/compose-file/03-compose-file/

後方互換性のため `docker-compose.yaml` or `docker-compose.yml` も読み込まれますが、ファイル内にフォーマット `version` 指定も不要です。おやっと思った人は、知識がcompose v1で止まってそうですが、compose v1は2023年6月にEOLの予定なので、知識もv2にアップデートしておきましょう。

おしまい。
JavascriptでブラウザからPinecornに対して検索を実行


### 概要

以下で作成したPinecornに登録したベクトルに対してブラウザから検索リクエストを実行した。

https://qiita.com/tthogho1/items/869166d5b65bca4d69d8

サーバレスで使用したく、javascriptから手軽に検索できることを期待したが、クロスドメイン制約を回避することができず、結局Webサーバ(Apache)を使用して実行した。

### 環境
CentOS Stream 9(docker)
Apache 2.4

### やったこと

#### テスト画面作成
ボタンを押したら、画像からベクトルを生成してqueryを投げるようjavascriptを作成した。
検索に使用した画像は、ベクトル登録時にも使用したファイル。ベクトル生成も、同じように実施した。つもり。
検索の条件は、nodeから実行したときと同じく類似した検索の上位5件を取得する。

```html
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
<script>
async function check(){

	const model = await tf.loadGraphModel("https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v2_100_96/feature_vector/2/default/1",{ fromTFHub: true });
	const img = document.getElementById('myImage');
	const tensor = tf.browser.fromPixels(img).resizeBilinear([96, 96]).expandDims(0).toFloat().div(tf.scalar(127)).sub(tf.scalar(1));

	const features = await model.predict(tensor);
    const float32array = features.dataSync();
    const featureVector = Array.from(float32array.slice(0));

	fetch('http://localhost/query', {
  		method: 'POST',
  		headers: {
    		'Content-Type': 'application/json',
    		'Api-Key': '<apiキー>'
  		},
  		body: JSON.stringify({
    			vector: featureVector,
    			topK: 5,
    			includeMetadata: false,
    			includeValues: false,
    			namespace: 'imageindex'
  		})
	}).then(response => response.json()
	).then(data =>{
  		console.log(data);
	}).catch(error => {
		console.log(error);
	});
}

</script>
</head>
<body>
<button type="button" onclick="check()">check</button>
<img id="myImage" src="1011516521.jpg"></img>
</body>
</html>
```

#### Apacheの設定
Pinecornには、Mongodb AtlasのBearer 認証のような、CORSエラーの対策はなさそうだった。なので、ローカル環境のWebサーバ(Apache)に、作成したHTMLファイルを配置(デフォルトの/var/www/html/index.html)し、プロキシの設定を行った。パスが/queryの場合、PinecornのURLにリクエストを送信するようにした。

転送先は、httpsのサイトのため、mod_sslをインストールしてhttp.confに以下を追記した。
```conf
<VirtualHost *:80>
        ServerName any
        SSLProxyEngine on
        ProxyPass /query https://imageindex-c5a7176.svc.us-east-1-aws.pinecone.io/query
        ProxyPassReverse /query https://imageindex-c5a7176.svc.us-east-1-aws.pinecone.io/query
</VirtualHost>
```


### 実行結果

検索結果は、前にnodeから検索したときの画像（ベクトル）と同じものが返ってきた。
が、順序が若干異なっており、また同じ画像でもscoreが1にはなってないのは気になるが、追及する力はない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284235/f3436fc2-f257-2352-7ffe-80ac5c69b1a1.png)

ちなみに1番似ているとされる画像。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284235/d9cfacbd-bf7d-bf84-b4ae-3f96af9d86e6.png)
RedmineからOffice365へのメール送信

# 内容
　EC2からDockerで立ち上げたredmineで、OFFICE365へのmail送信が出来ず、ついにpythonでリレーメールすることで解決した。 

# 完成コード
　一応、自宅のNASでは動作した。月曜に会社の環境で再テストする。
　なぜRedmineから送れなかったのかは、原因不明のままであるが・・・

# 注意点
* NASはIPアドレスとすること（ホスト名では送れず）
* 1025はポート開放すること
* dockerホストのアドレスでは送信不可(localhost)

```python.py
import smtpd
import asyncore
import smtplib
import pdb

class CustomSMTPServer(smtpd.SMTPServer):
    def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
        # Forward the message to another SMTP server
        smtpObj = smtplib.SMTP('smtp.office365.com', 587)
        smtpObj.starttls()
        smtpObj.login("アドレス","パスワード")
        smtpObj.sendmail("送信元", "宛先", data)

server = CustomSMTPServer(('192.168.1.40', 1025), None)
asyncore.loop()
```

```configuration.yml
default:
  # Outgoing emails configuration
  # See the examples below and the Rails guide for more configuration options:
  # http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
  email_delivery:
  # ==== Simple SMTP server at localhost
    delivery_method: :smtp
    smtp_settings:
      address: "192.168.1.40"
      port: 1025
```

# はまったこと
・Redmineだけで解決しようとしていたが、問題はメールサーバー側であった。
・ドッカー環境、ＥＣ２クラウド環境、さんざん突き詰めて丸３日悩む。
・メールサーバーも、ポート開放やなんやらで悩み倒す。
・最後が自前と言うのは自分のアイデアで解決　→　CHATGPTはひらめきは与えてくれないが、アイデアを具現化するには役立った。
Spring Cache

# Springでcacheを利用する
Spring cache abstractionを依存関係に追加し利用する。

## キャッシュを有効にする
* @EnableCachingを@SpringBootApplicationのクラスに指定する。
~~~ java
@SpringBootApplication
@EnableCaching
public class SpringitemApplication
~~~

* データ取得のメソッドに＠Cacheableを付与し、取得結果をキャッシュするようにする。
~~~ java
@Cacheable(value = "getItems")
	public List<Item> getAllItems(){
~~~
valueにてキャッシュ管理名称を指定する。

* キー値別にキャッシュ管理する場合には、key属性も指定する。
~~~ java
	@Cacheable(value = "getItem", key="#p0")
	public Optional<Item> getItem(Long itemId) {
~~~
一般的には#p0がよく使用される。検索のキー値ごとに管理されるようになる。

## キャッシュを削除する
* CasheEvictでキャッシュの値を削除する。

⇒データ新規登録時に、既に登録されている全件検索時のキャッシュを削除する場合などに使用する。
~~~ java
	@CacheEvict(value = "getItems", allEntries=true)
	public void addItem(Item item) {
~~~
allEntries=true

指定した文字列で管理されているキャッシュ全体を削除したい場合に指定

* 複数のキャッシュ削除を指定したい場合

⇒@Cacheingアノテーションにevict属性を用いて@CacheEvictを複数指定することができる。

指定データ更新・削除時に、対象のキー値で管理されているキャッシュ　および　全件検索取得のキャッシュをそれぞれ削除したい場合などに使用する。
~~~ java
	@Caching(evict = {
			@CacheEvict(value="getItem", key="#p0"),
			@CacheEvict(value="getItems", allEntries=true)
	})
	public void updateItem(Long itemId,Item item) {
~~~
【JavaScript】配列の要素を二分探索で抽出してみた

# 二分探索のメリット
線形探索よりも短い時間でターゲットを見つけることができる。

# コード
```
// arr ソート済みの配列
// target 見つけたい要素
function binarySearch(arr, target) {
    let idx = null;
    let iMin = 0;
    let iMax = arr.length - 1;
    while (iMin <= iMax) {
      let iMid = Math.floor((iMin + iMax) / 2);
      if (arr[iMid] === target) {
        idx = iMid;
        break;
      } else if (arr[iMid] < target) {
        iMin = iMid + 1;
      } else {
        iMax = iMid - 1;
      }
    }
    
    return idx;
  }
```

初期値（idx）をnullにすることで、配列の要素に正の数、負の数混じっていても抽出することができるようになりました。この関数終了時にidxに値が代入されていれば、要素発見となります。idxにnullが代入されている場合は探索したい要素が配列に存在しなかったことになります、

# 参考文献(コードをお借りしました)
- JavaScriptによる2分探索(バイナリサーチ) のサンプルコード
https://tech-blog.s-yoshiki.com/entry/195
【Flutter】Github Actionsでバージョン管理システムのFlutterバージョンを使う

## はじめに
Flutterバージョンをあげたとき、Github Actionsのワークフローで使うFlutterバージョンも書き換えるのめんどくさいですよね？
今回はfvmとasdfのバージョンをGithub Actionsで使う方法を紹介します。

## fvm
flutter-fvm-config-actionを使うと、fvm_config.jsonファイルからFlutterバージョンを取得してワークフローを書けます。

```
- uses: kuhnroyal/flutter-fvm-config-action@v1
- uses: subosito/flutter-action@v2
  with:
    flutter-version: ${{ env.FLUTTER_VERSION }}
    channel: ${{ env.FLUTTER_CHANNEL }}
    cache: true
```


https://github.com/kuhnroyal/flutter-fvm-config-action


## asdf
import-asdf-tool-versions-actionを使うと、.tool-versionsファイルからFlutterバージョンを取得してワークフローを書けます。

```
- uses: wasabeef/import-asdf-tool-versions-action@v1.0.1
  id: asdf
- uses: subosito/flutter-action@v2
  with:
    channel: stable
    flutter-version: ${{ steps.asdf.outputs.flutter }}
    cache: true
```


https://github.com/wasabeef/import-asdf-tool-versions-action

## まとめ
楽！
社会の問題をデータ分析で－フジテレビ「THE SECOND」の後攻有利について－

フジテレビの『THE　SECOND』
https://www.fujitv.co.jp/the-second/

「開幕戦ノックアウトステージ（32→16）」と「ノックアウトステージ(16→8)」で「後攻有利では」との意見があったので検定してみた。

```python
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt

df = pd.read_csv('THESECOND.csv')
df = df.dropna()
df['first'] = df['first'].astype(int)
df
```

```
first	second
0	232	252
1	252	257
2	284	274
3	233	254
4	257	266
5	254	266
6	248	239
7	252	277
8	225	281
10	269	269
11	271	260
12	232	277
13	245	276
14	265	269
15	265	282
16	273	283
17	276	290
18	274	275
19	284	285
20	269	275
21	234	284
22	289	258
23	271	278
```
- 東京ダイナマイトさんが欠場で１レコードは削除しています。

```python
plt.hist(df['first'], bins = 10, alpha = 0.5, label='first')
plt.hist(df['second'], bins = 10, alpha = 0.5, label='second')
plt.legend(loc='upper left')

plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116049/fc802c25-06ab-dd31-4c9a-f664baff1d08.png)

- なるほど後攻有利に見える。Weltchのt検定をしてみる

```python
stats.ttest_ind(df['first'], df['second'], equal_var = False)
```

```
Ttest_indResult(statistic=-2.514719088692096, pvalue=0.016210681692063588)
```

ご指摘あり、効果量を見てみる
効果量については
Staat様の技術ブログ[効果量](https://corvus-window.com/whats_effect-size/)
など

t検定では0.８０でも大きいらしい。

```python
abs(-2.514719088692096)*((24+24)/24*24)**0.5

```
17.42
```

- おを、やはりあり得ない値か。後攻有利。

# でも「開幕戦ノックアウトステージ（32→16）」よりも「ノックアウトステージ(16→8)」の方が僅差なので、分けてみた。

```python
df1 = df.iloc[0:15, :] # 開幕戦ノックアウトステージ（32→16）
df2 = df.iloc[15:, :]  # ノックアウトステージ(16→8)
```

## 「開幕戦ノックアウトステージ（32→16）」

```python
plt.hist(df1['first'], bins = 10, alpha = 0.5, label='first')
plt.hist(df1['second'], bins = 10, alpha = 0.5, label='second')
plt.legend(loc='upper left')

plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116049/b222a5da-caad-c411-db06-34d3a1d80e38.png)

```python
stats.ttest_ind(df1['first'], df1['second'], equal_var = False)
```

```
Ttest_indResult(statistic=-2.6637042977615826, pvalue=0.01321143249116919)
```

同じく効果量

```python
stats.ttest_ind(df1['first'], df1['second'], equal_var = False)
```

```
14.59

```

- 「開幕戦ノックアウトステージ（32→16）」はやはり後攻有利か。

## 「ノックアウトステージ(16→8)」

```python
plt.hist(df2['first'], bins = 10, alpha = 0.5, label='first')
plt.hist(df2['second'], bins = 10, alpha = 0.5, label='second')
plt.legend(loc='upper left')

plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116049/026c5aa4-6cf6-d361-ecb6-81c5bc21e1be.png)

- 外れ値があるものの意外と拮抗？

```python
stats.ttest_ind(df2['first'], df2['second'], equal_var = False)
```

```
Ttest_indResult(statistic=-1.069473268339255, pvalue=0.30700785772217687)
```

```
abs(-1.069473268339255)*((8+8)/8*8)**0.5
```

```
4.28
```

- とのことで、効果量が大きく減ってはいるものの0.８０を大きく上回っており、後攻有利が弱またったとまでは言えなさそう。

ということで決勝戦ではそマシンガンズさんと囲碁将棋さんの決勝戦を期待しています。

Weltchのt検定でよいのかって？

[マイナーだけど最強の統計的検定 Brunner-Munzel 検定](https://hoxo-m.hatenablog.com/entry/20150217/p1)
の記事が参考になります。

サンプルサイズの考察抜け、私もいつもはBoxプロットかJitterプロットにするのですが、不用意にヒストグラムを描いてしまうなど大変失礼いたしました。統計的に正しくは本記事にコメントをいただいておりますので、そちらをご参照ください。
【Dart】命名規則について

# はじめに
最近、流行りのFlutterを勉強し始めました(乗り遅れてるかも笑)

Swiftとは命名規則が異なっていそうなので調べてみました。

https://dart.dev/guides/language/effective-dart/style

# UpperCamelCase(先頭大文字キャメルケース)
### classes
```dart
class MyClass { ... }
```

### enum types
```dart
enum MyEnum { ... }
```

### typedef
```dart
typedef MyFunction = ...
```

### type parameters
```dart
class MyGenericClass<T> { ... }
```

# lowerCamelCase(先頭小文字キャメルケース)
### class members
```dart
class MyClass {
  int myVariable = ...

  void myMethod() { ... }
}
```

### top-level definitions
```dart
int myGlobalVariable = ...

void myGlobalFunction() { ... }
```

### variables
```dart
int myVariable;
```

### parameters
```dart
void myFunction(int myParameter) { ... }
```

### named parameters
```dart
void myFunction({int namedParameter}) { ... }
```

# lowercase_with_underscores(スネークケース)
- フォルダ名(`my_folder`)
- ファイル名(`my_class.dart`)
- ライブラリ名(`my_library`)

# 特殊
### 略語や頭字語
> 略語や頭字語は、大文字だけの文字列だと読みづらくなりますし、複数の頭字語が連続する場合には曖昧な名前になってしまいます。例えば、「HTTPSFTP」という名前があった場合、それが「HTTPS FTP」なのか「HTTP SFTP」なのかは分かりません。
このような問題を避けるために、略語や頭字語は通常の単語のように大文字で始めます。
```dart
class HttpConnection { ... }

var httpRequest = ...
```

### 例外
> 2文字の頭字語（例：IO）は全て大文字で表記されます。
一方、2文字の略語（例：ID）は通常の単語と同じように大文字で始めます。
```dart
class DBIOPort {}

var userId = ...  
```

# おわり
ちゃんとドキュメントを読んだはずですが、間違っているところがあるかも知れません
もし間違っている箇所があればコメントで教えてください
Jetson NX Developer Kit で Jetpack 5.1.1がブートしなかった件

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. Jetson NX Developer Kit でJetpackを新しくしようとしたが､ブートローダーが変わっていて､待てど暮らせどブートしなかった件

まあ､皆さんはそういうことはないと思うのですが､あまり何も考えずにJetpack4.6系のようにSSDカードにイメージを焼き付けてブートしようとしたために､3時間ほど時間を無駄にしたというお話です｡

以下のURLからSDカードイメージをダウンロードして､SDカードにイメージを書き込んでブートします。
しかし、起動しなかったためSDカードイメージを3回書き直し、ブート後に1時間放置してみたりしてみました。

https://developer.nvidia.com/embedded/jetpack

# 1. まあ､よく見ろや

こういうことですね｡
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/a26a5791-d8dc-0347-584e-9164ceffb068.png)

Flashing Support — Jetson Linux<br/>Developer Guide 34.1 documentation

https://docs.nvidia.com/jetson/archives/r35.1/DeveloperGuide/text/SD/FlashingSupport.html#to-upgrade-jetpack-4-x-to-jetpack-5-x-on-jetson-xavier-nx-p3668-0000

以下を実行すればよいようです(tarの部分は微妙に間違っておりますので私のインストラクションをご確認ください)｡

```
$ sudo flash_eraseall /dev/mtd0
$ tar -xvf Jetson_Xavier_NX_QSPI_35.1.tbz2 jetson-xavier-nx-devkit.spi.img
$ sudo flashcp jetson-xavier-nx-devkit.spi.img /dev/mtd0
```

# 2. Jetson_Xavier_NX_QSPI_35.1.gz をダウンロード

以下のURLから`Jetson_Xavier_NX_QSPI_35.1.gz`をダウンロードします｡
Jetson上で実行しないといけないので､ブートできるJetpack4.6系をインストールしたSDカードイメージで起動します｡

https://developer.nvidia.com/embedded/L4T/r35_Release_v1.0/QSPI-img/Jetson_Xavier_NX_QSPI_35.1.gz

```bash
wget https://developer.nvidia.com/embedded/L4T/r35_Release_v1.0/QSPI-img/Jetson_Xavier_NX_QSPI_35.1.gz
```

# 3. `Jetson_Xavier_NX_QSPI_35.1.gz`を展開する

ダウンロードしたファイルはgzとなっているのでgzipと思いきや､tar.bz2ファイルなので

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/9365d55b-5acf-5f03-387d-5ee940850f64.png)

以下のコマンドで展開します

```bash
tar -jxvf Jetson_Xavier_NX_QSPI_35.1.gz jetson-xavier-nx-devkit.spi.img
```

# 4. フラッシュROMを削除

```
sudo flash_eraseall /dev/mtd0
```
コマンドは変わっていて､`sudo flash_eraseall /dev/mtd0 0 0`みたいですが､上記のコマンドでも実行できます｡

フラッシュROMを書き込むまでリブートしてはいけません
4分程度で終わります｡
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/028e47f1-8dd6-da36-a36c-c89bca874651.png)

# 5. フラッシュROMを書き込む

書き込み時には何も出ないのでご注意ください｡2分程度で書き込み終了します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/33575703-bfd7-c74a-c055-172a0dad9293.png)

# 6. 最新のSDカードイメージでブートする

書き込みが終わったら､一旦シャットダウンします｡
構造体の中にスライス(string)を持っているやつの初期化方法

# やりたいこと
柔軟に値を出し入れできる構造体を使いたい。
例えば、こんな構造体を初期化したい

``` go
type Account struct {
	asset     []string 
	liability []string 
	benefit   []string 
	cost      []string 
}
```

## 結論

初見じゃ思いつかんです。
なおポインタへの代入だとまた変わったりするらしい

``` go
	var defSubjects Account = Account{
		asset:     []string{"cash", "bank"},
		benefit:   []string{"salary"},
		cost:      []string{"food", "water", "phone"},
		liability: []string{"loan"},
	}
```

## 「参考」筆者がやらかした間違った方法

``` go
	var defSubjects Account = Account{
		asset:     {"cash", "bank"},
		benefit:   {"salary"},
		cost:      {"food", "water", "phone"},
		liability: {"loan"},
	}
```
poetry lock, poetry install, poetry update が全然終わらなくなった

# 結論
`pyproject.toml` に `urllib3 = "<2"` を追加することで解決した。

```diff_toml
  [tool.poetry.dependencies]
  ...
+ urllib3 = "<2"  # 追加
```

# 解決するまでの道のり
* つい最近 `poetry lock` をやると、 `Resolving Dependencies...` の状態が数十分経っても全然終わらなかった
  - `poetry install` や `poetry update` も同様の状況
* `poetry lock -vv` で詳細なログを出力すると、以下のようなログが繰り返し出ていた
  - どうやら `botocore` に関連する依存関係の解決がうまくいっていない様子

```
   2: conflict: no versions of botocore match >1.29.135,<1.29.136
   2: ! botocore (>1.29.135,<1.29.136) is partially satisfied by not botocore (==1.29.135)
   2: ! which is caused by "botocore (1.29.135) depends on urllib3 (>=1.25.4,<1.27)"
   2: ! thus: botocore (>=1.29.135,<1.29.136) requires urllib3 (>=1.25.4,<1.27)
```

* https://github.com/orgs/python-poetry/discussions/7937 を発見し、そこに書かれているとおり、 `urllib3 = "<2"` をヒントとして追加することであっさりと解決した
* `urllib3` は最近バージョン2系が出たようで、それが原因だったっぽい
  - https://pypi.org/project/urllib3/#history

# 反省
* 最初は `-vv` オプションに気づかず、ひたすらネットワークの不調を疑っていて時間が溶けてしまった
* ログを見ることは大事
[自分用]Next.jsの空配列について

## useEffectの第二引数の役割とは
簡単にいうと、[]に記述された変数が変更されると、改めてuseEffectの中身が実行される。

下記はクリックイベントのコードだが、そこで使用した変数`foo`をuseEffectの第二引数に記述。
そうすることにより`foo`が変わるたびにuseEffectの中身が実行される。
```jsx
export default function Home() {
  const [foo, setFoo] = useState(1);

  const handleClick = () => {
    setFoo(foo => foo + 1);
  };

  useEffect(() => {
    console.log('その次にマウントが実行されるよ');
    return () => {
      console.log('fooが変わると最初にアンマウントが実行されて');
    }
  }, [foo]);

  return (
    <>
      <h1>{foo}</h1>
      <button
        onClick={handleClick}>
        ボタン
      </button>
      <Main page="index" />
    </>
  )
}
```

## useCallbackの第二引数の役割とは
こちらも[]に記述された変数が変更されると、改めてuseEffectの中身が実行される。

ちなみに、
下記に例を記述したが、第二引数に何も指定しなかったら[foo]の中身はずっと同じ状態になる。
（ほんとは2,3,4...と増えてほしい）

理由はuseCallbackは再生成されないから。
```jsx
const handleClick = useCallback(() => {
  console.log(foo);
  if(foo < 10){
    setFoo(foo => foo + 1);
  }
},[])
```

## なぜこんな機能があるのか
コード量が多くなったときに、全てレンダリングするのは効率とパフォーマンスが悪くなる。
だから必要最低限のレンダリングを実行させるためにも必要な機能。
SysOps アドミニストレーター(SOA-C02)勉強方法の紹介(1回落ちて2回目で合格）

# はじめに
先日AWS認定　SOA-C02に合格しました。
2回受験したので1回目、2回目受験時に実施したことを記事にしてみました。

受験時のAWS保有資格はCLF/SAA/DVAになります。

# 1回目受験までの勉強方法
[TechStock AWS WEB問題集で学習しよう](https://techstock.jp/)
1~最後までの問題を繰り返し実施し、ほとんどの問題を暗記して試験に臨みました、不合格判定となってしまいました。
再受験無料キャンペーンにつられての受験だったので、勉強期間は3週間くらい、スコアは692点でした。

# 受験後の自己分析
他の試験を受験したときは、書籍やskill builderを繰り返して、ある程度知識をつけたうえで
問題集に臨んでいたので、このサービスはこうやって使うのね、と納得感を持って答えを選んでいましたが、SOAはWEB問題集しか使用していないので、こう問われたらこう、とパターン化して覚えてしまっていて応用が利かなかったと感じました。一回書籍で知識をつけたほうがよいと考えました。

# 2回目受験前に実施したこと
以下のSOAの参考書を購入し、3回ほど読み返しました。
[AWS認定資格試験テキスト AWS認定SysOpsアドミニストレーター - アソシエイト 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%9ASysOps%E3%82%A2%E3%83%89%E3%83%9F%E3%83%8B%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/481560908X)

この問題集の後ろの模擬試験の問題と解説が、個人的には知識を確認するのにかなり役立ちました。
書籍内の解説の粒度と、サービスのユースケースなどが、試験で問われるものと合致していて程よいと感じました。

書籍を3回読み返すのに3週間ほど使い再受験し、2回目は無事合格することができました。

# おすすめの勉強方法
もし私が今回使用した教材で再度受験するとしたらですが、
書籍１～２回ほど読む→WEB問題集→書籍もう一回読む、が効率のいい勉強方法になるかなと思います。

# テストを終えて
SOA1回目不合格になるまでは、CLF,SAA,DVAと順調に取得していたので、ほとんどのサービスは
理解してるだろうし、問題集だけでいいかなと考えていました。
1回目受験後と2回目受験後の自身のAWSスキルを考えると、1度落ちて、書籍で知識を定着させることができたのはAWSのスキルアップを目的とした受験なので結果的にはよかったのかなと思います。
次はSAPの取得を目指して頑張りたいと思います。本記事がSOA受験を考えている方の参考になりましたら幸いです。
MySQL 8.0.30 のutf8mb3で記録されないはずの文字列の怪奇現象

# これなに
MySQLを5.6とか7の頃から触っているDB屋さんにとってちょっとした珍事というか謎、怪奇現象。

# 経緯
もともとAWS RDSでホスティングされていた MySQL 5.6 とか 7 というバージョンでは、４バイトのUTF-8エンコーディングされた文字列をDBに収めたかったら、`utf8mb4` というエンコーディングを MySQLに指定する必要があった。

やらないと何が起こるかというと `𩸽` とか `髙` とか `﨑` とか `竈門禰󠄀豆子` とかINSERTできないか `???` になるかのどちらかだったように記憶している。

# MySQL 8.0.30では何が起こっているかというと・・
３バイトまでしか記録できないはずの utf8mb3さんが4バイトの文字を記録している。

```
mysql> show variables like '%char%';
+--------------------------+-------------------------------------------+
| Variable_name            | Value                                     |
+--------------------------+-------------------------------------------+
| character_set_client     | latin1                                    |
| character_set_connection | latin1                                    |
| character_set_database   | utf8mb3                                   |
| character_set_filesystem | utf8mb3                                   |
| character_set_results    | latin1                                    |
| character_set_server     | utf8mb3                                   |
| character_set_system     | utf8mb3                                   |
| character_sets_dir       | /rdsdbbin/mysql-8.0.30.R1/share/charsets/ |
+--------------------------+-------------------------------------------+
8 rows in set (0.09 sec)

mysql> select * from test_encoding;
+---------------------+
| font                |
+---------------------+
| 髙                 |
| 﨑                 |
| 㐂                 |
| 竈門禰󠄀豆子 |
| 𩸽                |
| 𪘚                |
+---------------------+
5 rows in set (0.10 sec)
```

ど、どういうことだってばよ・・ 保存できて・・いる？

# MySQL 8.0.xx Changelog

## 8.0.11 
https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-11.html#mysqld-8-0-11-charset

**Character Set Support**
The utf8mb3 character set will be replaced by utf8mb4 in a future MySQL version. The utf8 character set is currently an alias for utf8mb3, but will at that point become a reference to utf8mb4. To avoid ambiguity about the meaning of utf8, consider specifying utf8mb4 explicitly for character set references instead of utf8. (WL #10778)

要約すると「utf8はutf8mb3のエイリアスだけどそのうちutf8mb4に置き換わるよ近い将来。」

そしてときは流れ。

## 8.0.31 
https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-31.html#mysqld-8-0-31-compiling

Renamed internal Performance Schema functions from _utf8* to _utf8mb4* as they've used utf8mb4 since v8.0.11. (Bug #34351301)

**v8.0.11 以降 utf8mb4 を使用しているため、内部パフォーマンス スキーマ関数の名前が _utf8* から _utf8mb4* に変更されました**

# どういうこと？

8.0.11から30までのchangelogを斜め読みましたが、「置き換わったよ！」とかそんなこと書いてないように見える・・

つまりどこかのタイミングで utf8 = utf8mb3 = utf8mb4 になった？のか？

DBのエンコーディングはutf8mb3で問題ないよ！と言い切れなくてとても気持ちが悪い。

自分でDBを構築するときは過去にハマった経験から、必ずエンコーディングは `utf8mb4` を指定していたんだけど、このたび他人が構築したDBを見てびっくりしたということ。

どうせ作った側の会社に聞いても調べる能力はないだろうし・・（多分デフォルトでやっている）これが開発終盤で爆発しないことを祈ることしかできないのか・・・
Flutter での prerelease版のパッケージによるエラー

# 概要
2023/5/19日に
Flutter でintl(ver0.18.1)という日付を扱うパッケージを入れたところエラーが発生しました。
すでに入れていたawesome_notificationsという通知に関するパッケージががエラーをはいているようで確認したところバージョンが以下のように自動でアップデートされていたようです。

# 原因
awesome_notificationsがintlをインストールしたタイミングで**prerelease版に勝手にアップデート**されたようです。

awesome_notificationsのバージョン
以前のバージョン : 0.7.4
エラー時のバージョン: 0.7.5-dev.2+1

尚、この時**pubspec.yaml(パッケージ管理ファイル)のawesome_notificationの部分は変わらず0.7.4**のままです。
intlとの相性の問題でこうなったのか、flutter自体の設定で自動でアップデートされたのかわかりません。

# 解決策
awesome_notificationをダウングレードして解決しました。pubspec.yamlを変えるだけではダウングレードされなかったので、**buildフォルダのawesome_notificationsのフォルダを手動で削除して再インストール**しました。

# 終わりに
**今回の問題は最初はエラーが表示されませんでした**。一度環境(VSCode)を再起動するとエラーが表示されました。Flutterは簡単にモバイルネイティブアプリを簡単に書けますが、たまにエラーが表示されないことがあるので注意が必要だと思います。
もし、今回のエラーの原因がわかる方がいらっしゃれば、教えていただけると幸いです。
【Linux】lsコマンドでディレクトリのみ取得する方法

## ディレクトリのみ取得する方法

次のようにコマンドを実行するとディレクトリのみ取得できます。

```zsh
ls -F [パス] | grep /
```
隠しファイルも含めて表示
```zsh
ls -aF [パス] | grep /
```
```zsh:サンプル
$ ls -F path/to/sample | grep /
app/
bin/
config/
db/
lib/
log/
public/
spec/
storage/
templates/
test/
tmp/
vendor/

$ ls -aF path/to/sample | grep /
./
../
.devcontainer/
.docker/
.git/
.vscode/
app/
bin/
config/
db/
lib/
log/
public/
spec/
storage/
templates/
test/
tmp/
vendor/
```

または、次のコマンドを実行します。

```terminal
ls -d */
```

```terminal
$ ls -d */
app/		node_modules/	public/		supabase/
```
日本最大級のポイントサイトで経験した失敗と挑戦

# はじめに
勉強会でスピーカーをしました。
その際に使用したスライドとなります。

# 勉強会テーマ
「【リンケージxセレス】～失敗する開発とその対策～」
https://connpass.com/event/281786/

アーカイブで勉強会の様子も見れます
https://www.youtube.com/live/fSEH3kxcBQs?feature=share

# スライド

<script async class="docswell-embed" src="https://www.docswell.com/assets/libs/docswell-embed/docswell-embed.min.js" data-src="https://www.docswell.com/slide/ZXYPRY/embed?key=2023-05-23-174034" data-aspect="0.5625"></script><div class="docswell-link"><a href="https://www.docswell.com/s/6211087170/ZXYPRY-2023-05-23-174034">日本最大級のポイントサイトで経験した失敗と挑戦 by @6211087170</a></div>
【Git】git管理下のファイルをリネームしたらdeletedとuntrackedの２つになってしまった時

# はじめに
タイトルの通り、Git管理下のファイルを(例えば)IDE上でリネームするとdeletedとuntrackedで分かれてgit status上に表示されることがあります。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/912016da-87dc-1dfa-5a68-a3d6a0829eed.png)
黄色枠の箇所です。`UmaInfo.module.css`を`UmaInfoIcon.module.css`へリネームしたところ、リネーム前がdeletedでリネーム後がUntrackedになってしまいました。

# やりたいこと
Gitにrenamedとして管理させたい。

## ステップ１
`git rm リネーム前のファイル名`をして、リネーム前の削除したファイルをステージングする。
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/b37a9cf5-1f36-757f-bd76-4694be45a63c.png)
↑ステージングされました。

## ステップ２
`git add リネーム後のファイル名`をして、リネーム後のファイルをステージングする。

## 結果
renamedで登録できました。
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/a76506eb-ad93-8bf7-e32a-a2b19befdf27.png)

# さいごに
なんでこんな記事を書いたかというと、先にリネーム後のファイルだけをステージングしたところ、new fileとして登録されてしまい、後からリネーム前のファイルをrmしたら`error: the following file has changes staged in the index:`と怒られてしまったので備忘録として残しておきたかった次第です。
UserDefaultにFont .font(.title) を保存する方法

## 宣伝

アプリ作っているので入れてみてください！！
よろしくお願いいたします！！

https://apps.apple.com/app/6446189340


https://apps.apple.com/jp/app/meime/id6446994707?l=ja


## 本題








普段フォントとして、
.font(.title)などと使われているものは省略記法であり、実際は

.font(Font.title)
となります。

今回は好みでInt型に置き換えて、UserDefaultに保存します。


保存するために、Intに変換する
```Swift


func getIntValue(from font: Font) -> Int {
    switch font {
    case .largeTitle:
        return 10
    case .title:
        return 9
    case .title2:
        return 8
    case .title3:
        return 7
    case .headline:
        return 6
    case .subheadline:
        return 5
    case .body:
        return 4
    case .callout:
        return 3
    case .caption:
        return 2
    case .caption2:
        return 1
    default:
        return 0
    }
}


```


保存されたIntからFontに変換する

```Swift

func getFontValueFromInt(int: Int) -> Font {
    switch int {
    case 10:
        return .largeTitle
    case 9:
        return .title
    case 8:
        return .title2
    case 7:
        return .title3
    case 6:
        return .headline
    case 5:
        return .subheadline
    case 4:
        return .body
    case 3:
        return .callout
    case 2:
        return .caption
    case 1:
        return .caption2
    default:
        return .body
    }
}

```


UserDefaultから取得

```Swift
 self.font_size = getFontValueFromInt(int :UserDefaults.standard.integer(forKey: "font_size"))
```






セレクターで選ぶ。

```Swift
 VStack {
            Picker("Font Size", selection: $selectedFontSize) {
                Text("Title").tag(4)
                Text("Title 3").tag(3)
                Text("Body").tag(2)
                Text("Caption").tag(1)
            }
            .pickerStyle(SegmentedPickerStyle())
            .padding()
            

        }

```






作ったアプリ。


https://apps.apple.com/app/6446189340


では。