OmniAICreator/Qiita-1.07M huggingface dataset:
自己紹介がてら「自分を紹介するホームページでも作ってみない？」3日目

# 初手からソースコード
```html:index.html
<html>
    <head>
        <meta charset="utf-8">
        <title>NattyanTV</title>
        <script>
            window.addEventListener("load", (() => {
                const userNameElement = document.querySelector(".user-name");
                if (userNameElement !== null) {
                    userNameElement.innerHTML = "NattyanTV"
                }
                setInterval((() => {
                    document.getElementById("deeply-world").insertAdjacentHTML("beforeend", "!");
                }), 1000);
            }));
        </script>
    </head>
    <body>
        <h1 class="user-name">Loading...</h1>
        <div id="deeply-world">Welcome to 深淵!</div>
        <style>
            body {
                background: #d3d9db;
            }

            .user-name {
                max-width: 80%;
                width: 50rem;
                margin: 0 auto;
                font-family: serif;
            }

            #deeply-world {
                max-width: 80%;
                width: 50rem;
                margin: 0 auto;
                font-family: sans-serif;
            }
        </style>
    </body>
</html>
```
※これは1日目の最後に適当に載せたコードです。

# 今日は何〜
実際にコードを解説しながら、HTMLの簡単な構造について理解してみましょう。

# 前提知識
`<html></html>`については前回の記事をご覧くださいませ。

# `head`部
## `meta`

```html
<meta charset="utf-8">
```

これは前回記述したとおりでしょうか、文字コードを`UTF-8`に設定するってだけです。

## `title`

```html
<title>NattyanTV</title>
```

こちらも前回記載させていただいた、ページのタイトル設定です。
このページにおけるタイトルを設定します。

## `script`

```html
<script>
    window.addEventListener("load", (() => {
        const userNameElement = document.querySelector(".user-name");
        if (userNameElement !== null) {
            userNameElement.innerHTML = "NattyanTV"
        }
        setInterval((() => {
            document.getElementById("deeply-world").insertAdjacentHTML("beforeend", "!");
        }), 1000);
    }));
</script>
```

でましたわね！ JavaScriptです！
説明については、次回の記事に回したいと思います。

# `body`部

## `h1`

```html
<h1 class="user-name">Loading...</h1>
```

こちらは見出しですね。
一番大きいサイズの見出しで「Loading...」って表示しています。
`class="user-name"`っていうのがあると思いますが、これは「属性」と言います。
`<h1 属性名="要素">`みたいな感じで書くことができる、そのタグに対する追加情報みたいなものです。
そうですね、`meta`の時にあったものに似てますね。
今回の`h1`は、`class`を`user-name`にしていますね。

`class`という属性はその名の通り「クラス」属性を設定します。
クラスというのは後で使用しますので覚えておきましょう。


## `div`

```html
<div id="deeply-world">Welcome to 深淵!</div>
```

これは`div`要素で、段落を追加します。
今回の`div`は、`id`を`deeply-world`にして、「Welcome to 深淵!」と表示しています。

`id`属性はその名の通り「ID」属性を設定します。
こちらも後で使用しますので覚えておきましょう。

## `style`

```html
<style>
    body {
        background: #d3d9db;
    }

    .user-name {
        max-width: 80%;
        width: 50rem;
        margin: 0 auto;
        font-family: serif;
    }

    #deeply-world {
        max-width: 80%;
        width: 50rem;
        margin: 0 auto;
        font-family: sans-serif;
    }
</style>
```

ﾃﾞﾏｽﾀ-!
CSSです。ちなみにCSSは「カスケードスタイルシート」の略です。
CSSについても次回の記事で解説します。

# まとめ

今回はHTMLについて簡単に説明させていただきました。
では次はJavaScript、CSSについて触れていきます。
もうすぐ終わりますよ！
セキュリティ・ジュニアキャンプ2023に参加した話②

実際に参加した雰囲気を書きます。5日分
# 0日目 前泊民
前泊していたので前の日から泊っていました。会場内を回ったり、夕食を食べたりしていました。あとは部屋で技術系の本を読んだり、開発のアイデアを考えたりです。
(入口)
![IMG_3221.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3353450/6cb1fb65-696a-5b06-a2be-e13a38628033.jpeg)

# 1日目 はじまり 
昼から講義が始まるので次の日に備えてたくさんねました。参加者が集まると開会式があり、倫理系の講義を受けました。
(部屋)
![IMG_3224.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3353450/e053be05-f61a-5ee9-cc17-ba822706d5bd.jpeg)

# 2日目 講義
講義を受けます。実践的な内容を学べます。いままで独学で適当に学んできてたんですがしっかり教えてもらえるとすごくよかったです。触れたことのない分野のものも教えてもらえるのでその後の学習や開発にすごく役立ちます。あとは夜に協賛企業の紹介イベントがありました。企業の方と話せるチャンス!!
# 3日目 講義&開発
IPAに行っていろいろ見ます。自分の知らなかった世界を見ることができた気がしました。今後の開発に役立てていきたいと思いました。
(ごはん)
![IMG_3240.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3353450/2a82e352-639b-2b54-e22f-7183f926df81.jpeg)

# 4日目 開発
最終日のためにごりごりに開発します。開発しまくりました。ほかの参加者も開発しているのでモチベは保たれます。楽しいです。
# 5日目 発表
朝はプレゼン発表に追われてほかのことは考えられませんが、発表が終わるとあ～セキュキャン終わるなーってなります。各参加者(ジュニアと開発コース)すごいものをつくっていました。すげぇ。とか思っていたらあっという間に終わりました。
(最寄りの駅の写真)
![IMG_3293.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3353450/cc4b0447-00ac-6675-a61b-6b58048e4e0c.jpeg)

# 感想まとめ
応募前や0日目はかなり不安がありましたが実際に始まってみるとあっという間に終わってしまいます。めちゃくちゃ楽しいです。とくにジュニアの年齢で参加できたのが今後のつながりにも良い影響がありそうでよかったです。
Teachable MachineとNode-REDを使って体温チェック判定できるLINEBotを作ってみる。

おつかれさまです。
金融業界で長年働いている事務員兼主婦です。
前回はLINE Botでアルコールチェック判定にチャレンジしてみました。


https://x.com/kiku_2005/status/1729103416318951516?s=20





# Let'sチャレンジ！LINE Botで体温チェック判定
コロナやインフルエンザなどで自宅待機を余儀なくされる場合、職場への体調報告が必要になったりしますよね。今回はTeachableMachineとNode-REDを使用して体温チェック判定ができるLINE Botにもチャレンジしてみました。

# 完成品

https://x.com/kiku_2005/status/1729091764869566855?s=20



# 使用ツール
・Teachable Machine
　https://teachablemachine.withgoogle.com/
・Node-RED
　https://nodered.org/
・LINE Bot
　https://developers.line.biz/
・[LINE Developers](https://developers.line.biz/ja/ "LINE Developers")　


# 製作開始
## １. Teachable Machineによる画像判定

詳しい使い方は下記の記事を参考にしました。

https://qiita.com/misa_m/items/d8a20d153c8ee7daf0c1

今回は画像パターンを使い、class名は３種類「平熱ＯＫ 出社可能」「微熱要確認 自宅待機」「高熱ＮＧ 病院で検査」にしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/579b8e9d-4b20-bb0e-3d71-f1ff10dc6d8b.png)



## ２. Node-REDを作成

**全体のフローはこちらです。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/5c54b274-4049-30e9-825e-21c7bd335d2d.png)

 
<details><summary><b>各ノードの設定を表示（折りたたみ）</b></summary><div>

**①webhook**
Pathは`/webhook`にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/abd77e9f-d036-eae5-7fff-b05aed8f577d.png)


**②http request**
URLは下記を入力します。

    https://api-data.line.me/v2/bot/message/{{{line.event.message.id}}}/content

`認証を使用`にチェックを入れ、種別は`Bearer認証`を選択します。トークーンにはLine-DevelopersのMessaging API設定から、チャンネルアクセストークンをコピーして貼り付けます。
最後に出力形式はバイナリバッファを選択してLINE画像の送付準備は完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/e2ecd2d2-46c5-ec23-8e81-c89f50f56b62.png)


**③image**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/9446fd81-568e-afb2-4714-01324e957485.png)


**④TeachableMachine**
Urlには自分がアップロードしたTeachable MachineのデータセットのURLを入れてください。その他の項目は、下記画像の通り設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/46ca1b7f-e0bf-4a3e-49f9-1ad210fa76ae.png)


**⑤temple**
テンプレートに`{{payload.0.class}}`を貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/8c8206e5-d849-54df-486b-2a58137db1b1.png)

**⑥Reaply**
SecretはLINEのチャネルシークレットを貼り付け、
Access TokenはLINEのチャネルアクセストークンを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/24d63030-f723-9b03-9d63-b769dfb71db2.png)


</div></details>

最後に右上のデプロイボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570716/616df516-2e2d-2206-32db-5d8ca2239a64.png)

## ３. LINEの設定
LINE Messaging APIのwebhook設定時、Node-REDのURLはcloudの後ろに`/webhook`を付ける必要があります。
例：https://team-ユーザー名-75c●●●●●.flowfuse.cloud<font color="Red">/webhook


以上で設定完了です。



# 感想
ここまで到達する間にNode-REDのサーバーと接続できないエラーが何度も頻発しました。田舎なので通信状態が悪いのでしょうか:sweat_smile:今回完成出来たポイントはおそらくTeachableMachineへの機械学習（画像＆色別）で画像をたくさん撮る事でした。幸いにもコロナの予防接種を受けた後だったのでテストがたくさんできました。これからも、もっと様々な形で応用していけるようにチャレンジしていきたいと思います。

# 参考資料

https://qiita.com/h21550/items/3674caeb7531183021be

https://qiita.com/am003004/items/b297a9616a0f820458eb

https://atlabo-handson-08.netlify.app/


