OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerで.NET webapi 環境構築


# 概要
以下の手順で環境構築できる
1. docker-compose.ymlを作成
2. コンテナを立ち上げる
3. webapiのプロジェクトを作成
4. 開発用サーバーの設定変更
5. 開発用サーバーの起動
6. 動作確認


# 1. docker-compose.ymlを作成
以下の内容のファイルを作成
```yaml
# docker-compose.yml

version: '3'

services:
  dotnet_webapi:
    tty: true
    image: mcr.microsoft.com/dotnet/sdk:6.0
    container_name: コンテナ名（任意）
    working_dir: /app
    volumes:
      - .:/app
    ports:
      - "8000:8000"
```

### Docker関連の解説
#### 1. Dockerイメージ
`mcr.microsoft.com/dotnet/sdk:6.0`
以下の.NETのレジストリを確認したところ、SDKをはじめ、.NETランタイムやASP.NET CoreのランタイムのDocker imageが用意されている
今回は、開発環境を構築したいため、.NET SDKのイメージを使用する

https://hub.docker.com/r/microsoft/dotnet


#### 2. ポート
webapiサーバーを起動するにあたり、8000番のポートを開放する
.NET webapiのデフォルトでは、ポートをランダムに使用する（7098番あたり）が、今回は、コンテナを使用するため、devServerのポートは8000番に固定する
8000番でなくてもローカルマシンの使用中ポートと重複していなければ、任意の値で良い

# 2. コンテナを立ち上げる
以下のコマンドを実行してコマンドでコンテナを立ち上げる
`docker-compose up --build -d`

# 3. webapiのプロジェクトを作成
コンテナが起動したら、以下のようなexecコマンドでコンテナにアタッチする
`docker exec <コンテナ名> -it bash`
アタッチできたら、以下のコマンドを実行してwebapiのプロジェクトを作成する
`dotnet new webapi -o <プロジェクト名>`
※ここで、`dotnet new -l`を実行することで、作成できるプロジェクトの種類を一覧表示できる
（"webapi"の部分を変更することでMVCや、Razor、React関連のプロジェクトも作成可能)

# 4. 開発用サーバーの設定変更
devServerのポート固定する
前述の通り、デフォルトだとランダムにポートを指定されるので今回は8000番に固定する
以下のようにファイルを書き換える
```json
/プロジェクト名/appsettings.Development.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "urls": "http://0.0.0.0:8000" <-ここを追記
}
```
【注意】ここで、プロトコルをhttp, ホストを0.0.0.0に設定する
プロトコルがhttpsの場合、証明書を信頼するためのコマンドの実行が必要になる
ホストをlocalhostに設定するとコンテナにリクエストを届けることができない


# 5. 開発用サーバーの起動
プロジェクトのディレクトリで以下のコマンドを実行
`dotnet run`
以下のような表示になればOK
```shell
root@7015f1354552:/app# dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://0.0.0.0:8000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app/
```
※ここで、`dotnet watch run`を実行すると、ホットリロードを利用できる

# 6. 動作確認
webブラウザで（ http://localhost:8000/WeatherForecast ）にアクセス
以下のような結果が返ってくれば起動成功
値はランダムなため、以下の結果と異なることもある
```json
[{"date":"2024-07-18T12:33:51.0448246+00:00","temperatureC":34,"temperatureF":93,"summary":"Balmy"},{"date":"2024-07-19T12:33:51.0457181+00:00","temperatureC":44,"temperatureF":111,"summary":"Mild"},{"date":"2024-07-20T12:33:51.0457207+00:00","temperatureC":2,"temperatureF":35,"summary":"Cool"},{"date":"2024-07-21T12:33:51.0457209+00:00","temperatureC":2,"temperatureF":35,"summary":"Sweltering"},{"date":"2024-07-22T12:33:51.045721+00:00","temperatureC":50,"temperatureF":121,"summary":"Mild"}]
```

良い.NETライフを！
学習記録

## 内部結合
### JOIN/INNER JOIN
両方のテーブルにあるデータのみを取り出す。


order_id | user_id | product
---------|---------|--------
1        | 1       | Laptop
2        | 2       | Smartphone
3        | 1       | Headphones
4        | NULL    | Monitor
5        | 3       | Tablet


```sql
SELECT 
    users.username,
    orders.product
FROM 
    users
INNER JOIN 
    orders
ON 
    users.user_id = orders.user_id;
```



## 外部結合
### LEFT JOIN/RIGHT JOIN/OUTER JOIN
どちらかのテーブルにデータがあれば、取り出す

order_id | user_id | product
---------|---------|--------
1        | 1       | Laptop
2        | 2       | Smartphone
3        | 1       | Headphones
4        | NULL    | Monitor
5        | 3       | Tablet



```sql

SELECT 
    users.username,
    orders.product
FROM 
    users
LEFT JOIN 
    orders
ON 
    users.user_id = orders.user_id;

```


## まとめ
NULLを許容するかしないかって事かな
30代後半フリーランスの私が考えるエンジニアライフプラン

# はじめに
自分の考えるエンジニア像やライフプランについては、おすすめはしませんし、自分の考え方や生き方が正しいとは全く思いません。
私と似たような考えの方であったり、これを見て何かしらの役に立つ方がいれば良いかなと思い書いてみます。
こんな人もいるんだなーとか、こんな人でも生きていけているんだぐらいに思ってください。

個人の見解であり、所属する組織とは関係ありません。
また、ただのポエムなので批判などは受け付けていません。共感や賞賛などポジティブなものは受け付けています。

# 経歴について
新卒で入った会社を1年ほどで辞め、その後も転職を5度ほどした後にフリーランスエンジニアとして働いています。

同じ会社で働いていると大なり小なり不満が出てくるのが普通だと思いますが、それが1社しか勤めたことがないと比較ができないのでもっと働きやすい職場があるのではないか？と転職を繰り返してきました。
そんな中、きっかけもありフリーランスとして色んな場所や会社の環境を見てみた方がいきなり正社員になるよりも経歴的にも良いんじゃないかと言うことで今はフリーでやっています。

# 今までのエンジニアライフ総括
つくづくラッキーだったなと思います。
- プログラマーとして最初に扱ったのがモバイルアプリ開発であり、それが現在も需要が多いのであるのでやっていけていること
- SESとして客先常駐した際もきちんと技術が身に着くような現場であったこと。プログラマー志望なのにずっとテスターを続けさせられたり、全く別のことをやらされたりと言った話も良く聞くが、幸運なことに私は基本的にはほぼそのような扱いを受けたことがない
- それまでの仕事上の繋がりだけで仕事が続けられていること。タイミングや出会いなども運が良く、私自身は自分が営業をかけたりすることなく声をかけてもらってフリーランスとして仕事ができたこと

境遇や出会いなどはかなり幸運だったなと思いつつも、もちろんそれぞれの場所で自分のできることをきちんとやっていくってことも同じように大切だと感じます。

# エンジニアライフについて
今のところ仕事に困ることはなさそう、かつ他の仕事よりも楽で高給であると思っています。それはPE-BANKであったり、その他にも多数ありますが、フリーランスのエンジニアが仕事を見つけるためのサービスがとても充実しているからだと思います。
またコロナの影響もあってリモートワークが加速度的に進んだことも私のようなエンジニアにとってはとても幸運なことでした。（以前、東京で働いていたこともありましたがその時は満員電車に心をやられました）

エンジニアライフとしてはなるべく自分のやりたいことをできるようにするを目標にしてやってきています。

私は同じ場所で長く働くことが苦手で、1年ぐらいでなんとなく仕事をしたくなくなってきて、仕事を辞めて別の場所で働いたり、しばらく休みを取るみたいな生活を続けてきました。普通であればこんな生き方はできませんが、フリーランスなら自分の需要があるうちだけかもしれませんが、自分の好きなスタイルで働くことができます。

会社については外側からわかることなんてほとんどなくて、実際に働いてみないとわからないことが多いです。
良い表現かはわかりませんが、フリーランスであれば契約期間が決まっているのでもし嫌な職場であってもその期間が過ぎてしまえばそのまま終われますし、逆に働いてみて自分にとって良い職場であればずっと続けたり、場合によってはそのまま正社員として入ることもできると思うのでその辺りも良いかなと思います。

ただ、普通の人と違うことをしているときにはいつも思い出すのが、ジブリの「耳をすませば」から有名な言葉で【人と違う生き方は、それなりにしんどいぞ。何が起きても、誰のせいにもできないからね】と言うものがあります。

人と違うことをするのは当然様々なリスクがあるわけで良いことばかりではありません。それはその道を選んだ自分の責任であり受け入れなければならない、他人に責任を押し付けるような考えをしてはいけないと考えています。

それでも、人と同じ生き方の方が私にはしんどいし、もし誰かに言われた通りにして失敗したとしてもそれを誰かのせいにしたとしても何の意味もない、その人が責任を取ってくれるわけでもない。結局はどの道を選んでも自分の責任でしかないのであれば自分の好きな道に進むのが良いのではないでしょうか。

# 今後について
40代、はたまた50代も同じ考えでいてやっていけているのかは現時点ではわかりません。
ただ、それについてはどんな生き方をしている人でも同じではないでしょうか。
生成AIの今以上の発達や、その他にも現時点では想定していなことが起こってくるでしょう。

そんな中で大事なことは変化が起きたときそれに対応できるかどうかなのかな思っています。（これは常に最先端の技術を追うであるとかそういう意味ではありません）

もしかしたらこんな考え方ではエンジニアとしてやっていけていないかもしれませんが
それはそれで別の仕事を見つけたら良いのかなと今のところそんな感じで考えています。
5~10年後にまた振り返り、答え合わせをしてみたいです。

以上です。
mruby 3.3でfib(32)

mruby on YABMをいろいろ整理してみたので、測ってみました。

