OmniAICreator/Qiita-1.07M huggingface dataset:
Webpackの導入手順


Webpackの導入は以下の手順で行う


2. npmを初期化して`package.json`ファイルを作成
   ```bash
   npm init -y
   ```

3. WebpackとWebpack CLIをインストール
   ```bash
   npm install --save-dev webpack webpack-cli
   ```

4. `webpack.config.js`設定ファイルをプロジェクトのルートに作成し、設定を記述。ここではバンドルするindex.jsをentryに記述、バンドルされたファイル名をbundle.jsとしてoutputに書く。

   ```javascript
   const path = require('path');

   module.exports = {
     entry: './src/index.js', // エントリーポイント
     output: {
       filename: 'bundle.js', // 出力ファイル名
       path: path.resolve(__dirname, 'dist'), // 出力ディレクトリ
     },
   };
   ```

これで基本的なWebpackの環境はこれで完了です。
次は実際にpjで導入したことを書こうと思います。
.NET 9で登場予定のLINQのメソッド

## 参考
この記事は、以下の動画を参考にしています。詳しくは、動画をご覧ください。

https://youtu.be/l5RA_x-WbC8?si=hZbBFn8_md3SNbhd

以下の記事にも、同じメソッドについての言及があります。

https://medium.com/codenx/net9-alpha-linq-updates-c2df66d20e1b

## CountBy
引数で指定したselectorが戻すキーの値ごとに、要素数を数える。
戻り値は、キーと要素数のペアのコレクション。

従来なら、`GroupBy`, `Select`, `Count`を組み合わせて書いていたところ。

```C#
// .NET 8
var oldResult = items.GroupBy(x => x.Key).Select(g => (g.Key, g.Count());
// .NET 9
var newResult = items.CountBy(x => x.Key);
```

## AggregateBy
引数で指定したkeySelectorが戻すキーの値ごとに、集計する。
戻り値は、キーと集計値のペアのコレクション。

```C#
// .NET 9
var keyValuePairs = items.AggregateBy(seed: 0,
                                      func: (total, x) => total += x.Value,
                                      keySelector: x => x.Key);
```

## Index
戻り値は、要素番号と要素のペアのコレクション。

従来なら、`Select`のバリエーションを使っていたところ。

```C#
// .NET 8
var oldResult = items.Select((x, index) => (index, x));
// .NET 9
var newResult = items.Index();
```
MiniAPI(一): MiniAPIの開始

MiniAPI以前の公式.net webフレームワークは、他の言語のように軽量ではありませんでした。例えばgo、python、またはc#ベースのnancyのように、webへの旅をシンプルな方法で開始することができませんでした。そのため、一部の仲間からは.netのwebベースが使いにくいとの不満がありましたが、.net6では公式にMini APIが導入され（少々遅れましたが）、この部分の仲間の恋煩いを解消するために登場しました。
```C#
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello .net mini api");
app.Run();
```
VS2022プレビュー版、.NET6を使用し、わずか3行のコードでweb hostを構築できます。これは極めてシンプルで明快です。
もし、単純なhostを構築したいだけなら、非常に簡単ですが、もっと複雑で機能豊富なものを望むなら、どのように進むべきでしょうか？
```C#
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
app.MapGet("/", () => "Hello .net mini api");
app.Run();
```
このように、最初にbuilderを作成し、build前に多くの他の機能コンポーネントを装填できるようにすることで、Mini APIの機能を豊かにすることができます。ここでは一例を紹介しただけで、詳細は後述します。
![alt 画像](https://mmbiz.qpic.cn/mmbiz_png/4CAA63nvHRDO0juoMFIkgmRqv07b4vicibNic9BePsX6jbyRek2BBcn1N5yacMnsCJB4Y9HibyAVGlUDXEwEzM57HQ/640?wx_fmt=png)
そのため、最近.NET Mini APIシリーズの開始に着手しました。この道を遠く、深く進めていくことです。基本的な考え方は、このシリーズがweb api開発で一般的な面をカバーし、最初のステップとして短い記事を前もって用意し、動的な内容を示す短い動画が補足として提供されることです。
このシステムは基本的に以下をカバーします：
1. Mini APIの基本機能
2. Mini APIの便利なサードパーティライブラリ
3. Mini APIを基にした迅速なチーム開発

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247484771&idx=1&sn=90115ca2b39f2ad2d445165a5b6d65c3&chksm=9f005a49a877d35f3979aa291503d9ecfb4d518d7e928c28b01c66f1fb72078c8f0a93273494&token=2050451386&lang=zh_CN#rd
【備忘】シングルサインオン（SSO）の認証方式の種類と仕組み

前回、シングルサインオン（SSO）認証について記載しましたが今回はSSOの認証方式の種類と仕組みについて記載します。

### シングルサインオン（SSO）認証方式の種類
大きく分けて下記5つ
1.エージェント方式
2.リバースプロキシ方式
3.代理認証方式
4.フェデレーション方式
5.透過型方式

#### 1.エージェント方式
##### 仕組み
エージェント方式では、クライアント側にエージェント（ソフトウェア）を導入。
ユーザーがサービスにアクセスすると、エージェントが認証サーバーにユーザーの認証情報を送信し認証を行い、認証が成功すると、エージェントはサービスにアクセスする際トークンを提供し、ユーザーはログインせずにサービスを利用可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303394/0b1b2f87-9571-61e8-608c-e1b525b1c4f1.png)



##### メリット
サービス側での大規模な変更が不要であり、既存のアプリケーションでも比較的容易に導入可能。
クライアント側での認証情報の保持が可能で、セキュリティが強化される。

##### デメリット
クライアント側にエージェントをインストールする必要があり、管理が煩雑になる場合がある状況。
エージェントが正常に動作しない場合、認証が失敗する可能性あり。

#### 2. リバースプロキシ方式
##### 仕組み
リバースプロキシサーバーが認証を行い、ユーザーをサービスに透過的に認証実施。
ユーザーがサービスにアクセスすると、リバースプロキシサーバーが認証情報を要求しユーザーの認証を行い、認証が成功すると、リバースプロキシサーバーはユーザーのリクエストをサービスに転送し、ユーザーはログインせずにサービスを利用可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303394/b6d2061f-28f5-cb1f-f56d-5bb766fd3d13.png)


##### メリット
サービス側での変更が不要であり、既存のインフラストラクチャに統合しやすい。
ユーザーにとっては透過的な認証が提供され、利便性が高い。

##### デメリット
リバースプロキシサーバーが単一障害点となり得るため、冗長化や負荷分散が必要。
サービス間で認証情報の共有が難しい場合あり。

#### 3. 代理認証方式
##### 仕組み
代理認証方式では、ユーザーの代理人がユーザーを代理して認証実施。
代理人が認証サーバーに認証情報を提供し、ユーザーの代理としてサービスにアクセス可能。
サービスは代理人からの認証情報を受け入れ、ユーザーはログインせずにサービスを利用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303394/63a897b5-2c00-ef63-6a45-7250df8247fc.png)


##### メリット
ユーザーが認証情報を直接提供する必要がないため、セキュリティが向上する。
代理人がユーザーの認証を管理し、認証情報の共有を容易にすることが可能。

##### デメリット
代理人による認証は信頼性が問題となります。代理人の認証情報が漏洩した場合、セキュリティ上のリスクが発生し、代理人の管理が煩雑になる場合がある。

#### 4. フェデレーション方式
##### 仕組み
フェデレーション方式では、複数の組織間で認証情報を共有。
ユーザーがアクセスしようとするサービスの認証サーバーにリダイレクトされ、ユーザーの所属する組織のフェデレーションサーバーに認証情報が送信される。
フェデレーションサーバーがユーザーを認証し、サービスに対するトークンを発行します。ユーザーはログインせずにサービスを利用可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303394/dc7e6637-447e-c063-e3a7-c8b821307c20.png)


##### 利点
複数の組織間で認証情報を共有することができ、利便性が向上。
フェデレーションサーバーが認証を管理するため、セキュリティが強化される。

##### デメリット
複数の組織間での信頼関係が必要であり、設定や管理が煩雑になる場合がある。
フェデレーションサーバーがダウンした場合、アクセスに支障が生じる可能性あり。

#### 5. 透過型方式
##### 仕組み
透過型方式では、ユーザーがサービスにアクセスすると、認証が自動的に行われる。
例えば、ユーザーが企業のネットワーク内にいる場合、ネットワークに接続されている端末からのアクセスであれば、ユーザーの認証情報が自動的に識別される。
このような認証方式は、透過型認証と呼ばれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303394/9c0504a6-62db-5242-6615-b69dd56f6b78.png)


##### メリット
ユーザーが特別な操作を行わずに認証が行われるため、利便性が高い。
ネットワーク内にいる場合に限定されるため、外部からの不正アクセスが制限される。

##### デメリット
ネットワーク外からのアクセスでは認証が行われないため、セキュリティリスクが生じる可能性あり。
ユーザーがネットワーク外からのアクセスを必要とする場合には、追加の認証手段が必要になる。

### 参考情報
https://www.ogis-ri.co.jp/column/themistruct/c106480.html
「ソフトウェアテストの教科書」を読んで、業務に落とし込みたいと思ったこと

#### 「この1冊でよくわかるソフトウェアテストの教科書: 品質を決定づけるテスト工程の基本と実践」
を読み、個人的に品質管理についての解像度が上がったので共有いたします。

【結論】
普段、デバッグの業務をするだけでは気づけないようなポイントが数多く紹介されていました。それと同時に、実際の業務に落とし込んだら、品質管理がもっと良くなるという確信を得ることもできました。


