OmniAICreator/Qiita-1.07M huggingface dataset:
【Github Actions✕Firebase】リモートマシン上でfirebase deployを実行時に警告が表示される。

# はじめに
Github Actions上でのFirebaseのデプロイ自体は成功するがリモートマシン上に警告が表示されたので対応しました。

# 問題
以下の警告がGithubのリモートマシン上に表示される。

```console
⚠  Authenticating with `FIREBASE_TOKEN` is deprecated and will be removed in a future major version of `firebase-tools`.
Instead, use a service account key with `GOOGLE_APPLICATION_CREDENTIALS`: 
```
大まかに訳すと、「FIREBASE_TOKEN」を使った認証は非推奨だからやめてね、代わりに「GOOGLE_APPLICATION_CREDENTIALS」を使った認証の方法にしてね、という感じ。
警告発生時点でのymlの設定は以下の通り。

```yaml:autoDeproy.yml（抜粋）
      - name: Deploy to Firebase Hosting
        run: |
          ./node_modules/.bin/firebase deploy
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
          FIREBASE_CLI_EXPERIMENTS: webframeworks
```
以下のドキュメントを参考にしましたが、どうやらこの方法だとセキュリティ的にNGのようです（トークンが漏れたら第３者に好き放題される懸念）。

https://firebase.google.com/docs/cli?hl=ja#cli-ci-systems

# 解決方法
ググったらGCPのサービスアカウントで適切な権限を設定する方法があるとのことなので、その通りに修正。

<details><summary>autoDeploy.yml（修正後）</summary>

```yml:autoDeploy.yml
name: Auto Deploy

on: push

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      VITE_SUPABASE_URL: ${{secrets.SUPABASE_URL}}
      VITE_SUPABASE_ANON_KEY: ${{secrets.SUPABASE_ANON_KEY}}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: oven-sh/setup-bun@v2

      - name: Install dependencies
        run: bun install

      - name: Run build
        run: bun run build

      - name: Install firebase-tools
        run: bun install --save-dev firebase-tools

      - name: Decode Firebase service account key
        run: |
          echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./firebase-key.json
          echo "GOOGLE_APPLICATION_CREDENTIALS=${{ github.workspace }}/firebase-key.json" >> $GITHUB_ENV
      - name: change space
        run: ./node_modules/.bin/firebase use ${{ secrets.FIREBASE_PROJECT_ID }}

      - name: Deploy to Firebase Hosting
        run: |
          ./node_modules/.bin/firebase deploy
        env:
          FIREBASE_CLI_EXPERIMENTS: webframeworks

      - name: delete GOOGLE_APPLICATION_CREDENTIALS
        run: rm $GOOGLE_APPLICATION_CREDENTIALS
        if: ${{ always() }}

```

</details>

↑のようにファイルを修正後、pushすることで警告が消えました！素晴らしい…

# おわりに

出来たからOK、動いたからOKという考えではなく、警告が出たときはちゃんと対応しようね！（自戒）

# 参考

https://qiita.com/acu8/items/85852e0b014510d63b6c

https://note.com/build_service/n/nd4756ceb103f

https://zenn.dev/jinwatanabe/articles/4026d373383739

## JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！

https://projisou.jp/
Swift Charts 特定の時だけデフォルトのAxisラベルを使いたい

Swift Chartsの小ネタです。

データが多いとうまいことラベルの表示位置を制御できなかったので、表示期間によってラベルの表示を変えたいことがありました。
ただラベルをカスタムしているので、標準のラベルをどうやって明示的に利用するのか悩んでしまいました。
以下でできましたので共有になります。

```swift
    @AxisContentBuilder
    private var chartXAxisContent: some AxisContent {

        if historyRange != .all {
            AxisMarks(
                preset: .extended,
                position: .bottom,
                values: .stride(by: .day, count: histories.count / 6)
            ) { value in
                if let date = value.as(Date.self) {
                    AxisTick()
                    AxisGridLine(centered: false)
                    AxisValueLabel(collisionResolution: .disabled) {
                        xAxisLabel(date)
                    }
                }
            }
        } else {
            AxisMarks()
        }
    }
```

# 参考記事

いつもお世話になっております。

https://qiita.com/yamakentoc/items/55a7d7264691b2caf592
zero-shot-react-descriptionの覚書


https://medium.com/@ismail.lamaakal/unlocking-the-power-of-langchain-building-llm-powered-applications-for-the-future-e7c315cc35ad




```python
!pip install langchain=="0.1.14" langchain-openai=="0.1.1"
!pip install google-search-results


import os
from google.colab import userdata
os.environ['OPENAI_API_KEY'] = userdata.get('OPENAI_API_KEY') 
import pprint
os.environ["SERPAPI_API_KEY"] = userdata.get('SERPAPI_API_KEY')
```


```python
from langchain_openai import ChatOpenAI
from langchain.agents import load_tools
from langchain.agents import initialize_agent


langchain.verbose = True
chat = ChatOpenAI(
    temperature=0,
    model="gpt-3.5-turbo",
    streaming=True,
    callbacks=[
        #StreamingStdOutCallbackHandler()
    ]
)
tools = load_tools(["serpapi", "llm-math"], llm=llm)

agent = initialize_agent(tools, chat, agent="zero-shot-react-description")
agent.run("レオナルド・ディカプリオの恋人は誰？そして彼女の年齢を0.43乗すると何歳になる？")

```
JavaScript: カレンダーアプリで今月に記述されている「先月の最終週」と「翌月の最初の週」を取得する方法

## 読んで欲しい人

- カレンダーアプリで下記の部分を取得する方法がわからん人
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819522/8727104d-bf27-f6c9-7bb0-d888b0ce861d.png)
  - 1.先月から今月に、はみ出てきてる奴ら：28, 29, 30, 31
  - 2.翌月から今月に、はみ出てきてる奴ら：1, 2, 3, 4, 5, 6, 7

- dotインストールの問題を自力で解こうと頑張ってた過去の俺

## ソースコード

### 1.先月から今月に、はみ出てきてる奴ら：28, 29, 30, 31

```javascript
  const getCalendarHead = () => {
  
    const dates = []
    const d = new Date('現在の年', '現在の月', 0).getDate()
    const n = new Date(currentYear, currentMonth, 1).getDay()

    for (let i = 0; i < n; i++) {
      dates.push(d - i)
    }

    return dates
  }
```

**考え方**

- 先月の最終日を `d` として定義する。
- 今月の1日の曜日を `n` として定義する。

イメージ
| 28 | 29 | 30 | 31 | 1 | 2 | 3 |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| Sun  |  Mon | Tue  | Wed  | Thu  | Fri  |  Sat |
|   |   |   | d  |   |   |   |   |
| 0  |  1 |  3 |  4 |  5(n) |   |   |   |

- 先月の `d(最終日)`から`n（曜日分）`分のループを回して1ずつ引いていく


**解説**

- `new Date('現在の年', '現在の月', 0).getDate()`
  - `new Date`の日数の引数に0を指定して、`getDate()`をすると先月の末日を返してくれる
  - イメージ：2024/08/00 = 2024/07/31 だよね

- `new Date(currentYear, currentMonth, 1).getDay()`で曜日を取得する
  - jsでは、曜日は0-6の数値で取得されます
  - 0が日曜日、２が火曜日といった具合


### 2.翌月から今月に、はみ出てきてる奴ら：1, 2, 3, 4, 5, 6, 7

```javascript
  const getCalendarFoot = () => {
  
    const dates = []
    const n = new Date('現在の年', '現在の月' + 1, 0).getDay()

    for (let i = 1; i < 7 - n; i++) {
      dates.push(i)
    }

    return dates
  }
```

**考え方**

- 翌月は逆に数字を足していくことで求められる
- 最終日の曜日から土曜日までループを回して、日数を取得する

| 28 | 29 | 30 | 31 | 1 | 2 | 3 |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| Sun  |  Mon | Tue  | Wed  | Thu  | Fri  |  Sat |
|   |   |   |  n |  1 |  2 |  3 |  4 |

**解説**

- `new Date('現在の年', '現在の月' + 1, 0).getDay()`で今月の最終日の曜日を取得して`n`に定義する

以上


## 感想、考えたこと

- ロジックを考えるのが苦手なので精進します

- ロジックを考える上で意識したほうがいいのかな？と思ったこと
  1. 求めたい内容（表示したい、取得したい etc）を定義する
  2. 何があれば1が実現できるのか、考える
  3. 2を実行する
  4. 3の結果を元に検証して2に戻る

- Atcodeとかやったほうがいいのか
Workato：ワークスペースに招待された時に行うこと（Workatoを初めて利用する方向け）

# はじめに

これからWorkatoのレシピ開発や運用に携わる方は、組織が管理するWorkatoのワークスペース管理者よりWorkatoワークスペースの招待を受けることで、組織のWorkatoワークスペースを利用できるようになります。

