OmniAICreator/Qiita-1.07M huggingface dataset:
KubernetesでnamespaceがTerminatingのまま消えない時

# namespaceが消えない
sock-shopを使っていたら，不具合が起きたのでnamespaceごと削除した時，以下のエラーが出力された！

```
:~$ ks delete -f complete-demo.yaml
Warning: deleting cluster-scoped resources, not scoped to the provided namespace
namespace "sock-shop" deleted
```
deleted以降何も表示されず仕方なく中断をすると
以下のような状態になる
```
~/sock-shop/microservices-demo/deploy/kubernetes$ kubectl get ns
NAME                 STATUS        AGE
default              Active        38d
kube-node-lease      Active        38d
kube-public          Active        38d
kube-system          Active        38d
prometheus           Active        124m
sock-shop            Terminating   93m
system-upgrade       Active        38d
```

「monitoring」と「sock-shop」がterminatingのままになっている．
これを削除しないと新規の同じnamespaceが作成できない．

# 削除方法
削除方法は2通り考えられる．
1. terminatingをひたすら待つ
1. kubernetesの設定をいじる．

## kubernetesの設定をいじる
https://www.redhat.com/sysadmin/troubleshooting-terminating-namespaces
を参考に作業を行う！

行ったコマンド
削除したいnamespceをjsonファイルに書き込む
```
$ kubectl get namespace ${NAMESPACE} -o json > tmp.json
```
エディターでtmp.jsonファイルを編集し，finalizer配列のkuberntesを削除
```
$ vi tmp.json
```

kubernetes APIサーバへのプロキシを開放する←後の作業でcurlコマンドを実行するためバックグラウンドで実行
```
$ kubectl proxy &
```

反映させるために以下のコマンドを実行
```
$ curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json http://127.0.0.1:8001/api/v1/namespaces/${NAMESPACE}/finalize
```
Sassで色の管理をする(使い方・色の略称など)

# 色について
## Sassで色を管理するとき
https://qiita.com/manabuyasuda/items/ae42db5604cd723fb3cd

## Visual Studio Code で Sassを使うとき
https://blanche-toile.com/web/vscode-live-sass-compiler


## カラーの略称

DK：ダーク
LT：ライト
BL：ブルー
BR：ブラウン
GR：グリーン
GY：グレイ
OR：オレンジ
PI：ピンク
PU：パープル
RE：レッド
WH：ホワイト
YE：イエロー

▼略称が2文字、3文字など、複数で確認する
https://dereremit.jp/archives/102

▼もっと多くの色を確認する
http://www.angle-japan.com/cc.htm
基本情報対策：科目B「単方向リスト」

今回は単方向リストの解説についてこちらの教材、予想問題①科目B：問8で
解説していこうと思います。すでに購入された方向けとなりますので、
ご理解ください。
![B0BR3DJW3X.01.S001.LXXXXXXX.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698835/5bf1c650-05eb-9477-73be-0910729d98f8.jpeg)
かんたん合格 基本情報技術者予想問題集 令和5年度
　

<h2>なぜこの問題を解説するのか</h2>
・twitterのフォロワーの方のツイートを見て自分も同じ内容で理解できない部分があった為、この機会にどのような処理になっているのか理解するために解説することにしました。

<h2>問題のポイント</h2>
・この問題を解くためにはまず「単方向リスト」について知っておかなければなりません。

※問題集の解説を見たらある程度分かると思います。

・ただしく問題を理解する
　今回紐解いてみて見落としていた部分がたくさんあったのでそちらをふまえて解説します。


<h2>解説</h2>
まずは小さなところから順を追って紐解いていきます。

※問題については載せられない為、手元の教材を見ながら進めてください。

処理の流れについて解説します。
①関数appendが文字列を引数に取り、発火します。
②ListElement型: prev,currが宣言される。
③currがコンストラクタ(qval)で文字列valを格納する。
④条件分岐、trueの場合currがlistHeadに格納される。
⑤条件分岐、falseの場合、prevにlistHeadが格納される。
⑤-①　繰り返し処理、prev.nextが未定義ではない場合prevにprev.nextが格納される。
⑥prev.nextにcurrが格納される。


<h5>②,③prev,currの役割について</h5>
　ここで宣言されるprev,currがどのように使われるのか詳しく見てみるとcurrはコンストラクタを用いて初期化を行っており、新しい要素を格納する変数ということが見て取れます。prevについて、prevはlistHeadを格納しており、参照を取得しているよう見て取れる。その為prevはlistHeadを直接操作しない為の一時変数のような役割だと理解しました。
<hr>
<h5>④listHeadにcurrを格納する</h5>
　条件分岐の中で行う操作を考えた時, ListHeadにcurrを格納する操作をしている。格納する場合のケースとしてどのような場面が考えられるかというと、先頭に要素が何もない場合(つまり未定義の場合)に格納しなければならないと推測ができると思います。※PGの方なら未定義の参照はExceptionが発生すると言ったら理解できるかもしれませんね。
よって問題aについては未定義である場合にtrue判定にする必要があると理解できると思います。
<hr>
<h5>⑤prevにlistHeadを格納する</h5>
　まず前提としてlistHeadとはについてですが、大まかにグローバルな変数と理解しました。なのでlistHead自体をそのまま操作可能かと思いますが、あえてprevに格納する手順が記載してあります。※プログラミングのお作法で直接データ操作を行うのはご法度だった気が...。
<hr>
<h5>⑤‐① prev.nextが未定義ではない場合にprevにprev.nextが格納される</h5>
　こちらは④とは逆になり、既にlistHeadには１つ以上のデータが存在する状態だということになります。なぜこの操作を行う必要があるのかというと、単方向リストの一番最後にデータを格納したい=未定義にデータを格納する為、一番最後の要素にアクセスする手順を踏んでいるいるということになります。
<hr>
<h5>⑥prev.nextにcurrが格納される。</h5>
　ここが僕も理解できなかったポイント。当時の僕はcurr.nextを選択していたと思います。答えとしてcurrが正解になるのですが、それについて理解するにはデータ構造に着目する必要がありました。prev.nextにはどんな参照を入れなければならないのかについて考えます。上の表にはLisrElementが持つ変数等の記載あると思います。そちらのnextの型を確認するとListElement型を格納すると記載がありました。(僕の見落としポイント)型が分かればあとは答えがわかるはずです。今回、単方向リストの末尾に追加したい要素は引数qvalの値、すなわちcurrに格納されていることがわかりました。またcurrはListElement型で定義がされており、currそのものを格納する必要があると理解しました。(再起処理みたいなイメージで考えたらわかりやすいかも...)
<hr>



以上が解説になります。
分からないことがあれば質問してください。
木苺も萎れきた

3年前に購入した Raspberry Pi 3 model B+、当初は Chromium ブラウザも VSCode もなんとか動いたけど今はもう重すぎて無理。

Jellyfin メディアサーバーと、一日一回のモデムのリセットにしか使っていない。でも それだけでも価値がある。
Dr.Sumのインポートとリビルド

# はじめに
Dr.Sumではインポートコマンド・バッチ（dwtab_import）を使って
外部データを取り込むことができます。
インポートやテーブルデータの更新方法によっては繰り返し処理することでテーブルが断片化するため、
断片化した場合にテーブルの再構築・リビルドで解消する方法について紹介します。

:::note info
補足
本記事の内容・キャプチャ等はDr.Sum Datalizer Ver.5.6のものです。
設定方法など詳細は[公式Dr.Sum Datalizer Ver.5.6 マニュアル](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-db492be6-586e-85ba-b530-0b183d4f8648.html)を参照してください。
:::

# インポート方法の種類
Dr.Sumでは外部データを取り込む方法がいくつかあります。
 - Dr.Sum Enterprise Managerを使う
　- インポートウィザード・仮想テーブル（vtb/vtfファイル）を使って外部データベースやCSV/Excelファイルを取込
　- インポートタスクからタスクを作成してCSV/Excelファイルを取込
 - インポートコマンド（dwtab_import）を使う
　- コマンドをバッチ化して外部データベースやCSV/Excelファイルを取込

また、インポートコマンド（dwtab_import）とデリートコマンド（dwtab_delete）を組み合わせて、必要な年月分のデータを選択的に入れ替えることもできます。

:::note info
補足
詳細は公式マニュアルを参照してください。
・[Dr.Sum Enterprise Managerのインポートタブ](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-0fa4a842-00f4-4f1e-b9a7-c4b2b3eceadf.html)
・[デリートコマンド（dwtab_delete）](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-eab17478-800f-26fc-e24b-d1830abd5b9e.html)
・[インポートコマンド（dwtab_import）](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-acf63819-e010-3b0c-553b-4a65694a9888.html)
・[コマンドのバッチ化](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-fbc944ce-bc78-1a70-7132-2a721e4b97e1.html)
:::

# インポートモードの種類
いずれの方法でインポートする場合でも、インポートモードを選択できます。
既存テーブルにデータをインポートする場合に主に使用するのは下記の２つです。
 - テーブル内の行を削除してインポート
既存データをすべて削除してからインポートするモード
 - テーブルに行を追加
既存データは消さずに追加でインポートするモード