ここまでお付き合い頂きありがとうございました。
セキュリティ・ジュニアキャンプ2023に参加した話①

# セキュリティ・（ジュニア）キャンプはいいぞ!!
2023年度のセキュリティキャンプ（以下 seccamp）について書きます!!
## セキュリティ・キャンプとは
セキュリティ・キャンプ全国大会は、情報セキュリティに関する高度な技術教育と倫理教育を、審査に通過した22歳以下の学生・生徒に対して実施するもので、セキュリティ・キャンプ事業の中心的な行事です。4泊5日の合宿形式で行うことから「キャンプ」と称しています。
[IPA公式より](https://www.ipa.go.jp/jinzai/security-camp/about.html)
全国、ジュニア、ネクストがあり、100名以上が同じ空間で5日間過ごします。かなり成長できる貴重な機会です。あとは交通費、前後泊費を運営が負担してくれるのがありがたいです。

![xwavefuchu](https://negishi-tako.com/wp-content/uploads/2023/09/IMG_3228-scaled-1.jpg)

## 選考課題
4月くらいになると選考課題がIPAのサイトにアップされます。
2023年度は加点主義だったのでめちゃくちゃ書いた気がします。調べたこと、知ってたことを全部書いたイメージでした。出てきたテーマにリンクする情報まで書いていたかもしれません。開発実績についても今まで作ったものを思い出してめちゃくちゃ書いた覚えがあります。これらだけで選考されるのでこれに全力を注ぎました。
## 事前学習
参加決定後はDiscordとかに招待されてほかの参加生とかとコミュニケーションをとれます。いろいろな参加生と話そうと思えば話せるので専門じゃない分野の情報も得られます。ほかの授業のチャネルにも入っているのでそこを見ると新しいことが見つかったりします。
また、事前課題があります。ただそこまでの量ではありません。特にジュニアは小中学生onlyなので学校生活に影響が出ないようにということで少なめなよう。プログラムを書くものもあれば考える系のものもある感じです。
## 参加のメリット
もちろん、当日の講義が受けられるのがまず大きなメリットです。実際に業界で働いているエンジニアのみなさんから幅広い内容を教えてもらうことができます。
詳しくは↓
[IPA公式 ジュニア講義2023](https://www.ipa.go.jp/jinzai/security-camp/2023/junior/program_list.html)
もっと大きいのがその後のつながりをつくれること。ジュニアに限らず、セキュキャンコミュニティ的なものはかなり大きく、自分の地区でも知り合いができたりします。
あとは夏休みに無料で東京に行けます。地方民にとっては最高です。
UnityでScrollViewをもっと便利に使う方法

## はじめに

初めてQiitaで記事を書くので、つたない部分あるかもしれませんが温かく見守っていただけると幸いです。基本的には普段の開発のアウトプットと備忘録を兼ねています。

## ターゲット

Unityの使い方は概ね分かっていて、ScrollViewを使ってみたことのある人を想定しています。

## 結果

こんな感じのができました
![Qiita1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/048af165-d4b6-072e-52b7-3196d653bc5c.gif)


UnityのScrollViewを解説する記事が他のUI（ButtonやImage）に比べてあまりに少なかったので、まずはScrollViewの簡単な使い方からやっていきます。

## ScrollViewの出し方
この辺はまだ探せば記事が出るので手短に、
![スクリーンショット 2023-11-27 194310.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/4e2aaac5-4a39-3b68-5e00-2a3cbe67108c.png)

ScrollViewを出したいCanvas上で右クリック　→　UI　→　ScrollView　でScrollViewがGameに出る

ScrollViewの構成はこんな感じ
![スクリーンショット 2023-11-27 194651.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/44f70f91-7561-5882-23e8-fedac7112b57.png)

大事なのはViewPart>Contentのところ、極論スマホゲームなら
Scrollbar Horizontal
Scrollbar Vertical
はあんま使わないから消しちゃっていい




![スクリーンショット 2023-11-27 195038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/1c57ca9c-6c7b-409e-e8e3-964926798225.png)

詳しいコンポーネントの解説は伏せるが、Contentに
ContentSizeFilterコンポーネント
（縦のScrollViewなら）VerticalLayoutGroupコンポーネント
（横のScrollViewならHorizotalLayoutGroup、格子状ならGridLayoutGroup）

を付ければ、超簡単にScrollViewを作れる

## これの問題点

![Qiita1_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/d4cb2b0e-85c3-a0b0-3b03-a8684f7b46a0.gif)

ただこのままだと縦のScrollViewは出来るけど、
ScrollViewの一要素として横にボタンを配置することができない。
そんな壁にぶち当たった人向けの記事です。

## 解決法

結論から言えば、横に配置したいボタンを空のオブジェクトに入れる。![スクリーンショット 2023-11-27 201212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/066acbb3-027b-8ddb-ecb2-9dfa60708851.png)

今回はContentに3つの要素を入れた。
1.　上の白いImage
2.　空のObject（Buttons）（Heightは400（自由に変えられる））
　　＞Button
　　＞Button(1)
3.　下の白いImage


![スクリーンショット 2023-11-27 201242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535484/8e8b5439-fa9a-f909-9d4e-72b252d5f87d.png)

こんな感じになる。

そのまま入れると2つのButtonが縦に並んでしまうが、
空のObjectを経由することで子どものButtonのtransformを好きにいじれるので、
x座標をいじれば、好きに配置できます。


最後まで読んでいただきありがとうございます。
わかりづらい箇所などあればご指摘いただけますと幸いです。
【ml5.js】「この問題わかる人～？」～在りし日の思い出～

# いつのことだか 思いだしてごらん
先生の「この問題わかる人～？」は、誰しも聞き覚えがあるのではないだろうか。
もう戻れない学生時代を懐かしく思う。

ちょっとアプリで再現してみますか。
**名付けて、『「この問題わかる人～？」～在りし日の思い出～』**

（ネーミングセンスはどこかに落としてきました。）

# どんなのつくろう
:::note info
【目標】
　■ 挙手を先生に気づいてもらい指してほしい（ml5.js：Handpose）。
　■ 発話にて回答したい（Web Speech API）。
:::

# 技術・環境
ml5.js：Handpose（JavaScriptライブラリ）
Vue.js（JavaScriptライブラリ）
Web Speech API（発話の聞き取り）
Bootstrap（Web制作サポートツール）
CodePen（アプリ制作環境）
Netlify（完成アプリ公開環境）

# 授業はじめるぞ～
## Netlify
**使い方はアプリ内に記載していますので、さっそく遊んでみてください！**
（誤判定の確率を下げるため、カメラから50cm以上離れてください。）

https://65631ac209319d559640ab7f--helpful-maamoul-ce6eac.netlify.app/

##  中身はこちら
### CodePen
**第1画面**
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="PoVaVGE" data-user="XE-AY" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/XE-AY/pen/PoVaVGE">
  【HW】この問題わかる人～？</a> by XE-AY (<a href="https://codepen.io/XE-AY">@XE-AY</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

**第2画面**
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="OJdEdgv" data-user="XE-AY" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/XE-AY/pen/OJdEdgv">
  【HW】この問題わかる人～？（呼ばれ先）</a> by XE-AY (<a href="https://codepen.io/XE-AY">@XE-AY</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 機械学習、奥深し
毎度のことながら初体験の技術だったので、実装はそこそこ苦労した。
今回の課題としては以下。
* 問題＆回答をランダム表示にしたい（もっとバリエーションが欲しい）。
* 手の認識精度が低く、顔を手だと誤判定されるので改善要（私の顔が手に似ている？）。

でもまあ、そわそわ手を挙げ、ドキドキ答えたあの頃の気持ちを、思い出すことができた。

**あれ…今も職場で同じ思いをしているような…？**
CLIコマンド1発でBigQueryデータセットの権限を付与/削除する方法

Google Cloudに関するアクセス権の多くは `gcloud project add-policy-binding` コマンドなどを使うことで、コマンド1発で付与/削除できます。

しかし、BigQueryデータセットへの権限付与をコマンドラインからやろうとすると、以下のドキュメントにかかれているように複数コマンドが必要になってしまい煩雑です。

https://cloud.google.com/bigquery/docs/control-access-to-resources-iam#bq_2

また、JSONファイルをダンプした後に修正して反映という流れを取っているので、ダンプ後に他の箇所から権限の変更が行われた場合は、それを上書きしてしまうという欠点もあります。
そのため、 `add-policy-binding` などと同様にコマンド1発で権限の付与/削除を行う方法があると便利です。

このようなbqコマンドを使うとコマンド1発で権限の付与/削除ができます。
GRANT文やREVOKE文では1発で処理を行えるため、それをbq query経由で呼び出しています。

```sh
bq query --use_legacy_sql=false \
  'GRANT <ロール名> ON SCHEMA `プロジェクト名.データセット名` TO "user:メールアドレス"'

bq query --use_legacy_sql=false \
  'REVOKE <ロール名> ON SCHEMA `プロジェクト名.データセット名` FROM "user:メールアドレス"'
```
【Rails】modelでメソッドにselfをつける時とつけないときの違い

どうもこんにちは。

今回はRailsでモデルファイルで定義したメソッドに`self`をつける時とつけない時の違いについて説明します。（おまけでバリデーションメソッドについても説明しています。）

# モデルにメソッドを定義する理由

## 1. 全体で利用可能

モデルに定義したメソッドはアプリケーション全体で利用可能となるメソッドです。そのため、コントローラやビュー、他のモデルの中でも使用することができます。

## 2. 処理の共通化

アプリケーション内で何度も同じ処理をする必要がある場合があります。その時に**同じ処理の共通化**を目的としてモデルにメソッドに定義し、同じ処理をしたい箇所でメソッドを呼び出すことでコードが簡略化できます。

## 3. バリデーションを定義

本来は、`validates`メソッドを使用してカラムに対して「空白禁止」や「文字数制限」を定義します。大体のバリデーションは1行で完結できます。しかし、二つのカラムにデータが入っていない場合のバリデーションを定義するときには、俗にいう「バリデーションメソッド」を定義します。

# selfを付けない場合

`self`を付けないメソッドは**インスタンスメソッド**というものです。

まず、Userテーブルに以下のデータが登録されているとします。

| カラム名 | 型 | 値 |
| --- | --- | --- |
| id | integer | 1 |
| first_name | string | 試験 |
| last_name | string | 太郎 |

以下のようなメソッドを定義していたとします。

```ruby
class User < ApplicationRecord
  def full_name
    "#{first_name} #{last_name}"
  end
end
```

メソッドを使用する時には、インスタンスに対して使用します。

```ruby
# インスタンス生成
user = User.find(1)
# インスタンスに対してメソッドを呼び出す
puts user.full_name
```

バリデーションメソッドはインスタンスに対してバリデーションをかけるので`self`をつけずにメソッドを定義します。

# selfをつける場合

`self`を付けるメソッドは**クラスメソッド**というものです。

クラスメソッドは、データの登録を行う場合や複雑な条件を指定してデータを取得する場合に使用します。

```ruby
class User < ApplicationRecord
  def self.user_create
    User.create(first_name: "試験", last_name: "次郎")
  end
end
```

メソッドを使用する時には、クラスに対して使用します。

```ruby
# モデルに対してメソッドを呼び出す
User.user_create
```

# バリデーションとして定義する場合

単純なバリデーションであれば、以下のようにしてバリデーションを設定することができます。

```ruby
# 空白禁止
validates :name, presence: true
# 最大文字数制限
validates :note, length: { maximum: 1000 }
```

しかし、「名前かあだ名のどちらか一方は入力されるようにする」というバリデーションを定義するとします。

まずは、以下のようにバリデーションを定義します。

```ruby
validate :name_or_nickname
```

これで`name_or_nickname`というメソッドを使用してバリデーションを定義できるようになります。

次にメソッドを定義します。

```ruby
def name_or_nickname
    # どちらかが入力されていればOK
    return if name.present? || nickname.present?

    errors.add(:name, :blank) if name.blank?
    errors.add(:nickname, :blank) if nickname.blank?
end
```

以上のようにメソッドを定義することで複雑なバリデーションを設定することができます。

# まとめ

最初の方はコントローラにメソッドを定義するだけで乗り切れますが、複雑なアプリケーションになるにつれて、コントローラだけではうまくコードを書けなくなってきます。

そのため、モデルにメソッドを定義して使用できるようになると非常に便利です。

以上
システム開発における「テスト」と言う言葉の定義が分かりにくいあなたへ

新卒時代に「テスト」というものがよく分からなかった私が、
7年以上の経験を経て体系化した「テスト」という言葉の定義を共有します

<table>
<tr>
    <td>テストの段階</td>
    <td>目的</td>
    <td>実施内容</td>
    <td>重要な観点</td>
</tr>
<tr>
    <td>単体テスト</td>
    <td>
        モジュールが単一で期待通りの動作をしているかを検証する。
    </td>
    <td>
        単一の「関数」、「クラス」、「画面」が
        想定されうるInputに対して期待したOutputおよび処理や動作をしているか検証する。
        <br>*以降、「関数」「クラス」「画面」を総称してモジュールと表現させてください。
    </td>
    <td>
        <ul>
            <li>
                Inputの網羅性(例外的なInputや処理を想定できているか)
            </li>
            <li>
                ソースコードの通過性(カバレッジ)
            </li>
        </ul>
    </td>
</tr>
<tr>
    <td>結合テスト</td>
    <td>
        単体テストをクリアしたモジュール、及び異なるシステム同士が連携することによって、
        想定通りの動作をしているか/逆に想定外の動作をしていないかを検証する。
    </td>
    <td>
        依存関係がある複数の「関数」、「クラス」、「画面」、「システム」を連結した際に、
        想定されうるInputに対して期待したOutputおよび処理や動作をしているか検証する。
    </td>
    <td>
        <ul>
            <li>
                連携失敗時の想定や対応
            </li>
            <li>
                ソースコードの通過性(カバレッジ)
            </li>
        </ul>
    </td>
</tr>
<tr>
    <td>
        シナリオ(システム)テスト
    </td>
    <td>
        システムを導入し、エンドユーザーと擦り合わせた要件を実現できているか/実現できたいない箇所はないかを検証する。
    </td>
    <td>
        特定の「画面」、「機能」、「システム」を繋ぎ合わせた際に、
        想定している業務やシナリオを実施できるかを検証する。<br>
        *特に特定の業務のみを対象とするテストをシナリオテスト
        システム化対象の業務全てを対象とするものをシステムテストと呼んでいる印象。
    </td>
    <td>
        <ul>
            <li>
                業務の実施可否
            </li>
            <li>
                想定操作パターンの網羅性
            </li>
            <li>
                想定外な操作時の対応
            </li>
            <li>
                応答/遷移速度
            </li>
            <li>
                セキュリティテスト
            </li>
        </ul>
    </td>
</tr>
<tr>
    <td>受入テスト</td>
    <td>
        システムを導入することで、エンドユーザーが期待していた効果が出るかどうか検証する。
    </td>
    <td>
        システムテストのようなシステム全体のテストを「エンドユーザー」が実施するもの。
    </td>
    <td>
        <ul>
        <li>
            想定操作パターンの網羅性
        </li>
        <li>
            ユーザー操作のわかりやすさ
        </li>
        </ul>
    </td>
</tr>
</table>
classNameの定義はtailwind-variantsとtailwind-mergeで宣言的にスッキリ書ける

classNameの定義方法でこれが良さそう！というものを学びましたので参考にしていただけると幸いです！

## これまでの書き方

```javascript
import { twMerge } from 'tailwind-merge'

const baseClass = 'p-4';
const spacingClasses = spacing !== undefined && {
  ['ml-4 mr-4']: vertical,
  ['mt-4']: !vertical,
}

const hoge = ({ vertical }) => {
    return (
      <div className={twMerge(baseClass, spacingClasses)}>
        <p>hoge</p>
      </div>
    )
}
```

この書き方は論理演算子のロジックを読んだ上でどのようなスタイルが当たるのかを把握しないといけなくなってしまうコードとなります。

## tailwind-variantsを使って書いてみる

```diff_javascript
- import { twMerge } from 'tailwind-merge'
+ import { tv } from 'tailwind-variant'

- const baseClass = 'p-4';
- const spacingClasses = spacing !== undefined && {
-   ['ml-4 mr-4']: vertical,
-   ['mt-4']: !vertical,
- }

+ const customClass = tv({
+  base: 'p-4',
+  variants: {
+    vertical: {
+      true: 'ml-4 mr-4',
+      false: 'mt-4',
+    }
+  }
+ })

const hoge = ({ vertical }) => {
    return (
-     <div className={twMerge(baseClass, spacingClasses)}>
+     <div className={customClass({vertical})}>
        <p>hoge</p>
      </div>
    )
}
```

`tv({})`の中に共通で持たせたいclassを`base`として定義して、動的に付与したいclassを`variants`の中に定義します！

:::note info
`vertical`という値がbooleanの場合の記述、オブジェクトの中をtrueとfalseと定義しておきます!
:::

classNameの定義箇所で`customClass({vertical})`で呼び出して、propsを渡してあげたらあとは状態に応じてclassがレンダリングされます！

また、propsでclassNameを受け渡すようにしたい場合したい場合は`tailwind-merge`を併用します！

```diff_javascript
+ import { twMerge } from 'tailwind-merge'
import { tv } from 'tailwind-variant'

const customClass = tv({
  base: 'p-4',
  variants: {
    vertical: {
      true: 'ml-4 mr-4',
      false: 'mt-4',
    }
  }
})

const hoge = ({ vertical, classNameProps }) => {
    return (
+      <div className={twMerge(customClass({vertical}), classNameProps)}>
        <p>hoge</p>
      </div>
    )
}
```

## 【classNameの定義はtailwind-variantsとtailwind-mergeで宣言的にスッキリ書ける】まとめ

classの定義方法はさまざまな書き方があります。
`tailwind-variants`も使い方によっては冗長的な記述になってしまうケースもあるのかもしれません。

ただ、classの付与条件が多岐にわたる場合にはコードの見通しを良くするのに有効な手段だと考えますので検討してみてください！
モニターが映らない！――ケーブルを挿しなおしてみましょう――

## はじめに
PCを使っている中で外部モニターが映らないという事象に出くわした方はかなり多いのではないでしょうか。
特に何もしていないはずなのに突然映らなくなるモニターには手を焼かされる物です。
今回はそんな時に落ち着いて対応するための手順をご紹介いたします。

## まずはここからやってみよう
### モニターの電源は入ってる？
多くのモニターは電源ボタンがあります。
一度電源を落としたのち、再度電源を入れなおしてみましょう。
モニター内部で何らかの不具合がある場合も軽度なものならこれで回復することがあります。

### モニターのコンセントは刺さってる？
電話窓口でおなじみの対応ですね。
「一度コンセントを抜いてください」
この言葉に聞き覚えのある方も多いのではないでしょうか。
電源不要のモバイルディスプレイでなければ電源への接続は必須です。
もし電源タップなどで刺し口が複数あれば他へ刺し替えてみましょう。
このときにモニター本体側に刺さっている方も接続を確認しましょう。

### モニターはPCと接続されてる？
PCが接続されていなければモニターは何を映せばいいのかわかりません。
ケーブルの抜き差しが多いと接続が緩くなってしまっていることもあるかもしれません。
もし予備のケーブルがある方は刺し替えてみることもお勧めします。

<br>
ここまでで大半の不具合は解消されます。

まずは電源とケーブルの接続確認を思い出せると落ち着いて対応できるようになるかと思います。

## 少し詳しく見てみよう
もし会社にお勤めの方でPC設定に不慣れな方は、ここからは詳しい方に相談されることをお勧めします。
対応する側の者としてはここからは自分の目で確かめたい部分も多いです。

### モニターの入力信号は正しい？
PCとモニターを接続するケーブルには複数の種類があります。
これが正しく設定されているときにモニターは映ります。
モニターには電源ボタンの他にもいくつかのボタンがある型が多いです。
これを操作して入力信号を設定する画面に行きましょう。
ボタンレスでも入力信号を選択する部分はあるかと思われます。
ここで接続しているケーブルと対応する規格が選択されていることを確認しましょう。
ケーブルには規格が記されていることが多いですから確認してみましょう。

### PCはモニターを認識している？
上記の事項は正しく設定されているにも関わらずモニターが映らない場合、PC側でモニターを認識していないことがあります。
Windowsの場合は「デバイスマネージャー」を起動し、「モニター」の中に対象のモニターが表示されるか確認しましょう。
ここに表示されない場合はPC側で不具合が起きている可能性があります。
PCを再起動してみましょう。

これでも映らない場合はモニタードライバーをインストールする必要があるかもしれません。
Windows95以降は多くの機器でPnP（Plug and Play）という仕組みを採用しており、接続するだけで映像が映るようになっております。
古い機器をお使いの方はここがポイントになるかもしれません。
モニターの裏面などに記載されている型番で検索してドライバーをインストールしましょう。
その後再度接続をお試しください。

## こんなこともあるかも
### モニター本体が帯電しているかも
電源をおとしてコードやケーブルを完全に外して2分ほど待機したのち電源を入れてください。

会社問い合わせ時点では映らなかったモニターが翌日映った事例があります。
近くで落雷があったときはこれが原因の可能性が高まります。
お急ぎでなければ放電させている間に家事を済ませたり休憩をとったりしましょう。

## お手上げだ！
ここまでやって解決しないときはモニター本体もしくはPCのハード面に問題があるかもしれません。

他のモニターに接続して映るならばモニター本体の問題かもしれません。
もし接続しているのとは別のPCが手元にあれば、それを接続してみましょう。
これで正しく映るならば、PCのハード面に問題がある可能性があります。
ここまでくるとかなり詳しい方でないとすぐには解決できないかもしれません。

購入元や製造元の相談窓口を探して連絡してみましょう。

## レアな事例
私が遭遇したレアと思われる事例をいくつかご紹介いたします。

### ①2枚の外部モニターのうちType-C接続の物だけが映らない
Windows11のノートPCでHDMIとType-Cで2枚の外部モニターに出力していた事例です。

Type-C接続しているモニターのみ映像が映らず、PCもモニターを認識されませんでした。
合わせてType-Cポートでの充電ができなくなっておりました。
上記の手順で最後まで直らず、他のPCをつなぐと正しく接続されました。
PCのサポートに引き取り修理を依頼したところ、システムボードが交換されて帰ってきました。

会議などでケーブルの抜きさしが多い方でしたので、ポート側に不具合が出たようです。

### ②M1のMacBookAirで2枚目の外部モニターを接続したけど映らない
M1のMacBookAirでは外部モニターの出力は1枚に制限されております。
そのため、2枚目のモニターを接続するにはDysplayLinkという仕組みを利用する必要があります。

これに対応したアダプターを購入し、接続したところ通電を示すランプがついたのでユーザーに渡しました。
ところがこれを使っても映らないといわれてしまいました。
MacBookAir本体がアダプターのUSB接続を認識していませんでした。
残念ながらアダプターの初期不良です。
返品交換の結果、今度は映りました。

このように見た目上は正常に見える場合でも、システム側が認識していないとモニターは映らないということを学ぶことになりました。

## まとめ

今回の記事をまとめたいと思います

- モニターの電源を入れなおす
- モニターのケーブル類を挿しなおす 
- モニターの入力信号を確かめる
- PCがモニターを認識しているか確かめる
- ケーブル類をはずして放電する
- 上記でダメならPCorモニターのサポートに連絡する

最初の2つで多くの場合は解決します。
ここだけでも覚えていただけると書いた者としてはうれしい限りです。

皆さんもモニターの不具合で出会った特殊な事例や解決方法があればぜひ教えてください！
「プロダクトマネージャーのしごと」を読む

### 第一章　プロダクトマネジメントの実践
* 日常の業務は思ったほどビジョナリーではなく、地味、でも重要な多くのタスクをこなす必要がある。プロダクトの成功に関してはなんでも探して取り組むことが求められる。（が、長時間労働を推奨しているわけではなくプロダクトやユーザーに向き合うことこそ価値）
* 細かいズレや認識の齟齬は後々プロダクトの失敗に繋がるので、先回して確認する。

### 第二章 プロダクトマネジメントのCOREスキル
　 * Coreスキル（ハードスキル）　UX/テクノロジー/ビジネス　これらのスキルが重要であるとはいえ、プロダクトマネージャーはエンジニア、ビジネスアナリスト、デザイナーでもない。独自なものと考えた方が良い。
　 * Coreスキル(ソフトスキル）　コミュニケーション/組織化/ビジネス　-コミュニケーション能力は友達になるとかそういう話ではない。意思決定の透明性や相手への尊重などが重要。
　 * 特に印象に残ったこと-> 組織課題は個人に目を向けるのではなく、システムそのものに目を向ける必要があるということ。個人に目を向けると組織の雰囲気も悪くなるので絶対やってはいけない。
　 
### 第三章 好奇心をあらわにする
　　　*　さまざまな分野に興味を示す必要がある。
　　　*　イエス、ノーの気持ちのぶつかり合いにならないようにする
　　　*　なぜ？と聞く前にやり方を教えていただけませんか？と聞く。
　　　*　自分の場合だと、エンジニアリングの背景があるのでビジネス、UI,UXへの興味が必要。（実際に興味ある！！）
　　　
### 第四章 過剰コミュニケーションの技術
　　　*　説明するか迷ったら説明する！
　　　*　当たり前を問うことを恐れない。これを問い続けることで、PJメンバーの共通認識を強固のものにする。
　　　*　迷ったらコミュニケーション！！
　　　*　MTG嫌い、メール嫌いの誘惑に耐える！MTGやメールを相手の時間を奪うことだとは思わず、有効活用することだけを考える。
　　
### 第五章 シニアステークホルダーと働く。
 * 幹部や経営層に厳しいFBをもらって自信をなくすこともあるかもしれない。とはいえ、彼らの意思決定をサポートして支援し、自分の経験にしていくことが重要。
 * 自分で何かを意思決定する際はシニアステークホルダーに事前に共有しておきます。それも、過剰な頻度でしっかり行う。

### 第六章 ユーザーに話しかける
 * ユーザーヒアリングこそが命。
 * より具体的な話を聞く。抽象的な話だと架空のユーザーを自分の頭の中で作ってしまうので注意が必要。
 
### 第七章 ベストプラクティスのワーストなところ
　 * ベストプラクティスは単なる出発点！。フレームワークを当てはめたい衝動に駆られが、プロダクトマネジメントに銀の弾丸はない！（エンジニアリングと同じ！）
　 * プロセスを嫌う（効率を重視して、ステップを飛ばす）方を早めに巻き込んで、文書に残す！（意思決定のプロセスを明確化する）
### 第八章 アジャイルについての素晴らしく残念な真実
* アジャイル関連の専門用語は使用しないようにしましょう。エンジニアリング用語、ビジネス用語、UIUX周りの用語すべてに言える。わかりにくい言葉を使用すると認識の齟齬が生まれてしまう。
* チームとレトロスペクティブをする時間を確保する。レトロスペクティブとはスプリントの振り返りのこと。日々のタスクに追われてこれが確保されない話は体験してきたので耳が痛い。。
### 　第九章 プロダクトの仕様書はプロダクトではない
* メニューは食事ではない。仕様書事態がユーザーに価値を届けるものではない。
* テンプレートを作成後、３度自分で使用してみる。
### 第十章 ビジョン、ミッション、達成目標、戦略を始めとしたイケてる言葉たち
* イケてる言葉はチームが理解しやすくなるために存在する。
### 第十一章 「データ、舵を取れ！」
* 特定の情報を一般化するためにデータという言葉を使わないでください。
* 施策を打つ前にどのような結果になることを期待することを忘れない。
### 第十二章 優先順位づけ：すべてのよりどころ
 * 機能を引き算することはユーザーやビジネスにとって付加価値になる場合があります。これは本当に共感できて、過剰な機能追加はユーザーを困らせる場合がある。
 * あなたが下す意思決定は全てがトレードオフになる。それをステークホルダーに説明する義務がある。（
### 第十三章 おうちでやってみよう：リモートワークの試練と困難
　　* リモートワークと対面に優劣はない！（どうしても、自分のバックグラウンドで優劣を判断してしまう可能性があるから注意したい）
　　* 結局、素直にコミュニケーションを取ることが大事。　
### 第十四章　プロダクトマネージャーのなかのマネージャー（プロダクトリーダーシップ編）　
* マイクロマネジメントであると感じたとしても、必要な情報が確実に得られるようにする。
* 部下やチームが作った後にフィードバックが得られないまま放置されるのは絶対に避けるべき。

### 第十五章　良い時と悪い時
* 良いプロダクトは対立をオープンとして扱う組織。（どの組織にも対立は当たり前のように存在し、それを見て見ぬふりをしてしまうのが一番良くない。）
* 組織が自動操縦にならないように気をつける。新しいアイデアや挑戦をチームに持ち込むのが重要。
Pythonで「累算代入演算子(複合代入演算子)の使い方」の動作を確認してみた

# 概要

Pythonで「累算代入演算子(複合代入演算子)の使い方」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/var/index6.html

# 実装

以下のファイルを作成しました。
```sample.py
num = 10
print("num = " + str(num))

# num に 5 を加算します
num += 5
print("num = " + str(num))

# num に 10 を乗算します
num *= 10
print("num = " + str(num))

str = "Hello,"
str += "Python"
print(str)

str = "Good!"
str *= 4
print(str)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
num = 10
num = 15
num = 150
Hello,Python
Good!Good!Good!Good!
```

# まとめ

何かの役に立てばと。
戻り値（返り値）とはどういう概念か掘り下げて考えた

## 自己紹介
はじめまして、はると申します。完全異業種からのエンジニア転職を目指して、スクールに通いながら学習をしています。

## 概要
プログラミングにおける「戻り値」について、Rubyの例を用いて説明します。

## 注意
私は前職が完全異業種であり、英語も苦手で、スクールに入って初めてプログラミングに触れました。
そんな自分が理解しづらかった部分を、同じように初めてプログラミングの概念に触れた人に向けてまとめました。
自分の復習も兼ねて、超超噛み砕いて書いているため、周りくどい書き方になっている箇所もあるかと思います。

また、初学者のため、間違っている箇所もあるかもしれませんのでその際は教えて頂けると嬉しいです🙇

## 戻り値とは
戻り値とは、言語に関わらずプログラミングに共通する概念です。
この記事全体を通して説明していきます。

## 噛み砕いて考える
私が初めて戻り値に出会ったときは、「 **あらかじめ定義しているメソッド** を **使って** 結果が得られている」のに、どうして **「戻り」** 値なの？🤔と疑問に思っていました。
　
それでは、例を用いて説明します。下記の例は別の言語ですが、どちらも
- `number　+ 2`を実行するためのメソッド（関数）
- numberに`2`を代入した状態でメソッドを実行して出力する一行
が書かれています。
　
 
**JavaScriptの場合**
```jsx
function addition(number) {
  return number + 2;
}

console.log(addition(2)); /* =>4 */
```

**Rubyの場合**

```ruby
def addition(number)
	number + 2
end

puts addition(2) #=>4
```

JavaScriptでいう関数や、Rubyでいうメソッドは、定義しただけでは何も出力されません。
JavaScriptであれば`console.log`、Rubyであれば`puts`などの、**「出力して表示させる」ためのコード**が必要になります。
　
　
順番を逆にして、出力された結果側をスタートにして考えてみると、（Rubyで説明します）
　
コード実行時に`4`が画面に表示（出力）されている。
↓
`4`を表示しているのは、`puts addition(2)`の部分のコード。
↓
`addition(2)`は引数`2`をつけて`addition`メソッドを実行している。
↓
`addition`メソッドの中で、`2 + 2`が行われる（引数の`2`をnumberに代入して実行）
↓
メソッドで計算したその結果 = `addition(2)`ということになる。
↓
`puts addition(2)`が`puts 4`に置き換わる。（計算結果が`addition(2)`に入っている。）
　
　  　
という流れになります。
「定義した`addition`メソッドがあるから`puts addition(2)`で使えている」のではなく、
**「`puts addition(2)`で呼び出された`addition`メソッドは、計算結果を返す」**

という言い方ができます。
　
そのため、`addition`メソッドの結果の`4`が **「返り値」「戻り値」** と呼ばれます。
　　
そう考えると、`return`や、「戻り値」という言葉が使われていても納得できますね。

:::note
自分はRailsでNo Method Error（呼び出そうとしているメソッドが存在しません）などに沢山遭遇して、やっとこの**呼び出される順番**のイメージがつくようになりました。
:::
 
## まとめ
- 実際に実行する部分（**呼び出し元**）の目線に立って、定義したメソッドを「呼び出す」、値が「返ってくる」という言い方をする。

- どの目線から使われている言葉なのかや、コードが実行される順番を考えることが重要。
　
## 参考記事
- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典　戻り値とは](https://wa3.i-3-i.info/word1441.html)
- [引数・戻り値はこうやって理解する](https://blog.senseshare.jp/argument.html#google_vignette)
高専ロボコンとATVの将来

## はじめに

高専ロボコン2023が終了しましたね。大阪公大高専の皆様おめでとうございます.  
今年の高専ロボコンを観戦し,思ったことを書き綴っていこうと思います.  
今年の高専ロボコンについて特に __批判をするわけではなく,私の知っている技術を皆さんに共有したい__ ので書いているものになります.ここを抑えて,この記事を読んでいただければと思います.  

## 今回の高専ロボコンと通信
きっと永年の課題だとは思うのですが,WiFiやBluetoothなどによる通信で,チャンネルブッキングによる混信があったと思います．
僕がYoutubeで見ていた限りだと,和歌山や東京などはその影響なのかなと思っています.  
真偽は分りませんので,あまり信用はしないでください.
きっとHoloLensやVRゴーグルなどの映像機器がかなり発達してきて,それを利用するためにWiFiなどを使っていると思います.  
ですが,この通信て途切れたらまずいですよね？コントローラーも同じような通信方法であれば,もう操縦できませんよね.

## 思うに
WiFiの特性上,電波の混信やチャンネルダブりはよくあるので,そこを防ごうとしても __無駄に近しい__ ものがあると思います.  
こういった混信を減らすためには電界強度・出力でごり押しするか,運営側がWiFiなど制限を設けるなど運営側の対応の二択になると思います.最も,後者の運営側の対策はかなり高難易度かつ強制力を持たせることが至難の業になると思うのでほぼ無理でしょう.会場でテザリングしてる人を退場させようとしても,電波は目に見えないですし,誰が発しているか特定するのは無理でしょう.  
結局,この問題を解決するには,各高専が対応したほうが早いのでは？とな思いました.

## だけども
先ほどの文で, __「高専が仕様を変えれば問題ない」__ のようなことを書きましたが,だからと言って一般来場者が何もしなくていいという話にはなりませんよね.  
一般来場者は「WiFiを使用するテザリングなどを控え,Bluetooth機器も可能な限り電源を落とす」という配慮は必要でしょう.互いに対応策を出し合い,それを実行することによって快適な電波環境が得られるものだと思っています.  
どちらか一方の力だけでは,この問題は一生解決できないでしょう.

## じゃあどうすればいいの？
「WiFi接続が安定しないから,じゃあWiFiから他のものを使おう.」  
もしそうなった場合を仮定しましょう.きっと,他に何があるんだろうという風になりますよね.実際WiFiほど帯域幅を取れるモノってなかなかないです.だからこそ __WiFiが便利に使われていて,離れられない関係__ になっていたんじゃないかと思います.  
ですが一つあるんですよね.他に使えるものが.  
それが ___ATV___ という技術です.詳しく説明しましょう.

## ATVってなんだ？
もはや古代の技術として扱われているATVなのですが,ATVは「アマチュア・テレビジョン(Amature TeleVision)」の省略で,その名の通りテレビのような映像を伝送できるものになります.  
なんでアマチュアって名前がついているのかというと, __アマチュア無線__ を使用するからです.もうあまり耳にしなくなりましたね.それが古代の技術とした使われてる理由でもあったりするのですが.  

## なにがいいの？
WiFiなどと比べて,周波数を選ぶことができます.  
WiFiなら大体2.4GHzか5GHzなのですが,ATVはアマチュア無線に割り当てられてる周波数で許可されている帯域を使うことができるため,430MHz,1200MHz,2400MHz,5600MHz,10GHzとかなりバリエーションがあります.また,帯域も広いため,他チームとの混信も余裕をもって回避することができます.  
また,コントローラーなどの通信もアマチュアバンドに載せることができるので,かなり汎用性は高いと思います.  
  
基本的にテレビ放送と同じ仕組みなので,同時に多数の人たちがその映像を見ることができます.つまり,カメラとビューワー(HoloLensなど)従来1対1でなければいけなかったものでも,ATVに切り替えることで1対多数で受信することができ,2人でコントロールしているのであればその状況を二人で共有することができます.  

また,WiFiなどデジタル変調の上にパケットが乗っているモノとは違い,アナログ方式ATVを採用すれば,万が一混信しても映像すべてが映らなくなるということはないでしょう.  
他にもたくさんありますが,一部抜粋して挙げてみました.  

## いいところばっかりなの？
いえ,そういうわけではないです.
どのソリューションにも欠点というのは存在していて,この技術においても同じです.  
割と枯れ切った技術で,もはや「ロストテクノロジー」に近しくなってきているため,これといって参考になる文章などがあまりないです.きっと,昔趣味でATVをやっていた人が一番わかるんじゃない？と筆者が思うくらいには情報がないです.一応書籍なども出版されていたころがあったので,それを手に入れれたらGOODかもしれません.今も,ATVを趣味でやっている人も少なからずいるので,そこにあたってみるのもありかもしれませんね.  

また,アマチュア無線なので免許がいります.そこまで難しくないですし,きっと高専ロボコンあるいはそれの類似競技に出場するくらいのバイタリティがあるのであれば余裕だと思います.「第4級アマチュア無線技士あるいはそれに相当する資格」があればATVを運用することは可能です.

またあまり関係ないようにも思いますが,電波法でアマチュア帯での通信は暗号化をかけてはいけないという法律があります.つまり,BSやCS放送などで,料金を支払うことによって暗号を解くことができるキーをゲットできるように,アマチュア帯でも自分のチームだけの暗号アルゴリズムをかけて...なんていうのはできないんです.

## なんでATVを勧めるの？
私がATVの導入を勧めるのは何よりも __安定性__ です.  
かなり安定して通信することができ,システムを構築できれば混信などの影響もMAXで受けないのでかなり強力なツールになるんじゃないかなと思います.  
WiFiやBluetoothなどという大衆化された通信より,より通信信頼性があります. 
なにより,通信障害による「動かない」という事象を防いで,その悔しい気持ちをどうにか無くせないかなと思っている次第です.

## さいごに
Qiitaに随時ATVの記事を更新していく(はず)なので,今回は触りだけです.
もし,高専ロボコンでATVを導入したい高専ありましたら jm8psy.qso()gmail.com に連絡してください.ATVでの送受信を経験していますので,なんでも聞いて下さい.  
()は@に置換してください.
Node.jsのCJSとESM の挙動の違い

# はじめに
Node.jsを久しぶりに触ってCJSとESMでの挙動の違いに少し苦戦してしまったのでその違いをまとめようと思って書きました。

## Node.jsのバージョンの意味
Node.jsの偶数は長期サポートが保証されているもの
奇数は新しい機能を試すためのもの
- Current
- Active LTS
- MAINTENANCE

## CJSとESMの挙動の違い
- __filename, __dirnameへの対応
- require, module.exports
- require JSONで自動でパースされない

```js
__filename
__dirname
```
この書き方はCJSでは対応しているけど、ESMでは対応していない
ESMでパスを扱うにはこのようにする
```js
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
```

### モジュールの読み込み方の違い
CJSの書き方
```js
const plus = (a, b) => {
  return a + b;
}

module.export { plus }
```

```js
const plus = require(./plus); // .jsを省略できる

console.log(pulus(3, 4)); // 7を出力
```

ESMの書き方
```js
const plus = (a, b) => {
  return a + b;
}

export { plus }
```

```js
import { plus } from "./plus.js";

console.log(pulus(3, 4)); // 7を出力
```

### JSONの取り扱いの違い
CJSでは
```js
const jsonObj = require("./users.json");
console.log(jsonObje); // オブジェクトとして出力される
```
ESMでは
```js
import { createRequire } from "module";

const require = createRequire(important.meta.url);
const jsonObj = require("./users.json");
console.log(jsonObj); // オブジェクトとして出力される
```

## まとめ
CJSとESMでは挙動が異なり、同じ書き方ができない部分もあります。これらの違いを理解することでエラーの原因を特定しやすくなります。Node.jsは普段フロントのコードを書いている人と親和性の高い技術なのでNode.jsを入り口にバックエンドを少しづつ学習することで市場価値を高めることにもつながるのでNode.jsの学習はおすすめです。
サイトのFAQを自然言語検索できるRAGチャットをAWSで動かしてみた

## この記事について
この記事は [SUPER STUDIO Advent Calendar 2023](https://qiita.com/advent-calendar/2023/superstudio) の7日目の記事になります。

## RAG(Retrieval Augmented Generation、検索拡張生成)とは
大規模言語モデル（LLM）に特定の情報を参照できるようにすることで、ユーザーの質問に対して、与えた情報から回答を生成する仕組みです。
FAQやナレッジデータベースなどの一次情報を指定することで、自然言語による一次情報の検索、および回答を返却することができるようになります。
AWSでは、検索エンジンサービスの「Amazon Kendra」と、生成AIサービスである「Amazon Bedrock」を組み合わせることで簡単に実現できます。

## RAGチャットを動かしてみるには
手っ取り早くRAGチャット実行するには、AWSの生成AIワークショップの通りに手順を踏めばいいです。

https://catalog.workshops.aws/generative-ai-use-cases-jp/ja-JP

このワークショップではRAGチャットだけでなく、文章要約や画像生成といったいろいろな生成AIについて、実際に動かして試すことができます。
構成図的には以下の通りです。

![構成図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/b25f1ff0-b9c8-11c4-2f8d-1afa1695dc94.png)

権限回りについての記述がないため、IAMロールの許可ポリシーの追加に困ったくらいで、本当に書いてある通りで問題ありません。

## データソースの変更
このワークショップでは、RAGが参照する情報はS3バケットに配置したドキュメントファイルを参照しますが、今回はインターネット上に公開しているサイトを読み込ませたいので、そこだけ手順を変更します。

今回読み込ませるサイトについては、弊社が提供している統合コマースプラットフォーム「ecforce」のFAQを使用します。

[ecforce faq](https://support.ec-force.com/hc/ja)

ワークショップの手順「3.データの追加」で上記サイトのURLを読み込ませるようにしてみます。
まず、「3.1 S3へのアップロード」はスキップして構いません。
次に「3.2 KendraとS3の連携」を以下のようにします。

元の手順では、Kendraのデータソースとして「Amazon S3 Connector」を指定しますが、ここでデータソースを下にスクロールしていくと「Web Crawler V2.0」があるのでそちらを選択します。

![スクリーンショット 2023-11-26 19.08.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/26d99208-5f60-606b-c069-998a60a030e0.png)

次にクローラーの設定です。
データソース名に適当な名前を設定して、Default languageは日本語のサイトなので「Japanese(ja)」を選択します。

![スクリーンショット 2023-11-26 19.10.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/f1c234b9-04cc-f5d3-e7d7-ce18fea48883.png)

クロール対象はFAQのURLを入力します。

![スクリーンショット 2023-11-26 19.12.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/ecf3baf6-76f3-a7c6-32bf-aba3555f5752.png)

あとはデフォルトのままで設定完了です。
最後に同期の頻度はオンデマンドにしているので、`Sync　now` で手動で同期させます。
今回のFAQでは、クローリングからインデックスの作成まで３時間弱くらいで完了しました。

## RAGチャットを使ってみる
あとはワークショップの手順通りにアプリを立ち上げて、RAGチャットを使用してみます。

![スクリーンショット 2023-11-26 19.04.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/c81d6d78-0217-532b-26d1-142c11535890.png)

良い感じに回答が出力されました！
もう少し漠然とした質問をしてみます。

![スクリーンショット 2023-11-26 19.53.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/f7e241ab-4bde-4e10-9853-d43fc4f201aa.png)

クロールによってFAQ以外のページからも回答を検索して、うまく回答してくれています。
最後に少し見当違いな質問をしてみます。

![スクリーンショット 2023-11-26 19.19.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19193/6471299f-7f55-cc80-d0ec-a81aac7b10a7.png)

データソースに関係ない質問には答えないように制御できていますね。

## まとめ

巷ではChatGPT勢の話題に比べて、Amazon Bedrockは盛り上がりに欠けていますが、検索サービスであるAmazon Kendraをうまく組み合わせれば、コードをほとんど書かなくてもサイトのクローリングからLLMによる自然言語検索が簡単に実装できることがわかりました。
微調整には時間がかかるかもしれませんが、PoCレベルであれば十分な性能であると感じました。
ちなみにコストは３日使って４ドルでした（利用が済んだらリソースの削除はお忘れなく）。

## 追記
こんなことしていたら、AWS re:Invent 2023でAmazon Qが発表されましたね。
もっとお手軽にRAGチャットが使えるようになりますね。
[Linux / docker] docker containerから、localhostへアクセスしたいときのHack

# 概要

dockerコンテナ内から`localhost`にアクセスしようとすると、アクセス先は**コンテナ内**になってしまいますよね。
でも、コンテナの外にあるホストOS上に他のサービスが立ち上がっていて、そのサービスにアクセスしたい場合って、きっとありますよね？(\*´﹃｀\*)

（いつか図を書こう）

そんなときの対策。

# 結論

次のコマンドで、`HOST_IP_ADDRESS`という環境変数にlocalhostのIPアドレスを設定できました。

```bash
$ export HOST_IP_ADDRESS=`ip -4 a show ens5 | grep inet | grep -v inet6 | sed -E "s/inet ([0-9]{1,3}.[0-9]{1,3}.[0-9].{1,3}.[0-9]{1,3}).*$/\1/" | tr -d "\t"`
```

※`ens5`は、AWS EC2上においてlocalhostのIPアドレスを指す名前でした。
　環境によってこの名前は異なるので、自身で`$ ip a`コマンドを打ってみて、どんな名前のブロックにlocalhostのIPアドレスがあるかを事前に確認してみましょう(^ワ^\*)

　たとえば、私のwsl2で実行してみたところ、`ens5`ではなく`eth0`でした。


# このコマンドはどうやって生まれたか

## 1. 最初 (ifconfigコマンドを利用)

最初はこの記事に書かれている方法でlocalhostのIPアドレス抽出を行っていました。

https://qiita.com/ijufumi/items/badde64d530e6bade382#%E3%81%9D%E3%81%AE4docker-composeyml-%E3%81%A7%E6%8C%87%E5%AE%9A--%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%82%92%E4%BD%BF%E3%81%86

次のような感じです。

```bash
$ ifconfig en0 | grep inet | grep -v inet6 | sed -E "s/inet ([0-9]{1,3}.[0-9]{1,3}.[0-9].{1,3}.[0-9]{1,3}) .*$/\1/" | tr -d "\t"`
    172.000.000.255
```

## 2. 最終系 (ipコマンドを利用)

しかし、`ifconfig`コマンドは非推奨という次のような記事を見かけたので、

https://qiita.com/suzutsuki0220/items/dc72df23f1e1b1cda5f2

今度は、次の記事に書かれていた`$ ip -4 a show ens4`というコマンドを流用させていただきました。

https://linuxfan.info/ip-address

スペースをちょっと書き換えて次のように修正したら、期待通りの動きになりました。

```bash
$ ip -4 a show ens5 | grep inet | grep -v inet6 | sed -E "s/inet ([0-9]{1,3}.[0-9]{1,3}.[0-9].{1,3}.[0-9]{1,3}).*$/\1/" | tr -d "\t"
    172.000.000.255
```

（正規表現あんまりわかってないので、偶然の産物です）

# 感想

元の記事からほんのちょっとしか書き換えてないけど、とはいえ、これだけのために結構時間を食ったので、記事にしておくことにしました(｡ŏ﹏ŏ)
[Docker / nvidia/cuda] exec /opt/nvidia/nvidia_entrypoint.sh failed: No such file or directory の対策

# Env

|Docker image|tag|
|:--|:--|
|nvidia/cuda|11.2.2-cudnn8-devel-ubuntu20.04|


# 症状

以下のようなエラーが発生。

```bash
[FATAL tini (7)] exec /opt/nvidia/nvidia_entrypoint.sh failed: No such file or directory
```

# 原因

`/opt` ディレクトリを `volume` で上書きしてしまったせいで、このエラーが発生していた。

```yaml:docker-compose.yml
version: '3.7'
services:
  python:
    # 略
    volumes:
      - ./:/opt
```

# 対策

仕方ないので、 `/opt` は使用せず、何か他の名前のディレクトリを使うようにする。

```yaml:docker-compose.yml
version: '3.7'
services:
  python:
    # 略
    volumes:
      - ./:/workdir # <- /opt から変更した
```


:::note warn
**volume 変更の影響範囲**
自分の場合は `working_dir` が Docker container 内の `/opt` になっていたので、そちらも `/workdir` に変更する必要があった。

その他、元々 `/opt` と記載していた箇所全てを書き換える必要があるかもしれないので、よく確認した方が良い。
:::
量子コンピュータ初学者の理解(1)

NTTデータ先端技術株式会社の原田です。

この記事は量子コンピュータ初学者の学習による理解を記載したものです。
何分初学者ですので明らかに間違った内容があったりすると思いますが温かく流していただければと思います。
12月に開催される講演のあとにもう1本掲載予定ですので全2回でお届けいたします。

## 量子コンピュータとは
私の相棒 Azure OpenAI Service 曰く、

> 量子コンピュータは、量子力学の原理を利用して情報を処理するコンピュータです。従来のコンピュータがビット（0または1の値を持つ）を基本的な情報単位として扱うのに対して、量子コンピュータは「量子ビット」または「キュビット」と呼ばれる量子力学的な状態を持つものを基本的な情報単位として扱います。

とのことでした。
では量子力学について「量子コンピュータにおける量子力学について教えてください。」と質問してみました。

> 量子力学では、物理量の測定結果が確率的に決まるという原理があります。また、量子力学では、物質や光が波動として振る舞うことが認められており、波動の性質を利用して量子ビットが処理を行います。
量子ビットは、従来のビットと異なり、0と1のどちらかの状態だけでなく、これらの状態の重ね合わせ状態を持つことができます。例えば、量子ビットが0と1の状態の重ね合わせ状態にある場合、測定すると0または1が確率的に得られます。

ポイントとなるのは <INS>量子ビットは、従来のビットと異なり、0と1のどちらかの状態だけでなく、これらの状態の重ね合わせ状態を持つことができます。</INS> になるかと思います。
つまり量子コンピュータでは 1 個のビットが 0 であり 1 でもあると言う情報を持てる、言い換えると従来型コンピュータ(以降古典コンピュータと記載します)における n 個のビット分の情報量を取り扱えるため、情報の集積率が高く並列実行の得意なコンピュータを作ることができる仕組みである理解しました。

なぜビットが 0 でもあり 1 でもあることができるかについては、ここではそう言うものだまでに留めます。

## 量子コンピュータの歴史
私が耳にし始めたのはつい最近でしたが歴史自体は古く 1980 年代に遡ります、そこから 2010 年代後半～2020年代に商用量子コンピュータが開発されたあたりが一般的なキーワードとして浸透してきたころだと思います。
古典コンピュータでは基礎理論から開発・淘汰を経て汎用化されるのに 40～50 年かかってますが、量子コンピュータは開発・淘汰のフェーズに入って少し経ったあたりのところですのでまだまだ 10年単位の時間はかかるのでしょう。
がこの勝者が次の時代のイニシアチブを握れるわけですので力も入りますよね。

## 量子コンピュータの用途
現時点では汎用的な用途は想定されておらず、創薬や金融市場のシュミレーションなどの特定用途に対して量子コンピュータに適合したアルゴリズムを開発するという流れで進んでいるようです。
なのでこの特定用途の近くにいないとなかなか触れる機会を得られないという現状はあると思います。
私はブロックチェーンが破れちゃうんじゃないかと言うのが真っ先に浮かびましたが、ビットコインに絡めてその観点に触れている記事もいくつかありました。
どこかの天才が奇跡のアルゴリズムを発明して汎用コンピュータへの道が開ける、なんてシナリオもあり得るんでしょうかね。

## 量子コンピュータの課題
量子ビットは 0 であり 1 でもあるという情報を持てますが、演算に使用する際には確率に基づき値が確定します。(10 回のうち 4 回は 0 で 6 回は 1 という感じ)
ただこの確率に結構な誤差(ノイズ)が出てそれが検算結果にも影響を与えてしまうと言う問題があり、このノイズをいかに抑制・訂正するかというの目下かつ最大の課題となっているようです。
加えて実は演算に際しては値が確定する(並列実行した演算結果のうち1つしか取り扱えなくなる)と言うのもポイントで、ここをうまく潜り抜けないと量子コンピュータの特性が生かせないという課題もあります。

## 量子コンピュータの取り組み
Microsoft Ignite 2023 で AI × Quantum と言うキーワードがありましたので、3大パブリッククラウドの量子コンピュータの取り組みについて調べてみました。

* Azure : [Azure Quantum](https://azure.microsoft.com/ja-jp/products/quantum)
* AWS : [Amazon Braket](https://aws.amazon.com/jp/braket/)
* GCP : [Quantum Engine API](https://quantumai.google/cirq/google/engine)

国産ですと理研の[量子計算クラウドサービス](https://www.riken.jp/pr/news/2023/20230324_1/)がありますが研究機関向けでした。

## おわりに
ひとまず現時点で書けるのはこんなところかなと思います、本当に必要なのは「じゃあ自分はどうする？」なんですがそのイメージはまだ付かないのが現状です。
次回は講演を受けての自己フィードバックも含めた継続学習による理解について記載いたします。
Windowsデスクトップのアイコンがうまく表示されない時の対処法

# はじめに
　PCを使っているとき、例えば新しいいアプリをインストールしたり新たなファイルを作成したときにデスクトップに表示させることがあると思います。
　そのとき表示したはずのアイコンが真っ白になってしまったりすることがあります。
　今回はそんな状況になった時の対処方法を示していきます。　※Windowsはバージョン11です。

## （１）PCの再起動
　この方法はどんな不具合が起きたときでも一度は試してみますよね。再起動することで問題がある状況でない限り一度試してみましょう。
　ただ今回はこれで直らない場合が多いかもしれません。その場合は条件に応じて次以降の方法を試してみてください。
 
## （２）ショートカットの再作成
　表示したいアイコンが何かのショートカットだった場合はこの方法を取ってください。作成したショートカット自体に問題が発生している可能性があるからですね。
　簡単にですが手順を下記に記します。
- デスクトップにあるアイコンを削除
- Explorer開き作成したいアプリケーションがある場所まで移動
- アプリケーションの右クリックし「ショートカット作成」を実行
- （そのままデスクトップに配置されなかったら作成したショートカットをExplorer内でデスクトップに移動）

## （３）アプリケーションの再インストール
　
　上記の方法が駄目ならこの方法です。雑になりますがアプリを一旦アンインストールして、その後再インストールしてみてください。
　※ちなみに私はこの方法では直りませんでした。

## （４）セーフモードで再起動
　上記三つの方法が駄目だった、試したくないという人はこれをやってみましょう。
　恐らくこの方法が一番解決できると思います。
 下記に方法を示します．

- Windows Updateの設定を開く
 ![スクリーンショット 2023-11-27 171816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111717/38d106eb-25b9-c4ea-64f8-56097ab4f212.png)

- 詳細オプションを選択
![スクリーンショット 2023-11-27 171851.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111717/0d9271aa-f3de-1667-231b-907caaa433e3.png)

- 回復を選択
![スクリーンショット 2023-11-27 171909.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111717/968f9330-5849-6359-9855-bcc97c7ed976.png)

- 今すぐ再起動を押して再起動をかける
![スクリーンショット 2023-11-27 171929.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111717/1d41876a-4191-7a4f-d84f-a6cff6d7a93f.png)

- スタートアップ設定の画面でセーフモードを有効にする
- セーフモードが有効な状態で再起動を行う
- セーフモード起動出来たら、通常の再起動で起動しなおす

# 終わりに
　4つの方法のいずれかで解決できたでしょうか。お力になれたら幸いです。もし出来なかったら力不足で申し訳ないです。
　どうしてもできなかった場合で、アイコンの表記が気になる場合は素直にカスタマーサポートに連絡して聞くのが良いかもしれません。（このアイコン表記だからと言ってアプリケーションが動かないわけではないと思うので、気になった場合はという話にはなりますが。）
スプレッドシートで参照がズレてイライラする時に見る記事

## はじめに

今年もアドベントカレンダーはじまりました！
この記事はNE Advent Calendar 2023のカレンダー1枚目1日目の記事です。
NE株式会社のエンジニアが自分の興味あるテーマについて自由に書いていきます。
毎年一緒に参加して盛り上げてくれる皆さんに感謝です :clap:

## 概要

例えばこんな元データがあったとします。（プルリク数を集計するようなシート）

![スクリーンショット 2023-11-27 13.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/f752a464-1682-28c3-502c-d60718af3b3b.png)

このデータを人別・月別に集計します。

![スクリーンショット 2023-11-27 14.47.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/b0c3ba9e-4bae-becf-57dc-d334191e950d.png)

関数としては以下のように組みました。
* 名前の欄（A2:A）にてE2（Aさん）のもの
* マージ月の欄（C2:C）にてF1（202309）のもの
```
=countifs(A2:A, E2, C2:C, F1)
```

正しく集計され「2」というカウントになりました。
良さそうなので他の人や月にも反映します。
数式をコピーして他のセルに貼り付けてみると。

![スクリーンショット 2023-11-27 14.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/8c62bb46-aec9-f274-57db-8ee183453a81.png)

おや、おかしいですね。
全部0になりました。
貼り付けた数式を見てみると

![スクリーンショット 2023-11-27 14.51.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/1f33ef60-88ce-b1b9-67c2-b6aaf8cf6601.png)

```
=countifs(A3:A, E3, C3:C, F2)
```

* 名前の欄はA2:AにしたいのにA3:Aになってしまっている。
* 検索する人はBさん（E3）なので合ってる。
* マージ月の欄C2:CにしたいのにC3:Cになってしまっている。
* 検索する月は202309（F1）にしたいのにF2になってしまっている。

セル１個下にコピペすると相対参照され、数値の部分が1プラスされます。
E2からE3は意図しているのでいいですが、他の部分は1プラスされたくないですよね。
こうなってしまうとコピペで展開できず1セル毎に微調整が必要になりイライラしますよね。
これを解消しましょう！

## 相対参照と絶対参照

### 相対参照

普通にA2とかを指定するとコピペした際に相対的に値が変動します。
下のセルだと2から3
右のセルだとAからB
のように相対的にAの横だからBやろ、みたいな感じでいい感じにやってくれます。
これが都合が良い場合はこれでいいですね。

### 絶対参照

相対だと都合が悪い場合に使うのが絶対参照です。
これは「$」マークを使って表現します。
例えばA2という参照があったとして以下のように記述できます。

| 記法 | 意味 |
|:-:|:-:|
| `$A$2`  | Aも2も絶対参照。コピペしても動かない。  |
| `$A2`  | Aが絶対参照。左右にズレてもAのまま。2に関しては上下に動く。  |
| `A$2`  | 2が絶対参照。上下にズレても2のまま。Aに関しては左右に動く。  |

これをうまいこと利用することでコピペで意図した形にすることができます。

## 実践

先程の関数は以下のように変えてみました。
```
=countifs($A$2:$A, $E2, $C$2:$C, F$1)
```

これで他のセルにコピペしてみると…

![kw4un4Bs61.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/2839cecc-d1dc-adba-61a4-2c03ff338110.gif)

無事にやりたい参照で反映できました！
少し解説すると
* A2:Aは人の列として固定の参照範囲なので全て固定
* C2:Cについても同様に全固定
* E2は検索する人の名前
    * これについては左右はズレて欲しくないが上下はズレて欲しい
    * そのため`$E2`としてEのみ固定し、2,3,4と動くようにした
* F1は検索する月
    * これについては左右はズレて欲しいが上下にはズレて欲しくない
    * そのため`F$1`として1のみ固定し、F,G,Hと動くようにした

## まとめ

相対参照と絶対参照をうまく使い分けてスプレッドシートレベルを上げていきましょう！

## おわりに

今年も完走目指して頑張りましょー！
この後もNEのアドカレをお楽しみに！！
LPIC/Linux学習記録#3

〇自戒のための自己への宣誓
1. お前に足りないのはインプットだ！！！インプットしろ！！！インプットの奴隷になれ！！！
2. 記事の書き方とか今はどうでもいいから書け！！！インプットをアウトプットしろ！！！やる前からこだわりとか持つな！！！
3. 見られることとか評価されることとか気にするな！！！MECEとか構造化されてるかどうかとか気にするな！！！構造化はアウトプットの整地であって、インプットが足りないお前が手を出す領域ではない！！！ていうかお前頭良いんだからインプットに注力しろ！！歴史を刻め！！！歴史をまとめようとするな！！！未来を描け！！過去を清算するな若者め！！！！
4. 疑問を持つことを恥じるな！！！お前は頭はいいがインプットが足りない未熟者だ！！！インプットの奴隷になれ（再掲）！！！

〇学習記録
IPアドレスを調べたいとき：ifconfig(Windowsならipconfig)。ネットワークインターフェースの情報がわかる。他にも、ip addressとかnetstat -anoとかがあるらしい。ssとかも聞いたことあるけど使い方知らない。
仮想化コンピュータでもethXと出る。dockerだとdockerXと出る。いずれにせよネットワークは変わらないらしい。

ip address add [ip/mask] dev [NIC name]でIPアドレスを追加できるらしい。追加して何すんねんと思ったけど、構築の際に個別で割り振る際は必要なのかね。でもDHCPで割り振ったり、スイッチならconfigをテキスト形式で作成して投げれば自動でNICごとに割り振ってくれるってのを聞いたことがある。あれか、それを実施するための具体的な手段がip add [ip/mask] dev [NIC name]になるのか。納得。

ip address del [ip/mask] dev [NIC name]でIPアドレスを削除できるらしい。IPアドレス削除してどうすんねん。

ip routeってのを学んだ。
ルーティングっていうのはルーター（最近だとL3スイッチ）がするものだと思ってた。プロキシサーバーみたいにノードとルーターの間にサーバーが入るのが普通じゃないんだと気づいた。プロキシとか負荷分散とかいう言葉があって、それはサーバーとかルーターみたいな筐体レベルの単語を一緒に使わないのでなんでやねんと思ってたがこういうことなのか。ルーターみたいなことをルーターじゃなくてもできるんで、普通のコンピュータ（普通のコンピュータじゃないな、LinuxとかWindowsっていう多用途な？OSだね）をノードの（論理的な）集約点としておいてプロキシとか負荷分散とかができるんだろうね。普通のコンピュータっていうのはSocketを含むプロトコルスタックを持ってるもの。論理的な集約点っていったのは、インターフェースがスイッチとかルータほどなければそもそも物理的に接続ができないはずなので、どこかにL3スイッチとかおいてるんじゃないかなと憶測。
となるとLinuxサーバーとかでIPアドレス追加したり削除したりデフォルトゲートウェイ設定したりする意味が分かってきた。

でことでデフォルトゲートウェイの設定方法は、ip route add default via [ip address]。ルーティングの設定は、ip route add [target NW/mask] via [pass ip] dev [NIC name]。ルーティングテーブルに書くような基本的なことを入力すればいいっぽい。
neo4jのMERGEでつまずいた話

## はじめに
　本記事では，私がneo4jのMERGE句の利用でつまずいたので，備忘録とカレンダーの作成がてらMERGE句の使い方をまとめていこうと思います
 
 MERGE関連の公式ドキュメント
- [チートシート](https://neo4j.com/docs/cypher-cheat-sheet/5/neo4j-community/#_merge)
- [詳細](https://neo4j.com/docs/cypher-manual/current/clauses/merge/)

## MERGE句とは
　MERGE句は，ノードやリレージョンが存在するときは上書きを，存在しない時は新規に作成を行ってくれる構文になります
### 基本的な使い方
[公式より](https://neo4j.com/docs/cypher-cheat-sheet/5/neo4j-community/#_merge)
```cypher
MERGE (n:Label {name: $value})
ON CREATE SET n.created = timestamp()
ON MATCH SET
  n.counter = coalesce(n.counter, 0) + 1,
  n.accessTime = timestamp()
```
### MERGEを利用しない場合
#### 作成時
```cypher
CREATE (n:Label {name: $value, created: timestamp()}
```
#### 更新時
```cypher
MATCH (n:Label)
WHERE n.name =  $value
SET
  n.counter = coalesce(n.counter, 0) + 1,
  n.accessTime = timestamp()
```
or
```cypher
MATCH (n:Label {name: $value})
SET
  n.counter = coalesce(n.counter, 0) + 1,
  n.accessTime = timestamp()
```
プログラムから利用することを考えると，場合分けをしないで使えるMERGE句のありがたみが分かると思います

## 発生した問題
　現在作成中のプログラムは，ユーザーの関係を管理するためneo4jを採用しました．Userの持つプロパティは一部省略しますが以下のようになっています
 - `id`：ユーザーID ユニーク
 - `displayName`：表示名
 - `createdAt`：Userの作成時刻

idはユニークですので，neo4jに以下の設定を行いました
```cypher
CREATE CONSTRAINT unique_user_id IF NOT EXISTS
FOR (u:User)
REQUIRE u.id IS UNIQUE
```
ここで，プログラム側の実行時に公式アカウントを作成済みでなければ作成する機能が欲しかったので，以下のようなcypherを実行するプログラムの作成を行いました
```cypher
MERGE (:User {
  id: "official",
  displayName: "公式",
  createdAt: datetime()
})
```
一回目の実行では正常に成功し，以下のようなUserが作成されました
```json
{
  "id": "official",
  "displayName": "公式",
  "createdAt": "2023-12-01T00:00:00Z"
}
```
期待通りの結果が得られ，ヨシッとこの時までは思っていました．が，次の機能を開発し，サーバーを再起動すると以下のエラーが出るようになりました．
```
Node(0) already exists with label `User` and property `id` = 'official'
```
このエラーはユニーク制約に引っかかって出力されるエラーになります．テストのために以下のようなコードを作成し，検証を行いました
```cypher
MERGE (:Test {prop: "test"})
```
しかし，こちらのコードでは何回実行してもエラーにはなりませんでした．ここで私は,「MERGE句の内部処理で一回同じidのノードを作成してしまっているのではないか」とあたりをつけてバグの解決策を調べ始めました．~~自分のプログラムは絶対あってるって思っちゃうよね~~
　しかし，neo4jの公式やライブラリのissueをみても解決せず...ここでやっと自分のプログラムが間違っているのではないかと考え始めました．
## 解決
　よくよく考えてみると，MERGE句はどこで新規か上書きかの判別を行っているのかといった疑問が浮かびました．調べた結果が以下になります(唐突)
```cypher
MERGE (n:Label {ここに一致条件を列挙})
ON CREATE SET
  ここに新規作成時に設定するプロパティを列挙
ON MATCH SET
  ここに更新時に設定するプロパティを列挙
```
私のプログラムを修正すると以下のようになります
```cypher
MERGE (u:User {id: "official"})
ON CREATE SET
  u.displayName = "公式",
  u.createdAt = datetime()
})
```
## まとめ
　今回，MERGE句の利用でつまずいたので，MERGE句の使い方についてまとめてみました．直接的にエラーで指摘されないと，自分のコードを間違ってると思えないのは悪い癖ですね．私失敗しないのでって言えるエンジニアになりたい...(先は長そう)
 　記事にまとめてみると，その時自分は何を考えてそうしたかや，どうするべきだったか反省出来て良かったです．ゆめみの24卒カレンダーに参加しているので，また何かしら問題に詰まったら，復習がてら記事を書いてこうと思います．では！