しかし、招待を受けたけれども、組織のワークスペースを利用する方法が分からない方もいらっしゃるかと思います。今回、そのような方向けに手順をまとめてみました。

# ワークスペースへの招待（メール受信）

管理者からWorkatoのワークスペースへの招待を受けると次のようなメールが届きますので、「View invitation」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/b30032c8-5353-7a92-cf1e-bfadaf6c3ccb.png)


# Workatoへのサインアップ（ユーザー登録）

::: note info
サインアップが既に完了している場合は次項へお進みください。
:::


招待されたメールアドレスで初めてWorkatoを利用する（Workato上で当該メールアドレスでのアカウント登録が無い）場合、サインアップ画面（ユーザー登録画面）が表示されます。

ユーザー名とメールアドレスは既に入力されていると思いますので、表示されているルールに従いパスワードを設定し、「Create your account」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7c1c9c1f-2603-697c-53e1-cf7f7d46391e.png)

「Create your account」をクリック後、確認メールが届きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d08a4ac3-c8d8-387f-842f-fd70235b00b5.png)

確認メールの「Activate Account」をクリックすると、アカウントが有効化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/934a2177-5207-9525-92b4-87148f6a3324.png)

# Workatoへのログイン

::: note info
ログインが既に完了している場合は次項へお進みください。
:::

Workatoへのログインが完了していない場合、あるいは上記メールの「Activate Account」をクリックすると、サインイン画面（ログイン画面）が表示されます。

メールアドレスとパスワードを入力し、「Login」をクリックすると、Workatoへログインが行われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8a86a6a1-f771-6311-ad81-2603212f4025.png)

# 招待の受諾

ログインが完了すると、自分（個人）のワークスペースの画面が表示されます。

この画面の左上に「Pending invitation」という表示と「View invite」というボタンがありますので、「View invite」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3174ed6b-d4cb-b56f-5737-d0e46c7f9948.png)

Pending invitationsに招待を受けたワークスペースが表示されますので、「Accept」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/e249dc68-e9ea-343f-f69f-56c9ee682c6c.png)

以下のようにメッセージが表示され、招待されたワークスペースが利用可能な状態となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/66e52cf6-cb5c-a69f-0c41-f9fed739e16d.png)


# ワークスペースの切り替え

以下の記事をご参照ください。

https://qiita.com/tabimoba/items/7f7a281b03125c27d49d
Workato：組織のワークスペースに切り替える方法（Workatoを初めて利用する方向け）

# はじめに

Workatoで組織のワークスペースへ切り替えるには、以下①②のように、ログイン後、ワークスペース切り替え操作を行い、ワークスペース切り替え後に組織のワークスペースが利用可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/abdd47b5-ad98-0b0f-0984-efeceb35792a.png)

しかし、初めてWorkatoに触れる方にとっては、この手順は分かりにくいと感じるかと思います。今回は、そのような方向けに手順をまとめてみました。

# ワークスペース切り替え手順

組織のワークスペースに切り替える際は、Workatoへログイン後、まず最初に画面右上のアイコンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/14b60a70-d2e2-050c-1ba3-65e62dd7911d.png)


切り替え可能なワークスペースが一覧で表示されます（１つしか無い場合は１つしか表示されません）。切り替えたいワークスペースを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7c076eff-351b-3920-dc1a-ea40c2ea67e3.png)


選択されたワークスペースに切り替わり、選択されたワークスペース上で作業が行える状態となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/89f3e4da-cf32-05be-237d-f16c4229fa3a.png)

なお、現在表示中のワークスペースは、右上のアイコン（アバター）にマウスオーバーすることで確認可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/2535a22a-0950-b223-4749-6e412c66f3c1.png)

# SAML SSO環境下における注意点

SAML SSOをWorkatoの認証方式として選択した環境（Entra IDやOkta等のIdPをWorkatoの認証に用いている環境）においては、上記とは手順が異なります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/38416b4a-ca8e-737b-fbb5-8e81157644ec.png)

まず、IdP-Initiatedの場合（IdP上でWorkatoワークスペースを選択した場合）は、IdPが提供するポータル画面等からワークスペースに対応するアプリを選択することで、Workato上でワークスペースを切り替えることなく、直接目的のWorkatoワークスペースを開くことが出来ます。（組織のワークスペースをユーザーへ利用させる際は、最もスマートな方法になります）

次に、SP-Initiatedの場合（Workato上でWorkatoワークスペースを選択した場合）は、ワークスペース切り替え後にIdPへリダイレクトされます。IdPの認証が完了していない場合（あるいはIdPのログインセッションが有効期限切れとなった場合）は認証が求められ、認証後に目的のワークスペースへリダイレクトされます。

なお、注意点として、SP-Initiatedの場合のログイン（図の「①ログイン」）は、IdPで払い出された認証情報ではなく、Workatoで設定された認証情報を入力する必要があります。

Workatoのワークスペースは、ユーザーあるいは組織ごとに独立しており、認証方式の設定も組織で一体になっておらず、ワークスペースごとに独立しています。つまり、**SAML SSOは組織のワークスペースに対して設定されていても、個人のワークスペースにその設定が反映されません。** よって、個人のワークスペースへログインする際は、Workatoで設定された認証情報を利用する必要があります。

SAML SSOをWorkatoの認証方式として選択される際は、以上の仕様があることを予め理解いただくとともに、ログインの仕様についてユーザーに対して説明いただくことを推奨いたします。
Linuxで迷わない！rpmとyumの違いをやさしく解説


# はじめに

Linuxを使っていると、ソフトウェアのインストールや管理で「RPM」や「YUM」という言葉を耳にすることがあると思います。今回は、RPMとYUMの違いについて初心者向けにわかりやすく解説します。

## RPMとは？

**RPM**（Red Hat Package Manager）は、主にRed Hat系のLinuxディストリビューション（例：CentOS、Fedora、RHEL）で使用されるパッケージ管理システムです。RPMパッケージは、.rpmという拡張子のファイルとして提供されます。

### 主な機能
- **ソフトウェアのインストール**: rpmコマンドを使って、指定したパッケージをインストールします。
- **ソフトウェアのアップグレード**: 既にインストールされているパッケージを新しいバージョンにアップグレードします。
- **ソフトウェアの削除**: 不要になったパッケージを削除します。
- **パッケージの情報取得**: パッケージのバージョンや依存関係などの情報を表示します。

### RPMの基本コマンド例
```bash
# インストール
rpm -ivh package_name.rpm

# アップグレード
rpm -Uvh package_name.rpm

# 削除
rpm -e package_name

# 情報取得
rpm -qi package_name
```

## YUMとは？

**YUM**（Yellowdog Updater, Modified）は、**RPMパッケージを管理するための上位ツール**です。RPM単体でもパッケージ管理は可能ですが、YUMを使うと依存関係の解決が自動化され、複数のパッケージを一度に管理することが容易になります。

### 主な機能
- **依存関係の自動解決**: YUMは、インストールするパッケージが依存している他のパッケージも自動でインストールしてくれます。
- **リポジトリの利用**: リポジトリというパッケージの集まりから、インターネット経由でパッケージを取得・インストールできます。
- **簡単なアップデート管理**: システム全体のパッケージを一括でアップデートできます。

### YUMの基本コマンド例
```bash
# パッケージのインストール
yum install package_name

# パッケージのアップデート
yum update package_name

# 不要なパッケージの削除
yum remove package_name

# システム全体のアップデート
yum update

# リポジトリの情報取得
yum repolist
```

## RPMとYUMの違い

| 項目 | RPM | YUM |
| --- | --- | --- |
| 基本機能 | パッケージのインストール、削除、情報取得など | RPMパッケージの管理、依存関係の自動解決、リポジトリ管理など |
| 依存関係の解決 | 手動で解決 | 自動で解決 |
| 利便性 | 手動操作が多く、初心者には難しいことがある | 依存関係の自動解決や一括アップデートが可能で、初心者でも使いやすい |

## まとめ

RPMはLinuxのパッケージ管理の基本ツールですが、依存関係の解決が必要な場合はYUMの方が便利です。特に、初心者にはYUMを使ってパッケージ管理を行うことをお勧めします。

この記事がRPMとYUMの違いを理解する一助となれば幸いです！
TeamsでWorkflows(PowerAutomate)を使う

TeamsでWorkflowsを使用し、躓いたことを記載していく。

# 現在の時刻を取得する
現在の時刻を取得後にタイムゾーンの変換をおこない日本時間にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123325/229be723-97cb-0a54-5377-166f5ae3bc88.png)

動的変換後の時間を使う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123325/9576ad3e-1216-b96a-69d9-6fae740d4d93.png)

また、タイムゾーンの変換で表示形式を指定できる
＊カスタムを選ぶこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123325/caca5b3a-5faf-c89c-f965-3617715be7c6.png)

