OmniAICreator/Qiita-1.07M huggingface dataset:
【VSCode】VSCodeVimでカーソル移動した際に折りたたみが展開されないようにする

## 状況

カーソルを `j`, `k`で移動させ、折りたたみを通過した際に以下のように展開されてしまいました。

![画面収録 2024-06-07 23.46.13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/d1c8a2a3-18fc-b930-6e8c-5f086e876ea9.gif)

## 対処法

`settins.json`に以下の設定を追記します。

```settings.json
{
  "vim.foldfix": true,
  "vim.normalModeKeyBindingsNonRecursive": [
    {
      "before": ["<C-u>"],
      "after": ["H", "z", "z"]
    },
    {
      "before": ["<C-d>"],
      "after": ["L", "z", "z"]
    }
  ]
}

```

`"vim.foldfix": true,` だけでは `<C-d>` や `<C-u>` でスクロールした際に展開されてしまうため、 `"vim.normalModeKeyBindingsNonRecursive"` も合わせて設定する必要があります。

## 参考

https://arc.net/l/quote/ephkgalk

https://zenn.dev/kenfdev/articles/3637e70b450d56
Rails・Rubyでbenchmarkの使い方について

お疲れ様です。

今日は「Rails・Rubyでbenchmarkの使い方について」について部分いたします。

Ruby on RailsとRubyを使用してベンチマークを取るための基本的な方法について説明します。Benchmarkモジュールを使用すると、コードの特定の部分の実行時間を測定することができます。

# 基本的な使い方
RubyのBenchmarkモジュールを使用して、ブロックの実行時間を計測する方法は以下の通りです。

```ruby
require 'benchmark'

Benchmark.bm do |x|
  x.report("sleep 1:") { sleep(1) }
  x.report("sleep 2:") { sleep(2) }
end
```

上記のコードでは、sleepメソッドを使って異なる長さの遅延を挿入し、その実行時間を計測しています。出力は次のようになります。

```
       user     system      total        real
sleep 1:  0.000000   0.000000   0.000000 (  1.001234)
sleep 2:  0.000000   0.000000   0.000000 (  2.002345)
```

## Railsでの使用例

Railsアプリケーションでの具体的な使用例を紹介します。例えば、コントローラのアクションの実行時間を計測する場合です。

```ruby
class ArticlesController < ApplicationController
  def index
    time = Benchmark.realtime do
      @articles = Article.all
    end
    Rails.logger.info "Time to load articles: #{time} seconds"
  end
end
```

この例では、Article.allの実行時間を計測し、ログに出力しています。

# ベンチマーク結果の詳細な表示

より詳細な情報を取得するために、Benchmark.measureを使用することもできます。

```ruby
require 'benchmark'

result = Benchmark.measure do
  # ベンチマークしたい処理
  sleep(1)
end

puts result
```

出力は次のようになります。

```
  0.000000   0.000000   0.000000 (  1.001234)
```

各項目の意味は次の通りです。

- user: ユーザーCPU時間
- system: システムCPU時間
- total: 合計CPU時間
- real: 実時間

# まとめ

RubyのBenchmarkモジュールを使用することで、簡単にコードのパフォーマンスを測定することができます。Railsアプリケーションでも、特定の処理の実行時間を計測して、アプリケーションのパフォーマンス改善に役立てることができます。

今日は以上です。

ありがとうございました。
よろしくお願いいたします。
FlaskとchatGPTのアプリ製作が面白すぎる話

どうも。専門学校でプログラミングを学んでいるとろくまです。
今回はFlaskとchatGPTで無限にアプリが作れるアプリの話をしたいと思います。
    必要なものはFlaskと使用するライブラリの環境とchatGPTのアカウントです。
    学校で教師あり学習のデータを作るために用いる画像を28×28のグレースケールに変換するアプリも30分で作れたし、
    簡単な診断アプリも作ることができたし、
    SQLAlchemyを用いた名刺管理アプリも作ることができました。
作り方は簡単
１　chatGPTに作りたいアプリ名のサンプルコードを作ってと送る
２　フォルダ構造を聞く
３　インストールするライブラリのバージョンを聞く
４　統合開発環境で仮想環境を作る
５　ライブラリを入れる
６　フォルダとhtmlファイルやapp.pyファイルを作る
７　サンプルコードをコピペ
８　完成

まだシンプルなアプリしか作っていませんかこれからもう少し複雑なアプリも作っていきたいと思います。
以上とろくまでした。
Laravel `php artisan queue:retry`でtimeoutの変更が反映されない

バージョン
`Laravel Framework 10.45.1`


Laravelの queue:retry はソースコードの変更は反映される[^1]けど`timeout`の設定が反映されなかったって話

[^1]: キューワーカーのリスタートはする必要がある

# 事象

実装したJobがタイムアウトしてfailed_jobsに入っていた


```
namespace App\Jobs;
class MyCustomJob implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public int $timeout = 100;
...
```

Jobのタイムアウト設定を変更して

```
    public int $timeout = 600;
```

リトライしたけど、やはりタイムアウトしてしまう

`php artisan queue:retry {uuid}`


# 原因

`failed_jobs.payload`

```
{
  "uuid": "c2805ac5-75ef-4e15-b2ba-a92ba4365785",
  "displayName": "App\\Jobs\\MyCustomJob",
  "job": "Illuminate\\Queue\\CallQueuedHandler@call",
  "maxTries": null,
  "maxExceptions": null,
  "failOnTimeout": false,
  "backoff": null,
  "timeout": 100,
  "retryUntil": null,
  "data": {
  }
  ...
```

**!!!**

```
  "timeout": 100,
```

# 解決

`failed_jobs.payload`のjson内のtimeout値を書き換えてからretryする


以上
Vuls Tips色々（覚書）

# つらつらと

体系だってあれこれ考えた話じゃないのですが、後日またやらかしそう（今回またやらかした）話をメモっておこうと思います。

## Vulsを走らせるOSのメモリは２Gじゃ足りない

以下のようにあるのですが、、
https://vuls.io/docs/en/tutorial-vulsctl-docker.html

gostでubuntuのデータをsqlite3で格納するあたりでとんでもなく重たくなりました。
メモリの利用率がかなりたかどまりしており。
仮想化環境の条件も違いはしますが、４G割当している環境ではそういうストレスは特にありませんでした。
流石に2Gはやめておきますか、、

# 脆弱性情報収集時はhttpも開ける

ログ上はhttpsでアクセスしているように表示されるが、裏では多数のURLにアクセスしており、その中にはhttpでのアクセスもある。

# config-test.sh

単純にconfig.tomlの文法チェックをするだけでなく、リモアク先にアクセスしてみて、取得対象として指定しているdockerコンテナがあるかなどを見てくれる。

# dockerコンテナ（動作しているもの）のスキャン

https://vuls.io/docs/en/usage-scan.html#example-scan-running-containers-dockerlxdlxc

スキャンすると、ホストOS側と、コンテナ側の両方がスキャンされる。
コンテナだけにすることもできる。
https://vuls.io/docs/en/usage-scan.html#to-scan-containers-only-docker-host-will-not-be-scanned

ホストとコンテナを両方スキャンしても、結果は明瞭に別れている。

```
# cat ./config.toml 
[servers]

[servers.remotehost]
host               = "10.0.0.65"
user               = "user"
port               = "22"
#keyPath            = "/root/.ssh/id_ed25519"
scanMode           = ["fast"]

[servers.httpd]
host               = "10.0.0.65"
user               = "user"
keyPath            = "/root/.ssh/id_ed25519"
containerType      = "docker"
containersIncluded = ["httpd"]

# ls ./results/2024-05-25T01-19-01+0000/
httpd.json  httpd@httpd.json  remotehost.json
```

コンテナ名とコンフィグ上でのサーバ呼称が両方httpdになっているのでわかりにくいですが、本体とコンテナで別々のjsonに分かれるので、区分けは簡単です。

## CPEスキャン

```
$ cat ./config.toml 
[servers]

[servers.cpe]
type               = "pseudo"
cpeNames           = [
"cpe:/o:fortinet:fortios:4.3.0",
"cpe:/a:python:python:3.8.5",

]
```

XXX.jsonも、他のケースと変わらず。
cpeURIsという要素が増えるが、これはconfig.tomlに書いたものがそのまま表示されているだけで、該当の脆弱性がヒットするcpe一覧などを表示してくれているわけではない。
googletransを使って簡単翻訳



# googletransとは
translate.google.com の Web API を使用する非公式ライブラリ
無料で無制限のPython ライブラリ

https://pypi.org/project/googletrans/

