OmniAICreator/Qiita-1.07M huggingface dataset:
replitで数あてゲーム

数あてゲーム（数当てゲーム、数猜測遊戲）は、プレイヤーがある範囲内の数を推測し、正解を当てるゲームです。典型的な数あてゲームのルールと仕組みは次のようなものです：

### 基本ルール
1. **範囲の設定**: ゲームの開始時に、当てる数の範囲が設定されます。例えば、1から100までの数など。
2. **数の選択**: ゲームの管理者（コンピューターまたは他のプレイヤー）がその範囲内のある数をランダムに選びます。この数はプレイヤーには見えません。
3. **推測の開始**: プレイヤーはその範囲内の数を推測して入力します。
4. **ヒントの提供**: 各推測の後、管理者は推測が正解の数より「大きい」か「小さい」かをプレイヤーに伝えます。
5. **繰り返し**: プレイヤーは正解を当てるまで推測を繰り返します。
6. **正解**: プレイヤーが正解の数を当てたらゲーム終了です。

### 例
1. コンピューターが1から100までの数から50を選んだとします。
2. プレイヤーが30を推測します。
3. コンピューターは「正解の数はそれより大きい」と伝えます。
4. 次にプレイヤーが70を推測します。
5. コンピューターは「正解の数はそれより小さい」と伝えます。
6. プレイヤーが50を推測します。
7. コンピューターは「正解です」と伝え、ゲーム終了です。

### 変種
- **制限回数モード**: プレイヤーが推測できる回数に制限があり、限られた回数内で正解を当てる必要があります。
- **マルチプレイヤーモード**: 複数のプレイヤーが交互に推測を行い、誰が先に正解を当てるかを競います。
- **範囲の動的変更**: 正解に近づくにつれ、範囲が狭まっていくルールもあります。

このように、数あてゲームはシンプルながらも楽しさと緊張感を提供するゲームであり、プログラミングの入門教材としてもよく用いられます。
    import random

    def guess_number_game():
    print("=== 数当てゲーム ===")
    print("1から100の間の数を当ててください。")

    secret_number = random.randint(1, 100)
    attempts = 0
    max_attempts = 10

    while attempts < max_attempts:
        guess = int(input("あなたの予想する数を入力してください: "))

        attempts += 1

        if guess < secret_number:
            print("もっと大きな数です。")
        elif guess > secret_number:
            print("もっと小さな数です。")
        else:
            print(f"おめでとうございます！ {secret_number} は正解です。")
            print(f"あなたは {attempts} 回目で正解しました。")
            break

        if attempts == max_attempts:
            print("残念！チャンスは使い果たしました。正解は", secret_number)

    play_again = input("もう一度プレイしますか？ (yes/no): ")
    if play_again.lower() == "yes" or play_again.lower() == "y":
        guess_number_game()
    else:
        print("ゲームを終了します。お疲れ様でした。")

    #ゲームの開始
    guess_number_game()
開発者モードの主要なCookie属性

## 概要
ブラウザの開発者モードで見ることができるネットワークのCookieについて、確認の仕方、主要な属性を記載しています。



## 確認手順

①ログイン画面でログイン

②ログイン後の通信ページをクリック

③リクエストヘッダー 「Cookie」 チェック
`PHPSESSID=p6cq649369vt9s7iid9f0m5.....…`
<br>

![screenshot_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711935/6cd32dcd-2f7b-3382-eefc-50f8481f92a5.png)
<br>

④ 「Cookie」 ヘッダーオプションで確認

![screenshot_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711935/3c5232ea-8f7e-0081-255a-cb3f34cb5083.png)


## 主要な属性の説明

#### **1\. 名前**

Cookieの名前指定、サーバーに送信される際に、特定のCookieを識別するためのキーとなります。
<br>

#### **2\. 値**

セッション識別子
<br>


#### **3\. Domain**

このCookieが有効であるドメインを指定、Cookieはそのドメインでアクセス可能になります。
<br>


#### **4\. Path**

このCookieが有効であるパスを指定、 `/`  はそのドメイン全てのページでCookieが有効になります。
<br>


#### **5\. Expires/Max-Age (有効期限/最大年齢)**

**`Expires:`**  Cookieがいつ期限切れになるかを示します。
具体的な日付と時間（通常はGMT）で設定されます。

「セッション」と表記されている場合※画像の状態
Cookieは、ブラウザが開かれている間のみ存在し、ブラウザが閉じられると自動的に削除されます。


**`Max-Age:`** この属性は、Cookieが作成されてからどれくらいの秒数で期限切れになるかを示します。`Max-Age`が設定されている場合、`Expires`よりも優先されます。
AWS Certified Solutions Architect - Associate(SAA-C03)に合格するための施策

## 前書き
直近一年間、業務中やプライベートでAWSを使用する機会が非常に多くて、理解度を検証するために[Solutions Architect - Associate(SAA-C03)](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)を受験し、合格しました。
この記事で行った勉強や使用した教材を紹介します。
![E8801E54-A482-48B6-9CBD-50E3BA358A3A.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/8616ffb8-157f-b424-e1a4-a3e7627d2ebe.jpeg)


## 試験問題サンプル
![6EF5C5B7-B317-49E3-B8CB-0C27B2BFEA73_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/05164729-abf9-11bd-cbfd-d067201ac227.jpeg)

多分公式が出してます。[リンク](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Sample-Questions.pdf)
回答付きで全10問、無料公開されてます。
難易度は本番試験レベルで、SAAの試験を受けてみたいと思ったら、まずこのサンプル問題解いてみるのが良いと思います。

## AWS認定資格試験テキスト　AWS認定ソリューションアーキテクト - アソシエイト　改訂第3版
![71hjjuFv5+L._SY466_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/2848e08f-5bb5-82c4-8860-6bc8747cae8f.jpeg)

2023年9月に発売されました。
試験対象となるサービスの解説と練習問題、模擬問題も含まれています。個人的には読みやすかったです。
ただし、どうしても紙の本は情報量に限りがあるため、この一冊だけでは多少物足りなさを感じました。

## AWS教科書 AWS認定ソリューションアーキテクトアソシエイト テキスト＆問題集

![81FDHmzF7RL._SY425_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/1f9be939-84ec-40ca-0de3-ed01d040d578.jpeg)
2024年4月に発売されました。比較的新しい本です。
解説の範囲や難易度は『AWS認定資格試験テキスト』と近いですが、より多くのサービスの解説を網羅しており、さらにサービスごとに重要度の印も付けられています。
試験問題の量も多く、さらにダウンロード模試も一回分付いています。より試験対策に特化した印象でした。
気のせいかもしれませんが、この本の試験問題は本番試験問題により近い気がします。

## 【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）

![8E457FE2-D96C-4530-B6AD-9599316BB6D3_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/a126c64c-3a8e-e910-8195-10fc961d1d9f.jpeg)
Udemyの過去問コンテンツ、最新の模擬試験1回分と、多少古いもの5回分が含まれています。
回答後には詳細なレポートが表示され、間違った問題を見直しやすくなります。説明もテキストと画像付きでわかりやすく、知識が不足している分野を見つけやすくなっています。試験前に過去問をひたすら解きたい方や、自分の弱点を見つけて対策したい方におすすめです。
筆者はすべての過去問を受けて、正解率は6～7割でした。本番より軽い気持ちで受けていたこともありますが、本番問題の難易度に近い問題集という印象でした。

## 【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座

![93151A95-C955-40B5-8C4A-EEA9BF36D9DF.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/9874f481-ac42-52ec-3d2d-f851d8d11295.jpeg)

神です!
試験範囲内のサービスはAWSコンソール上で実際に操作しながら解説します。手を動かせるので、ただ本を読むだけよりも理解しやすく、忘れにくいです。
また、模擬試験も2回分付いており、「これだけでOK!」は大袈裟ではありません。一番おすすめです。

## 試験本番

試験は65問で130分です。
問題文が長い問いもあり、国語試験のような解読力が試される問題もある印象でした。
試験問題には見直しフラグが存在するため、確信が持てない場合は一旦フラグを立て、最後に問題を見直す機能を活用するのが良いと思います。
github copilot chatにファイル添付ボタンが作成された


# github copilotにファイル添付ボタンが作成された