書式は下記を参照

https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings

# エラーが発生する
### このフローを実行するには、位置情報サービスを有効にする必要があります。

動いていたのに少し修正したら、急にこのエラーが発生し、動かなくなることがある。

位置サービスが問題というよりもアカウントの接続の問題？

https://make.powerautomate.com/

フローを新規作成で作り直したところ直った。
もっと効率のいい解決方法があるといいのだが、原因はよくわからず。

### 実行でエラーになる
関数を使用しているのであれば、引数が足りていない場合がある。エラー文は全く関係ない場合があるので関数を使っている場合は引数を確認すること。

### 動的コンテンツ、式エディターがでない。関数が使用できない。
式を直接メッセージに入力しても使用できない。
式エディターを使用する。
式エディターは画面の倍率が大きいと表示されない。
縮小すると出てくる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123325/3b4ec455-325f-7413-7688-4ac5dd306651.png)


# トリガーで入力値を使う
### メッセージ投稿時、オン/オフの選択肢を設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123325/54c462c8-d393-9de8-1083-bd7c49b45a49.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123325/d18d7bdd-7767-9fb7-b970-7cccede0c67b.png)

### リストから選択肢を設定する。
カードを使用する。
EXCELの列のアルファベットを取得する関数

以下の数式を使うと、Excelのセルの列番号をアルファベット表記に変換することができます。

具体的には、次のような数式です：

```excel
=SUBSTITUTE(ADDRESS(ROW(),COLUMN(),4),ROW(),"")
```

### 解説:
- `ADDRESS(ROW(), COLUMN(), 4)` は、現在のセルのアドレスを "R1C1" 形式で取得します。例えば、セル A1 なら "A1"、セル B2 なら "B2" となります。
- `SUBSTITUTE` 関数を使用して、取得したアドレスから行番号（ROW()）を削除します。これにより、列のアルファベットだけが残ります。

例えば、セル C5 にこの数式を入力すると、結果は "C" になります。

この方法を使用して、任意のセルの列のアルファベット表記を取得することが可能です。
自己紹介的なもの

はじめまして

れいと申します。

普段はほとんどOracle Databaseの運用保守をやっているおっさんです。

こういうものは、初めて書くのでいささかどうすればいいかわかりませんが、やりながら徐々に慣れていきたいとおもいます。

なかなか、技術系の記事は正確な情報を書くのが難しいですが、自分の過去の経験や勉強したことを色々書ければと思います。

ちなみに、現在はreal application testing（RAT）の勉強をしてます。

それでは、また次の記事で。
Flutterでtodoアプリを作る

https://www.flutter-study.dev/todo-app/about-todo-app

👆を参考に分からないところと、新しい学びをメモ

### 画面遷移
#### ある画面から別の画面へ移動
```dart
{
Navigator.of(context).push(
            MaterialPageRoute(builder: (context) {
              // 遷移先の画面としてリスト追加Widgetをラップするclassを指定
              return TodoAddPage();
            }),
```

#### 元の画面へ戻る
```dart
{
    // "pop"で前の画面に戻る
    Navigator.of(context).pop();
          },
```
+ Navigator.of(context).push(...)、.pop()
    + Navigator
        + Flutterのウィジット
        + アプリ内のナビゲーションを管理する
        + クラスとして定義されている
    + .of(context)
        + Navigatorクラスの静的メソッド
        + 現在のコンテキストに関連する Navigator インスタンスを取得する
    + push(...)
        + 取得したNavigatorインスタンスのメソッド
        + 新しい画面をスタックに追加する
    + pop()
        + ナビゲーションスタックの一番上にある画面を削除して、前の画面に戻る
Pythonを使って電卓を作ろう！！

Pythonをつかって電卓を作ろう。
下のコードは見た目だけだ。

```
# 電卓 Level0

import sys
import tkinter as tk

# メイン関数
def main():
    root = tk.Tk()
    root.title("電卓L0")
    den = Dentaku(root)
    root.mainloop()

# 電卓クラス
class Dentaku():
    # 作成
    def __init__(self, root):
        self.tf = tk.Frame(root)    # トップレベルのフレーム
        self.tf.grid(column = 0, row = 0, padx = 15, pady = 15)

        # ボタンを配置
        ButtonDef = (
        #     行 列 ラベル 関数
            (4, 0, "0", self.numinput),
            (3, 0, "1", self.numinput),
            (3, 1, "2", self.numinput),
            (3, 2, "3", self.numinput),
            (2, 0, "4", self.numinput),
            (2, 1, "5", self.numinput),
            (2, 2, "6", self.numinput),
            (1, 0, "7", self.numinput),
            (1, 1, "8", self.numinput),
            (1, 2, "9", self.numinput),
            (4, 1, "*", self.mul),
            (4, 2, "/", self.div),
            (1, 3, "-", self.sub),
            (2, 3, "+", self.add),
            (3, 3, "=", self.equal),
            (4, 3, "C", self.clear))

        root.option_add('*Button.font', 'ＭＳゴシック 28')
        for r, c, label, func in ButtonDef:
            Button = tk.Button(self.tf, text = label)
            Button.bind("<Button-1>", func)
            Button.grid(column = c, row = r, sticky = tk.N +tk.E + tk.S + tk.W)

        # 数字が表示される「エントリー」
        root.option_add('*Entry.font', 'ＭＳゴシック 32')
        self.NumBox = tk.Entry(self.tf, width = 10, justify = tk.RIGHT)
        self.NumBox.insert(tk.END, "0")
        self.NumBox.grid(column = 0, columnspan = 4, row = 0)

    # ボタン毎の動作を定義（イベントドライバ群）
    def numinput(self, e):            # 数字キー
        pass

    def mul(self, e):                # ×
        pass

    def div(self, e):                # ／
        pass

    def sub(self, e):                # －
        pass

    def add(self, e):                # ＋
        pass

    def equal(self, e):                # ＝
        pass

    def clear(self, e):                # Ｃ
        pass

if __name__ == '__main__':
    main()

```
まずは…。
1️⃣　計算できるようにしてみよう。
2️⃣　小数点まで計算できるようにしてみよう
10万円台のプログラミングスクールに通った話

# なぜこのプログラミングスクールに通ったのか
　フルリモートの仕事に応募したくて、技術力をつけたかった。支部が家から近かったので通った。支部の社員と話をすると「私は以前、フリーランスをやっていて実務経験があります」「ここに通えば簡単にフルリモートの仕事ができますよ」と答えたので期待してしまった。
# 講師の質
　プログラミングを教えるのは自分が通う支部の社員ではなく、県外の支部の社員が講義をしているのを配信で見るという形だったので面食らった。この講師はここのスクール卒業生で不安になった。
 　なのでIT関係の企業で働いた話やフリーランスで稼いだ話などがないので、プログラミングで収入を得ることに関して何を言っても言葉が上滑りしているように思えた。自分が通う支部の社員はフリーランスでの実務経験があるので、聞けば的確なアドバイスがもらえた。
 # 授業内容
　教材を用意していないので、講師がスクールに関係ない企業のHPやプログラミング関係のサイトをひたすら音読しているだけだった。どこかのサービスにアカウントを作ってちょっと触って終わりの繰り返しで技術が身に付かなかった。
  　ChatGPTで簡単なアプリを作る授業に時間をかけていたが、授業が進めば進むほど、生徒の作ったものの画面構成がバラバラで、機能を追加するとインデントエラーが出たりで全体的に上手くいっていない印象だった。Slackの生徒たちのコメントを見ていると完成させられてない人が大半に思えた。自分も完成させることができなかった。
   # 卒業制作
　全体的に生徒数が少なかったので、Slackで県外の人とチームを組んでアプリを作らなければならなかった。過去の講座だと受講生が多かったので支部内で話し合って作っていた。
 　今までやってきた授業が講師の音読を聞くことばかりで、生徒はあまり手を動かしていない割には、提出物に求められる基準が高いので、無茶苦茶だと思った。
  　テーマ決めで印象深かったのが、チームで出た案を講師に話した時、
  　「あなたたちが言ってるような、検索すれば出てくるようなサービスやアプリに対して、顧客はお金を出しますか？」
   　といったダメ出しだった。「それはそうだな」と思う反面、これまでやってきた授業のレベルで独自のアプリを作るのは無理だろう、と思い、辞めようかと思ったが、運良くも他のチームメンバーの案が講師に通ったので辞めずに済んだ。
