OmniAICreator/Qiita-1.07M huggingface dataset:
useReducerを使ってみた

### はじめに
ReactでuseReducerを使ってみました。React歴、フロント歴ともに1年半位なのですが、useReducerを触った事がありませんでした。ビジネスロジックが複雑になるにつれて、useStateでやり切るのは難しいなと感じ、今回useReducerを触ってみることにしました。

### 成果物
![counter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/65a40fe4-4508-29f2-6dca-50805f4df372.gif)

### ソースコード

```tsx:Counter.tsx(useReducer利用)
import React, { useReducer } from 'react';
import { Action, State } from './type';

// reducer関数を定義
const reducer = (state: State, action: Action): State => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

const Counter: React.FC = () => {
  // useReducerを使って状態を管理
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      Count: {state.count}
      <br />
      <button onClick={() => dispatch({ type: 'increment' })}>+1</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
    </div>
  );
};

export default Counter;
```
→これで動きます。ただ、useStateを使う場合、下記で書けます。

```tsx:Counter.tsx(useState利用)
import React, { useState } from 'react';

const Counter: React.FC = () => {
  // useStateを使って状態を管理
  const [count, setCount] = useState(0);

  return (
    <div>
      Count: {count}
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  );
};

export default Counter;
```

→これで動きます。

### useReducerの使いどころ
useReducerはuseStateより書くコード量が増えるため、シンプルな処理の場合はuseStateで良いかな。ただ、stateの特定値による処理変更、イベント情報により処理が変更される等のビジネスロジックが変わる時に使うのがいい気がします。
| n |　君は何者？

rubyの学習をしていると

| n |　


| i |

| number |


なんかよくみるやつありますよね、例えば


``` ruby 

numbers = [1, 2, 3, 4]
sum = 0
numbers.each do |number|
  sum += number
end
puts sum

```

上記のコードで numbers っていうのは変数で　配列として　　1,2,3,4　を代入しているというのはわかるんですが

|number|

変数として宣言した　numbers　ではないし

単数系だしどこからきたねん！　なるほどわからん。状態でした😅

<br>

上記のコードが何をしているかというと

- 配列の定義: numbers = [1, 2, 3, 4] この行は、1, 2, 3, 4 という四つの要素を持つ配列 numbers を作成している。
- 合計の初期化: sum = 0 この行は、合計を計算するための変数 sum を0で初期化。これは、配列の要素を加算していくための開始点。

- 各要素の加算: numbers.each do |number| この行は each メソッドを使って配列 numbers の各要素にアクセスします。|number| はブロック変数で、配列の各要素を順番に参照していく。
sum += number この行で、現在の要素（number）が sum に加算されます。これにより、配列の各要素が順に sum に加えられていく。
- 合計の表示: puts sum この行は、最終的な合計値（この場合は 1 + 2 + 3 + 4 = 10）をコンソールに出力する。


結果として、このコードは配列 numbers の全要素の合計（この場合は10）を計算し、それを出力する


さて　|number|　さん

この方はブロック変数で、書籍などで学習していればそのコードを書いた人が決めた変数であって、なんだっていいってわけです


## | number |　が　| n |　でもいい

``` ruby

numbers = [1, 2, 3, 4]
sum = 0
numbers.each do |n|
  sum += n
end
puts sum

```

## 　| i |　だっていい


``` ruby

numbers = [1, 2, 3, 4]
sum = 0
numbers.each do |i|
  sum += i
end
puts sum

```


**| n |　は 何者でもなく　ブロック変数と呼ばれる変数だった**

|　n　|　　この表記は　変数はn　ね、　numbers　を 変数 n　に代入していってねこと


なるほどわかった！😀w
クラスの継承の関係について


クラスの継承について誤っておぼえてたので間違いの履歴として残す。
スーパークラスを継承したら、スーパークラスの内容をメソッドなどを使かえるようになったBのクラスだと思っていた。

<h2>しかし、実際は</h2>
インスタンスがA型の場合はBのクラスであってもAのメソッドしか使えない。
A型で宣言したものは使用できるのがAクラスで定義されたメソッドのみに限定される。


```java
class A{
    public void hello(){
        System.out.println("hello");
    }
}

class B extends A{
    public void sample(){
        System.out.println("sample");
    }
}

public class Main{
	public static void main(String[] args){
        A a = new B();
	    a.sample(); //Aクラスには存在しないメソッドなのでコンパイルエラー
    }
}
```
rex0220 プラグイン 休暇届で休日を除いた日数計算

rex0220 プラグインを使って、休暇届で休日を除いた日数計算を行います

# 概要

休暇届アプリで、休日アプリを参照し、休日を除いた日数計算を行います。
開始日と終了日からテーブルに休暇届用の日付を展開して、期間内の休暇がわかりやすくします。

![screencapture-devenxyfi-cybozu-k-2790-show-2023-12-16-14_14_39 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5badeba9-1488-ae7d-fd48-97e361191776.png)

# 操作例

![2023-12-16_15h05_03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/fc943fc8-d331-ef03-01c4-21e8639d619e.gif)


# 使用するプラグイン

- アプリ集計プラグイン
    - 休日アプリから休日データを取得
- 計算式プラグイン
    - 開始日と終了日からテーブルに日付を展開
    - 有給日数、慶弔日数、欠勤日数、休暇日数の計算
    - 日付から曜日を計算
    - 休日テーブルから休日区分をセット
    - 休暇区分の自動セット
- 項目検証プラグイン
    - 開始日・終了日のチェック
    - 休暇区分の必須チェック
- ちょっと便利なプラグイン
    - テーブルヘッダ部を固定表示
- 休日プラグイン
    - 休日アプリで、祝日を取得


# アプリ集計プラグイン
- 休日アプリから休日データを取得

![2023-12-16_15h22_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/cca6a70b-bb83-5637-de6d-a4f40f9efcba.png)

- 対象アプリ条件
開始日と終了日の期間内の休日レコードを取得します。

![2023-12-16_15h21_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/665db94d-56aa-c780-6bd0-57f2bfdd1b58.png)

- テーブル項目
開始日と終了日の期間内の休日データを取得します。

![2023-12-16_15h23_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/379ffbf6-45b6-4ce1-cbce-fd863437d02d.png)

# 計算式プラグイン
- 開始日と終了日からテーブルに日付を展開
- 有給日数、慶弔日数、欠勤日数、休暇日数の計算
- 日付から曜日を計算
- 休日テーブルから休日区分をセット
- 休暇区分の自動セット

![2023-12-16_15h17_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4fc93b13-0e28-e124-d28e-54eae22c2805.png)

```計算式プラグイン.js
// 終了日 DATE (editable)
IF(開始日>終了日,開始日,終了日)

// 有給日数 NUMBER
COUNTIF(休暇区分T="有給",1)

// 慶弔日数 NUMBER
COUNTIF(休暇区分T="慶弔",1)

// 欠勤日数 NUMBER
COUNTIF(休暇区分T="欠勤",1)

// 休暇日数 NUMBER
SUM(有給日数,欠勤日数)

// 休暇申請 SUBTABLE
DATE_DIFF(開始日,終了日,"days")+1

// 休暇申請.#:行番号 NUMBER
ROWNO(休暇申請)+1

// 休暇申請.日付:日付T DATE
DATE_ADD(開始日,ROWNO(休暇申請),"day")

// 休暇申請.曜日:曜日T SINGLE_LINE_TEXT
LET(
  weekdayNum, DATE_FORMAT(日付T, "e"),
  SUBSTR("日月火水木金土", weekdayNum, 1)
)

// 休暇申請.休日区分:休日区分T SINGLE_LINE_TEXT
IF(IN(曜日T,"土","日"),"休日")&
LET(dt,日付T,
  FIRSTIF(dt=日付,休日区分&"("&休日&")")
)

// 休暇申請.休暇区分:休暇区分T DROP_DOWN (editable)
IFS(
  IN(曜日T,"土","日"),"",
  休日区分T,"",
  休暇区分T,休暇区分T,
  "有給"
)
```

# 項目検証プラグイン
- 開始日・終了日のチェック
- 休暇区分の必須チェック

![2023-12-16_15h15_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c7bb7e35-3299-8121-8fad-1b7161ce1f68.png)

# ちょっと便利なプラグイン
- テーブルヘッダ部を固定表示

![2023-12-16_15h18_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/75d5a410-1e69-51b9-7dcd-b344fb962780.png)
UiPath Friends で感じた生成AIとRPAの可能性

## はじめに
2023年12月15日に開催された「UiPath Friends」イベントに参加しました。
軽い気持ちで参加したら、予想以上に充実した内容と参加者の熱量に驚かされました！

## 生成AIを活用
今年の大きな出来事は、ChatGPTをはじめとした生成AIの登場です。
UiPathのアクティビティ検索にこれを活用しようと試みましたが、
情報の少なさやバージョンの多様性に苦労していました。

そんな会話をしていたら、
「いい方法がある」とのこと。

それは知りたい！

## Coded Automationの革新的な活用
それは、「Coded Automation」。
このアクティビティを使えば、コードをRPAに直接組み込むことが可能になります。
※UiPath Studioで利用できる特別なアクティビティで、StudioXでは使用できません。
これは従来のアクティビティ探索を超えた新しいアプローチです。

生成AIで「こんな処理をしたい」とリクエストを投げて、
適切なコードが出てきたら、それをRPAに組み込むだけ。
これで、手軽にプロセスが完成しちゃうかもしれません。

ワクワクしますね！！