#### googletrans使用する上での注意事項
- 1 つのテキストの最大文字数制限は 15,000
- Google 翻訳の Web バージョンの制限により、この API はライブラリが常に適切に動作することを保証するものではない
- 安定性を気にする場合は[Google の公式翻訳 API](https://cloud.google.com/translate/docs?hl=ja)推奨

https://cloud.google.com/translate/docs?hl=ja


# インストール
```
pip install googletrans==3.1.0a0
```
:::note warn
バージョン指定せずインストールするとエラーが発生するので、
上記のバージョンを指定し、インストールしてください
:::

# スクリプト
```python
from googletrans import Translator

catchphrase = 'なんて日だ！' 

translator = Translator()
translated = translator.translate(catchphrase)
print(translated.text)

# 結果
>>> What a day!
```

<br></br>

デフォルトは英語に設定されているので、言語指定したい場合は
引数を追加して言語を記載する
```python
translated = translator.translate(poem, dest='ko')
print(translated.text)

# 結果
>>> 얼마나 날이야!
```
<br></br>
言語一覧は下記ファイルに記載してある
```
/venv/lib/python3.10/site-packages/googletrans/constants.py
```

# エラー対応

> ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)

上記のエラーが発生した場合、
__verify=False__ 
を画像のように追加してください。

![IMG_1378.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634951/1bad1965-4ef2-e6c9-32a4-6b2ce27f287d.png)

# 参考サイト
https://stackoverflow.com/questions/72234326/how-to-disable-the-security-certificate-check-for-google-translate

https://yonesuke0716.hatenablog.com/entry/2023/02/07/112154

# 最後に
読んでいただきありがとうございます:blush:
もし、別のバージョンで動作するよ！など情報あれば
共有していただきたいです！！

また、記事内容に関してご指摘あればお願い致します。
シェルで一斉にファイルコピーメモ


複数ファイルを、文字列一括置換
```
#!/bin/bash

# 配列の定義
declare -a tasks=(
  "/c/original/aaaa.txt:abc:cde:Abc:Cde"
  "/c/original2/bbbb.txt:def:fgH:Aka:Midori"
)

# 配列の要素をループで処理
for item in "${tasks[@]}"; do
  # ':' で区切られたファイルパスと変換ペアを分離
  IFS=":" read -r src_file -a transformations <<< "$item"
  
  # 一時ファイルの作成
  temp_file=$(mktemp)

  # 元のファイル内容を一時ファイルにコピー
  cp "$src_file" "$temp_file"
  
  # 各変換ペアについて処理
  for (( i=0; i<${#transformations[@]}; i+=2 )); do
    from="${transformations[i]}"
    to="${transformations[i+1]}"
    
    # 一時ファイルでの文字列置換
    sed -i "s/${from}/${to}/g" "$temp_file"
  done

  # 置換後の内容を元のファイルに上書き
  mv "$temp_file" "$src_file"
done

echo "All files processed and transformations applied successfully."


```

複数ファイルを一括コピー＆リネーム
```
#!/bin/bash

# 配列の定義
declare -a files=( "/c/original/aaaa.txt:/c/src/data/" "/c/original/bbbb.txt:/c/src/data/" )

# 配列の要素をループで処理
for item in "${files[@]}"; do
  # ':' で区切られたファイルパスとディレクトリを分離
  IFS=":" read -r src_file dest_dir <<< "$item"

  # コピー先に data.txt が存在する場合は削除
  if [ -f "${dest_dir}data.txt" ]; then
    rm "${dest_dir}data.txt"
  fi

  # ファイルをコピー先にコピー
  cp "$src_file" "$dest_dir"

  # コピーしたファイルを data.txt にリネーム
  mv "${dest_dir}$(basename "$src_file")" "${dest_dir}data.txt"
done

echo "All files processed successfully."

```
【OutSystems】LifeTime API v2を使ってみよう

OutSystemsのITユーザーやチームを簡単に管理したいな～と思ったとき
LifeTimeのAPIなるものがあったので、その使い方をまとめてみました

今回は[LifeTime API v2](https://success.outsystems.com/ja-jp/documentation/11/reference/outsystems_apis/lifetime_api_v2/)の使い方になります


# 環境
Service Studio

# 手順
### 1. URL取得
LifeTimeにログインして、図の赤枠部分をコピーして置いておきましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775282/347b555c-66bc-1d00-ee17-e39fa4d9f9f8.png)