:::note info
補足
「テーブルを新規に作成してインポート」するモードもありますが、バッチなどで定期的にインポートする場合は上記のいずれかのモードで既存テーブルを更新することがほとんどだと思います。
また、「キーが重複したらアップデート」のモードもありますが、DataLoaderのセットアップなどが必要となります。
詳しくは[公式マニュアル](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-5ddfb001-991a-46c7-3f69-3cb0973d4b24.html)を参照してください。
:::

# テーブルの断片化とリビルド
デリートコマンド（dwtab_delete）とインポートコマンド（dwtab_import）を使ってインポートモード「テーブルに行を追加」でバッチなどを使い部分的なデータの入れ替えを繰り返し実行するとテーブルの断片化が発生します。
断片化が進むとパフォーマンス劣化や容量の肥大化などの影響が出るため、定期的にテーブルのリビルド・再構築を行って断片化を解消することをお勧めします。
（なお、インポートモード「テーブル内の行を削除してインポート」でインポートした場合やtruncateコマンドを使ってデータを全件削除してインポートした場合は断片化は起きないはずです。）

# リビルドの種類
Dr.Sumのリビルドには「完全リビルド」と「簡易リビルド」の２つがあります。
完全リビルドは後述の通り実行時の影響が大きいため注意が必要です。
 - 完全リビルド
　　テーブルを構成する物理ファイル（CRXファイル・DATファイル）をすべて再構築します。
 - 簡易リビルド
　　テーブルを構成する物理ファイルのうちDATファイルのみ再構築します。

:::note warn
完全リビルドの実行時の影響
再構築中は対象テーブルをロックするため、当該テーブルを参照することができない時間が発生します。また、件数が多い場合は相応の時間がかかることが見込まれます。　
※リビルドの実行時間は行数、項目数やユニーク制約のある項目の数などにも影響されますが、具体的な実行時間を事前に算出するのは難しいです。
:::

:::note info
補足
・CRXファイル：カーディナリ分のデータを格納しているファイル。テーブルからレコードが削除されてデータ上ではカーディナリが低くなっても再構築しないとカーディナリは変わらない。
・DATファイル：カラム毎に各レコードとCRXファイルで管理しているIDを紐づけるデータを格納しているファイル。テーブルからレコードが削除されても再構築しないとファイル上は物理削除されない。
詳しくは公式マニュアルを参照してください。
　[テーブルの物理構造](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-4d171043-249f-dccd-35a0-6ee79af64937.html)
　[テーブルを再構築（リビルド）する](https://cs.wingarc.com/ja/howto/dr_sum/19496?brand=dr_sum&service=6136&scenario=6142)
　[テーブルの再構築のタイミングを判断するには](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-4369b72d-37ef-8d1e-0a59-292cc8fb8f02.html)
:::

# リビルド方法

テーブルの再構築・リビルドはEnterpriseManagerから実施する方法とコマンド（dwtab_rebuild）で実施する方法があります。
具体的な操作手順は[公式マニュアル](https://cs.wingarc.com/manual/drsum/5.6/ja/UUID-fc9ab144-cd37-1bae-fceb-da704357186f.html)を参照してください。
microSD規格

# カード規格
・保存容量
|規格     |最大容量|
|:----:   |:------:|
|miroSD   |2GB     |
|miroSD HC|4~32GB  |
|miroSD XC|64GB~2TB|

# スピードクラス
・転送保証速度。これ以上速度が出る事を保証しますよ、という事。
・4種類(Class2, Class4, Class6, Class10)
|Class|最低書き込み速度|
|:---:|:------------:|
|Class2|2MB/s        |
|Class4|4MB/s        |
|Class6|6MB/s        |
|Class10|10MB/s      |

# UHS(Ultra-High Speed)
・Bus Interface
・最大転送速度
|UHS  |最大転送速度|
|:---:|:---------:|
|UHS-1|104MB/s    |
|UHS-2|312MB/s    |
|UHS-3|624MB/s    |

# UHS(Ultra-High Speed)スピードクラス
・最低転送速度
・U2は存在しない。
|U    |最低転送速度|
|:---:|:---------:|
|U1   |10MB/s     |
|U3   |30MB/s     |

# ビデオスピードクラス
・最低書き込み速度の保証
・動画撮影用の機器向けに策定された規格
|V  |最低速度|用途  |
|:-:|:-----:|:----:|
|V6 |6MB/s  |SD|
|V10|10MB/s |HD/FHD|
|V30|30MB/s |2K/4K|
|V60|60MB/s |4K/8K|
|V90|90MB/s |8K|

# アプリケーションパフォーマンスクラス
・最小ランダムアクセス速度
・アプリの起動時間や読み込み時間に影響

(R):Read
(W):Write
IOPS(Input Output / sec):1秒間にI/Oアクセス出来る数。
|A  |最小ランダムアクセス速度(R)|最小ランダムアクセス速度(W)|シーケンシャル最低処理速度|
|:-:|:-----------------------:|:-----------------------:|:----------------------:|
|A1 |1500IOPS                 |500IOPS                  |10MB/s                  |
|A2 |4000IPOS                 |2000IOPS                 |10MB/s                  |
デフォルトモードのAzure SignalR ServiceをWebアプリとFunctionsで共用する

## 知りたいこと
Azure SignalR Serviceのマニュアルを見ると、Functionsを接続する場合はサーバレスモードのSignalRを使ってね、と読める。下記が両立するのかを知りたい

* WebアプリとFunctionsでSignalRを共用したい
* Webアプリ側は通常のハブプログラミングモデルを使いたい

## やったこと
* SignalRのインスタンスをデフォルトモードで作成
* WebアプリとしてAppService上に[これ](https://github.com/aspnet/AzureSignalR-samples/tree/main/samples/ChatRoom)をデプロイ
* Functionsを[これ](https://learn.microsoft.com/ja-jp/azure/azure-signalr/signalr-quickstart-azure-functions-csharp)をもとに作成

Functionsのコード
```C#
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

namespace FunctionApp1
{
    public static class Function1
    {
        //メッセージ送信
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            [SignalR(HubName = "chatsamplehub")] IAsyncCollector<SignalRMessage> signalRMessages,
            ILogger log)
        {

            //メッセージを送信　お試しのため内容は固定値
            await signalRMessages.AddAsync(
                new SignalRMessage
                {
                    Target = "BroadcastMessage",
                    Arguments = new[] { "name", "message" }
                }
            );

            string responseMessage = "done";

            return new OkObjectResult(responseMessage);
        }

        //ネゴシエート
        [FunctionName("negotiate")]
        public static SignalRConnectionInfo Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
            [SignalRConnectionInfo(HubName = "chatsamplehub")] SignalRConnectionInfo connectionInfo)
        {
            return connectionInfo;
        }
    }
}

```

## 結果

### ネゴシエート
接続用のトークンが取得できている→OK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77403/1bfd5c3d-3da8-543d-c31f-aeec087362a3.png)


### メッセージ送信
実行成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77403/f70cadc1-48b0-9008-f0cd-23bf49576b83.png)

ほかのクライアントでメッセージをちゃんと受信できている→OK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77403/2e5ab1f3-613d-d197-8a93-ec736163f099.png)

## わかったこと考えたこと
デフォルトモードのSignalRにFunctionsから接続し、メッセージを送ることができた
→Webアプリがサーバ側としてSignalRに継続して接続している場合は、デフォルトモードのSignalRが使えるが、サーバ接続がない場合は、サーバレスモードを使わないといけない、ということかもしれない。
同時に二箇所弄っちゃダメ

メインのデスクトップマシンは大分古く、最近は起動(OSでなくハード)しないことがある。そうするとたまにBIOS設置も消えたりする。

そんななか、昨日は久しぶりに Linux カーネルを再構築。今まで使っている 4.5.75 は最近のコンパイラでビルドできない。そもそも 4.5 に留まっているのは、物凄く古い Nvidia グラフィックカードを搭載して、それ用のドライバが 4.5までしか対応してないから。

4.5系統最新の 4.5.249を問題なくビルドできた。

それが、起動して見ると kernel panic - no init found だと。つまり、ルートデバイスが見つからない。まあ、しようがないかと思い、現行の 4.5.75で起動すると... こっちも同じ症状。どう言うことだ、これは。古い方は全然弄ってないのに。

ようやく分かったのが、 BIOS でハードディスクを AHCI にするする設定が消えて、デフォルトの ATA に戻ってた。(このマシン古いって言ったろう？)

AHCI に設定したら古いカーネルも新しいカーネルも起動した。カーネルの問題じゃなかった。
インフラエンジニアって？

# はじめに
この記事は「インフラエンジニア」って知ってるけどさらに細かい分野やら仕事は曖昧だな・・・と感じた私の頭を整理する為のものです。
ネットで調べるとたくさんの情報が出てきますのでそれらを解釈して自分が分かるように纏めてみようと思います。

### そもそもインフラって？
インフラ整備とかよく聞くけどどういう意味？って聞かれたら一瞬フリーズしてしまう・・・
インフラ→人々の生活を支える基盤を意味する言葉。公共施設、ガス、水道、電気などなど・・・確かにそれか一つでも無くなったり停止したら生活崩壊するなこりゃ。
そして近年、ネットワーク環境も重要なインフラの一つとして挙げられている。
確かに私自身、ネットを使わない日は無い。朝起きてSNSチェックするのが日課になってしまっているので・・・

そんな大切なインフラの一つ、ネットワーク環境の設計、構築、保守、運用を行うのが「インフラエンジニア」ってワケ。なるほど。
大枠は掴めたので細かい分野に視点を移してみる。

#### １.サーバーエンジニア
名前のまんま、サーバー関連の業務が主。
ネット上でよく使われる「鯖落ち(サーバーがダウンした状態)」。鯖落ちした時に復旧作業にあたるのも主にこの方々だそうな。
チケット・グッズ争奪戦の度にサーバー復旧お疲れ様です・・・
要は「サーバーに関することならお任せ」って事。分かりやすい。

#### 2.ネットワークエンジニア
これも名前の通り、ネットワークに関する事・・・でもネットワークって枠組み広すぎやしないか？と言うことで調べてみた。
ルーターやLANで電子機器を繋いでネットワーク環境を構築し、保守・運用する専門家。って事っぽい。
Wifiとか無線LANとかよく聞くよね・・・普段当たり前のように使っているインターネットが使えるのはこれらのネットワークが機能しているから。
PCと向き合ってダカダカコード書く！ってよりはルーターなどの実機を触る機会が多いのがネットワークエンジニアの特徴かな？　周辺機器への知識は人一倍ありそう。
最近はスマホと家電をネットで繋いで操作できる！って物、かなり増えてきたけどこのあたりも担当領域に入っている予感。スマホ一台で簡単便利！の影にネットワークエンジニアさんあり。

#### 3.データベースエンジニア
何をするにしてもデータが保存されないと始まらない！って事で、データを保存したり取り出したりするデータベースの保守・運用がメイン業務であるエンジニア。
面白いこと思いついた！後で見返す為にメモアプリに残しておこう・・・あれ、このメモアプリ保存できないんだけど？なーんて事があった日には大惨事。
あ、これ欲しかったやつ！とりあえずカートに入れておいて後で購入しよう・・・あれ、さっきカートに入れたはずなのに無いんだが！？保存されてなかったの！？・・・カートの底抜けとるなんて思わんやん。
こんな感じでどのアプリにもWEBサービスにも「データベース」って必要不可欠な存在。
これから先、様々な電子化が進んでいけばデータの保存は非常に重要。インフラエンジニアの中でもシステムの核に近い場所のお仕事。

#### 4.セキュリティエンジニア
サイバー攻撃やウイルス感染を防ぐ機器やシステムを構築・導入しトラブルを未然に防ぐ事がメインのエンジニア。
最近、ニュースでウイルス感染によって顧客データが何万人分流出、とか聞くとヒェ・・・ってなるんだけど、それらを未然に防ぐ、再発を防ぐために頑張る方々です。
企業サイドからしても顧客の情報はかなり敏感にならないといけない部分なので注目度、需要共に高い分野。

### まとめ
インフラエンジニアって一言で言っても色々あるんだなぁと。
とりあえず各分野の上辺をさらってみただけなので浅い・・・と感じられるでしょうがご容赦ください。
それぞれの分野によって持ってたら役立つスキルや資格も違いそうなのでこれからも調べていくつもりです。
エンジニア志望してまだ1年経ってないひよっこなので認識の齟齬や間違いがあれば教えて頂けると嬉しいです。
[Servicenow]PDIへのアクション方法

メモ程度です。

PDIへアクションを行いたいとき（例えば、Demoデータを削除したいとき）は、以下の方法で行える。

1. Developerサイトへアクセスする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636124/6bf67ca7-53b9-3d0b-ba4d-90ab638bdc26.png)