### 教えてくださった@Hash1moさん
Advent Challenge #1 in the UiPath Community Forumに事例を投稿されています。
- [Hash1moさんのQiitaプロフィール](https://qiita.com/Hash1mo)
- [UiPath Community Forumの投稿](https://forum.uipath.com/t/advent-challenge-1-in-the-uipath-community-forum/703356/19)

## コード生成の挑戦と対策
生成AIで生成されたコードは、必ずしも動くとは限りません。
上手くいかないときは、以下の方法で解決できるかもしれません。

- 小さな単位でコードを作成する
- 色々なプロンプトでコード生成を試す
- よりシンプルなコードを生成する

## 参加の価値
このイベントでは、参加者同士の会話から実際の業務に役立つ具体的な知識を得ることができました。
RPAに関する新しい視点やアイデアを共有し、学ぶことができたのは非常に価値のある経験でした。

## RPA仲間との出会い
RPAに情熱を持つ仲間との出会いも、このイベントの大きな魅力の一つです。
同じ分野に興味を持つ人々との交流は、新しい知識や刺激を得る絶好の機会です。

## まとめ
UiPath Friendsイベントに参加して、新しいインスピレーションを得ました！
来年も楽しんでRPAの可能性を広げていきたいですね！



イベントでは、みんなでおっきいクリスマスケーキを食べました♪
Merry Christmas★☆
![1000009902.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654609/670d20cb-a212-c5b3-abc1-42a6359bb4e2.jpeg)


https://qiita.com/advent-calendar/2023/uipath
MinGWでPythonコードをpydにコンパイルのやり方


VSツールをインストールする必要はなく、pydファイルの使用説明。

## scoopを使ってMinGWを自動的にインストール、設定する

パッケージマネージャーのscoopでMinGWをインストールします。このステップは、手動でmingwをダウンロードして設定することも可能です。

``` 
scoop install mingw
```

## CythonとSetuptoolsのライブラリをインストールする

```
pip install setuptools -i 
pip install cython -i 
```

## setup.pyでコンパイル内容を設定する

```python
from setuptools import setup
from Cython.Build import cythonize
from setuptools.extension import Extension

# 複数の拡張モジュールを定義'
extensions = [
    Extension(name="main_screen_ini_gbk", sources=["main_screen_ini_gbk.py"]),
    Extension(name="tcpserver_ini_gbk", sources=["tcpserver_ini_gbk.py"]),
    # Extension(name="mylib1", sources=["mylib1.py"]),
    # さらに多くのモジュールを追加できます
]

setup(
    ext_modules=cythonize(extensions, language_level=3)
)
# python setup.py build_ext --inplace  --compiler=mingw32
```

## 以下のコマンドを実行してpydファイルにコンパイルする

64ビットのMinGWをインストールしていても、--compiler=mingw32で実行する。

```
python setup.py build_ext --inplace  --compiler=mingw32
```

## pydファイルをインポートして使用する

コンパイルが完了したpydファイルの名前は「スクリプト名.cp38-win_amd64.pyd」のような形式になります。生成されたpydファイル名は変更せず、インポートする際はスクリプト名の部分のみを使用します。直接.pyスクリプトをインポートする場合と同じです。

**注意：.pydは外部ファイルとしてインポートされるだけで、直接実行することはできません。別の.pyスクリプトを書いてpydファイルをインポートし、エントリーポイントとして使用する必要があります。.pydとpyが同時に存在する場合、実行時には.pydファイルが優先的に実行されます。**

![](https://gitlab.com/lovedva/pic404/-/raw/main/pictures/2023/12/12_14_13_4_20231212141304.png)

```python
# pydパッケージをインポート
import main_screen_ini_gbk 
# pydに封じ込められたメソッドを使用
main_screen_ini_gbk.push2NextHome(tsclibrary) 
```
コードの保守性担保の重要性

---

## 導入:
初めまして、Flutterエンジニアのトマトです。
この秋に転職し、コードの綺麗さが開発に与える影響について多くを学びました。
この記事では、綺麗なコードを書く意味と、汚いコードがもたらす問題点を共有します。

尚この記事はflutterエンジニア初心者やエンジニア初心者向けに作成しております。
すでにWEB・アプリエンジニアとして働かれている先輩方には不要な記事かもしれませんのでその点をご了承ください。

## 綺麗なコード vs 汚いコード:
まず初めに皆さんは綺麗なコードと汚いコードの違いとは何だと思いますか？
変数名の命名規則？？
コメントアウトでコードの意味が明確になっているかどうか？？
リファクタリングを考えているかどうか？？
正直どれも正解です。
それ以外にも綺麗なコードと汚いコードというのは色々と差があります。
しかしどれにも共通するものがあります。
それは相手のことを考えてコードを書くか書かないかの差です。
本当にそれを実感しました。
転職してまだ一ヶ月ちょっとしか経っていないジュニアのエンジニアですが会社のコードを見て唖然としました。

## 綺麗なコードへの無関心
過去を振り返ると、私自身、綺麗なコードを書くことの重要性を軽視していたことを認めざるを得ません。
インターン時代、綺麗なコードについて度々指摘を受けましたが、当時の私はタスクの完了に集中しており、コードの可読性や保守性にはほとんど注意を払っていませんでした。

## 過去の自分への謝罪
今、こうして振り返ると、私がどれほど多くの先輩エンジニアに迷惑をかけていたかを痛感しています。
私の未熟さと無知が彼らの負担を増やしていたことを深く反省し、心から謝罪したいと思います。
そして、今後はレビュワーをはじめとする他のエンジニアのことを常に考え、より読みやすく、理解しやすいコードを書くことを心掛けます。

## 汚いコードとの格闘
実際に直面したコードは以下のようなものでした。

未使用の謎の変数が散乱
dynamic型の乱用と、Lintエラーを無視する文化
極端なネストと、一つのファイルに500行近くもある膨大なコード
これらのコードは、読むこと自体が一苦労。
転職後、早々にリファクタリングの任を負った私は、この「脳筋コード」との戦いに多くの時間と労力を費やしました。


## 教訓としての反省
この経験を通じて、私は自分自身の過去のコードを振り返る機会を得ました。
そして、ある衝撃的な真実に気付かされたのです。
私の書いたコードも、他人にとって読みづらく、理解しにくいものだったという事実です。
過去に私が書いたコードを見返すと、その複雑さに自分でさえ頭を抱えてしまいます。
目先のリリースに追われ、コードの質よりも速さを優先してしまった結果、無秩序で理解しづらいコードが生まれていたのです。
その当時の私は、リリースを最終目標と捉え、そのためには手段を選ばない状況でした。
その結果、コピペされたコードの断片が乱雑に組み合わされ、それらがどのように機能しているのか、後から振り返っても理解するのが困難でした。
今思えば、このような状態でコードを書いたことに深く後悔しています。
コードは単なる文字列の羅列ではなく、未来の自分や他のエンジニアが読み解き、利用するためのもの。
その重要性を痛感しています。
このような過去の経験から、私は今後はより慎重に、そして他人が読んで理解しやすい「綺麗なコード」を書くことを心掛けています。
開発プロセスの中でリリースは確かに大切ですが、それに至る過程の品質も同様に重要だということを、私はこの経験を通じて学びました。


## まとめ
汚いコードは、開発の意欲を削ぎ、バグの温床となり、プロジェクト全体を停滞させます。
私は今、コードをただ書くのではなく、読みやすく、理解しやすく、そして保守しやすい「綺麗なコード」を心がけています。
これは単なる技術的な問題ではなく、共同作業者への思いやりでもあるのです。
awkコマンドで2列のgroup by集計

# はじめに
apacheログで「特定のURLパス」の「時間帯」ごとのレスポンス速度を集計する際に、シェルスクリプトの**awkコマンドを使って、2列のgroup by集計**が必要になったので、やり方を備忘録として残します。

# 結論
group byしたい2列を**文字列結合して集計**するだけ。
(※あとで更に修正しやすいように、集計後に再度列を分割して出力を推奨)

# 例
下記のようなログデータがあるとする。
```apache.log
20231218-112000 /users 2
20231218-113000 /categories 3
20231218-114000 /users 5
20231218-115000 /categories 1
20231218-121000 /categories 4
20231218-122000 /users 8
20231218-123000 /users 2
20231218-124000 /categories 7
```
※日時 URLパス レスポンス時間(秒)
※日時は20231218-112000 = 2023年12月18日11時20分00秒の意味

このデータをもとに、下記のような「各パス」の「時間帯」ごとの「平均レスポンス時間(秒)」を集計したい。
```plaintext
/categories 11 2 ※11時台は平均2秒のレスポンス時間
/categories 12 5.5
/users 11 3.5
/users 12 5
```

### ステップ1
group byしたい2列を文字列結合して出力。
```zsh
#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' # $1:日時, $2:URLパス, $3:レスポンス時間(秒)

# ↓出力結果
11/users 2
11/categories 3
11/users 5
11/categories 1
12/categories 4
12/users 8
12/users 2
12/categories 7
```
:::note info
`awk '{print $1$2}'` と、カンマで区切らず書くことで、列を文字列結合できる。
上記例では、「時間帯」だけ必要だったので、`substr($1, 10, 2)`で時間を抽出したうえで`$2`(パス)と結合させている
:::

### ステップ2
ステップ1の出力をもとに集計する。
```zsh
#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' | # $1:日時, $2:URLパス, $3:レスポンス時間(秒)
awk '{count[$1]++; sum[$1]+=$2} END{for(i in count) print i, sum[i]/count[i]}' # $1:時間＋URLパス, $2:レスポンス時間(秒)

# ↓出力結果
11/categories 2
12/users 5
12/categories 5.5
11/users 3.5
```

### ステップ3
使いやすい&見やすいように、列を分割、列の並び順を整理し、行もソートする。
```zsh
#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' |
awk '{count[$1]++; sum[$1]+=$2} END{for(i in count) print i, sum[i]/count[i]}' |
awk '{print substr($1, 3), substr($1, 1, 2), $2}' |
sort -k1 -k2 # 1列目、2列目でソート

# ↓出力結果
/categories 11 2
/categories 12 5.5
/users 11 3.5
/users 12 5
```
**完成🎉🎉🎉**

#### ステップ4(おまけ)
スプレッドシートなどに貼り付けやすいように加工する。
```zsh
#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' |
awk '{count[$1]++; sum[$1]+=$2} END{for(i in count) print i, sum[i]/count[i]}' |
awk '{print substr($1, 3)"\t", substr($1, 1, 2)"\t", $2}' |
sort -k1 -k2 | tee >(pbcopy)

# ↓出力結果
/categories      11      2
/categories      12      5.5
/users   11      3.5
/users   12      5
```
:::note info
`"\t"`を挟んで、タブ区切りにする。
`tee >(pbcopy)`で標準出力を確認しつつ、クリップボードにもコピー。
:::

コピーされた内容をスプレッドシートにそのまま貼り付けると、表として綺麗に貼り付けできる(下図)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667968/f3a22374-a5e9-50b2-f98b-9ec9aad7ec92.png)

# おわりに
awkコマンドを活用することで、テキストログから有用な情報を抽出できます。
是非活用してみてください！！
GolangのTestでブレークポイントを貼りデバッグする(VSCode編)

## はじめに
表題通り、GolangのTestでブレークポイントを貼りデバッグします。

### 成果物
![go_test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/82acd8bd-c61f-1dd6-c20f-0754e44433f8.gif)

### ソースコード

```shell:ディレクトリ構成
~/go/src/go_test_delve$ tree
.
├── go.mod
├── main.go
└── main_test.go

1 directory, 3 files
```

```go:main.go(プロダクトコード)
package main

import "fmt"

func add(a, b int) int {
    return a + b
}

func main() {
    result := add(2, 3)
    fmt.Println("2 + 3 =", result)
}
```

```go:main_test.go
package main

import (
	"fmt"
	"testing"
)

func TestAdd(t *testing.T) {
    result := add(2, 3)
    expected := 5
    fmt.Println("2 + 3 =", result)

    if result != expected {
        t.Errorf("Expected %d, but got %d", expected, result)
    }
}
```


### デバッグする準備
VSCodeでテストをするには、`.vscode`を作成する。

```json:vsocde.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Package Test",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${fileDirname}",
            "args": [],
            "showLog": true,
            "trace": "log"
        }
    ]
}

```
→これで準備完了。テストを動かせば、デバッグできるようになります。
Google謹製のクロージャ・コンパイラが使えなくなっている！！！

![DALL·E 2023-12-16 14.27.23 - A surprised hacker discovering that their usual Google tools are no longer accessible. The scene depicts a computer desk with multiple monitors, each .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/e35192a5-f39f-2000-7735-db3170a3e2f0.png)

# はじめに

ふとしたことで、久しぶりにクロージャー・コンパイラーを使う必要が出てきました。
こんな時はGoogle謹製のツールを使うのが簡単で安心です。

# あれ！

ブックマークしてあるGoogleの[Closure Compiler Service](https://closure-compiler.appspot.com/home)にアクセスしてみます。

使い方はとっても簡単です。
圧縮したいソースコードを所定の位置にペーストし、[Compile]をクリックするだけです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/8c18bf35-658c-038c-1e61-20367fe9706e.png)

おやおや、減るはずのコード量が逆に増えてる！それも約5倍弱に増えています!!!
久しぶりに使ったということもあり、何か間違ったかなと思い、オンランマニュアルを参照してみると。。。。
なんと、すでにサポートが終了していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/b1c96d53-a197-5d1c-c89c-066b1ad09bcc.png)

明らかにバグってますが、もう改善は望めませんね。。。
# 終わりに

この後、色々と調べた結果、Google様がNPMモジュールとして代替手段を提供してくれていることがわかりました。さすが、Google様です。
その名も、**google-closure-compiler**です。

具体的な導入方法と使い方は別の記事として書いています。
興味のある方はご参照ください。

https://qiita.com/yanagih/items/d668360b3db0e2e50a86

# 参考

https://developers.google.com/closure/compiler/docs/gettingstarted_ui?hl=ja

https://closure-compiler.appspot.com/home

https://www.npmjs.com/package/google-closure-compiler

https://qiita.com/yanagih/items/d668360b3db0e2e50a86
フリーランス向け法人化のナレッジ

文字ばかりですが、フリーランスの方で法人化を検討している方には読んで頂ければと思います。

# 法人化による節税額のシミュレーション
- 税理士費用も勘定にいれること（年間5,60万程度）
    - 「20~30万円程度じゃないの？」と思うかもしれませんが、なんやかんやとられます。
    - 基本的に経理は全て税理士に丸投げしましょう。自分でやるくらいならその分本業の稼働をした方が得。
- これを踏まえてせいぜい**数万程度×数年程度の節税目的なら法人化はおすすめしない**です。個人事業で青色申告してた方が絶対いいと思います。

# 事業所の所在地
- 引越を頻繁にする方や住所公開したくないならバーチャルオフィスも
    - バーチャルオフィスのデメリットもあるようなので要調査
- 自分の住所にすると度々法人向けのチラシが来ます。それ以外に害はないかと（個人の感想）

# 初年度の確定申告
- おそらく初年度は法人、個人いずれも確定申告が必要になります。
    - 構図としては「正社員（法人）が副業（個人事業、アルバイト）の確定申告をする」と変わり無いのでそのあたりの情報を参考にすると良いと思います。
        - やはり顧問税理士がいたほうが安心

# 創業赤字になり得る
- 登記した時点から出ていくお金として保険料（会社負担分）と役員報酬（こちらは登記後３ヶ月以内に出さないと損金算入できません）、また諸々の家事按分経費があります。それに対して売上ですが、大抵仕事の契約は３ヶ月〜の更新となります。法人としての売上が立つまでには銀行口座開設`*`の期間も併せて最長で5ヶ月程度掛かる見込んでください。この場合、何もしなければ創業はじめの数ヶ月は赤字となり、事業年度によっては創業赤字となり得ます。
    - 赤字の影響として銀行から融資を受ける際に影響があるぐらいです。フリーランスとしてやり続ける場合は問題ないと思われる
    - 対策として
        - 初年度の役員報酬は低めにする
        - 今個人として請けている契約を法人としての契約に覚書を交わせないか交渉する
            - その為には登記後最速で銀行口座開設を行うこと

`*` ちなみに法人の銀行口座開設は必須になります。無いと法人として取引してくれません。

# あったほうがいいもの
- 法人名義のクレジットカード（必須）
- 会社HP
    - 口座やクレカの開設の審査に必要だったりします。
    - 暇なければSaaS。ペラ１でいいので自分で作ってAWS等にホスティングするとかなり安く済む
- プリンタ。できればLANで接続するもの
    - 個人事業主ではPCに直接接続する小型のプリンタを購入し、使う度にプリンタをだしてしまってを繰り返してました。法人化後ではプリンタを使う頻度がかなり増えます。すぐに使える状態にしておくことを強く推奨します。
        - 役所のペーパーレス化に期待してはいけない
- gbiz Id 登記したらできるだけ早く取得したい。設立後の労務諸々の申請をe-govからできると思われる

# なくてもいいもの
- 就業不能保険
    - 個人事業主は基本、傷病手当金の制度がない為、別途就業不能保険等に加入される方がいるかもしれません
対して法人化するとどこかしらの健保組合に加入することになります。保険料は上がりますが、こちらは傷病手当金の制度があります。

# 税理士の選定
- 節税、補助金等の提案には期待しない。これは税理士の良し悪しではなくフリーランスとしてやっていく上で得られる節税や補助金はほとんど無い
- （同業者の方、是非コメント頂きたい）

# おわりに
法人化は上記以外にもやることがたくさんあります。
再度書きますが、せいぜい数万程度×数年程度の節税目的なら法人化はおすすめしないです。

それなりの節税効果が見込まれる、法人化により信用を得て仕事に繋げたい。あるいは今後自分で事業を興したいといった理由があればしても良いと思います。
Powershellでパスワード変更（ターゲット、接続先が管理者ユーザの場合）

```
PS>Get-LocalUser
Name               Enabled Description
----               ------- -----------
ユーザ名              True

PS>$PASSWORD = ConvertTo-SecureString -AsPlainText -Force -String "変更したいパスワード"
PS>Set-LocalUser -Name "パスワード変更するユーザ名" -Password $PASSWORD
```
参考URL
https://tex2e.github.io/blog/powershell/change-localuser-password
Vitestの内部で使われているvite-nodeを紐解く

この記事は[ZOZO Advent Calendar 2023](https://qiita.com/advent-calendar/2023/zozo) シリーズ3 16日目の記事です。

## vite-nodeとは

vite-nodeは、Vitestの内部で利用され、Vitestと共に開発されているライブラリでTypeScriptのトランスパイルなどをよしなにやってくれるランタイムのようなものです。
TypeScriptのトランスパイルをよしなにやってくれるランタイムのようなソリューションは思いつくだけでもいくつかあります。
[Bun](https://bun.sh/)、[Deno](https://deno.com/)、[ts-node](https://www.npmjs.com/package/ts-node)、[tsx](https://www.npmjs.com/package/tsx)、[tsimp](https://www.npmjs.com/package/tsimp)など。

対してvite-nodeは、TypeScriptだけではなく、CSSや画像、Vite(Rollup)用プラグインによってVue.jsやSvelteのコンポーネントファイルなどもサポートできます。
Vitestでは、vite-nodeを内部的に利用することでJestでは設定が複雑になっていたUIコンポーネントのテストなどをより簡潔にできるようにしています。

## vite-nodeの使い方

vite-nodeはts-nodeのようにコマンドラインから実行することができます。

```sh
vite-node src/index.ts
```

また、ここでは省略しますが、プログラムに組み込んで利用することもできます。

## vite-nodeの仕組み

vite-nodeを紐解くには、Viteの仕組みを理解する必要があります。

### Viteの仕組み

ここでは、Viteの開発サーバーの仕組みを~~簡単に~~紹介します。

StackBlitzでPlaygroundを用意しました。
Vite(Vue.js+TypeScript)のテンプレートのままです。

https://stackblitz.com/edit/vite-mechanism-playground

上記のPlaygroundにアクセスすると、Viteの開発サーバーが立ち上がります。
(PC)画面右では、プレビューが表示されます。

DevToolsのNetworkタブを開き、プレビューをリロードするとネットワークのログが閲覧できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213450/0dc23704-b8be-4ad5-2a0f-18bd294f98bb.png)

一番上のログは `/` へのアクセスで `/index.html` 相当が返されていることが確認できます。
その中には、 `<script type="module" src="/src/main.ts"></script>` が含まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213450/07c7e9ef-3d2f-f156-f25b-cb02b28afc0e.png)

ブラウザは、このスクリプトを読み込むため、 `/src/main.ts` にアクセスしてファイルを取得します。
ブラウザはTypeScriptを実行できないので、Viteの開発サーバーは `/src/main.ts` をトランスパイルして返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213450/767f4437-d2c5-a27f-6da9-c6e39ca4a46b.png)