## はじめに

見た方が早いので、画像を貼ります。

![github copilot chat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/542dd7d5-bce9-0eb0-94aa-5b3e830f9c53.png)

チャット欄の左側のマイクボタンと送信ボタンの間にファイル添付ボタンが作成されました。

## 使い方

ファイル添付ボタンをクリックすると、ファイル選択ダイアログが表示されます。

![ファイル選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/f9774271-7264-2417-5783-77c37e831e1c.png)

一番上には，以下の三つの選択肢があります．

- Selection : 今開いているファイルの現在選択されている範囲を資料として読み込ませます．

- Terminal Selection : 現在開いているターミナルの選択されている範囲を資料として読み込ませます．

- Symbol : 主にmdファイルの見出しやコードブロックを資料として読み込ませます．

それに続いて，最近開いた順にファイルが表示されます．

## 試してみる

試しに，`Selection`と`__docs.md`を選択してみます．

以下のように，今添付されているものが表示されます．（見やすい！）

![添付](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/ae8d54ec-cc18-f20b-8670-b977b4f40109.png)

すでに添付されているものは，選択肢からなくなります．

![選択肢](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/c021ee26-9a58-0f00-3069-d966246fe49b.png)

## 新しい機能がついたわけではない

元々，`#file`と入力することでファイルを添付することができました．
そのため，新しい機能がついたわけではありません．

しかし，見た目がわかりやすくなったので，使いやすくなったと思います．

:::note warn
`#file`では同じファイルを複数回添付できてしまっていました．

![同じファイル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/9db2d2b7-f8de-12bf-6b76-49fdb8dc5084.png)
:::

ちなみに，わんちゃんgpt-4oみたいなのがついたかと思い，pdfを添付してみましたが，読み込んでくれませんでした．

![pdf](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/a782062c-2620-e93d-b0d8-1a4b3b8dccd5.png)

## おわりに
github copilotにもgpt-4oがついたらいいなぁ．
JAWS-UG 大分 で AWS BuilderCards をプレイ【イベントレポート】

## はじめに

2024/6/14(金) に JAWS-UG 大分のイベントを開催しました

AWS BuilderCards をみんなで遊び、 AWS 各種サービスの話題で盛り上がりました！

https://jawsug-oita.doorkeeper.jp/events/173353

翌日には JBUG 大分も開催しました

https://qiita.com/RyoWakabayashi/private/8b81b00b09c9eea67881

## JAWS とは

JAWS は日本の AWS ユーザー会です

日本全国の地域支部や、セキュリティ、メディアなど分野・技術に特化した支部が多数活動しています

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

https://jaws-ug.jp/

## AWS BuilderCards とは

AWS BuilderCards は AWS を楽しく学べるカードゲームです

AWS の初心者から上級者まで、誰でも楽しめる内容になっています

詳しくは公式ブログを参照してください

https://aws.amazon.com/jp/builders-flash/202405/japanese-builder-cards/

## AWS BuilderCards のルール

ルールは前述のブログにも書いてありますが、イベントでは [98lerr](https://x.com/98lerr) さんが1枚にまとめてくれた資料を印刷して配布しました

https://speakerdeck.com/98lerr/aws-builder-cards-guide-ver-dot-2024-dot-03-dot-02

慣れないうちは何度もルールを確認しながら進めるので、1枚にまとまっているのは大変助かりました

## イベントの様子

畳の上という JAWS-UG 大分らしい風景

https://x.com/fm609hr/status/1801563201278251292

何らかの絵画のような構図の三人

https://x.com/sugimisu/status/1801559606625505532

AWS ユーザーには見慣れたアイコンが並んでいます

https://x.com/tahara0119/status/1801580604817129961

「EC2 を中心として構築していくか」「Lambda を中心として構築していくか」というのが大筋の戦略になっていきます

サーバーレス好きな私はついつい Lambda を集めますが、それと組み合わせて効果を発揮できるカードが来るかは、、、

そういう意味では、AWS を普段から使っている、サービスに愛着がある人ほど戦略が非合理的になる傾向あり

https://x.com/nakaji573/status/1801576685940392202

## 反省点

新しいカードセットを開けてプレイしたのですが、シャッフルが足りなかったせいで結構カードが偏ってしまいました

特に EC2 が山の底に沈んでいたため、全く出てこず

組み合わせで発動するエフェクトがなかなか活かされませんでした

プレイする前には十分シャッフルしましょう

## 懇親会

豊後魚鮮水産さんで懇親会

https://uosensuisan.com/oita/

年代を超えた交流ができました

## まとめ

参加者全員で AWS BuilderCards をプレイすることができました

初めてのイベント参加者も多く、盛り上がって非常に良いイベントになりました
闘魂Elixir ーー AtCoder Beginner Contest 343(B)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 343](https://atcoder.jp/contests/abc343)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [B - Adjacency Matrix](https://atcoder.jp/contests/abc343/tasks/abc343_b)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_

私にとっては、問題文の意味を理解するのに一苦労でした。実はけっこう単純で、1が立っているところのインデックス（左端が1)を行ごとに出力しなさいというものです。解法の骨格にはおなじみの専門家の間では畳み込みと呼ばれている[Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3)関数を使いました。

```elixir
defmodule Main do
  def main do
    n = IO.read(:line) |> String.trim() |> String.to_integer()
    
    list_of_lists = for _i <- 1..n do
      IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)
    end
    
    solve(list_of_lists)
    |> IO.puts()
  end
  
  def solve(list_of_lists) do
    list_of_lists
    |> Enum.reduce([], fn list, acc ->
      Enum.with_index(list, 1)
      |> Enum.reduce([], fn
        {0, _}, acc -> acc
        {1, index}, acc -> [index | acc]
      end)
      |> Enum.reverse()
      |> Enum.join(" ")
      |> List.wrap()
      |> Kernel.++(acc)
    end)
    |> Enum.reverse()
    |> Enum.join("\n")
  end
end
```




</details>




---

# さいごに