7ページ～
ソフトウェア関連のトラブル事例として挙げられているケースの一つに、新型コロナウイルス接触確認アプリ「COCOA」をAndroid端末で利用した場合、通知が来ないようになっていた。
この障害が発生した原因として、
・急激な新型コロナウイルスの拡大に伴い、急ピッチで開発が進められた
→通知が来ないという障害が発生し、本来の役割を果たせなかった(短納期開発に潜むリスクが顕在化した)
と説明されている。
https://www.mhlw.go.jp/stf/newpage_16532.html

【感想】最近のことなので、聞き覚えのある話題だと思います。実際に使っていて、バグがあるなと思った方もいらっしゃると思いますし、潜在的に察していて、気づいた頃には使うのをやめていた方もいらっしゃるかもしれません。


11ページ～
品質要素を「当たり前品質」「一元的品質」「魅力的品質」の3つに分類したもののことを「狩野モデル」といいます。
「当たり前品質」：充足されていて当たり前であり、不充足の場合は不満に感じる機能のこと。
「一元的品質」：充足されていると満足し、不充足の場合は不満に感じる機能のこと。
「魅力的品質」：充足されていると満足し、不充足の場合は「仕方がない」と感じる機能のこと。

【感想】品質を担保するといっても一つの基準しかないわけではないということを言語化されています。開発者は、どの機能がれに該当するのか、早めに知っておくべきですし、常に固定とは限りません（例えば、一元的品質だったものが当たり前品質に変わることもあります。）


78ページ～
同値分割テスト、境界値テスト
同値分割テスト：テストの工数を減らす方法。電話番号(国際電話などを除き、10桁か11桁しかない)を例に使うと、弾かなければいけないのは0~9桁と12桁以上なので、「0~9桁」と「12桁以上」から1通りずつ、計2通りのテストをすればよいとする考え方のこと。
境界値テスト：欠陥は協会に潜んでいる可能性が高いので、仕様条件の境界となる値とその隣の値に対してテストを行うテスト技法。

【感想】デバッグを行うときに、他よりもリスクが高いポイントと、外してはいけないポイントを教えてくれています。


152ページ～
組み合わせテスト
複数ある設定を組み合わせた場合の動作確認も必要。「単一の条件だけでは発生しないが、複数の条件が組み合わさった際に発生する欠陥」を見つけるため。

【感想】網羅的に確認することの重要性と同時に、ここは外してはいけないというポイントを教えてくれています。


253ページ～
記述の粒度
あまりに簡略化した抽象的な記述だと、読み手によってさまざまな解釈ができ、誤解が生じる危険性が高まる。ただし、詳しく書いてあるほど良いわけではない。適切な記述の粒度で、文書に起こすことが求めれる。

【感想】特に我々の会社では、昨日に詳しくないアルバイトさんがデバッグを担当することも少なくありません。そういった方々が作業を詰まらせることがないように、必要最低限かつ簡潔に「やってほしいこと」が書かれていなければならないんだと改めて感じました。


270ページ～
不具合報告書
良い例と悪い例が挙げられていました。
・開発者が、一目見て内容が分かる
・検出環境（端末、OS、バージョン、ID+パスワードなど）
・感情的ではなく事実を書く
・適切なランク付け
・エビデンス（主にキャプチャ）


【感想】同じくデバッグに関することで、こちらは開発者ではなくデバッグの担当者が心掛けたいことになります。
必要な情報が伝わる簡潔な文章を書けるように、自分も勉強していきます。テクニカルライティングの技法を知ったうえで適切に使えるといいと思います。


309ページ～
テスト自動化

【書いてあったこと】人間が行っているソフトウェアテストを、コンピューターに実行させること。テスト実施工数の削減を目的とし、その先にある品質の強化、競争力の強化を目指して行われるが、工数やコストがゼロになるわけではないことを把握しておくべき。

【感想】人手には限界があるので、いずれ検討しなければいけないことだとは思います。他社の事例もキャッチアップしていきます。
GWTでwebアプリを開発すると長く使える

# 実はワイGWTを2007年ごろからずっと使っている
おいおい、簡便してくれよ、いつの話だよ・・
いいかい学生さん、いつでも・・とんかつを・・とんかつを食える・・
いいや、ずっと昔からでも、互換性が担保されているんだよ

# GWTは最初からSPA(Single Page Application)
webアプリが面倒な、原因の一つが、ページ遷移の制御
だから、MVCフレームワークとかいう、くそわかりづらい物が生まれた

# フロントとバックは同じJava言語だけで書ける
あのさ、フロントはJavaScriptにして、バックはPHPとかそんな分ける必要なんてない

# フロントとバックの通信はJavaだけでできる
jsonとかXMLとかそんなものは覚える必要がない

# 結論
だから、GWTを使ってwebアプリを開発すると、長く使えます
git squash コマンドの使い方について説明する（※釣り）

# git rebase -i

![git squash](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78152/82be9a4f-06d8-f679-9404-187ce378ea00.png)

`git rebase -i` の実行の際に `squash` やその省略形である `s` を指定すると、図のように複数のコミットを1つにまとめることが出来ます。

```bash
git rebase -i develop
```

```diff_shell
  pick abcd123 すごい機能 仮実装
- pick efgh456 バグ修正
- pick ijkl789 誤字修正
+ squash efgh456 バグ修正
+ squash ijkl789 誤字修正
```

> If you want to fold two or more commits into one, replace the command "pick" for the second and subsequent commits with "squash" or "fixup".

https://git-scm.com/docs/git-rebase

しかし、`git rebase -i` するたびに手作業で全ての `pick` を `s` に置換していくのは面倒ですし、 `:%s/pick/s/gc` と入力して一気に置換するのもそれはそれで面倒ですよね。

# squash を2個のコマンドで

代わりに以下のコマンドで同様の処理が実行できます。

```bash
git reset --soft <base-branch>
git commit -m <commit message>
```

例えば、具体的には以下のようになります。

```bash
git reset --soft develop
git commit -m "すごい機能を実装"
```

※これを行うとコミットメッセージ、コミット時刻、コミットの author が消失してしまうため注意してください。
※また、ステージング済みの変更があるとそれもコミットされてしまうため注意してください。

## 解説


![git_reset_commit_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78152/4394fa8c-d95b-12b3-7a17-de13d621076c.png)

`--soft` を指定して `git reset` を行うことにより、コミット済みのファイルをインデックスに残したまま、`<base-branch>` ブランチまでのコミット履歴を一旦無かったことにしています。（つまり、現在チェックアウトしているブランチの指し示す先が、`<base-branch>` の指し示すコミットと同じになります。）

この状態で `git commit` を行うことで、インデックスに追加されているファイルが再度コミットされ、1つだけのコミットが残ることになります。

https://git-scm.com/docs/git-reset

https://git-scm.com/docs/git-commit

# 参考リンク（余談）

この記事を書いた後に気付いたのですが、世の中には賢い人が居るようで……。

https://stackoverflow.com/questions/7275508/is-there-a-way-to-squash-a-number-of-commits-non-interactively

> ```shell
> EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>
> ```

## 余談の解説

git rebase コマンドは EDITOR で指定されたエディタを開き、引数として一時ファイルを渡しています。EDITOR に指定されたコマンドでは、指定されたファイルの `2` 行目から `/^$/` 行目まで `/^pick\b/` を `s` に置換する（`s` コマンド）という処理を行い、指定されたファイルに上書きします。 `/^$/` 行目という正規表現に一致する行は存在しないので、最後までの全ての行に対して処理が行われることになります。

ただし、`git config core.editor` などで既に他のエディタが設定されている場合は、EDITOR 環境変数よりもそちらの設定の方が優先されてしまうようでした。

# お詫び

`git squash` というコマンドはありません。記事のタイトルは釣りです。
RubyOnRails: Turbo の使い方

次のページを参考にしました。
[サンプルアプリケーションを作成する](https://note.com/everyleaf/n/n0a5934373f12#b09d9a92-6d30-457e-9ce2-4d4862cf88db)

## 確認した環境

```text
$ ruby --version
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux-gnu]

$ rails --version
Rails 7.1.3

$ bundle --version
Bundler version 2.5.6
```

## 必要な Gem のインストール

```bash
sudo gem install turbo-rails
```

## プロジェクトの作成

```bash
rails new sample_aa
cd sample_aa
bundle install
rails generate scaffold Book title:string
rails db:migrate
```

## サーバーの起動

```bash
rails server -b 0.0.0.0
```

ブラウザーでデータを入れた状況
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/86d15454-e5d3-02c7-9dce-76f2549ada75.png)

## データベースの確認

```text
$ sqlite3 storage/development.sqlite3
SQLite version 3.40.1 2022-12-28 14:03:47
Enter ".help" for usage hints.

sqlite> .table
ar_internal_metadata  books                 schema_migrations   

sqlite> select * from books;
1|いばらひめ|2024-02-14 00:09:20.511030|2024-02-14 00:09:20.511030
2|赤ずきん|2024-02-14 00:09:39.345029|2024-02-14 00:09:39.345029
3|おいしいおかゆ|2024-02-14 00:09:50.736723|2024-02-14 00:09:50.736723
4|星の銀貨|2024-02-14 00:09:59.033606|2024-02-14 00:09:59.033606
sqlite>
```

## エラー対策

rails new sample_aa
で次のようなエラーが出る時の対策

```text
Could not find net-imap-0.4.10, net-pop-0.1.2, net-smtp-0.4.0.1,
bigdecimal-3.1.6, drb-2.2.0, mutex_m-0.2.0, rake-13.1.0, rdoc-6.6.2,
io-console-0.7.2, date-3.3.4, net-protocol-0.2.2, psych-5.1.2, stringio-3.1.0 in
locally installed gems
```