2.画面右上の自分のアイコンをクリックし、行いたいアクションを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636124/3f8cea35-c65d-1a8e-fdf3-48901994fbb2.png)
教師からエンジニアに未経験から転職して感じたこと

# 自己紹介
* 27歳
* 受託開発企業にてweb開発をメインに行なっています
* 開発言語
    * React.js(Next.js)
    * Python
    * Java
* 資格
    * ITパスポート
    * 基本情報
    * AWS CCP
    * Salesforce Platform Developer

Twitter
https://twitter.com/js_manabitai

## キャリア
* March文系卒
* 2年間高校教師として勤務
* 1年間ほどニート
* 現在エンジニア２年目


# 転職のきっかけ
はじめにプログラミングを触ったのは教師時代にspreadsheetで情報を管理しており、GASを使って業務を効率化したいと思ったのがきっかけです。

そのため、Javascriptをまずは勉強し始め簡単な通知機能や自動化ツールなどを作成しました。
それが評価されたことが嬉しくてプログラミングを学びたいと思い、仕事が終わってからドットインストールでJavascriptを使用した簡単なwebアプリを作ったり、Vue.jsを使用してWebアプリを個人開発しました。

この頃、組織の中でSX化が進んでいきプログラミングをできる人が重宝され管理職になりやすい傾向が感じられました。

そこで、単純な私は「これからはどんな仕事においてもプログラミングが求められる！」と感じ、それならばプログラミングを仕事にして学びたいと思いました。

## 転職活動
その後訳あって教師を退職し、1年間ほどニートしたのちにエンジニアとしての就職活動を行いました。

Vue.jsとFirebaseを使ったポートフォリオを３つほど用意し、合計10社ほどエントリーしました。

転職エージェントや転職サイトなどいくつか登録しましたが、Paizaでの求人が自分には一番良かったです。(ランクはB)

書類落選: 5社
面接落ち: 3社
内定: 2社

未経験だったので、転職可能かどうか不安でしたが当時25歳ということもあり、ポテンシャル採用という結果で内定をいただくことができました。

年収もボーナス込みで500~600万円ほどを提案していただき、未経験エンジニアとしては破格の条件で採用されたかと思います。


# エンジニアとしての働き方

## 最初の半年間

最初の半年間は未経験ということもあり、右も左もわからない状況で全く役に立てなかったことを悔しく思ってます。
業務はエクセルにスクリーンショットを貼り付けるだけという、ほぼ社内ニート状態でした。

「これではまずい」と感じ、基本情報を取得したり、個人開発を頑張ったりしましたが、プロジェクトにはあまり貢献できませんでした。

## 半年後〜１年後
その後簡単なHPの作成やSalesforceの開発、Pythonでのニューラルネットワーク構築などコードを書く仕事を経験でき、少しづつですが、エンジニアとしてのキャリアを歩み始めてきているなと感じています。

# 学び

ここから先をたくさん書いたのに、記事の投稿時になぜかすべて消えてしまったので、復元方法を調べています。
Windows機でPython開発環境を構築

会社の勉強会の教材としてWindows機でPython開発環境を構築し記事として残す。
　※初学者向けとするため、出来るだけ分かり易い方法で行う。

**今回、構築する物**
　Visual Studio Code
　Python ３系

**記事制作時の動作環境**
　Windows 10 Pro　22H2

**手順**
<H4>Visual Studio Code のインストール</H4>
Windowsスタート　→　Microsoft Store　で、ストアを起動する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/e91d55bd-cf88-9f34-5d7e-7bc6bc7c3199.png)

検索ワード入力欄に「 __visual studio code__ 」と入力して🔍押下する。
Visual Studio Code が表示されるので［**インストール**］を押下する。
　※以降、「Visual Studio Code」は「VSCODE」と表記します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/380421a3-2714-ba24-2bab-7d86d4eb29b6.png)

インストールが完了したら、VSCODEを起動する。
※画像では検索から起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/9e6aa17a-3a34-a37c-7966-b518ba878474.png)
<H5>VSCODEにPythonをインストール</H5>

VSCODEの拡張機能タブアイコン押下で検索タブを表示して、入力欄に __Python__ と入力して、候補の中からPythonを選択し、[__インストール__]押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/70b6dd37-490d-d5a3-7217-8602c00f0eae.png)

<H4>実行用のPythonをインストール</H4>

Microsoft Store　から「 __Python__ 」を検索してインストールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/21786d27-8dda-9b14-9560-b895cb64c8d5.png)

インストールが済んだらDOS窓で確認します。
Win+R でファイル名指定実行を開いて「__cmd__」を入力して[__OK__]押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/910ba2c5-24aa-291d-e174-44359d22dd54.png)

下記のDOS窓で「python」と入力し[enter]、インストールできていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/7582e06c-9c07-37d9-083a-2e7113a1b159.png)

<H4>Pythonの動作をVSCODEで確認</H4>

VSCODEメニューの　ファイル　→　新しいファイル　で「__test.py__」を作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/9951506d-0154-c0e2-e2ec-54deea535106.png)

テストのための簡単なコードを入力する。
`print('test')`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/f4f8a5a0-0918-4bbe-d891-4d59046040a5.png)

メニューから　表示　→　出力　を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/8482dc55-f2e7-964f-d0f9-bbabf96e619c.png)

実行ボタンとデバッグのタブアイコン押下し、[__実行とデバッグ__]押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/4ebff27c-3266-325d-766b-8fa2768e6066.png)

「Pythonファイル　現在アクティブなPythonファイルをデバッグする」押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/d71eb43e-24da-1426-876d-6188abe4fc2e.png)