[AtCoder Beginner Contest 343](https://atcoder.jp/contests/abc343)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
闘魂Elixir ーー AtCoder Beginner Contest 343(A)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 343](https://atcoder.jp/contests/abc343)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [A - Wrong Answer](https://atcoder.jp/contests/abc343/tasks/abc343_a)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_

少し珍しい問題かもしれません。何でもよい（いずれかひとつ出力してください）と言われると迷います。迷いますが、「迷わず行けよ行けば分かるさ」の精神で一歩踏み出すしかありません。何でもよいと言われたので、リストの中から任意の要素を取り出す[https://hexdocs.pm/elixir/Enum.html#random/1](Enum.random/1)関数を使ってみました。

```elixir
defmodule Main do
  def main do
    [a, b] =
      IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)
    
    solve(a, b)
    |> IO.puts()
  end
  
  def solve(a, b) do
    Enum.reject(0..9, & &1 == a+ b)
    |> Enum.random()
  end
end
```




</details>




---

# さいごに

[AtCoder Beginner Contest 343](https://atcoder.jp/contests/abc343)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
書評「エンジニアのためのマネジメント入門」

https://gihyo.jp/book/2023/978-4-297-13334-4

マネジメントにおける広い分野で重要なポイントがわかりやすく書かれており、入門書としては私にはピッタリでした。
いくつか、章をピックアップして感想を述べたいと思います。

## 第3章 『チームをエンジニアリングする』

私は若手時代から小規模の会社でばかり働いていて、マネジメントなどのない状態、手本とできることがない中での業務が多かったので、今は自分が「やってみせて」を実現できることを強く意識していました。

しかし、それにこだわりすぎて本書での「6つのリーダーシップスタイル」の「先導型リーダーシップ」に走りすぎていたのだなと反省しました。

> 指示者の能力の限界が、組織の能力の限界になってしまうのです。

確かに先導型ではメンバーそれぞれがリーダーやマネージャーより高い能力がある部分を活かしきれいないし、現状で自分自身が蓋をしてしまっていた部分もあると感じました。

マイクロマネジメントになるべくならないように、やり方も業務を進める本人にしっかり検討してもらい、応援するべきだと思います。

## 第6章 『人材の成功にコミットする』

構造化面接はすでに自分自身が採用活動の中で実施していましたが、行動面接というのは参考になりました。
ついついサマリーを聞きたくなりますが、そうすると創作の入る余地があるのは確かになと思います。

評価については、一般論や考え方を学びたいと考えていたので、とても参考になりました。
例えば、「外的要因により成果が変動した場合はどう扱えばよいか」など。
成果評価・能力評価・情意評価の3つ要素群の扱いがイメージできました。

## 第7章 『技術とわたしのマネジメント』

> 技術を学ばないエンジニアは尊敬できませんが、マネジメントを学ばないマネージャーも尊敬できません。マネージャーも学び続けなければレベルアップはできないでしょう。

手厳しいなと思う反面、まったくその通りだなと感じました。

「人事評価の基本」で下記のようありましたが、プレイングマネージャーがプレイヤーとしての業務中心となり、マネージャーとしての職務を果たせていないのは、職務放棄とみなされるのかもしれません。

> 人事評価の結果は、被評価者の人生が変わるほどの影響を与えることもあるため、マネージャーは評価の責任を重たく感じることでしょう。「そのような重責は背負いたくない」というマネージャーがいるかもしれませんが、それは職務放棄でしかありません。企業は、企業として社員を評価する必要があり、評価者は直属の上司であるマネージャーが適任です。評価することの一歩目は、人を評価することに対する覚悟を持つところからです。

## マネジメントと向き合う

技術の進歩に追いつくのが難しく、また学習してもきりがなくて逃げ出したくなります。
しかし、技術職として働くかぎり向き合うしかないと考えています。
スピードは遅くても、着実に一歩一歩前進するしかありません。

マネジメントについても、成果を感じにくく、ときに不毛な時間のように感じてしまう。
何が正しいかわからなくなる。
こちらも逃げ出したくなるものです。

しかし、マネージメントは誰かがその役割を担う必要があります。
その立場に立つ必要があるかぎり、これも同様に向き合う必要があるのでしょう。
シークレット情報をpushして怒られたけど、コミットの消し方がわからない

**コメント頂き修正しました。ありがとうございます！**

初心者過ぎてGCPのクレデンシャル情報をpushしてしまったところ…。

```
$ git push origin main
Enumerating objects: 33, done.
Counting objects: 100% (33/33), done.
Delta compression using up to 8 threads
Compressing objects: 100% (23/23), done.
Writing objects: 100% (23/23), 7.48 KiB | 7.48 MiB/s, done.
Total 23 (delta 9), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (9/9), completed with 8 local objects.
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: 
remote: - GITHUB PUSH PROTECTION
remote:   —————————————————————————————————————————
remote:     Resolve the following violations before pushing again
remote: 
remote:     - Push cannot contain secrets
remote: 
remote:     
remote:      (?) Learn how to resolve a blocked push
remote:      https://docs.github.com/code-security/secret-scanning/pushing-a-branch-blocked-by-push-protection
remote:     
remote:      (?) This repository does not have Secret Scanning enabled, but is eligible. Enable Secret Scanning to view and manage detected secrets.
remote:      Visit the repository settings page, https://github.com/sh-go/NenQ/settings/security_analysis
remote:     
remote:     
remote:       —— Google Cloud Service Account Credentials ——————————
remote:        locations:
remote:          - commit: 73111118429ee34e9a081f97ea71f5d81ac276b0
remote:            path: backend/terraform/key.json:1
remote:     
remote:        (?) To push, remove secret from commit(s) or follow this URL to allow the secret.
remote:        https://github.com/sh-go/NenQ/security/secret-scanning/unblock-secret/2hrQpuiDMCyidysiUDLJDZ9SHWe
remote:     
remote: 
remote: 
To https://github.com/sh-go/NenQ.git
 ! [remote rejected] main -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/sh-go/NenQ.git'
```

ちゃんと怒ってくれてpushを止めてくれました。ありがとうGitHub。

書いてある通り、コミットを消すか、シークレット情報をオープンにする許可を出すかのどちらかをしないとpush出来ないそうです。もちろん公開したくはないので、コミットを消してpush出来るようにします。


## `reset`を使おう
`reset`は文字通りリセットになるので、変更を巻き戻してなかったことにします。

類似したものに`revert`がありますが、これは履歴を残しつつ『指定されたコミットを打ち消したよ！』というコミットをします。

https://qiita.com/chihiro/items/2fa827d0eac98109e7ee

なのでコミット履歴が残ってしまい、今回のケースだとpush出来ません。

よって、`reset`を使いました。先程のエラーメッセージに該当コミットのIDがあるので、それを用いて`git reset 7311111`と実行。

よしこれでいける！


## あれ？pushがまた通らない？
`push`したところ、また同じエラーが出ました。`git log --oneline`で確認したところ、

```
7311111 (HEAD -> main) xxxxxxxxxxxxx
d560811 yyyyyyyyyyyyyy
28fcc81 zzzzzzzzzzzzzz
...
```

やはりコミットが消えていない…。なぜだ…。


## 消したいコミットに対して、IDの指定の仕方を間違えてた
数分悩んで調べた結果、gitの公式に説明がありました。

![スクリーンショット 2024-06-16 7.50.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1426862/a8130b16-8407-a5b9-bcb5-a3b4e193f902.png)

文章最後に、

>`git reset 9e5e6a4`を実行すると`master`ブランチがコミット`9e5e6a4`を指すようになります。

とあります。ということは、 **指定したID時点を含み、そこまで戻る** という動きをするんですね。勉強不足でした…。

ということで、`git reset d560811`とし、`add`、 `commit`、 `push`を実行すると無事にpush出来ました！


:::note  info
`reset`でIDを指定するときは、消したいコミットの一つ前のIDを指定しよう！
:::


:::note warn
`revert`でIDを指定するときは、消したいコミットのIDになるので注意
:::
python の datetime で zoneinfo を使って環境が変わっても特定のタイムゾーンの時間を取得する

`datetime.now()` をローカル環境で実行したときは日本時間だったのにクラウド環境で実行したら UTC になるの、あるあるだと思います。

バグにつながるのを防ぐために事前に指定しておいたほうがよいです。

## やりかた

環境が変わっても日本時間を取得するには zoneinfo を使います。（Python3.9以降）

参考：[Python 公式ドキュメント zoneinfo --- IANA タイムゾーンのサポート](https://docs.python.org/ja/3/library/zoneinfo.html)


```python
from zoneinfo import ZoneInfo
from datetime import datetime, timedelta

# ローカル環境から実行
dt = datetime(2020, 10, 31, 12)
print(dt) # 2020-10-31 12:00:00

dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
print(dt) # 2020-10-31 12:00:00-07:00
dt.tzname() # 'PDT'

dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("Asia/Tokyo"))
print(dt) # 2020-10-31 12:00:00+09:00
dt.tzname() # 'JST'


dt = datetime.now() 
print(dt) # 2024-06-16 08:40:08.106375

dt = datetime.now(ZoneInfo("Asia/Tokyo"))
print(dt) # 2024-06-16 08:40:08.118271+09:00

dt = datetime.now(ZoneInfo("America/Los_Angeles"))
print(dt) # 2024-06-15 16:41:19.497516-07:00
```

日本で働いていると扱う機会が少ないと思いますがサマータイムを考慮することもできます。

fold が 1 であればサマータイムを考慮した時間, 0 であればサマータイム遷移前の時間を取得します。

```python
# ロサンゼルスでは 2024年11月3日はサマータイム、11月4日は標準時
dt = datetime(2024, 11, 3, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
print(dt)                 # 2024-11-03 01:00:00-07:00
print(dt.replace(fold=1)) # 2024-11-03 01:00:00-08:00

dt = datetime(2024, 11, 4, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
print(dt)                 # 2024-11-04 01:00:00-08:00
print(dt.replace(fold=1)) # 2024-11-04 01:00:00-08:00
```
テスト業務のないデータサイエンティストが見たTestRailの活用アイデア

# はじめに

https://qiita.com/official-events/5100659e9b4ffbcb941b

この企画をきっかけに、「テクマトリックス株式会社」様のTestRailを知りました💡

残念ながら、私の業務において「テスト」はありません・・・笑

そこで、テスト業務のない人から見たTestRailと活用アイデアを考えてみたいと思います！


# TestRailって？
「Excelを使ったテスト業務に限界を感じていませんか？」
と紹介されていますが、テスト業務をしていない私には、イメージが沸きませんでした・・・。

★TestRail=テスト管理ツール

エクセルとの違いは、下記サイトに非常にわかりやすくまとめてあります💡

https://www.techmatrix.co.jp/product/testrail/excel_testrail.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3091004/50de2232-0658-4e27-5fee-3808dd9e7d77.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3091004/2ced87ad-e23b-b0bb-31ea-4c566461dc48.png)





# 活用アイデア？
上記エクセルでの悩みって、テスト業務意外にも思い当たるところがたくさんあると感じました。


・タスク管理表＋週間報告の管理
・PJ内の細かいタスクの進捗状況の管理
・他部署からの依頼・回答のやり取りの管理

上記内容であれば、横展開できそうな気がしました💡

# 最後に
デモサイトを利用しましたが、どの画面も丁寧な説明ポップが出て、次はここ見るといいよ！と誘導してくれます。
UI/UXに気を配った構成となっていて、非常にわかりやすいです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3091004/35114667-5aa0-cd77-05e2-a45d35802070.png)

テスト業務をされている方は、まずはデモサイトで体験してみるといいかと思います💡
まったく、メールアドレス等の記入は不要でした！
OpenStudioのチュートリアルを試してみる　その7

# 1. はじめに
先日[OpenStudioのチュートリアルを試してみる　その6](https://qiita.com/bebebefu/items/036d3a2b8bb96db7411c)の記事にて、以下のリンクの動画シリーズで紹介されているOpenStudioを用いたfire station（消防署）のモデル作成・シミュレーションの8番目の動画についての手順を追っていきました。今回はこの動画シリーズの9番目の動画の手順を追っていきたいと思います。

https://www.youtube.com/playlist?list=PLRW2KXkdSVUdY2iQ6yjohNT5E5ElLVIhU

# 2. 実施環境
CPU: CORE i5 8th Gen
メモリ: 8GB
OS: Windows 11 22H2

# 3. 手順
本記事で内容・手順を追った動画（上記動画シリーズの9番目の動画）：

https://www.youtube.com/watch?v=0r1-arLaz20&list=PLRW2KXkdSVUdY2iQ6yjohNT5E5ElLVIhU&index=9

## 3.1 Buildings loadの設定の解説
まず以下の図で赤枠で囲んだloadのタブをクリックします。
![スクリーンショット 2024-06-15 085449.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/4d5bc629-6da9-60da-ba49-4ae5d2645d70.png)

そして以下の図で赤枠で囲んだ"People Definitions"を選択し、動画の中では各項目の
解説がなされますが、ここでは特に設定変更はないです。
![スクリーンショット 2024-06-15 085707.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/a347f114-13ae-573d-6b7a-a943eb7711c2.png)

次に以下の図で赤枠で囲んだ"Light Definitions"を選択し、動画の中では各項目の
解説がなされますが、ここでも特に設定変更はないです。
![スクリーンショット 2024-06-15 090011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/eb9c5520-0849-95aa-cec1-cf535ad7dcd5.png)

## 3.2 電子レンジのLoadの設定
以下の図で赤枠で囲んだ項目を"x2"ボタンをクリックして、"Electric Equipment Definitions"をコピーしてMicrowave(電子レンジ)を作成していきます。
![microwave_コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/fe96427b-fca2-4b3c-df71-86edf7a72f7f.png)

"x2"ボタンをクリックしてコピーした項目について、以下の図の赤枠で囲んだ"Name"を"Office Microwave"とします。次に黄色枠で囲んだ"Design Level"を1200Wとします。なお、"Watts Per Space Floor Area"と"Watts Per Person"の項目は何も値を入力しません。
![name_change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/89fa1b85-3385-b0e0-f97d-01c4b36fa35b.png)

## 3.3 電子レンジのScheduleの設定
以下の図で赤枠で囲んだ"Schedules"のタブを選択します。そして"+"ボタンをクリックして新しい項目を追加します。
![Schedule_選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/76dad607-25bd-9a53-83f3-abfc244b6adb.png)

次に以下の図で赤枠で囲んだように"fractional schedule"を選択します。そして"apply"ボタンを押します。
![スクリーンショット 2024-06-15 092418.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/ea9cf8bb-7ad7-b2ca-ae4d-64b0f955e371.png)

そして以下の図で赤枠で囲んだ"Schedule name"を"Office Microwave Schedule"とし、使用時間を7:00～7:04と8:00～8:04と9:32～9:36と11:00～11:04と11:08～11:12と12:00～12:08と16:20～16:24と18:36～18:40に設定します。

![スクリーンショット 2024-06-15 093054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3581920/c91ab479-7b22-b4b8-7e4d-68737c08d217.png)

このあとLoadの方にこのScheduleを紐づけていくと思ったのですが、動画ではLoadの設定の解説するだけでした。紐づけ設定については他の動画で述べるようです。

# 4. まとめ
とりあえずここまでも特にエラーなく進めることができました。なお、今回参考にした動画の中では他にもLoadの設定方法についての紹介がありました。しかしその動画の中ではOpenStudioの設定に反映することはありませんでしたので、本記事では省略しました。
次回は動画シリーズの10番目：https://www.youtube.com/watch?v=_tN3scXakiM&list=PLRW2KXkdSVUdY2iQ6yjohNT5E5ElLVIhU&index=10 を実施していきたいと思います。
【Linux Ubuntu環境】lessコマンドでよく使う操作をまとめてみました

# 1.はじめに
短いテキストファイルやプログラムを読む場合であれば、Linuxのcatコマンドを使って標準出力に表示することが多いと思います。
ログファイルなどの長いテキストファイルやスクロールが必要なプログラムをコマンドプロンプト上で手軽に読みたいときもありますよね？そんなときに、おすすめなのがLinuxのlessコマンドです。

本記事では、Linuxのlessコマンドでよく使う操作をまとめてみました。
本記事で目指すゴールは、「Linux初心者の方がログファイルなどの長いテキストファイルを気軽にコマンドプロンプト上で読めるようになること」です。

# 2.lessコマンドと基本的な使い方

lessコマンドとは何かですが、指定したテキストファイルを1画面ずつ表示するLinuxのコマンドです。コマンドプロンプトで手軽にテキストファイルでの単語の検索や末尾へのジャンプなどができるので、便利です。

以下コマンド例のようにテキストファイル(この例だとsample.txt)を指定し、実行します。
```
less sample.txt
```
lessコマンドを実行すると、指定したファイルの中身が表示され、ファイルの操作はキーボード操作で行います。上記で開いたファイルを閉じたい場合は、キーボード操作で「q」を打ちます。

# 3.lessコマンドのよく使う操作

### ファイルを上下にスクロール
ファイルを上にスクロールするには、キーボード操作で「k」を打ちます。
ファイルを下にスクロールするには、キーボード操作で「j」を打ちます。
また、ファイルの上下スクロールはキーボード操作の矢印キーの上下でも行えるので、
操作しやすい方法で行ってください。

### ファイルの先頭・末尾にジャンプする
ファイルの先頭にジャンプするには、キーボード操作で「g」を打ちます。
ファイルの末尾にジャンプするには、キーボード操作で「G」を打ちます。

### ファイル内で単語を検索する
ファイル内で単語を検索するには、キーボード操作で「/」を打ちます。
例えば「Error」という単語で検索をかけたい場合は以下の例のようにします。
```
/Error
```
ちなみに「/」はファイルの上部から単語を検索します。複数の検索結果があった場合、次の検索結果に移動するには「n」を打ちます。前の検索結果に移動するには「N」を打ちます。

# 4.おわりに
本記事では、Linuxのlessコマンドでよく使う操作をまとめてみました。
lessコマンドは本記事で紹介した方法以外にも、様々なオプションやファイル操作の方法があり、これらを覚えるとより便利に使えますので、興味を持たれた方は他のサイトもご参照ください。
本記事の内容が少しでも何かの役に立てば幸いです。
SpringBoot起動時にdocker-composeも実行してくれるって本当ですか？

# 結論
はい、本当です。

## 設定方法
springboot3.1から
依存関係に以下を含めておくと
SpringBoot起動時にプロジェクトルートにある
docker-composeを自動で実行してくれます。
```
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
```

これがまじ便利です。

### 詳細
以下みたいな感じでdocker-composeを配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916357/93f25571-9a53-e8cb-6f87-0ce9708d0293.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916357/35075600-1628-b01d-7979-46cd3715e4cc.png)



## 注意点

基本的には上記の手順だけで動くのですが
S3の代替としてローカル環境でminioを使用している場合
minioとは別にminio/mcを使ってバケットの作成や初期データの流し込みなどを行うためだけのコンテナを立ち上げると思うのですがそのようなケースだとminio/mcのコンテナが自分の役割を終えると勝手に終了してしまいます。
そしてその終了をspringbootが検知してアプリケーションの起動が中止されてしまうので以下のように
minio/mcに tty:trueを設定して役目が終わった後も起動だけさせてる設定にしておかないといけないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916357/ca57e579-978a-c37a-d05d-43606dd110b2.png)

これはminio/mc以外でも短命のコンテナを使用していると発生する問題なので注意してください。



## 最後に
これはまじ便利。
LeetCode挑戦日記：Day9

# はじめに

最近、業務で実装する時間よりも資料作成やレビューをする時間が多くなってきました。
このままでは自身のコーディング能力が落ちそうで怖いので、LeetCodeを始めてみました。

自身の学習の記録 & LeetCodeに興味のある人が挑戦しやすいように、記事に残していきます。
このような競技プログラミングをした経験がないので、ひよってEasyからやっていきます...

# [Medium] 443. String Compression

文字の配列`chars`が与えられたとき、次のアルゴリズムを使用して圧縮する。

空の文字列`s`から始めます。`chars`の連続する同じ文字のグループごとに以下を実行する。
* グループの長さが1の場合、その文字を`s`に追加
* それ以外の場合は、その文字とグループの長さを`s`に追加
   
圧縮された文字列`s`は別々に返されるのではなく、入力文字配列`chars`に格納する。
グループの長さが10以上の場合は、その長さが`chars`に複数の文字として分割されることに注意が必要。

入力配列を修正し終えた後、配列の新しい長さを返す。

追加の定数空間しか使用しないアルゴリズムを実装する必要がある。

## 素直に解いてみる

### 考え方

1. `chars`の前からなめていき、グループ毎に`chars`の先頭から圧縮した文字列を入れていく

### コーディング

```typescript
function appendGroup(char: string, length: number): string {
    let s = '';
    s += char;
    if (length !== 1) {
        s += length.toString();
    }
    return s;
}

function compress(chars: string[]): number {
    if (chars.length === 1) { return 1; }

    let s = '';
    let groupCharacter = chars[0];
    let groupLength = 1;
    for (let i = 1; i < chars.length; i++) {
        if (groupCharacter === chars[i]) {
            groupLength++;
        } else {
            s += appendGroup(groupCharacter, groupLength);

            groupCharacter = chars[i];
            groupLength = 1;
        }
    }
    s += appendGroup(groupCharacter, groupLength);

    const compressCharacters = s.split('');
    compressCharacters.forEach((char, index) => chars[index] = char);

    return compressCharacters.length;
};
```

### 結果

Runtime：49ms
Beats 100.00%

Memory：52.37MB
Beats 93.56%
【Chakura UI】テンプレートを使っていい感じのデザインにしてみた

# はじめに
現在React×TypeScript×Chakura UIでアプリを作成中です。
最低限の機能実装が終わり、レイアウトを整えている段階で初めてテンプレートを使いました。
Chakura UIのテンプレートは幾つかありますが、**今回は無料で良い感じのデザインが作成できるchoc-uiを使ってみました。**
# choc-uiとは
**Chakra UI コンポーネントの一種**です。前述のとおり、**基本的に無料で使用可能**です。
あくまでも所感ですが、**全体的にスタイリッシュなデザイン**だと思います。（好みです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/0cbb1066-1a49-77ce-852d-24b39f39b763.png)

https://github.com/anubra266/choc-ui

# 実際に使ってみた
今回は投稿記事表示欄を良い感じのデザインにしていきます。
**HP上で使用したいコンポーネントの右側にあるアイコンをクリックすると、CodeSandboxの画面に遷移します。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/88d21a48-683f-2565-8072-a06a1ca59864.png)