```bash
sudo gem install sprockets-rails sqlite3 puma
sudo gem install importmap-rails stimulus-rails jbuilder bootsnap debug
sudo gem install web-console error_highlight capybara selenium-webdriver
sudo gem install bindex addressable regexp_parser xpath base64 rexml
sudo gem install net-imap net-pop net-smtp bigdecimal drb mutex_m rake
sudo gem install rdoc io-console date net-protocol psych stringio
```
Python : PDF表のExcel化、メモ

Python : PDF表のExcel化、メモ

***

# install tabula-py

PDFファイルから表を読み取るためには、テキストベースのPDFファイルからテキストを抽出するのではなく、表の構造を解析してデータを抽出する必要があります。これには`tabula-py`などの専用ライブラリが有効です。

    !pip install tabula-py
    !pip install JPype1

# Javaのインストール

*   jdk-21<br>
    <https://www.oracle.com/jp/java/technologies/downloads/>

# jre-1.8 インストール

*   jre-1.8<br>
    <https://www.java.com/en/download/manual.jsp>

jdk-21だけで良いかもだけど、備忘録で記載

# 環境変数

`C:\Program Files\Java\jdk-21\bin` は、Java Development Kit (JDK) のバージョン21がインストールされた場所を示しています。このパスには、Javaの実行ファイルや開発ツールが含まれており、これをシステムの環境変数に追加する必要があります。

環境変数にこのパスを追加する手順は以下の通りです：

1.  **コントロールパネルを開く**：スタートメニューから「コントロールパネル」を開きます。

2.  **システムとセキュリティに移動**：コントロールパネルで「システムとセキュリティ」を選択します。

3.  **システムを開く**：「システム」をクリックします。

4.  **システムの詳細設定を開く**：左側のメニューから「システムの詳細設定」を選びます。

5.  **環境変数を開く**：「詳細」タブの「環境変数」ボタンをクリックします。

6.  **PATH環境変数を編集**：
    *   「システム環境変数」セクションで「Path」を見つけて選択し、「編集」をクリックします。
    *   「新規」ボタンをクリックし、`C:\Program Files\Java\jdk-21\bin` を入力して「OK」をクリックします。

7.  **全てのウィンドウを閉じて変更を保存**：すべてのウィンドウで「OK」をクリックして閉じ、変更を保存します。

これでJDKの`bin`ディレクトリが環境変数に追加されました。変更を有効にするために、コンピュータを再起動してください。再起動後、コマンドプロンプトで`java -version`を実行して、Javaが正しくインストールされていることを確認してください。

# Pythonコード

    import tabula
    import pandas as pd
    import tkinter as tk
    from tkinter import filedialog

    def pdf_to_excel_tabula():
        # ファイル選択ダイアログを開く
        root = tk.Tk()
        root.withdraw()
        file_path = filedialog.askopenfilename(filetypes=[("PDF Files", "*.pdf")])

        if not file_path:
            return

        # PDFファイルから表を読み取る
        dfs = tabula.read_pdf(file_path, pages='all', multiple_tables=True)

        # 読み取った表を一つのExcelファイルに保存する
        with pd.ExcelWriter(file_path.replace('.pdf', '.xlsx')) as writer:
            for i, df in enumerate(dfs):
                df.to_excel(writer, sheet_name=f'Sheet{i+1}', index=False)

        print(f"Excelファイルが保存されました: {file_path.replace('.pdf', '.xlsx')}")

    pdf_to_excel_tabula()
情報処理安全確保支援士登録手続き

<h4>情報処理安全確保支援士登録日</h4>
年２回<br>
4月1日登録：2月15日締切<br>
10月1日登録：8月15日締切<br>

参考文献
https://www.ipa.go.jp/jinzai/riss/touroku/to-register.html

手順2～4の所要時間約2時間。
<h4>1.合格発表確認</h4>
IPAにて合否を確認。

<h4>2.登録に必要な申請書類の入手</h4>
下記から登録の手引きと必要書類を入手。

参考文献
https://www.ipa.go.jp/jinzai/riss/formlist/new-request.html


<h4>3.申請書類の準備</h4>
2で入手した書類に必要事項を入力。
住民票はマイナンバーカードを使用してコンビニで取得するとお得。

<h4>4.申請書類を簡易書留で郵送</h4>
郵便局で収入印紙を購入。
封筒の糊付けは郵便局においてある糊で。
エンジニアとしての挑戦と変化を楽しむキャリアパス

# はじめに

Qiita×Findy記事投稿キャンペーン 「自分のエンジニアとしてのキャリアを振り返ろう！」の参加記事です。 

良いきっかけなので、自分のこれまでのキャリアを振り返ってみようと思います。

あと振り返りを通して、エンジニアとしてキャリアに悩んでいる方に自分なりの経験やアドバイスもできたら良いなと思います。

# 1年目〜
プログラミングは、2015〜2016年ごろアフィリエイトのブログを自分で立ち上げたときに、サイト構築のためにHTMLやCSSを触ったことがきっかけで興味を持ちました。
 
何も知らない当時は、自分の書いたコードでHPの見た目が変わるなんてスゲーといった感じで、なんだか純粋にすごく楽しかった記憶があります。

これを仕事にしたら楽しいかもと思い、独学でAndroidのアプリを作りマーケットにリリースして、プログラマーの採用面接を受けました。
Android Studioはあったと思うのですが、確かまだベータ版で、その当時は情報量が多かったEclipseを使って実装しました。

思い返すと当時は今ほどプログラミングスクールもなく、どちらかというとIT土方はやめとけみたいな風潮が強かった印象だったので、面接も最初の1社で合格いただけました。
我ながら運が良かったと思います。

その後、2017年1月からプログラマーとして働き始めました。

その会社は受託やSESもやっている会社だったので、色々なクライアント先にいけて楽しかった思い出です。

最初の仕事は、先輩の書いたコードをJUnitでひたすらテストコードを書くようなことを2〜3ヶ月ぐらいしていた気がします。

新人の内では自分が一番コードを書けたので、いくつかの機能実装も経験させてもらっていました。

この現場でPMが失踪したり休日フル出勤だとか、「こんなこともできないのか！」とめちゃくちゃ罵倒されたり、いわゆるデスマーチ的なことも経験しましたが、とりあえずコードを書けるのが楽しかったのであまり苦ではなかったです。(思い出は美化される)

# 2年目〜

プライベートでは、土日はほぼ社外内の勉強会に参加したりconnpassとかで勉強会を主催したりしてました。

そこでフリーランスの人や同じレベル感のエンジニアと知り合って、勉強会後はご飯行ったりして交流を持ちました。

この当時は1〜2年目ぐらいだったので、色々な先輩エンジニアのキャリアの話を聞く機会が多くて、すごく勉強になっていた気がします。

コーディング業務以外では増員した後輩の面倒を見たり、
クライアントから直接案件をもらったりしてました。

前職がIT系の営業をしていたので、そういったお金にまつわる話もある程度わかっていたのも大きかったかなと思います。

# 3年目〜

3年目ぐらいに、当時参画していたプロジェクトのPMが移動することになったのがきっかけで、クライアントからの指名でPMをやることになりました。

このときはクライアントが日本人で、エンジニアチームのメンバーの7割が外国人だったのもあり、ブリッジ的な役割での抜擢だったかと思います。

業務的には、要件定義のほか、スケジュールの調整や進捗報告などを、クライアントと密に連携するなどしてプロジェクトを進めていきました。

PMは3年ぐらいやっていたと思いますが、他にもそれぞれ違うポジションで複数の案件に参画したりしていました。

この時期がめちゃくちゃ忙しくて、A案件ではPython、B案件ではRailsとかそんな感じで、言語ごとの書き方を思い出すのも大変だった記憶があります。

そのときにすごく仲良かったトルコ人エンジニアが、イスラム教なのにトンカツ大好きというクレイジーな人だったのも、なかなか良い思い出です。

世の中には色々な人がいます。

# 4〜5年目

その後、自社で新たに受託開発に特化した子会社を設立することになり、その新会社の代表取締役兼システムインテグレーション(SI)事業部長に抜擢されました。

会社運営から本格的にセールス的な仕事、マネジメントや人事採用も行うようになって、非常に多くのことを経験させていただきました。
今でも当時の親会社の社長には本当に感謝しています。

# 6〜7年目

2年ほど経ち、
自分の中では自社サービスで良いプロダクトを作りたいというメンタルになっていました。

このときはコーディング業務が全体の2割程度だったので、もっとガッツリ手を動かしたい気持ちも強かったです。

事業として受託をメインでやる以上、収益などの関係で自社サービスに舵を切るのが難しかったという状況でした。

自分がやりたいことと周りから求められていることが違うということが、個人的にかなりキツくて苦しかったです。

色々と悩み抜いた末に転職を決意し、現在の自社開発のスタートアップに転職しました。

プログラマーとして採用していただいたので、給与はかなり減りましたが、コーディングできる喜びが勝って、結果的には良かったかなと思っています。

# 8年目〜現在

去年の4月ごろから自社サービスのリニューアルに合わせてPdMとして、プロダクトを任せていただくことになりました。

現在はサービスを統括する立場ですがプログラマーも兼任しつつ、日々やりがいを感じています。

# 自分なりの経験やアドバイス

自分で言うのもアレですが、経歴的にもかなり特殊な部類なので
モデルケースとしては正直あまり参考にはならないのかもしれません。

自分もまだまだで偉そうなことは全然言えませんが、
ただ一つ言えるのは、自分はいつもその状況をいかに楽しめるかを考えて仕事をしてきました。