「Pythonインタプリタの選択]押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/797d6c5b-9891-14ae-1b3e-e43d4b3583e4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/a7fb7324-5a46-27e8-ff8a-533c05edc039.png)

以下の様に出力パネルのターミナルに「test」と表示されていればPython開発環境の構築は成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/69527775-8e9b-16e4-7a7e-57757074ce43.png)
Java 基礎の基礎

# はじめに
- Javaの学習を始めたので、備忘録としてまとめる
- 基礎の基礎からしっかりと

# 学んだこと
- パッケージ、クラス、メソッド
- 基本的なデータ型
- インポート宣言

# パッケージ、クラス、メソッド
### パッケージ宣言
```java
package jp.hogehoge.javastudy;
```
>ポイント
・クラスやインターフェイスをグループ化するしくみ
・名前の衝突を避けるため、できるだけユニークに命名する

### クラスの生成
```java
クラス 変数名 = new クラス名 (引数)
```
>ポイント
・クラスを作る（＝javaのプログラムを作る）
・クラス = フィールド（データを格納） + メソッド（処理の記述）

### メソッドの定義
```java
　アクセス修飾子 その他修飾子 返り値タイプ メソッド名（引数）
```

```java:例
public static void main(String[] args) 
```

>アクセス修飾子
・public「他のクラスからアクセス可」
・protected「同一パッケージ内　継承クラス」
・なし「同一パッケージのみ」
・private「同一クラス内のみ」

>その他の修飾子
・adstract「抽象クラスメソッド」
・static「クラスから直接呼び出せる」
・final「変更できない」
など

>voidメソッド
戻り値がないメソッド

>args
一般的に使われるが、別の引数でも良いらしい

つまり、例のmainメソッドは、
```java:例
public static void main(String[] args) 
```
・他のクラスから main メソッドにアクセスでき
・クラス自体に紐づいており、インスタンスを作成せずに直接呼び出すことができ
・メソッドが戻り値を返さず
・最初に呼び出される特別なmainメソッド
といったところでしょうか。

# 基本的なデータ型
### 整数
- byte「8bit 8桁の2進数」
- short「16bit 16桁の2進数」
- int「32bit 32桁の2進数」
- long「64bit 64桁の2進数」
###### よく使うのはint

### 実数
- float「32bit」
- double「64bit」
###### よく使うのはdouble

### 文字
- char「16bit 1文字」
###### Stringはデータ型ではない
###### 文字列はクラスで扱う

### 真偽値
- boolean「8bit true or false」

# インポート宣言
別のパッケージに所属するクラスやインタフェースを使用するために必要な宣言のこと。

```java:例）Scanner クラス
import java.util.Scanner;
```
>補足
・別のパッケージに所属するクラスやインタフェースを使うために「参照する」という意味
・インポート宣言を使用すると、別のパッケージにあるクラスやインタフェースの名前を省略して使うことができる
・コードの可読性を向上させることができる

# まとめ
- 1つ1つ理解を深めたい
- パッケージ、インポート宣言について理解が浅いため、まだまだ学習を深めたい

⚠️学習4ヶ月目の初学者による投稿です。
⚠️間違いがあるかもしれません。ご容赦ください。
⚠️ご指導、ご教授いただけると幸いです。
初めてのpythonで静的解析・コード整形

## Python開発環境に初めてコード整形ツールを導入
業務では最近主にNode.jsを使っており、Eslint, Prettierの使用経験はありましたが、最近使い始めたPythonのコードについては全く静的解析ツールやコードフォーマッターを入れていないので、VSCodeの開発環境に導入していきます

## 導入するプロジェクトの概要
### ディレクトリ構成
```
(root)
┣ app/
┣ docker-compose.yml
┣ Dockerfile
┣ poetry.lock
┗ pyproject.toml
```
### 導入するツール
#### 静的解析
- flake8
- mypy
#### コード整形
- black
- insort