|target|CPU|ARCH|serial|gcc|fib(32)|
|:--|:--|:--|:--|:--|:--|
|rtlbm|RTL8196C|Lexra4181|38400|4.4.7|21秒|
|rtlbm|RTL8196E|Lexra4181|38400|4.4.7|22秒|
|rtlbm|RTL8197D|Lexra5281|38400|4.4.7|7秒|
|rtlbm|RTL8198|Lexra5281|38400|4.4.7|8秒|
|bcmbm|BCM5354|MIPS 4K|115200|4.9.2|25秒|
|admbm|ADM5120|MIPS 4K|115200|4.9.2|62秒|
|armbm|RT1310|ARM V5|38400|4.9.2|21秒|
|armbm|KS8695|ARM V4|115200|4.9.2|31秒|

LexraはMIPSの亜種ですが、特殊なのでベンダー提供のgccを使っています。

モジュールのタイマーで測っているので、精度は怪しいですが、それほど間違ってはいないと思います。

異常値は無く、正常なパフォーマンスが出ていると思われます。

RT1310をポートしていて、最初スタックのアドレスを0番地からのメモリの最後のほうにしていて、その領域はキャッシュ無しの設定になっていたので、48秒と異常値になっていました。このSOCの物理メモリの実体は0x40000000からでその領域はキャッシュONにしているので、コードとデータはキャッシュがきいていたようです。

pcから現在のアドレス拾って、gasの.ifdefを使ってRT1310の時は--defsym rt1310=1オプションでビルドするようにしてみた。

```
 mov sp,pc
 and sp,sp,#0xf0000000
.ifdef rt1310
 add sp,sp,#0xf00000
.else
 add sp,sp,#0x700000
.endif
```

あまり綺麗なやりかたではないのですが、なんか困った時にまた考える事にします。
Type Challenges 中級編15: Reverse, Flip Arguments, FlattenDepth

# Type Challenges 中級編15: Reverse, Flip Arguments, FlattenDepth

## はじめに

[GitHubのtype-challengesリポジトリ](https://github.com/type-challenges)は、TypeScript型システムの理解を深めるための型クイズ問題集です。高品質な型を作成することで、バグを減らし、プロジェクトの保守性を向上させることができます。今回も中級編から3つの問題に挑戦します。

## 1. Reverse

この課題では、配列を逆順にする型を実装します。これはJavaScriptの `Array.reverse` の型版です。

### 例

```typescript
type A = Reverse<['a', 'b']>; // ['b', 'a']
type B = Reverse<['a', 'b', 'c']>; // ['c', 'b', 'a']
```

### 私の回答

```typescript
type Reverse<T extends Array<unknown>, U extends Array<unknown> = []> = 
  T extends [infer F, ...infer Rest] ? Reverse<Rest, [F, ...U]> : U;
```

### 解き方

- `Reverse` 型は、ジェネリック型 `T` が配列であることを前提とし、再帰的に先頭要素 `F` を取り出して残りの要素 `Rest` を逆順にします。
- 基本的な考え方は、配列の先頭要素を新しい配列 `U` の先頭に追加していくことです。

このようにして、配列を逆順にする新しい配列型を作成することができます。

:::note info
再帰を使用して新しく配列を作ってしまえば問題ないですね！
:::


## 2. Flip Arguments

この課題では、関数の引数の順序を逆にする型を実装します。これはLodashの `_.flip` の型版です。

### 例

```typescript
type Flipped = FlipArguments<(arg0: string, arg1: number, arg2: boolean) => void>;
// (arg0: boolean, arg1: number, arg2: string) => void
```

### 私の回答

```typescript
type Reverse<T extends Array<unknown>, U extends Array<unknown> = []> = 
  T extends [infer F, ...infer Rest] ? Reverse<Rest, [F, ...U]> : U;

type FlipArguments<T> = 
  T extends (...args: infer ARGS) => infer R ? (...args: Reverse<ARGS>) => R : never;
```

### 解き方

- `FlipArguments` 型は、関数型 `T` が引数 `ARGS` と戻り値 `R` を持つ場合に、引数の順序を逆にした新しい関数型を返します。
- まず、`Reverse` 型を使って引数 `ARGS` の順序を逆にし、その結果を新しい関数型として返します。

このようにして、関数の引数の順序を逆にする型を作成することができます。

:::note info
関数の引数を推定して1問前のReverseを使えば簡単ですね、
:::


## 3. FlattenDepth

この課題では、配列を指定された深さ `depth` まで再帰的にフラット化する型を実装します。深さが指定されていない場合は1回フラット化します。

### 例

```typescript
type A = FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2>; // [1, 2, 3, 4, [5]]. flattern 2 times
type B = FlattenDepth<[1, 2, [3, 4], [[[5]]]]>; // [1, 2, 3, 4, [[5]]]. Depth defaults to be 1
```

（答えを見ました、情けない、、）

```typescript
type FlattenDepth<
  T extends any[],
  S extends number = 1,
  U extends any[] = []
> = U['length'] extends S
  ? T
  : T extends [infer F, ...infer R]
  ? F extends any[]
    ? [...FlattenDepth<F, S, [...U, 1]>, ...FlattenDepth<R, S, U>]
    : [F, ...FlattenDepth<R, S, U>]
  : T;
```

### 解き方

- `U` は再帰的にフラット化するためのカウンタとして使用しているようです
- `U['length']` が `S` に達するまで、配列の各要素をチェックし、ネストされた配列の場合は再帰的にフラット化しているようです、思いつかないだろこんなの、、

:::note alert
いや難しすぎる！！〇〇回繰り返す、とか難しい、、、
:::

## まとめ

これらの課題を通じて、TypeScriptの型システムに対する理解が深まり、複雑な型操作のスキルが向上します。特に、タプルや配列の操作、オブジェクト型のプロパティの操作に関する知識を強化できます。ぜひ、これらの課題に挑戦して、型の理解を深めてください。

### 参考記事

- [TypeScript公式ドキュメント](https://www.typescriptlang.org/docs/)
- [type-challenges GitHubリポジトリ](https://github.com/type-challenges/type-challenges)
【Power Apps】文字列を抜き出す方法

Power Appsで文字列を抜き出す方法を以下の3通りに分けて紹介します。

- 最初に出現する文字より前の部分を取得したい場合
- 文字と文字の間を抜き出す場合
- 不要な文字列の削除による抜き出し

## 最初に出現する文字より前の部分を取得したい場合

### Left関数+Find関数

Excelでもよく使用される、Left関数+Find関数です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/e542d086-29fb-63bc-011a-889d25e9a2bd.png)

検索する文字を含めたくなければ、Len関数を使用してFind関数の出力から文字数分引きます。

![image.png](https://powerplatformnikki.com/wp-content/uploads/2023/10/00ca69a8ed18df166fd71a8a53d76806.png)

### Split関数+First関数

Find + Leftよりもコードが短くなるのでよく利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/ebe0a726-c652-24a5-a0b4-fd9d503ed7c7.png)

Split関数で「.」を区切り文字にして文字列をテーブルに変換し、その一番上の値を取得することで指定した文字よりも前の文字列を抜き出しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/a4e08cd4-ef5b-2d72-d399-0c7b2339d4cc.png)

https://powerplatformnikki.com/split

## 文字と文字の間を抜き出す場合

### Match関数

これまでの手法を組み合わせることでも文字列を抜き出すことが可能ですが、Match関数を使用すればより短く記述することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/abb4dc6b-53e8-e9e9-05b0-af490954614a.png)
最初の「.」から最後の「.」までを抜き出す場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/1457bd71-e359-bec4-a2d7-db7228e544d6.png)
最初の「.」から2番目の「.」まで抜き出す場合

https://powerplatformnikki.com/match

### Split関数+Index関数

Split関数で作成された区切り文字ごとのテーブルから、Index関数を使用して何番目の部分を抜き出すかを指定することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/be9433dd-25fa-369f-e339-ab8442635952.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/0eb561be-1309-ec1e-97f2-bcc6f5bf1eee.png)

https://powerplatformnikki.com/index

### MatchAll関数+Index関数

Split関数の代わりにMatchAll関数を使用しても同様の処理が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/2c205f5f-4da0-4ffd-3711-fdcf8e155bee.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/7b4c01d1-f51c-26d3-6634-adeb30bc93b1.png)

## 不要な文字列の削除による抜き出し

不要な文字列のみ削除・置換することで必要な文字列を抜き出す場合は、Substitute関数を用いて不要な部分を削除します。

また、抜き出した後の文字列に不要な部分がある場合にも使用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/ebdc2080-8fe9-5d67-7e2f-6eca54f401e5.png)

https://powerplatformnikki.com/substitute

## 数値部分のみ抜き出す

数値部分のみ抜き出す場合は、MatchAll関数で正規表現使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/9636fd5d-c408-4155-882e-10eb394e218b.png)

https://powerplatformnikki.com/checknumberofcontrol

https://powerplatformnikki.com/powerappsregexmatch

## Power Automateはこちら

https://powerplatformnikki.com/powerautomatesubtexttemplate

## 元記事

https://powerplatformnikki.com/charactersextraction/
ハーフマラソンを走りました（Qiitaで）