　他のチームメンバーが有能で自分の出る幕はないな、と思ったが、彼がアプリの大枠を作ったはいいものの、どのダブをクリックしても同じ情報が出てくるといったエラーが解決せず、制作を投げたので自分がChatGPTで「クリックしたダブの情報を個別に出てくるようにしろ」と命令して修正した。
　このチームメンバーが最後までアプリを完成させたら自分は役立たずであっただろう。
# 感想
　控えめに言って10万円台の価値はなかった。月1000円台で受けられるオンラインのプログラミングスクールがあると後で知った。たとえばN予備校なら、色んな言語の授業が見放題で月1000円なわけで、就職のサポートがない10万円台のスクールに通う意味などなかった。
 # 学んだこと
 　授業内で「わからないなら検索しろ」というワードが頻発したが、基礎的なプログラミングの知識がないと検索するワードが出てこない。
  　ChatGPTは魔法のツールなどではなく、プログラミングの基礎知識があって補助的に使えば有効なツールなのであり、プログラミングを知らない者がChatGPTを使ってアプリを作っても、なぜエラーになるのか意味がわからなかったり、修正しようにもChatGPTにどう尋ねたらいいのかわからないといったことがおこり、そしてChatGPTの出した答えの意味がわからない状態になる。
　したがって、勉強に近道などなく、地道な参考書の読書や、コードの写経といった積み重ねを行った後でやっとChaTGPTを有効活用できるのだと思う。
GitHub Pull requestsのUnityの.metaファイルを全て非表示にするスクリプト (ブックマークレット)