さらに、main.tsでは `/src/App.vue` をimportしているのでファイルを取得します。
（元のファイルでは `./App.vue` をimportしていますが、絶対パス相当に変換されます）
当然、ブラウザは `.vue` ファイルを解釈できないので、Viteの開発サーバーは `/src/App.vue` をJavaScript相当に変換して返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213450/c2aea50a-5802-e13c-1a28-e29637aea5dd.png)

このように、Viteではモジュール単位でサーバーに問い合わせてJust-in-timeにトランスパイル処理などをしています。
これにより、開発時はバンドル処理などを(ほぼ)省略でき、高速な開発ができるようになっています。

※ネットワークリクエストはモジュールの数だけ増えますが、基本的にはローカルでの利用が想定されているために大きな問題にはなりません。
※当たり前のように書いていますが、Vite以前はモジュールごとにリクエストせず、ほぼすべてのモジュールを1ファイルにバンドルするのが主流でした。

### vite-nodeの仕組み

Viteは先に確認したように、サーバーとクライアントの仕組みで動作しています。

vite-nodeは、Viteのサーバーを動作させつつ、クライアント側もNode.js上で再現しています。
つまり、Viteの開発サーバーで動作を確認したようにモジュール毎にサーバー側へ問い合わせ、トランスパイルなどのステップが行われています。
トランスパイルされたコードは `node:vm` モジュールの [`script.runInThisContext`](https://nodejs.org/api/vm.html#scriptruninthiscontextoptions) で実行されます。

当然ですが、Vite(Rollup)で動作するプラグインによるモジュール解決が行われます。
Vue.jsやSvelteなどの開発者はVite向けのプラグインを作るだけでvite-node、Vitestの対応も完了します。

## まとめ

vite-nodeはVitestの内部で使われているライブラリです。
Viteの仕組みを活用することで、通常そのまま実行できない言語やファイルを処理しNode.js上でそれらの実行を可能にします。

上では述べていませんが、Bunも本体側がPlugin(Loader)の機能を持つことで同等の処理を実現しています。
しかしながら、Vitest(vite-node)はViteをフロントエンドフレームワークのコアに持ち併用する場合には、追加の設定などは不要になり複雑怪奇な設定地獄から解放してくれることでしょう。
Jupyter NotebookをPythonファイル(.py)に変換する

![DALL·E 2023-12-16 13.56.59 - A detailed scene depicting the conversion of a Jupyter Notebook to a Python file. The image shows a modern, well-lit office environment with a large c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/d779ed43-5dfc-d5dd-a02e-66e6eb2a6bba.png)

# はじめに

みなさん、Pythonプログラミング楽しんでいますか！
私も仕事柄、プログラミングをすることがあります。
最近ではJavaScritとPythonの比率が、JavaScrit:Python=2:8ぐらいとなっています。

# いざ、変換！

PythonプログラミングはJupyter Notebookを使用される方が多いと思います。
以前の私もJupyter Notebookを使用することが多かったのですが、最近はもっぱら、VS Codeに直接Pythonコード(.py)を入力しています。
仕事柄、他のエンジニアからJupyter Notebook形式のファイル(.ipynb)を受け取ります。Jupyter Notebookを実行する環境は用意しているのですが、やはり、直接 VS Codeで操作したいものです。(デバッグが楽なので！個人的な感想)

方法はコマンド一発で.ipynbを.pyに変換できます。
```shell
jupyter nbconvert --to python app.ipynb
```
カレントディレクトリに```app.py```というファイルが作成されています。

# 終わりに

Enjoy Python Life With VS Code!

# 参考

```shell
jupyter nbconvert
```
BQクエリ高速化のボトルネックを討伐しろ！〜実行グラフという名の地図〜

この記事はラクスパートナーズ Advent Calendar 2023の20日目の記事です。

## はじめに
少し奇抜な見出しから始まる本記事は、BigQueryでのクエリ高速化に取り組んだ実体験から学んだことをまとめるものになります。しかし、ただまとめるだけでは味気ないので、とあるモンスターを狩るゲーム風にして書いてくというのがコンセプトになります。簡単に設定の整理をしておきます。

- 課題：BQクエリの高速化＝モンスターを狩る
- 問題：どのコードがボトルネックで、それはどこにあるのか＝モンスターは何で、どこに生息しているのか
- 方法：ボトルネックとなるコードを修正する方法＝モンスターを倒す方法

## 最初に取り組んだこと
村長からモンスターを狩るように依頼を受け、どんなモンスタ－がきてもいいように装備を整えることから始めました。
### とりあえず倒す装備を整える
クエリの高速化に関する知識を書籍やネットを通じて調べて知識を蓄えていきました。
- SELECT * を避ける（必要なカラムを指定する）
- クロス結合の回避
- 集合関数の代わりにウィンドウ関数を検討
- etc...

この知識を適用できる箇所を探せばなにかしらできるだろう！と思っていました。すなわち、「ある程度の武器と防具があれば、どんなモンスターでも倒せるだろう！」と装備を整えたのです。モンスターには強みや弱点があり、それによって装備を変えなければならないという基本も忘れ、ましてやモンスターの位置も正体すらもわからないままに。。。😇

### いきなり荒野に飛び出す
次に、知識というの名の装備を整え（たと勘違い）、クエリという名の荒野にいきなり飛び込んで上から下まで読みました。そこで気づくのです。あ、あれ、モンスターどこにいるの？。。。というかどのモンスターを退治すればいいの？？と。
以下はクエリの概要です。

```sql
CREATE XXX TABLE AS

WITH XXX AS (
    ...
)

SELECT 
    A,
    B,
    ...
FROM C
INNER JOIN D
LEFT JOIN E
LEFT JOIN F
...
```
このクエリは、必要なカラムのみが記載され、クロス結合も、集合関数もありませんでした。。。
装備を整えたところで倒すべき相手が何でどこにいるかすらもわからないのです。

## 実行グラフと出会う
諦めて村へ帰り、村長に「なんの成果もありませんでした！」と報告しようとした時に、実行グラフという地図を見つけました。

実行グラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621732/bf26010c-e643-7585-f410-6ea997b133b6.png)
参考: [クエリ実行グラフを使用した BigQuery 分析クエリのトラブルシューティングと最適化](https://cloud.google.com/blog/ja/products/data-analytics/understanding-the-bigquery-query-execution-graph)

実行グラフとは、クエリの各ステージを視覚的に分割し、処理の流れや指標を示してれるものです。簡単にいうと目でクエリ実行の流れが追える人間にありがたいツールです。（こちらにより詳しい記事を書いてくださっている方がいらっしゃいます。参考：[BigQueryの「実行グラフ」をさわってみた](https://qiita.com/UenoKazuki/items/518bd2d58604e50c0af8)）
そこで元のクエリを動作させ、実行グラフとを確認したところ、コードを目で追うだけではわからなかったボトルネックが簡単に発見できました。それが以下の部分です。

```sql
FROM C
INNER JOIN D
...
```
なんてことない内部結合がこのクエリの大半の実行時間とコストを消費していたのです。さらに調査すると、Cテーブルが巨大なまま使用されていることが原因だとわかりました。ここにきて、ついにモンスターとその居場所を突き止めたのです。（←最初にやれ）

## モンスター討伐！
さて、後は正体がわかったCテーブルというモンスターを討伐するだけになりました。（だけ、と言いつつもこの後も戦闘は続いていくのですが、それはまた別のお話。。。）
結果として、BQのスロット時間を従来からおよそ1/7程度にすることができました！

## 振り返り
Bigqueryの実行グラフを紹介するという記事を書くつもりでいましたが、他にも学べたことがあるので振り返っておきたいと思っています。
1 . 原因が何かを把握する
 - コードを読むことももちろん重要ですが、実際に動かして、どこが原因か検討をつけるということが大切だと痛感しました。

2 . 原因がわかったら、適した解決策を考える
- 今回は解決策を調べて原因を探すという真逆のことを行いましたが、これでは知っている方法以外の原因＝なにもできなくなるということになります。原因がなにかをわからないと路頭に迷います。。

3 .BQで原因の特定に一役買ってくれるのが「実行グラフ」！ぜひ皆様も活用してみてください！

この記事が、少しでもお役に立てれば幸いです。読んでいただきありがとうございました！
Ruby on Rails で ElasticSearch をChewyで検索した際のN+1問題

Ruby on Rails で ElasticSearch と Chewyを活用して全文検索を実装しています。

> ### Chewyとは？
> Chewy is an ODM (Object Document Mapper), built on top of the official Elasticsearch client.
> https://github.com/toptal/chewy


検索した際にN+1問題がBulletで検知されました。

```ruby
objects = ParentModelIndex.query(match_query).load.objects
objects.each do |obj|
 obj.child # ここの行で
end
```

N+1が検出されます。

```text
GET /...
USE eager loading detected
ParentModel => [:child_model]
Add to your query: .includes([:child_model])
Call stack
```

## ChatGPTの解決策
これをどのように対応すべきか？ChatGPTの提案は以下の通りでした。

```ruby
ids = ParentModelIndex.query(match_query).load.map(&:id)
objects = ParentModel.where(id: ids).includes(:child_model)
```

納得いきますかこのコード？ `Chewy::Search::Response.objects` の処理は以下の通りです。

```ruby
  def objects
    @objects ||= begin
      objects = @loader.load(hits)
      if @paginator
        @paginator.call(objects)
      else
        objects
      end
    end
  end
```

ChatGPTの処理は劣化処理になっています。

## Chewyのコードを読み解く

そこでソースコードを読み解き増すと`Chewy::Search::Request.load`の定義は以下の通りです。

```ruby
      # Stores ORM/ODM objects loading options. Options
      # might be define per-index or be global, depends on the adapter
      # loading implementation. Also, there are 2 loading options to select
      # or exclude indexes from loading: `only` and `except` respectively.
      # Options are updated on further method calls.
      #
      # @example
      #   PlaceIndex.load(only: 'city').load(scope: -> { active })
      # @see Chewy::Search::Loader
      # @see Chewy::Search::Response#objects
      # @see Chewy::Search::Scrolling#scroll_objects
      # @param options [Hash] adapter-specific loading options
      def load(options = nil)
        modify(:load) { update!(options) }
      end
```

## 結論

以下のように`load`の際に`scope`を指定して`includes` してください。
```ruby
ParentModelIndex.query(match_query).load(scope: -> {includes([:child_model])})
```
不必要に/usr/srcを持ってませんか？ freebsd-update upgrade が遅いですよ

<!-- https://qiita.com/belgianbeer/items/a5ffcee86d2c660747f6 -->

# 不必要に/usr/srcを持ってませんか？ freebsd-update upgrade が遅いですよ

## はじめに

FreeBSDで新しいリリースが出て既存のFreeBSD環境をアップグレードする場合、`freebsd-update ugprade -r リリース`を実行します。この時`/usr/src`ディレクトリにソースが展開してあると、アップグレードにかかる時間が大きく増えます。これについて簡単に説明してみたいと思います。

なお本記事を書く前に同様の話があるかと検索してみたところ、数日前に投稿された「[FreeBSD14.0 アップグレード祭り](https://qiita.com/strnh/items/1940eec8cb42f2b0327d)」の記事でも中で触れられています。

## どうして/usr/srcがあると遅くなるの？

答えは単純です。/usr/srcがあれば、アップグレード時に更新しなければならないファイルが増えるので時間がかかるのです。

では実際/usr/srcにはどのぐらいのファイルがあるのでしょうか。そもそも全体でシステム関連ファイルの数はいくつあるのでしょう。ということで、簡単に数えてみましょう。

## FreeBSD 14.0-RELEASEでファイル数を数えてみる

次の一覧は FreeBSD 14.0-RELEASEで用意されているインストール用のtarballです。

```
$ ls
base-dbg.txz    kernel-dbg.txz  lib32-dbg.txz   ports.txz       tests.txz
base.txz        kernel.txz      lib32.txz       src.txz
$
```

portsとtestを除いて[^test]、各tarballのファイルを数えてみます。なおこの数え方ではディレクトリを除いているだけなのでシンボリックリンク等が含まれてしまいますが、全体から見れば誤差なので無視します。

[^test]:portsはfreebsd-updateでは関係無いですが、testは含めるべきかもしれません。

```
$ mv ports.txz tests.txz ..
$ ls
base-dbg.txz    kernel-dbg.txz  lib32-dbg.txz   src.txz
base.txz        kernel.txz      lib32.txz

$ for f in * ; do printf '%-16s %6d\n' $f $(tar tf $f | grep -v '/$' | wc -l) ; done
base-dbg.txz       1058
base.txz          27979
kernel-dbg.txz      858
kernel.txz          861
lib32-dbg.txz       243
lib32.txz           710
src.txz           96438
$
```

結果を見るとわかるように、srcのファイル数は10万個近いのに対して、他を合計してもファイル数は3万2千個程度で、3倍程度の違いになります。freebsd-update upgradeやfetchでは変更の無いファイルはダウンロードしませんが、OSのメジャーバージョンの時には大多数のファイルが更新されます。つまり/usr/srcがある場合は、無い場合に比べて4倍程度のファイル数のダウンロードが必要になるわけです。

## freebsd-updateの挙動とSSLのオーバーヘッド

通常freebsd-updateではシステムを更新する場合、次の2つの手順を踏むことになります。

1. 更新に必要なファイルをダウンロードする (freebsd-update fetch や freebsd-update upgrade -r XXXX)
2. ダウンロードしたファイルをインストールする (freebsd-update install)

問題となるのは最初の更新に必要なファイルをダウンロードするところで、freebsd-updateでは更新に必要なファイルを**1個づつダウンロード**します。現状freebsd-updateのサーバーはすべて海外であるため、RTTの関係でファイルのダウンロードに時間に占めるSSLのオーバーヘッドの割合が国内のサーバーに比べて極端に大きくなります。つまり更新ファイルを海外のサーバーから1個づつダウンロードする状況において/usr/srcが存在すると、占有時間が極端に増加することになります[^rtt]。

[^rtt]:実際には各ファイルのチェックサムによる確認なども行われるますが、トータルに占める割合は転送時間の方が大きくなります。

## おわりに

毎回カスタムカーネルを使っている状況なら/usr/srcは必須かもしれませんが、そうでなければ/usr/srcは無い方がリリースの更新時の処理時間を短縮できまるので、迷わず削除をお勧めします。

```
$ doas rm -rf /usr/src/* 

```

アップグレード時の処理時間を短縮する観点から、パッと思いついたアイデアを並べてみます。

- カスタムカーネルが必要な場合でもカーネルコンパイルを行うのは1台だけに限定して、そのサーバーだけ/usr/srcを保持し、他のサーバーで/usr/srcは持たない。
- 単に参照用に/usr/srcを持つのであれば、freebsd-updateでupgradeの作業中のみ/usr/srcを別名に変更し、OSの更新完了後に/usr/srcに名前を戻してあらためて`freebsd-update fetch ; freebsd-update install`を実行する
- ソースファイルは/usr/srcには展開せず、他の場所でgitを使って管理する

筆者の場合複数のFreeBSDサーバーを運用していますが、/usr/srcがあるのは1台だけに限定しています。また、以前に投稿した「[ストレージを消費しているものを探す](https://qiita.com/belgianbeer/items/44d2e9c2f9ee43f6537f)」にも書いたようにDEBUG関連のファイルを置かないのも、ストレージ使用量だけでなくファイル数の面でも多少のメリットがあります。
WindowsでCMakeを使う(MinGW, without VS)

# はじめに
WSL等, Linuxが使えて, そちらで代用できる場合はLinuxの方がよいかも

:::note alert
この記事は2023年12月時点での操作です. 情報が古くなっている可能性があります.
:::

# インストール
1. [MSYS2](https://www.msys2.org/)の公式ページからインストーラをダウンロード
1. 指示された手順通りにインストールを進めます
1. 8, Now you can call `gcc` to build software for Windows.まで出来たら一度 Windowsを再起動しておきます.
1. MSYS2 MINGW64を起動します. (アプリ一覧のMSYS2フォルダの中にあります)
1. 以下のコマンドを順に実行します. 
```
pacman -Suy
```
インストール済みのパッケージ群をアップデートします.
ターミナルが閉じられることもあります.
```
pacman -S --needed mingw-w64-ucrt-x86_64-toolchain
```
このコマンドを実行すると次のような選択を求められます
![スクリーンショット 2023-12-16 133404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2233331/67023334-8dc9-0175-6830-0048e6bc1ef8.png)
**C言語のプロジェクトで, CMakeを使う場合は 8番と15番をインストールします**

:::note warn
[VSCode](https://code.visualstudio.com/docs/cpp/config-mingw)のページを見ると全てインストールしていたりするので好みの問題でもあります.
8,15の場合は500Mib弱, 全てインストールすると1000MiB強です.
:::

:::note alert
2024/01/03追記
番号ずれてます
:::

```
pacman -S mingw-w64-x86_64-cmake
```
cmakeをインストールします.

# 使ってみる
プロジェクトのディレクトリで, 次を実行します. (大前提ですが, build/ の中に入っています)
```
cmake .. -G "MSYS Makefiles"
```

# おわりに
[16日目] PythonとFletで作ったソフトをexe化する

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の16日目の記事です。

昨日の記事で、PythonとFletを使ってYouTube動画ダウンロードソフトを作りました。

https://qiita.com/narikakun/items/118b704ea037ff8f7d73

今回は、このソフトを簡単に配布して動かせるようにexe化していこうと思います。

# exe化する方法
Pythonでは、exe化する方法としてPyinstallerというパッケージが用意されています。

https://pyinstaller.org/en/stable/

今回はこれと、Fletのパッケージ化機能を使って簡単にexe化していこうと思います。

# Pyinstallerのインストール
まず最初にPyinstallerをインストールします。いつも通りpipでインストールできます。

```
pip install pyinstaller
```

# パッケージ化
FLetのパッケージ化コマンドを利用して簡単にパッケージング出来ます。
今のコマンドで出来ます。
```
flet pack yt-downloader.py --name YouTubeVideoDownloader
```

実行するファイルと、nameにはソフト名を入力するだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/2913612c-2e6d-3160-eab2-284e5d7946e4.png)

完了すると、dictディレクトリとbuildディレクトリが生成されます。
dictディレクトリの中にexeファイルが保存されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/91c895d7-f3ec-d99c-f08d-dfc273a681a2.png)

実行するとしっかり起動することが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/250cfd95-9811-b849-2f77-b8328cf1dcaf.png)

# ソフトアイコンを作る
ソフトにはアイコンが無いと見分けがつきにくいですよね。ってことで、アイコンを作ります。
自分で作るのはめんどくさいので、AIに任せてしまいましょう（雑）
AIが作ってくれたアイコンです。まあまあいいのではないでしょうか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/e97be4aa-67c7-9409-cb85-53f16fae1e2d.png)

次にPython側です。png形式をicoなどに変換するためにpillowというモジュールをインストールする必要があります。pipでいつも通りインストールしましょう。

```
pip install pillow
```

後は、先ほどのパッケージ化コマンドに--iconでpngを指定するだけです。

```
flet pack yt-downloader.py --name YouTubeVideoDownloader --icon icon.png
```

これで完成です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/cb94c455-c6d5-4baf-61c9-e5752211b333.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/e4b2bae2-d260-df3a-c119-3bb7e12346c5.png)

# 最後に
今回出来たソフトを配布しておきます。

https://github.com/narikakun/youtube-video-downloader/releases/tag/v1.0

最後までお読みいただきありがとうございました。
LEGO Education SPIKEからMINDSTORMSへの移行

## はじめに
　先日公開した「LEGO Education SPIKE App3はクソ！」という記事で、ファームウェアを書き換えるという案を紹介しました。
 
https://qiita.com/cyber-yuito723/items/bdc1f54a35aa59ebd390

　この記事ではその手順を紹介したいと思います。

## ハブのファームウェアの書き換え
### ハブのファームウェアがApp3の場合
　この場合は、先にファームウェアをApp2(Legacy)に**ダウングレードする必要**があります。その後に、この記事の「App2(Legacy)の場合」の方に進んでください。ダウングレードの方法は、以下の記事で詳しく説明されています。

https://afrel.co.jp/product/spike/technology-spike/basic/software-basic/54122/

　**Windows**でダウングレードを行う場合は、**ドライバーを導入する必要がある**みたいです。Mac OSとChrome OSの場合は、追加のドライバーを導入する必要はないみたいなので、以下のサイトに直接アクセスして行うことができると思います。

https://spikelegacy.legoeducation.com/hubdowngrade/#step-1

### ハブのファームウェアがApp2(Legacy)の場合
　マインドストームのアプリを起動して新規プロジェクトを開いた上で、ファームウェアがApp2のハブをパソコンに**USBケーブル**で接続してください。次に右上の接続ボタンを押してください。そうすると「ハブOS更新が利用可能です。」みたいなポップアップが出てくると思うので、画面の指示に従って更新をしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/471c2dd9-5524-620b-d507-0640b28cb6ae.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/d3ac2462-d1cc-53f6-6029-bb26899961a7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/ef671023-00b4-8bb3-9201-b4d6bb9f6550.png)

