OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】ネストされた関連オブジェクトのレンダリング問題とその対処法

## 概要

`Rails` で `API` を開発する際に、`ActiveModelSerializers` のバージョン `0.10.x` を使用しているとネストされた関連オブジェクトをレンダリングできないという問題に直面しました。この問題は、`render` メソッドで `include` オプションを明示的に指定することで解決できます。

## 原因

`ActiveModelSerializers` のバージョン `0.10.x` では、デフォルトでネストされた関連オブジェクトの自動レンダリングがサポートされていません。これにより、期待通りにネストされた `JSON` を返却するために追加の手順が必要になります。

## 対処法： `include` オプションの使用

期待通りにネストされた `JSON` レスポンスを生成するためには、`render` メソッド内で `include` オプションを使用して、明示的にネストされたオブジェクトを指定する必要があります。以下は、店舗情報とその関連オブジェクトをレンダリングする `Rails` コントローラーの実装例です。

```ruby:get_stores_controller.rb
class Api::V1::StoresController < ApplicationController
  def index
    stores = Store.includes(:company, :prefecture, :city).order(id: :desc)
    render json: stores, include: ['company', 'prefecture', 'city'], status: :ok
  end
end
```

この方法を用いることで、クライアントに対して期待通りのネストされた `JSON` レスポンスを返却することが可能になります。

## 参照

https://github.com/rails-api/active_model_serializers/issues/1077

自らの備忘録のために投稿してますが、なにかお役に立てましたら幸いです！:clap:
また、なにか間違ってましたらご指摘いただけますと幸いです！:pray:
デメテルの法則とは

# デメテルの法則とは
デメテルの法則（Law of Demeter）は、オブジェクト指向プログラミングにおけるソフトウェアデザインの原則の一つです。この法則は、オブジェクト間の結合を緩やかにすることを目的としています。

デメテルの法則は、次のように表現されます。

「モジュールは、他のモジュールに直接の依存を持たないようにすべきである。」

より具体的には、以下のような原則に基づいています。

1. メソッドは、自身のクラス、引数として渡されたオブジェクト、メソッドで生成またはインスタンス化されたオブジェクト、その属性にのみメッセージを送信するべきです。メソッドがこれら以外のオブジェクトにメッセージを送信する場合、それはそのオブジェクトとの結合を強めることになります。
2. メソッドは、引数として渡されたオブジェクトのメソッドのみを呼び出すべきであり、そのオブジェクトの属性には直接アクセスすべきではありません。
3. メソッドは、自身のクラスに属する属性やメソッドにのみアクセスすべきです。他のオブジェクトの属性やメソッドに直接アクセスすることは避けるべきです。

# まとめ
デメテルの法則に従うことで、オブジェクト間の結合を緩やかにし、コードの保守性や拡張性を向上させることができます。
#1 AppのGIF録画に慣れる

iOSブートキャンプでの学習過程をQiitaに記録していきたいと思います。最初の課題は、シミュレータの録画機能に慣れることでした。そこで、以前に作成したプロジェクトを使ってこの課題を完了することにしました。

それは、私の履歴書アプリです！このアプリは、将来日本の企業面接で使用する予定です。内容には、私が持っているスキルや職務経験などが含まれています。将来的には、自分の履歴書なども追加するかもしれません。

![Simulator Screen Recording - iPhone 15 Pro - 2024-03-25 at 00.19.29.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3703986/498545d3-924a-9add-4821-08e3fddb2dd9.gif)

以下はGitHubのリンクです：
GitHub - liyoway/MyResume
Mathematica で burning ship fractal