## 内容 
* Unity開発時の、GitHub Pull requestsで.metaファイルをすべて非表示にしてレビューしやすくするJavaScriptです
* ChromeのJavaScriptコンソールで下記のスクリプトを実行します
* または、[ブックマークレット](https://ja.wikipedia.org/wiki/ブックマークレット)に登録しておくとすぐに使えて便利です

## .metaファイルをすべて非表示にする
```js
var elements = document.getElementsByClassName("file");
for (var element of elements)
{
    if (element.dataset.fileType.indexOf(".meta") != -1)
    {
        element.remove();
    }
}
```
## ブックマークレットに登録
ブックマークにJavaScriptを登録する仕組みであるブックマークレットを作成しておくとすぐに実行できて便利です。


#### Chromeの登録画面
![chrome_bookmark.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203221/f278dec0-6b60-32f5-6e5a-8960f3b49fa5.png)



URL欄に以下のコードを入力します。
```js
javascript:var elements = document.getElementsByClassName("file"); for (var element of elements) {     if (element.dataset.fileType.indexOf(".meta") != -1)     {         element.remove();     } }
```

※ ブックマークレットはブラウザのブックマークでURLに`javascript:`に続けて任意のJavaScriptコードを入力するとブックマークを開いたときにそのコードが実行される仕組みです。

※ 参考
[知ってそうで知らないブックマークレットの仕組みと使い方](https://www.lifehacker.jp/2013/04/130402bookmarklet_matome.html)
【SOA】試験対策メモ その3

# Amazon Route 53
## アウトバウンドエンドポイント
アウトバンドへの転送ルールはVPCに紐づける必要がある

>ルール
ネットワークの DNS リゾルバーに転送するクエリのドメイン名を指定するには、1 つまたは複数のルールを作成します。各ルールは 1 つのドメイン名を指定します。次に、ネットワークにクエリを転送する VPC にルールを関連付けます。

https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/resolver-forwarding-outbound-queries.html

## Aliasレコード
実態はAレコードやCNAMEレコードでも、レコードの作成時にAliasの指定ができる。
ELBなどはIPが変更される可能性があるので、そもそもAliasレコードで作成される。

# AWS サポートプラン
## プラン変更
変更用ポリシーを持つIAMで変更可能。ルートユーザーでなくても可能。

# EC2
## システムチェック
インスタンスのホスト上で問題が起きているか確認する。
システムチェックがエラーの場合、インスタンスを一度停止し、インスタンスが実行されるホストを変更する必要がある。
(インスタンスが停止され、再起動すると実行ホストが変更される)

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html

## インスタンスステータスチェック
活動しているインスタンス上で問題が起きているか確認する。
メモリの枯渇やファイルシステムの破損などが原因で失敗と判定されることがある。

# AWS Systems Manager
## Systems Manager Distributor
サードパーティソフトウェアをAWS Systems Managerドキュメント化するサービス。
このサービスでパッケージングすることで、state Managerなどで簡単に使用することができる。

# ELB
## ALB
7層を扱うので、リスナーはHTTPやHTTPS

## NLB
4層を扱うので、リスナーはTCPやUDP

## スキーム
外部インターネット向きか、VPC内部向きか選択することができる。
Cloudfrontを前段に設置する場合は、外部インターネット向きで作成する必要がある。

# Savings Plans
## 概要
1年または3年の期間コミットメントした料金で割引をうけることができる。

## Compute Savings Plans
柔軟性が高く、インスタンスファミリーやリージョンなどを変更できる。

## 利用率の監視
SavingsPlansUtilizationメトリクスが存在する。

# S3
## Glacierの取り出し時間
Glacier Instant Retrieval：即時
Glacier Flexible Retrieval：迅速（5分未満）、標準（3~5時間）、大容量（5~12時間）
Glacier Deep Archive：標準（12時間）、大容量（48時間以内）

https://dev.classmethod.jp/articles/amazon-s3-glacier-flexible-retrieval-improves-restore-time/

# AWS OpsWorks
## 概要
Chef や Puppet のマネージド型インスタンスを利用できるようになる構成管理サービスです。
いにしえソフトをクラウドで実行するツール？

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

# Amazon Athena
## 概要
S3内のファイルをSQLでクエリできるサービス。

# RDS
## Aurora Global Database
別リージョンにセカンダリークラスターがレプリケートされる。

# IAM
## IAMユーザー作成の検知
AWS CloudTrailで検出する。

# CloudWatch
## メトリクスフィルター
CloudWatch logの中から特定のパターンのログの出現をメトリクスにpushする機能。

## サブスクリプションフィルター
CloudWatch logをstream系のサービスにデリバリする機能。

# CloudWatchエージェント
## procstatプラグイン
インスタンス上で実行されているプロセスをcloudwatch metricsに転送することができるプラグイン。

# Cloudfront
## 代替ドメイン設定機能
Cloudfrontは自身の認識しているドメインでのアクセスしか受け付けない（Route53でCNAME設定するだけではダメ）。
そのため、Cloudfrontの代替ドメイン設定とRoute53のレコード作成どちらも必要

# Amazon Detective
## 概要
Amazon VPC Flow Logs、AWS CloudTrail ログ、Amazon EKS 監査ログ、統合された AWS のサービスから AWS Security Hub に送信された検出結果、Amazon GuardDuty の検出結果などの複数のデータソースからインシデントを検査するサービス。

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

# Amazon GuardDuty
## 概要
悪意のある操作や不正な動作などアカウント全体を継続監視するサービス。


# セキュリティグループ
## デフォルト値
インバウンド/アウトバウンドどちらも全てのトラフィックを許可している。
[paiza]野球の審判

# だんだんやる気が。。。
千葉大会の市船の決勝戦、監督が直接審判とやり取りできないからって、キャプテンの子が審判と監督の間を行ったり来たりの板挟み状態で、これは将来立派な中間管理職になれそうですね！
ってか、オリンピックもそうだけど、これだけカメラだったりAIの技術が上がったんだから、誤審して叩かれる人間の審判ってもういらなくね？

あとサッカーの超演技的痛がり方はもはや芸術の域だよね！
あんなに痛がってたのに、数秒で立ち上がってプレー再開できるとか超人なのか？

https://paiza.jp/works/mondai/c_rank_skillcheck_archive/umpire

# 面倒くさいので画面パタメータをListでもらった後のFunctionだけ
ちなみに引数のListを作ってる箇所は[こっちの記事](https://qiita.com/AsilHatake/items/842548e48ae4a0eae119)に書いてあるYO!!

```javascript:umpire.js
// [問題文（原文）]
// 野球の各打者はストライクが 3 つたまるとアウトとなり、ボールが 4 つたまるとフォアボールとなります。
// アウトあるいはフォアボールになると、この打者の番は終了します。
// 
// あなたはストライクとボールを判定してコールする審判です。
// その場の状況に合わせて適切なコールを出しましょう。
// 
// 【コール一覧】
// ストライクが 1 〜 2 つたまったとき → "strike!"
// ストライクが 3 つたまったとき → "out!"
// ボールが 1 〜 3 つたまったとき → "ball!"
// ボールが 4 つたまったとき → "fourball!"
// 
// ある打者の番における投球の結果 (ストライクまたはボール) が与えられるので、各投球に対してどのようなコールをすればよいかを出力してください。
// なお、実際の野球にあっても上記にないルール (ヒット、ファウルなど) については考慮する必要はありません。
// 
// 
// 1 球目: ボール → "ball!"
// 2 球目: ストライク → "strike!"
// 3 球目: ボール → "ball!"
// 4 球目: ストライク → "strike!"
// 5 球目: ストライク → "out!"
// 
// 5 球目では、ボールが 2 つ、ストライクが 3 つたまったのでこの打者はアウトとなります。
// これは、入力例 1 に対応しています。
// 
// 
// 1 球目: ボール → "ball!"
// 2 球目: ストライク → "strike!"
// 3 球目: ボール → "ball!"
// 4 球目: ボール → "ball!"
// 5 球目: ストライク → "strike!"
// 6 球目: ボール → "fourball!"
// 
// 6 球目では、ストライクが 2 つ、ボールが 4 つたまったのでこの打者はフォアボールとなります。
// これは、入力例 2 に対応しています。
function umpire(lines) {
  // 入力は、以下のフォーマットで与えられます。
  // 
  // N
  // s_1
  // s_2
  // ...
  // s_n
  // 
  // 1 行目に合計の投球数を表す整数 N が与えられます。
  // 続く N 行のうち i 行目 (1 ≦ i ≦ N) に i 番目の投球の結果を表す文字列 s_i が与えられます。i 番目の投球がストライクであれば s_i は "strike"、ボールであれば "ball" となります。
  // 入力は合計で N + 1 行からなり、入力値最終行の末尾に改行が１つ入ります。
  if (!Array.isArray(lines) || lines.length < 4 || lines.length > 7) {
    console.log("4～7行以上入れろや！");
    return;
  }
  // 投球数
  const throwCnt = Number(lines[0]);
  if (isNaN(throwCnt) || !Number.isInteger(throwCnt) || throwCnt < 3 || throwCnt > 6) {
    console.log("投球数は3～6の数値入れろや！");
    return;
  }
  // 各投球に対する適切なコールを以下の形で出力してください。
  // 
  // c_1
  // c_2
  // ...
  // c_N
  // 
  // 期待する出力は N 行からなります。
  // N 行のうちの i 行目 (1 ≦ i ≦ N) に問題文の条件に即して打者へのコールを表す文字列 c_i を "strike!", "ball!", "out!", "fourball!" のいずれかで出力してください。
  const count = [0, 0];
  lines.slice(1, throwCnt + 1).forEach((throwResult) => {
    let call = "";
    if (throwResult === "strike") {
      count[0]++;
      call = count[0] === 3 ? "out!" : "strike!";
    } else if (throwResult === "ball") {
      count[1]++;
      call = count[1] === 4 ? "fourball!" : "ball!";
    }
    console.log(call);
  });

}

module.exports = {
  umpire
};
```

なんかもっといい感じに書けそうな気がするけど、とりあえず仕様通りに動くやつ。
【Next.js】Imageをピクセル以外でサイズ指定したい

いつもwidthとheightを指定してImageコンポーネントを使用していたのですが、ピクセル指定ではなく幅いっぱいに広げたい時があり、やり方を調べました。
バーションなどによっても違うみたいですが、今の私の環境 (Next.js 14.1.4) での指定の仕方を記録しておきます。

tailwindCSSを使用しています。

## 結論
```ts
<div className="w-full">
    <Image alt="hoge" src="/hoge/hoge.png" fill className="!relative" />
</div>

```

Imageコンポーネントの親要素で希望の幅を指定し、Imageコンポーネント自体にrelativeを充ててimportantにし、fillをtrueにすると完成です。

width/heightは基本的に必須のPropsですが、fillを指定したらなくても大丈夫のようです。

## 公式サイト確認する
以下、公式サイトのfillの説明です。


>A boolean that causes the image to fill the parent element, which is useful when the width and height are unknown.
>The parent element must assign position: "relative", position: "fixed", or position: "absolute" style.
>By default, the img element will automatically be assigned the position: "absolute" style.
>If no styles are applied to the image, the image will stretch to fit the container. You may prefer to set object-fit: "contain" for an image which is letterboxed to fit the container and preserve aspect ratio.
>Alternatively, object-fit: "cover" will cause the image to fill the entire container and be cropped to preserve aspect ratio. For this to look correct, the overflow: "hidden" style should be assigned to the parent element.

https://nextjs.org/docs/pages/api-reference/components/image

「親要素を画像で埋めるブール値」だそうですので、親要素で幅指定してfillをtrueにしたらOKということみたいです。
また、「position: "absolute"」がimageコンポーネント自体にデフォルトで割り当てられているので、relativeをimportantで指定しないと意図しないところに画像が表示されてしまいます。

公式サイト読むの少し抵抗ありますが勇気を出して(翻訳して)読むと、意外と理解できます。
わからなかったらまず公式の癖つけたいです。
Langchainの覚書

# langchainとは

LangChainは、LLMを活用した開発のためのフレームワークです。次々と開発される新しい仕組みに追従するため、抽象レイヤーを用いて開発を行うことができます。LangChian自身も開発のスピードが早く、2024/1/6 にバージョン 0.0.354 から 0.1.0 へのアップデートが行われ、LangChain 初の安定バージョンとしてリリースされています。PythonとJavaScriptの両方から利用ができるという点も非常に大きなメリットです。

https://js.langchain.com/v0.1/docs/get_started/introduction/


一方で、0.2からは大きくパッケージの構成なども変わり、0.1系で使われてきた仕組みをそのまま利用することができない場合も多い点には注意が必要となっています。

https://python.langchain.com/v0.2/docs/introduction/

![IMG_0058.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/9978b704-6a13-aa92-a52b-68df6024637a.jpeg)

この辺りの最新の情報のキャッチアップは、

LnagChainの公式ブログ
https://blog.langchain.dev/
などを見ておくと機能追加や、最新情報は理解できるかと思います。

また、下記のawesome-langchainなどでは、langchainを活用したオープンソースなどが紹介されていたりするためユースケースなどを知ることなどができます。

https://github.com/kyrolabs/awesome-langchain

https://docs.llamaindex.ai/en/stable/examples/data_connectors/WebPageDemo/

# 実行環境

簡単に実行するために、GoogleColabを活用します。
また、ブラウザからFlowiseAIというアプリを利用することで手軽にlangchainを実装することもできます。

https://flowiseai.com/


# Langchainの基本的な使い方

Langchainには6つのモジュールが用意されています。

Model/IO...言語モデルを使いやすくする
Retrieval...未知のデータを扱う
Memory...過去の対話を記憶
Chains...複数の処理をまとめる
Agents...自律的に外部と干渉する
Callbacks...イベント発生時の処理を行う

となっています。これから一つずつ事例を書いていこうと思います。


# Model/IO...言語モデルを使いやすくする

```python

```

# Retrieval...未知のデータを扱う


```python
!pip install llama-index
!pip install python-dotenv
!pip install llama-index llama-index-readers-web
!pip install html2text
!pip freeze | grep -e "openai" -e "llama" -e "langchain"
```

```python
import os
from google.colab import userdata
os.environ['OPENAI_API_KEY'] = userdata.get('OPENAI_API_KEY')
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core import ServiceContext, SQLDatabase, VectorStoreIndex
from llama_index.core.indices.struct_store import SQLTableRetrieverQueryEngine
from llama_index.core.objects import SQLTableNodeMapping, ObjectIndex, SQLTableSchema
from llama_index.legacy import LLMPredictor
from llama_index.core import SummaryIndex
from llama_index.readers.web import SimpleWebPageReader
from IPython.display import Markdown, display
import os
```

```python
documents = SimpleWebPageReader(html_to_text=True).load_data([
"https://ja.m.wikipedia.org/wiki/%E3%82%AB%E3%83%96%E3%83%88%E3%83%A0%E3%82%B7"
])
```

```python
index = SummaryIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("カブトムシの種類を5つ教えて")
display(Markdown(f"<b>{response}</b>"))
```

![IMG_0048.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/c85252b3-b257-80a8-bb6c-bbd6dce1f600.jpeg)

![IMG_0049.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/66e23fec-1dd0-4718-e3ec-5cdfea4916f9.jpeg)

![IMG_0050.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/c8dd48ae-815e-e83b-bc0e-fbd91bacec3b.jpeg)



```python

```

# Memory...過去の対話を記憶

```python

```

# Chains...複数の処理をまとめる

```python

```

# Agents...自律的に外部と干渉する

```python

```
Renesas Flash Programmerのcli

mruby/cのvmはCode FlashにおいてmrbはData Flashにおくようにしてみました。

R5F52108ADFPの場合Code Flashの書き込み回数は1000回ですが、Data Flashは100000回です。

Renesas Flash Programmerのcliで焼いてみます。

```
C:\Program Files (x86)\Renesas Electronics\Programming Tools\Renesas Flash Progr
ammer V3.16>rfp-cli.exe -d rx200  -port COM32 -a C:\Users\hiroki\Downloads\hoge.
mot C:\Users\hiroki\Downloads\main.mot
Renesas Flash Programmer CLI V1.10
Module Version: V3.16.00.000
Load: "C:\Users\hiroki\Downloads\hoge.mot" (Size=514, CRC=E9C1492D)
Load: "C:\Users\hiroki\Downloads\main.mot" (Size=333508, CRC=69B28360)

Connecting the tool (COM port)
Tool: COM32
Interface: 2 wire UART

Connecting the target device
Main Clock: 32 MHz
Speed: 57,600 bps
[Warning] ID Authentication is disabled

Connected to RX200 Series

Erasing the target device
  [Data Flash 1]       00100000 - 00101FFF

  [User Boot Area 1]   FF7FC000 - FF7FFFFF

  [Code Flash 1]       FFF80000 - FFFFFFFF

  [Data Flash 1]       00100000 - 001007FF

  [Code Flash 1]       FFF80000 - FFF9BFFF

  [Code Flash 1]       FFFFF000 - FFFFFFFF

Writing data to the target device
  [Data Flash 1]       00100000 - 001000FF

  [Code Flash 1]       FFF80000 - FFF9B1FF

  [Code Flash 1]       FFFFFF00 - FFFFFFFF

Verifying data on the target device
  [Data Flash 1]       00100000 - 001000FF

  [Code Flash 1]       FFF80000 - FFF9B1FF

  [Code Flash 1]       FFFFFF00 - FFFFFFFF



Disconnecting the tool

Operation successful

```

これはうまくいったのですが、mrbのData Flashだけ書き込むと起動しなくなります。

```
C:\Program Files (x86)\Renesas Electronics\Programming Tools\Renesas Flash Progr
ammer V3.16>rfp-cli.exe -d rx200  -port COM32 -p C:\Users\hiroki\Downloads\hoge.
mot
Renesas Flash Programmer CLI V1.10
Module Version: V3.16.00.000
Load: "C:\Users\hiroki\Downloads\hoge.mot" (Size=514, CRC=E9C1492D)

Connecting the tool (COM port)
Tool: COM32
Interface: 2 wire UART

Connecting the target device
Main Clock: 32 MHz
Speed: 57,600 bps
[Warning] ID Authentication is disabled

Connected to RX200 Series

Erasing the target device
  [Data Flash 1]       00100000 - 001007FF

Writing data to the target device
  [Data Flash 1]       00100000 - 001000FF



Disconnecting the tool

Operation successful

```


なんでだろう？
【C#5】1週間で身につくC#の問題を改題して作成した問題を実装

# はじめに
1週間で身につくC#の練習課題を改題して作成した問題を***C#5***で実装しました。

## 問題
>1から10の2つ乱数を発生させ、それぞれの数をたて、よこの■の数として、四角形を表示させるプログラムを作ってください。
>以下の画像のように表示させてください。

![test1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055346/8ddb99f1-5d5b-fe97-3ec5-7af7a179e427.jpeg)

## 実装したソースコード
```C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Probkadai1
{
    class Program
    {
        // 乱数で取得したたて、よこの個数分、「■」を表示する。
        static void Square(int h, int w)
        {   
            string ans;
            for(int i=1;i<=h;i++){
                ans = "";
                for(int j=1;j<=w;j++){
                    // よこの個数とjが一致したとき■の後に半角スペースを入れない。
                    // 一致しない場合は■の後ろに半角スペースを入れる
                    if(j == w){
                        ans += "■"; 
                    } else {
                        ans += "■ ";
                    }
                }
                Console.WriteLine(ans);
            }
        }
        
        static void Main(string[] args)
        {
            Random r = new Random();
            int height = r.Next(1,11);
            int width = r.Next(1,11);
            Console.WriteLine("たて = {0}" ,height);
            Console.WriteLine("よこ = {0}",width);
            Square(height,width);
        }
         
    
```

## 実行結果
実行結果は下記の画像です。(あくまで一例)

![test2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055346/c379ac6c-5e81-47fc-bc41-c74ea21727b1.jpeg)

# 最後に
課題に挑戦してみました。
２つデータを比較して重複がない項目のみExcelに書き込みたい

## よく聞かれる習い始めの方のつまづき
:::note warn
私の記事の中ではあまり難しくありません
PowerAutomateDesktopのVerは2024年6月以降のものにしてください。

:::


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/dd4d782d-3245-f816-cf45-6c19b7cd487e.png)



例)毎日とあるcsvファイルがメールで送られてくる
その中には1カ月分が毎日更新されて記載されているけれど台帳.xlsxに書き写したい。

そういった時に2つのデータを比較して重複していないデータを調べるのに
ExcelだとVlookUpまたはCountIf関数などを利用して調べていたと思います。

PowerAutomateDesktopだとどうできますか？
こういった質問をよく受けました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/660d1cab-9f9a-3a4d-2867-8cb25a6df590.png)