それぞれのツールに関する説明は[こちらの記事](https://zenn.dev/alivelimb/articles/20220501-python-env#%E9%9D%99%E7%9A%84%E8%A7%A3%E6%9E%90%E3%81%A8%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%82%BF%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B)で丁寧に説明されていたので詳しくはリンク元を見てください🙇

## 手順
poetry導入済みのDocker環境が作成されていることが前提になります。
今回docker-composeを使っています。

```
docker-compose exec poetry app add flake8 -D
docker-compose exec poetry app add black -D
docker-compose exec poetry app add insort -D
docker-compose exec poetry app add mypy -D
```

## 除外したいエラーをVSCode上でignore
1. VSCodeの画面左下のSettingsを開きます
2. 「flake8」で検索し、Python › Linting: Flake8 Argsに除外したいエラーの規約番号を`--ignore`のパラメータに渡します
```
--ignore=E501
```

## 良かったこと
静的解析で不適切な箇所を事前に発見し、かつコードが綺麗になるのはもちろん良いのですが、最初静的解析を入れていない状態でコードを書いていたので入れた瞬間にエラーが出まくり、知らないPythonの規約を知れたので良かったです
Pythonのassertを使いこなしたい

# アサーションとは
アサーション(assertion)とは、**プログラムが期待する条件で動いているかチェックする機能**のことです。

アサーションを適応することで条件外の挙動が起きた時にAssertionErrorが出力され、デバッグしやすくなるといった特徴があります。

## if文との違いは？
if文ではエラーチェックを行えますが、アサーションとの違いは何でしょうか？

エラーチェックは**ユーザーや外部システム**による**予期しない入力や挙動を処理**し、アサーションは**開発者**がコードの振る舞いについて**設定した前提条件を確認するため**に使用されます。

アサーションはプログラムのバグチェックに使えます。アサーションを使うことで早期にプログラム上の重大な欠陥を見つけ出し、修正するのに役立ちます。

# 構文
基本的には`assert`の後ろにチェックしたい式を記述します。
~~~python
assert expression
~~~

また、カンマ区切りで任意のエラー文を出力できます。
~~~python
def check_age(age):
    assert age >= 0, "Value Error"
    
    return age

check_age(-1)
# Value Error
~~~

# 注意点

## `assert`はデバッグ目的に使用する
基本的にはコードに欠陥がないか開発やデバッグフェーズで利用するものです。運用時には例外処理などのエラーハンドリングを行います。

## `assert`の無効化
Pythonの実行オプションである`-0`や`-00`を用いることで`assert`文は無視されます。これは`assert`が
~~~python
if __debug__:
  if not expression: raise AssertionError
~~~
と等価であるためです。組み込み変数`__debug__`は通常`True`ですが、最適化が要求された場合(`-0`, `-00`)、に`False`となります。

## 常に`True`となる`assert`
assert文にタプルを渡したとき、空でなければ常に`True`となります。したがってタプル内に変数を渡してチェックさせようとした時、常に`True`と判定されることになります。

~~~python
x = 2
assert (x == 1 , "xに1以外の値が入ってます")
~~~
テストケースを作成するときに気を付けないといけないですね。ただしPython3では`SyntaxWarning`を表示してくれます。

# 参考サイト

https://codezine.jp/article/detail/12179

https://docs.python.org/ja/3.10/reference/simple_stmts.html#the-assert-statement

https://note.nkmk.me/python-assert-usage/

https://it-biz.online/python/assertion/
RailsのDelegateを理解する

# はじめに
Ruby on Railsを使ったプロジェクトに配属され、Railsを学び始めた新卒エンジニアです。コードを読む中で、見慣れないDelegateメソッドを見つけたので調べてみました。
本記事の対象者はRubyやRailsの初心者、オプジェクト指向プログラミング初心者向けの記事となっています。修正点や改善点などがあればコメントまでお願いします。


# Delegateとは
あるオブジェクト（一般的にはモデルオブジェクト）から別のオブジェクトへのメソッド呼び出しを委譲するために使用されます。[定義に関してはこちら](https://github.com/rails/rails/blob/7-0-stable/activesupport/lib/active_support/core_ext/module/delegation.rb)


```ruby: delegateの定義
delegate :カラム名, to: :委譲先のオブジェクト名
```
また、委譲できるメソッドは複数追加することが可能です。

```ruby: 複数のメソッドの委譲
class Order < ApplicationRecord
  belongs_to :customer
  delegate :name, :address, :phone_number, to: :customer, prefix: true
end
```
上記では、OrderモデルはCustomerモデルのname、address、phone_numberメソッドを同時に委譲しています。

DelegateメソッドはRailsアプリケーションの中であれば、特別な設定やインクルードなしに自動的に利用できます。しかし、Ruby on Railsを使わない純粋なRubyのプログラムでは、ActiveSupportライブラリを明示的にrequireして、該当のクラスでextend ActiveSupport::Concernを行う必要があります。
```ruby:Ruby(Railsを使わない場合)
require 'active_support/core_ext/module/delegation'

class MyClass
  extend ActiveSupport::Concern
  # delegateメソッドを利用可能
end

```


# 具体例
CustomerとOrderの間の一対多の関係を示す図で、一人のCustomerが複数のOrderを持つ例を考えてみます。

```sql:具体例
  +-------------+     +-----------------+
  |  Customer   |     |   Order         |
  +-------------+     +-----------------+
  | - id        |<---　　| - id            |
  | - name      |     | - product_name  |
  | - created_at|     | - product_price |
  | - updated_at|     | - quantity      |
  |             |     | - customer_id   |
  +------------+      | - created_at    |
                      | - updated_at    |
                      +-----------------+

```



### Delegateを使わない場合
```ruby:Ruby
class Customer < ApplicationRecord
  has_many :orders
end

class Order < ApplicationRecord
  belongs_to :customer

  def customer_name
    customer.name
  end
end

order = Order.first
puts order.customer_name
```
customer_nameメソッド内で明示的にcustomerオブジェクトのnameメソッドを呼び出しています。



### Delegateを使って変更した場合
```ruby:Ruby
class Customer < ApplicationRecord
  has_many :orders
end

class Order < ApplicationRecord
  belongs_to :customer

  delegate :name, to: :customer, prefix: true
end

order = Order.first
puts order.customer_name 

```
delegateを使うことでOrderオブジェクトから**直接**customer_nameメソッドを呼び出すことができます。このcustomer_nameメソッドは、Orderオブジェクトに関連づけられたCustomerオブジェクトのnameを返します。


### prefixオプション
Delegateメソッドを使用してメソッドを委譲するとき、prefixオプションを指定することで、そのメソッド名に接頭辞が追加されます。この接頭辞は、委譲されるメソッドがどのオブジェクトから委譲されているのかを明示的に示すために役立ちます。


```ruby: prelixをつけない場合
class Customer < ApplicationRecord
  has_many :orders
end

class Order < ApplicationRecord
  belongs_to :customer
  delegate :name, to: :customer
end

order = Order.first
puts order.name 
```
この方法では、CustomerのnameメソッドがOrderに直接委譲されているため、order.nameという表記でCustomerのname属性にアクセスできます。

上記だと、order.nameがOrder自体のname属性を指しているのか、それとも委譲されたCustomerのname属性を指しているのかが一見してわからないため誤解を招く可能性があります。そのため、Delegateメソッドのprefixオプションを使用して、委譲されたメソッド名に接頭辞を追加します。これにより、委譲元のオブジェクトが明確になり、コードの可読性が向上します。


# まとめ
今回はメソッドの委譲をする際に用いるdelegateについて調べました。delegateを使用することでコードの可読性や保守性も向上するため、積極的に使っていきたいです。

# 参考

https://railsguides.jp/active_support_core_extensions.html#delegate
C言語で指定された添字の整数を出力する方法

# 注意！
・ネタバレあり。

https://atcoder.jp/contests/abc255/tasks/abc255_a

# 学んだこと
・二重ループのiとjの使い方
・添字は0から始まる。

# ACしたコード
```C
#include <stdio.h>
int	main(void)
{
	int	r,c;

	scanf("%d%d",&r,&c);
	// printf("%d %d\n",r,c);
	int a[2][2];
	// iは縦に使う
	for (int i = 0; i < 2; i++)
	{
		// jは横に使う
		for (int j = 0; j < 2; j++)
		{
			scanf("%d",&a[i][j]);
			// 標準入力から受け取れているか確認
			//printf("%d ",a[i][j]);
		}
		//printf("\n");
	}
	// 添字は0から始まるので問題文のrとcをそのまま指定するとズレるから-1する必要がある。
	printf("%d\n", a[r - 1][c - 1]);
	return (0);
}
```
GASで作ったサイトの読み込みが遅い件について

## 本題に入る前に
弊社では一部の部署でフリーアドレス制をとっています。
ところが「誰がどこに座ってるかわからん！」という指摘が多く困っていたので助けてあげることにしました。
そこで無料で簡単に使えるWebプロトタイプの王である「GAS」で座席管理システムを作りました。（勝手に呼んでるだけ）
最初は弊部のみでやっていましたが、噂が流れ別部署に導入したり、最近はフロア一体に導入になりました。

## 実はそんなに乗り気じゃない
システム作って使われるというのはエンジニアにとって非常に嬉しいことなのですが、そんな楽観的になれない理由があります。


* 保守運用がワンオペ
    * 一人で空き時間にえっちらおっちら作っていたので、ここまで規模が大きくなることを想定していませんでした。
    * GAS（JS）が分かる人がいない、学びたい人がいないため詰んでます。
※良い子は無計画でシステムを作っちゃダメだぞ☆
* あくまでプロトタイプ
    * セキュリティ周りはガバガバです。（漏れて困る情報はないので問題ないともいえる
    * 将来的にはAWSとかクラウド使ってきっちり作りたいので、ここがゴールではないです。~~止まるんじゃねぇぞ~~
    * コードもある程度のリファクタリングにしています。（完全にリファクタリングする時間がない）
   

* UX的にイマイチ（納得してない
    * 座席にQRコードを貼って、カメラで読み込み、メールアドレスを入力してもらって着席ボタン・・・長いわ！！！
    * O365入れてるのでPowerAppsとかでちゃちゃっとできれば楽ちん♪と考えてます。
    * 要らないスマホとか置いて顔認証して完全オートで着席管理するのが夢です。

## さて本題
説明した通り、性能試験とかそんなものしてませんし、やったテストは単体テストと遷移テストぐらいです。
全フロア対応をしたところ、やたら座席の表示が遅いことに気付きました。
流石に「うぬぅ」って声が出るくらいのレスポンスだったので優先度高で対応することにしました。

## 確認したこと
* for文と呼び出しレスポンス周りにログを仕込む
    * for文がネスト構造（多重ループ）になると処理が遅くなるため、コードを要チェックします。
    * レスポンス投げるところで呼び出しがおかしかったりする可能性があるので確認します。
→一か所怪しいところがあったので書き直しました。

* スプレッドシートから取得/書き込み部分の洗い出し
    * スプレッドシートが絡むと処理がかなり遅くなります。←今回の原因はこれ
    * メソッドで切り出していたりすると気づかない場合があるので確認します。

## 原因と対策
原因は「**for文で毎回スプレッドシートを読み込み**」に行ってました。
ﾔﾗｶｼ～
座席とメンバーの情報の部分だったので、変更がない限り初期のタイミングでしか取得しないように変更しました。
たったこれだけで解消しましたｗ（皆さん笑ってください。

## まとめ
決してGASの処理は速くありませんが、スプレッドシートを模擬DBとして使ってサイトを作ったり、チューニングによっては普通のサイトと謙遜ない速度で処理ができたりするので便利です。
もっと腕を磨かなくては・・・
【SwiftUI】インスタのかっこいい背景色を再現する

# はじめに
インスタにかっこいい背景があったのでSwiftUIで再現してみます

![IMG_3400.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/239c42ca-90a6-f8d1-f327-4e3d8bc885cd.png)

# 実装
```swift
import SwiftUI

struct GradationBackgroundView<T: View>: View {
    @ViewBuilder var content: () -> T

    var body: some View {
        ZStack {
            LinearGradient(gradient: Gradient(colors: [.orange, .purple, .cyan, .blue, .green, .yellow]), startPoint: .topLeading, endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
            Rectangle()
                .foregroundStyle(Material.ultraThickMaterial)
                .edgesIgnoringSafeArea(.all)
            
            content()
        }
    }
}
```

# 使い方
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        GradationBackgroundView {
            ScrollView {
                VStack {
                    ForEach(0..<100) { _ in
                        Text("テスト")
                    }
                }
            }
        }
    }
}
```

# 完成
![simulator_screenshot_8561EA9E-2C22-4A48-A795-7D273F452E22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/560ab35f-fbde-85f9-f586-a2ec7249a0bc.png)

# おわり
結構再現度高いと思います！
Python_Bottleフレームワークで静的ファイルのルーティング設定をする

PythonのBottleフレームワークを使用してcssファイルのルーティングを設定したが、
うまくいかなかったので解決策をメモ。

## ディレクトリ構成
app
├ bottle.py
├ process.py
│
├ public
│   └index.html
│
├ static
│   └style.css


## cssが読み込まれなかった時のコード
```test.py
# cssファイルを設定する
@route('/static/<filepath:path>')
def server_static(filepath):
	return static_file(filepath, root='./')  # root=どこのパスを設定するのか不明