[Burning Ship fractal](https://en.wikipedia.org/wiki/Burning_Ship_fractal) を Mathematica で描いてみた！

## 1. 条件
- 漸化式
```math
\left\{ \begin{align}&z_{n+1}=(|\mathfrak{R}(z_n)|-i\,|\mathfrak{I}(z_n)|)^2+c\\&z_0=0\end{align}\right.
```
- 最大反復回数：100 回
- 画像の縦の長さ：1920 px
- 表示範囲：左上 -1.8 + 0.0825 i , 右下 -1.7 - 0.0175 i

## 2. コード
```wl:burningship.nb
burningship[re_, im_, maxIter_] := (c = re + im I; z = 0. I; 
  For[i = 1, i < maxIter + 1, i++, 
   z = (Abs[Re[z]] - I Abs[Im[z]])^2 + c; 
   If[Abs[z] > 2, Return[N[i/maxIter]]]]; Return[0])
   
xrange = {-1.8, -1.7}; yrange = {0.0825, -0.0175};
width = xrange[[2]] - xrange[[1]];
height = yrange[[1]] - yrange[[2]];

rows = 1920;
columns = Round[(width/height) rows];
result = ConstantArray[0, {rows, columns}];

rspace = Array[# &, rows, yrange];
cspace = Array[# &, columns, xrange];

For[rowIndex = 1, rowIndex < rows + 1, rowIndex++, 
  im = rspace[[rowIndex]]; 
  For[columnIndex = 1, columnIndex < columns + 1, columnIndex++, 
   re = cspace[[columnIndex]]; 
   result[[rowIndex, columnIndex]] = burningship[re, im, 100]]];
   
wb = ImageAdjust[Image[result]] (*白黒*)
Colorize[wb,ColorFunction->Hue,ColorRules->{0->Black}] (*カラー*)
```
## 3. 出力結果
![burningshipwb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3278375/f3554213-1e0d-8e59-671f-d054db841330.jpeg)
![burningshipcolor.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3278375/5d1100dc-e11e-4ec9-e933-129446b87872.jpeg)

名前の通り（沈んでいる）船みたいに見えます。
めちゃくちゃ綺麗！！
ユーザーマスタはマスタデータか？

もしかして、最近のスタッフにデータの基本的な種類を教えてなかったんじゃないかと思った次第です。
すでにいろんなところで論じられている内容ですが、自分用に記載。

# 「マスタデータ」とはなにか

面接をしているときもこれを答えられる人に出会っていないのはなぜだろう。
マスタデータとトランザクションデータというのは基本情報などでも出ていたはずです。
データ一貫性のトランザクションはみんな知っているのだけれど、トランザクションデータを知らない。

> マスターデータ（master data）とは、企業内データベースなどで、業務を遂行する際の基礎情報となるデータのこと。また、それらを集約したファイルやデータベースのテーブルなど。単に「マスタ」と省略するのが一般的である。
> IT用語辞典

https://e-words.jp/w/%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%87%E3%83%BC%E3%82%BF.html

> トランザクションデータ（transaction data）とは、企業の情報システムなどが扱うデータの種類の一つで、業務に伴って発生した出来事の詳細を記録したデータのこと。 ファイルに記録したものは「トランザクションファイル」という。
> IT用語辞典

https://e-words.jp/w/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%87%E3%83%BC%E3%82%BF.html

自分はいい加減ですが、単純に「マスタデータは基本的なデータで変更されることはあまりない」、「トランザクションデータはユーザによって常に更新が発生するデータ」と認識しています。
そのため、マスタデータはキャッシュ可能、トランザクションデータはキャッシュ困難（不可能とは言っていない）というふうにしています。（考え方がゲームAPIサーバー的なのは癖みたいなものです）


# ユーザーマスタはマスタデータか？

上記の文脈だと、我々利用するオンラインサービスのほとんどは、ユーザーの基本情報を管理するデータはトランザクションデータということになります。
ユーザーは自らサインアップして、データをオンラインサービスに作り、プロフィールも変更しちゃいます。
ですが、開発者は「ユーザーマスタ」と言いがちです。

これは「業務システムではユーザーマスタは、管理者によってあらかじめ作られるもの」というところの名残が未だに受け継がれているのだと思っています。

例えばグループウェアに新入社員のアカウントを作るときは、会社の管理部や人事部といったところで作成、削除するという感じです。不用意に作られては困りますからね。

https://zenn.dev/dove/articles/c5672dda4c268e


# ちなみに消していいのか

マスタデータにしてもトランザクションデータにしても原則消してはいけません。
基本的にマスタデータは恒久的なデータなので、たとえ必要な時期が過ぎたとしても、残しておくの通常だと思います。
ECの商品データ、辞めた従業員のアカウント、再度同じIDやアカウント名を使用して、古いデータと意図せずリンクしてしまわないように、メールを受け取ってしまわないようにしておく必要はあると思います。

それにも消してしまうのには理由があるはずです。
トランザクションデータ、特に履歴のデータであれば保管期間を過ぎたものを容量の都合で消すとかですかね。
【CSS】中心からグラデーションをかけた円形UIの作成方法

# ◆はじめに
本記事ではグラテーションのかかった円形のUIを作成します。
イメージとしては、円の中心から離れるにつれ徐々に透過される円形のグラデーションです。
HTML、CSSを使用します。


# ◆HTML
簡単にHTMLを作成します。
CSSを当てる予定の`div`タグを1つ作成しておきます。
```html:index.html
<!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="./index.css">
        <title>Document</title>
    </head>
    <body>
        <div class="blur-gradient"></div>
    </body>
</html>
```

# ◆CSS
- `body`：widthとheightを指定し、ページ全体に対して横幅と高さを100%に設定します。
また、FlexBoxを指定して、上下中央に子要素を配置しています。

- `blur-gradient`：border-radiusプロパティを用いて要素を円形にします。
backgroundプロパティで中心から外側に向かって徐々に色が変化するグラデーション（青⇒透明）をつけています。

```css:index.css
body {
  padding: 0;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
}

.blur-gradient {
  width: 300px;
  height: 300px;
  border-radius: 50%;
  background: radial-gradient(rgb(24, 155, 255) 10%, transparent 100%);
}
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/e8c4d77d-d6e0-43c8-90ae-5fda836c4a56.png)
軌跡とプログラミング

# はじめに
高校数学2、3において放物線、円、楕円、双曲線の軌跡と方程式は頻出である。しかし、定義からそれらを実際に図示してみるという取り組みはあまりないようである。従って、本記事ではPythonを用いて、定義からそれぞれのグラフを描写することができるかどうかを考察する。具体的には、まず各曲線において描き方（定義）を述べ、それに応じたプログラムを作ることでどのようなグラフになるのかを図示する。


# 円
## 定義
定点から距離が一定の点が描く軌跡を円と呼ぶ。
## プログラム
複素数平面を用いてプログラムを作成した。

```python circle_tra.py
import numpy as np
import matplotlib.pyplot as plt
import math
import japanize_matplotlib

m=2
n=100

#座標空間の設定
x=np.linspace(-m,m,n)
y=np.linspace(-m,m,n)

X,Y=np.meshgrid(x,y)

#Z=(X**2+Y**2)**0.5

Z=abs(X+1j*Y)

plt.contourf(X,Y,Z)
plt.colorbar(label="半径")
plt.savefig("円の軌跡.png")
plt.show()
```

![円の軌跡.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/0c660bbf-00cd-1ff6-470d-2a0498574c0a.png)

# 楕円
## 定義
2点からの距離の和が一定な点が描く軌跡のことを楕円と呼ぶ。
## プログラム
``` ell_tra.py
import numpy as np
import matplotlib.pyplot as plt
import math
import japanize_matplotlib

m=2
n=100

#座標空間の設定
x=np.linspace(-m,m,n)
y=np.linspace(-m,m,n)

X,Y=np.meshgrid(x,y)

Z_a=1
Z_b=-1

z=X+1j*Y

Z=abs(z-Z_a)+abs(z-Z_b)

plt.contourf(X,Y,Z)
plt.colorbar(label="距離の和")
plt.savefig("楕円の軌跡.png")
plt.show()
```
![楕円の軌跡.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/a4451fd1-d58e-2744-2e1a-fd8616ad4334.png)

# 双曲線
## 定義
2点間からの距離の差が一定になるような点が描く軌跡を双曲線と呼ぶ。
## プログラム
``` python hyper_tra.py
import numpy as np
import matplotlib.pyplot as plt
import math
import japanize_matplotlib

m=2
n=100

#座標空間の設定
x=np.linspace(-m,m,n)
y=np.linspace(-m,m,n)

X,Y=np.meshgrid(x,y)

Z_a=1
Z_b=-1

z=X+1j*Y

Z=abs(z-Z_a)-abs(z-Z_b)

plt.contourf(X,Y,Z)
plt.colorbar(label="距離の差")
plt.savefig("双曲線の軌跡.png")
plt.show()
```
![双曲線の軌跡.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/f3cf7904-c852-002d-aadd-2bc721efafb0.png)

# 放物線
## 定義
ある点とある直線からの距離が等しくなるような点が描く軌跡を放物線と呼ぶ。
## プログラム
``` python par_tra.py
import numpy as np
import matplotlib.pyplot as plt
import math
import japanize_matplotlib

m=2
n=100

#座標空間の設定
x=np.linspace(-m,m,n)
y=np.linspace(-m,m,n)

X,Y=np.meshgrid(x,y)

Z_x=-1

Z=1

z=X+1j*Y

Z=abs(z-Z)-(z-Z_x).real

plt.contourf(X,Y,Z)
plt.colorbar(label="直線と点からの距離の差")
plt.savefig("放物線.png")
plt.show()
``` 
![放物線.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/254de751-56af-ed5d-4002-711cda96ab94.png)


まとめ
今回は、コンター図を用いて二次曲線の軌跡を定義からプログラムを用いて描写した。ただし、描写においては複素数平面を用いた。結果としてきれいに描写することができていることが分かった。
[過去記事]Vue.js 定義した文字列を仮想DOMで表示する

## 概要

今回は前回の記事で使用したソースを解説しつつVueで定義した文字列を仮想DOM側で表示する方法をまとめます。仮想DOMがなんだかわからないよ〜という方は「script要素内のVueで定義した文字列をbody要素内に表示するんだな〜」くらいに思っておいてください！

前回はこちら↓

https://qiita.com/miriwo/items/84ee6cadf243e0d6028f![Document-1-1024x232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/156b4553-1015-aea3-98f5-50f00aec7b59.png)

## 前回のソース

まずは前回記載したindex.htmlファイルのソースを下記に記載します。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <header></header>
    <main>
        <div id="app">
            {{ message }}
        </div>
    </main>
    <footer></footer>
    <script>
        let app = new Vue({
            el: '#app',
            data(){
                return {
                    message: 'Hello Japan'
                }
            },
        })
    </script>
</body>
</html>
```

上記ファイルをブラウザで開くと下記のように表示されます。

![Document-1-1024x232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/8fbf6bdc-4ae6-9ee4-6bb1-fff88352be68.png)

## 前回のソース

まずはmain要素内部から見てゆきましょう！下記にmain要素内部のソースを記載します。

```html
<div id="app">
    {{ message }}
</div>
```

div要素にid「app」を設定してその中にマスタッシュ構文でvueのmessageの内容を表示するように指定しています。

次にscript要素内を見てゆきましょう！下記にscript要素のソースを記載します。

```html
<script>
    let app = new Vue({
        el: '#app',
        data(){
            return {
                message: 'Hello Japan'
            }
        },
    })
</script>
```

変数appを定義して、その中にインスタンス化したvueを格納しています。
インスタンス化されているvueのソースではelオプションを用いてmain要素内部の範囲（今回で言う所のdiv要素のid名）を指定しています。
dataメソッドでキーであるmessage:を定義して値は「Hello Japan」を格納しています。

この２つの要素でvueで記載した文字列が画面に表示されていたということです！

## 最後に

以上で準備時に記載したソースの解説は以上です！次回はいよいよ本格的にVueのソースを記載してゆこうと思います！
useStateとは

useStateとは、ReactのHooksの一つで、状態を管理したいときに使う！
状態(state)とは、コンポーネントが内部で保持するデータであり、文字列、数値、真偽値、配列などさまざまな値を保持できる。

useStateは二つの値を持っており、一つが現在の状態の値を表す変数。
二つ目が状態を更新するための関数です。この関数を使って新しい状態の値をセットすることができる。

ボタンをクリックするとcountの値が1ずつ増加するプログラムを例にする。

```.jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  function handleIncrement() {
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleIncrement}>+1</button>
    </div>
  );
}
```
ここではuseStateの初期値に0を渡している。
そして、setCount関数を呼び出すことで、countの値がプラス１される。
また、handleIncrement関数はbuttonが押されるたびに呼ばれる。

このようにuseStateを使うことで状態を管理してあげることができる！
ObsidianのVimモードでノーマルモード移行時にIMEを自動で切り替える設定


マークダウンエディタ [Obsidian][obsidian] でvimモードを使いたかったのですが、日本語IMEの場合、カーソル移動時に「っj」みたいな文字がばらまかれて厄介だったので対策しました。

Vim IM Selectだと、「im-select使ってね！」っぽいことを言っていたんですが、なーんかうまくいかなかったので、「これzenhan噛ませたらいけんじゃね？」とやってみたらできたかんじです。

# 使うもの

**Obsidianプラグイン**
- [obsidian-vimrc-support][vimrc-support]
- [vim-im-select-obsidian][vim-im-select]

**IME自動切替プログラム**
- [zenhan][zenhan]
iuchi様が作成してくださったプログラムです
イイ感じの場所に置いてください

# 手順

1. プラグインをインストール
2. [zenhan][zenhan]をダウンロードして適当な場所に置く
3. Vim IM Select の **Setting for Windows platform** 欄の値を以下のようにします
パスの部分は、zenhanの記事でパスを書いてる部分と同じ書式で書いてください。
ex.) `C:\\users\\foo\\bin\\zenhan.exe`

| オプション                         | 値                      |
| ----------------------------- | ---------------------- |
| Windows Default IM            | 0                      |
| Obtaining Command for Windows | (zenhan.exeの絶対パス)      |
| Switching Command for Windows | (zenhan.exeの絶対パス) {im} |

:::note warn
設定後はObsidianを再起動してください
:::

以上の設定が完了すれば、ノーマルモード移行時にIMEが半角英数になっているはずです。
これでObsidianでもVim生活が送れるよ！
各プラグインを作ってくださった方々には感謝しかありません

# リンク

- [Obsidian][obsidian]
- [Vimrc Support][vimrc-support]
- [Vim IM Select][vim-im-select]
- [zenhan][zenhan]

[obsidian]: https://obsidian.md/
[vimrc-support]: https://github.com/esm7/obsidian-vimrc-support
[vim-im-select]: https://github.com/ALONELUR/vim-im-select-obsidian?tab=readme-ov-file
[zenhan]: https://qiita.com/iuchi/items/9ddcfb48063fc5ab626c
【ターミナル】最近覚えたコマンド一覧の紹介(Mac)