2024年6月のバージョンアップでデータテーブル系アクションが追加となり
その回答の仕方が変わりましたのでこの記事を書きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/c7600cab-23d3-acbf-095b-b72520036d07.png)

## やり方

まずcsvとExcelのデータをそれぞれ読み込みましょう

#### CSV
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/e8d9a84f-c757-e0ac-5151-b595bdae5db3.png)

#### Excel
※日付のデータが入っているとき読み取ると自動で時間も追加されてしまうので
セルの内容をテキストとして取得のトグルをオンにしています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/3c42eb42-f202-7145-9152-1c5e82401b2b.png)

## ここからが新しいやり方

### 2つのデータテーブルを結合アクションを使用


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/3e855dd6-e84c-f55a-e773-c0967a55dec8.png)
その名の通りで2つのデータテーブルを結合してくれます。
|アクション内コマンド|入力内容|
|:-:|:-:|
|最初のデータテーブル|%CSVTable%|
|2つ目のデータテーブル|%ExcelData%|
|結合操作|完全|
|ルールを結合|下記画像を参照|


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/1eddb005-d220-ed6b-94c3-e26aefd20596.png)
※今回はすべての項目が合致するようにしましたがその限りではありません。

結果は下記のとおりで２つのデータテーブルがくっつき、
データが存在する場合は入荷日(2)、商品名(2)…のところに項目が記載されました。
これらが見つけたかった重複データです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/b05feccc-0b33-e355-3af8-bd5a5ef426de.png)

### ここでフィルターデータテーブルアクションの追加
今回データを取得したいのは入荷日(2)、商品名(2)…が空欄となっているデータですので
フィルターデータテーブルアクションを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/8202a9a8-5dcb-9399-dc3a-fa88c50e0e0e.png)
|アクション内コマンド|入力内容|
|:-:|:-:|
|データテーブル|%JoinedDataTable%|
|適用するフィルターの編集|下記画像を参照|

下記画像のように演算子を空白であるを選択してください。

:::note warn
列名はインデックスで指定してみましたが、インデックス指定の場合は1,2,3…ではなく0,1,2,3…と0からのスタートですので注意しましょう。

:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/b46976f6-14bf-3a3f-878d-99b8a79829f6.png)

結果は下記の通りです。これで重複していないデータのみを取り出せました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/cbc605f6-2dd8-6a93-1443-6caf79a372b2.png)


## 最後に

Excelで取得したデータテーブルは
データテーブルアクションで操作できるということ自体を知らない方も多いと思います。

しかしながら今回データテーブル系のアクションが多く追加され
Loopしながら取得することがかなり減りました。
これをきっかけにぜひデータテーブルアクションを利用していくとよいと思います:grin:

※ただし大量のデータ操作の場合は
データベースコマンドが固まってしまったりすることがあるので
ご自身の環境で一度試してから使ってみてください。
【備忘録】PSGI環境で動くMovable Type が503エラーになる場合の対処法

# 動作環境
+ Movable Type 7

以下のドキュメントを元に、CGI→PSGI環境に移行

https://bashalog.c-brains.jp/16/08/08-100000.php

# 原因
長期間停止にしていたMovable Type(以下MT)用のサーバを起動した際に、PSGI環境でMTを実行するプロセス(Starman)が起動していないことが判明。

調べてみると、設定していたはずのプロセスIDを格納する`/var/run/mt/mt.pid`とそのディレクトリの`/var/run/mt`が消失していたことが原因と断定。

また、以下のコマンドでプロセス監視用に導入した`supervisord`のMT用プログラムの状態が、何故か`STARTING`と表示。
(本来なら`RUNNING`の状態が望ましい。)

```shell:supervisordのコマンド
sudo /etc/init.d/supervisord status
```
```shell:本来の状態
movabletype                      RUNNING   pid 18783, uptime 0:02:16
```
```shell:今回のエラー
movabletype                      STARTING
```

調べてみると、設定していたはずのプロセスIDを格納する`/var/run/mt/mt.pid`とそのディレクトリの`/var/run/mt`が消失していたことが反映。
それにより、どのファイルを参照すれば良いか不明であったため、503エラーが発生したものと断定。