## おわりに
　この記事の手順で進めてもらうとファームウェアをマインドストームのものに書き換えられると思います。SPIKEよりもマインドストームの方が明らかに高機能なので、ぜひ皆さんも試してみてはいかがでしょうか。これからもニッチな記事の執筆を頑張りたいと思います。
複数の動画ファイルを一気にmp4で圧縮する

![DALL·E 2023-12-16 13.16.42 - A scene depicting a computer setup with multiple video files being compressed into MP4 format simultaneously. The setting includes a large, high-resol.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/2211a298-b38a-cb6d-5617-1b241ecd8793.png)

# はじめに

最近、デモ動画を作成することが多くなりました。
デモ動画の収録には、QuickTimeを使うことが多いのですが、保存された動画ファイルは```mov```ファイルです。
ここで1つ問題が。数分の動画ファイルであっても数百MBになることです。
それと、もっと汎用的な形式であるmp4に変換したいところです。

# いざ圧縮 & MP4に変換

導入に必要なファイルはこちらからダウンロードできます。

https://ffmpeg.org/download.html

実行方法はとても簡単です。

```shells
ffmpeg -i 元のファイル 圧縮変換後のファイル
```
実行例
```shells
ffmpeg -i in.mov out.mp4
```
最も簡単に圧縮&MP4化が実現できます。
圧縮後サイズはおよそ1/10程度となり、パソコンのディスクにも優しいです。