こんにちは！
今回は最近覚えたターミナル基本的なコマンド10選を紹介したいと思います。
最後まで見ていただけたら嬉しいです！

## コマンド一覧

### 1, ls
``` php
ls //現在のディレクトリ内のファイルとディレクトリをリストします。
```

### 2, cd
``` php
cd ディレクトリのパス //ディレクトリを変更します。
```

### 3, pwd
``` php
pwd //現在の作業ディレクトリのパスを表示します。
```

### 4, mkdir
``` php
mkdir ディレクトリ名 //新しいディレクトリを作成します。
```

### 5, rm
``` php
rm ファイル名 //ファイルを削除します。
```

### 6, rmdir
``` php
rmdir ディレクトリ名 //空のディレクトリを削除します。
```

### 7, cp 
``` php
cp ソースのファイル/ディレクトリ ターゲットの場所 //ファイルやディレクトリをコピーします。
```

### 8, mv
``` php
mv ソースのファイル/ディレクトリ ターゲットの場所 //ファイルやディレクトリを移動させます。または、名前を変更します。
```

### 9, touch
``` php
touch ファイル名 //ファイルを作成します。存在しない場合は、空のファイルを作成します。
```

### 10, cat
``` php
cat ファイル名 //ファイルの内容を表示します。
```


## 終わりに
今回は以上になります！
最後まで見ていただきありがとうございました！
では、また次の記事で〜！
【git】コンフリクトをマージせずに解決する方法 "リベース"

## はじめに
コンフリクトが起きた時、プルリクを作り直してmergeしていたところ、メンターさんに「リベースで解決できるといいね」とアドバイスをいただきました。リベースってなんだ、と思い使ってみたところとても便利なコマンドだったのでメモしたいと思います。

## リベースとは
以下の図のようにmasterブランチから複数のブランチが切られているとします。（図はgit graphを用いています）
![スクリーンショット 2024-04-13 22.48.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/fc95d180-99fc-9fc2-0b65-0eb197c572f7.png)

図のように片方（feature/1）が先にmergeしたとします。
![スクリーンショット 2024-04-13 22.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/864804d3-c363-e0f1-6976-2657ede384b2.png)

その後、feature/2をmerge(`git merge origin/feature/2`)すると以下のようにコンフリクトが発生して拒否されます。
![スクリーンショット 2024-04-13 22.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/888b24f8-ae38-2a21-b054-32993bb98e8b.png)

そんな時、リベースが力を発揮します！
現在のmasterの状態をfeature/2にpushします。
```
git push origin master:feature/2 -f
```

feature/2にチェックアウトし、フェッチしてから、リベースします。

```
git fetch
```

```
git rebase origin/master 
```
上記2つのコマンドは以下のコマンドでまとめて実行することもできます。
```
git pull --rebase origin master
```
すると、まるでfeature/1のマージ後にfeature/2ブランチを切ったかのようになります。
![スクリーンショット 2024-04-13 23.27.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/7da822b0-7e78-9d0e-269b-33b529342c02.png)
※訳あってmasterがmainになってます


このようにベースを定義し直すことからリベースと呼ばれるのかもしれませんね。

## 最後に
リベースはマージと比べてコミットが作られないというメリットもあるそうです。これまでマージしか使ってきませんでしたが、これから目的に応じてこれら２つを使い分けられるようになりたいです。
【大発見】Markdownで楽にリンクを貼る方法

# 前書き

GitHub上でmdファイルをいじっているときに偶然発見した。
またVSCodeのmdファイルでも同様のことができた。

しかしQiitaの編集画面ではできなかった！残念！

# 方法

1. テキストを入力
1. そのテキストを選択
1. コピーしたURLをペーストするとリンクが貼られる

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/e7f46e48-d8ba-fc18-15cb-b9e732a5dfba.gif">
自己紹介記事

# 自己紹介

これからQiitaを投稿していくに辺り、
どんなやつが書いたのか自己紹介ぐらいは書いておけと記事がありましたので
軽く自己紹介記事を最初に投稿しようと思います。

これまで、プログラムは無理だなと思っていた私ですが
仕事上機会があり、Go言語を用いた開発に携わることとなりました。

仕事では、Go言語でのデバイス制御や
バックエンド開発を行っております。

当初より想像以上にプログラムができてしまったので(挫折すると思ってた)
趣味でもいかせないかなぁと、何か面白いことができないか模索中です。

主にGo言語での開発記事がメインとなるかと思います。
・Go言語のebitengine(興味があるので早く手を出したい。)
・GUIに定評がないけどGo言語でのGUI等(結構触りました。)
その他としては
・Macを使ったSwiftUI(まだ一人でアプリ作れるレベルではない)
・Unity等を使ったゲーム開発(まだ入り口)

何か面白い話があれば、
作れる範囲で挑戦していきたいと思ってます。
LTで失敗した話

# LTでの失敗と反省
新卒２週間目のエンジニアです。
今回は会社主催のLT枠で失敗してしまったのでその反省と戒めをこめて、少しここに残しておこうかなと思います。
今後は技術的なアウトプットとして記事を投稿していきたいです。

## 経緯
会社主催の勉強会に参加しようとした際に枠がないためLT枠で参加した。

## 失敗
技術、知識に乏しいため「何を」、「どのように」発表すればいいのかわからなかった。

## なぜそうなったのか？
勉強会やLTに初参加だったため、どういうものかを理解していなかったため資料などを準備していなかった。
発表したいことを発表する場という雰囲気だった。
勉強に選んだ題材もまとめにくいものだった。
行き当たりばったりすぎた。

## 初勉強会の感想
静かでもくもくと勉強できる環境だったので勉強ははかどりました。
また、いろいろな方のお話も聞け、交流関係が深まったり、知らない知識を知ることができるのはとても有意義だと感じました。


## 次回以降の勉強会（LT）に生かすこと
普段から技術に触れることで題材なども見つかると思うので触っていく。
勉強、業務で学んだことなどは常にアウトプットしていく。
準備をしっかりすること（資料作成、題材選び）。

### まとめ
毎月勉強会を行っているので次回も参加したいと考えていますが、もう一度雰囲気や流れをつかむために、一度LT枠ではない枠で参加して、6月の勉強会ではLT枠として参加したいと考えています。
【書評】systemdの思想と機能

# 読んだ本

https://gihyo.jp/book/2024/978-4-297-13893-6

# 概要

なんとなく触っているsystemdについて、概要から、具体的な仕組み、そして各機能について細かくまとまっていて全体像が把握できる本でした。
Linuxのかなり広い範囲がsystemdに支えられていることが知れ、普段意識せずに触っている場所についても裏側の動きがしれてとても興味深いです。

下記目次になります。

第1章　systemdとは
第2章　unitとunit file
第3章　unitの状態，unit間の依存関係，target unit
第4章　プロセス実行環境の用意
第5章　service unit
第6章　timer/path/socket unit
第7章　generatorとmount/automount/swap unit
第8章　control group，slice unit，scope unit
第9章　udev，device unit
第10章　systemd-journald
第11章　core dump管理
第12章　systemd-logind，pam_systemd
第13章　systemd-tmpfiles，systemd-sysusers
第14章　D-Busとpolkit
第15章　systemd-resolved
第16章　systemdのその他の機能

# おすすめの人

- 普段Linuxを触っているが、なんとなくsystemdに触れている人

# 次に読むなら

- 個人的に、D-Bus周りが気になったのと、普段遣いレベルでのsystemd-resolvedの用途がよくわからなかったので深堀りしてみたいです

# 感想

systemdはservice周りでしか使ったことがなく、そこについて詳しく知れたのが良かったです。
また、ログインなどユーザーセッションなどにも活用されていることを知り、思っていたより大きな機能だと知れたことで見え方が大きく変わりました。
設計思想も素晴らしく、こういう仕組みを作ってみたいなと思わせられました。
【PostgreSQL】「ERROR: Invalid digit, Value ' ', Pos 0, Type: Integer」の解消方法

# この記事を書く目的
- 掲題のエラーに遭遇した時の備忘のため
- 課題解決のステップを参考として

# 結論
## 原因
0または1が格納されているべきカラムがNULLであったため
## 対応方法
レコードの該当カラムを0で更新した
→ カラムのしようとして0または1であれば良いので1でもOK

# 経緯
データ分析ツールの一部機能を開発中にユニットテストを実施した際に掲題のエラーが発生しました。
エラー全文は以下の通り
```
SQLエラー [XX000]: ERROR: Invalid digit, Value ' ', Pos 0, Type: Integer
  詳細:
  -----------------------------------------------
  error:  Invalid digit, Value ' ', Pos 0, Type: Integer
  code:      1207
  context:  
  query:     37551053
  location:  :0
  process:   query0_125_37551053 [pid=0]
  -----------------------------------------------
  ```

  # 原因考察のプロセス
  - 前日の開発中にSQLを実行した際は特に問題なく実行完了した
  - エラーメッセージで調べたがRedshiftのこと（関係なさそうなページ）ばかり
      - 経験則による直感だがググって出てきたことは解決に結びつかなさそうな気がした
  - エラーの内容的に数値が来てほしいところに空文字が来てそう
      - 例外処理が抜けている？
          - 確かに例外処理は抜けていた
          - NULLとか空文字だったらゼロとして処理しようかな
          - テーブル定義確認
              - 0か1どちらかは来るデータじゃん = 空文字とかNULLは来るはずがない
          - 例外処理を入れる必要はなさそう
              - あってもいいけど必要ではなさそうなので対応しないと判断
      - テーブル確認
          - 該当のカラムに何もデータ入ってないじゃん！
          - データ入れる、とりあえず0で
  - 再実行→解消！