CodeSandbox上にこのような形でソースコードが展開されているので、コピペして使っていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/b0cc11b0-0b1d-b97e-7a2a-4b26a73763a4.png)

なお、今回はCardコンポーネントのテンプレートを使ってみました。

https://choc-ui.com/docs/elements/cards#cards/ma

**使用前**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/79687a22-a4a6-1fd2-80a4-d9db21d0ad1b.png)

**使用後**　（まだ修正の余地はありますが。。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/c30b4b3d-b18b-07e4-c72b-4a3c90abdbbd.png)




# おわりに
私はデザインに対してかなり疎い人間なので（後々しっかり勉強したいと思ってます！）、一から構想を練るのは難しい状態にありました。
なので、このようなテンプレを使用できるのはめちゃくちゃありがたいと思います。
# 参考

https://choc-ui.com/
IntelliJでコミット画面のモーダル表示をやめたい

## はじめに
IntelliJでいつからのアップデートから
commit確認画面がモーダルで表示されるようになってそれが邪魔くさかったので
元に戻す方法を調べました。

### Before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916357/08c60b19-1a0c-8a84-d596-d9f6fb11a9a1.png)

### After
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916357/b598b92d-1157-471c-26a0-f9f3e467f6f5.png)


### 設定変更方法
1.⌘ ＋　, で設定画面を開く
2.verisionControllかわcommitを開く
3.use non-modal commit interface にチェックを入れる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916357/39c66350-aae7-3d90-51f1-1d0f59876ae2.png)