# 解決法
手動で`/var/run/mt`と`/var/run/mt/mt.pid`を作成すれば一応は解決するが、停止や再起動の度に手動作成するのは手間なので自動設定する方法を考案。

最初に`/var/run/mt`と`/var/run/mt/mt.pid`を作成するスクリプトを作成。
スクリプト名を`/usr/local/bin/setup_mt.sh`とし、以下の内容を記載。
```shell:/usr/local/bin/setup_mt.sh
#!/bin/bash

# /var/run/mtディレクトリがない場合は作成
if [ ! -d /var/run/mt ]; then
    mkdir /var/run/mt
fi

# /var/run/mt/mt.pidファイルがない場合は作成し、仮のプロセスID(ここでは「11111」を設定
if [ ! -f /var/run/mt/mt.pid ]; then
    echo "11111" > /var/run/mt/mt.pid
fi

# ディレクトリの所有者をapacheユーザーに変更
# $HTTPDUSERが別の場合は、必要に応じて変更
chown -R apache:apache /var/run/mt
```

作成後、スクリプトに実行権限を付与。
```shell
sudo chmod +x /usr/local/bin/setup_mt.sh
```

次にSystemdユニットファイルを作成。
ここでは`/etc/systemd/system/setup_mt.service`という名前で作成。
Systemdユニットファイルを作成することで、上記スクリプトを`sshd`や`httpd`のようにシステム化、自動起動の設定を行うことができる。
```
# サービスの説明
# ここでは「MTディレクトリとPIDファイルの設定」と記載
[Unit]
Description=Setup MT Directory and PID File

[Service]
# サービスの種類を指定
# 「ExecStart」で指定したコマンドを実行して、それが完了したタイミングで起動完了（かつサービス終了）と判断
Type=oneshot
# サービスを開始するために実行されるコマンドを指定
ExecStart=/usr/local/bin/setup_mt.sh
# コマンドが終了した後もサービスをアクティブなままにすることを指定
RemainAfterExit=true

[Install]
# システムが複数ユーザーでの利用を許可する標準のマルチユーザーモードであることを指定
WantedBy=multi-user.target
```

Systemdユニットファイルを作成後、Systemdサービスを有効化して、次回起動時に自動で実行されるようにする。
```shell:サービスを有効化
sudo systemctl enable setup_mt.service
```

```shell:サービスを起動
sudo systemctl start setup_mt.service
```

最後にSystemdサービスが正しく動作するかを確認する。
```shell
sudo systemctl status setup_mt.service
```

```shell:実行結果の例
[opc@mt-server ~]$ sudo systemctl status setup_mt.service
● setup_mt.service - Setup MT Directory and PID File
     Loaded: loaded (/etc/systemd/system/setup_mt.service; enabled; preset: disabled)
     Active: active (exited) since Thu 2024-08-01 13:59:22 JST; 1h 47min ago
    Process: 1554 ExecStart=/usr/local/bin/setup_mt.sh (code=exited, status=0/SUCCESS)
   Main PID: 1554 (code=exited, status=0/SUCCESS)
        CPU: 4ms

 8月 01 13:59:22 mt-cloudii8 systemd[1]: Starting Setup MT Directory and PID File...
 8月 01 13:59:22 mt-cloudii8 systemd[1]: Finished Setup MT Directory and PID File.
 ```

 以上で、システム起動時にスクリプトが自動的に実行されるようになる。
 Systemdサービスとして設定することで、スクリプトの実行順序や依存関係を管理しやすくなり、サービスの再起動も簡単に行うことができる。
SharePoint リストでデータ登録時に自動採番する


# はじめに

SharePoint リストでは、元々、以下のように、ID という内部の列を持っており、サービスとして、ID 列に重複しない番号を付与してくれます。この ID 列によって、行を特定することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/507d4912-071e-d34f-583a-c6378a005b84.png)

ただし、この番号ではなく、例えば、「XXX-0001」といった感じにしたい場合もあると思います。残念ながら標準ではこのような機能はありませんが、ID 列を利用してそのような番号を発行する方法を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/dbf17a3b-d460-1a38-2b95-dc21cd116e48.png)

# 実装方法

非常にシンプルです。Power Automate で列が作成された際に、以下のような式を使って列を更新するだけです。
formatNumber関数 を使用することで桁数を指定して数値をフォーマットすることができるため、こちらの例では 4 桁にして、固定文字とつなげています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/1c2fd7a5-8266-33e6-d213-0e450eb57d6f.png)

```
formatNumber(triggerOutputs()?['body/ID'],'0000')
```

# まとめ

SharePoint リストでデータ登録時に自動採番する方法を紹介しました。個人的には、出来るだけ ID 列をそのまま使う方がいいと思いますが、このような方法もあるため参考までに紹介しました。

なお、Microsoft Dataverse の場合、元々オートナンバーという種類の列があるため、そちらを利用するだけでよいです。
Airtableのformulaで月の最終日（eomonth）を計算する

# はじめに
ExcelやGoogle Sheetsにあるeomonth関数がAirtableにはない。
したがって、関数の組み合わせにより実装する必要がある。

# 具体的な書き方
例えば、翌月末日の計算はこのように実装できる

```
DATEADD(
    DATETIME_PARSE(
        MONTH(DATEADD({日付フィールド}, 2, 'month')) & 
        "/" & 1 & "/" & 
        YEAR(DATEADD({日付フィールド}, 2, 'month'))
    ), 
  -1, 'day'
)
```
# 注意点
タイムゾーン設定を参照元・参照先のフィールドで整合させる必要がある
mapメソッドを活用した繰り返し処理の効率化：具体的な事例と解説

### `map`メソッドとは？
`map`メソッドは、JavaScriptで配列の各要素に対して同じ処理を行い、その結果を新しい配列として返すメソッドです。元の配列は変更されず、新しい配列が生成されます。

### 具体的な事例

#### 1. 配列の各要素に1を足す
```javascript
const numbers = [1, 2, 3, 4, 5];
const numbersPlusOne = numbers.map(number => number + 1);
console.log(numbersPlusOne); // [2, 3, 4, 5, 6]
```
`map`メソッドを使用することで、元の配列の各要素に1を足し、新しい配列を簡単に作成できます。

#### 2. オブジェクトの配列から特定のプロパティを取り出す
```javascript
const users = [
  { name: 'Taro', age: 25 },
  { name: 'Jiro', age: 30 },
  { name: 'Saburo', age: 35 }
];
const names = users.map(user => user.name);
console.log(names); // ['Taro', 'Jiro', 'Saburo']
```
オブジェクトの配列から、特定のプロパティ（ここでは`name`）を抽出し、新しい配列を作成します。

#### 3. 配列の要素を文字列に変換する
```javascript
const numbers = [1, 2, 3];
const strings = numbers.map(number => number.toString());
console.log(strings); // ['1', '2', '3']
```
数値の配列を文字列の配列に変換する例です。

#### 4. 複数のオブジェクトのプロパティを計算する
```javascript
const products = [
  { price: 100, tax: 0.1 },
  { price: 200, tax: 0.15 },
  { price: 300, tax: 0.2 }
];
const finalPrices = products.map(product => product.price * (1 + product.tax));
console.log(finalPrices); // [110, 230, 360]
```
各商品の価格と税率を使って、最終価格を計算する例です。

### `map`メソッドのメリット

1. **簡潔なコード**: `for`ループなどよりも、少ないコードで繰り返し処理を実装できます。
2. **読みやすさ**: 処理内容が一目で分かりやすく、コードの可読性が高まります。
3. **新しい配列の生成**: 元の配列を変更せずに、新しい配列を作成するため、副作用を減らすことができます。


### まとめ
`map`メソッドは、配列の各要素に対して処理を行う際に非常に便利なメソッドです。`for`文に比べてコードが簡潔になり、読みやすさも向上します。JavaScriptの配列を扱う際には、ぜひ活用してみてください。
luatos ESP32 の 環境構築

# luatos ESP32について
LuatOSは、ESP32-C3を使用したコア開発ボードで使用できるOSです。詳細な使用方法やチュートリアルは、LuatOSの公式ウィキ3で提供されています。
https://wiki.luatos.org/chips/esp32c3/board.html
この記事ではarduino IDEとPlatformIOでESP32-C3を開発する環境を構築します。
## Arduino IDE
Arduino IDEに独自のボードライブラリを追加するため、設定を行います。
File -> Preferences
Additional boards manager URLsのテキストボックスにhttps://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
と入力し決定してください。
次にBoards ManagerにESP32と入力しesp32をinstallしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3195955/d7647849-c752-51e3-4907-9bb6b62ced72.png)