# 今回は対応しなかったけど他に考えられる対応方法
- 該当カラムの型はInteger、けど0/1ならbooleanでも良いのでは？
    - カラムの型を変更するとか
        - 理由があってできなかった、理由は忘れた、確認しておこう


# さいごに
BI関連の開発をやっており、今後また遭遇しそうなエラーだと思ったので備忘のために書きました。

また、
『エラーが起こったらこんなふうに解決していくんだよ』的な思考のプロセスは言語化しておくと未来の自分のためにもなるかなと思ったこと、
「最近プログラミング始めました」みたいな人のためにもなればと思って書きました。

ご参考までに。
【Javascript】スプレッド構文

公式ドキュメント
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax

配列の要素を関数の引数に一気に渡したり、オブジェクトを作る時に既存のデータをそのままぶち込むことができる。

### 配列操作

#### スプレッド構文を使わずの配列結合

配列の結合を`concat`メソッドで行う例：

```javascript
const names = ["山田", "鈴木"];
const emails = ["yamada@example.com", "suzuki@example.com"];
const ages = [25, 30];

// 各情報の配列をconcatメソッドで連結
const combinedInfo = names.concat(emails).concat(ages);
```
直感的でわかりやすいですが、複数の配列を結合する場合には、concatを繰り返し使用しなければならないから、冗長になりやすい。あとconcatメソッドは新しい配列を返すため、大量データを扱うにはパフォーマンス的に向いてなさそう。

#### スプレッド構文を使って結合

```javascript
const names = ["山田", "鈴木"];
const emails = ["yamada@example.com", "suzuki@example.com"];
const ages = [25, 30];
// スプレッド構文を使用して情報の配列を一つに結合
const combinedInfo = [...names, ...emails, ...ages];
```

# Webpackの設定で使う

Webpackで本番/開発環境などの複数環境のビルドプロセスや複数PJの管理をしたいといときにmodule.exportにまとめて渡さないといけないので複数環境やPJで分解して渡す際に使用した。以下は本番/開発環境で分けた例

```javascript
// 共通の設定
const commonConfig = {
  entry: './src/index.js',
  module: {
    rules: [{ test: /\.js$/, use: 'babel-loader' }]
  }
};

// 本番環境の設定
const productionConfig = {
  ...commonConfig,//スプレッド構文で共通の設定をコピー
  mode: 'production',
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
  optimization: {
    minimize: true
  }
};

// 開発環境の設定
const developmentConfig = {
  ...commonConfig,//スプレッド構文で共通の設定をコピー
  mode: 'development',
  devtool: 'source-map',
  plugins: [
    ...commonConfig.plugins,
    new webpack.HotModuleReplacementPlugin()
  ]
};

module.exports = (env) => {
  if (env.production) {
    return productionConfig;
  } else if (env.development) {
    return developmentConfig;
  } else {
    return commonConfig;
  }
};

```
スプレッド構文を使わないと、毎回entryやmodule用意してentry: commonConfig.entryという感じで冗長してしまうが、...commonConfigで書かなくてもよくなった。少しは可読性が上がった、と思う。
【WSL】PDF結合をWSLで1コマンドで行う

# はじめに
何かと面倒なPDFファイルの編集。
ネットで検索するとAdobeの公式サイトほか、様々なサイトが出てくる。
しかし、Adobeは無料会員ではできることが限られているし、ほかのサイトにはプライベートな情報が載ったPDFをアップロードするのは怖い。
色々試した結果、WindowsではWSLにパッケージをインストールしてPDFの結合を行うのが一番手っ取り早い方法だったので、Adobeとの比較もしつつ方法を書いておく。

# Adobe Acrobat オンラインツール
 「Windows PDF 編集」などと検索するとはじめに行き着くサイト。
 https://www.adobe.com/jp/acrobat/online.html
 
 PDFの結合をはじめとして、WordファイルのPDF化やページ順序入れ替えなど、欲しい機能は基本的にすべてそろっている。...ように見えるが、実は有料会員登録しないと使えない機能がほとんど😥
 
 特にPDF結合に関しては、自分が試したところ、
 - 1回目：会員登録なしでできる
 - 2回目：無料会員としてのアカウント登録が必要
 - 3回目：有料会員登録が必要
 
 のようになっているようだった。

 有料会員になれば便利な機能が使い放題になるようだが、使用頻度の低いサブスクはなるべく増やしたくないところ。

# WSL上でpdfuniteコマンドを導入
※WSLって何？という方は、https://learn.microsoft.com/ja-jp/windows/wsl/faq のページなどがわかりやすいと思います。

さすがUbuntu。UbuntuにはPDFファイルを結合する`pdfunite`という夢のコマンドがある。デフォルトでは入っていないので、以下コマンドでパッケージをインストールする。

```shell-session
sudo apt install poppler-utils
```
この時点で、`pdfunite`コマンドが実行可能になる。

# pdfunite の実行
あとは実行するだけ。「Ubuntuのコマンドだから、Ubuntu上のファイルしか結合できないのでは？面倒くさそう😓」と思った方がいるかもしれないが、Ubuntu のターミナルからWindowsのファイルのアクセスは、ファイルパスの頭に `/mnt/c/`と付けるだけでUbuntu内のファイルと同様に扱うことができる。
結合したいPDFファイルがあるディレクトリにまとまっているなら、`cd`でそのディレクトリに移動しておくとコマンド作りが楽。

```shell-session
# windows 内の PDF が入ったディレクトリに移動。適宜変えてください。
cd /mnt/c/Users/user/Documents/
# pdfunite を実行
pdfunite front_cover.pdf contents.pdf end_cover.pdf output.pdf
```

pdfunite コマンドでは、結合したいファイルを列挙したあと、作成したいファイル名を最後に書きます。

# より発展的な操作
今回書いた `pdfunite` コマンドは結合の専用のコマンドだが、抽出や回転などさらに発展的なことを行いたい場合は `pdftk` コマンドをインストールすると実現できるらしい。
https://qiita.com/masashi_mizuno_chestnut/items/14c0b877bed7fee0877b

引数が少し難しそうだったので、結合しかしない場合は `pdfunite`で十分そう。
ABC349をPythonで（A～E）

AtCoder Beginner Contest 349の解答等のまとめ

https://atcoder.jp/contests/abc349

# A問題
Aの総和の正負を反転させたものが正解
```python:A
input()
print(-sum(map(int, input().split())))
```
# B問題
1. 各文字の使用個数を計算
1. 使用個数の個数を計算
1. 条件に適合するか調べる
```python:B
d = dict()
for s_i in input():
    if s_i not in d:
        d[s_i] = 0
    d[s_i] += 1

count = [0] * 110
for val in d.values():
    count[val] += 1

print("Yes" if all(c_i in {0, 2} for c_i in count) else "No")
```
# C問題
Tと同じ文字がSにあるか最初から確かめる
3文字使用されているか２文字使用かつ最後が$x$ならYes
```python:C
s = input()
t = input().lower()

flag = 0
i = 0
for s_i in s:
    if s_i == t[i]:
        i += 1
    if i >= 3:
        break

print("Yes" if i >= 3 or i == 2 and t[-1] == "x" else "No")
```
# D問題
$l$のビットを小さいほうから見て、立っているかつそれを切り上げても$r$以下なら切り上げる。超えたら打ち切り
その後、$r$を超えないように上から値を追加して$r$に収束させる
```python:D
l, r = map(int, input().split())

ans = []
now = l
for _ in range(200):
    for i in range(61):
        if now >> i & 1:
            nxt = now + 2 ** i
            if nxt <= r:
                ans.append([now, nxt])
                now = nxt
            else:
                break

for i in range(60, -1, -1):
    if r >> i & 1 and not (now >> i & 1):
        ans.append([now, now + 2 ** i])
        now += 2 ** i

print(len(ans))
for a_i in ans:
    print(*a_i)
```
# E問題
マルバツゲームを解く
全マス埋まったらその盤面のスコアを計算して判定する