```

```index.html
<link rel="stylesheet" href="static/style.css">
```

## cssが読み込まれない原因
static_file関数の第二引数である`root`はどこまでのパスを書けば良いかわかっていなかった。

## 原因の解決方法
rootは'/'の場合、.pyファイルが置かれた場所のことを言う。
今回はstyle.cssの場所を設定しないといけないため、`./static/` が正しい。


## 参考サイト
https://qiita.com/tomotaka_ito/items/377b2287e71ecd8b4f16
http://kitabatech.blogspot.com/2014/07/bottle.html
https://bottlepy.org/docs/dev/tutorial.html#request-routing
Scan to Salesforce/Pardot を使ってみた感想


# まずはインストールでの不思議。

日本語のページは以下ですが、ここからはうまくインストールできませんでした。

https://appexchangejp.salesforce.com/appxListingDetail?listingId=a0N3A00000G0yJkUAJ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c224e597-be22-39ab-965b-983b8a150e07.png)


英語の環境からアクセスしてもインストールまでたどり着けないですね。

https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000G0yJkUAJ

仕方ないので、英語版をインストールします。

https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FeFeJUAV

無事インストールできました。　日本語の文字もきちんと認識してくれます。素晴らしい。

# 読み込んだ名刺の変換

取引先については、会社名で既存の取引先を検索しているようです。
ただ、弊社の場合カタカナが半角（基幹システムの桁数の関係で...）また株式会社を㈱で登録していることも多いので一致しないんですよね。会社名を既存の取引先と同じようにすれば問題ないんだけど...

画面フローで類似した取引先名を検索してユーザに選択してもらうことにします。

あああ、カスタム画面なので編集できないですね。
仕方ない、ユーティリティーバーから画面フローを起動して、最後にアップロードしたレコードだけを取得して処理することにします。

起動させるボタンはカスタムコンポーネントで作成（本当はこの画面に配置したかった...）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a451ca86-4292-6400-6d96-7ac27d9cf89a.png)

起動直後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1358f916-b63e-ba49-2cfb-b90578fdeda7.png)

ここで問題ユーティリティがそのままだと邪魔なんですよね。
フローを起動する前に最小化したいけど...

あったよ。方法が

+ [How to auto-close utility window?](https://developer.salesforce.com/forums/?id=9062I000000IGYIQA4)

いいねぇ、思ったように動きました。
crontab -e

crontabで自動実行の設定する
crondプロセスが常駐している。こいつが自動起動をスタートさせる
```
root       1293  0.0  0.0 126420  1724 ?        Ss   09:05   0:07 /usr/sbin/crond -n
```
自動起動ルールの修正
```
crontab -e
```
毎時45分にsample.shを実行
```
45 * * * * /home/linuxstudy/sample.sh
```
x時45分、自動的に処理が動き出す
```
メールが /var/spool/mail/linuxstudy にあります
[linuxstudy@localhost ~]$  less /var/spool/mail/linuxstudy
```
```
From linuxstudy@localhost.localdomain  Tue Jul 11 16:45:03 2023
Return-Path: <linuxstudy@localhost.localdomain>
X-Original-To: linuxstudy
Delivered-To: linuxstudy@localhost.localdomain
Received: by localhost.localdomain (Postfix, from userid 1000)
        id C074223087AC; Tue, 11 Jul 2023 16:45:02 +0900 (JST)
From: "(Cron Daemon)" <linuxstudy@localhost.localdomain>
To: linuxstudy@localhost.localdomain
Subject: Cron <linuxstudy@localhost> /home/linuxstudy/sample.sh
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
Precedence: bulk
X-Cron-Env: <XDG_SESSION_ID=65>
X-Cron-Env: <XDG_RUNTIME_DIR=/run/user/1000>
X-Cron-Env: <LANG=en_US.UTF-8>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/linuxstudy>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=linuxstudy>
X-Cron-Env: <USER=linuxstudy>
Message-Id: <20230711074502.C074223087AC@localhost.localdomain>
Date: Tue, 11 Jul 2023 16:45:02 +0900 (JST)

#!/bin/sh -v
    echo "this is sample.sh"        //sample.sh実行結果
this is sample.sh
```
[React] stateとは？(state使い方)

# state

<br><br>
**react**で**state**は本当に重要です。
**state**は一体何でしょうか？

<br><br>

簡単に言えば変数と似た意味です。
**state**に値を保存して使用することです。

<br><br>

まず宣言からしてみます。
```react
import { useState } from 'react';
import './App.css'

function App(){
  let [a,b] = useState('hello world');
  return (
    <div className="App">
    </div>
  )
}
```

<br><br>

**useState**を書くと
```react
import { useState } from 'react';
```
が自動的にインポートされます。

<br><br>

一番重要な宣言部ですが
```react
let [a,b] = useState('hello world');
```
従来のジャバスクリプトとは異なる姿を見ることができます。
aには「hello world」が入ることになり、
bにはbを設定する関数が入ります。（この部分は後で説明します。）

<br><br>

もっと直観的にコードを書いてみると
```react
let [name, setName] = useState('kimura');
```
これですね。

<br><br>

これをnameで呼び出します。
```react
function App(){
 
  let [name, setName] = useState('kimura');
  return (
    <div className="App">
      <div>
        <h4>{ name }</h4>
      </div>
    </div>
  )
}
```
<br><br>

#### 出力結果
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509555/6f1919bc-9ccc-00b8-1bb1-7ae90e9b88d2.png)

<br><br>

## なぜstateを使うのか
普通のletに入れて使うのと同じに見えますけど
なんでわざわざ面倒くさくstateを使うんだろう。

その理由は**自動再レンダリング**のせいです。

stateを使うとstateの中にある変数が変わると自動的に反映されます。

頻繁に変わる名前ならstateに入れておいた方がいいです。
(リンクだけです)「ArgandDiagram(アーガンド図)」を調べてみたい。

オリジナル?

https://github.com/osnove/other/blob/master/complex_plane.py

https://mathworld.wolfram.com/ArgandDiagram.html

https://www.web-dev-qa-db-ja.com/ja/python/matplotlib%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E8%A4%87%E7%B4%A0%E6%95%B0%EF%BC%88%E3%82%A2%E3%83%BC%E3%82%AC%E3%83%B3%E3%83%88%E5%9B%B3%EF%BC%89%E3%82%92%E3%83%97%E3%83%AD%E3%83%83%E3%83%88%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/1041168212/

# google検索

https://www.google.com/search?q=%E2%80%9D%E3%82%A2%E3%83%BC%E3%82%AC%E3%83%B3%E3%83%89%E5%9B%B3%E2%80%9D&rlz=1CAUHAM_enJP1038JP1038&sxsrf=AB5stBhNlaEnfzxMWSctnoEe82nrsph9gQ%3A1689060527629&ei=rwStZN2DJsTQ1e8PxIWv0AM&ved=0ahUKEwidl4PmkIaAAxVEaPUHHcTCCzoQ4dUDCA8&uact=5&oq=%E2%80%9D%E3%82%A2%E3%83%BC%E3%82%AC%E3%83%B3%E3%83%89%E5%9B%B3%E2%80%9D&gs_lp=Egxnd3Mtd2l6LXNlcnAiGOKAneOCouODvOOCrOODs-ODieWbs-KAnTIFEAAYogQyBRAAGKIEMggQABiJBRiiBDIFEAAYogQyBRAAGKIESJRVUPoSWJ5McAZ4AJABAJgByAGgAfsJqgEFMi44LjG4AQPIAQD4AQHiAwQYASBBiAYB&sclient=gws-wiz-serp
【Snowflake】select文で返す結果のデータ型を確認する

## はじめに
小ネタです。
SQLの結果が今あなたは何型で返してくれてるんでしたっけ？と確認したいときが、稀によくあると思います。（ない？）

## 確認方法
system$typeof()関数を使うことによりSELECT文で確認が可能です。
``` sql
select 'test',system$typeof('test'),
        3.3/3,system$typeof(3.3/3);
```
（実行結果）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2964512/a1ea2e03-0ccb-bbe4-1346-dcb4ddb170ea.png)


## 参考リンク
https://docs.snowflake.com/ja/sql-reference/functions/system_typeof
required initって何？

# この記事で得られる情報
この記事では以下のことについて説明しています。
- required修飾子とは何か
- required initの使い方
- required initはどういう時に使うのか
- required initがUIViewControllerなどを継承した際に強制実装されるのはなぜか

# required修飾子ってなに？

required修飾子とは、以下の特徴を持つ修飾子です。

- イニシャライザにのみ使用することができる
- required initを持ったクラスを継承したサブクラスでは、必ずrequired initを実装する必要がある

コードを見ないとピンとこないかもしれません。次で解説します。

# required initの使い方

実際には以下のように使います。

```swift
class Animal {
    var name: String

	// requiredを持ったイニシャライザを実装
    required init(name: String) {
        self.name = name
    }
}

// required initが実装されているAnimalクラスを継承
class Dog: Animal {
	