以上。
Javaで「多次元配列の初期化」の動作を確認してみた

# 概要

Javaで「多次元配列の初期化」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/array/index8.html

# 実装

以下のファイルを作成しました。
```JSample8_1.java
class JSample8_1{
  public static void main(String[] args){
    int[][] num = {{87,54,67}, {76,92,48}};
    
    for (int i = 0; i < 2; i++){
      for (int j = 0; j < 3; j++){
        System.out.println("num[" + i + "][" + j + "] = " + num[i][j]);
      }
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample8_1.java 
$ java JSample8_1 
num[0][0] = 87
num[0][1] = 54
num[0][2] = 67
num[1][0] = 76
num[1][1] = 92
num[1][2] = 48
```

# まとめ

何かの役に立てばと。
デプロイに毎回こけるのでhuskyとlint-stagedを導入した

最近、WordPressをヘッドレスCMS化してNext.jsでWebサイトを構築しました。ホスティングにはNetlifyを使っています。
実際に構築したサイトがこちらです。
青年海外協力隊でアフリカに行ったときからの友達で彼が個人事業主→法人になるタイミングでサイトリニューアルの依頼を受けて構築させていただきました。
（写真・映像の事業を行なっていて、彼の作品は大好きです）

https://nebonga.com/

話がそれちゃいましたが、サイト構築時に、悩んでいたことがあります。
それは、Netlifyでデプロイするときコケることがありました。
```
12:11:26 AM: Failed to compile.
12:11:26 AM: ./app/layout.tsx
12:11:26 AM: 1:1  Error: Run autofix to sort these imports!  simple-import-sort/imports
```
原因としては、ローカル環境でlintのエラーを解消し忘れていたのです。
エンジニアは怠惰であるべきなのに、僕はなぜ毎回こんなことを手動でやっていたのだろう...。

この問題を解消してくれたのが`husky`、`lint-staged`になります。

## huskyができること
`commit`や`push`のタイミングで自動でスクリプトを走らせることができます。今回の僕の問題でいうと、`lint`が通っていないにも関わらず`push`してしまい、`Netlify`でデプロイされる状態になっていました。
`lint`が通っていない`commit`することができなくなります。

## Next.jsの開発環境にhuskyを導入してみる
導入の前に基本の理解をしておきます。

💡Husky
Gitフックで任意のプログラムを実行するライブラリ

https://typicode.github.io/husky/