# 終わりに

「『複数の動画ファイルの処理』を忘れていませんか？」という声が聞こえてきました。
はい、こちらです。
shell scriptを使う方法です。大量の動画ファイルも一気に変換できます。
コーヒーでも飲みながら一休み。

```shell
for i in *.mov
do
  fn=$(basename $i .mov)
  ffmpeg -i $i ${fn}.mp4
done
```
## 補足
ファイル名にスペースを含む場合はエラーが発生します。対策としては、変数をクオートする事です。
```shell: クオートの例
#!/bin/bash
for i in *.mov
do
  fn=$(basename "$i" .mov)  # $i をダブルクォートで囲む
  ffmpeg -i "$i" "${fn}.mp4"  # $i と ${fn} をダブルクォートで囲む
done

```
# 参考

https://ffmpeg.org/

https://www.shellscript.sh/loops.html

https://man7.org/linux/man-pages/man1/basename.1.html
機械学習のモデルについてのモデルのまとめ

機械学習に関する知識関するメモになります。

### ロジスティック回帰モデル
- ロジスティック回帰モデルは、分類問題を解くための統計的手法であり、特に2つのクラスに分ける場合に利用されます。例えば、あるメールが「スパム」か「非スパム」かを判定するときに使用されます。
- ロジット変換は、線形結合の結果を確率に変換するために行われます。ロジスティック回帰は、シグモイド関数を通じて線形結合の結果を確率に変換します。この確率は0から1の間であり、通常、0.5を超える場合に一方のクラスに、それ以下の場合に他方のクラスに分類されます。
- ロジスティック回帰モデルは、特徴量の重みとバイアスによって定義される線形モデルです。トレーニングデータに基づいて最適な重みとバイアスを学習します。