	// 親クラスで定義されているrequired initを実装
	required init(name: String) {
		super.init(name: name)
	}
}
```

# どういう時に使うの？

requiredおよび、required initの使い道は
俺を継承するなら初期化時に絶対にこれやれ！
なことを実装したい時に利用します。

先ほどのコードで説明すると、親クラスAnimalを継承したクラスは初期化時に必ず名前を設定する必要がある、ということですね。

こうすることで以下のようなメリットを得られます。

- コードの一貫性が保たれる
    - Animalクラスを継承したクラスは一貫して「名前」を持たせることになります。
- 予見可能性が向上する
    - requiredを使用せずにDogを生成した場合、名前を持たないAnimalの子クラスが生成される可能性があります。もしクラスの実装で「名前を持たないと致命的なエラーが出る！」なんて実装をしていた場合、Animalクラスでrequiredを実装していなかったせいで、防げたエラーが防げなかった、ということになってしまいます。

# required initを強制的に実装させられたんだけど…

UIViewControllerやUIViewを継承したクラスでイニシャライザを実装した時、required initも実装せえよって怒られます。

これは単純にUIViewControllerやUIViewがrequired initを実装しているからです。

この辺について、詳しくは以下の記事が参考になります。

https://qiita.com/coe/items/9723381ec0046fd8d8ad

# まとめ

required initはイニシャライザ専用のprotocolみたいな感じだと思います。

required initを使用することで、子クラスに特定の初期化処理を強制させられるので、コードの安全性を高めたり可読性も上がったりします。

以上、マニアックな修飾子「required」の解説でした〜
PCにログオンしたら必要なアプリが自動で起動できたらいいなぁ

# はじめに
ある日のこと、、、
デスクトップ立ち上げた時点でChromeとEdgeとVSCodeとOutlook勝手に起動しないかなぁ～、と思いました。

:::note info
ネタバレ：カッコつけてpythonで設定しましたが、Windowsにはスタートアップというシステムがありました(;'∀')
:::

# 方法
Windowsには「タスクスケジューラ」なるものがあり、設定したタイミングでプログラムを起動してくれます。

まずは以下のようなpythonコードを書きます。

~~~ pyton:task_startup
import subprocess

# Edgeを起動
subprocess.Popen('C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe')

# Google Chromeを起動
subprocess.Popen("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe")

# VSCodeを起動
subprocess.Popen("C:\\Users\\ユーザー名\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe")

# Outlookを起動
subprocess.Popen("C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\OUTLOOK.EXE")

~~~

:::note info
subprocessはpythonにデフォルトで備わっているので新たにインストールは必要ないです。
:::

続いてスタートメニューからタスクスケジューラを検索して起動します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/0f7a54bc-c131-71f8-b8b3-8ff0354fb774.png)

右タブの基本タスクの作成をクリックします。タスクの名前を適当に決めます。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/21f4658d-2ef7-ec11-b309-0495ce9d8e63.png)

トリガーを設定します。今回はログオン時にしました。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/e3d7391e-57a2-3492-34ab-69c908a9dfa5.png)

操作内容を設定します。pythonプログラムを動かしたいので、プログラムの開始を選択します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/26f17c46-46e8-931c-11a6-4cce52c14904.png)

プログラムのパスを指定します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/c7615ca6-0acf-f167-d31a-865f68dca152.png)

完了を押せばセット完了です。次回ログオン時に自動的に設定したアプリが起動します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/1757ef1d-73fd-9a26-4a7d-440914e38b0a.png)


# Windowsのスタートアップ
ここまでpythonでカッコつけましたが、Windowsのスタートアップを使えば簡単にできます(;^ω^)

エクスプローラー(Windowsキー+E）を開いて、クイックアクセスに「shell:startup」と入力します。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/c1746a6b-8ecd-2a54-fc9c-fa543057228f.png)

表示されたフォルダに起動したいアプリを格納したら終わりです。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/fd5c3d50-511d-00a8-10b0-3bf29c96952e.png)

# おわりに
カッコつけてpythonとタスクスケジューラを使いましたが、そんなものはMicrosoft様がすでに準備してくださっていました(ﾟ∀ﾟ)
ただ、タスクスケジューラはなんか便利そうなので活用方法は今後考えていきます。

ではまた。
Tips: CloudFrontのキャッシュをパージする方法

## この記事は何
最近CloudFrontのキャッシュをパージする必要があったので、Tipsとしてまとめておきます。

## 手順

### キャッシュ削除ページへ移動
CloudFrontのディストリビューション（`https://your-domain.aws.amazon.com/cloudfront/v3/home?region=your-region#/distributions`）に訪れます。
ページに訪れた後、キャッシュを消したいディストリビューションを選択します。

選択後、ヘッダーから「キャッシュ削除」を選択し、キャッシュ削除ページへ移動します。
（`https://your-domain.aws.amazon.com/cloudfront/v3/home?region=your-region#/distributions/your-distribution/invalidations`）

![スクリーンショット 2023-07-11 16.10.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158501/96d52d7f-1766-7a03-0fa3-fad90a2347b5.png)

### キャッシュを削除する
キャッシュ削除ページから、「キャッシュ削除を作成」をクリックすると、以下のようなキャッシュ削除をするパスを指定するフォームへ移動します。

![スクリーンショット 2023-07-11 16.12.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158501/4e33d854-41fa-d70c-b93f-907f4447a354.png)

こちらで、キャッシュを削除したいページのパスを指定することで、キャッシュの削除を行うことができます。
JavaのflatMap()とは

`flatMap()` は、Javaのストリーム操作（Stream API）で使用される中間操作の一つです。
`flatMap()` メソッドは、ストリーム内の各要素を別のストリームに変換し、それらのストリームをマージして単一のストリームにするために使用されます。

`flatMap()` メソッドは、各要素を複数の要素からなる新しいストリームに変換するために使用されるようです。
各要素に対してマッピング関数を適用し、その結果をフラット化して単一のストリームに結合します。

サンプル↓

```java
List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2, 3),
    Arrays.asList(4, 5, 6),
    Arrays.asList(7, 8, 9)
);

List<Integer> flattenedList = nestedList.stream()
   .flatMap(Collection::stream)
   .collect(Collectors.toList());

System.out.println(flattenedList);
```

この例では、入れ子になった整数のリスト `nestedList` があります。`flatMap(Collection::stream)` を使用して、各リストをフラット化し、単一の整数のリスト `flattenedList` を生成しています。

出力結果↓

```
[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

`flatMap()` を使用することで、ネストされたリストの各要素が個別の要素としてマージされ、フラット化された単一のストリームになります。

`flatMap()` は、要素をフラット化するための便利な方法です。ネストされたリストやマップなど、要素が入れ子になっている場合に特に有用です。

難しい〜
[React] 初心者なら必ず知っておくべきJSX

# JSX
<br><br>
**react**を開発した経験のある人なら、一度は聞いたことがあると思います。
<br><br>

私はいつも初心者を相手に説明するので、あまり理論的なことはさておき、理解しやすく説明します。
<br><br>


まずは**文書**です。
公式文書を探してみるのは良い習慣です。
[JSX](https://legacy.reactjs.org/docs/introducing-jsx.html)
<br><br>

結論から言えば**JSX**は**react**で使う言語です。（正確には構文拡張です）

<details><summary>より多くの情報</summary>
JSXはJavaScript XMLの略で、

ReactのようなJavaScriptライブラリまたはフレームワークでUIコンポーネントを作成するために使用される文法拡張です。 
JSXは、JavaScriptコードの中でXMLと類似した構文を使用してUI要素を作成できるようにします。

既存のJavaScriptでは、動的にDOM要素を生成したり操作したりする時、一般的にDOM操作メソッドを使用しました。
しかし、JSXを使えば、JavaScriptコードの中でHTMLと類似した文法を使ってコンポーネントを宣言して操作することができます。 
JSXは単に文法的な拡張であるため、Babelのようなツールを使用して一般JavaScriptコードに変換されて実行されます。
</details>  

<br><br>
これまでjavascriptだけで開発してきたら戸惑うかもしれませんので
たくさん使う文法と特徴をいくつか紹介します。
<br><br>



## 1. タグを変数に貯蔵できる
```jsx
const divTag = <div>hello world</div>;
```

<br><br>

## 2. 変数を中括弧で
変数を中括弧でどこにでも入れることができる。
```jsx
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
```

甚だしくはタグの属性やスタイルにも可能だ。
```jsx
const style = {
      backgroundColor: 'white',
      fontSize: '10px',
      fontWeight: 'bold'
  }

  	<div style={style}>test</div>

```

<br><br>

## 3. class -> className
タグのclassはclassNameに変更すること。
```jsx
<h1 className="greeting">
    Hello, world!