💡Gitフック
Gitの特定のコマンドの実行前後にスクリプトを実行する仕組み

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%95%E3%83%83%E3%82%AF

💡lint-staged
Gitで変更されたファイルにのみ`lint`や`format`をするためのライブラリ

https://github.com/lint-staged/lint-staged

それでは導入方法についてです。

### husky&lint-stagedの導入
パッケージをインストールします。
```
$ npm install --save-dev husky lint-staged // huskyとlint-stagedの導入
```
ドキュメントに沿って下記のコマンドを実行します。
```
$ npx husky init
```
`.husky/`ディレクトリに`pre-commit`スクリプトが作成され、`package.json`の`prepare`スクリプトが更新されます。
`package.json`に追加されます。
```diff:package.json
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
+   "prepare": "husky"
},
  ```
またルート直下に.huskyファイルが生成されているかと思います。
```:rootディレクトリ
.husky
├ _
│ ├ pre-commit
│ ├ pre-push
│ └ etc...
└ pre-commit
```

`.husky/pre-commit`ファイルを編集します。
```diff:pre-commit
- npm test
+ npx lint-staged
```

これでインストールは完了しました。

## lint-stagedの設定
```diff:package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
+   "fix:lint": "eslint --fix",
    "prepare": "husky"
  },
+ "lint-staged": {
+   "*.{ts,tsx}": "npm run fix:lint"
+ }
}
```

あとは、プロジェクトの`.eslintrc.json`や`eslint.config.js`のルールに沿って自動で修正されるようになります。

## まとめ
これで品質を保ったコードのみ（`lint`を通ったコード）がPRできるようになりました。
開発を始める前にこのあたりを整えておくべきだったなと勉強になりました。
コピーのやり方

```kotlin
val src = arrayOf<Int?>(1, 2, 3, 4, 5)
var dest = src.clone()
dest += 6

println(dest.contentToString()) // [1, 2, 3, 4, 5]
println(src.contentToString())  // [1, 2, 3, 4, 5, 6]
```
配列の場合は`clone()`を使用してコピーする
```kotlin
val mutableList = mutableListOf('A', 'B')
val copiedMutableList = mutableList.toMutableList()
mutableList += 'C'

println(mutableList)       // [A, B, C]
println(copiedMutableList) // [A, B]
```
リストは`toMutableList()`を使用してコピーできる。

他言語はシャローコピー、ディープコピーなるものがあるがKotlinはどんな仕様なんでしょう？

#### 参考

https://www.techiedelight.com/ja/create-shallow-copy-array-kotlin/

https://qiita.com/sdkei/items/fecde2fac2d2083a3433
【Java】インターフェースのdefaultメソッド衝突問題をアドホックに解説する

## README
- この記事の内容はあくまで"Java Sivlerの試験で問題を解くためのもの"です
- <font color="red">**正しい情報ではないので注意**</font>

## はじめに
### 経緯
Java Silverの勉強してる時に、Interfaceのdefaultメソッドの衝突問題が出てくる。
これがまあ自分にとっては分かりづらい。
自分の直感に対して、出力の違うことがいっぱいある。
そのため、自分のためにイメージ図を作成して覚えることにした。

### ゴール
以下のようなコードの挙動が説明できるようにする。

- 親クラスのInterface vs 子のInterface
    ```java
    interface InterfaceWithSuper {
    	default void hoge() {System.out.println("this is interfaceWithSuper hoge");}
    }
    
    interface InterfaceWithChild {
    	default void hoge() {System.out.println("this is interfaceWithChild hoge");}
    }
    
    class Super implements InterfaceWithSuper{}
    
    
    class Child extends Super implements InterfaceWithChild{};
    
    class Main{
    	public static void main(String[] args){
    		var a = new Child();
    		a.hoge(); // コンパイルエラー
    	}
    }
    ```


## アドホックな説明

### クラスとは？
クラスは以下の３要素をまとめたもの
- メンバー変数 （属性）
- メソッド （操作）
- 親クラス

イメージとしては以下のような感じになる
![スクリーンショット 2024-06-16 4.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567980/16e482c2-9202-b06f-abae-5327f1a6335f.png)


### インターフェースとは？
インターフェースは実態を持たない。
インターフェースは「お前はこの操作(メソッド)を必ず作れよ」という口だけ野郎。

【埋め込む時のイメージ】
![スクリーンショット 2024-06-16 4.21.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567980/5a0f4c1a-74ca-ac22-abab-0eccd43e121f.png)



### インターフェースのdefaultメソッドの場合はどうなる？（オーバーライドしないとき）
インターフェースのdefaultメソッドの場合は、 ***クラスのメソッドには追加されない。***
クラスでメソッドが呼ばれた時に、
「俺持ってないメソッドあんねんけど貸してくれん？？」みたいなノリで呼び出す。

![スクリーンショット 2024-06-16 4.30.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567980/84ea445d-eebd-a0d4-92ab-874cb4851659.png)


### 親クラスにインターフェースを埋め込む時
親クラスに埋め込まれた時も、インターフェースは子供クラスにも貸し出せるようにしておく。
![スクリーンショット 2024-06-16 4.43.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567980/d0598af1-215d-4a86-8a3f-0bb484b81781.png)

### クラスのメソッドを呼び出す時の振る舞い
 - 1.自分自身のメソッドを探す
 - 2.親クラスのメソッドを探す (親クラスがさらなる親クラスを持っている場合は再起的に)
 - 3.貸出可能なインターフェースの中から探す


## じゃあ冒頭のコードはなぜエラーになるのか
1 自分のメソッドは定義されていない (defaultメソッドは借りてくるものなので、メソッドの中にはない)
2 親のメソッドを探すが、そこにもない 
3 借りてくるためにインターフェースの中から探すが、２個あるのでエラーになる

![スクリーンショット 2024-06-16 5.11.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567980/8502b34b-8475-88f5-1611-6423aa9e123d.png)


## まとめ（覚え方）
- オーバーライドしたメソッドは、「クラスに実装される」
- インターフェースのdefaultメソッドは ***「クラスには実装されない」***
    - 必要な時に借りてくる
- メソッドの優先度は、
    - ①自分自身
    - ②親
    - ③インターフェースが持ってるやつ
VB.NETでDB操作する

## 前提条件
・DBは"MicroSoftSManagimentStudio"を使用
・BookListというテーブルから値を取得する
・データテーブルを使用する
<table>
  <thead>
    <tr>
      <th>ID</th><th>Name</th><th>Author</th><th>ReadFlg</th>
    </tr>
  </thead>
  <tr>
    <th>1</th><th>プラネタリウムのふたご</th><th>いしいしんじ</th><th>true</th>
  </tr>
  <tr>
    <th>2</th><th>medium</th><th>相沢渉呼</th><th>false</th>
  </tr>
  <tr>
    <th>3</th><th>ハーモニー</th><th>伊藤計劃</th><th>false</th>
  </tr>
</table>

## SELECT
・データセットでDB接続されている（dsDataSet.xsd）
　・データセット名：dsDataSet
 ・取得した値をaspxに表示する（BookIDをViewStateに保持する）