[**Qiita Engineer Festa 2024**](https://qiita.com/official-campaigns/engineer-festa/2024)の**投稿マラソン**という企画で、**ハーフマラソン**にあたる期間中に19個の記事を投稿しました（この記事が19個目です）。この記事では、参加の経緯と記事を書いてみて改めて思ったことを書き残したいと思います。

## 参加の経緯
なんで参加しようと思ったかと言われると、こういう**祭り事があったら参加したくなってしまう性**というのがほとんどなのですが、もう1つ、今まで得てきて散り散りになっていた知識を、この機会にまとめてドキュメントとして残しておこうと思ったからです。

昨年まではよくハッカソンに参加をしていて、締切に迫られながら取り敢えず動くものをと急いで実装するということが多かったです。それが今年に入ってから、ハッカソンへの参加は少なくなり、サークル・コミュニティでの開発、個人開発、などなどで比較的じっくりとプログラムを書く機会が増えました。

開発の中でよりよく作るにはどうすれば良いだろうと、色々と調べながら進めてきましたが、**そこで得た知識が色々なところに散り散りに**なってしまっていました。**コードとして残ってはいますが、それをドキュメントとしても残しておこう**ということでこの機会に記事を書くことにしました。

## 実際に記事を書いてみて
実際に記事を書いていて感じたのは、**記事を書くために改めて知識を整理することで、理解をより深めることにつながる**なということです。

当時実装をした時も、色々と調べながらあれこれ試行錯誤してようやく動くようになって、それで理解しきった気になっていました。ただ、また落ち着いて調べ直してみると、要らない記述があったり、より良い書き方が見つかったりといったことがありました。

また、小さな要素に分けて記事にすることを意識していたので、その個々の処理をより一層理解することにも繋がった気がしています。

## ハーフマラソンの完走を目指してみて
ただ記事を書くだけではなく、Qiita Engineer Festaの投稿マラソンでハーフマラソンの完走目指して記事を書くことで感じたのは、やはり**締め切りがあることでモチベーションを得ることができた**のが良かったなという点です。

自分のような怠惰な人間は、やっぱり締め切りがないとダラダラと記事を書いてきっと投稿するのも遅くなってしまいます。それがこのキャンペーンでは一定の期間で19本という目標が設定されていて、高すぎずちょうどいいくらいの目標になりました。

投稿はやっぱり期間ギリギリになって、最終日前の2日で10記事を投稿してますが、この締め切りがなかったらこれらの記事を書くのももっと後だっただろうなと思います。

## 終わりに
今回のEngineer Festaの投稿マラソンでは、主に今年に入ってからの半年で得た知識をまとめて記事にしました。きっとこの先半年の期間でも、色々と学び知ることも多いと思います。なので次は12月のアドカレで、また記事という形で知識を整理する機会を設けられたら良いのかな、なんて考えています。

半年ごとにEngineer Festaとアドカレという大きめの投稿イベントがあると、定期的な整理の機会としてちょうど良いですよね。その時はもっと計画的に記事も書けるようにしていきたいです。

あと、ちゃんと運動する習慣つけてリアルでハーフマラソンも走ってみたいなー。

一連の投稿した記事が、どこかで誰かの助けになれば幸いです。
受注に対する納期を算出する【Excel】【PowerBI】説明①

原則として、現実の物品を扱い販売を行う限り必ず「納期回答」という業務は発生します。

この「納期回答」は日常的に行われる行為であるため、半自動 or 全自動で算出することができれば業務に対しそれなりに寄与するはずです。

「納期回答」のむつかしい所は下記だと私の認識だと下記です。

1. 完全受注発注でない限り受注数も発注数ともに任意であるため計算がややこしい
2. 取扱品目数が増えれば増えるほど計算がわからなくなってしまう

派生はいろいろとあるのですが、基本は上記の2点ととらえています。
これを自動化する＝解決するために最初は最も単純なモデルから考えてみましょう。
品目数は1点のみ。その受注と発注の関係は下図となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/cab0926a-52a1-5388-f380-305ba99b145f.png)

もちろんこのレベルであれば回答は下図赤文字となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/da1b6bc6-aaed-25fd-2869-5e91a15a4c51.png)

ここから、上記の視覚と暗算による結論を自動化するためのロジックを記載します。

ステップ１：在庫と入荷に累計数の欄Bを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/39a1315b-8f0a-f0dd-4bb2-ed994eb94e55.png)

受注数A－累計数Bを算出する差分欄を追加し、差分がマイナスとなる行は削除する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/d90f41ee-45be-0ad2-c958-b7f43d692a35.png)

残った行の集合における最小の日付が「当該受注に対する引当予定日」となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/c6c9d84e-2a92-0118-470f-415782f559b2.png)

結論は「在庫を含む入荷予定の累計を算出し、受注数との差が0以上である集合の中で日付が最小のものが『ある受注に対する引当予定日』である」となります。

これはどんなに品目数が増えたとしても、入荷ルートが複雑になったとしても基本は同じです。
次に書く（予定）の記事はこの前提を抑えたものとなりますので、困ったら戻って確認してみてください。
CodeCatalystのMarkdown表示機能についてわかったこと

# はじめに

みなさんこんにちは！Amazon CodeCatalyst(以降はCodeCatalystと記載します)のソースリポジトリにてドキュメント管理をする中で、図・画像のMarkdown表示機能についてわかったことをご紹介していきたいと思います。

# CodeCatalystとは

AWS公式が提供するドキュメントによると、CodeCatalystについて以下の記載があります。
>Amazon CodeCatalyst は、ソフトウェア開発プロセスに継続的インテグレーションとデプロイの方法を採用するソフトウェア開発チーム向けの統合サービスです。 CodeCatalyst 必要なツールがすべて 1 か所にまとめられています。継続的インテグレーション/継続的デリバリー (CI/CD) ツールを使用して、作業の計画、コードの共同作成、アプリケーションの構築、テスト、デプロイを行うことができます。

https://docs.aws.amazon.com/ja_jp/codecatalyst/

ソフトウェア開発に必要な機能を備えており、タスクの管理・ソースコードの管理・ワークフローの実行等が可能となっています。

# 図・画像のMarkdown表示機能についてわかったこと

それでは図・画像のMarkdown表示機能についてわかったことを紹介していきます。今回は以下2点について確認しました。
* Mermaid形式の図の表示
* 画像の表示

## Mermaid形式の図の表示

Mermaid形式の以下図をCodeCatalystで表示してみます。

~~~markdown
```mermaid
graph LR
 A-->B-->C-->D
```
~~~

GitHubなどのMermaidに対応するMarkdown表示機能では次のように図として表示されます。

```mermaid
graph LR
 A-->B-->C-->D
```

一方、CodeCatalystの画面は以下になります。図は表示されず、コードがそのまま表示されました。

![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773682/d8a2510f-ad57-8304-4eeb-3a6b25aee742.png)


## 画像の表示

画像の表示はインターネット上の画像を参照する場合とリポジトリ内の画像を参照する場合で結果が異なりました。
以下画像をCodeCatalystにて表示してみます。