</h1>
```

<br><br>

## 4. タグを必ず閉めること。
既存のinputタグなどは閉じなくても良いが、jsxでは必ず閉じなければならない。
```jsx
<input></input>
<input />
```

これくらいが**jsx**でよく使われる文法と概念です。
Linuxにおけるファイルとディレクトリ

# 参考書籍
[新しいLinuxの教科書](https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E/dp/4797380942/ref=sr_1_1?adgrpid=117229375656&hvadid=655144332605&hvdev=c&hvqmt=e&hvtargid=kwd-1152146940662&hydadcr=21814_13461165&jp-ad-ap=0&keywords=%E6%96%B0%E3%81%97%E3%81%84linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8&qid=1688622508&sr=8-1)

# 動作環境
+ Windows11
+ Oracle VM VirtualBox
+ CentOS 7

# ファイル
+ Linux では Windows や MacOS X と同様に**情報（データ）は「ファイル」として扱われる**。
+ Linux ではハードディスクやキーボード、 Linuxカーネルもファイルが割り当てられており、**すべてがファイルとして表現されている**。

# ディレクトリ
+ ディレクトリとはファイルを整理する入れ物のことである。
+ Windows や MacOS X では「**フォルダ**」と呼ばれるものと同じである。
+ あるディレクトリの中にあるディレクトリを**サブディレクトリ**（または**子ディレクトリ**）といい、逆にあるディレクトリから見て1つ上にあるディレクトリを**親ディレクトリ**という。
<details><summary> ディレクトリ構造図の例</summary>

> `fruit`
　├ `apple`
　│  　└ `date`　
　│
　└ `orange`
>
>この例でみると`apple`ディレクトリのサブディレクトリは`data`ディレクトリ、親ディレクトリは`fruit`ディレクトリとなる。

</details>

### パス
+ あるファイルを指し示す情報のこと。
+ 各ディレクトリは`/`で区切る。（Windowsでは`\`）

</details>

#### 絶対パスと相対パス
+ 絶対パス（またはフルパス）とは、**[ルートディレクトリ][語句補足]を起点としたパス**のことである。
+ 相対パスとは、**[カレントディレクトリ][語句補足]を起点として表記されるパス**のことである。
<details><summary>パスの例</summary>

> `/`
└ `home`
&emsp;&emsp; └ `sumisumi` &emsp;&emsp; ← <strong>カレントディレクトリ</strong>
&emsp;&emsp;&emsp;&emsp;&emsp; └ `work`
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp; └ `file`
> <br>
> + `file`の絶対パスは`/home/sumisumi/work/file`となり、<br>相対パスは`./work/file`もしくは`work/file`となる。
> + `home`の相対パスは`..`となり、`/`の相対パスは`../..`となる。
> +  `.`はカレントディレクトリを表し、`..`は親ディレクトリを表す。

</details>

## 語句補足
<dt>ルートディレクトリ</dt>
<dd>
<strong>ディレクトリ構造における一番上のディレクトリ</strong>のこと。<br>
全てのファイルとディレクトリは、親をたどっていくと最後にこのルートディレクトリにたどり着く。
</dd>

<dt>カレントディレクトリ</dt>
<dd>
今現在、<strong>自分が位置しているディレクトリ</strong>のこと。<br>
<code>pwd</code>コマンドで確認でき、<code>cd</code>コマンドで変更できる。。
</dd>

# 終わりに
ディレクトリとフォルダが同義であると認識することで理解しやすかった。

次はディレクトリとファイルに関するコマンドをまとめたいと思う。

[**次回**](https://qiita.com/sumisumi2000/items/1a0d561fe4c61f961452)

何かご指摘がありましたら、コメントしていただけると幸いです。
最後までお読みいただきありがとうございました！

[語句補足]: #語句補足
ストーリーポイントはじめるためのTips

# これはなに
- 先日、なんちゃってスクラムにストーリーポイントを導入した人の話
- まあまあメリットあったものの、立ち上がりが少し大変なので、お役立ち情報をまとめておく
- ストーリーポイントとはみたいな話はよくあるが、それを実際やるとどういう難しいことがあるのか

# なにが最初大変なのか
既存のプロダクトバックログアイテム全てにポイントをつけていくのが大変。誰か一人の意見で決めてしまっても仕方ないわけで、当然みんなで話し合って決めるが最初はスクラム開発への理解度の差とかコードへの知見の差もあってかなり時間がかかる。
自分のチームのケースだと1個のアイテムだけで30分くらいかかった。

# それに対するTips
以下、実際にやってみて良かったことをつらつら書いてみる。

### 過去のポイント一覧を作る
完了したプロダクトバックログアイテムのポイントとかはどっかいってしまうので、二重管理になってもいいからバックログツールとは別にポイント一覧があると使いやすい。相対見積もりでポイントつけるので。

### プロダクトバックログアイテムを分割しまくる
そもそも適切なサイズでアイテムを作成できてれば何も問題ないが、自分のチームの場合はそんなことなかったので、これでかすぎてポイントつけれんやん→じゃあここで分割しようって話になった。

あと、すでに進行中のプロダクトバックログアイテムのポイントはどうすんの問題があると思っていて、これも(ちょっと変だが)すでに終わってる部分と未着手の部分にアイテム分割してしまうとやりやすそう。(これは試してない)

### たのしむ
大変なので楽しめてないとたぶん効果出るとこまでいかない。このポイント振る時間で実装した方が得やんとかなりそう。。

### フィボナッチ数列など→どっちでもええ
やった方がチームとしてやりやすいとかあれば。
自分のチームの場合は特に自然数での見積もりで困らなかった。

### プランニングポーカー→楽しいからやったらええやん
これもどっちでもいいけど大体楽しいので

# おまけ
ストーリーポイントの運営とか、スクラム開発のための良いツールがなくて困ってます。。
単にタスク管理とかスケジュール管理なら素晴らしいツールがいっぱいあるんですが、こうやってプランニングポーカーしようとかポイント一覧出そうとかやるといろんなツールに跨ってしまいました。
ちょうど良いのがあったらどなたか教えてください！><
Googleのお問い合わせフォームの作成

## はじめに
Googleフォームの作成をしたので
忘れないようにメモとして書き留めておきます。

## Googleフォームの作成
Googleフォーム作成では下記のサイトを参考に作成しました。
参考：[PATANO](https://www.ec-create.jp/google-forms/how-to-make/blog-contact-form/)

## Viewにリンクを表示
```ruby:
<%= link_to "お問い合わせ", "GoogleフォームのURL"%>
```
作成したGoogleフォームのURLを記載します。
これでGoogleフォームの作成が出来ました！
internlm-chat-7b をCPUで動かしてみる

internlm-chat-7b をCPUで動かしてみる

https://github.com/InternLM/InternLM

# 追加情報
V1.1が追加されてテストしていたところ推論速度が速くなっていたので
再度測定を行ったので下の記事を参照してください

https://qiita.com/winyaado/items/4776dfc04d5369952d07


# まとめ
CPUでも動作は可能だかトークンが増えると推論にかかる時間が現実的でない
モデル読み込み時RAMピークが38GB近くになるためそれ以上のメモリが必要
英語と中国語で学習しているモデルだが日本語でも簡単なpythonのコードを書くことができた


# 推論テスト
<details>
<summary>推論用コード</summary>

~~~
import torch
import time
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True).cpu()
model = model.eval()
model = model.to("cpu")
history = []

while True:
    txt = input("msg:")
    start_time = time.perf_counter()
    response, history = model.chat(tokenizer, txt, history=history)
    print(response)
    end_time = time.perf_counter()
    elapsed_time = end_time - start_time
    print(f"worktime:{elapsed_time}")
~~~
</details>

推論結果
~~~
msg:おはよう
はい、何事が欲しいですか？

msg:hello
Hello! How can I assist you today?

msg:你好
你好，有什么我可以帮助你的吗？

msg:pythonで1から10まで足し合わせるコードを書いて
以下は、Pythonで1から10までの和を計算するコードです。

```python
sum = 0
for i in range(1, 11):
    sum += i
print(sum)
```

msg:Write a code that adds up from 1 to 10 in python
Sure, here's a simple code snippet that adds up the numbers from 1 to 10 in Python:

```
sum = 0
for i in range(1, 11):
    sum += i
print(sum)
```

This code initializes a variable `sum` to 0, then uses a `for` loop to iterate through the numbers 1 to 10 (inclusive) and add each number to the `sum` variable. Finally, it prints the value of `sum`, which should be 55 (1 + 2 + 3 +... + 10).
~~~

# 推論速度テスト
<details>
<summary>推論速度テスト用コード</summary>

~~~
import torch
import time
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True).cpu()
model = model.eval()
model = model.to("cpu")

testdata = ["おはよう","hello","你好",
            "pythonで1から10まで足し合わせるコードを書いて",
            "Write a code that adds up from 1 to 10 in python"]

for txt in testdata:
    start_time = time.perf_counter()
    response, history = model.chat(tokenizer, txt, history=[])
    print(f"in:{txt}\nout:{response}")
    end_time = time.perf_counter()
    elapsed_time = end_time - start_time
    print(f"worktime:{elapsed_time}")
~~~
</details>

テスト環境A
CPU:E5-2623V3 * 2
Cinebench R23:4700pts
RAM:104GB

テスト環境B
CPU:i9-12900F
Cinebench R23:15691pts
RAM:128GB

| input | tokens | 環境A | 環境B | 
| ---| --- | --- | --- |
|おはよう|3|14.90s|9.75s|
|hello|1|14.09s|11.43s|
|你好|1|13.07s|10.38s|
| pythonで1から10まで足し合わせるコードを書いて|16|1359.67s|1041.29s|
|Write a code that adds up from 1 to 10 in python|14|1289.46s|1029.31s|
負荷テストヒヤリハット

# 負荷テストヒヤリハット

## 危なかったこと

開発中のWebアプリをAzure App Serviceにデプロイして、負荷テストを行いました。
負荷テストにはK6を使用しましたが、Application Gatewayを使用したドメイン名でアクセスしようとしてしまいました。

### Application Gatewayって何？

Azureのリソースの一つで、Webトラフィックのルーティングと負荷分散を行うロードバランサーサービスです。
HTTPやHTTPSトラフィックを受け取り、バックエンドのサーバーに転送する役割を果たします。
今回負荷テストを行おうとしたアプリもApplication Gatewayのバックエンドのサーバー群に含まれていました。

注意しなければならないのは、会社で使用している**Application Gatewayでは負荷テストを行おうとしているアプリだけでなく、
その他複数のアプリもバックエンドのサーバー群に含まれている**ということです。
Application Gatewayを使用したドメイン名で負荷テストを行ってしまうと、
対象アプリだけでなくそのほかのアプリにも負荷テストの影響が出てしまい、
最悪サーバーが止まってしまうことも考えられます。

## **気を付けよう**

他のアプリにも負荷を与えてしまう危険性があったため、
危うくApplication Gatewayを使用している他のアプリにも負荷を与えてしまうところでした。
負荷テストを実施するときは、FQDNを直接使用するようにしましょう。