```vb:BookList.vb
Dim DBConStr As String = "接続文字列"
Using ta As New dsBookListTableAdapters.BookListTableAdapter(DBConStr)
  ' データを取得
  Dim dt As New dsBookList.BookListDataTable()
  'ページデータセットに保持する場合
  'PageDataSet.M_BookList = New dsBookList.BookListDataTable()
  ta.Fill(dt)
  'ta.Fill(PageDataSet.M_BookList)
End Using


```
## INSERT or UPDATE
トランザクションにする
```vb:BookList.vb
Using tran As New Transactions.TransactionScope(Transactions.TransactionScopeOption.Required)
  Using ta As New dsBookListTableAdapters.BookListTableAdapter(DBConStr)
    ' 特定のIDでデータを取得
    Dim dt As New dsBookList.BookListDataTable()
    ta.FillByID(dt, book.ID)

    If dt.Rows.Count = 0 Then
      ' 取得できなかった場合は新規登録
      Dim newRow As DataRow = dt.NewRow()
      With newRow
        ' IDはIdentityとして設定しない
        .Item("Name") = book.Name
        .Item("Author") = book.Author
        .Item("ReadFlg") = book.ReadFlg
      End With
      dt.Rows.Add(newRow)
    Else
      ' 取得できた場合は更新
      Dim row As dsBookList.BookListRow = dt.Rows(0)
      row.Name = book.Name
      row.Author = book.Author
      row.ReadFlg = book.ReadFlg
    End If

    ta.Update(dt)
    'If ta.Update(dt) = 0 Then
      'Exit Sub
    'End If
  END Using
  tran.Complete()
END Using

'PageDataSetに既にta.FillByID(dt, book.ID)で取得したデータがあり、それをベースとする場合
Using tran As New Transactions.TransactionScope(Transactions.TransactionScopeOption.Required)
  Using ta As New dsBookListTableAdapters.BookListTableAdapter(DBConStr)
    ' 特定のIDでデータを取得
    Dim dt As dsBookList.BookListDataTable = PageDataSet.M_BookList

    If dt.Rows.Count = 0 Then
      ' 取得できなかった場合は新規登録
      Dim newRow As dsBookList.BookListRow = dt.NewBookListRow()
      With newRow
        ' IDはIdentityとして設定しない
        .Item("Name") = book.Name
        .Item("Author") = book.Author
        .Item("ReadFlg") = book.ReadFlg
      End With
      dt.AddBookListRow(newRow)
    Else
      ' 取得できた場合は更新
      Dim row As dsBookList.BookListRow = CType(dt.Rows(0), dsBookList.BookListRow)
      row.Name = book.Name
      row.Author = book.Author
      row.ReadFlg = book.ReadFlg
    End If

    ta.Update(dt)
  END Using
  tran.Complete()
END Using
```
CTFのrev作問で簡単な難読化をしたいときに見るメモ

# はじめに
CTFのreversing問ではFLAGを実行ファイル内に隠すものがありますが，平文でFLAGを置くわけにはいきません．

作問時にFLAGをどうやって難読化するかで悩まないよう，簡単なメモを作っておきます．


# 入れ替え
文字列のインデックスを入れ替える．逆順は普通に目grepでばれる．
最低限FLAGが平文にならないように．
``` c
void shuffleStr(char *input, char *output) {
    size_t len = strlen(input);
    for (size_t i = 0; i < len; ++i) {
        output[(i * 7) % len] = input[i];
    }
    output[len] = '\0';
}
```

# XOR
Ghidraで見れば普通に分かる．
``` c
void xor(char *input, char *output, char key) {
    size_t len = strlen(input);
    for (size_t i = 0; i < len; ++i) {
        output[i] = input[i] ^ key;
    }
    output[len] = '\0';
}
```
``` c
size_t len = strlen(input);
size_t keyLen = strlen(key);
for (size_t i = 0; i < len; ++i) {
    output[i] = input[i] ^ key[i % keyLen];
}
```
# シーザー
FLAGのROT13がSYNTなのはよく見る．
``` c
void caesar(char *input, char *output, int shift) {
    size_t len = strlen(input);
    for (size_t i = 0; i < len; ++i) {
        if (input[i] >= 'a' && input[i] <= 'z') {
            output[i] = (input[i] - 'a' + shift) % 26 + 'a';
        } else if (input[i] >= 'A' && input[i] <= 'Z') {
            output[i] = (input[i] - 'A' + shift) % 26 + 'A';
        } else {
            output[i] = input[i];
        }
    }
    output[len] = '\0';
}
```

# 文字コードシフト

Ghidraで見れば分かる．

``` c
void shiftChar(char *str, int shift) {
    for (int i = 0; str[i] != '\0'; i++) {
        str[i] += shift;
    }
}
```

# OpenSSL

opensslに入ってる物を色々使う．
aes, sha, des, rsa ...

``` c
#include <openssl/aes.h>
#include <openssl/sha.h>
```
``` c
void aesEncrypt(const unsigned char *key, const unsigned char *input, unsigned char *output) {
    AES_KEY aesKey;
    AES_set_encrypt_key(key, 128, &aesKey);
    AES_encrypt(input, output, &aesKey);
}

void aesDecrypt(const unsigned char *key, const unsigned char *input, unsigned char *output) {
    AES_KEY aesKey;
    AES_set_decrypt_key(key, 128, &aesKey);
    AES_decrypt(input, output, &aesKey);
}
```
``` c
void sha256Hash(const unsigned char *input, unsigned char *output) {
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, input, strlen((char *)input));
    SHA256_Final(output, &sha256);
}
```

# One-Time
keyをランダム生成する．
このコードは多分使わないが，キーをランダム生成するのはたまによくやる
``` c 
void generateKey(char *key, size_t len) {
    srand(time(NULL));
    for (size_t i = 0; i < len; ++i) {
        key[i] = rand() % 256;
    }
    key[len] = '\0';
}
```

# Obfuscator-LLVM

しっかり難読化して，読ませたくないときに．

https://github.com/obfuscator-llvm/obfuscator?tab=readme-ov-file

https://dl.acm.org/doi/10.5555/2821429.2821434

FLAGを構築する単純な関数などを，このツールで難読化する．

無駄な if や while がたくさん挿入され，Ghidraでデコンパイルしてもまともに読む気を無くすようなコードになる．
```
build/bin/clang -c flag.c -fPIE
```
```
-mllvm -sub
-mllvm -bcf
-mllvm -fla
```
難読化のオプションを3種類つけられる．論文ではオプションの違いやその比較をしているが，使う側としては全部載せでいい……はず．
Difyで作成したアプリをStreamlitに埋め込む方法

## はじめに
`ChatGPT`をはじめとする生成AIは最近のホットトピックであり、様々な活用方法が模索されています。生成AIを活用したアプリケーション開発を独自に行っている企業も多く見受けられます。

そんな中、最近リリースされた`Dify`はノーコードでチャットアプリの開発ができるプラットフォームとして注目を集めています。  これにより、自前で構築するのは面倒なRAGやエージェント機能などを組み込んだアプリを容易に構築、公開することが可能です。

今回は`Dify`で作ったチャットアプリを`Streamlit`で作成したアプリ上に埋め込む方法を解説します。

https://github.com/langgenius/dify/blob/main/README_JA.md

## 必要なもの
- git
- Docker

(`Dify`のシステム要件)
- CPU ≧ 2コア
- RAM ≧ 4GB

## 方法
### 1. `Dify`をローカル環境で起動
```sh
$ git clone https://github.com/langgenius/dify.git
$ cd docker 
$ docker compose up -d
```
これにより`Dify`が起動されるので`http://localhost/install`にアクセスし、各種設定を進めてください。
自前で起動した場合、メールアドレスやパスワード等が漏洩する恐れはありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449785/32fb3de6-aad8-b1c5-028d-fee714290ef8.png)

### 2. `Dify`上でアプリを作成
`Dify`でのアプリ作成方法は、様々な方がわかりやすい記事を書かれているためそちらに譲ります。


### 3. `Streamlit`のアプリを作成
`Streamlit`でアプリを作成する前に、`Dify`アプリを埋め込むためのHTMLコードを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449785/9af4c080-ff27-cd18-8e6b-ed34f9f35348.png)

`Dify`の埋め込みは2パターン用意されています。  
Case1は任意の場所にiframeとして埋め込む方法、Case2はwebページ右下に埋め込む方法です。  
`Streamlit`の場合、Case1ではChatのリフレッシュができなかったため、Case2の利用を進めます。(やり方をご存じの方がいらっしゃればコメントください。)
取得したHTMLコードを`Streamlit`のアプリ上に記述します。

```python:app.py
import streamlit as st
import streamlit.components.v1 as stc

st.title("Embedding Dify app in Streamlit")
# Case 1の場合
st.write("## Case 1.")
# iFrameのHTMLコード
html_code = """
<iframe
 src="http://localhost/chatbot/rPUgO3KU7eCYC9nJ"
 style="width: 100%; height: 100%; min-height: 700px; border: 2;"
 allow="microphone">
</iframe>
"""

# HTMLをStreamlitアプリに埋め込む
stc.html(html_code, height=800)

# Case 2の場合
st.write("## Case 2.")
# HTMLとJavaScriptを埋め込む
html_code = """
<script>
 window.difyChatbotConfig = {
  token: 'rPUgO3KU7eCYC9nJ',
  baseUrl: 'http://localhost'
 }
</script>
<script
 src="http://localhost/embed.min.js"
 id="rPUgO3KU7eCYC9nJ"
 defer>
</script>
"""

stc.html(html_code, height=700)
```
アプリを起動します。
```
streamlit run app.py
```
`http://localhost:8501`にアプリが展開されるので、ブラウザからアクセスします。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449785/bd480068-3229-3b9d-1b13-3e8f99af5906.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449785/f34f66a3-ce31-f972-33ee-a3301d961163.png)