![CodeCatalystのしくみ](https://d1.awsstatic.com/codecatalyst/hiw-diagram-codecatalyst.2f03c075835539db18fd73ccdf9ee813618ae64b.png)

引用元

https://aws.amazon.com/jp/codecatalyst/

### インターネット上の画像を参照する場合

引用元のサイトより画像のリンクを取得し、ドキュメント内で参照します。
サンプルコードは以下になります。

~~~markdown
# インターネット上の画像を参照する場合

CodeCatalystの仕組みを以下に示します。
![CodeCatalystの仕組み](https://d1.awsstatic.com/codecatalyst/hiw-diagram-codecatalyst.2f03c075835539db18fd73ccdf9ee813618ae64b.png)
~~~

CodeCatalystの画面は以下になります。インターネット上の画像を参照する場合は、画像が表示されました。

![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773682/8aae9d74-0cb6-ee4b-a7f0-9c77fe3554ea.png)


### リポジトリ内の画像を参照する場合

同じ画像をリポジトリ内に保存し、ドキュメント内で参照します。
サンプルコードは以下になります。

~~~markdown
# リポジトリ内の画像を参照する場合

CodeCatalystの仕組みを以下に示します。
![CodeCatalystの仕組み](./XXX.png)
~~~

CodeCatalystの画面は以下になります。リポジトリ内の画像を参照する場合は、画像が表示されませんでした。

![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773682/019f4bca-8be5-5fef-a971-fea1d2ca1798.png)


:::note info
現状のCodeCatalystで図・画像をプレビュー表示するためには、一度インターネット上に画像を公開し、そのリンクを参照するなどの回避策をとる必要がありそうです。
:::

# まとめ

いかがだったでしょうか。今回はCodeCatalystのソースリポジトリにおける図や画像のプレビュー表示についてご紹介しました。この記事が誰かのお役に立てますと幸いです。

---

- AWS は、米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
- その他、記載されている会社名および商品・製品・サービス名は、各社の商標または登録商標です。
Wordpress.comの「Application Manager」を使って認証処理を実装してみる

# Wordpress.comの認証
Wordpress.com 上のデータを外部から扱うには認証（OAuth2.0）が必要です
Wordpress.comから提供されている認証エンドポイントを利用して、外部からWordpress.comのデータを扱えるようにしましょう。

# 手順
1. Application manager で認証アプリを作る
1. アプリケーションパスワードを発行する
1. 認証処理を実装する

# Application manager で認証アプリを作る
Application Managerのリンクは以下。

https://developer.wordpress.com/apps/

このリンクの右上に「Create New Application」があるのでクリックすると、以下のようなアプリ作成が出ます。

![スクリーンショット 2024-07-09 1.31.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/dc3fc83f-7a61-ea37-3185-37c397044b33.png)

### 各項目の説明
- Name
    - アプリケーションの名前
- description
    - アプリケーションの概要
- Website URL
    - この認証アプリを適応するブログURL
- Redirect URLs
    - OAuth認証後にユーザーがリダイレクトされるURL
- Javascript Origins
    - この認証アプリを適応するブログURLでいいと思います
- 　What is 7 + 5?
    - 　なんか聞かれるのでちゃんと答えよう
- 　Type
    - 　Webアプリで使うかネイティブアプリで使うかの選択
- 　Follow Developer blog
    - 　Wordpress.comの [Developer Blog](https://wordpress.com/blog/) の更新情報を自分のメールに配信するか

これらを入力して保存すると、以下の情報が表示されますが、赤で囲っている部分を後ほど使用します。

![スクリーンショット 2024-07-09 1.53.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/53d93291-d739-6ccc-f81f-19389ace8310.png)


# アプリケーションパスワードを発行する
以下を参考にしてください。

https://qiita.com/KyongminS/items/12e4d43956256d8ce7b7

# 認証処理を実装する
envはよしなに設定してください。

```php:認証トークンの発行
// 1. で作成したアプリの Client ID と Client Secrets を使う。
public function getToken($user, $password): string
{
    $curl = curl_init( config('services.wordpress.endpoint'). "/oauth2/token" );
    curl_setopt( $curl, CURLOPT_POST, true );
    curl_setopt( $curl, CURLOPT_POSTFIELDS, [
        'client_id' => config('services.wordpress.client_id'),
        'client_secret' => config('services.wordpress.client_secret'),
        'grant_type' => 'password',
        'username' => $user,
        'password' => $password,
    ] );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1);
    // Access-Control-Allow-OriginをCORSがおこならないように設定
    curl_setopt( $curl, CURLOPT_HTTPHEADER, [
        'Access-Control-Allow-Origin: *',
    ] );
    $auth = curl_exec( $curl );
    $auth = json_decode( $auth );
    $access_key = $auth->access_token;

    return $access_key;
}
```

```php:Wordpress.comの記事投稿APIを使ってみる
public function post($baseUrl, $user, $password, $data): Response
{
    return
        Http::withHeaders([
                'Authorization' => 'Bearer '.$this->getToken($user, $password)
            ])
            ->post(config('services.wordpress.endpoint'). "/wp/v2/sites/". parse_url($baseUrl, PHP_URL_HOST). "/posts", $data);
}
```

これで Wordpress.comのREST APIが使用できます。

＃追記
この手法は **このアプリを作ったユーザのアイパス出ないと動きません。**
改善手法はまた後日に紹介します。

https://developer.wordpress.com/docs/oauth2/#4-testing-an-application-as-the-client-owner
DockerでMySQLを"最速"で実装する方法

## Dockerでmysqlを使う

:::note warn
docker コマンドが使える環境が整っている前提で進めます。
:::


## image作成＆コンテナ作成＆コンテナ起動

このコマンド一つでimage作成,コンテナ作成,コンテナ起動をしてくれます。
~~~
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=パスワード -d mysql:tag
~~~



## コンテナに入る
~~~
docker exec -it some-mysql bash
~~~


## mysqlに入る
~~~
mysql -u root -p
~~~
このコマンド実行した後にパスワードを求められます。
最初のコマンドで設定したパスワードを入力しましょう。


## まとめ
めっちゃ簡単ですね。

https://hub.docker.com/_/mysql
Laravelのenvの値はどの優先順位で参照されるのか

# 結論
1. コマンドラインオプション（php artisan test **--env=test**　←コレ）
1. サーバ環境変数
1. `phpunit.xml` の設定値（テスト実行時）
1. `.env` の値
1. `.env.production`
1. `.env.example`

# 補足
サーバ環境変数は
```zsh
export ENV=production
```
としたら
```php
$env = env('KEY');
```
で参照できます。

無理やりDBのコネクションを変えたりオプションを書き換えたい場合は、コマンドラインオプションを使うのがいいですね。
【VR開発】Meta Questコントローラーの速度を取得する

# はじめに

こんにちは。
ジョジョ好きなXRクリエイターの [もふるね](https://twitter.com/mofurune_k) です。

今は院試が終わってルンルンでVR開発をしてるところです。
開発で得た知識を備忘録として残します。

開発環境
・Unity 2022.3.20f1
・Meta XR Core SDK
・Meta XR Interaction SDK Essentials
・Oculus XR Plugin
使用機材
・Meta Quest2

# 結果

<iframe width="560" height="315" src="https://www.youtube.com/embed/ZYLTg12nF48?si=-eChQH2FiqpnATwb" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

速度をとって、速度の数値をテキストとバーで可視化しています。
速度の大きさが1を超えると色が緑から赤に変化します。


# つくりかた

速度をとるコード

```cs:
// 左手のコントローラを変数に登録
OVRInput.Controller LeftController = OVRInput.Controller.LTouch;
// コントローラの速度を取得
Vector3 LConVel = OVRInput.GetLocalControllerVelocity(LeftController);
// 速度の大きさを計算
VelValue = LConVel.sqrMagnitude;
```

取得できるコントローラの速度はx,y,z軸それぞれの速度です。
sqrMagnitudeでxyzそれぞれの速度の2乗を足した値を計算しています。

取得できるデータは[Oculus Integrationで取得出来るOculus Goの主要な入力【Unity】【VR】【アセット】【Oculus Go】](https://kan-kikuchi.hatenablog.com/entry/Oculus_Integration)を参考にしました。


# 応用

手を速く動かすとロウソクの火が消える仕組みをつくってみた

<iframe width="560" height="315" src="https://www.youtube.com/embed/lkHnXJQr9Kw?si=8g_4pFjg8a6Ev_Q1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


# 振り返り

ホラゲーが好きなので、コントローラーの速度を活かしたVRホラゲーつくってみたい。
最近はバイオ7と8を買った。怖い。最高。
機械学習を超えて生き残るためにエンジニア初心者はどうすればいいのか？

[インフラエンジニアのキャリアについてのポエム](https://qiita.com/fmlorg/items/8cad1b81f3ac3adb6fb3)裏面(Side-B)です


2024年6月に次の記事がありました

https://techtarget.itmedia.co.jp/tt/news/2406/19/news08.html

別に目新しいことは言っていなくて、あえていえば「生成AIが、さらにトドメを刺そうとしている」という話です



## なにが問題か？


いままでは新人としての修行時代が普通ありました

> 先輩が稼いできた売上で食べさせてもらいながら修行して実戦配備できるのを待っていただいていた幸せな時代


**将来への投資**として、自分(先輩社員)がやれば30分なのに、あえて新人に3日かけてやってもらう(+ 先輩が直す)みたいなことをやってきたわけです

もう多くの企業側にそういう余力がなくなってきているでしょう

そして**眼の前の売上を伸ばしたいだけ**なら、いまいる社員が、機械学習サービスを下請けとして使いこなして、その「そこそこの結果」を元に修正すれば、新入社員とか不要なわけです

まぁ、その会社は30年も経てば廃業しているでしょうけれど、転職前提の現役ベテラン勢は別に困らなそうです

問題は、いま新人とか、これから新人になる人、そして新人以前のヒヨコ(学生、生徒)は、どうすればよいのか？でしょう



## 答えはあるのか？


(新人時代がない=)社会に出る段階の能力で評価されるしかない状態です。自分で勉強するから大丈夫という発想は甘いです。社会人は何かと忙しいので、じっくり新しいことを勉強する暇がとれません。「現在、社会人が勉強にあてられる時間は1日13分」説を聞いたことがあります(あくまで、そういう説を聞いたことがあるだけです。これに関する、きちんとした社会学的統計があるのかどうかは知りません)



残念ながら、聞こえの良い解決策は持ち合わせておりません。あえて言えば、次の二点だけです

1. 使い方の勉強で満足せず、その背後にある原理(論理)を理解してください
1. (現役社会人より圧倒的にヒマなんだから)場数をこなしてください

ここは、[ポエムのＡ面](https://qiita.com/fmlorg/items/8cad1b81f3ac3adb6fb3)の繰り返しです。ひとつだけ追加するなら、**じっくり勉強する余裕がある**学生時代に(卒業時に)即戦力と思ってもらえるように

> 上(1. と 2.)の修行のため、時間の猶予をもらえるチャンスがあるなら、もらって修行してください(4年といわず、さらに、もう2年とか...)


これも先立つものが必要なので、万能策ではありませんが ...

かつてモラトリアムがバカにされた時代があります(モラトリアム世代という表現もある)。そりゃ、時間の無意味な使い方をしていればバカにされてもしかたありませんが、有意義な使い方をすればよいのです。もらえるなら**モラトリアム**をもらってください



## あとがき


テーマごとに分けたほうが読みやすいかな〜と思って、同じ話のウラ面(Side-B)を別に書いてみました


## updates (2024/07/24)

https://qiita.com/bisketoriba/items/116e73224232703b3965

この記事の後半でGoogleの人が同趣旨のこと(A面+B面２つ分の趣旨)を述べていると思います

## updates (2025/03/18)

（上の記事が予言している未来は、すでに到着済でした）

2025年2月末のSalesforceのCEOいわく「(今年度は)もうエンジニアは採用しない」「(みんな安心しろ！AI使って)売上は伸びてる」。

※(記事には書いてないけど)もちろん別枠で著名なエンジニアの一本釣りとかはしていくのでしょうけど、それは通常の職探しルートではないので、この採用停止云々には含まれないと思います。

いずれにせよ、すでに新卒どころか中堅も修行する場所がない（自腹で、自宅で、修行しなさい）状態みたいです。 日本は何周か遅れてるので、次の４月にこうなるとは言いませんが、遅かれ早かれ、そうなるでしょう

https://sfstandard.com/2025/02/27/salesforce-marcbenioff-layoffs-tech-agents/


## CHANGES

- 2024-07-24: updates (2024/07/24)セクションを追加
- 2024-10-21: fix typo: 1. 〜 1. 〜 (すいません、1. 2. と表示されていませんでした;_;)
- 2025/04/07: tag を拡張、一連のシリーズ記事と合わせました


## 参考文献


- [長くエンジニアを続けたいなら、論理力を鍛えよう、そのためには場数が重要](https://qiita.com/fmlorg/items/8cad1b81f3ac3adb6fb3)
    - これが本ポエムの表面(Side-A)
    - レコードが知らないと、Ａ面とかＢ面がわからないよね〜(涙)


Copyright (C) 2024-2025 Ken’ichi Fukamachi, CC BY-NC-SA 4.0
「Composeの基本レイアウト」のメモ#9 ~ホーム画面 - スクロールの実装~ 

### [10. ホーム画面 - スクロール](https://developer.android.com/codelabs/jetpack-compose-layouts?hl=ja#9)

#### 最小構成　
```Kotlin
@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
    // Implement composable here
    Column() {
        SearchBar()
        HomeSection(title = R.string.align_your_body) {
            AlignYourBodyRow()
        }
        HomeSection(title = R.string.favorite_collections) {
            FavoriteCollectionsGrid()
        }
    }
}
``` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/e5114a83-6c68-7d15-6320-ecea4af93a1d.png)

#### SearchBarの微調整
 + 上と水平方向にそれぞれ`16.dp`のpaddingをつける
     + `Spacer(modifier　= modifier.height(16.dp))`
         + 上部のパディングがSpacerの役割であることがわかりにくなるので、`Spacer`を使用する
     + `SearchBar(modifier = Modifier.padding(horizontal = 16.dp))`
         + 水平方向のpadding

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/ad49eefe-9c43-2328-cc7b-4cfb575310ca.png)
+ 隙間ができる

#### Columnの微調整
+ `LazyColumn`でない場合にスクロール動作を追加するときは　、`modifier.verticalScroll`を使用する
長くエンジニアを続けたいなら、論理力を鍛えよう、そのためには場数が重要

インフラエンジニアのキャリアについてのポエムです。対になる[ポエム裏面(Side-B)](https://qiita.com/fmlorg/items/5a2a35bb00174d7453ad)も、ぜひ御覧ください

[![](https://lpic-2024q2.demo.fml.org/dist/slide-p.51.png)](https://speakerdeck.com/fmlorg/burauzanohutawokai-ketehttpti-yan-siyou-20240608v1-dot-0-0?slide=51)(上図をクリックするとスライドに飛びます)



## 長く続けられる技術者には何が必要か？


1. ひととおり何でも分かる
1. 論理的能力
1. 技術を抽象化して俯瞰的に見られる

そうは言っても、万遍なくいけるオールラウンダー(1.)なぞ滅多にいないでしょう。とうぜん得意不得意があるはずです。うちらは、その得意分野に「ITインフラ」いかがですか？と営業をしているわけです、はい:-)

以下 2. と 3. の話が続きます

が、その前に、少し脇道にそれますが...



## [内向的でもいいじゃないか](https://speakerdeck.com/fmlorg/burauzanohutawokai-ketehttpti-yan-siyou-20240608v1-dot-0-0?slide=54)


もちろん引きこもりではダメなのですが、だからといって無理に外向的になろうとする必要は無いと考えます。人間には向き不向きがあるものです

むしろ内向的な人の方が、粛々と作業するインフラエンジニアに向いてるのではないか？と思ったりもします

われわれは、飛び込み営業をしたり、お客さんと談笑するのが本業ではありません。お客さんのあいまいな「ほげほげがしたい」から、お客様が本当にやりたいことを推測し、適切なシステムを提案・実装・構築・納品することが技術部の仕事です(売上の回収は営業さん、よろしくです)

そして、このためには(推論も含む)高い論理的能力が必要となるでしょう



## 論理的能力を鍛える


これは場数しかないと思います

### [ヒマがあれば手を動かす](https://speakerdeck.com/fmlorg/burauzanohutawokai-ketehttpti-yan-siyou-20240608v1-dot-0-0?slide=56)


どうせ手を動かすなら、**OSの実務的な動作原理の理解**が必要なことに挑戦したいものです。OSのパッケージを増減して遊ぶのではなく、ソースからコンパイルするとか、OSのカスタマイズ(例:1.4MBのLinuxディストロを作る)とか ...





### [アウトプットする](https://speakerdeck.com/fmlorg/burauzanohutawokai-ketehttpti-yan-siyou-20240608v1-dot-0-0?slide=57)


技術文書を書く(Technical Writingの)練習が必要です。読書感想文ではなく論理的な文章の書き方

書く動機づけに、定期的にblogを書くとか、技術同人誌を作るとか、心に決めて 「〆切駆動開発」とか「イベント駆動開発」(イベントあわせで頑張ること:-)を考えると良いのではないか？と思います



## [技術を抽象化して俯瞰的に見られるとよい](https://speakerdeck.com/fmlorg/burauzanohutawokai-ketehttpti-yan-siyou-20240608v1-dot-0-0?slide=58)


歴史は繰り返しませんが、似たようなところには返ってきます(あえて言えば、スパイラル)。

いまのクラウドを見ると、Amoebaっぽいと見なすこともできるし、インターネット第1世代(1969-1983)の前の(御先祖さまの)時代の構想に近づいてしまっているんですよね

**出来事史ではなく、それを抽象化して俯瞰的に見られることが大事**

ただ、即効性はありませんし、それができれば先読みもできるのか？というと、確実に予想できるようになるとも言えませんけれど ...大事だと思っています



## まとめ


将棋の名人だって、とてつもない場数(訓練)の先に、(機械学習を越える)解答を瞬時に決断できている(超人的なショートカットができている?)はずで、この点、エンジニアの能力も一緒です。だから場数が大事

たんなる場数ではなく、とてもたくさんの場数(努力)の先に何か(奇跡?)があるのでしょう

いまどき、たいていの「そこそこの答え」は機械学習が出してくれますが、「そこそこ」からハミ出た部分は、いつまでも残ります。そこをなんとかするのが、これからのエンジニアの役目になると考えています





## あとがき


もともと書こうと思っていたら、ちょうど Qiita Festa 2024 になったので、「このウェーブに乗るしかない」と乗ってみました(w)

ITインフラといっても広いのですが、このポエムの元はLPIウエビナー用なので、ネットワークの話がなくて、おもにシステム構築寄りです。すみません





## 参考文献


「NN周年」をトリガーにした「イベント駆動」:-)で、かなり出来事史だけに近づけた薄味(カルピスウォーター?)版の歴史をちまちま書くシリーズです

- [シリーズ「色づかないworld-wide-webの昨日から」(qiita 版)](https://qiita.com/tags/%e8%89%b2%e3%81%a5%e3%81%8b%e3%81%aa%e3%81%84world-wide-web%e3%81%ae%e6%98%a8%e6%97%a5%e3%81%8b%e3%82%89)




## 初出情報


本ポエムは、LPIウエビナー 2024-06-08 13:00- のCパートで語っているキャリア形成ネタのダイジェストを少し改訂したものです。ふりかえってみると、このウエビナー、二つのテーマ(ハンズオンとキャリアの話)を混ぜるな！という感じはあります(少し反省です)けれど、全力で振りきるイキオイはヨシと思いました、うむ

- [スライド(p.51 - p.59)](https://speakerdeck.com/fmlorg/burauzanohutawokai-ketehttpti-yan-siyou-20240608v1-dot-0-0?slide=51)


- Youtube にアーカイブ動画があります。51分30秒くらいからがCパートです
    - https://youtu.be/y84Asag9O1o


## CHANGES

- 2024/10/21: fix typo: 1. 〜 1. 〜 1. 〜 (すいません、1. 2. 3. と表示されていませんでした;_;)
- 2024/10/21: ポエム裏面へのリンクを追加
- 2025/04/07: tag を拡張、一連のシリーズ記事と合わせました

Copyright (C) 2024 Ken’ichi Fukamachi, CC BY-NC-SA 4.0
クラウドじゃないけど宇宙開発のスケールアップ・スケールアウト - アポロ11号の月着陸から55年 -

番外編のポエムです


## アポロ11号の月着陸から55年


1960年代の宇宙開発競争における設計方針は、おおまかにいって、アメリカはスケールアップ、ソ連はスケールアウトだったと言えるでしょう

運用部隊としては、コロリョフ(ソ連の宇宙開発のチーフアーキテクト)の設計方針に好感がもてるのですが、残念ながら当時の技術力ではシンクロが難しすぎて、うまくいきませんでした。

もちろん、アメリカの(フォンブラウンチームが作り上げた)サターンVもエンジンが5つあるのですが、ソ連の「30機のエンジンを(たぶん1/1000秒くらいのスケールで)シンクロ」は、はるかに難しいでしょう。半導体技術でも遅れていたソ連なので、アポロより相当アナログなつくりだったろうし ...

クラウドサービスが巨大な分散システムと言っても1/1000でシンクロとか、そういう要請は無いですから、ITシステムのスケールアウト・スケールアップとは次元が違う難しさです

ハードウエア制御は難しい ...(けど、これはこれで、うまく動けば楽しいんでしょうね〜)


### 注意

正確には

- 7/16 (UTC) 打ち上げ
- 7/20 (UTC) 月着陸

なので、いま(本記事の投稿時点)は打ち上げから半日くらいたったくらい(から55年)です


## 参考文献


PBS（アメリカの教育テレビ相当）製作のアポロ計画のドキュメンタリがおすすめです。邦訳は知りませんけど、たぶん、ないのではないか？と ...

original site: https://technotes.fml.org/tech/history/worlds-in-mono/

(qiita版も致命的な間違いやTYPOは修正しますがupdatesはoriginalのほうだけです)

Copyright (C) 2024 Ken’ichi Fukamachi, CC BY-NC-SA 4.0
Type Challenges 中級編14: ObjectEntries, Shift, Tuple to Nested Object

# Type Challenges 中級編14: ObjectEntries, Shift, Tuple to Nested Object

## はじめに

[GitHubのtype-challengesリポジトリ](https://github.com/type-challenges)は、TypeScript型システムの理解を深めるための型クイズ問題集です。高品質な型を作成することで、バグを減らし、プロジェクトの保守性を向上させることができます。今回も中級編から3つの問題に挑戦します。

## 1. ObjectEntries

この課題では、TypeScriptのオブジェクト型をキーと値のペアのタプルに変換する型を実装します。これはJavaScriptの `Object.entries` の型版です。

### 例

```typescript
interface Model {
  name: string;
  age: number;
  locations: string[] | null;
}

type ModelEntries = ObjectEntries<Model>; // ['name', string] | ['age', number] | ['locations', string[] | null];
```

### 私の回答

```typescript
type ObjectEntries<T> = {
  [K in keyof T]-?: [K, T[K]]
}[keyof T];
```

### 解き方

- `ObjectEntries` 型は、オブジェクトの各プロパティキーに対して、そのキーと対応する値のペアを生成するマッピングを作成します。
- 最終的に、各ペアのユニオン型を返します。

このようにして、オブジェクトのすべてのプロパティをキーと値のペアのタプルとして取得することができます。

:::note info
早速前回学んだ`-?`が役立ちましたね！
:::


## 2. Shift

この課題では、配列の先頭要素を削除した新しい配列型を返す型を実装します。これはJavaScriptの `Array.shift` の型版です。

### 例

```typescript
type Result = Shift<[3, 2, 1]>; // [2, 1]
```

### 私の回答

```typescript
type Shift<T extends Array<unknown>> = T extends [infer _, ...infer Rest] ? Rest : [];
```

### 解き方

- `Shift` 型は、ジェネリック型 `T` が配列であり、その配列が非空の場合に先頭要素を除いた残りの配列を返すようにします。
- `infer` キーワードを使用して先頭要素と残りの要素を抽出します。

このようにして、配列の先頭要素を削除した新しい配列型を作成することができます。

## 3. Tuple to Nested Object

この課題では、文字列のタプル型 `T` と任意の型 `U` を受け取り、タプルをネストされたオブジェクト型に変換する型を実装します。
:::note alert
いや急に簡単？inferさえできればできる。
:::

### 例

```typescript
type A = TupleToNestedObject<['a'], string>; // {a: string}
type B = TupleToNestedObject<['a', 'b'], number>; // {a: {b: number}}
type C = TupleToNestedObject<[], boolean>; // boolean. if the tuple is empty, just return the U type
```

### 私の回答

```typescript
type TupleToNestedObject<T, U> = 
  T extends [infer F, ...infer Rest] ? { [K in F & string]: TupleToNestedObject<Rest, U> } : U;
```

### 解き方

- `TupleToNestedObject` 型は、タプル `T` が非空である限り、最初の要素 `F` をキーとし、そのキーの値が残りのタプル `Rest` をネストしたオブジェクト型となるように再帰的に処理します。
- タプルが空の場合は、型 `U` を返します。

このようにして、タプルを元にネストされたオブジェクト型を生成することができます。

 `{ [K in F & string]: TupleToNestedObject<Rest, U> } `
 (Fは文字列リテラル)
 でオブジェクトを作れることも覚えておこう。


## まとめ

これらの課題を通じて、TypeScriptの型システムに対する理解が深まり、複雑な型操作のスキルが向上します。特に、タプルや配列の操作、オブジェクト型のプロパティの操作に関する知識を強化できます。ぜひ、これらの課題に挑戦して、型の理解を深めてください。

### 参考記事

- [TypeScript公式ドキュメント](https://www.typescriptlang.org/docs/)
- [type-challenges GitHubリポジトリ](https://github.com/type-challenges/type-challenges)
next.js で "Hello World" する <js教入信その1>

# この記事とは
いままでC言語C++を使ってきた筆者がjs教に入信することでQOLを向上させたいので、習得した知識をまとめるために作った。
# やること
その1 : node.jsのダウンロード
その2 : npxのインストール
その3 : next.jsのプロジェクトの作成
その4 : 開発サーバーの起動

と言って感じで、C++であればコーディング→コンパイル→実行といった具合で単純だったが、お作法が多め。また、横文字しかないので頭が混乱する。

# node.jsのダウンロード
javascriptはChrome、edge、firefoxなどの検索エンジンに搭載されているjavascriptエンジンによって動作するのが基本だが、これをパソコン上で動かせるようにするのがnode.jsだ。これをダウンロードする。node.jsの公式ページにあるインストーラーを実行して、PowerShellかcmdで以下の構文を打とう。

```powershell:node.jsのバージョン確認
node -v　# インストールしたバージョンが表示される
```

```powershell:npmのバージョン確認
npm -v　# インストールしたバージョンが表示される
```
C系のコンパイラでも-vはしっかりインストールできているか確認する定番のコマンドである。これでバージョンが表示されたら成功である。なお、npmはnode.jsをインストールしたときにもれなくついてくる。こちらも必要なものなのでバージョン確認をして正常にインストールされているか確認しよう。

# npmとは
npmとはパッケージの管理をしてくれるもの。必要になったら自動でインストールしてくれます。パッケージとはC系でいうヘッダーファイルで、npmが#includeを自動でやってくれるとでも思っとく。

# npxのインストール
プロジェクトフォルダーをどっかに作って PowerShell or cmd を開いて以下のコマンドを実行する
```powershell:next.jsプロジェクトの作成
npx create-next-app@latest my-next-app
```
このコマンドを実行するとエラーが出るなぜならnpxがインストールできていないからだ

### npxとは
npmはパッケージの管理を行うのに対してnpxはパッケージの実行を行う。C系の言語にはなかった考え方でキモイ

というものをインストールしていく
```powershell:npxのインストール
npm install -g npx
```
これでさっきのコードを入力してプロジェクトを作成する。

# 開発サーバーの起動
いろいろ準備が整ったところでサーバーを作ろうmy-next-appフォルダに移動してそこで以下のコードを実行する
```powershell:開発サーバーの起動
cd my-next-app
npm run dev
```
これで実行できた。最後に http://localhost:3000 にアクセスしてnext.jsのページが表示されたら成功。

# 最後に
開発環境の整備がかなり気持ち悪いがコード単体で見れば簡単なので頑張ろう
iPhoneから得られる端末情報があてにならない

タイトル通りです。

不具合の報告を受け「どれ、ユーザーエージェント情報は……」と思って確認すると、「iPhone9」と書いてありました。

でも、iPhoneシリーズって8の次X(10)なんですよね。
* [なぜ歴代iPhoneにはiPhone2とiPhone9がないのか？ - iPhone Mania](https://iphone-mania.jp/news-268228/)

じゃあこの人の使ってる端末は何なのか。
実は、「**iPhone7**」です。

たどり着いたのは以下の記事。

* [iPhone iPad 端末での 一般名と内部名の対応表 #iPhone - Qiita](https://qiita.com/YumaInaura/items/31838a72678fa09d7e19)

以下は一部抜粋です。
| 一般名 | InternalName |
|-------|--------------|
|iPhone 6s	|iPhone8,1|
|iPhone 6s Plus	|iPhone8,2|
|iPhone SE	|iPhone8,4|
|iPhone 7	|iPhone9,1|
|iPhone 7	|iPhone9,3|
|iPhone 7 Plus	|iPhone9,2|
|iPhone 7 Plus	|iPhone9,4|
|iPhone 8	|iPhone10,1|

~~6が8名乗ってんの控えめに言ってカス~~
たまたまiPhone9がなかったから気付けたけれど、
知らなかったらiPhone8のことiPhoneXと思い違いしたままになるところでした……

参考に記載されているリンクには記事にないXS以降とかも記載があります。
* [Models - The iPhone Wiki](https://www.theiphonewiki.com/wiki/Models)

**Identifier**が識別用の文字列ですね。
Identifierだけ見たらiPhoneXはiPhoneXRよりiPhone8に近いんでしょうか？
ホームボタンがなくなっても内部的にはマイナーバージョンアップなの……？？
発表した日ベースのナンバリングなん……？？

 * [歴代iPhone（初代からiPhone 15）を比較！発売日や当時話題になった特徴は？ | 家電小ネタ帳 | 株式会社ノジマ サポートサイト](https://www.nojima.co.jp/support/koneta/129368/)

 あくまで「どんくらい古いスマホ使ってるのかなー」程度にしか使わないので、正確な情報を求めているわけではないものの、売り出してる名前と内部的な識別子が一致していないのは気持ち悪さがありますね。

 iOSのバージョンの方が重要なのかも……？？
* [iOS・iPadOSバージョン別の対応機種一覧 | アールケー開発](https://www.rk-k.com/archives/5533)

iPhoneなんも分からん……

ちなみに不具合の原因にどのiPhone使ってるかは関係なくて端末の言語設定の問題でした。
[toLocaleString()の罠 #JavaScript - Qiita](https://qiita.com/mito_droste/items/040183b12b46300ef8f9)

不具合調査は普通に生きてたら知らなかったような知識が得られたりして楽しいですね、結局iPhoneなんも分からんままですが。

### 参考
* [なぜ歴代iPhoneにはiPhone2とiPhone9がないのか？ - iPhone Mania](https://iphone-mania.jp/news-268228/)
* [iPhone iPad 端末での 一般名と内部名の対応表 #iPhone - Qiita](https://qiita.com/YumaInaura/items/31838a72678fa09d7e19)
* [Models - The iPhone Wiki](https://www.theiphonewiki.com/wiki/Models)
* [歴代iPhone（初代からiPhone 15）を比較！発売日や当時話題になった特徴は？ | 家電小ネタ帳 | 株式会社ノジマ サポートサイト](https://www.nojima.co.jp/support/koneta/129368/)
* [iOS・iPadOSバージョン別の対応機種一覧 | アールケー開発](https://www.rk-k.com/archives/5533)
Reactでコンポーネントを作成してみる

# はじめに
こんにちは、Webエンジニアの岩田史門([@SI_Monxy](https://x.com/SI_Monxy))です！
今回はReactのコンポーネント作成について記事を書いてみました！
改善点や修正点があれば、コメントにて優しくご指導いただけると嬉しいです！

# 概要
Reactを使って、最初のコンポーネントを作成し、簡単なUIを構築する方法を学びましょう。

# コンポーネントの作成
Reactでは、コンポーネントはJavaScriptのクラスまたは関数として定義されます。まずは、シンプルなテキストを表示するコンポーネントを作成してみましょう。

``` jsx
// HelloWorldComponent.jsx

import React from 'react';

class HelloWorldComponent extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, World!</h1>
        <p>This is my first React component.</p>
      </div>
    );
  }
}

export default HelloWorldComponent;
```

このコンポーネントでは、Hello, World! という見出しと、簡単な説明文が表示されます。

# UIの構築手順
## Reactプロジェクトのセットアップ
最初に、Reactのプロジェクトを作成し、必要なライブラリをインストールします。以下は、プロジェクトのセットアップ例です。

``` bash
npx create-react-app my-react-app
cd my-react-app
```

## コンポーネントの作成
上記のように、コンポーネントを作成します。コンポーネントは、UIの部品として機能し、他のコンポーネントと組み合わせて使います。

## コンポーネントの組み合わせ
複数のコンポーネントを組み合わせて、より複雑なUIを構築します。各コンポーネントは再利用可能で、独立してテストすることができます。

# 参考
- [React公式ドキュメント](https://ja.react.dev/)
【2024マラソン38】markdownAIで、Qiitaマラソン記事のまとめページを作った

# 何の記事？
 Qiitaマラソンはまとめページが存在しないので、markdownAIでまとめページを作ってみました。

# できたもの

https://mdown.ai/content/6dec8cdc-7cd6-41d2-b78e-f2e0dc556de9

# 感想
こういった Qiitaでまとまっていない記事や、 markdown記事に色をつけて装飾したい場合に便利だと思いました。
本来だと、cssを勉強して、テーブルもタグを書いて……となるところが、cssさえ引っ張ってくれば装飾をつけられるのが良かったです。

# 参考

https://mdown.ai/content/6dec8cdc-7cd6-41d2-b78e-f2e0dc556de9

https://qiita.com/c9h11o2/items/cf7b9b9f4bb37e4b5ff7
【リモートワーク】周りに認めてもらうために

# はじめに
対面で会話しながらの方がコミュニケーションは取りやすいことには同意だが、今の時代場所が異なる人と仕事をするのは割と当たり前なので、リモートワークでも当然同じだけの成果が求められる。

会社に出社しても結局他の場所で働いている人達と仕事することも多いので、
オンラインミーティングは必須だしチャットツールなども必須となる。

このような状況だと、いつも以上に成果が見えづらい状況になりやすい。

では、このような状況で、客や上司から高く評価されやすくするためにはどうすれば良いのか？
について記載していこうと思う。

# 実践してみたこと
### 報告の徹底
開発戦略的に個人の報告の場は毎日あったので、実施済みのタスクは漏らさず報告。
ただし、必ず事前に管理ツールなどのチケットとかに自分の進捗状況を記載した。

そんなの当たり前だろ？
と思うかもしれないが、色んな人に見られることを恐れているのか意外と皆んな書かない
(少なくとも私のチームではその傾向がある)
そのため、他との差異にもなるなと思い私は積極的に記載しました。

口頭で報告する場合は、
記載した上で報告の場でチケットを開き要約した内容を報告(口での報告は簡潔に)

※🤩報告の仕方は私の過去記事参照
　https://qiita.com/H_Stephen/items/18eef0a57d84cae7ce49

### 誰かの困り事
チームメンバが多いと、誰に聞いて良いのか分からず、全体宛に聞いてしまうことがあります。

これ、ぱっと見問題は無さそうなんだけど、割と誰も回答してくれないんだよね。。
何故なら、バイネームで指名されてないから、スルーでまあ良いか、ってなっちゃう

こういう場合は、積極的に首突っ込みました。
割と私のスキル的に大体なにかしら知っていることが多かったということもありますが、自分自身の作業もこなしつつ、首を突っ込む。

そうすると、必ずしも解決できなかったものもありますが、
少なくとも位置的に近いリーダーの目には必ず止まります。

かつ、自分のタスクはキッチリこなすと、
１コーダーの立ち位置からテックリードやテクニカルなマネージャー層にランクアップしやすい利点もある。

一時期大体の困り事に首突っ込んでましたが、つまらない内容がほとんどです。
こういう系はあんま面白く無い内容で、且つ面倒な困り事が無い
(面倒じゃなければ自己解決してるよ、ってことなので)

しかし、この問題をら解決しないと前に進まない割と困った状況なので、サポートすると結構有り難られる。

※🤩つまらない仕事に対する考え方は私の過去記事参照
　https://qiita.com/H_Stephen/items/16a2c1912a65b5bce3af

ちなみに、これは何も評価されるためにやってたわけではありません。

チームメンバが多い場合、コミュニケーションは偏りがちなので色んなエンジニアと会話して、お互いに良い経験ができれば良いと思ってました。
　→困った😅→サポート→解決→同じようなことがあったらすぐに解決に導ける　or 私以外の人がサポートできることになります。

また、解決できたら困ったといった人に資料作成を促し、こんな感じでナレッジをコツコツ積み上げて開発効率を少しでも上げたかった、というのが狙い。

### 今ちょっと良いですか？
っていう類の聞かれ方をされた場合は、MTGなど無い限り即答で 大丈夫やで！　としています。
考え方としては、以下な感じです。

❌　自分のタスクが増える　→ ヤダ😖

ではなく、

⭕️  他の異なるエンジニアと会話する機会が増え、
　　自分にとっても知らなかったことを知る機会にもなるし、チームにとってもプラスになる

といった感じ。

チームなので、自分のタスクだけやってりゃ良いってことにはやりません‼️こらは間違いなく。
これを単なる割り込み作業と捉えるか、必要なタスクでスキルアップに繋がるしやったるぜ！、
っていうのだと全然違うと思う。

### ペアプロ
相談の延長線上でペアプロに突入することもあります。
これも緊急タスク、MTGなど無い限り基本一緒にやる方向で動きます。

時間が足りなさそうであれば、時間区切って別の時間帯で再開するとかでも良い。
すぐ突っぱねるのではなく、やり方はいっぱいあるんだから前向きに一緒に解決しようとしてます。

# こういう活動をする上で大事なこと
自分のタスクをスケジュールにパンパンに詰めないこと。
常にある程度の余裕を持つようにしています。

残業嫌いだし、早く帰って子供に会いたいので！
そのため、周りをサポートし自分の評価を上げつつ周りからも有り難られる、かつ自分のタスクをキッチリこなせば自然とリーダーやもっと上の役職者からの評価が勝手に上がります。

※🤩私が記載した"スケジュールの立て方"については以下過去記事参照
　https://qiita.com/H_Stephen/items/0d3da7bae17334df71a7

 以上
TypeScript入門：基本的な型付けと基礎文法

# はじめに
こんにちは、Webエンジニアの岩田史門([@SI_Monxy](https://x.com/SI_Monxy))です！
今回はTypeScriptの基礎文法について記事を書いてみました！
改善点や修正点があれば、コメントにて優しくご指導いただけると嬉しいです！

# 概要
TypeScriptはJavaScriptのスーパーセットであり、静的型付けをサポートするプログラミング言語です。JavaScriptの機能に加えて、型アノテーションやインターフェースなどの機能が追加されています。

# 型の基本
TypeScriptでは、変数や関数の引数、戻り値に対して型を指定することができます。これにより、コードの安全性や可読性を向上させることができます。

## 基本的な型
``` typescript
// 数値型
let num: number = 10;

// 文字列型
let str: string = "Hello, TypeScript!";

// 真偽値型
let flag: boolean = true;

// 配列型
let arr: number[] = [1, 2, 3];

// オブジェクト型
let obj: { id: number, name: string } = { id: 1, name: "Alice" };
```

# 関数の型付け
``` typescript
// 引数と戻り値に型を指定
function add(x: number, y: number): number {
    return x + y;
}

let result: number = add(3, 5); // resultは8となる
```

# 型エイリアスとインターフェース
TypeScriptでは、型の再利用性を高めるために型エイリアスとインターフェースを利用します。

## 型エイリアス
``` typescript
// 複数の型を組み合わせて新しい型を定義
type ID = number;
type Username = string;

let userId: ID = 1;
let username: Username = "bob";
```

## インターフェース
``` typescript
// オブジェクトの型を定義
interface User {
    id: number;
    name: string;
    age?: number; // オプションパラメータ
}

let user: User = { id: 1, name: "Alice" };
```

# 型の推論
TypeScriptは型推論も行いますので、明示的な型指定が必要な場合以外は省略することができます。

``` typescript
// 型推論により、numは自動的にnumber型となる
let num = 10;

// 配列の初期化時に型を推論
let arr = [1, 2, 3]; // arrはnumber[]型となる
```

# 参考
- [TypeScriptドキュメント](https://www.typescriptlang.org/docs/)
「Composeの基本レイアウト」のメモ#8 ~ホーム セクション - スロット APIの実装~ 

### [9. ホーム セクション - スロット API](https://developer.android.com/codelabs/jetpack-compose-layouts?hl=ja#8)
+ 作成した`LazyRow`,`LazyHorizontalGrid`を同一のページに表示する
    + 空のUI（slot）を提供するslotAPIを使用する
+ 作成したコンポーザブルの最後のパラメータにラムダを受け取る`content`を追加する
+ `content`引数に渡されるのが

#### 最小構成
```Kotlin
@Composable
fun HomeSection(
    @StringRes title: Int,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
){
    Column(modifier){
        Text(stringResource(title)),
        content()
    }
}

//呼び出し時
 HomeSection(R.stirng.align_your_body){
     // ここで呼び出した関数が、contentに渡される
     AlignYourBodyRow()
 }
```

#### Text()の微調整
+ テキストのベースラインと上部の間の間隔は`40.dp`
    + `modifier.paddingFromBaseLine(top = 40.dp)`
+ ベースラインと要素の底部の間隔は`16.dp`
    + `modifier.paddingFromBaseLine(bottom = 16.dp)`
+ 水平方向のpaddingは`16.dp`
    + `modifier.padding(horizontal = 16.dp)`
【Qiita Engineer Festa 2024】たった25日間で38記事を書いて思うこと

# はじめに
この記事は[Qiita Engineer Festa 2024](https://qiita.com/official-campaigns/engineer-festa/2024)の完走感想記事です。~~(語呂いいですね)~~

https://qiita.com/official-campaigns/engineer-festa/2024

Qiita Engineer Festa 2024、みなさんお疲れ様でした。

私はこの記事が38記事目で、晴れて完走することができました🎉
楽しかったしキツかったし嬉しかったです。

# きっかけ
そもそもこの短期間で38記事を書くことになったのは私の不用意な発言からでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/c16cba3c-9cc8-1a31-8f86-2af58738a3f1.png)

元々はハーフマラソンで手を引くつもりでしたが、思った以上にorganizationの順位が伸びてしまって、「どうせならフルマラソン完走してやろう！！」となったわけです。

どうせならみんなでグッズ貰いたいですもんね

私は文章をスラスラ書けるタチではないのでこの短い期間で完走するのはなかなか過酷でした。
もっと早くに気付きたかった。


# 感想
この Engineer Festa を通じて、いくつかの重要な気づきがありました。

まず、驚いたのは organizationの順位が想定以上に伸びたことです。
最初は控えめな目標を立てていましたが、他のメンバーの努力と運に恵まれていたおかげか、予想を大きく上回る伸びを見せてくれました。
ほんとにびっくり

当初は完璧な記事を目指そうとしていましたが、時間的な制約もあり、不完全でも取り敢えずアウトプットすることも多々ありました。
記事の内容は完璧でなければいけない気がしたのですが、意外なことに伸びる記事も多くあって需要があることが分かりました。

完璧を求めるあまり発信をためらうよりも、不完全でもアウトプットすることって重要なんですね。

ただ一つ問題があって、[しなさんの記事](https://qiita.com/CinnamonSea2073/items/52e558363a4f3c3dbe57#%E3%81%84%E3%81%A4%E3%81%A7%E3%82%82qiita%E3%81%AE%E3%81%93%E3%81%A8%E3%82%92%E8%80%83%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)でもあったように日常でもQiitaのことばかり考えてしまう病になってしまいました。
こわいですね。

しかしながら、この短ーーーーーい執筆期間は、私にとって自分の知識の整理や新しい学びの機会にもなったように思います。
記事を書くために調べ物をする中で、今まで気づかなかった視点や情報に出会うこともあり、とても刺激的な経験でした。

このQiita Engineer Festa 2024は私にとって挑戦であり、成長の機会でもありました。
完走できてほんとによかったです。


# さいごに
無事に38記事書いて完走することができました。
目標以上のことができて嬉しかったです。
みなさん、本当にお疲れ様でした。そしてありがとうございました！

次やるときはちゃんと準備して挑みたいな～～～～～。

それでは。
ラズベリーパイのIPアドレス固定をGUIから設定する

## はじめに
こんな記事を書いていてなんですが、**ラズパイ側で固定IPの設定はしない方がいい**みたいです。DHCPを制御する**ルータ側で設定するのが望ましい**んだとか。それについては以下の記事に書いています。

https://qiita.com/mochi_2225/items/3abcc45db6378e7dbb17

この記事は、それでも大学や社内の環境で簡単にはルータはいじれないって方に向けてのものになります。

## 背景
ラズパイが手元に来たら、とりあえずSSH接続しやすくするために**IPアドレスを固定する**のが定石かなと思ってその方法を調べていました。

ただ、ネットでヒットする方法を試してみても、どうもうまくいきません。大体の方法は **`/etc/dhcpcd.conf`を編集する**、とのことだったのですが、このファイルがそもそも見当たらないです。

色々調べてみると、参照する記事のほとんどではWi-Fiの設定に`dhcpcd`が用いられていましたが、2023年10月にあったRaspberryPi OSの更新から、**デフォルトのWi-Fiの設定にはNetworkManagerというものを使うようにOS自体が変更**になったようです。そのため**IP固定の設定方法も大きく変わっていた**とのことでした。

以下の記事などNetworkManagerを使ったCLIでの設定についてまとめられている記事もありましたが、まだ情報も少なく理解するのが大変そうだなーと思っていました。

https://raspida.com/nmcli-static-ipaddress/

そこで、そもそも**CUIを使わずにGUIで設定できる**のでは？と思い実際にやって見たところ、比較的簡単に設定できたのでこの記事ではその方法をまとめます。

## GUIでIPアドレスを設定
一旦、手動でWi-Fiに接続します。そして、画面右上のWi-Fiのアイコンから、赤枠で囲んだ「Advanced Options」 => 「Edit Connections」と選んでいきます。

![raspi_gui_ip_1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351104/59b5bdb4-1c20-c7e8-5a8b-77dc2dd04381.jpeg)

そしたら、以下のようなウィンドが開かれるので、接続するWi-FiのSSIDを選択して、下部の歯車マーク「Edit the selected connection」をクリックします。

![raspi_gui_ip_2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351104/eddf3895-a4b1-0914-312b-97819e82249c.jpeg)

そうすれば以下のような設定画面が表示されたかと思います。この中の「IPv4 Settings」のタブを開きます。

![raspi_gui_ip_3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351104/6e8fc7f8-816e-f88e-a292-e3c8873fa69a.jpeg)

設定項目としては、はじめMethodの箇所が`Automatic (DHCP)`のようになっているかと思いますので、これを`Manual`にします。そうしたらその下の`Address`の箇所で`Add`のボタンを押し、左から順に設定項目を入力していきます。設定項目は以下のとおりです。

- `Address`：自身の固定IPアドレス
- `Netmask`：ルータのサブネットマスク
- `Gateway`：デフォルトゲートウェイ（一般的にルータ自身のIPアドレス）

`Address`は固定したいIPを設定してください。`Netmask`と`Gateway`がわからない場合は、次の手順で確認ができます。

今度は画面右上のWi-Fiのアイコンから、赤枠で囲んだ「Advanced Options」 => 「Connection Information」と選んでいきます。

![raspi_gui_ip_4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351104/5ce64846-f477-9302-be22-2a112137061b.jpeg)

そして表示されたウィンドウの、「Subnet Mask」と「Default Route」の値が該当の箇所に入力する内容です。`Gateway`の入力内容が上記の画像ではCIDR表記の`24`となっていますが、`255.255.255.0`のようなアドレス表記でも入力できました。

![raspi_gui_ip_5.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351104/ea64c6ce-0611-3b68-8d6f-90be980fa879.jpeg)

これでラズパイを再起動すれば、設定したIPアドレスになったかと思います。

## 参考

https://raspida.com/nmcli-static-ipaddress/
booleanに変換

 ```ts
 /**
 * 入力値がブール値または文字列 'true' であるかを確認し、ブール値を返します。
 *
 * @param value - ブール値に変換する値。
 * @returns 入力値に基づくブール値。
 */
export const toBool = (value: string | boolean) =>
  value === 'true' || value === true
```

意外と便利なので投稿しました。
migrationで不整合を防ぐ

# はじめに
昨日コーディングインタビューにて「migrationファイルにおける不整合データの対策について」を問われた際にパッと答えることができなかったので、ここで供養していく。

# 問題
以下のようなテーブル定義のmigrationファイルがあった際、どのようにして不整合データの対策をしていくかといった内容。(以下Ruby on Railsのmigrationを例に)
``` ruby:
  def up
    create_table :follows do |t|
      t.references :follow_to, foreign_key: { to_table: :users }
      t.references :follow_by, foreign_key: { to_table: :users }
      t.timestamps
    end
  end
```
よくあるsnsのユーザーフォローの機能のテーブルをイメージしていただきたい。
followsテーブルとusersテーブルは1:Nの関係になっている。

## どんな不整合が起こりうるか
思いつくのは存在しないユーザーとの関連データ/欠損データ/重複データの3つ。
- 存在しないユーザーとの関連データ
    - 外部キー(follow_to,follow_by)に出鱈目なユーザーのidを格納することで生じるデータ
- 欠損データ
    - 外部キー(follow_to,follow_by)にnullが格納されることで、必要なリレーションが欠損したデータ
- 重複データ
    - フォローしたユーザーとされたユーザーの組み合わせが同じなレコードを複数存在させたデータ
## どうやって対策するのか
- 存在しないユーザーとの関連データ
    - 上記migrationは既に対応済みではあるが、外部キー制約を付与することで存在するユーザーのみを格納するようにする(referenceやadd_foreign_key)
- 欠損データ
    - NOT NULL制約をすることで、不完全なデータを作成しないようにする
- 重複データ
    - follow_to,follow_byの組み合わせにindexを追加して、重複データが作成されないようにする

上記の対策を施したmigrationは以下のようになる。
``` ruby
  def up
    create_table :follows do |t|
      t.references :follow_to, null: false, foreign_key: { to_table: :users }
      t.references :follow_by, null: false, foreign_key: { to_table: :users }
      t.timestamps
    end
    add_index :follows, %i[follow_to_id follow_by_id], unique: true
  end
```