上流工程に参画するときやキャリアチェンジなど、正直本当に自分にできるのか？といつも不安になります。
もう本当に夜しか眠れなくなります。

ただ挑戦することを恐れずに飛び込んでみたら、失敗もありましたが、意外とうまく行ったことは過去の経験上たくさんありました。

経験することで自分の視野も広がります。

あまり無責任なことも言えませんが、
何か選択するときは、とりあえずやってみるという選択をしてみても良いのかもしれません。

もしこれからのキャリアにおいて、何か新しい一歩を踏み出す際には、この話が少しでも勇気づけになれば幸いです。
Semantic link を使用して Microsoft Fabric ワークスペース上のアイテムを一覧表示する

## はじめに

REST APIとか使わずにFabric 内でアイテム一覧を取得したかった


### 参考

- https://learn.microsoft.com/ja-jp/fabric/data-science/semantic-link-overview
- https://learn.microsoft.com/en-us/python/api/semantic-link-sempy/sempy.fabric?view=semantic-link-python#sempy-fabric-list-items

## 手順

1.ノートブックを作成して、sempyをインストールする
```python: pyspark
%pip install semantic-link
```

2.以下のコードを実行する
```python: pyspark

import sempy.fabric as fabric

items=fabric.list_items()
display(items)


```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6ac8ca5b-ace8-0e76-4223-21e6892521c3.png)