### 決定木モデル
- 決定木モデルは、樹形図で表現される機械学習モデルであり、条件分岐によってデータを分類または回帰します。各ノードは特定の条件でデータを分割し、葉ノードでは最終的なクラスまたは数値を予測します。
- 決定木は、データの非線形な関係を捉える能力があり、直感的に理解しやすい特徴があります。ただし、過学習のリスクがあるため、適切な枝刈りやアンサンブル法（例：ランダムフォレスト）の利用が一般的です。

### ランダムフォレスト
- ランダムフォレストは、複数の決定木モデルを組み合わせるアンサンブル学習法の一つです。各決定木は異なる部分集合のデータでトレーニングされ、結果を組み合わせてより汎化性能が高いモデルを構築します。
- ランダムフォレストは過学習への耐性があり、高い予測性能を持ちつつ、ハイパーパラメータの調整が相対的に容易です。
- 特徴の重要性を評価する際にも利用され、どの特徴が予測に重要であるかを理解するのに役立ちます。
Flutter WebとWasmGCと最適化

## はじめに
WebAssembly(WASM)において標準化が最終段階にあるガーベージコレクション(GC)サポート(WasmGC)についてChromeのJavaScriptエンジンであるV8のブログに[興味深い投稿](https://v8.dev/blog/wasm-gc-porting "A new way to bring garbage collected programming languages efficiently to WebAssembly · V8")がありました。

WasmGCの最大の特徴はもちろん、Dart、Java、Kotlin、Go、C#等のメモリ管理をGCに頼る言語(GC言語)においてWASMをターゲットとしたコンパイラ実装が容易になることです。
また、WASMにコンパイルしたGCエンジンをアプリに同梱するのと比較して、アプリのロード、実行時間、メモリ管理が効率的になります。

しかし、個人的に同ブログで最も興味深かったのは最適化に関する話題でした。
以降、WasmGCにおける最適化について話します。

## ツールチェーン最適化(AOT最適化)

下図は同ブログからの引用です。

![workflows1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37980/ee6a2744-4c36-6774-6500-2b752e88f220.png)

上図において、各ボックスはコンパイラツールチェーンにおけるツールです。
Source codeはソースコードから中間表現(IR)を生成するコンパイラのフロントエンドツールです。
Language optsは言語固有の最適化ツールです。
WasmMVPがC、C++、Rust、Swift等のメモリ管理を静的に指示する言語(非GC言語)を想定したWASMコード生成ツールです。
WasmGCがGC言語対応のWASMコード生成ツールです。

General optsは言語横断の一般的最適化ツールですが、注目すべきはその位置です。

非GC言語の実装の多くはLLVMを活用しており、WASM等のターゲットコードの生成前にLLVMのツールチェーンにより一般的最適化が行われます。
言語ごとに一般的最適化を実装しなくて良いところがLLVMのメリットでもあります。

対して、WasmGCワークフローではWASMコード生成後に一般的最適化が行われています。
WasmGCにおけるヒープオブジェクト(GCオブジェクト)はGCの都合上、原始的な型安全が確保されています。
この特徴を利用して、自動変数が指すGCオブジェクトのアロケーション、デアロケーションを省略する等の一般的最適化がWASMコードにおいて可能になるとのことです。
他にも関数ポインタとその呼び出し、コレクション要素の型他に関して最適化の余地があるそうですが、その詳細は同ブログからはわかりませんでした。

下図も同ブログからの引用です。

![workflows2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37980/b81f30e2-3958-be28-b197-a1751eaa883b.png)

LLVMも一応GC言語をサポートしていますが、これまでGC言語の多くはLLVMを活用せず、AOT最適化の全てを言語固有の最適化ツールが行っていました。
WasmGCワークフローでは、一般的最適化をBinaryenに期待しており、Googleはそこに投資していくそうです。

## VM最適化(JIT最適化)
一般的なGC言語では、スーパークラス型の変数を介したメソッド呼び出しにおいて、たとえそれが`virtual`と宣言されていなくとも、サブクラスでオーバーライドしたものがあればそれを呼び出します(ポリモーフィズム)。
そして、そのインライン化(ポリモーフィックインラインキャッシュ)は実行時(JIT)に行います。
また、ポリモーフィズムには実行時型(runtime type)が不可欠と言う点でGCと類似します。
V8におけるWASMのポリモーフィックインラインキャッシュは、WasmGC対応の一環で実装されたそうです。

ちなみに、非GC言語における関数のインライン化(インライン展開)はAOTに行います。

## 非GC言語におけるWasmGC
非GC言語においても、malloc等をGCオブジェクトにできる場合は、上記AOT最適化が可能となります。
その場合、メモリ管理が抽象化されるため、メモリのコンパクション(デフラグメント)も可能となります。
そう考えると、非GC言語の中では、メモリ安全なCarbonがもっともWasmGC恩恵を被る言語のひとつかもしれません。

## flutter WebとFlutter(ネイティブ)におけるWasmGC
FlutterのAdvent Calendarでしたので、Dartに話を戻します。

ブラウザで「ネイティブ」に実行するというDartの10年来の悲願がWasmGCによってまもなく達成されようとしています。
そして、当然ながらFlutter WebもWASM対応になり、それが標準になることでしょう、SafariもWasmGCをサポートすればですが。

ところで、Webを除くFlutterのターゲットプラットフォームではDartはネイティブにAOTコンパイルされます。
AndroidにおいてもFlutterアプリはARTを用いないネイティブアプリとなります。
ここで、Wasmerを使えばWASM経由でもネイティブにAOTコンパルが可能となるはずです。
そうすれば、言語固有最適化としていたものの多くを一般的最適化としてBinaryenに集約することも可能かもしれません。
しかしこれは、[JITコンパイルを避けるためにポリモーフィックインラインキャッシュをとりあえず諦めた](https://github.com/dart-lang/sdk/issues/37774#issuecomment-521163419 "AOT code is 65% slower than JIT on dart_style benchmark · Issue #37774 · dart-lang/sdk")ということでもあります。

他方で、WasmGC対応のVMならJITコンパイルを避けつつ、ポリモーフィックインラインキャッシュは行えるはずです。
つまり、AndroidやiOSがWASIを標準的に実装するとすれば、WASMコンパイル済みFlutterアプリをデプロイするという将来もあるかもしれません。
その前に、WASM VMを同梱したWASMコンパイル済みFlutterアプリをデプロイするという将来も。
プログラミングについて管理者がとりあえず知っておきたい内容　TypeScript編

# プログラミング全般について

ちょっと勉強しただけでは使えるようにはならない。
ただ、ちょっとだけでも勉強すると、ちょっとだけ雰囲気が分かる。
雰囲気が分かると、技術者と会話ができる。
ちょっと勉強して、技術者と会話できるなら、それはだいぶ勉強してみる価値がある。
管理者として手を動かせる機会が少なくなっている現実と向き合う！

組織のコミュニケーション機会が増えるだけでも十分！

管理者が、何でも分かる訳ではないが、分かろうとする姿勢は重要！


## 手始めにMicrosoft Bingに聞いてみた

TypeScriptの特徴と利点について、以下のようにまとめてみました。

・TypeScriptは、Microsoftが開発したJavaScript互換のプログラミング言語です。
　JavaScriptを静的型付けの言語にすることで、エラーを防ぎやすくしたり、大規模開発に適したりするメリットがあります。

・TypeScriptで書かれたコードは、コンパイルするとJavaScriptのコードに変換されます。
　これにより、JavaScriptの実行環境やライブラリをそのまま利用できます。

・TypeScriptは、クラスやインターフェースなどのオブジェクト指向の機能をサポートしています。
　これにより、コードの再利用性や保守性が向上します。

・TypeScriptは、Googleが開発するWebフレームワークのAngularで推奨されているほか、ReactやVue.jsなどのフレームワークでも使えます。
　TypeScriptは、JavaScriptの進化版とも言える、将来性の高い言語です。

もし、TypeScriptを学びたいと思ったら、以下のサイトが参考になるかもしれません。

TypeScriptとは？どのような言語で何ができるのかをわかりやすく解説
　https://qiita.com/IM_Tohru/items/b0471fff6cd08ae32926

TypeScriptとは？JavaScriptとの違いや特徴、メリット・デメリットを解説
　https://techmania.jp/blog/javascript0004/

需要急上昇で学習コスパ最強!TypeScript(タイプスクリプト)の特徴と学習方法
　https://descartes-search.com/media/why-you-should-learn-typescript/

【初めての】TypeScriptを使うべき3つのメリットと使い方
　https://tech.playground.style/javascript/typescript-merits/

TypeScriptの魅力について、少しでもお伝えできたら嬉しいです。

----

さすがAI！
上記の文章と、URLを見るだけで、分かった気がした。
※なお、上記のQiitaサイトに、TypeScriptの具体的な使い方あり。


ただ、そもそも日頃プログラムに表面的にしか触れていないのでTypeScriptの良さが分からない。

上記のようなJavaScriptのエンジニアが、TypeScriptのメリット記載しているWEBを「なるほど～」と分かっているか分かっていないかの狭間でみている。


ならば、ちょっとだけ本で勉強してみる。

# 図解！Typescriptのツボとコツがゼッタイにわかる本 「プログラミング実践編」　中田　亨「著」


まずはインストール！
Windowsの場合以下を実施。

・Node.jsのインストール。
　・https://nodejs.org/en/download

・コマンドプロンプトを開き


```node.jsのバージョンを確認
> node -v
```
```Typescriptのインストール
> npm install -g typescript
```

```Typescriptのバージョンを確認
> tsc -v
```


以下は本のホント最初の部分。詳しくは本を参照ください！

---
### TypeScriptでは定義されていないプロパティを参照することはできない。
```
　const obj = new Object();
　obj.name = "ゼリー"
```
※TypeScriptではエラーになる。JavaScriptではエラーにならない。

⇒クラスを使って、定義してオブジェクトを用意する。


簡単にオブジェクトを利用するための「オブジェクトリテラル」

「｛｝」を使うとプロパティを備えたオブジェクトとして使える。
```
const obj = {
 name:"ゼリー"
 flavor:"アップル"
}
```
```
obj.flavor="オレンジ"
```

----

### 型定義ファイル

型情報を持たないJavaScriptのライブラリをTypescriptから利用できるようにするためのファイル

----

以下、最初にやること


```tscconfigの作成
> tsc --init
```


app.ts(中身は空で良い)を作成し、作成したフォルダ上で
```コンパイルテスト
> tsc
```
⇒app.jsが作成されればOK



```クリーンビルド
> tsc --build --clean
```
⇒app.jsが削除されればOK


本ではapp.tsを「テストコード」用に存分に利用していた。

----

改めて
### 「オブジェクト」と「クラス」

##### オブジェクト
　・プロパティ(属性)
　・メソッド(機能)

⇒定義されたオブジェクトを実体化して利用する


##### クラス
　・オブジェクトがもつプロパティやメソッドを定義したもの



##### クラスを作成するための設計

　1. オブジェクトの洗い出し
　2. オブジェクトがもつ性質を決める
　3. オブジェクトのプロパティとメソッドを決める
　4. オブジェクトを性質(「動く」「表示」等)毎に分類し、
　5. 複数のオブジェクトに共通する機能の扱い(実装)を決める
　6. 共通利用のインターフェースやクラスをプロパティ、メソッドを決める
　7. オブジェクト毎のクラスについて、プロパティ、メソッドを決める(共通利用機能を反映する)
　8. これをパーツとして
　9. メインプログラムの流れを決める
　10. ファイル名とディレクトリ構造を決める

以上
Ubuntu 22.04でi3-gapsを導入する方法

# 背景

Linuxで利用可能な[i3wm](https://i3wm.org/)は、ウィンドウを自動でタイル型に配置してくれる便利なウィンドウマネージャです。

ただ、ウィンドウが隙間なく敷き詰められてしまい窮屈な印象があるため、ウィンドウ同士や画面の隅からの余白を調整できる機能が追加されたi3-gapsがi3-wmのフォークとして開発されてきました。そして、現在i3-gapsはi3wmのメインラインにマージされています([RELEASE-NOTES-4.22.txt](https://i3wm.org/downloads/RELEASE-NOTES-4.22.txt))。

ArchLinuxではi3-wmを導入するとデフォルトでi3-gapsが導入されるように[なっているのです]( https://wiki.archlinux.jp/index.php/I3)が、Ubuntuにはi3-gapsというパッケージは提供されていません。

Ubuntu 23.04以降では、i3-gapsがマージされた新しいi3-wmパッケージが降ってくるのですが、 \
Ubuntu 22.04に対して提供されるi3-wmのバージョンは4.20.1で[止まってしまっています](https://packages.ubuntu.com/search?keywords=i3)。

# 導入方法

Ubuntu 22.04でgaps機能を持つi3を使いたい場合は、手動で新しめのi3を導入するしか無さそうです。

一度現バージョンのi3を削除します（導入している場合）

```
$ sudo apt remove i3
```

jaistのリポジトリからv4.22.2のi3-wmを入手してインストールします。

```
$ cd ~/Downloads
$ curl -LO https://ftp.jaist.ac.jp/pub/Linux/ubuntu/pool/universe/i/i3-wm/i3-wm_4.22-2_amd64.deb
$ dpkg -i i3-wm_4.22-2_amd64.deb
$ rm i3-wm_4.22-2_amd64.deb
```

これでconfigファイルからgaps inner / gaps outerの値を設定すれば余白が生まれてくれます。 \
個人的には仕事のデスクトップで使うなら、gaps inner 8 / gaps outer 0くらいがデスクトップ背景の主張が控えめながらも少しチラ見えして好みです。

詳細なconfig設定方法は以下を参照。

https://i3wm.org/docs/userguide.html#gaps
UWSCRの組み込み関数：ファイル操作系

ファイル操作系組み込み関数の変更点および新規に追加された関数の解説です。

# 変更

## fopen

fopenの戻り値が数値ではなくなりました。代わりにファイルIDオブジェクトを返します。

:::note warn
以下のような記述はできなくなりました。

```php
fopen("hoge.txt")
fget(1, 1)
```
:::

### `F_APPEND`の追加

`F_APPEND`を指定するとテキストファイルの末尾に追記を行います。この場合第三引数に書き込みたい文字列を渡します。

```php
fopen("hoge.txt", F_APPEND, "書き込む文字列")
```

### ファイルIDオブジェクト消失時のファイルクローズ

ファイルIDを保持する変数がなくなった場合、そのファイルは自動でクローズされます。

```php
fid = fopen("fopen.txt", F_WRITE)
fput(fid, "てすと")
fid = EMPTY // この時点でファイルがクローズされ変更が反映される
```

これにより以下のような記述が可能になりました。

```php
fput(fopen("fopen.txt", F_WRITE), "べこべこ")
// 1. 第一引数評価時にファイルを開きファイルIDを返す
// 2. fputが対象ファイルに書き込みを行う
// 3. fput実行後にファイルIDが保持されていないため自動クローズされる
```

また、fcloseの呼び忘れなどでファイルをクローズしていなくてもスクリプト終了時にも自動クローズされます。

:::note info
ファイルIDオブジェクトのデストラクタ(のようなもの)でファイルクローズ処理を行っています。
:::

## iniファイル関連

### ファイルIDによるiniファイルの読み書き

iniファイル操作系関数にファイル名を渡す代わりにファイルIDを渡すことができるようになりました。

```php
inifile = "test.ini"

// ファイル名を指定した場合は都度ファイルをオープン/クローズする
writeini("filename", "foo", 1, inifile)

// iniファイルをfopenする
// 排他制御もできる
fid = fopen(inifile, F_WRITE or F_READ or F_EXCLUSIVE)

writeini("fid", "foo", 1, fid)
writeini("fid", "bar", 2, fid)
writeini("fid", "baz", 3, fid)

// fclose時に変更を反映
fclose(fid)
```

:::note info
- readiniには`F_READ`が必要です
- writeiniには`F_WRITE`が必要です  
    - 追記の場合は`F_WRITE or F_READ`にします
- deleteiniには`F_WRITE or F_READ`が必要です
:::

### readiniによるセクションおよびキー一覧の取得

iniファイルのセクション一覧およびセクション内のキー一覧を取得できるようになりました。
readiniの第一引数(セクション名)を省略すると対象iniファイルのセクション一覧を配列で返します。セクション名を指定し第二引数(キー名)を省略すると対象セクションのキー名一覧を配列で返します。

```ini:test.ini
[hoge]
foo=1
bar=2
baz=3
[fuga]
foo=1
[piyo]
bar=2
```
```php
inifile = "test.ini"

// セクション名省略でセクション一覧を得る
print readini(, , inifile)
// [hoge, fuga, piyo]

// キー名省略でキー一覧を得る
print readini("hoge", , inifile)
// [foo, bar, baz]
```

## getdir

:::note alert
破壊的変更があります。
:::


関数の戻り値が取得されたファイル名の配列となり、それに伴い`GETDIR_FILES`特殊配列変数は廃止されました。




# 新規

## zipファイル

zipファイルを扱えるようになりました。

:::note warn
パスワード付きzipファイルは未対応です。
:::

### zip

作成するzipファイル名とzipに含めたいファイルパスを指定し、zip圧縮します。

```php
// 3つのファイルをzipファイルに圧縮する
zip('test.zip', 'foo.txt', 'bar.txt', 'baz.txt')

files = [
    'qux.txt',
    'quux.txt',
    'corge.txt'
]
// 配列も可
zip('test2.zip', files)
```

### unzip

zipファイルを任意のフォルダに展開します。展開先フォルダが存在しない場合は新規に作成されます。

```php
unzip('test.zip', 'test')
for file in getdir('test')
    print file
next
// foo.txt
// bar.txt
// baz.txt
```

### zipitems

zipファイルに含まれるファイル一覧を得ます。

```php
for file in zipitems("test2.zip")
    print file
next
// qux.txt
// quux.txt
// corge.txt
```
余りの計算

:::note info
この記事は「[Infocom Advent Calendar 2023](https://qiita.com/advent-calendar/2023/infocom)」カレンダーの18日目の記事です
:::

今年も競プロのネタです。
「何らかの数式の計算結果を求める問題で数式の解の桁が大きくなるので、intで収まる程度の数字で割った余りを答えよ。」
といったタイプの問題が良く出ます。
今まで、計算の仕方もわからないし、余りを出力する意味もわからなかったのですが、今年読んだ対策本に数学の性質を利用して解くと解説があり、より深く習得するために本記事に記します。ただ、
余りを出力することが、現実的に何かに役立つのかは未だよくわかっていません。
『競技プログラミングの鉄則] 米田 優峻 (著)を参考にして記載しています。


# 一つ目の性質
足し算、引き算、掛け算の場合、好きなタイミングで余りをとっても答えは変わらない。
ただし、計算結果が負の数になる場合は、割る数を足す工夫が必要です。

数式で書くと以下。
~~~
//m, nをxで割った商(a, c)と余り(b, d)
m = ax + b
n = cx + d

(m + n)%x = (m%x + n%x)%x = (b + d)%x
(m - n)%x  + ((m < n) ? x : 0)= (m%x - n%x)%x =(b - d) < 0 (b-d+x)%x: (b-d)%x (m > n)
(m * n)%x = (m%x * n%x)%x =(b * d)%x
~~~
足し算と引き算はこの数式を見ればなんとなくわかります。
(m < n)の場合、(m - n)%xが負の数となるため、+xする必要があります。
掛け算については、mをn回足した余りは、足し算の性質を利用して、(b*n)%x。同じようにnをb回足すと考えると、(b * d)%xが導けます。


# 二つ目の性質
割り算の場合でxが素数かつnがxの倍数でない場合、以下に置き換えても計算結果は変わらない。
~~~
(m / n)%x =  m%x / n%x = (m%x * (n%x)^(x-2))%x
~~~
これは、フェルマーの小定理というのが関連してるそうでわかりそうにないので丸暗記します。
切り出すと、 /n%x は、*n^(x-2)の%x。
x-2乗で数字が大きくなる対策として、一つ目の性質を利用して、掛ける度に余りを取ります。更に計算量を減らすには繰り返し２乗法を使うそうです。
~~~
a^4%x = a^2%x * a^2%x
a^8%x = a^4%x * a^4%x
~~~
xが素数かつnがxの倍数でない場合と条件が限定されているので使いどころは注意が必要そうです。

#検証用のクラス
~~~
public class Amari {

	public int plusAmari(int m, int n, int x) {
		return (m % x + n % x) % x;
	}

	public int minusAmari(int m, int n, int x) {
		int o = (m % x - n % x);
		o = (o < 0) ? o + x : o;
		return o % x;
	}

	public int multifyAmari(int m, int n, int x) {
		return (m % x * n % x) % x;
	}

	public int devideAmari(int m, int n, int x) {

		/*
		 * (m/n)%x
		 * (→ (m%x / n%x)%xは成り立たない )
		 * = (m%x * (n%x)^(x-2))%x
		 */

		return (int) ((m % x * Math.pow(n % x, x - 2)) % x);
	}

	//(n%x)^(x-2) が大きい数字となる対策として都度、余りを取る
	public int devideAmariBig(int m, int n, int x) {

		//Math.pow(n%x, x - 2)%xの計算
		int nx = n % x;
		int nn = nx;
		for (int i = 0; i < x - 2 - 1; i++) {
			nn = multifyAmari(nn, nx, x);
		}

		return (int) ((m % x * nn) % x);
	}
}
~~~
# 応用
これらを使えば、pCr = p!/(r!*(p-r)!)をxで割った余りを求める問題が計算可能になります。

①p!%xを計算。mとする。
②r!%x、(p-r)!%xを計算。nとする。
③(m/n)%xを二つ目の性質を使って計算（mとnはあまりを取ったあとの数字のため、m/nを計算してはいけない）

AtCoderの過去問といて習得しようと思います。