たぶんどこかにあるマルバツゲームのコードをコピペしたら早かったと思う
```python:E
from functools import lru_cache

a = [list(map(int, input().split())) for _ in range(3)]
lst = [[(1, 2), (3, 6), (4, 8)],
       [(0, 2), (4, 7)],
       [(0, 1), (5, 8), (4, 6)],
       [(4, 5), (1, 7)],
       [(3, 5), (1, 7), (0, 8), (2, 6)],
       [(3, 4), (2, 8)],
       [(7, 8), (0, 3), (2, 4)],
       [(6, 8), (1, 4)],
       [(6, 7), (2, 5), (0, 4)]]


@lru_cache(maxsize=None)
def three(P):
    p = []
    for _ in range(9):
        p.append(P % 3)
        P //= 3

    for i, j, k in [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]:
        if p[i] == p[j] == p[k] != 0:
            return p[i], p
    return 0, p


@lru_cache(maxsize=None)
def dfs(is_first=True, P=0):
    # その盤面をもらった人が勝つか
    turn = 1 if is_first else 2
    x, p = three(P)
    # print(is_first, x, p, P)
    if x != 0:  # 並んでいるところがあったら、もらった人は負け
        return False

    if 0 not in p:  # 最終盤面
        f, s = 0, 0
        for i in range(3):
            for j in range(3):
                if p[i * 3 + j] == 1:
                    f += a[i][j]
                elif p[i * 3 + j] == 2:
                    s += a[i][j]
        # print(f, s)
        return s > f

    else:
        lst_2 = []
        for i in range(9):
            if p[i] > 0:
                continue
            for l_i in lst[i]:
                if p[l_i[0]] == p[l_i[1]] and ((is_first and p[l_i[0]] == 1) or (not is_first and p[l_i[0]] == 2)):
                    return True

            lst_2.append(i)

        for i in lst_2:
            f = dfs(is_first ^ True, P + (3 ** i * turn))
            if not f:
                return True

    return False


flag = dfs()

print("Takahashi" if flag else "Aoki")
```
Condaでgfortranの仮想環境の構築

Condaを用いてgfortranとnetcdf-fortranが使える仮想環境を簡単に構築できます．aptが使えない（superuserになれない）スパコンでも有効です．ただし，東大Wisteria-Oではログインノードでのコンパイル実行はできましたが，interactive-nodeでの実行はできませんでした．そもそもinteractive-nodeではcondaコマンドが動きませんでした．
conda-forge channelを採用します．
WSL2 Ubuntu 22.04と東京大学情報基盤センターWisteria-Oで検証済みです．

```bash
conda create -n gfortran -c conda-forge cmake fortran-compiler
conda activate gfortran
conda install -c conda-forge libnetcdf netcdf-fortran
```

インストールされたパッケージを確認します．
```bash
conda list
```
特定のパッケージを確認します．
```bash
$ conda list netcdf-fortran
# packages in environment at /work/g***/******/miniconda3/envs/fabm-gfortran:
#
# Name                    Version                   Build  Channel
netcdf-fortran            4.6.1           nompi_hacb5139_103    conda-forge

```

ベンダーによってgfortranがインストールされている場合でも，仮想環境内では上記でインストールしたものが使えます．ログイン環境および仮想環境において，`gfortran --version` を実行すると，バージョンがそれぞれ異なることを確認できます．

## パッケージの探し方

conda-forgeにパッケージが存在するか，探す方法です．

### bashターミナルの場合
```bash
conda search -c conda-forge <パッケージ名>
# netcdfを含むパッケージを探す場合
conda search -c conda-forge netcdf
```