Tools -> Boards
ESP32C3 Dev Moduleを選択
Tools
USB CDC on Bootを選択 Enableに変更
Flash ModeをDIOに変更
これで設定は終わりです。
テスト用コードを添付します
```C++
#include <Arduino.h>

#define LED_PIN 12

void setup() {
  // LEDピンの設定
  pinMode(LED_PIN, OUTPUT);
  
  // シリアルモニタの初期化
  Serial.begin(115200);
  Serial.println("Starting LED blink test...");
}

void loop() {
  // LEDを点灯
  digitalWrite(LED_PIN, HIGH);
  Serial.println("LED ON");
  delay(1000); // 1秒間点灯
  
  // LEDを消灯
  digitalWrite(LED_PIN, LOW);
  Serial.println("LED OFF");
  delay(1000); // 1秒間消灯
}

```
## PlatformIO
プラットフォームIOをインストールし、以下の画面に移動してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3195955/9d681d2d-28aa-6fb1-be72-7a28ef600ccc.png)
New Projectを選択し以下のように選択してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3195955/b4cf1fe9-2bbb-0538-928d-b1cc0f2b16af.png)
構築したプロジェクトのplatformio.iniに
[env:esp32-c3-devkitm-1]

platform = espressif32

board_build.flash_mode = dio

board = esp32-c3-devkitm-1

framework = arduino

monitor_speed = 115200 
を追加し保存してください

これで設定は終わりです。
# さいごに
参考にしたサイトです

https://blog.csdn.net/a1415539404a/article/details/124534428

https://www.codetd.com/article/14315849

公式サイト↓

https://wiki.luatos.org/chips/esp32c3/board.html#external-spi-flash-control

私が購入したESP32 C3です

https://www.temu.com/jp/esp32-development-board-type-c-with-wifi-wireless-compatible-ble-support-esp32-c3-microcontrollers-with-up-to-160mhz-clock-speed-4mb-flash-384kb-rom-400kb-sram-compatible-with-arduino-ide-g-601099539616554.html?_oak_mp_inf=EKqmoqSm1ogBGiA1NzUwYTgxZGZmNWQ0MzlkYjJkZjAwYzQyM2IxZGQ1MSCG%2F5blkDI%3D&top_gallery_url=https%3A%2F%2Fimg.kwcdn.com%2Fproduct%2FFancyalgo%2FVirtualModelMatting%2Fe0dc0ba5e2a6ba7b16d318b038674cbe.jpg&spec_gallery_id=2076331830&refer_page_sn=10009&refer_source=0&freesia_scene=2&_oak_freesia_scene=2&_oak_rec_ext_1=NTc2&_oak_gallery_order=2046677514%2C2074396925%2C2052689631%2C1710218338%2C101557816&search_key=ESP32%20C3&refer_page_el_sn=200049&_x_ns_irclickid=38EWXCxsTxyKTnpV1txUxUX4UkC26MxEX0NfW00&_x_ads_account=18350&_x_ads_id=1580294&_x_ns_iradname=Online%20Tracking%20Link&_x_ns_iradsize=&_x_ns_prodsku=&_x_ns_irmptype=mediapartner&_x_ns_sharedid=MSN%20Temu%20Japan_3350025&_x_ns_ts=1722407702404&_x_ns_randint=3168116&_x_ns_adtype=ONLINE_TRACKING_LINK&_x_ns_irmpgroupname=%22ag%22&_x_ads_channel=impact&_x_ns_mp_value2=&_x_ns_mp_value3=&_x_ns_irmpname=Tradedoubler.&_x_ns_irpid=2216680&_x_vst_scene=adg&_x_sessn_id=bfy6awhyzf&refer_page_name=search_result&refer_page_id=10009_1722494074964_gg6hjr0rq1

中国系のサイトに飛びます。
R3liveの実行手順③(実行編)

### 実行前にR3liveのgithub、もしくはR3liveの実行手順①を参照して準備を完了する。

https://github.com/hku-mars/r3live

## サンプルの実行
### 試しにサンプルを実行してみましょう
サンプルはここから入手

https://github.com/ziv-lin/r3live_dataset

フォルダーに入れて実行

```
source ~/catkin_ws/devel/setup.bash
roslaunch r3live r3live_bag.launch
# Ctrl+zで停止
rosbag play YOUR_DOWNLOADED.bag
```
YOUR_DOWNLADED.bagは
homeディレクトリのusernameディレクトリにdegenerate_seq_00.bagファイルをダウンロードした場合
```
home/username/degenerate_seq_00.bag
```
と表記する

コントロールパネルをクリックしキーボードでｓを押すと、PCDファイルが記録される。
![Screenshot from 2024-07-30 16-28-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847047/906d7619-def7-15f8-e3be-0a738c066cf5.png)
生成されたPCDファイルはデフォルトでは r3live_output フォルダに格納される。


## 自身で記録したファイルで実行する方法
まずは2センサー間(LiDAR-カメラ）のキャリブレーションを行う。
下を参照

livox_ros_driverとカメラのrosdriverをそれぞれのターミナルで起動して、rosbag recordコマンドで記録する。

```ruby:terminal1
source ~/ws_livox/devel/setup.bash
roslaunch livox_ros_driver livox_lidar_msg.launch
```

```ruby:terminal2
source ~/catkin_ws/devel/setup.bash
roslaunch spinnaker_camera_driver camera.launch
```

```ruby:terminal3
#動いているrosノードを確認
rostopic list
#確認したら、カメラとLiDAR、IMUセンサーに対応するトピックを記録する。
rosbag record /livox/lidar /livox/imu /camera/image_color/compressed
#データの収録が完了したら、記録を停止する
Ctrl+C
#ターミナルを閉じる
Ctrl+D![Screenshot from 2024-07-30 16-28-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847047/b691fadf-2fd8-4fdb-0add-c877f0625136.png)

```

記録が完了したらサンプル再生のときと同様に再生、マップ作成を行う。
R3liveの実行①(インストール編）


# LiDARとは

LiDAR(Light Detection and Ranging)は本体から発射されたレーザーパルスが物体にあたって反射してくるまでの時間を計算して距離を求める技術である。ToF(タイムオブフライト)方式と言われる。 

このレーザを四方八方発射することで3Dの点群を生成することができる。 

Livox社から発売されているLiDARなど技術進歩によって低価格のものが多く発売されており気軽に使用することができる。 

LiDARでは3Dの点群の他に反射したレーザーの強さがどれくらいになって返ってくるかの情報が記録される。Livox社のLiDARでは反射強度と呼ばれる値である。 

R3liveでは、カメラを搭載することで、カメラの色情報を同時に付与することができる。

# R3liveとは

R3liveとは香港大学(HKU)によって開発された技術で、

・LiDAR-慣性オドメトリ(LIO）と
・Visual-慣性オドメトリ(VIO)を組み合わせたもので、

LIOによって生成された点群データに対してVIOを適用することで点群に色をつけることができる。

# R3liveの実行手順

### 実行環境

・Ubuntu 20.04 LTS 

 ・ROS Noetic 

 ・Livox Avia 
 
 ・FLIR Blackfly S USB3

## ROSのインストール
 以下のサイトを参考にしてROSをインストールする。

 [ubuntu20.04LTSにROS Noeticをインストールする](https://qiita.com/porizou1/items/7c2c4b33126cfad05944)
 
## Livox-SDK2のインストール
[ここからインストールする](https://github.com/Livox-SDK/Livox-SDK2)

Livox-SDKでも動作するが、SDK2での動作が推奨されている。
## ROSの追加パッケージをインストールする 
```
sudo apt-get install ros-noetic-cv-bridge ros-noetic-tf ros-noetic-message-filters ros-noetic-image-transport ros-noetic-image-transport* 

```

## Livox_ros_driverのビルド
```
git clone https://github.com/Livox-SDK/livox_ros_driver.git ws_livox/src 
cd ws_livox 
catkin_make 
source ./devel/setup.sh 
```

R3live実行中にエラーが発生した場合はcatkin_ws内でもビルドしておく
```
cd catkin_ws_src
git clone https://github.com/Livox-SDK/livox_ros_driver.git
cd catkin_ws
catkin_make 
source ./devel/setup.sh 
```
## CGAL and pcl_viewer (optional)
```
sudo apt-get install libcgal-dev pcl-tools
```

## PCLのバージョン確認
以下のコマンドでPCLのバージョンを確認する
```
pkg-config --modversion opencv
```
R3liveの作成もとは3.3.1, 3.4.16, 4.2.1 , 4.5.3.での動作を確認している。

## Open CVのインストール(必要な場合)
以下のリンク等を参考にする

https://qiita.com/2yuu/items/e151beb455769c264443

https://ja.linux-console.net/?p=30012#google_vignette

## R3liveのビルド
以下のコマンドを実行する

```
cd ~/catkin_ws/src
git clone https://github.com/hku-mars/r3live.git
cd ../
catkin_make
source ~/catkin_ws/devel/setup.bash
```

以上でインストールは完了です。

本稿では以下のサイトを参照して作成した。

https://github.com/hku-mars/r3live