それぞれのCaseで、`Dify`で作成したチャットアプリを使えることが確認できました。
どちらのCaseを採用するかは、用途によって使い分けてください。

## 終わりに
`Streamlit`上にチャットアプリを埋め込む方法を紹介しましたが、同様の手法を使えば、ありとあらゆるアプリケーションにチャットボット機能を追加することができます。これにより、既存のアプリに簡単な変更を加えるだけで、ユーザーエクスペリエンスの向上に貢献することができます。

`Dify`によるチャットボットの普及は、生成AIの民主化の勢いを加速させています。技術が進化する中で、より多くの企業や開発者がAIを活用し、革新的なソリューションを生み出しています。将来的には、生成AIがさらに進化し、私たちの日常生活に深く浸透することが期待されます。


生成AIの可能性はまだ始まったばかりです。その進展を常に注視し、新しい機会を見逃さないことが重要です。
我々はその動向を注目し、未来の可能性に備えて行動していく必要があります。

是非、この機会に`Dify`やその他の生成AIツールを探索し、あなたのアプリケーションに統合してみてください。未来のテクノロジーを今日から活用し、競争力を高める第一歩となるはずです。
さくらレンタルサーバーからBitbucketにSSH接続するための手順

さくらレンタルサーバーを使った例。
リポジトリをHTTPS接続ではなく、SSH接続で管理したい

**備忘録**のため殴り書きです

## レンタルサーバーで鍵を作る

#### レンタルサーバーにSSHで接続する
```
$ ssh {ユーザー名}@{ホスト名}
```

#### 鍵を作成

ユーザーのホームディレクトリにある`.ssh`をカレントディレクトリとして

```
$ ssh-keygen -t rsa
```

1. 任意のファイル名を聞かれる
1. パスフレーズを聞かれる
1. パスフレーズの確認

`{任意のファイル名}` = 秘密鍵ファイル
`{任意のファイル名}.pub` = 公開鍵ファイル
の2ファイルができる。

## Bitbucketのリポジトリに設定する

1. リポジトリの`Repository settings`/`セキュリティ`/`アクセスキー`にアクセス
1. `Add Key`から、作成した**公開鍵ファイル**の中身コピペし設定

## レンタルサーバーからBitbucketにSSHで接続する


レンタルサーバーの`.ssh/config`ファイル（なければ作る）に以下を記述

```
Host bitbucket.org
 HostName altssh.bitbucket.org
 User git
 Port 443
 IdentityFile ~/.ssh/{秘密鍵ファイル}
 TCPKeepAlive yes
 IdentitiesOnly yes
``` 

#### 接続確認
`git fetch`コマンドなどで対象のリポジトリが接続できているか確認

## その他

HTTPSで接続していたリポジトリについて

`git remote get-url origin`でHTTPSとなっていたら以下の通り変更する

`git remote set-url origin git@bitbucket.org:{ワークスペース/リポジトリ名}.git`

（Bitbucketの対象リポジトリのcloneする時のものを指定するで良い）
好みのフレーバーから日本酒を探すWEBアプリをNetlifyでデプロイ


## 自分が好きなフレーバーの日本酒はあるのか？
「今夜日本酒を飲みたい」と思った時、あなたはどうのように酒を探しますか？
蔵元の都道府県やブランドの知名度、精米歩合やパッケージデザイン・・・色々あると思います。
でも好みの味から探すことってあまりないと思いませんか？
辛口か甘口かの分類であれば絞り込みはできますが、それだけでは絞り込みが弱く１つを特定をするところまではなかなか行けないと思います。

そこで、こんなの作ってみました。


## アプリの動作画面
![RPReplay_Final1718468667.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770353/6ea4b65d-f8b2-2193-73f8-9ee1cd802b33.gif)
■動作説明
* スライダーを操作して好みのフレーバーになるように調整する
* サーチボタンを押す
* 好みのフレーバーに近い日本酒が５つ表示される

実際に触ってみる↓

https://amazing-speculoos-905595.netlify.app/


## ソース
今回CodePenを使用してプログラムを書き、Netlifyでデプロイして公開しています。
ソースとリンクは置いておきます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JjqMoJO" data-pen-title="sakeRecommend" data-user="taka-the-sasster" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/taka-the-sasster/pen/JjqMoJO">
  sakeRecommend</a> by taka (<a href="https://codepen.io/taka-the-sasster">@taka-the-sasster</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

https://codepen.io/taka-the-sasster/pen/JjqMoJO

### 個人的に一番重要ポイント
今回APIを使用してさけのわデータから日本酒のデータを取得していますが、API利用に関連して、CodePenのコードとNetlifyにデプロイしているコードは少々違います。

https://sakenowa.com

CodePenからノーマルのやり方でさけのわデータのAPIを呼び出そうとすると、CORSエラーが発生してしまい上手くいきません。（CORSエラーなんて初めて遭遇したのでだいぶ苦労しました。）
詳しく知りたい方はこちらの記事など参考にしてみてください↓
[CORSをざっくり理解し、CORSエラーを解決する](https://zenn.dev/yarai/articles/6e3c5b017a5b8d)

CodePenでは無料のプロキシサーバーを使い対応しました。
```js
const proxyUrl = 'https://cors-anywhere.herokuapp.com/'; //この部分
const targetUrl = 'https://muro.sakenowa.com/sakenowa-data/api/flavor-charts';
const response = await fetch(proxyUrl + targetUrl);
```
（このやり方は最善ではない気がしていますが、一旦動いたのでこちらを採用しています。
他に良い方法があれば適宜変更して試してください。）

__ちなみにこのままNetlifyにデプロイすると動きません。__
デプロイするときは、このコードを次のように書き換えて下さい。
```js
const targetUrl = '/api/sakenowa-data/api/flavor-charts';
const response = await fetch(targetUrl);
```
そして_redirectsファイルを一つ作成して、次のように記述します。
```:_redirects
/api/*  https://muro.sakenowa.com/:splat  200
```
これをJSファイルやHTMLファイルがある階層と同じところに配置してデプロイします。

何をやっているか気になる人は下記の記事確認してみてください～
（Netlifyのプロキシを使うための処理です）

https://docs.netlify.com/routing/redirects/

https://docs.netlify.com/routing/redirects/redirect-options/#splats


## 改善が必要なポイント
何回か操作していただければ分かるのですが、「本当に自分の好みのフレーバーの酒が提案されているのか？」と疑問を持つことがあります。
今回のロジックは6種類のフレーバーをベクトルとして扱い、入力したフレーバーとさけのわデータが保有しているデータをコサイン類似度で類似性を求め、近いものを5個ピックアップするというものです。

私が考える問題点
* あまり似ていなくても5つピックアップされてしまう（⇒閾値か何かを設定した方が良さそう）
* さけのわデータの各フレーバーが0.5に寄っていそう（⇒時間がなく実際に分布を確認していませんが、恐らくほとんどの銘柄が0.3~0.7の範囲に収まっているデータになっており、ユーザーがその範囲外の数値を入れると、結果が直感的に分かりづらいです。分布に基づいて重みづけ等した方が良さそう🤔）

データ分析に興味がある人は、最適なロジックを考えてみてください！


## 最後にこの記事のモチベーションを共有
前回↓の記事を書きました。

https://qiita.com/YopiBee9/items/4e4db0bb00ff3bcc8c58

これは、Codespacesを使用してLINE Botを動かすというものでした。居酒屋での使用をユースケースとして想定していましたが、居酒屋行く前にCodespacesを起動しておくのは面倒くさい。
そこで、いちいち起動・停止の作業しなくても済むものが作りたい。これがモチベーションでした。
飲み会が楽しみです。