### WEBの場合
ブラウザで[Anaconda cloud](https://anaconda.org/)にアクセスします．
Search Packagesの検索窓で検索します．このとき，パッケージ名だけでなく，type（channel名）とPlatformを指定すると絞り込めます．
```
type:conda platform:linux-64 netcdf
```

## 特定のビルドを指定してインストール

netcdf-fortranにはバージョンの違いやmpiかnompiかによって多くのビルドが存在します．特に指定しない場合は最新のもので依存関係を自動的に判断してインストールされます．
特定のビルドを指定してインストールすることもできます．バージョン4.6.1かつopenmpiのnetcdf-fortranをインストールする場合です．

```bash
conda install -c conda-forge netcdf-fortran=4.6.1=mpi_openmpi_*
```
あるいはmpi_openmpiだけを指定して，最新版をインストールできます．
```bash
conda install -c conda-forge netcdf-fortran=*mpi_openmpi*
```
BOMモジュールを作成する方法

複数のモジュールを持つMavenライブラリではBOM（bill of materials）を提供するものも多くなってきました。
例えばFirebaseの場合、以下のように使います。

```kotlin
implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
implementation("com.google.firebase:firebase-auth")
implementation("com.google.firebase:firebase-firestore")
```

BOMをplatformで指定しておくと、ライブラリごとのバージョンを個別で指定する必要がなくなり、複数のモジュールに分かれたライブラリでバージョンを統一することができます。特に、モジュールごとにバージョンが同一でない場合、バージョンの組み合わせを管理できて便利です。

複数のモジュールを持つライブラリを作成する場合は、BOMも提供することを検討すると良いでしょう。
BOMモジュールを作成する方法は簡単で以下のように作ります。

# BOMモジュールを作成する

前提として複数のモジュールを持つライブラリなので、すでにマルチモジュールの構成ができていると思います。
追加でBOMのためのモジュールを作成します。ルートプロジェクト直下にモジュールディレクトリを作成し、`build.gradle.kts`ファイルを作成します。

そして、`setting.gradle.kts`にモジュールを追加します。

```setting.gradle.kts
include(":hoge-bom")
```

`build.gradle.kts`は以下のようになります。

```hoge-bom/build.gradle.kts
plugins {
    id("org.gradle.java-platform")
    id("org.gradle.maven-publish")
}

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            from(components["javaPlatform"]) // javaPlatformの構成を指定

            // publishに必要な設定諸々
            groupId = "com.example.hoge"
            artifactId = "hoge-bom"
            version = "1.0.0"
        }
    }
}

dependencies {
    constraints {
        // BOMに掲載するモジュールを列挙する
        api(project(":core"))
        api(project(":api"))
    }
}
```

maven-publishに関する設定は通常のモジュールとほぼ同じです。これに関する解説は省略、最低限publishToMavenLocalが動く記述にしているので適宜補完してください。

BOMを作成するためには`java-platform`プラグインを使います。
そして、dependencies.constraintsの中に掲載するモジュールを列挙するだけです。
これでpublishするとBOMが作成されます。

ついでに、buildディレクトリは作成されるので、必要に応じて.gitignoreも追加します。

```hoge-bom/.gitignore
/build
```

## BOM掲載モジュールを自動で設定する

単に列挙するだけなので、一度書いてしまえばよいし、その後モジュールが増減したら都度追加削除すれば良いことではあります。しかし、追加を忘れていてもその時点でビルドエラーなどになるわけではないので、忘れたままpublishしてしまって〜ということも起こってしまいそうですね。
なので、何を掲載するかも自動化してしまいましょう。

以下のように記述すると、`"org.gradle.maven-publish"`プラグインを使っている=ライブラリとして公開するモジュールを自動的に追加することができます。
チョットしたハックですね。

```build.gradle.kts
dependencies {
    val thisProject = project
    constraints {
        rootProject.subprojects {
            if (this@subprojects != thisProject) {
                plugins.withId("org.gradle.maven-publish") {
                    api(this@subprojects)
                }
            }
        }
    }
}
```

Gradle Version Catalogを使っている場合はpublishプラグインのIDもそこから取るのが良いですね。build-logicでまとめたpublishプラグインを使っているものという条件で追加しても良いでしょう。

```build.gradle.kts
dependencies {
    val thisProject = project
    val publishPluginId = libs.plugins.build.logic.mavenPublish.get().pluginId
    constraints {
        rootProject.subprojects {
            if (this@subprojects != thisProject) {
                plugins.withId(publishPluginId) {
                    api(this@subprojects)
                }
            }
        }
    }
}
```

retrofitのbomでこの手法が使われていて、Jakeが「Very nice!」ってコメントしてますね。

https://github.com/square/retrofit/pull/4022

以上です。
Cisco AnyConnectでVPN接続するとwsl2がsshで外部サーバーにつながらない問題の解決策(Windows)

# 問題・エラー
Cisco AnyConnectでVPN接続して、Windowsでwsl2からsshで外部サーバーにアクセスすると
Temporary failure in name resolutionなどと、名前解決エラーが出てアクセスできない問題

# 解決策 (ここではwsl2はUbuntuを例とする)
### VPN接続した状態で操作1と2をPower shellで(管理者として)実行する

## [操作1] Cisco Anyconectの優先度を6000に変更
#### →値を十分に大きく(6000)にすることで、接続の優先度を落とす
``` shell: Windows Power Shell (管理者権限つき)
Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000
```

## [操作2] resov.confに、DNSアドレスを書き込む
```　shell: Windows Power Shell (管理者権限つき)　(Ubuntuの場合)
Get-DnsClientServerAddress -AddressFamily ipv4 | Select-Object -ExpandProperty ServerAddresses | % { "nameserver " + $_ } | wsl -d Ubuntu --user root -- tee /etc/resolv.conf
```

### ※Ubuntu 22.04.3 LTSの場合は[操作2]を、以下に変えて実行する
(つまり、wsl -d と --userの間を、使用するwsl2のものに適宜変更すればよい。)

```　shell: Windows Power Shell (管理者権限つき)　(Ubuntu 22.04.3 LTSの場合)
Get-DnsClientServerAddress -AddressFamily ipv4 | Select-Object -ExpandProperty ServerAddresses | % { "nameserver " + $_ } | wsl -d Ubuntu-22.04 --user root -- tee /etc/resolv.conf
```

# 問題の原因 (詳細は、参考文献[3]を参照)
外部サーバーにアクセスする際、wsl2がホストに接続先外部サーバーのIPアドレスの問い合わせを行うが、
Cisco AnyConnectが、ホスト→wsl2方向の経路を断ってしまうため、
問い合わせの返信がwsl2に届かず、wsl2側が名前解決(Name resolution)できなくなり、
その結果、名前解決エラー(Temporary failure in name resolution)が発生しているらしい。

# 本解決策の位置づけ＆他のアプローチ
### 主なアプローチは2つ。
#### 1. 手軽なアプローチ(ただし、接続先を複数切り替えたい場合は破綻する、暫定的対応)
wsl2側がIPアドレスをあらかじめ参照できるようにresolv.confに格納し (→本手法[操作2])、
かつ、
VPN側に接続が行かないように、Cisco AnyConnect側のインターフェースメトリックス値を6000にすることで、接続優先度を下げる (→本手法[操作1])

なお、本記事で紹介している方法は、参考文献[1]の方法とほぼ同じであるが、
より動きやすいように修正及び補足説明を加えたものである。

#### 2.少し複雑なアプローチ(接続先を複数切り替えたい場合でも対応できる、恒久的対応)
wsl-vpnkitを導入することで、wsl2側がホストとやり取りできる道を構築する
→基本的には参考文献[2]のサイト参照

ただし、ゲストOS側の2の2行目のコマンド：
```shell: wsl2(Ubuntuなど)側
sudo cp ./wsl-vpnkit.service /etc/systemd/system/
```
の部分は、
```shell: wsl2(Ubuntuなど)側
sudo cp /etc/systemd/system/wsl-vpnkit.service .
```
に変更する必要がある(でないと私の環境では動かなかった。)

本記事では1のアプローチを詳細に取り上げたが、
接続先サーバーが複数ある場合などは、複雑ではあるものの、
基本的には2(wsl-vpnkitを用いる方法)のアプローチをとることを推奨する。

# 参考文献(2024年4月13日時点、すべて閲覧可能)
[1. 本手法の元] https://zenn.dev/dozo/articles/21630720e6476b
[2. 少し複雑な別のアプローチ] https://zenn.dev/xeres/articles/2023-10-05-install-wsl-vpnkit
[3. 問題の原因の詳細説明など] https://aquasoftware.net/blog/?p=1472
Unity Packageインストール後にUnity Editorを再起動するスクリプト

Unityパッケージをインストール後にUnity Editorを自動再起動するためのクラスです。開発したUnity PackageのEditorディレクトリ以下に設置してください。

パッケージのインストール後やアップデート後に再起動プロンプトが表示されます。一度実行された後にパッケージバージョンを`EditorPrefs.SetString`で記録し、バージョンアップされない限り再実行されないようにしています。

`RestartUnityEditorAfterPackageInstallation.cs`
```cs
using System.Linq;
using UnityEditor;
using UnityEditor.PackageManager;

/// <summary>
/// Restart Unity Editor after package installation
/// </summary>
class RestartUnityEditorAfterPackageInstallation
{
    [InitializeOnLoadMethod]
    static void CheckNeedRestart()
    {
        // Get the infomation of the package of this script 
        var MyPackageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.Assembly);
        string MyPackageName = MyPackageInfo.name;
        string MyPackageVersion = GetPackageVersion(MyPackageName);

        if (EditorUserSettings.GetConfigValue("VersionOf_" + MyPackageName) != MyPackageVersion)
        {
            EditorUserSettings.SetConfigValue("VersionOf_" + MyPackageName, MyPackageVersion);
            if (EditorUtility.DisplayDialog("Restart Unity",
                "You need to restart Unity to apply the new changes. Restart now?",
                "Restart", "Later"))
            {
                // Restart Unity Editor
                EditorApplication.OpenProject(System.Environment.CurrentDirectory);
            }
            else
            {
                // Inform the user to restart Unity manually
                EditorUtility.DisplayDialog("Manual Restart Required",
                    "Please close and reopen Unity to complete the update.",
                    "OK");
            }
        }
    }

    /// <summary>
    /// Get the version of the package
    /// </summary>
    /// <param name="packageName"></param>
    /// <returns></returns>
    private static string GetPackageVersion(string packageName)
    {
        var request = Client.List(true, true);
        while (!request.IsCompleted) { }
        return request.Result.FirstOrDefault(package => package.name == packageName)?.version;
    }
}
```
ReactとLocalStorage保存

# 目録
- [1. 問題の概要](#問題の概要)
- [2. 問題の原因](#問題の原因)
- [3. 解決策](#解決策)
    - [3.1localStorage](##localStorage)
# 問題の概要

**問題**: Reactでページをリフレッシュするとデータが失われる。

# 問題の原因

1. **Reactの状態管理**: Reactはアプリケーションの状態をメモリ内に一時的に保持します。具体的には、JavaScriptの実行環境のヒープに状態が保存されています。
   
2. **JavaScript環境のリセット**: ページリフレッシュ時にブラウザは新しいJavaScript実行環境を作成し、既存のすべてのデータをクリアします。

3. **コードの再実行と状態の初期化**: リフレッシュにより、Reactコンポーネントが初期状態から再度レンダリングされます。これにより、ユーザーのインタラクションやネットワークからの応答による状態の更新が失われます。

# 解決策

データの永続性を確保するためには、クライアントサイドに永続的なストレージソリューションを使用する必要があります。主な方法は以下のとおりです：

## localStorage

### 1. **localStorageとは何ですか？**
`localStorage`はWebストレージ技術の一種で、ウェブサイトがユーザーのブラウザ上でデータを保存することを可能にします。このデータはタブやブラウザを閉じた後も保持されます。従来のcookieと異なり、localStorageはより直接的なデータアクセス方法を提供し、サーバーにデータを送信しないため、より大量のデータを保存するのに適しています。

### 2. **localStorage、sessionStorage、およびcookiesの違いは何ですか？**
- **localStorage**：データは永続的に保存され、有効期限がありません。ユーザーがブラウザのキャッシュをクリアすると削除されます。
- **sessionStorage**：データは単一のセッションでのみ保存され、タブやブラウザを閉じるとデータはクリアされます。
- **Cookies**：データはサーバーとクライアント間で送受信され、有効期限を設定できます。HTTPリクエストごとにcookieが送信されるため、サーバーが読み取る必要がある小さなデータに適しています。

### 3. **localStorageの容量制限はどのくらいですか？**
ブラウザによってlocalStorageの容量制限は異なりますが、一般的には約5MBです。容量制限を超えたデータを保存しようとすると、ブラウザは`QuotaExceededError`エラーを投げます。開発者はこの例外を処理し、アプリケーションのロバスト性を確保する必要があります。

### 4. **localStorageを使用してデータを保存および取得する方法は？**
JavaScriptでlocalStorageを操作するのは非常に簡単です。以下の例を参照してください：
```javascript
// データを保存
localStorage.setItem('key', 'value');

// データを取得
var value = localStorage.getItem('key');

// データを変更
localStorage.setItem('key', 'new value');

// データを削除
localStorage.removeItem('key');

// 全てのデータをクリア
localStorage.clear();
```

### 5. **localStorageにどのようなタイプのデータを保存できますか？**
localStorageは本質的に文字列型のデータのみをサポートしています。オブジェクト、配列、その他の非文字列型のデータを保存する必要がある場合は、`JSON.stringify()`を使用してデータをJSON文字列形式にシリアライズし、`JSON.parse()`を使用してこれらのデータを解析できます。

### 6. **localStorageのデータセキュリティはどのようなものですか？**
localStorageはデータの暗号化を提供していませんので、保存されたデータは悪意のあるスクリプトによって容易にアクセスされる可能性があります。特にクロスサイトスクリプティング（XSS）攻撃の状況下ではなおさらです。セキュリティを向上させるために、開発者は機密情報の保存を避け、XSSのリスクを限定する措置を取るべきです。

### 7. **localStorageの実際の使用シナリオは何ですか？**
localStorageは、ユーザーの設定（インターフェースのテーマなど）、ショッピングカートの内容、ゲームスコア、アプリの状

態などを保存するのに一般的に使用されます。これにより、データはセッションを超えて保持され、ユーザーエクスペリエンスとアプリのパフォーマンスが向上します。

### 8. **異なるタブやウィンドウ間でlocalStorageのデータを同期する方法は？**
localStorageのデータは同一ブラウザの異なるタブやウィンドウ間で自動的に共有されます。データのリアルタイム同期を実現するために、`window.addEventListener('storage', function(event) { ... })`を利用してlocalStorageの変更イベントを監視し、あるタブでデータが変更された場合、他のタブがそれに応じてデータを更新できるようにします。
RailsにおけるRSpecテストコードで生成されたデータがデータベースに保存されない仕組み

### RailsでRSpecなどのテストコードを実行すると、テストコード内で生成されたデータは通常、データベースに保存されません。これは、テストコードと本番環境を分離し、テストデータが本番データに混入することを防ぐためです。

# 仕組み

RSpecなどのテストフレームワークは、テストコードを実行する前に、以下の2つの重要な処理を行います。

1\. トランザクションの開始: テストコードの実行前に、データベースへのトランザクションを開始します。
2\. トランザクションのロールバック: テストコードの実行後に、トランザクションをロールバックします。

トランザクションのロールバックにより、テストコード内で生成されたすべてのデータ変更はデータベースにコミットされず、本番環境に影響を与えることはありません。

# 例外

一部のテストシナリオでは、テストデータをデータベースに保存する必要がある場合があります。そのような場合は、以下の方法で実現できます。

save! メソッドを使用する: モデルオブジェクトを保存する際に save! メソッドを使用すると、トランザクションのロールバック前にコミットされます。

DatabaseCleaner gemを使用する: DatabaseCleaner gemは、テストコード実行前にデータベースの状態をスナップショットし、テスト終了後に元の状態に戻す機能を提供します。

# テストデータと本番データの分離

テストデータと本番データを分離することは、テストの信頼性を高め、本番環境への影響を防ぐために重要です。RSpecなどのテストフレームワークが提供するトランザクション機能を活用することで、効率的にテストデータと本番データを分離することができます。
c言語のヘッダファイルはなぜコンパイル時にソースファイルと一緒にコンパイルしなくても大丈夫なのか

piscine中に疑問に思ったことがありました。
コンパイルするとき
    cc -Wall -Wextra -Wall main.c option.c additional.c ... 
というようにソースファイルを連ねていくと思うのですが、そのソースファイルに例えばheadder.hという自作のヘッダーファイルをインクルードしていたときにそれも入れなくていいのか？という話です。

最初は名前が同じだから勝手に機械が取り込んでいる（main.cという名前のソースファイルだと大抵main.hというヘッダーファイル名をつける）のかと思っていましたが、どうもそうではないらしい。そうこうしているうちにpiscine中は休む間もなく疑問が生じていき（そしてそれを逐一全部考えようとすると終わる）、この疑問もその一つになっていました。

そして3月のpiscineが終わり、入学式までの約2週間の間piscine中に生じたc言語の疑問・謎のアレコレの整理をしよう！ということになりました。

### Q. なぜヘッダファイルはなぜコンパイル時にソースファイルと一緒にコンパイルしなくても大丈夫なのか
### A. #include "" でダブルクオーテーションで囲まれた部分のファイル名を探してそれを取り込むから

printfを使用するときに取り込むstdio.h, writeを用いるときのunistd.hなど標準ヘッダファイルと呼ばれるものを取り込む場合は<>で囲みますが、自作のヘッダファイルは""で囲みます。
そうすると、そのソースファイルがある位置を起点として所定の場所におかれたヘッダファイルを取り込めます。
例えば、main.cにheader.hというヘッダーファイルをインクルードしたいとして、main.cとheader.hが同じディレクトリ内にあるなら
~~~c
#include "header.h"
~~~
違うディレクトリなら以下のように
例1：main.cと同じディレクトリにあるincludesというディレクトリの中に場合↓
~~~c
#include "includes/header.h"
~~~
例2：main.cの一つ上のディレクトリと同じ系列のincludesというディレクトリの中に場合↓
~~~c
#include "../includes/header.h"
~~~

そしてこのincludeなる特別な処理をしているのが**プリプロセッサ**なるもので、プリプロセッサ後のソースファイルをコンパイル(翻訳)してリンカ(結合)してプログラムが生成される、という流れです。
※この[資料](http://www.ed.u-tokai.ac.jp/takakura/jp/lecture/lecture_NOKO/cp2/L52print.pdf)の最初のページの図が分かりやすい
(piscine中の人へ：ライブラリやらオブジェクトファイルやらの話は後半のMakefileの課題で出てきます)

そういえば初めてヘッダファイルなるものを知ったのは始めのチーム課題（rush00）だったな。
あのときは一緒にコンパイルしなくていいファイルがあるのか、ていうちょっとした驚きだった。

以上！
(Mac) csvをBOMつきに変換

BOMなしcsvだとExcelで文字化けが起こります。

これをコマンド叩いて、すぐ変換してあげましょう。

## 準備

 nkfコマンドをインストール

```
 brew install nkf
```

## 対応

 文字化けしているファイル名をhoge.csvとします。以下を叩けばBOMつきになります。

```
 nkf --overwrite --oc=UTF-8-BOM hoge.csv
```

 
## 確認

実際開いても文字化けしないので確認できますが、コマンドで確認するには以下で　UTF-8 (BOM) (LF) となれば良い。


 ```
 nkf --guess hoge.csv
```
1週間の習慣をサポートするアプリ「シュウカン」をリリースしました



こんにちは！趣味で個人開発をしているりょうやです。
習慣を管理するアプリをリリースしました。

https://apps.apple.com/us/app/%E3%82%B7%E3%83%A5%E3%82%A6%E3%82%AB%E3%83%B3-%E7%BF%92%E6%85%A3%E6%94%AF%E6%8F%B4%E3%82%A2%E3%83%97%E3%83%AA/id6480456838

## アプリ概要

このアプリ「シュウカン」は、1週間の習慣をサポートするアプリになります。「本を１冊読む」「ジムに3回行く」など1週間の中で行う習慣について記録を付けることができます。また、習慣を達成すると獲得できる「ご褒美ポイント」を設定することができ、ポイントによって自分にご褒美を与えてモチベーションを継続させます。

## アプリの機能

### 習慣管理機能

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/4f3525c4-420b-f61d-09bc-5e56c47f9523.png)

習慣を設定、進捗管理などをすることができる画面です。1週間経つと習慣毎の進捗はリセットされます。

### ご褒美機能

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/0c9793e3-8309-bb6b-0ba0-9c6622fdaeaf.png)

自分へのご褒美を設定することができます。習慣を達成して獲得できるご褒美ポイントでモチベーションを継続しましょう。

## 最後に

大きな目標を達成するには日頃の習慣が大切になってきます。このアプリを使って1人でも多くの方の人生が充実するものになればと思います。
NanoPi + Armbian

良質な記事がたくさんあるので、自分用のメモ

参考：
https://www.mikan-tech.net/entry/nanopi-neo-setup

# 0. 環境

Windows11 PC

NanoPi Neo https://www.amazon.co.jp/gp/product/B0CJBVP5K9
※ 上記リンクは、メーカーがDovhmohとなっていますが、FriendlyElecとの違いが何なのかは不明


# 1. MicroSDカードを用意

もちろん、MicroSDカードリーダーも必要

# 2. イメージをダウンロード

https://www.armbian.com/nanopi-neo/

CLIの方をダウンロード
2024年4月13日時点で、Armbian Jammy が最新。

# 3. 書き込み

私は、Raspberry Pi Imagerを使いました

# 4. 有線LANでつなぐ

初期設定で、DHCPでつながります。ルーターで、IPを探すが、

ssh@nanopineo

とすればつながります。

# 5. 初期設定

初回起動時にパスワードなどの初期設定されます。

# 6. とりあえず、apt update && apt upgrade
前置・後置インクリメント





```Java
    public static void main(String[] args) {
        int num = 0;
        System.out.println(numB++); //後置:0と表示
        System.out.println(++numB); //前置:2と表示
    }
```

上記で0、2と出力される理由は、
インクリメントのタイミングが処理の「前」OR「後」というように異なるから。

##
▼後置

```Java
        int num = 0;

        System.out.println(num); //まず処理(＝出力)してから
        num++; //num = num + 1;  
```
つまり、
①表示(＝処理)としてはnumの初期値「0」が出力。
②そのあとに内部的にnumがインクリメントして「1」になる。表示は「0」のまま。

##
▼前置
```Java
       //※上記、後置の処理に続けているため、numは「1」の状態
       num++; //num = num + 1;
       System.out.println(num);
```
つまり、
①内部的にnumにインクリメントして「1+1＝2」になる。
②そのあとに表示(＝処理)として、代入された最新のnumの情報「2」が出る。
ESATA-SATAケーブル

ARecX6にはESATAのコネクタがあるので、ESATA-SATA変換ケーブルを使ってHDDを接続してみました。ケーブルはAmazonで560円でした。

![IMG_20240413_131616.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/cf9f52a2-5aeb-fd2c-7a58-7e812aef3788.jpeg)

3.5インチHDDは5V,12Vが必要で、ヨックモックの六本木ヒルズ箱に電源が入っています。NetBSDではwd0でHDDが見えます。2.5インチのHDDやSDDは5Vだけで大丈夫です。

https://dmesgd.nycbug.org/index.cgi?do=view&id=7671

このネタ[すでに書いていて](https://qiita.com/yamori813/items/ee07c90b6026755d44cd
)、電源をケースに入れたので新しく書きました。

![IMG_20240413_092801-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/0a23194c-1ab8-8c6f-ae3c-e28beb411a00.jpeg)

この電源は昔MACで使っていたSCSIドライブのもので、ドライブは調子悪くなって捨ててしまったのですが、電源は何かに使えると思ってとってありました。

ちょっとケーブルは長すぎるので、巻いてみました。
【UML】UMTP認定試験 L2 受験レポート

## この記事について

筆者が先日受験したUMTP認定試験 L2について、受験した経緯や受験に向けての学習、受験当日の様子などをまとめています。
UMLに興味がある人、UMTP認定試験 L2の受験を考えている人の参考になれば幸いです。

L1試験についての記事はこちら。

https://qiita.com/blue32a/items/c93f14cc3853a4ed4c40

## UMTP認定試験とは

UMTP認定試験とは、UMLモデリング推進協議会（UMTP）によって運営されるUMLモデリングスキルの認定試験です。現在はL1からL4までの4レベルに分類されており、今回私が受験したのはモデリングスキルレベル「UMLモデルの読み書きが普通にできる」が問われるL2です。[^L2]

[^L2]:https://umtp-japan.org/about_exam/exam_gaiyo/l2

## 受験した経緯

ソフトウェア設計やドメインモデリングに関心があり、設計活動やコミュニケーション活用するためUMLについて学習しています。最近はこの認定試験を軸に学習を進めていて、先日はL1に合格したので、次のL2にも挑戦することにしました。

## 受験に向けた学習

『徹底攻略UML モデリング技能認定試験問題集 L2 対応』
主にこちらの問題集の問題を解きつつ、不明点を深堀りしていく形で進めていきました。こちら初版が2008年なので、もしかしたら出題傾向などに変更があるのかもしれません。ただ実際に受験して困るようなことはありませんでした。

https://book.impress.co.jp/books/2662

『【改訂版】UMLモデリング技能認定試験 ＜入門レベル（L1）＞問題集』
L1で使った問題集も活用しました。

https://gihyo.jp/book/2007/978-4-7741-3245-7

『UMLモデリングのエッセンス 第3版』
通読はしていませんが、こちらの書籍も読みました。筆者の経験なども踏まえた実践的な内容が主体なので試験向きではない内容（非標準）も含んでいますが、Unified Processについてなどは参考になりました。（最終的には業務UMLで活用するのが目的なので、引き続き読み進めたい書籍です）

https://www.shoeisha.co.jp/book/detail/9784798107950

## 受験の申し込み

L1同様にピアソンＶＵＥで受験しました。（ピアソンＶＵＥでの申し込みについてはL1受験レポートを参照してください [^L1REP]）

[^L1REP]:https://qiita.com/blue32a/items/c93f14cc3853a4ed4c40

### 受験方法の追加について

この記事を書いていて知ったのですが、どうやら2024年2月からインターネット環境があれでどこでも受験できるようになったみたいです。（半日かけて受験会場往復したのはなんだったのか・・・）

## 試験について

L1と同じくPCで受験する仕組みです。

L1との違いですが、L1は選択肢から適切・不適切を選択するような問題でしたが、L2では図や文中の複数の空欄に対して選択肢から適切なものを選んで埋める形式が多くなっています。詳しい採点方法は不明ですが、おそらくは全て正しい組み合わせに出来て加点されるのだと思います。また選択肢は複数回使用することもあるので、消去法に頼らず適切な要素を選択していく必要があります。そのため問題記述をよく読み、複数の図の間で整合性をとりつつ回答していくことが大切になります。

## 受験した感想など

結果は合格点65%に対して得点82%で、無事合格となりました。思ったよりも余裕を持って進められたので90%までいければよかったですが、ひとまず良い結果が出た形になります。

このまま次のL3を目指すかどうかは検討中ですが、業務で活用するために実践と学習を継続していきます。

## まとめ

今回UML学習の一環としてUMTP認定試験のL2を受験したので、その体験を記事として公開することにしました。L2受験を考えている人の参考になれば幸いです。
PythonによるK-Center Greedyアルゴリズムの実装

大規模データセットから効率的に代表的なサンプルを選択する手法として、「K-Center Greedy」アルゴリズムがあります。このアルゴリズムは、クラスタリングや異常検出、データの要約に有効です。今回は、このアルゴリズムをPythonで実装し、その使用方法を紹介します。

## 1. 必要なライブラリのインポート

```python
from sklearn.datasets import make_blobs
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import pairwise_distances
```
* sklearn.datasets: データ生成用のモジュール
* numpy: 数値計算を効率的に行う
* matplotlib.pyplot: データの視覚化
* sklearn.metrics: 距離計算用の関数

## KCenterGreedy クラスの定義
```python
class KCenterGreedy:
    def __init__(self, features):
        self.features = features
        self.distances = pairwise_distances(features, features)

    def select_batch(self, initial_idx=None, N=10):
        if initial_idx is None:
            initial_idx = np.random.randint(len(self.features))
        selected = [initial_idx]
        min_distances = self.distances[initial_idx].copy()

        while len(selected) < N:
            next_idx = np.argmax(min_distances)
            selected.append(next_idx)
            min_distances = np.minimum(min_distances, self.distances[next_idx])

        return np.array(selected)

```
このクラスは、特徴量データを受け取り、そのペアワイズ距離を計算します。select_batchメソッドでは、貪欲法を用いてデータポイントを選択していきます。

## 3. データの生成とアルゴリズムの適用

```python
X, _ = make_blobs(n_samples=3000, centers=100, n_features=30, random_state=42)
k_center_greedy = KCenterGreedy(X)
selected_indices = k_center_greedy.select_batch(N=300)
selected_samples = X[selected_indices]
```
make_blobs関数を使用して合成データを生成し、KCenterGreedyアルゴリズムを適用しています。

## 結果のプロット

```python
figure = plt.figure()
ax = figure.add_subplot()
ax.scatter(X[:,0], X[:,1], c="blue", alpha=0.5, label="Original Data")
ax.scatter(selected_samples[:,0], selected_samples[:,1], c="red", edgecolors="k", label="Selected Samples")
ax.set_xlabel("Feature 1")
ax.set_ylabel("Feature 2")
ax.grid(True)
plt.show()


```
生成されたデータと選択されたサンプルをプロットして、アルゴリズムの結果を視覚的に確認できます。

![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/e100120d-25cb-3d1f-c4fe-40e5d828373d.png)


## まとめ
K-Center Greedyアルゴリズムは、大規模なデータセットから重要な情報を抽出するのに有用な手法です。このブログ記事で紹介した実装を参考にして、自分のデータ解析プロジェクトに活用してみてください。
layoutファイルを削除したらエラーから抜け出せなくなった

ルートのlayout.tsxとは別に新規でlayout.tsxを作成し、不要になったため削除してローカル環境を立ち上げたところ、Module not foundエラーから抜け出せなくなってしまった。

キャッシュが残っているのだろうと判断してクリアするコマンドを叩いても変わらず。
参考サイト：https://qiita.com/gourmet-dev/items/f95105f76ed931711bd3
```npm cache clean --force```
(あとからnpmのキャッシュ消してもそりゃ変わらんよな...と気づく)

microsoft copirotに聞いたところ、以下のような返答があった。

> Next.jsでは、.nextフォルダ内の.cacheフォルダにキャッシュが保存されます。
layout.tsxを削除した場合でも、.nextはlayout.tsxがまだappディレクトリに存在すると考えます。そのため、.nextフォルダを削除することで問題が解決するはずです。

>具体的な手順は以下の通りです：
プロジェクトのルートディレクトリに移動します。
.nextフォルダを削除します。これにより、Next.jsのキャッシュがクリアされ、Module not foundエラーが解消されるはずです。ただし、この操作を行うとビルド時間が長くなる可能性がありますのでご注意ください。

試しに.nextフォルダを削除してnpm run devしたところ無事エラーが解消された。
Relational Database, レコードやテーブルの削除3コマンドについて整理

テーブルのレコード削除のコマンドは3種あります。
DELETE, DROP, TRUNCATE です。それぞれの用途について解説および整理します。

# DELETE
### 構文
> DELETE FROM *table_name* [WHERE CLAUSE]

## 説明
（条件を指定して）レコードを削除する
DML

# DROP
### 構文
> DROP TABLE *table_name*

## 説明
**テーブル自体を**削除する
DROP は TABLE 以外にも, DROP INDEX, DROP CONSTRAINT, DROP CLUSTER, DROP VIEW, DROP PROCEDURE, DROP FUNCTION, DROP PACKAGE, DROP TRIGGER, DROP SEQUENCE,DROP SYNONYM, DROP ALIAS, DROP USER, DROP LOGIN, DROP TYPE 等, DB の様々な要素の削除に使われるコマンドで、TABLE はその一部である
DDL

# TRUNCATE
### 構文
> TRUNCATE TABLE *table_name*

## 説明
テーブルの必ず全行を**高速に**削除する
DDL

#### 参考
技術評論社 SQLポケットリファレンス[改訂第4版] 朝井淳 著
しゃくとり法やSliding Windowの個人的な実装テンプレート

しゃくとり法やSliding Windowと呼ばれるアルゴリズムの実装テンプレートです。これを利用する問題にぶつかるたび、どう実装するか忘れてしまうので、自分用に残しておきます。実装方法にはいろいろ流儀があるようですが、個人的には以下の形式が好みです。

```
let mut right = 0;
for left in 0..n {
    while right < n && 【条件を満たすか? (ex. sum+a[right]<k)】{
        【rightを1進める (ex. sum+=a[right])】
        right += 1;
    }

    【この時点で[left, right)は条件を満たす最大になっているので、処理を行う】
    【ex. ret+=right-left】

    if left == right {
        right += 1;
    } else {
        【leftを1進めるための前処理 (ex. sum-=a[left])】
    }
}
```

**利用例: LeetCode 713. Subarray Product Less Than K**

https://leetcode.com/problems/subarray-product-less-than-k

積がk未満の部分配列の数を求める問題です。

```rust
impl Solution {
    pub fn num_subarray_product_less_than_k(nums: Vec<i32>, k: i32) -> i32 {
        let n = nums.len();
        let mut right = 0;
        let mut product = 1;
        let mut ret = 0;

        for left in 0..n {
            while right < n && product * nums[right] < k {
                product *= nums[right];
                right += 1;
            }

            ret += right - left;

            if left == right {
                right += 1;
            } else {
                product /= nums[left];
            }
        }
        return ret as i32;
    }
}
```