### 2. 認証トークンの取得
[](https://success.outsystems.com/ja-jp/documentation/11/reference/outsystems_apis/lifetime_api_v2/rest_api_authentication/)を参考にサービスアカウントを作成してください
認証トークンが表示されるので、コピーしてください
**※サービスアカウントの作成には[ライセンス](https://www.tdi.co.jp/outsystems/faq/#:~:text=%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9,-%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E4%BD%93%E7%B3%BB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6&text=Outsystems%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E3%81%AF%E3%80%811%E5%B9%B4%E3%81%94%E3%81%A8%E3%81%AE%E3%82%B5%E3%83%96%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E5%A5%91%E7%B4%84%E3%81%A7%E3%81%99%E3%80%82)が**必要です

### 3. Consume REST APIで目的のAPIにアクセスしましょう
URLは次の方になります
    `<手順1で取得したURL>/lifetimeapi/rest/v2/<目的のAPI>`
※GetAPIの時は、[公式ドキュメント](https://success.outsystems.com/documentation/11/reference/outsystems_apis/lifetime_api_v2/)を確認して必要なクエリも追加してください

例：Get Applicationの場合
`https://xxxxxxxxxxxxxxxxxx.com//lifetimeapi/rest/v2/applications?IncludeModules={IncludeModules}&IncludeEnvStatus={IncludeEnvStatus}`

### 4. ヘッダーにAuthorizationを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775282/322b899c-086d-4171-dd27-cf35c7010f57.png)

### 5. テスト実行してみましょう
Authorizationには、`Bearer <authentication_token>`を渡してださい
※Bearerの後ろに半角スペース忘れずに😘
それ以外の引数には、[公式ドキュメント](https://success.outsystems.com/documentation/11/reference/outsystems_apis/lifetime_api_v2/)を確認して任意の値を渡してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775282/7f8deb32-469d-b952-07b6-afdedcfc1b2f.png)

### 6. 結果を確認してみましょう
テストを実行して `200 OK`が帰ってくれば成功です

# まとめ
LifeTime API v2の使い方は以上になります
これらを使って、何をするのか、それとも何もしないのか
心にしたがって決めてみてください
# 関連記事
[LifeTime Services APIを使ってみよう](https://qiita.com/syouhisya/items/43e1b5ff897a93552ae6)
Formオブジェクトの記述方法

丸３日データベースに保存されない状態に悩んだ部分です。
モデル間の関係性、記述方法、メソッドの使い方がややこしかった部分です。
モデルファイルに絞ってまとめます。



購入機能があるアプリで**購入すると配送先情報がorderテーブルへ、購入履歴がpurchaseテーブルへそれぞれ保存される**状態を目指します。

#### 1.model配下にorder_fomr.rbを作成
このファイルにorder.rbとpurchase.rbに記述するべきカラム、バリデーション、保存する処理を記述していく。
```ruby:order_form.rb
class OrderForm
  include ActiveModel::Model
end
```
新たなクラスを定義し、**include ActiveModel::Model**でform_with や render などのヘルパーメソッドの引数として扱え、バリデーションの機能を使用できるようにする。

#### 2.それぞれのモデルで扱うカラムをすべて記述
```ruby:order_form.rb
class OrderForm
  include ActiveModel::Model
  #orderテーブル、purchasesテーブルのカラムを書く
  attr_accessor :post_code, :region_id, :city, :house_number, :building_name, :tel, :item_id, :user_id
end
```
ここで、orderテーブルにはpurchase_idが入りそうな気がしますが、**purchase_idはorderが保存されてから生成される**のでこの時点で記述の必要はない。
purchaseは購入**履歴**なのでorderが済んでから、という考え方。

#### 3.バリデーション
```ruby:order_form.rb
class OrderForm
  include ActiveModel::Model
  #orderテーブル、purchasesテーブルのカラムを書く
  attr_accessor :post_code, :region_id, :city, :house_number, :building_name, :tel, :item_id, :user_id
  #purchase_idはorderが保存されてから生成されるので不要

  with_options presence: true do
    validates :post_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/, message: "はハイフンあり7桁で入力して下さい" }
    validates :region_id, numericality: { other_than: 1, message: 'を選択してください' }
    validates :city
    validates :house_number
    validates :tel, format: { with: /\A\d{10,11}\z/, message: "はハイフンなし10桁か11桁で入力して下さい" }
    validates :item_id
    validates :user_id
  end
  ```
  **with_options presence: true do**でdo ～　end内のバリデーションはpresence: trueであることをまとめられる。
  order.rbとpurchase.rbにバリデーションを記述する必要はない。

  #### 4.データ保存の処理
  ```ruby:order_form.rb
  class OrderForm
  include ActiveModel::Model
  #orderテーブル、purchasesテーブルのカラムを書く
  attr_accessor :post_code, :region_id, :city, :house_number, :building_name, :tel, :item_id, :user_id
  #purchase_idはorderが保存されてから生成されるので不要

  with_options presence: true do
    validates :post_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/, message: "はハイフンあり7桁で入力して下さい" }
    validates :region_id, numericality: { other_than: 1, message: 'を選択してください' }
    validates :city
    validates :house_number
    validates :tel, format: { with: /\A\d{10,11}\z/, message: "はハイフンなし10桁か11桁で入力して下さい" }
    validates :item_id
    validates :user_id
  end
    
  def save  #attr_accessorの値をそれぞれのテーブルに分ける
    
    #購入履歴を保存。orderでpurchase_idを使うので代入しておく。
    purchase = Purchase.create(item_id: item_id, user_id: user_id)
    #配送先情報を保存
    Order.create(post_code: post_code, region_id: region_id, city: city, house_number: house_number, building_name: building_name, tel: tel, purchase_id: purchase.id, user_id: user_id, item_id: item_id)
    
  end
end
```
ここで先ほどattr_accessorでは記述不要とした**purchase_id**が出てくる。
Orderがcreateされたタイミングでpurchase_idは必要になるので**purchase.id**として追加する。

<font color="Blue">attr_accessorの値を各テーブルに一つずつもれなく振り分ける、というイメージでいたのでOrder.createにitem_id,user_idの記述が足りないことに気づけず苦戦しました。

<font color="Blue">そしてpurchase.idの生成されるタイミングも難しかったポイントです。
紙に書きだして、一つずつ理解しながら進めていって解決できました。
頭の中でイメージするだけではうまく組み立てられないので、今後も紙ベースは使っていこうと思います。
Hack U KOSEN 2023に参加した話

# Hack U KOSEN 2023 とは
Hack U をご存知ですか。LINEヤフー株式会社が運営する、学生を対象としたハッカソンです。
その中でも、毎年冬に開催されるHack U KOSEN があります。これは参加資格が全国の高専生に限られるものです。
例年通りHack U KOSEN 2023が開催され、私も参加してきました。ついでに受賞したので、所感をインターネットの海に放流したいと思います。
# 参加のきっかけ
元々私はHack U存在そのものすら知りませんでした。Viva Engageという謎のマイクロソフト謹製SNSがあるのですが、同じテナント内のMicrosoft365アカウント同士で交流（？）ができます（つまり全国の国立高専の学生や教職員と交流できる）。
ある日、そこで誰かが投稿したHack U Kosen 2023の案内があり、当時暇を持て余していた私は研究室内で技術つよつよの同級生と先輩を誘い、参加することにしました。
# レギュレーション
開発期間が16日間、テーマが "クリスマスをHackせよ！" です。
Hackってなんだ？？？と調べ、"クリスマスに関連する何か作ればいいか" という短絡的結論に落ち着きました。
初期の会議では "物体検出でカップルを抽出して何かする" など取るにたらないアイデアが（10割私のせいで）たくさん出てきたのですが、"イルミネーションの光を集める" というコンセプトに落ち着きました。

最終的には[こんな作品](https://www.canva.com/design/DAF2qbyGolo/vhDVJ36_f47Jvj08XUeOjg/view)ができました。

ちなみにスライド内のイルミネーションは、仙台名物「光のページェント」です。毎年冬に実施しているので是非お越しください！

# 個人的な体験談

以下は個人的な体験談です。
なお、当時の私は
- OpenCV ろくに触ったことない
- Unity 一切わからん
- なんなら計算量とか考慮してコード書いたことない

という絶望的なスペックです。
## アルゴリズムわからん！
はい、そのまんまの意味です。私はこの作品でアルゴリズムの実装を担当しました（他の人はUnity上で光の玉の回収、クリスマスツリーの実装）。
どうにかしてカメラ映像からイルミネーションの光と判定する必要があります。
数ヶ月前までDCONやってた人間なので、真っ先にディープラーニングを思いつきましたが、スマートフォンのスペックでリアルタイムに画像からイルミネーションを抽出する必要があります。2週間でこれは難しいと判断し、アルゴリズムを考えることにしました。
### 最終的に採用したアルゴリズム
StackOverflowで提案されていた[こんな手法](https://stackoverflow.com/questions/20772893/how-to-detect-a-christmas-tree)を使うことにしました。

実際に落とし込んだものを要約すると
1. RGB画像をグレースケールに変換
1. グレースケール化した画像にガウシアンブラーを適用し、ごく小さな光源を除去
1. 画像を二値化し、イルミネーションマスクを作成
1. マスクのサイズが範囲内に収まっているのをイルミネーションと判定

イルミネーション会場での使用が前提なので、他の場所で使ったら変な挙動をする可能性はありますが、コンビニの明かり等では反応しないようになりました。

ちなみにデモ動画はHack U前日に撮影しました。めっちゃギリギリ。

## いざ東京へ
開発すると2週間はあっという間で、キックオフ間もなく当日を迎えました。
仙台→東京は東北新幹線で1時間半でした。速いですね。

ちなみに、おーいお茶はE5系のドリンクホルダーには入らないので要注意！
![入り切らないおーいお茶](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682739/46bc758b-fe87-1ef1-6ceb-4c176eb86ccd.jpeg)

会場のLINEヤフー本社。でかすぎ。
![LINEヤフー本社](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682739/1b3499ce-af27-1c08-01ae-7fcc13e7fd2c.jpeg)

発表前にパスタで腹ごしらえ。2階のお店で食べられます。
![パスタ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682739/91ac5790-bb22-e2f1-a76d-41682d4a3bf8.jpeg)

## 発表本番！
プライバシーの点から会場の写真はアップできないのですが、全国から14チームが集いました。
ARを活用したチームが我々を含めて3チームほど。ディープラーニングを使ったチームもいました。ハッカソンに出る高専生はやっぱりレベルが高いですね。

なんやかんやあって、Happy Hacking賞（参加者投票1位）を受賞しました！だいぶ端折りましたが、百聞は一見にしかず。ご自身で参加するのがオススメです！

## 少し渋谷を観光
日帰りでしたが、18時には終了したので渋谷を少し観光することにしました。
イルミネーションが綺麗でした（小並感）。
![渋谷のイルミネーション](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682739/45514734-1c2f-5e3d-6fce-f19256e1b1c9.jpeg)

## 無事帰宅
最終のはやぶさ号で帰ってきました。
![out of service](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682739/d510aa5d-b0ec-7a9f-062e-67d07512a233.jpeg)

# Hack Uを通して
以上が、初のハッカソン参加となるHack Uの一部始終でした。
短期間での開発は ~~生活に悪影響を及ぼすこともありましたが、~~ 一気に成長することができ、とても貴重な経験でした。
交通費さえ工面すればほとんどのハッカソンはタダで参加できるので、私自身もまた機会があればハッカソンに参加してみたいと思います。
Hilt の kapt を ksp にする

## はじめに

kapt 、ksp って何？ みたいな話は他者様の記事に任せるとして、本記事には Hilt + kapt の環境を Hilt + ksp に移行した作業のみを簡潔に記載する。

### 移行の方針

Hilt ＋ ksp にする方針は [kapt から KSP に移行する](https://developer.android.com/build/migrate-to-ksp?hl=ja) と [Dagger KSP](https://dagger.dev/dev-guide/ksp.html) の Requirements に基づく。

>    Dagger 2.48 (or above)
>     Kotlin 1.9.0 (or above)
>     KSP 1.9.0-1.0.12 (or above)

### 環境

AGP(Android Gradle plugin) は `8.4.1`。

``` Groovy: gradle/wrapper/gradle-wrapper.properties
plugins {
    id 'com.android.application' version '8.4.1' apply false
    id 'com.android.library' version '8.4.1' apply false
 (省略)    
```    

``` Groovy: app/build.gradle
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
```    

### build.gradle

``` Groovy
 plugins {
     id 'com.android.application' version '8.4.1' apply false
     id 'com.android.library' version '8.4.1' apply false
-    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
-    id 'com.google.dagger.hilt.android' version '2.44' apply false
+    id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
+    id 'com.google.dagger.hilt.android' version '2.48.1' apply false
+    id 'com.google.devtools.ksp' version '1.9.0-1.0.12' apply false
 }
(省略)
```

### app/build.gradle

``` Groovy
plugins {
     id 'com.android.application'
     id 'org.jetbrains.kotlin.android'
     id 'androidx.navigation.safeargs'
-    id 'kotlin-kapt'
     id 'com.google.dagger.hilt.android'
+    id 'com.google.devtools.ksp'
 }

 (省略)
      compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+        sourceCompatibility = JavaVersion.VERSION_17
+        targetCompatibility = JavaVersion.VERSION_17
     }
     kotlinOptions {
-        jvmTarget = '1.8'
+        jvmTarget = "17"
     }
     viewBinding {
         enabled = true
     }
-    kapt {
-        correctErrorTypes true
-    }
 }
 (省略)
      // Hilt
-    def hilt_version = "2.44"
+    def hilt_version = "2.48.1"
     implementation "com.google.dagger:hilt-android:$hilt_version"
-    kapt "com.google.dagger:hilt-compiler:$hilt_version"
+    ksp "com.google.dagger:hilt-compiler:$hilt_version"
 (省略) 
 ```
`sourceCompatibility` と `targetCompatibility` を `JavaVersion.VERSION_17` にしない場合は以下のビルドエラーが発生する。

```
Execution failed for task ':app:kspDebugAndroidTestKotlin'.
> 'compileDebugAndroidTestJavaWithJavac' task (current target is 1.8) and 'kspDebugAndroidTestKotlin' task (current target is 17) jvm target compatibility should be set to the same Java version.
  Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain
```

`jvmTarget` を `17` にしない場合も以下のビルドエラーが発生する。

```
Execution failed for task ':app:kspDebugKotlin'.
> 'compileDebugJavaWithJavac' task (current target is 17) and 'kspDebugKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.
  Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain
```

以上で移行完了。
goのlinterについて調べた

#### go vet
goのデフォルトlinter

```
$ go vet {file_name}
$ go vet {package name}
```

#### golangci-int
vs code　への設定方法

プロジェクト配下に設定ファイルを保存
.vscode/settings.json
```
{
    "go.lintOnSave":"workspace",
    "go.lintTool":"golangci-lint",
    "go.lintFlags":[
        "--fast"
    ]
}
```

vscodeのコマンドパレットで以下を入力
```
GO:Install/Update Tools
```
すべてチェックしてインストール


vscodeで保存するたびにlinterが走るようになった。
【UE5】ゼロから極めるゲーム開発　その4(モデリング続き)

# ブロッキングボリューム

いわゆる見えない壁のこと。侵入不可を作れる
これを配置するだけ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/92dd7a09-5e4b-79a6-b9fe-8e6354c55c59.png)

# オリジナルオブジェクトの作成

とげとげの床を作る

モデリングモードでコーンを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/1e0763c3-af61-1186-bb96-c6cf426d320f.png)

Altキーを押しながらドラッグすることで、オブジェクトを複製できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/995845e7-c62a-7215-9a7f-b8796aec99fb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/2e6ba336-fdeb-5898-12d7-12f8addbbb9f.png)

作成したオブジェクトをすべて選択し、[MeshOps]の[Merge]を実行するとオブジェクトが一つになる
床に設置させるオブジェクトなのでピボットを底面に設定しておくと便利。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/9f0e8019-48ce-7e7e-b127-f4df1bada363.png)

#### アセットとして保存する

ビューポートで作成されたオブジェクトは、そのマップのデータと同じ階層の[_GENERATED]フォルダ内に格納されている。
もしくは、オブジェクトを選択した状態で[Ctrl+B]を押すことでそのオブジェクトが格納されているフォルダを開いてくれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/899dfb52-b574-1d75-b243-8b4d3dad978c.png)

オブジェクトを保存したいフォルダに移動させればOK

# 終わり

短いけど今回はここまで。
モデリングによりいろいろなオブジェクトを作成できることがわかりました。面白そう！
社内のタスク実行管理を簡単にしたい! AppSheetで簡単解決出来るのか？







こんにちは、私は食品スーパーの事務所で働いています。
最近、私はデジタル勉強を始めました。
デジタルって、ハードル高かったけど意外に自分でも出来る事がある、と言うことに気付きました。
折角なので初心者の私ですが、デジタルで職場の問題を解決を試みました。


## 社内のタスク完了リストを超シンプルに作ってみました

<img width="400" alt="PSX_20240606_221407.jpg"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762532/34d3b549-d0e1-bd90-60fc-109e10c8e435.jpeg">

職場には、従業員に向けて、実行を必要とするものが沢山あります。
例えば、教育動画の視聴、社内アンケートの回答、人事システムの申請や更新等です。
職場にはアルバイトを含めると100名以上の従業員が働いています。
現在はその都度、管理名簿を作っています。
従業員は、完了したら管理名簿の自分の名前を探して、完了日を記入しています。
多い時は、３つ位の管理名簿が机に並ぶ時があります。
そんな時は、狭い机の上が名簿で散乱してしまいます。

### 毎月並ぶ管理名簿を、デジタル化する方法を考えてみました。



- ##### 先ずは完成動画でをご紹介します。



http://x.com/aTaKa2443/status/1798318061969346576

### 操作が簡単であることを目標に作り始めました。
沢山の従業員が使うので、誰でも分かる操作でないといけないと思いました。
登録は名前と完了日だけというシンプルなものをにしました。
>
>使用ツールは
>
>* AppSheet
>* Google スプレッドシート
>
>
>[参考にしたリンク](https://appsheet-apps.jp/appsheet/appsheet-make/)


#### <font color="oren">1. 最初にGoogleスプレッドシートの作成をします。
 - 「シート1」は名前と完了日が反映されます
 - 「シート２」以降は部門毎の名簿のリストです
 （従業員数が多いので部門毎で分けました）
- シートができたら機能拡張からAppSheetを選択します




<img width="600" alt="スクリーンショット 2024-06-05 17.40.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762532/52ed35b6-1fb9-50eb-a93f-69f7124e0c53.png">


#### <font color="oren">2. ここからは、AppSheetの設定になります

AppSheetは、データ型（Type）により入力規則を定義できます。

#### 最初に、Googleスプレッドシートの「シート1」に関する設定をします。
デーブルの入力規則の設定をします。
 - 名前は各部門毎に参照から選べるようにしました
 - 完了はカレンダーをクリックし日時を選択します




![AppSheet シート１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762532/599c1eac-1e2e-0494-a6fc-d4e57e43d76d.png)

#### 次に「シート2」以降は各部門のシート毎に設定をします。
 - 部門の名前のテキストをAppSheetから登録できるようにします



![AppSheet 部門.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762532/ebcd0ab7-60bf-bf01-32e8-31cc61f3c6fb.png)

#### にこちらが完成アプリの画面です。
 - ① 名前選択画面 = 部門を選択して参照の名前を選択します
 　NEW をタップすると新しい名前の登録ができます
 - ② 完了日を選択しsetをタップ、Saveで登録終了
 - ③ 登録完了画面 <font color="red">→</font> 部門タップ<font color="red">→</font>対象者をソートで確認できます



<img width="500" alt="!スクリーンショット 2024-06-10 17.29.33.png"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762532/13010194-d0e5-23f9-bf79-af5f1ef98066.png">

#### <font color="oren">スマホで操作するとこんな感じになります

https://x.com/aTaKa2443/status/1800060546261438812


### 実際に職場の人に使って使っていただきました。


先ずは私と同じ事務所で働く　Aさんです。
Aさんは、事務所の人事関係や店の管理関係の仕事をしています。
管理名簿はだいたいAさんが作っています。
Aさんの感想は、
「これなら名簿作らなくてすむし、直ぐにでも使いたい」　と嬉しい感想でした。

もう一人は、管理職のBさんです。
いつも私に、いろいろ良いアドバイスしてくれます。
Bさんの感想は
「これはいいじゃん、使いやすそう」　でした。
どちらも、アプリの感想は良いものでした。

### 今後の課題について


完成したアプリについては、
①部門選択ー②名前選択ー③完了日ー④当日の選択　
と4回タップします。
完了日については、開かずに、タップした時の時間で、完了日を登録できる方が使い易いと思いました。

google スプレッドシートについては、現状アプリを作る為の表でしかない為。
管理表としての役割になっていません。

今回実際に使っていただいた二人からも、この部分の指摘は受けていました。

今後、関数を取り入れて完成型にしたいと思っています。
改善点がしっかり見えているので、まだまだ進化させて行きます。
AWSデプロイ備忘録

# ECR
### 2つのリポジトリを作る

## ローカルでの実行
### ECRにログイン
```sh
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com
```

### イメージにタグをつける
```sh
docker tag {image name 1}:latest {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECRリポジトリ 1}:latest
docker tag {image name 2}:latest {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECRリポジトリ 2}:latest
```

### push
```sh
docker push {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECRリポジトリ 1}:latest
docker push {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECRリポジトリ 2}:latest
```


# EC2 

下記ファイルを作成する
```sh:deploy.sh
#!/bin/bash

# AWSリージョンとアカウントIDの設定
REGION="ap-northeast-1"
ACCOUNT_ID="{アカウントID}"

# リポジトリ名の設定
FRONTEND_REPO="{ECRリポジトリ 1}"
BACKEND_REPO="{ECRリポジトリ 2}"

# ECRにログイン
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com

# 最新のDockerイメージをプル
docker pull $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$FRONTEND_REPO:latest
docker pull $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$BACKEND_REPO:latest

# 既存のフロントエンドコンテナを停止して削除
docker stop frontend || true
docker rm frontend || true

# 既存のバックエンドコンテナを停止して削除
docker stop backend || true
docker rm backend || true

# フロントエンドコンテナを起動
docker run -d --name frontend -p 80:80 $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$FRONTEND_REPO:latest

# バックエンドコンテナを起動
docker run -d --name backend -p 8000:8000 $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$BACKEND_REPO:latest

echo "Deployment completed successfully."

```


```
$ scp -i ~/.ssh/keyPair.pem deploy.sh ubuntu@{ec2-ipv4}:/home/ubuntu/deploy.sh
```

### AWS CLIとDockerEngineをEC2にインストール
```sh
# まず、unzipをインストールします。
sudo apt-get update
sudo apt-get install -y unzip

# AWS CLIのダウンロードとインストール
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

#インストール確認
aws --version


# Dockerのパッケージをインストールするために必要なパッケージをインストール
sudo apt-get update
sudo apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# Dockerの公式GPGキーを追加
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Dockerのリポジトリをセットアップ
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Dockerエンジンのインストール
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Dockerサービスの起動と有効化
sudo systemctl start docker
sudo systemctl enable docker

# 現在のユーザーをdockerグループに追加して、sudoなしでdockerコマンドを実行できるようにする
sudo usermod -aG docker $USER

# ユーザーグループの変更を反映するために再ログインが必要
newgrp docker


```

aws configureで認証を通る必要がある。
EC2内にプロファイラを設定しておく
```
aws configure
```


スクリプトを実行してデプロイを行います。
```
chmod +x /home/ubuntu/deploy.sh
/home/ubuntu/deploy.sh
```


```sh
# credentialを使ってECRにログイン
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {account ID}.dkr.ecr.ap-northeast-1.amazonaws.com
```
GASで時間の計算をする

# はじめに
GASで時間計算をしたい場合、皆さんはどうしているでしょうか？
いろいろややこしい仕様があって、私は苦労していますね。
今回は、24時間を超える時間を計算したいときにどうすればいいのか、複数の時間を計算するにはどんな関数を作ればいいのかを紹介します。

# 24時間を超える計算をしたい場合。
上のバーの「表示形式の詳細設定」から「経過時間」をクリックすることで、24時間以上の時間を表示できます。

さらに、「h:mm」の形式にしたい場合は、「カスタム日時」から選択してください。

# 時間を足す関数
時間の足し引きをする場合、Date関数には年月日の情報も含まれているシリアル値で計算しているため、すこしややこしいです。
そのため、時間は時間、分は分として計算することで、シリアル値で計算しないようにしてみました。

```
function sumTime(...args) {
  Logger.log("sumTime入力: " + args);
  let sumHours = 0;
  let sumMinutes = 0;

  for (let i = 0; i < args.length; i++) {
    if (args[i].getFullYear() === 1899 && args[i].getMonth() === 11 && args[i].getDate() === 31) {
      sumHours += args[i].getHours() + 24;
    } else {
      sumHours += args[i].getHours();
    }
    sumMinutes += args[i].getMinutes();
  }

  const sumDate = new Date(1899, 11, 30, sumHours, sumMinutes);

  Logger.log("sumTime出力: " + sumDate);

  return sumDate;

}
```

```
if (args[i].getFullYear() === 1899 && args[i].getMonth() === 11 && args[i].getDate() === 31) {
      sumHours += args[i].getHours() + 24;
```
この部分は、24時間を超える場合の処理です。monthが11なのは、12月を11で表すからですね。
普通に計算すると「1899年12月30日」の時間が使われるようなので、24時間を超えると31日になります。
31日の場合に、hourに+24をしているというわけですね。

引数には、可変朝引数を使っています。
これで複数の時間の足し算を一度にできます。

最後に、1899年12月30日の日付で時間を返しています。
時間や分が基準を超える場合には、繰り上がりが起こります。



# 時間の引き算
時間の引き算もシリアル値での計算をしてしまうと、うまくいかないと思います。
なので、時間と分を分けて計算してみました。

```
function diffTime(t1, ...args) {
  Logger.log("diffTime入力: " + [t1, ...args]);

  let t1Flg = false;
  if (t1.getFullYear() === 1899 && t1.getMonth() === 11 && t1.getDate() === 31) {
    t1Flg = true;
  }

  let t1Hour = t1.getHours();
  if (t1Flg) {
    t1Hour = t1Hour + 24
  }
  let t1Min = t1.getMinutes();

  let sumHours = 0;
  let sumMinutes = 0;

  for (let i = 0; i < args.length; i++) {
    if (args[i].getFullYear() === 1899 && args[i].getMonth() === 11 && args[i].getDate() === 31) {
      sumHours += args[i].getHours() + 24;
    } else {
      sumHours += args[i].getHours();
    }
    sumMinutes += args[i].getMinutes();
  }

  const diffHour = t1Hour - sumHours;
  const diffMinute = t1Min - sumMinutes;


  const date = new Date(1899, 11, 30, diffHour, diffMinute);

  Logger.log("diffTime出力: " + date);

  return date;
}
```

t1から他の可変長引数を引くという形をとっています。
1899年12月31日については足し算で説明しています。
引数をすべて足して、t1(time1)から引いていることがコードからわかると思います。



# おわりに
いかがだったでしょうか。
GASで時間を計算するのは、少々面倒くさいですね。

もっと簡単なやり方があればぜひコメントしていただきたいです。
dayjsやmoment.jsなどでのコードの案なども歓迎です！
MySQLの結合について

## 1. 結合の基本

結合（JOIN）は、複数のテーブルから関連するデータを一つの結果セットとして取得するためのSQL操作です。結合の基本構文は次のとおりです：

```sql
SELECT columns
FROM table1
JOIN table2
ON table1.common_column = table2.common_column;
```

## 2. 主な結合の種類

MySQLにはいくつかの結合の種類がありますが、主に以下の4つがよく使用されます：

1. **内部結合（INNER JOIN）**
2. **左外部結合（LEFT JOIN）**
3. **右外部結合（RIGHT JOIN）**
4. **完全外部結合（FULL JOIN）** - MySQLでは直接サポートされていませんが、UNIONを使用して実現可能です。

---

## 3. 内部結合（INNER JOIN）

内部結合は、結合条件に一致するレコードのみを返します。どちらのテーブルにも一致するデータがある場合にのみ結果セットに含まれます。

### 内部結合の構文

```sql
SELECT columns
FROM table1
INNER JOIN table2
ON table1.common_column = table2.common_column;
```

### 内部結合の例

```sql
SELECT employees.name, departments.department_name
FROM employees
INNER JOIN departments
ON employees.department_id = departments.id;
```

このクエリは、`employees`テーブルと`departments`テーブルを`department_id`で結合し、各従業員の名前と所属部署を取得します。

---

## 4. 左外部結合（LEFT JOIN）

左外部結合は、左側のテーブルのすべてのレコードと、結合条件に一致する右側のテーブルのレコードを返します。一致しない場合、右側のテーブルの値はNULLになります。

### 左外部結合の構文

```sql
SELECT columns
FROM table1
LEFT JOIN table2
ON table1.common_column = table2.common_column;
```

### 左外部結合の例

```sql
SELECT employees.name, departments.department_name
FROM employees
LEFT JOIN departments
ON employees.department_id = departments.id;
```

このクエリは、`employees`テーブルのすべての従業員と、`departments`テーブルの一致する部署を取得します。部署がない従業員については、`department_name`がNULLになります。

---

## 5. 右外部結合（RIGHT JOIN）

右外部結合は、右側のテーブルのすべてのレコードと、結合条件に一致する左側のテーブルのレコードを返します。一致しない場合、左側のテーブルの値はNULLになります。

### 右外部結合の構文

```sql
SELECT columns
FROM table1
RIGHT JOIN table2
ON table1.common_column = table2.common_column;
```

### 右外部結合の例

```sql
SELECT employees.name, departments.department_name
FROM employees
RIGHT JOIN departments
ON employees.department_id = departments.id;
```

このクエリは、`departments`テーブルのすべての部署と、`employees`テーブルの一致する従業員を取得します。従業員がいない部署については、`name`がNULLになります。

---

## 6. 完全外部結合（FULL JOIN）

完全外部結合は、左側および右側の両方のテーブルのすべてのレコードを返します。MySQLでは直接サポートされていないため、UNIONを使用して実現します。

### 完全外部結合の構文

```sql
SELECT columns
FROM table1
LEFT JOIN table2
ON table1.common_column = table2.common_column

UNION

SELECT columns
FROM table1
RIGHT JOIN table2
ON table1.common_column = table2.common_column;
```

### 完全外部結合の例

```sql
SELECT employees.name, departments.department_name
FROM employees
LEFT JOIN departments
ON employees.department_id = departments.id

UNION

SELECT employees.name, departments.department_name
FROM employees
RIGHT JOIN departments
ON employees.department_id = departments.id;
```

このクエリは、`employees`テーブルと`departments`テーブルの両方のすべてのレコードを取得し、一致しない場合はNULL値を含めます。

---

## 7. クロス結合（CROSS JOIN）

クロス結合は、2つのテーブルのすべての組み合わせを返します。結合条件がなく、2つのテーブルの各行が組み合わせられます。

### クロス結合の構文

```sql
SELECT columns
FROM table1
CROSS JOIN table2;
```

### クロス結合の例

```sql
SELECT employees.name, departments.department_name
FROM employees
CROSS JOIN departments;
```

このクエリは、`employees`テーブルと`departments`テーブルのすべての組み合わせを取得します。結果セットの行数は、`employees`テーブルの行数と`departments`テーブルの行数の積になります。

---
未経験エンジニアになって2年経ったので、1年目の自分にアドバイスする

### やっておけばよかったこと 〜就職前、研修時〜
#### とりあえずハンズオン形式の技術書を買ってアプリをつくってみる
業務で何かするときに何もとっかかりがないときつい。。

言語の構文
フレームワーク
コンパイルとか、ビルド成果物
ここら辺を実際に手で触っているかいないかで大きな違いがあった
#### わからない時は聞きまくる
最初はわからない＝恥ずかしいと思って聞くことを避けていたが、わからない＝成長の機会だと思って聞くのがいい
自分に期待せず、さっさとエラーを解消しよう

### やっておけばよかったこと 〜1年目〜
#### dockerの本買って実際に動かしてみる
dockerめっちゃ使う
なんとなく既存のDockerファイルパクったりして理解していないとその後のクラウドでつらい
#### コピペしない
コピー＆ペーストはもちろん、他のコードを参考にして写すのもNG
意味を理解せずに書くのはやめよう
わからないまま書いていても2回目は書けないぞ
#### 10分でいいから学習する習慣をつくる
本を10分でいいから読む、その日わからなかったことを調べる、PlayGroundでちょっとコード書いてみる
なんでもいいから習慣化しておくと時間が経つだけで膨大な量をこなしていることになる
#### 学習は短期集中
モチベは思っている以上に厄介
学びたいことは長くても2週間で終わらせる
土日だけとかダメ。絶対
### やっておけばよかったこと ~2年目~
#### なんでもいいから本業以外で活動する
転職しようと思うと思っている以上に自分にスキルがあることの説明が難しい
qiitaに投稿しているとか、GitHubに草が生えているとか(コミット履歴がたくさんある)、副業しているとかあったら心強い
できれば外部からプレッシャーがかかるものがいい
例えば副業やスクールとか

以上です。誰かの人の助けになれば幸いです。
Ubuntuでfirefoxが起動しない

# 要約
Ubuntuでhomeディレクトリが変なところに作られてると，firefoxやopen-syobon-actionといったsnapで入るアプリケーションが動かないことがある．

```
username@hostname:~$ firefox
cannot create user data directory: /XXX/YYY/username/snap/firefox/1234: Permission denied
```

以下のコマンドを実行すれば良い．（`/XXX/YYY`の部分は↑に合わせて適宜入れ替える）

```
$ sudo snap set system homedirs=/XXX/YYY
```

# 調査したこと
- Permission denied なので`chown`や`chmod`などを試したが，どうもうまくいかなかった．
- snap 2.60.2 から 出るようになったエラーらしい（[出典](https://bugs.launchpad.net/snapd/+bug/2032679)）
- 解決策は[ここ](https://snapcraft.io/docs/home-outside-home)に載ってた
mmfewshotについてのまとめ

mmfewshotについてまとめられている日本語記事がなかったため、備忘録代わりにまとめておく。

## few shot learningとは
はじめにFew-shot learning (FSL)とは何かについて軽く説明する。
特徴は以下のような点
* 少数のサンプルから新しいタスクを学習する機械学習のアプローチ
* 事前知識（大規模なデータセットによる学習済みモデルなど）を活用して、新しいタスクに適応する
* 画像分類や物体検出などのタスクに利用される

簡単に言えばファインチューニングなどのこと。

## mmfewshotとは
mmfewshotとはOpenMMLab が提供する few-shot learning (FSL) のためのツールボックス。PyTorch をベースにしており、FSL 研究の促進を目的としている。
### 主な特徴
* 複数FSLタスクのサポート: 画像分類、物体検出などの複数のFSLタスクに対応している
* ベンチマーク: FSLの標準的なベンチマークを提供している
* モジュール性: データセット、モデル、評価指標などがモジュール化されており、柔軟なカスタマイズが可能

## 用語
* Training set (トレーニングセット): 各クラスに多数のサンプルを持つ十分に大きなデータセットで、ベースとなるモデルの学習に使用される
* Support set (サポートセット): ラベル付き画像の少数のセットで、すべてのクラスがトレーニングセットには存在しない
* Query set (クエリセット): 未ラベルの画像で予測対象の画像。サポートセットと同じクラスを共有する
* N way K shot (NウェイKショット): サポートセットの設定で、サポートセットの画像にN個のクラスが含まれ、各クラスにK個のサンプルがあることを意味する
    * classification（分類タスク）　サポートセットにはNxK個のサポート画像が含まれる
    * detection（検出タスク）　サポートセットにはNxK個のサポートインスタンスが含まれる。画像の数はNxKより少なくなることがある


続く
Dockerコンテナとイメージの削除・停止方法まとめ

# はじめに
<!-- 発端や概要を記載 -->
dockerイメージとコンテナってどうやって停止とか削除のやり方をまとめてみました．よかったらみてください！

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [dockerコンテナの停止と削除](#Chapter1)
1. [dockerイメージの削除、全削除、強制削除](#Chapter2)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 1. dockerコンテナの停止と削除方法
### コンテナの停止
```
docker stop <CONTAINER IDまたはNAME>
```
例
```
docker stop hello-world
```
### コンテナ削除
* コンテナを停止しないとコンテナを削除できません
```
docker rm <CONTAINER IDまたはNAME>
```
削除されたか確認
```
docker ps
```
<a id="#Chapter2"></a>
# 2. dockerイメージの削除、全削除、強制削除
### dockerイメージの削除
```
docker rmi <IMAGE IDまはたNAME>
```
### dockerイメージ全削除
```
docker rmi $(docker images -q)
```
### dockerイメージ強制削除
```
docker rmi <IMAGE IDまはたNAME> -f
```
### 強制全削除
```
docker rmi $(docker images -q) -f
```
イメージが削除されたか確認
```
docker images
```

<a id="#reference"></a>
# 参考文献
- [docker 日本語ドキュメント](https://docs.docker.jp/)
# Dockerに関する過去の投稿記事一覧
- [dockerハンズオン入門](https://qiita.com/tRbiWbc3hnM1Aor/items/73a7433abea6993ab10a)
- [dockerのイメージの種類と選び方](https://qiita.com/tRbiWbc3hnM1Aor/items/ad319d434675236e3fcd)
- [Docker環境で環境変数を扱う](https://qiita.com/tRbiWbc3hnM1Aor/items/74f5653c3190e0377e94)
maprayのサンプルを触ってみた

# はじめに

* おしゃれなCGアプリが作りたい
* maprayというライブラリを知り、触ってみることにした
    * https://mapray.com/

# 手順

1. maprayの利用登録
    * https://cloud.mapray.com/
    * ベータ版のアカウント作成し、ログイン
    * APIキーの発行
        * 名前は任意（後で変更可能）
        * ドメイン指定はなし（後で変更可能）
2. サンプルプログラムの作成
    * sample.htmlという名前でファイル作成
    * 下記のUsageにあるサンプルコードをコピペする
        * https://github.com/sony/mapray-js
    * "<your access token here>"の部分に、1で発行したAPIキーを貼り付ける
3.  動作確認
    * sample.htmlをブラウザで開く
    * きれいなCGが出てきた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612859/0301001d-7612-3163-b776-a21d1149892d.png)


## 今後

* ライブラリを使った開発手順も習得したい
* 視点移動や場所変更、何かしらのアイデアと組み合わせてみたい
Azure Bot Framework SDK  Python sample を App Service にデプロイした際に起動できないエラーの対処法

# はじめに

Azure Bot Service を試す場合、Bot Framweork SDK を使ったチュートリアルとしては下記が提供されています。

https://learn.microsoft.com/ja-jp/azure/bot-service/bot-service-quickstart-create-bot?view=azure-bot-service-4.0&tabs=python%2Cvs

この記事では、以下の Echo Bot がサンプルコードとして提供されている。

https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/python/02.echo-bot

この記事自体は、Bot Framework Emulator を利用して Bot の動作確認をするところまでが紹介されており、そこまでは問題なく動作する。

ただし、記事にリンクされた App Service へのデプロイで上記サンプルをそのままデプロイすると、App Service 上では、正しく起動できず、Web Chat をはじめ Botのバックエンドが動作しない状態となります。

https://learn.microsoft.com/ja-jp/azure/bot-service/provision-and-publish-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Ccsharp

# 発生しうるエラー

App Service 上で、アプリが起動できず、<AppName>.azurewebsites.net には 504.0 GatewayTimeout　応答が返されることになります。
Bot Service からのエンドポイントに指定してある アプリ名.azurewebsites.net/api/messages も応答を得られない状態となります。
その結果、Web Chat をはじめ、Bot が何の応答も返さないという状態となります。

Bot Service のポータルからは以下のような表示となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/92790513-cb9c-b01c-3957-60f04e752634.png)

App Service 側の起動ログは以下のような内容で再起動が繰り返されることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/79fab961-fa0e-1792-1262-d458c1932ad7.png)

App Service のログについては以下の記事を参考

https://azure.github.io/jpazpaas/2023/07/27/AppServiceOnLinux-Log.html

# 回避策

スタートアップコマンドに以下を追記することで正常にアプリケーションが起動できます。

```bash
gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/7108936d-1446-af70-c1a3-123d902df619.png)


# 解説

最初のチュートリアルでローカル起動させる際は、`python app.py` でプログラムをスタートさせていました。
一方 App Service では、下記の記事にあるとおり、Python アプリ用のスタートアップコマンドが自動で生成されるものとなります。

https://learn.microsoft.com/ja-jp/azure/app-service/configure-language-python#flask-app

サンプルの EchoBot は Flask プロジェクトではありませんが、app.pyが含まれるため、以下の起動スクリプトがデフォルトで適用されます。

```bash
gunicorn --bind=0.0.0.0 --timeout 600 app:app
```

一方で `app.py` の中身は以下の通り、`APP` という名前で `aiohttp` のサーバーを提供しています。

```python:app.py(L79~)
APP = web.Application(middlewares=[aiohttp_error_middleware])
APP.router.add_post("/api/messages", messages)

if __name__ == "__main__":
    try:
        web.run_app(APP, host="localhost", port=CONFIG.PORT)
    except Exception as error:
        raise error
```
https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/python/02.echo-bot/app.py#L79-L86

そのため、`app.py` を `gunicorn` から起動できるようにするためには、前述のカスタムスタートアップコマンドが必要となります。

https://docs.aiohttp.org/en/stable/deployment.html

`Oryx` によるスタートアップコマンドとカスタムコマンドについては下記記事も参考にしてください。

https://qiita.com/georgeOsdDev@github/items/d4f31dfa5bd1de362dd6

https://qiita.com/georgeOsdDev@github/items/abdadd35248b98c4ef88#blessed-image-%E3%81%AE-%E8%B5%B7%E5%8B%95%E3%81%A8%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89
Remix CloudFlareのテンプレートを使ってプロジェクトファイルを作るときに指定するアカウントが意図するものと違う

## 概要

`npm create cloudflare@latest my-remix-app -- --framework=remix`のコマンドを実行中に今すぐデプロイを選択すると「╰ Which account do you want to use?」と表示されアカウントの選択を求められる事がある。
複数のアカウントを持っていると意図しないものが出る可能性がある。これを回避する方法を簡単にまとめる。

## 方法

1. 一旦`npm create cloudflare@latest my-remix-app -- --framework=remix`のコマンドを停止する。
1. 下記を実行して一旦ログアウトする。

    ```shellscript
    wrangler logout
    ```

1. 下記を実行してログインする。

    ```shellscript
    wrangler login
    ```

1. カレントディレクトリの中途半端にできたプロジェクトファイルを削除する。

    ```shellscript
    rm -rf my-remix-app
    ```

1. 再度`npm create cloudflare@latest my-remix-app -- --framework=remix`を実行する。
パスワードの重要性

# はじめに
こんばんは、無知な田舎者です。今回は、パスワードについて書いてみました。今の時代には欠かせないパスワード。普段から利用していると思うんですけど、パスワードの設定や覚え方など習った覚えがなく、、なんとなくで作成したり使いまわしたりしていて、挙句の果てにパスワードをそもそも忘れることが過去に何回かありました。そこでパスワードの重要性などを再認識、理解を深めるためにまとめてみました。日本語が多少おかしい所や、間違った認識などがあればぜひコメントなどで教えてください。

# パスワードとは
特定の機能や情報にアクセスするために使う合言葉です。
一般的に、パスワードはユーザーが設定をする。

# パスワードの目的
### ユーザー認証
ユーザーが自分を特定のサービスに対して正当に認証するため。
登録しているユーザーが本人であると確認するため。

### セキュリティ保護
不正アクセスなどの外部からデータを守るため。

### プライバシー保護
個人情報や機密情報を保護し、他の人から見られないようにするため。

# 桁が8桁なパスワードや定期的な変更は無意味？
安全なパスワードと言えば、桁が8桁以上で定期的に変更するものだと思っていました。しかし、最近では、攻撃者の手口も進化をしてきていて、8桁では無意味と言われていて、パスワードにも進化が必要と言われています。

そもそもパスワード8桁以上と言われていたのは、2011年にIPAが目安で発表していたものです。ですが、現在は「できるだけ長く」「複雑で」「使い回さない」の3つをポイントにしており桁数は指定されていません。
パスワードを複雑にする理由は、攻撃者がパスワードの解読して見破る時間を長くするのが目的です。

次に、パスワードに定期的な変更が必要か、という問題です。

不正アクセス対策などにパスワードに定期的な変更が必要とNISTのガイドラインに記載されていたそうなのですが、最近のガイドラインに「サービス提供者はパスワードの定期変更を要求すべきでない」と記載が変更されていたそうです。マイクロソフトも変更は無駄とナンセンスだと言っています。安全なパスワードであれば変更不要で、変更してしまうことで覚えるために簡単なパスワードを作りがちになってしまうことがあるからだそうです。

# 安全なパスワードの３つのポイント
### 長さ
長ければ長い封土安全性は高まる。

### 複雑性
大文字、小文字、数字、特殊文字(@,!,/,%)を組み合わせること。

### 予測不可能性
予測されそうな名前、誕生、連続数字やアルファベットは避けてランダムな文字列にすること

# 安全なパスワードの作り方
### コアパスワード
コアパスワードとは、自分と関係ない固有名詞を利用する方法や何らかの文章を作成、文節、ごとの頭文字や単語をつなぎ合わせてワードをつくる方法です。
これは、IPAで推奨されています。

### パスワード管理ツールの利用
LastPass、1Password、Dashlaneなど、パスワード生成・管理ツールを使い、パスワードは自動生成し、代わりに覚えてくれるツールです。

### パスワードマネージャーの使用:
強力で一意のパスワードを生成し、安全に保存する。

### 二要素認証（2FA）の利用:
パスワードに加えて、追加の認証手段（例: SMSコード、認証アプリ）を使用する。

# 世界で一番使われているパスワード
「パスワードランキング」をご存知ですか？
セキュリティ企業である Nord Security がその年に世界で最も使われたパスワードのランキングを発表するというもので、同時に国別のランキングも発表されます。ダークウェーブを含むさまざまな角度からデータを収集しているようです。[パスワードランキングの2023年版](https://nordpass.com/most-common-passwords-list/)

TOP５
１位　123456　
２位　admin
３位　12345678
４位　123456789
５位　1234

攻撃者じゃなくても誰でも解読出来そうなパスワードが上位になりました。心当たりがある方も一定数いると思います。
実際に日本だけのランキングはこちら

1位：「123456」

2位：「password」

3位：「1234」

4位：「12345678」

5位：「akubisa2020

日本でもこのようなパスワードを使っている人は非常に多いです。

# パスワードの強度をチェックする
自分のパスワードが解読時間を調べられるサイトがいくつかあります。
解析コンピュータの条件など、詳しいことはわかりませんが、目安となりそうです。
[HOW SECURE IS MY PASSWORD](https://www.security.org/how-secure-is-my-password/)

[How Secure is Your Password?](https://www.passwordmonster.com/)

[HOW STRONG IS THIS PASSWORD?](https://nordpass.com/secure-password/)

# まとめ
今回パスワードは、数年前に比べて長く、複雑に作らなければ簡単に攻撃されてしまうことが分かりました。また、パスワードマネージャーなどに頼ることで自分で考えるより強固なパスワードを作れることが分かりました。自分のパスワードを改めて見直して不正アクセスされる前に対策しようと思います。最後まで見ていただきありがとうございました。
AnythingLLM と Ollama で agent を試す

# はじめに

前回紹介した AnythingLLM はRAGだけでなく、agent も簡単に利用できるので試してみます。2024/6時点、`rag-search`, `web-scraping`, `web-browsing` などのagentが実装されています。


https://qiita.com/orca13/items/d84a2c398aff2334c69c

# 設定

Workspace の設定の Agent Configuration で Agent LLM Provider と Agent model を選択します。

![allm_agent_01](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/e9239cde-485e-9be8-0392-87e3f30238fd.png)

Ollamaだと「LLMの能力不足でちゃんと動かないかも」と言う様な警告が出ますが、しょうがないので無視します。ローカルでも CommandR+ などより高性能なモデルが使えれば、よりちゃんと動く可能性が高まると思います。

# 実行

`@agent` に続けて URL を与えてみました。

![allm_agent_02](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/b6cb5f69-2dd6-a626-b6b3-35f11222f184.png)

自動で URL 先にアクセスして、内容を要約してくれました。
なお、続きで「01. Getting Started」について聞いてみましたが、上手く回答してもらえませんでした。今回使用したLLMの能力不足が原因かと思われます。

ちゃんとした動作例は公式ドキュメントにありますので、見てみてください。

https://docs.useanything.com/agent/usage

# まとめ

AnythingLLM で agent を試しました。最低限の動作は確認できましたが、LLMの能力不足のせいか、十分な結果は得られませんでした。
山奥SEOとは？完全ガイド

## 山奥SEOの基本：エンジニア視点での新たなSEO手法

SEO（検索エンジン最適化）は、エンジニアの論理的思考力や技術力を活かせる分野です。特に、競合が少なく成果を出しやすい「山奥SEO」は、効率的な戦略を求めるエンジニアにとって絶好の挑戦領域となっています。

本記事では、「山奥SEO」の定義、エンジニアが成功するための具体的な方法、そして潜在的な可能性を徹底解説します。

---

## 山奥SEOとは？成功への鍵を解明

「山奥SEO」は、検索ボリュームの少ないニッチなキーワードを狙い、競争の少ない領域で検索エンジン上位を目指すSEO手法です。この手法は、山奥に隠れた資源を探し出すようなアプローチで、大きな成果を生む可能性があります。

通常のSEOではビッグキーワードが注目されますが、競争が激化している中、「山奥SEO」は効率的かつ効果的に結果を出す新しい選択肢として注目されています。

---

## 山奥SEOでエンジニアが活躍できる理由

エンジニアが「山奥SEO」に適している理由は、以下の3点に集約されます。

### データ分析能力による精密な戦略

Google AnalyticsやGoogle Search Consoleなどのツールを駆使して、検索意図や競合状況を詳細に分析し、最適なキーワード戦略を立案できます。

### 技術力を駆使したサイト最適化

エンジニアの技術力を活かして、テクニカルSEO（サイト構造やページ速度改善、モバイル対応など）の分野で他との差別化を図ることが可能です。

### 作業効率化と自動化技術の活用

スクレイピングやAPI連携を通じて、キーワード調査やコンテンツ生成、被リンク獲得作業を自動化し、大幅な効率化を実現します。

---

## 山奥SEOの具体的な戦略

### ニッチなキーワードの発掘

エンジニアは、スクレイピング技術やAPIを活用し、通常のツールでは見逃しがちなニッチキーワードを見つけることができます。

### AIと連携した高品質コンテンツの生成

AI技術を活用して効率的にコンテンツを生成し、編集を加えることで独自性を高めた記事を作成します。

- **キーワード分析**: 関連データを集め、ターゲットを明確化。
- **コンテンツ生成**: AIを利用して基礎となる文章を作成。
- **人間による校正**: コンテンツを手直しして、独自性を強化。

### テクニカルSEOの徹底最適化

次のような技術的対策を実施します。

- サイト構造の最適化
- ページ速度の向上
- モバイルフレンドリー対応

### 被リンク戦略の自動化

スクレイピングとAPIを活用して関連性の高いサイトへのアウトリーチを自動化。被リンクを効率的に獲得します。

---

## 山奥SEOで開ける未来

### 独自SEOツールの開発

データ分析やコンテンツ生成に特化したツールを開発し、SEO業界に新たな価値を提供します。

### 専門分野に特化した情報サイト運営

ニッチ市場をターゲットにした情報提供で、検索エンジンからの評価を高め、持続的なトラフィックを確保します。

### ニッチアプリの開発

山奥SEOで得た知見を活かし、特定分野のユーザー向けアプリを開発し、新たな収益源を創出します。

---

## 山奥SEOまとめ

山奥SEOは、エンジニアがその技術力と論理的思考を活かし、新たな市場を開拓できる戦略です。この未開拓のフィールドで結果を出すことで、大きな成功を掴むことが可能です。

「山奥SEO」は、未来を切り開く鍵として、多くの可能性を秘めています。ぜひ挑戦し、新たな成功事例を作り上げてください。
【PowerShell】和集合、積集合、差集合を求める

# はじめに

以前に「[【C#】和集合、積集合、差集合、対象差を求める](https://qiita.com/nkojima/items/575a1e5879d62441662d)」という記事を書きましたが、この記事が思ったよりも高評価（※2024/06/07時点で34いいね）でした。
そこで勉強がてら、同様の処理をPowerShellで実装してみた結果を記事としてまとめてみました。

# テストコード

* 単にPowerShellで書くのではなく、ワンライナーでLINQのような形にしてみました。
* 和集合(Union)では、`-Unique`を使って重複を削除しています。
* 積集合や差集合はどのように実装すべきか悩みましたが、`Where-Object`を使って「条件にマッチする要素のみ抽出する」ことができたため、どうにか課題をクリアできました。

```powershell:test.ps1
$list1 = @("Tokyo", "Osaka", "Yokohama", "Nagoya", "Kobe")
$list2 = @("Tokyo", "Yokohama", "Sapporo", "Fukuoka")

Write-Host ("和集合(Union)：" + (($list1 + $list2) | Select-Object -Unique))
Write-Host ("和集合(Concat)：" + ($list1 + $list2))
Write-Host ("積集合(Intersect)：" + ($list1 | Where-Object { $list2 -contains $_ } ))
Write-Host ("差集合(Except)[list1-list2]：" + ($list1 | Where-Object { $list2 -notcontains $_ } ))
Write-Host ("差集合(Except)[list2-list1]：" + ($list2 | Where-Object { $list1 -notcontains $_ } ))
```

```text:実行結果
和集合(Union)：Tokyo Osaka Yokohama Nagoya Kobe Sapporo Fukuoka
和集合(Concat)：Tokyo Osaka Yokohama Nagoya Kobe Tokyo Yokohama Sapporo Fukuoka
積集合(Intersect)：Tokyo Yokohama
差集合(Except)[list1-list2]：Osaka Nagoya Kobe
差集合(Except)[list2-list1]：Sapporo Fukuoka
```

# 参考URL

* [【C#】和集合、積集合、差集合、対象差を求める](https://qiita.com/nkojima/items/575a1e5879d62441662d)
* [LINQっぽいこと - PowerShellらしい書き方](https://stayg.jpn.org/wp/?page_id=100)
* [配列に含まれているかどうか判定する](http://powershell.web.fc2.com/Html/Data/2011/12/14/0000.html)
* [PowerShell: 配列から重複を削除](https://step-learn.com/article/powershell/047-array-unique.html)
OpenSiv3DプロジェクトをVisual StudioとGitHubで管理する方法

# はじめに

この記事では、Visual Studioを使ってOpenSiv3DのプロジェクトをGitHubリポジトリで管理する基本的な手順を解説します。

# 前提条件

- Visual Studioがインストールされていること
- GitHubアカウントがあること
- Gitがインストールされており、Visual Studioと連携されていること

# ステップ1: `.gitignore` ファイルの設定

最初に行うべきは、適切な`.gitignore`ファイルをプロジェクトに追加することです。これにより、不要なファイル（ビルド生成物など）がGitリポジトリに含まれないようにすることができます。

1. [Siv3Dの`.gitignore`](https://github.com/Siv3D/gitignore)をダウンロードします
2. ダウンロードした`.gitignore`ファイルを、Visual Studioのソリューションがあるディレクトリ（プロジェクトフォルダ）に配置します

# ステップ2: Visual StudioでのGitの設定

Visual Studioには統合されたGit機能があり、これを使ってGitHubリポジトリの管理が可能です。

1. Visual Studioを開き、対象のOpenSiv3Dプロジェクトをロードします
2. ソリューションエクスプローラーでプロジェクトを右クリックし、「Git」>「リポジトリとして公開...」を選択します
3. `.gitignore`ファイルを配置したディレクトリをリポジトリのルートとして選択します

これにより、`.gitignore`が自動的に認識され、指定したファイルがGitリポジトリに追加されないように設定されます。

# ステップ3: GitHubとの連携

Visual StudioとGitHubアカウントが連携されている場合、以下の手順でリポジトリをGitHubにプッシュできます。

1. 「Gitの変更」パネルを使用して、変更をコミットします
2. 「プッシュ」オプションを選択して、コミットをGitHubのリポジトリにプッシュします

## ステップ4: リポジトリのクローンとプロジェクトの実行

他の開発者があなたのリポジトリをクローンする場合、以下のコマンドを使用します。

```bash
git clone [リポジトリのURL]
```

OpenSiv3Dがインストールされている環境であれば、クローンしたプロジェクトはすぐに実行可能です。