3.フィルタした例（[データラングラー](https://learn.microsoft.com/ja-jp/fabric/data-science/data-wrangler)使いました。

```python: pyspark
# Pandas DataFrame の Data Wrangler によって生成されたコード

def clean_data(items):
    # 列に基づいて行をフィルター処理する: 'Type'
    items = items[(items['Type'] == "SQLEndpoint") | (items['Type'] == "Warehouse")]
    return items

items_filtered= clean_data(items)
display(items_filtered)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/678e4c6d-e43e-97d0-45d9-305b8bb5bb4c.png)


## 補足

セマンティックリンクで帰ってくるデータフレームはspark じゃなくてpandasなので少し面喰らう。しかしその分データラングラーすぐ起動できるので〇
Markdownとは

# Markdownとは
Markdownは、軽量マークアップ言語の一種で、プレーンテキストを記述する際に使用され、HTMLへの変換が容易です。Markdownを使用すると、シンプルな記法で見出し、リスト、強調、リンクなどの要素を表現することができます。

JavaScriptでMarkdownを扱う場合、通常はMarkdownパーサーやライブラリを使用します。これらのライブラリは、Markdown形式のテキストをHTMLに変換したり、Markdownを表示するためのビューやコンポーネントを提供したりすることができます。

例えば、MarkedやShowdownといったライブラリがあります。これらのライブラリを使用すると、JavaScriptでMarkdownを解析してHTMLに変換したり、HTMLをMarkdownに変換したりすることができます。このようなライブラリを使用することで、ウェブアプリケーションやブログプラットフォームなどでMarkdown形式のコンテンツを扱うことができます。
【JavaScript】fetch APIとは

# fetch APIとは
Fetch APIは、Webブラウザーに組み込まれたJavaScriptの新しい機能で、ネットワークリクエストを発行し、サーバーからデータを取得するための方法を提供します。Fetch APIは、従来のXMLHttpRequest（XHR）を置き換えるものとして導入されました。Fetch APIを使用することで、より強力で柔軟なネットワークリクエストを行うことができます。

# 特徴
Fetch APIの主な特徴は以下のとおりです：

1\. **PromiseベースのAPI** : Fetch APIはPromiseベースのAPIです。これにより、非同期処理をより効果的に扱うことができます。データの取得が完了すると、Promiseが解決され、その結果を処理することができます。

2\. **シンプルなAPI** : Fetch APIはシンプルなAPIを提供し、リクエストを送信するためのfetch()関数を提供しています。この関数を使用して、リクエストを送信し、サーバーからのレスポンスを取得することができます。

3\. **HTTPリクエストとレスポンスのコントロール** : Fetch APIはHTTPリクエストとレスポンスを柔軟に制御する機能を提供します。ヘッダーの設定、クエリパラメーターの追加、HTTPメソッドの指定など、さまざまなオプションを使用してリクエストをカスタマイズすることができます。

4\. **JSONの自動パース** : Fetch APIは自動的にJSON形式のレスポンスをパースし、JavaScriptオブジェクトに変換します。これにより、サーバーからのJSONデータを簡単に処理することができます。

# 使用方法
以下は、Fetch APIを使用してGETリクエストを送信し、サーバーからのJSONレスポンスを取得する例です：
```js
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Fetch error:', error));
```
この例では、fetch()関数を使用してサーバーにGETリクエストを送信し、サーバーからのJSONレスポンスを取得します。その後、Promiseチェーンを使用して、レスポンスをJSON形式にパースし、データをコンソールに出力します。また、エラーハンドリングも行われています。
【JavaScript】暗黙的な型変換とは

# 暗黙的な型変換とは
JavaScriptにおける暗黙的な型変換は、異なるデータ型の値を操作する際に、JavaScriptエンジンによって自動的に型変換が行われる現象です。この動作により、異なるデータ型の値を予想外の方法で組み合わせることができますが、間違った型変換の結果、バグや予期しない動作が発生する可能性もあります。

# 
以下は、暗黙的な型変換の例です：
```js
let num = 10;
let str = "20";

console.log(num + str); // 出力: "1020"
```
この例では、数値型の変数 `num` と文字列型の変数 `str` を `+` 演算子で組み合わせています。JavaScriptでは、文字列型と数値型の演算では、数値型の値が自動的に文字列に変換され、文字列の結合が行われます。そのため、`num` の値が文字列 `"10"` に変換され、`str` の値と結合されて文字列 `"1020"` が出力されます。

暗黙的な型変換は、理解しにくいバグを引き起こす可能性があるため、注意して扱う必要があります。JavaScriptでは、明示的な型変換を行うことで、暗黙的な型変換による問題を回避することができます。例えば、`parseInt()` や `parseFloat()` を使って文字列を数値に変換することができます。
【JavaScript】条件演算子（三項演算子）とは

# 条件演算子（三項演算子）とは
条件演算子（三項演算子）とは、条件式が真である場合と偽である場合の2つの結果を返す演算子です。
三項演算子は以下のような形式を取ります：
```
条件式 ? 真の場合の値 : 偽の場合の値
```
この演算子は、条件式が真である場合は最初の値が返され、偽である場合は二番目の値が返されます。条件式は真または偽のどちらかの結果を返す式でなければなりません。

# 使用方法
以下は、三項演算子の例です：
```js
let age = 20;
let message = (age >= 18) ? "成人です" : "未成年です";
console.log(message); // 出力: 成人です
```
この例では、変数 `age` の値が18以上であるかどうかをチェックしています。条件式 `(age >= 18)` が真である場合は `"成人です"` が返され、偽である場合は `"未成年です"` が返されます。そして、変数 `message` に代入されます。

三項演算子は、if-else文の簡潔な書き方として使われることがあります。同じ結果を得るためにif-else文を使用することもできますが、三項演算子を使うとコードが短くなり、より読みやすくなります。
Go でパッケージを自作して API を作ってみる：個人開発メモ

更新：2024年2月13日
Go でパッケージを自作して API を作ってみます。

# パッケージを自作して API を作成

フォルダ tmp20240213 を作って、その下に main フォルダ作ります。そして main.go を作って、 go mod init と go mod tidy します。

```:Macbook Terminal
% pwd
/***/tmp20240213/main
% go mod init tmp20230213/main
go: creating new go.mod: module tmp20230213/main
go: to add module requirements and sums:
	go mod tidy
% go mod tidy
% ls
go.mod	main.go
```

```:test20240202/main/main.go
package main

import (
	"net/http"
	"tmp20240213/handler"
)

func main() {
	http.HandleFunc("/", handler.Router)
	http.ListenAndServe(":3000", nil)
}
```

フォルダ tmp20240213 の下に handler フォルダ作ります。そして router.go を作って、 go mod init と go mod tidy します。

```:Macbook Terminal
% pwd
/***/tmp20240213/handler
% go mod init tmp20240213/handler
go: creating new go.mod: module tmp20240213/handler
go: to add module requirements and sums:
	go mod tidy
% go mod tidy
% ls
go.mod		router.go
```

```:router.go
package handler

import (
	"fmt"
	"net/http"
)

func Router(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!!!")
}
```

カスタムパッケージを参照するように go mod edit と go get します。

```:Macbook Terminal
% pwd
/***/tmp20240213/main
% go mod edit -replace=tmp20240213/handler=../handler
% go get tmp20240213/handler
go: added tmp20240213/handler v0.0.0-00010101000000-000000000000
```

プログラムを実行します。

```:Macbook Terminal 1
% pwd
/***/tmp20240213/main
% go run .
```

```:Macbook Terminal 2
% curl http://localhost:3000
Hello World!!!
```

以上です。


# 参考

[Go 言語でパッケージを自作して、それを呼び出してみる](https://go.genzouw.com/2021/03/30/post-61/)
【JavaScript】データ型とリテラル

JavaScriptにはさまざまなデータ型があります。主なデータ型とリテラルを以下に示します。

1\. **プリミティブ型**
- **文字列 (String)** : ダブルクォート `"` またはシングルクォート `'` で囲まれた文字列。
```js
let message = "Hello, world!";
```
- **数値 (Number)** : 整数または浮動小数点数。
```js
let number = 42;
let float = 3.14;
```
- **真偽値 (Boolean)** : `true` または `false`。
```js
let isTrue = true;
let isFalse = false;
```
- **null** : "値が存在しない" または "不明" を表す特別な値。
```js
let empty = null;
```
- **undefined** : "値が割り当てられていない" を表す特別な値。
```js
let notDefined;
```
- **シンボル (Symbol)** : ECMAScript 6で追加された一意の識別子。
```js
let sym = Symbol("key");
```

2\. **オブジェクト型**
- **オブジェクト (Object)** : キーと値のペアを保持するコレクション。
```js
let person = {
  name: "John",
  age: 30
};
```
- **配列 (Array)** : 要素の集合。
```js
let colors = ["red", "green", "blue"];
```

リテラルとは、プログラミング言語の構文において、値そのものを直接表現する方法のことです。上記の例では、各データ型に対応するリテラルが使用されています。たとえば、文字列のリテラルはダブルクォート `"` またはシングルクォート `'` で囲まれた文字列です。同様に、数値のリテラルは単純な数値です。
スクリーンショットをターミナルだけで整理したい

乱雑に集められたスクリーンショットを整理する方法の覚え書き。

## 何がしたいのか？

画像を整理するために、ビューワーとターミナルを行き来するのは面倒です。

なので
- ターミナルに一本化したい
- できれば fzf であいまい検索したい

### fzfのプレビューに OCR 結果を載せる方法

OCR すればターミナルで取り扱えるというアイデアです。
fzf でディレクトリを絞り込みつつ、プレビューに OCR 結果を表示することで中身を確認します。

```bash
# ディレクトリの png ファイルをプレビューで確認しながらあいまい検索
find . -name '*png' | fzf --preview 'tesseract '"{}"' - -l jpn --psm 6 ~/.tesseract/.config'
```

まず画像が大きいと OCR プレビューが中々表示されないです。
あと、日本語ではまだまだ OCR の精度が足りないかな？という感じがあります。

### ビューワーを起動しないでターミナルに画像を表示する

もし、画像をターミナルに表示できれば OCR の精度や待ち時間を考えずに済みます。
ターミナルに画像を表示するためには `img2sixel` というコマンドがあります。

```bash
# ターミナルにあいまい検索した画像を表示
img2sixel "$(find . -name '*png' | sort -n | fzf --preview 'tesseract '"{}"' - -l jpn --psm 6 ~/.tesseract/.config')"
```

プレビューで `img2sixel` が使えれば簡単なのですが、使えないので次善の策です。
また、ターミナルエミュレータが`SixelGraphics`に対応してなければ `img2sixel` は使えないので気をつけて下さい。

### 付録

上のコードで使っている日本語用の `tesseract` の `.config` をおまけに付けておきます。
数年前に書いたものなので適当に現代化して使ってください。

```.config
language_model_ngram_space_delimited_language 0
preserve_interword_spaces 1
chop_enable T
language_model_ngram_on 0
textord_force_make_prop_words F
edges_max_children_per_outline 40
```
C++でC#のActionクラスを再現したかった...

### C++でC#のActionを再現してみたい
そう思ってしまったので勢いに任せて手を動かしました。
初めにC++でC#にあるActionクラスを再現できないか勢いに任せてやった試みのお話です。

１時間ぐらいで切り上げましたが、その過程を残してみます。

## 再現できたこと

1. 呼び出す関数の登録
2. 登録済みの関数を呼び出す

上記２つは再現できました。

しかし、登録済みの関数を登録解除する、という機能のみ実現できてないです…

以下がコードです

lambda_sample.h

```cpp
#ifndef LAMBDA_SAMPLE_H
#define LAMBDA_SAMPLE_H
#include <vector>
#include <iostream>
#include <functional>
using std::vector;
using std::cout;

class lambda_sample
{
private:
    vector<std::function<void()>> actions;

public:
    lambda_sample()
    {
    }

    ~lambda_sample()
    {
    }

    void add_action(std::function<void()> action)
    {
        actions.push_back(action);
    }

    void remove_action(std::function<void()> action)
    {
        for (int i = 0; i < actions.size(); ++i)
        {
            if (&action == &actions[i])
            {
                actions.erase(actions.begin() + i);
            }
        }
    }

    void call_all()
    {
        for (auto element : actions)
        {
            element();
        }
    }
};
#endif // LAMBDA_SAMPLE_H
```

lambda_sample.cpp

```cpp
#include "lambda_sample.h"
#include <iostream>
using std::cout;
using std::cin;

int main()
{
    lambda_sample func_array{};
    auto a = [] { cout << "a invoked" << '\n'; };
    auto b = [] { cout << "b invoked" << '\n'; };
    auto c = [] { cout << "c invoked" << '\n'; };
    cout << "a address : " << &a << '\n';
    cout << "b address : " << &b << '\n';
    cout << "c address : " << &c << '\n';
    
    func_array.add_action(a);
    func_array.add_action(b);
    func_array.add_action(c);
    func_array.call_all();
    func_array.remove_action(a);
    func_array.call_all();
    return 0;
}
```

そして以下が実行時のコンソールへの出力

```
a add : 000000937D6FF934
b add : 000000937D6FF954
c add : 000000937D6FF974
a invoked
b invoked
c invoked
a invoked
b invoked
c invoked
```

## 上記の出力を見て考えたこと

1. ~~「ラムダ式のアドレス同じところだったのか」~~ 
(1).アドレスよく見たら違いました... 
2. 「std::vectorの中身のアドレスはどうやろ」

~~1.に関しては匿名関数、使い捨ての関数だからなのでしょう。~~
2.に関しては配列に格納しているから先頭アドレスが返るのだと勝手に思っています
InfluxDB v1系の調査関連InfluxQL

# 概要

InfluxDBは2013年にGo言語で開発されたオープンソースとして時刻情報を主キーとしたデータを扱う時系列データベースです。
v1.x、v2.x、v3.xバージョンが存在して最新v3.xはRust言語で開発されています。
時系列データベースの目的としてはデータの挿入は照会であり、時間に対してのデータの処理です。
Azureの場合、「[Azure Data Explorer](https://azure.microsoft.com/ja-jp/products/data-explorer)」となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/be8f4abe-ffb0-5381-e2bf-d507d31da803.png)

# 用語整理

InfluxDBとリレーションデータベース(RDB)との比較です。

| RDB | InfluxDB |
|:-----------:|:------------:|
| Database | Database |
| Table | Measurement |
| Column | Key |
| Indexed Column | Tag Key |
| Unindexed Column | Field Key |
| Row | Point |

# v1.x系の公式ドキュメント

https://docs.influxdata.com/influxdb/v1/

# v1.x系の調査関連InfluxQL (Influx Query Language)

## データベース一覧

データベースの一覧を出力するコマンドです。
`_internal`は最初から存在するシステム用のデータベースで、`mydb`はユーザーが作成したデータベースとなります。

```bash
> SHOW DATABASES
name: databases
name
----
mydb
_internal
```

## データベースの指定

接続中にデフォルトで利用するデータベースを指定するコマンドです。
デフォルトとなるデータベースを指定しないと毎回クエリでデータベースを明示的に指定する必要があります。

```bash
> use mydb
Using database mydb
```

## メジャーメント一覧

メジャーメントの一覧を出力するコマンドです。
USEのデータベース指定ができてなければデータベース指定が必要があります。

```bash
> SHOW MEASUREMENTS
name: measurements
name
----
measurement_1
measurement_2
```

## 現在実行中のクエリ一覧

```bash
> SHOW QUERIES
qid query        database  duration status
--- -----        --------  -------- ------
6   SHOW QUERIES mydb      0s       running
```

## タグキーの一覧

```bash
> SHOW TAG KEYS
name: measurement_1
tagKey
------
key_type

name: measurement_2
tagKey
------
key_type
```

## タグキーの値一覧

```bash
> SHOW TAG VALUES WITH KEY = "key_type"
name: measurement_1
key      value
---      -----
key_type 2

name: measurement_2
key      value
---      -----
key_type 2
```

## Retention Policies

一定周期ごとにデータを自動的に削除するポリシーを確認します。
v2系ではRetention Periodを代わりに提供されます。

```bash
> SHOW RETENTION POLICIES
name       duration   shardGroupDuration replicaN default
----       --------   ------------------ -------- -------
autogen    0s         168h0m0s           1        true
short      24h0m0s    1h0m0s             1        false
long       8760h0m0s  24h0m0s            1        false
```

## Continuous Queries

一定周期ごとにデータを処理して新しいメジャーメントに保存する(ダウンサンプリング)クエリを確認します。
v2系ではTask를を代わりに提供されます。

```bash
> SHOW CONTINUOUS QUERIES
name: _internal
name query
---- -----

name: mydb
name query
---- -----
```

## Series

組み合わせ可能なタグキーの集合したものです。
たとえば、MemberというMeasurementに名前と年齢がTag Keyとして指定されている場合、保存されているすべてのデータの中で可能な名前と年齢のセットがSeriesです。

```bash
> SHOW SERIES
```
Goに入門

サーバー作りたいので`Go`で書いてみる:grinning:
まずは`Go`の基本的な書き方を確認:star:

## 実行
`.go`のあるフォルダでコマンド実行
```
go run .
```

## エントリーポイント
`main`関数が`Go`のエントリーポイントとなる
```go
package main

import "fmt"

func main() {
    fmt.Println("hello world")
}
```
## パッケージ
標準ライブラリをパッケージとして読み込んで使う（多分:baby_tone2:）
[Standard library](https://pkg.go.dev/std)に色々載ってる
```go
import "fmt"
```

複数を読み込むときの書き方
```go
// 一つずつ宣言しても良い
import "fmt"
import "reflect"

import (
    "fmt"
    "reflect"
)
```

## 数値型
```go
var num int
num = 1
num1 := 1

num2 := 123
var num3 int = 12345678
```
## 浮動小数点
```go
num4 := 1.23
var num5 float64 = 1.2233

// データ型を確認
fmt.Println(reflect.TypeOf((num5)))
```

## 文字列
```go
var string1 string = "hello"
string2 := "good morning"
```

## Boolean
```go
a := 10
b := 1
var num_bool bool = a > b	
```

## 配列
```go
arry := [3]string{"Tom", "Ken", "Mary"}
arry[1] = "Jim"

// 省略記法
arryB := [...]string{"Tom", "Ken", "Mary"}
fmt.Println(arryB[0])

// 2次元配列
arryC := [2][2]string{{"1", "2"}, {"3", "4"}}
fmt.Println(arryC[0][0])
fmt.Println(arryC[0][1])
fmt.Println(reflect.TypeOf(arryC))
```
## if 文
```go
age := 5
if age >= 2 {
    fmt.Println("adult")
} else if age == 0 {
    fmt.Println(("baby"))
} else {
    fmt.Println(("child"))
}

// 簡易文を使ったifステートメント(セミコロンで区切る)
if age := 30; age >= 20 {
    fmt.Println("adult")
} else if age == 0 {
    fmt.Println(("baby"))
} else {
    fmt.Println(("child"))
}
```

## for 文
for文しかないらしい
```go
// for文1
for i := 0; i <= 4; i++ {
    fmt.Println(i)
}

// for文2
i := 0
for i <= 4 {
    fmt.Println(i)
    i++
}

// for文3
i := 0
for {
    fmt.Println(i)
 	if i == 4 {
 		break
	}
 	i++
}
```

## 関数
```go
// 引数なし
func sayHello() {
 	fmt.Println("hello")
}

// 引数あり
func sayHello(greeting string) {
	fmt.Println(greeting)
}

// 引数が同じデータ型の場合は省略できる
// func cal(x int, y int) {
func cal(x, y int) {
	fmt.Println(x * y)
}

//　戻り値があれば戻り値の型も必要
func cal2(x, y int) int {
	return x * y
}

// Pythonのように戻り値を複数返せる
func cal3(x, y int) (int, int) {
	return (x / y), (x * y)
}

func cal4(x, y int) (int, int) {
	a := x / y
	b := x * y
	return a, b
}

// 戻り値を宣言している場合、returnの引数は省略可能
func cal5(x, y int) (a int, b int) {
	a = x / y
	b = x * y
	return
}

func main() {
    // 無名関数 jsの即時関数みたいな書き方
	func(greeting string) {
		fmt.Println(greeting)
	}("hello")
}
```

## 構造体
`Go`にクラスはない
```go
// 構造体
type Person struct {
	name string
	age  int
}

func main() {
	// 構造体の初期化
	var person Person
	person.name = "Tom"
	person.age = 20
	fmt.Println((person))

    // 構造体の初期化2
    person2 := Person{"Ken", 15} // 順不同
    fmt.Println((person2))

    // 構造体の初期化3　フィールド名の指定
    person3 := Person{name: "Foo", age: 30}
    fmt.Println((person3))
 }
```
メソッドの定義
```go
type Student struct {
	name string
	age  int
}

// 構造体にメソッドを定義
func (s Student) printName() {
	fmt.Println(s.name)
}

func main() {
	student := Student{name: "Make", age: 10}
	student.printName() // Make
 }
```

## Reference
- [introduction](https://go.dev/doc/effective_go#introduction)
- [Standard library](https://pkg.go.dev/std)
- [GO](https://go.dev/)
2024/2/14主にITとかセキュリティの記事

シスコのセキュリティアップデート確認を、深刻度「クリティカル」の脆弱性あり(2/12)
https://news.mynavi.jp/techplus/article/20240212-2880275/

シンガポールのサイバー庁がWordPressの暗号ウィジェットがデータ漏えいの可能性があると警告(2/12)
https://nextmoney.jp/?p=63968

Mac狙う新しいバックドアに注意、Visual Studioアップデート偽装(2/12)
https://news.mynavi.jp/techplus/article/20240212-2881995/

中国のサイバー攻撃者、FortiGateの脆弱性を悪用してオランダ軍ネットワークに侵入(2/12)
https://news.mynavi.jp/techplus/article/20240212-2879821/

プログラマーの目線から見たGoogleの失敗・不可解な取り組み41選(2/11)
https://gigazine.net/news/20240211-google-failure/

CPQとは？導入のメリットを解説(2/12)
https://zuuonline.com/archives/275829

ブラウザのパスワード管理機能を使わない5つの理由(2/12)
https://www.lifehacker.jp/article/236637reasons-shouldnt-use-browsers-password-manager-1/

DXコンサルティングとは？　製造業がDXを進める必要性について解説(2/12)
https://zuuonline.com/archives/251507

ChatGPT連携サービス12選！使われている技術やメリット・デメリットも解説(2/12)
https://weel.co.jp/media/collaborative

パソコンがウイルスに感染するとどうなりますか？ 気付かないこともあるのでしょうか【専門家が回答】(2/12)
https://news.allabout.co.jp/articles/o/75408/

「サイバー防衛へ投資強化を」　英高官、日本に促す(2/12)
https://www.nikkei.com/article/DGXZQOCB08B5O0Y4A200C2000000/

国連制裁査察官、仮想通貨企業を狙った北朝鮮のサイバー攻撃疑惑を捜査(2/12)
https://nextmoney.jp/?p=63984

中国に外務省公電漏洩疑惑　「日本版ＣＩＡ」「スパイ防止法」制定急げ　ケント・ギルバート(2/12)
https://www.sankei.com/article/20240212-HCF75YXQWBDXVLSOD4ROB73O2Y/?outputType=theme_weekly-fuji

戦闘機の輸出、日本が探る意味　「防衛産業を考える」 「防衛産業を考える」まとめ読み(2/12)
https://www.nikkei.com/article/DGXZQOUA09ATC0Z00C24A2000000/

北朝鮮の輸入が増加、ロシアとの貿易も急速に拡大―独メディア(2/12)
https://nordot.app/1129707823718007168

「大量監視」認めた日本の司法。「ムスリム捜査情報流出事件」から考えるレイシャルプロファイリング(2/12)
https://nordot.app/1129551548261761899

香港の国家安全条例　人と金の流出招かないか(2/12)
https://mainichi.jp/articles/20240212/ddm/005/070/011000c

DeFi 第2フェーズを考える：開発者・機関投資家・個人投資家の3つの視点から(2/12)
https://www.coindeskjapan.com/217206/

日本の食糧危機を救うカギとなるスマート農業の技術と農村の活性化(2/12)
https://dime.jp/genre/1717073/

資産運用立国への奥の手となるセキュリティートークン、二次流通開始も課題は山積(2/13)
https://xtech.nikkei.com/atcl/nxt/column/18/00138/020501460/

AppleとGoogleのスマホ「エコシステム」寡占にメス、政府が検討する新法案の中身(2/13)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/08890/

PDFのページ編集なら無料アプリの「CubePDF Utility」、パスワード設定も(2/13)
https://xtech.nikkei.com/atcl/nxt/column/18/02726/012200008/

富士通の2つのサービスで不正アクセス被害のエッカ石油、情報流出で謝罪(2/13)
https://xtech.nikkei.com/atcl/nxt/column/18/00598/100500252/
新しくAzureの環境作るから、どうせだったらやってみたいことリスト

弊社で全く新しいサービスを展開することが決まり、ドメインも新しく取得するから全部新しく作ろうってことで、Azure環境も新規に作成し、一部既存から流用することが決まりました。
どうせ新しく作るなら、いままでぐちゃぐちゃなインフラ構成を見直したいな、と

# DB周り
### サーバーログイン時にAzureAD利用で誰がなんの処理したかAuditできるようにする
いままでAdminアカウントをみんなで共有してました、はい。

# NW周り
### パブリック、プライベート分ける
AWSのVPCのようなことはできるんですかね？

# その他
### リソースグループをきちんと管理する
今までルールが無かったので、初期に作られた既存RGを使うか、新規に作りまくるという無法地帯だったので、サービスごともしくは環境(商用、ステージング、テスト)ごとに分けようかと。

#### 随時更新していきます
HttpServletRequestのヘッダをMapに変換

```java
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap
import java.util.Map;
import java.util.stream.Collectors;

public class Utils {

    public static Map<String, String> getHeaderMap(HttpServletRequest request) {

        return  new HashMap<String, String>() {{
            Collections.list(request.getHeaderNames())
            	.stream()
                .forEach(key -> {
                	put(key, request.getHeader(key));
            });
    	}};
    }

}
```
【ChatGPT】YouTube台本

家でとんこつラーメンを作るYouTube動画の台本を作ってみる。

# 利用例

## 入力したプロンプト
```
#指示
あはたは人気があるYouTubeの動画を作成するプロです。
YouTubeの動画の台本を作ってください。

#YouTubeチャンネルの特徴
・YouTubeチャンネル名は「お家でラーメンを味わいたい」
・家でラーメンを作る楽しさを発信する
・タオルを巻いた猫のキャラクター「たま」が高いテンションで話す

#動画のタイトル
手軽に楽しむ！「たま」のお家で作るラーメン講座

#制約条件
・動画の長さは10分
・台本にはセリフに合うリアクションを入れること

#出力
以下の形式で出力してください。
| テーマ|所要時間|台本|
```

## レスポンス（GPT-4）
![IMG_8749.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136275/8a89a581-414e-7125-9773-2d18d18ea952.jpeg)
![IMG_8750.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136275/69d6333b-55f1-cac8-1e41-d866f545e034.jpeg)
![IMG_8751.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136275/2ebb03a9-6ab6-44ff-4fd7-d860ab2ecf71.jpeg)
[Unity]ZenjectのSceneTestFixtureの簡単な使い方

# これはなに？
SceneTestFixtureの簡単なコーディングメモ

# 背景
- プロトタイピングをしたいが、UIを作っていちいち動作させるのがめんどくさすぎた。
- TestRunnerを使ってプロトタイピングしたくなった。
- けれど、ライブラリのセットアップなどをテストコードでするのはめんどくさすぎたので、Scene上にライブラリだけ動作する環境を作って、テストコードから色々試したかった。
- ZenjectIntegrationTestFixtureでSceneをLoadしたが、そのままではITickableが動作しなかったりと色々不都合があった。
- SceneTestFixtureでLoadSceneを行ったところ正常動作したが、コーディングに色々試行錯誤したためメモを残すことにした。



# 気をつけること
#### テストのAssemblyはターゲットのプラットフォームを選択する(ex.MobileならiOS,Androidなど)
これやらないとTestRunnerのPlayModeのところにテストケースが載りません。
#### テストするシーンをBuildSettingに追加しておく
そりゃそうじゃ
#### テストクラスはSceneTestFixtureを継承する
ITickableとかちゃんと動いてくれる
#### 各テストメソッドでyield return LoadScene("SceneName");する
[SetUp]とかでやるとうまく動かない。なぜかはまだ考えないことにした。
#### SceneContextはLoadSceneの記述のあとでDIする
シーン立ち上げないとSceneContextがそもそも無い

# 実装例
このように、シーン内で定義したDIContainerにテストコードからアクセスできる。
結果、色々はかどる。
```C#

// IAAAに準拠するAAAImplクラス
public class AAAImpl : IAAA{
}

/*
IAAAに依存しているBBBImplクラス
IBBBに準拠する
*/
public class BBBImpl : IBBB {
    readonly IAAA aaa;
    [Inject]
    public Hoge ( IAAA aaa){
        this.aaa = aaa;
    }
}

/// シーン(SceneName.scene)内でSceneContextで呼び出されてるInstaller
public class Fuga : MonoInstaller {
    /// IAAAにAAAImplを注入しちゃうぞ
    Container.Bind<IAAA>().To<AAAImpl>().AsCached();
}

/// TestAssemblyの中に作成したシーンテスト用クラス
public class Hoge : SceneTestFixture {
    [UnityTest]
    public IEnumerator 依存解決できるか(){
        yield return LoadScene("SceneName");
        /// IBBBにBBBImplを注入
        SceneContainer.Bind<IBBB>().To<BBBImpl>().AsCached();
        /// 依存性の解決
        /// シーン内で定義したIAAAの依存も解決して、AAAImplが注入されたBBBImplが誕生する。ハッピーバースデー
        var b = SceneContainer.Resolve<IBBB>();
        /// 依存解決できてるかテスト
        Assert.IsNotNull(b , "bの依存性解決に失敗した");
    }
}
```
Teamsチームメンバーの追加or削除をトリガーとするPowerAutomateフロー一本化

# 背景
Teamsにはチームメンバーが追加された時、削除された時それぞれのトリガーが存在します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670355/72a3fe74-7cdd-7b57-77ad-958eaf17a286.png)
これだと追加された時用のフローと削除された時用のフローの両方が欲しい時は2個のフロー作成必要でちょっと面倒。
↓を使えばフローが1本化できて管理がちょっと楽になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670355/08c7c690-742a-20a3-f678-34871028b52e.png)

# つまづきポイント
メンバーが削除された時は↓で判定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670355/be619b08-d390-01ba-863d-da3b0227dd48.png)
"deleted"で判定するのが実際に誰かを削除（犠牲）して検証しないと分からなかった。。。

# 心配ごと
こんな一言メモみたいな投稿をQiitaに残してよいのか少し不安です。。。
ガイドラインには下記の記述が。
> 例えば以下のような記事を書くことはやめましょう。
>
> 自分だけがわかる用語などを用いて、用語に対する説明を行わない
> 文章として成立していないメモや走り書きを投稿する

https://help.qiita.com/ja/articles/qiita-community-guideline

もし不適切だと思われる方がおられましたらご指摘いただければ幸いです。。。
自分がつまづいたポイントを共有して誰かの杖になれば、という思いで投稿しております。
MisskeyのAPIの叩き方(curl, Ruby)



https://misskey-hub.net/ja/docs/for-developers/api/

Misskeyの各サーバーはAPIを公開していて、そのAPIを使ってBotやツールを作れます。GoやJavaScriptなどいくつかの言語ではAPIのラッパーが存在していますが、今回はそれらを使わず標準ライブラリや標準的なツールのみを使ってAPIを叩く際のコードを紹介します。

トークンの取得方法やAPIのエンドポイントの一覧などについては省略しますので、上記のURLをご覧ください。

## シェルスクリプト(curl)

### フォローしているチャンネルのリストを取得

```sh
misskey_token="misskeyのトークン"
channels=$(curl "https://misskey.io/api/channels/followed" \
  -H 'content-type: application/json' \
  --data-raw "{\"i\":\"${misskey_token}\", \"limit\":100}" \
  | jq -r ".[].name")
```
結果はJSONのテキストなので、jqコマンドなどで必要な情報を取り出して使います。

### 画像をドライブにアップロードする

```sh
folder_id="フォルダーのID"
file_id=$(curl "https://misskey.io/api/drive/files/create" \
  -H 'content-type: multipart/form-data' \
  -F i="${misskey_token}" \
  -F folderId="${folder_id}" \
  -F name="$(date --rfc-3339=seconds).jpg" \
  -F file=@"misskey.jpg" \
  --compressed
```

フォルダーのIDについては、 設定>その他の設定>開発者モード をオンにすると、ドライブのフォルダを右クリックすることでフォルダーIDが取得できるようになります。
ノートに画像を添付する際には、`-F file=@test.jpg`のように`@`マークを付けます。

## Ruby

### 他のユーザーをフォローする

```rb
require 'net/http'
require 'json'

TOKEN = 'misskeyのトークン'
user_id = 'フォローする相手のID'

uri = URI.parse('https://misskey.io/api/following/create')
data = { i: TOKEN, userId: user_id }
res = Net::HTTP.post(uri, JSON[data], { 'Content-Type' => 'application/json' })
```

フォローする相手のIDも同様に、開発者モードをオンにすることでプロフィール画面から取得できるようになります。

### WebSocketを使ってリアルタイムに通知を受け取る

ここでは、websocket-client-simpleというライブラリを使用した例を紹介します。

```rb
require 'websocket-client-simple'
require 'json'

TOKEN = 'misskeyのトークン'
HOST = 'misskey.io'

ws = WebSocket::Client::Simple.connect "wss://#{HOST}/streaming?i=#{TOKEN}"

ws.on :message do |msg|
  json = JSON.parse(msg.data, symbolize_names: true)
  case json[:body][:type]
  when 'followed'
    by = json[:body][:body]
    puts "followed by @#{by[:username]}@#{by[:host] || HOST}"
  when 'note'
    by = json[:body][:body][:user]
    puts "note by @#{by[:username]}@#{by[:host] || HOST}"
    next if by[:isBot]
  else
    puts json[:body][:type]
  end
end

ws.on :open do
  puts 'open!!!'
  ws.send '{ "type": "connect", "body": { "channel": "main", "id": "id" } }'
  ws.send '{ "type": "connect", "body": { "channel": "localTimeline", "id": "id" } }'
end

ws.on :close do |e|
  p e
  exit 1
end

ws.on :error do |e|
  p e
  puts e.backtrace
end

loop do
  sleep 1
end
```

このプログラムを実行すると、misskey側でイベントが起こった際にWebSocketを介して`ws.on :message`から始まる行が実行されます。今回はフォローされたときと、タイムラインにノートが流れた際に誰からなのか表示するようにしています。

WebSocketが接続された際には`ws.on :open`から始まる行が実行され、ホストサーバー側にどのイベントを取得するのか通知します。今回はmainとlocalTimeline(LTL)を読むようにしています。idは任意に決められますが、今回は`"id"`としています。

## おわりに

これまで、スクリーンショットを自動でMisskeyに投稿するプログラムや、ノートに応じて返答するBotなどを作ってきました。しかしその際に参考になるプログラムがあまり無く、APIの叩き方を暗中模索することになり辛かったため今回筆を取りました。この記事を参考に読者のプログラムが動けば幸いです。皆でMisskeyやActivityHubを盛り上げていきましょう！

## 動作環境

```
$ curl --version
curl 8.6.0 (x86_64-pc-linux-gnu) libcurl/8.6.0 OpenSSL/3.2.1 zlib/1.3.1 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.7 libpsl/0.21.2 libssh2/1.11.0 nghttp2/1.59.0 nghttp3/1.1.0
$ jq --version
jq-1.7.1
$ ruby -v
ruby 3.0.6p216 (2023-03-30 revision 23a532679b) [x86_64-linux]
$ gem list websocket-client-simple
websocket-client-simple (0.8.0, 0.5.1)
```
.split()で分割した文字列を効率よく変数に代入する【JavaScript】

文字列分割をする時のテクニックと呼ぶほどのものでもないちょっとした小ネタ。

# 効率の悪い書き方
文字列を区切って配列化した後、キー指定でそのまま使うのは不親切なのでわかりやすい変数に代入していた。
```javascript
const fullName = 'Minami-Amy-Tanaka'; // 分割対象の文字列

// 区切り文字で分割して配列化
const nameArray = fullName.split('-');
// 配列をキー指定して変数に代入していく
const firstName = nameArray[0];
const middleName = nameArray[1];
const lastName = nameArray[2];

console.log(firstName);  // Minami
console.log(middleName); // Amy
console.log(lastName);   // Tanaka
```

# 効率の良い書き方
`.split()`で分割して生成した配列の要素を`.map()`でそのまま返して分割代入するという合わせ技。
```javascript
const fullName = 'Minami-Amy-Tanaka'; // 分割対象の文字列

// 区切って配列化したものを分割代入
const [firstName, middleName, lastName] = fullName.split('-').map(str => str);

console.log(firstName);  // Minami
console.log(middleName); // Amy
console.log(lastName);   // Tanaka
```
# おわりに
何を以て効率が良いと定義するかにもよると思いますが、これはこれでスッキリして良いと思います。

## 参考
- [String.prototype.split() - JavaScript - MDN Web Docs - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/split)
- [分割代入 - JavaScript - MDN Web Docs - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
- [Array.prototype.map() - JavaScript - MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
BigQueryのデータバックアップについて

## 概要
Google Cloudの資格の一つである、「Professional Data Engineer」の勉強メモとしてまとめようと思っています。
今回はBigQueryのバックアップについてまとめてみました。

:::note warn
お願い
勉強中ですので、内容が間違っている可能性があります。
その際はご指摘いただければ幸いです。
:::

## 更新履歴
* 2024.02.14 新規作成

## バックアップ方法
### [タイムトラベル機能](https://cloud.google.com/bigquery/docs/time-travel?hl=ja)
2-7日間(デフォルトは7日)で指定した期間のうちの変更分を保持していますので、任意の時に戻せるような機能が標準で備わっています。
リージョン障害には対応できませんが、7日以内でのデータ修正などには利用可能です。
また、誤ってデータを削除し、タイムトラベルで指定した期間が過ぎた場合はフェールセーフ機能によって7日間は保持されるそうです。

---

### [テーブルスナップショット](https://cloud.google.com/bigquery/docs/table-snapshots-intro?hl=ja)
ある特定の地点のデータを残したい場合に利用します。
VMのスナップショットみたいな感じで、データ更新する前やパイプライン処理を保守した際、念のため取っておくという使い方になるかなと思います。
スナップショットはタイムトラベルの期間を過ぎてもに残るので、例えば14日前のデータ更新が間違っていたことが分かった場合に戻すことができたりします。
ただ、スナップショットはCopy on Writeなので料金が発生しませんが、元のテーブルでデータの変更が発生すると料金が発生します。
※追加では発生しないようです。
更新の仕方によっては想定以上の料金が発生するため、更新頻度が低いデータについて使用するのがよさそうです。
また、[テーブルクローン](https://cloud.google.com/bigquery/docs/table-clones-intro?hl=ja)もありますが、こちらはどちらかというとサンドボックス的な使い方になると思われますので、割愛します。

----

### [データセットのコピー](https://cloud.google.com/bigquery/docs/managing-datasets?hl=ja#copy-datasets)

:::note warn
注意
2024.02.12時点でまだpre-GAです。
:::
データセットのコピーは、単純に別のデータセットにデータをコピーするだけとなります。同一リージョンでも、別リージョンでも可能です。
このコピーには[BigQuery Data Transfer Service ](https://cloud.google.com/bigquery/docs/dts-introduction?hl=ja)が使用されていますので、データバックアップを特定の周期で取得することが可能です。別リージョンにコピーしておくと、リージョン障害時の事業継続も可能になります。
ただ、このデータコピーはフルコピーなので料金は倍かかります。

---

### [GCS(Google Cloud Storage)へのExport](https://cloud.google.com/bigquery/docs/exporting-data?hl=ja)
BigQueryの各テーブルデータをGoogle Cloud StorageへExportすることが可能です。
Exportするファイルの種類も様々ありますので、毎日のデータをバックアップする際に利用できます。
ただし、ExportするGCSを配置するリージョンはBigQueryと同じリージョンにしていないと、復旧の際に戻せなくなります。
毎日のデータをバックアップするのに一番適しているやり方だと思われます。

---

## どんな問題が出そうか
::: note warn
注意
実際の問題を見ていないので、調べた内容から私が勝手に問題にできそうなものを書いています。
:::

問題を出す上でキーワードになりそうと思ったのは以下です。
* 7日以内
7日以内のデータを変更時に戻したいときどうするかという問題でタイムトラベルを選択させるというのが問題にしやすそうだなと思います。
ただし、テーブルを削除してしまっているなどあればタイムトラベルは使えないので、この2つを条件に出して問題が作れそうだなと思います。
* 8日以降(例：9日前とか2週間前とか)
* データ更新頻度
* コスト
* リージョン障害
上記の4つを元に問題を出せそうな気がします。

例1)
更新頻度低いデータに対して、2日後に作業で更新が発生する。
次回更新されるのが10日後の時、作業で実施した更新が原因だった場合元に戻したい。
2日後の作業でコストを最も小さくしつつバックアップを取得する方法はなにかという問題で、スナップショットを選ばせるという問題ができます。

例2)
更新頻度が低いデータに対して、3日後に作業で更新が発生する。
次回更新されるのが13日後の時、作業で実施した更新が原因だった場合元に戻したい。また、作業後にリージョン障害が発生した際にも別リージョンでデータを参照できるようにしたい。
3日後の作業でバックアップをどのように取得する方法は何かといった問題で、テーブルクローンを選ばせるという問題ができます。

例3)
更新頻度が高いデータ(毎日1回更新)に対して、7日間を過ぎてから更新前のデータを見たい場面が発生する。
この時、コストを最も小さくしつつバックアップをどのように取得する方法はなにかといった問題で、GCSへのExportを選ばせるという問題ができます。
【Git】git resetのオプションって何をどう使うの？

こんばんは～
今回はgitを使う上では欠かせないgit resetのオプション(soft, hard, mixed)の使うシーンと使った際の処理の違いについて説明します！
1人でgitをcommitやpushしていたときはあまりコメントに気を使っていませんでしたが、ついにチーム開発ということで、他の人に分かりやすく、間違いなくcommitするためにgit resetの方法を知っていくことは必須でした！(感想)

## git reset --softはどんな時に使う？
　『commitするときのコメント打ってる途中でenter押してしちゃったー』『手が勝手にcommitしてた～』という時ありますよね！そこでストップしてください！こんな時に使えるのがsoftオプションです。
 ```terminal
 $ git reset --soft
 ```
 このコマンドを打つと何が起きるかというと、`git commit -m "コメント"`を打つ直前に戻ることができます。つまり、さっきのcommitはなかったことに！ということになります。逆にcommit以外は何も変わっていないため、git addをした直後の状態で、インデックス(commitする前にgit addで更新された情報を移しておいた場所)や作業ツリー(自分が手元で編集したファイルなど)は変化していません。そのため、もしcommitしなおしたい場合はgit reset --softを打った後にもう一度commitしてみてください。

インデックスや作業ツリーとは何ぞや？という方はこちらの記事がおすすめ

https://tetoblog.org/2021/06/git-index/

## git reset (--mixed)とは？
　実はgit reset --mixedとgit resetは全く同じコマンドです。(git resetのデフォルトが--mixed)そのため、使用する際にはどちらを使ってもOKです！
 ではどんな時に使うかというと、commitしちゃったけどgit addをする前に戻りたい！という時に使います。それってそもそもどんな時かというと、例えば『自分の個人情報が載ったファイルをgit addしちゃった挙句そのまま気づかずcommitしちゃった』という時に用います。このままpushすると設定によっては全世界に自分の個人情報を晒しかねないということで、そんなときにgit resetを使います！
  ```terminal
 $ git reset #どちらを使ってもokです
 $ git reset --mixed
 ```
 これをするとcommitコメントはリセットされ、インデックスは`git add`する前の状態に戻ります。--softではコミットがなかったことになりましたが、--mixsedではそれに付け加えてgit addしなかったことにできます。つまり、git add直前の状態に戻れ、作業ツリーのみそのままです。
 
 git addでインデックスに追加したくないファイルを除外する方法はこちら(.gitignoreファイルについて)

 https://phoeducation.work/entry/20210813/1628809080

 ## git reset --hardは何ができる？
　これは先ほどの--mixsedの内容に加えて、前回のコミット後から編集したファイルの更新をすべてなかったことにできてしまいます。つまり、作業ツリーの更新データはすべて消え、前回のcommit直後の状態に戻るということです。正確には前回のcommit情報で現在の作業ツリーを上書きするというイメージです。commit、インデックス、作業ツリーのすべてが前回コミットの状況までリセットされます。
```terminal
$ git reset --hard
```
これは何らかの機能を実装したが最初から間違っていた、やり直した方が早いかもという時に使えるかもしれませんが、他にも書いた記述はすべてリセットされてしまうので、慎重に使いたいですね。

今回参考にさせていただいた記事はこちらです(全体)。

https://www-creators.com/archives/1069#git_reset-3

一番コンパクトで正しい説明文が載っているので、オプションを理解できたらこちらで覚えていただけるといいかなと思います。

#### おまけ(今日のgitエラー対処法)
 今日2人で同じbranchをcommitしてエラーが出たので:sweat_smile:(初心者あるある？)、その時に参考にした記事を載せておきます。

https://www-creators.com/archives/1097#i

また、ディレクトリ作成後、ターミナルでSSHのURLを間違えて登録してしまったときの対処法も参考にさせていただいたので、こちらもおまけで載せます。

https://qiita.com/minoringo/items/917e325892733e0d606e