OmniAICreator/Qiita-1.07M huggingface dataset:
ラズパイで使うOSイメージをサイズ縮小してmicroSDへ書き込む方法

# ラズパイで使うOSイメージをサイズ縮小してmicroSDへ書き込む方法

## 想定読者：
- ラズパイで64GBのmicroSDで環境構築したので、OSイメージごとバックアップしたいけど、手元に32GBのmicroSDしかない人
- 怒らない人

## 準備：
A. microSD A (OSの入ったもの)
B. microSD B (サイズを小さくしたOSを入れたいもの)
C. USB接続のmicroSDリーダー
D. Ubuntu22.04をインストールしたラズパイ (パーティションサイズ変更に使うだけなので、アレンジ可)

# 手順

## OSイメージ(64GB)をリサイズする
- 準備DのUbuntu22.04を起動
- Diskユーティリティを起動
- 準備CのmicroSDリーダーを接続
- 準備AのmicroSD A を挿入
- 64GBを30GBへResizeする

## リサイズしたOSイメージ(30GB)を保存
- ディスク名称の確認
```bash
$ sudo fdisk -l
# 容量みてデバイス名をみつけてください
```

# リサイズしたOSイメージのセクター数を確認する
- ddで書き込むカウント数を算出します

```
$ sudo fdisk -l
...
Disk /dev/sdf: 59.69 GiB, 64088965120 bytes, 125173760 sectors
Disk model: STORAGE DEVICE  
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3d39aab4

Device     Boot  Start      End  Sectors  Size Id Type
/dev/sdf1  *      2048   526335   524288  256M  c W95 FAT32 (LBA)
/dev/sdf2       526336 59121663 58595328 27.9G 83 Linux
```

1セクター512バイトで、1MBで2048セクターゆえ、
上記のセクター数から、
```
# カウント数を求める
59121663 ÷ 2048 = 28611
```

# OSイメージを保存する

```bash
sudo dd if=/dev/sdb of=/tmp/raspi-image.img bs=1M count=28611
```
ただし、下記とする
- リサイズしたOSのmicroSDのデバイス名：/dev/sdb
- 保存先 : /tmp/raspi-image.img
MQTT の Will メッセージを使うシナリオ

## 概要

クライアントが切断されると、関連する加入者に意志メッセージが送信されます。意志メッセージは次の場合に送信されます。

- サーバー上で I/O エラーまたはネットワーク障害が発生しました。
- クライアントは、定義されたハートビート期間中に接続を失います。
- クライアントは、オフライン パケットを送信する前にネットワーク接続を閉じます。
- サーバーは、オフライン パケットを受信する前にネットワーク接続を閉じます。

通常、Will メッセージはクライアントの接続時に指定されます。以下のように、接続時にインスタンスsetWillのメソッドを呼び出すことで設定されますMqttConnectOptions。以下のTopicを購読しているクライアントは、Will メッセージを受け取ります。

```
//method1 
MqttConnectOptions.setWill(MqttTopic topic, byte[] payload, int qos, boolean retained)
//method2 
MqttConnectOptions.setWill(java.lang.String topic, byte[] payload, int qos, boolean retained)
```

## 使用シナリオ

クライアント A が接続すると、Will メッセージは「オフライン」に設定され、クライアント B はこのウィル Topicにサブスクライブします。A が異常に切断すると、クライアント B はこの「オフライン」メッセージを受け取り、クライアント A がオフラインであることを知ります。

### 接続フラグパケットフィールド

| Bit    | 7              | 6             | 5           | 4        | 2         | 1           | 0        |
| ------ | -------------- | ------------- | ----------- | -------- | --------- | ----------- | -------- |
|        | User Name Flag | Password Flag | Will Retain | Will QoS | Will Flag | Clean Start | Reserved |
| byte 8 | X              | X             | X           | X        | X         | X           | X        |

クライアントが通常どおり切断メソッドを呼び出した後は、Will メッセージは送信されません。

## フラグ機能を発揮します

つまり、依頼者があらかじめ定め、異常切断時に残した最後のLast Will書（Last Will書とも呼ばれます）です。これは、クライアントによって事前に定義されたTopicおよび対応するメッセージであり、CONNECT の可変パケット ヘッダーに添付されます。クライアントの接続が異常な場合、サーバーはこのメッセージを積極的に発行します。

Will Flag のビットが 1 の場合、Will QoS と Will Retain が読み出されます。このとき、Will Topic と Will Message の具体的な内容がメッセージ本文に表示されます。それ以外の場合、Will QoS と Will Retain は無視されます。

Will Flag ビットが 0 の場合、Will Qos および Will Retain は無効になります。

## コマンドラインの例

Will メッセージの例は次のとおりです。

1. Sub 側 ClientID = sub が事前に定義されたメッセージが表示されます:

   ```
   mosquitto_sub --will-topic test --will-payload die --will-qos 2 -t topic -i sub -h 192.168.1.1
   ```

2. clientid = alive は 192.168.1.1 (EMQ サーバー) で will Topicにサブスクライブします

   ```
   mosquitto_sub -t test -i alive -q 2 -h 192.168.1.1
   ```

3. サブエンドがサーバー エンド (EMQ サーバー) から異常に切断され、パブ エンドが will メッセージを受信します。

## 高度な使用シナリオ

ここでは、Will メッセージで Retained メッセージを使用する方法を説明します。

1. クライアントAのLast Will メッセージは「オフライン」に設定され、Last WillのTopicは A/status通常の送信状態のTopicと同じに設定されます。
2. クライアント A が接続されたら、「オンライン」Retained メッセージをTopicA/statusに送信します。他のクライアントがTopicA/statusにサブスクライブすると、保持されたメッセージを「オンライン」として取得します。
3. クライアント A が異常に切断すると、システムはTopicA/statusに「オフライン」メッセージを自動的に送信します。このTopicにサブスクライブする他のクライアントは、すぐに「オフライン」メッセージを受信します。Will メッセージが「Retained」に設定されており、Topicにサブスクライブしている新しいクライアントがA/statusオンラインになると、取得されるメッセージは「オフライン」になります。
Vue3/Typescriptで縦型サムネイル付きカルーセルを作った

## はじめに
Vue3/Typescriptで縦型サムネイル付きカルーセルを作る際、条件を満たすUIライブラリを使うのに苦労した。
以下の表は、実装を検討したUIライブラリと断念した理由である。

<table>
  <caption>検討結果</caption>
  <thead>
    <tr>
      <th>UIライブラリ</th> <th>断念の理由</th>
    </tr>
  </thead>
  <tr>
    <td> slick </td> <td>DOMへのアクセスと操作において、vueは仮想DOM (Virtual DOM) ベースのアーキテクチャを使用する一方、slickの技術jQueryは直接DOMにアクセスする古いアプローチを採用していてバグが起こる原因になると考えたため</td>
  </tr>
  <tr>
    <td> Antd vue </td> <td>サムネイルの表示枚数を指定できなかったため</td>
  </tr>
  <tr>
    <td> vue-slick-carousel </td> <td>vue3に対応していなかったため</td>
  </tr>
  <tr>
    <td> vue3-carousel </td> <td>サムネイルを縦方向にスライドするカスタムが難しかったため</td>
  </tr>
</table>

もう少し時間をかければ各ライブラリを細かく検証したり手探りでカスタマイズ方法を見つけられたと思うが、今回は1週間とリミットを設けた。それぞれのUIライブラリを試して結局[Splide](https://ja.splidejs.com/)に落ち着いた。


## Splide
Splide（スプライド）は、モバイルファーストで軽量なJavaScriptライブラリで、カルーセルやスライダーなどの画像とコンテンツのスライドショーを実装するためのツールです。Splideは、直感的なインターフェース、高度なカスタマイズオプション、タッチデバイスに対応しており、ウェブサイトやウェブアプリケーションでスライドショーコンポーネントを実装するための強力なツールとして広く利用されています。 (ChatGPTから引用)

正直、Splideを利用してカルーセルを実装した後に気づいたのだが、Splideの最終リリースが2022年9月でそれ以降あまりメンテされていない印象なので、今後リファクタリングの機会があったらもう一度UIライブラリを見直そうと思う。。

## 以下を参照
実装したコードではなく参考にしたサイトを載せておく。
https://codesandbox.io/s/splide-slider-sandbox-vertical-jls7v?file=/src/components/BCVerticalGallery.vue
Pythonで「Jupyter Notebookの基本操作とショートカットキー」の動作を確認してみた

# 概要

Pythonで「Jupyter Notebookの基本操作とショートカットキー」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/jupyter-notebook/index5.html

# 実装

以下のファイルを作成しました。
```file20231020.ipynb
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50978cd4-df87-43d5-95d1-4b4da549724a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a011ffa-5121-476f-a588-16dd24b99e35",
   "metadata": {},
   "outputs": [],
   "source": [
    "123*48"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3ece9f26-7dbc-4a63-b198-6c7b4d517651",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "bf128bad-f868-4f2c-9ef8-b520197fb0e5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13\n"
     ]
    }
   ],
   "source": [
    "print(10+3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c85e86ba-f76d-445e-a3bb-5f2f780f3370",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "22\n"
     ]
    }
   ],
   "source": [
    "print(34-12)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb7a74e0-105a-46bc-a9a1-34a73cddfe95",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "70cfd46e-3de3-4e70-ad4a-d088eecc5955",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Orange\n",
      "Peach\n",
      "Lemon\n",
      "End\n"
     ]
    }
   ],
   "source": [
    "mylist = [ \"Orange\", \"Peach\", \"Lemon\" ]\n",
    "for val in mylist:\n",
    "    print(val)\n",
    "print(\"End\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4f2b21c-fdd5-47dc-8af9-4b36344c0779",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Finish\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5f489a51-b9cd-4828-8179-502aa54d4c1d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
```

実行画面は以下のとおりです。

![Screenshot from 2023-10-20 17-39-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/a05a311a-f465-eb0d-f755-c7a1a58de48c.png)

# まとめ

何かの役に立てばと。
QiitaのスラッシュコマンドをVSCode上でも再現する

## 概要

10/18の更新において、Qiitaのmarkdownエディタ上で、スラッシュコマンド (スニペット) がサポートされました。

https://qiita.com/release-notes/2023-10-18

下記のように、いくつかの便利なスニペットが追加され、特にdetailsについては毎回コピペしていた私は感動しています。

| 機能 | 説明 |
|:-:|:-:|
| Code block | コードブロックを挿入します |
| Alert | 警告の補足説明を挿入します |
| Warn | 注意の補足説明を挿入します |
| Info | 補足説明を挿入します |
| Comment out | 警告の補足説明を挿入します |
| Details | 折りたたみを挿入します |
| Reference | 脚注へのリンクを挿入します |
| Footnote | 脚注への注釈内容を挿入します |

![](https://camo.qiitausercontent.com/bf86326533f0d85bbbaeeee4f8683a4109dbf4e3/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f38382f37373834336331342d666232392d363762332d666231342d3133656462633162373630302e676966)

このスニペットを、VSCodeでも同じ使用感で使えるようにしたいと思ったので作りました。

## スニペット本体

`cmd+shift+P`でコマンドパレットを呼び出し、`Snipepts: Configure User Snippets` -> `markdonw.json`を選択してください。
その後、開いたファイルに次の内容をコピペしてください。

```jsonc:markdown.json
{
	"Qiita::Code block": {
		"description": "Qiita-style slash commands `/Code block`",
		"prefix": "/Code block",
		"body": [
			"```",
			"$0",
			"```"
		]
	},
	"Qiita::Alert": {
		"description": "Qiita-style slash commands `/Alert`",
		"prefix": "/Alert",
		"body": [
			":::note alert",
			"$0",
			":::"
		]
	},
	"Qiita::Warn": {
		"description": "Qiita-style slash commands `/Warn`",
		"prefix": "/Warn",
		"body": [
			":::note warn",
			"$0",
			":::"
		]
	},
	"Qiita::Info": {
		"description": "Qiita-style slash commands `/Info`",
		"prefix": "/Info",
		"body": [
			":::note info",
			"$0",
			":::"
		]
	},
	"Qiita::Comment out": {
		"description": "Qiita-style slash commands `/Comment out`",
		"prefix": "/Comment out",
		"body": [
			"<!--",
			"$0",
			"-->"
		]
	},
	"Qiita::Details": {
		"description": "Qiita-style slash commands `/Details`",
		"prefix": "/Details",
		"body": [
			"<details><summary>${1:details}</summary>",
			""
			"$0",
			""
			"</details>"
		]
	},
	"Qiita::Reference": {
		"description": "Qiita-style slash commands `/Reference`",
		"prefix": "/Reference",
		"body": [
			"[^KEY]"
		]
	},
	"Qiita::Footnote": {
		"description": "Qiita-style slash commands `/Footnote`",
		"prefix": "/Footnote",
		"body": [
			"[^KEY]: "
		]
	},
    // ...
}
```

## 結果

markdonwを開いて、`/`を入力するとサジェストが出るよ。

:::note warn
QiitaエディタではCode Blockが最優先でサジェストされますが、流石に優先度の順番まではこれではコピーできません。~~気が向いたらより細かいこともできる拡張機能を開発します。~~
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/4f68e6e7-c230-2880-3493-7c697798a76c.png)
ノーコードな言語をつくればいいんだよ

現在俺の中でノーコードというレベルで言えば、flutterをdartを生成する有料flutterflowがあるのだが、そんなの初心者からしたらどうでもいい。最初からなんの言語を生成してとかではなくて、オープンなノーコード言語を作ればいいのだと思う。

※俺の中では、内部でrustを吐き出しているのをイメージしているのだがｗ
なぜか？それはandroid osと相性が良いから？

あと、iosの生成も、そのディベロッパーとか言うキーワードにみんなうんざりしている。
そろそろappleさん、type-cにしたんだし、そっちもお願いしますよ。ｗ

flutter大学とかいう、うざい世の中から脱したいっすね。ｗ
rex0220 項目非表示プラグイン テーブル内項目の非表示

kintone のイベント処理で、テーブル内項目の非表示を行うと一瞬項目を表示後に非表示になります。
項目非表示プラグインでテーブル内項目の非表示を行うと、画面表示時に最初から非表示になりますので、一瞬でも表示させたくない場合に有効です。

# 概要

[rex0220 計算式プラグイン テーブル内集計消費税計算](https://qiita.com/rex0220/items/1767781773589d53ddf5) の操作例を比較します。
計算式プラグインはイベント処理で非表示処理を行うため、一瞬、すべての項目が表示される。
項目非表示プラグインは、CSS で項目を非表示にするため、編集画面表示時に項目が非表示になります。

- 計算式プラグインでテーブル内項目を非表示
    - 一瞬、すべてのテーブル内項目が表示される

![2023-10-20_13h37_48.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/bb19715c-89f4-4251-c27b-881d64314c0c.gif)

- 項目非表示プラグインでテーブル内項目を非表示
    - 編集画面表示時にテーブル内項目が非表示になる

![2023-10-20_13h40_42.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/cefbad37-b14c-48e4-bd28-1adad582c499.gif)

# 項目非表示プラグインの設定

![2023-10-20_17h21_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c65fb475-ef3c-5274-83e5-036640e31115.png)
AI-102試験対策のまとめ「責任あるAI」

## はじめに
Azure AI Engineer Associate(AI-102)取得に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AI-102取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください
※勉強しながら投稿しているため、追加で学んだことがあれば随時投稿内容を更新します。

## 試験対策のまとめ
## 責任あるAI
### 公平性
* AIシステムでは、すべてのユーザーを公平に扱う必要がある
* システムによる決定が下記などに基づいてグループ/個人を差別してはならない
    - 性別
    - 人種
    - 性的指向
    - 宗教など
* 例：銀行の融資承認申請をサポートする機械学習モデル

### 信頼性と安全性
* AIシステムを確実かつ安全に実行する必要がある  
* システムが設計通りに動作し、新しい状況にも安全に対応できることが重要  
⇒動作条件に対する厳格なテストと検証が必要となる
* 例
    - 自立走行専用のAIベースのソフトウェアシステム
    - 患者の症状を診断し、処方箋を推奨する機械学習モデル

### プライバシーとセキュリティ
* AIシステムは安全で、プライバシーを尊重する必要がある  
* AIシステムの予測や決定にはデータへのアクセスが不可欠  
⇒データと顧客のコンテンツを保護するための適切な保護機能の実装が必要

### 包括性
* AIシステムはすべての人を支援し、ユーザーを関与させる必要がある
* あらゆる人種と経験を考慮することがAIに義務付けられる
* 開発者が人々を意図せず排除する可能性のある潜在的な障害を理解し対処する必要がある
* 例
    - 聴覚に障碍のある方を支援するために音声テキスト変換を組み込む
    - 視覚に障碍のある方を支援するためにテキスト読み上げを組み込む

### 透明性
* AIシステムは理解可能である必要がある
* ユーザーはシステムの目的/しくみ/想定される制限事項などを充分に認識できる必要がある
* 例：ユーザーに認識させる必要があるもの
    - 機械学習モデルの場合：予測の精度に影響する可能性がある要因
    - 個人データに依存するAIシステムの場合：データの保存/使用方法/アクセス権

### アカウンタビリティ
* すべての人々がAIシステム対して説明責任を持つ
* AIベースのソリューションの設計者と開発者が責任を負う  
⇒ソリューションが明確に定義された下記の枠組みの中で作業する必要がある
    - 倫理的/法的基準を明確に満たすガバナンスと組織の原則
* 組織は下記を提供する内部の審査機関を設置することを検討する必要がある
    - AIシステムの開発と展開に関する監視
    - 分析情報
    - ガイダンス

<br>

* 参考
    - https://learn.microsoft.com/ja-jp/azure/cloud-adoption-framework/strategy/responsible-ai
    - https://learn.microsoft.com/ja-jp/azure/cloud-adoption-framework/innovate/best-practices/trusted-ai
    - https://learn.microsoft.com/ja-jp/training/modules/prepare-to-develop-ai-solutions-azure/5-understand-considerations-for-responsible-ai

## 次の試験対策のまとめ
* **AI-102試験対策のまとめ「Azure AI Language」**

https://qiita.com/fsd-jume/items/6d1fa44e7b16c0cea680

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/65aba5d5514e023fd66d
Chromeで音声が自動再生されなかった原因と対策

自分はwebページやアプリに何かと音を付けたがる癖があるのですが、音声の再生時にちょっと困るChromeの仕様があったので共有しておきます。

## エラー内容
[１時間ごと（０分０秒時点）に鳩の鳴き声がする鳩時計のアプリ](https://ogueki.github.io/pigeon-clock/)を作ってたんですが、音が鳴るときと鳴らない時があり困っていました。
原因を探って1時間ぐらい無駄にしましたが（時間帯か？とかよくわからんことを考えてた）、検証ツールのコンソールを見たらしっかりエラーが出てました。はじめから検証ツールを見るようにしましょう。

エラー文は以下の通りでした。
```
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
```

<b>ユーザーが最初にドキュメントを操作しなかったから、play()が失敗した</b>とのこと。
つまり何かしらの操作をユーザー側で行わないと、音声の自動再生が行われないということですね。これまで自動再生できていた時はクリックか何かを自分が行っていたということでしょう。

また、[Chromeの自動再生ポリシー](https://developer.chrome.com/blog/autoplay/)にはこんな記述がありました。日本語訳すると以下の通りです。

***
Chrome の自動再生ポリシーはシンプルです。
- ミュートされた自動再生は常に許可されます。
- 次の場合、音声付きの自動再生が許可されます。
  　・ユーザーがクリック、タップなどの操作を行った。
　・ユーザーが以前に音声付メディアを再生した場合
　・ユーザーはモバイルのホーム画面にサイトを追加したか、デスクトップにPWA をインストールしました。
- 上位フレームは自動再生許可をiframe に委任して、サウンド付きの自動再生を許可できます。
***

## 対策
ページを開いたユーザーに<b>何かしらの操作をさせるように促す</b>ことが確実な対策になります。
「このページは音声が鳴ります」みたいなウインドウを表示しているwebページはたまに見かけますね。

## まとめ
Chromeで音声が自動再生されなかった原因と対策でした。
最初は不便な制限だなーと思いましたが、<b>サイト開いたとたんに爆音で音楽が鳴るページ</b>とか昔はあった気がするので、そういうものを防ぐためにはいいのかもしれません。
絵文字の見え方がデバイスによって違った話

最近[鳩時計のアプリ](https://ogueki.github.io/pigeon-clock/)を作ってたんですが、その際に初歩的なミスをしてたので反省の記事を書きます。
自分の環境はWindowsです。

## 当初考えていた方法
黒い窓の中に鳩の絵文字を表示する方法を考えてた時に、自分は
「背景が黒なら普段は文字色を黒にして、一定時間だけ白にすればいいな」と考えました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/3ca90535-5830-ad19-eb50-666738c6fcef.png" width=50%>
↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/a492a632-9617-b67f-1919-d6e2e5d7ea35.png" width=50%>

時間になるか「はと」ボタンを押せば鳩が表示されるので、これで完成。かと思いきや…

## デバイスによる見え方の違い
数日後、上司にこのアプリを見てもらってたら
「鳩がずっと出てるよ」との指摘が。
上司の画面を確認させてもらうと確かに鳩がずっと居るし、<b>そもそも鳩の絵文字が全然違う</b>ことが発覚。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/830600c8-5df2-d34d-2db3-16b18836a2b8.jpeg" width=50%>
自分のiPhoneでも確認しましたが同じ現象が起きていました。
この綺麗な鳩の絵文字は色変えに対応しておらず、背景と同化させることができなかったわけですね。
<b>デバイスごとに絵文字の見え方が違う</b>ことを考慮していなかったことが今回のミスの原因でした。

結局、絵文字にdisplay:noneをつけ外しすることで対応しました。

## 他デバイスの絵文字のデザインを確認する方法
他のデバイスでの絵文字のデザインが気になったとき、確認する方法がないか調べてみたところ便利なサイトがありました！
<b>[Emojipedia](https://emojipedia.org/)</b>というサイトで、様々なデバイスやサービスでの絵文字の見え方を確認できます。
たとえば鳩だとこんな感じです。（下にまだまだあります）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/39a6e71f-d15e-54ee-72ed-31a6767bc605.png" width=70%>

微妙なデザインの違いで見え方が大きく変わることもあるので、有効活用していきたいと思いました。
WebのUIをクライアントアプリみたいにショートカットでサクサクと動かす

:::note info
最新のアップデートの詳細はこちら。[New Relic アップデート(2023年9月)
](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202309 "New Relic アップデート(2023年9月)")
:::

# はじめに
エンジニアは作業をどんな時でもサクサクと行いたい。だけど、無駄なことをしたくないはずだ。歴史的にも工夫をすることで、やりたいことを直感的に行える様にしてきた。複数のコマンド処理をスクリプトとしてコマンド化したり、GUIアプリケーションであればショートカットを駆使してきた。好き嫌いはあるけれど、**Ctrl-c**/**Command-c**や**Ctrl-s**/**Command-s**の存在に対して無意味だという人は少ないのでは？(異論はみとめます。)何を言いたいのかというと、みんな大好きショートカット機能が、New Relicのポータル上でも利用することができるように!!

# どんなショートカットが使えるの？
百聞は一件にしかず。やってみることが大事。まずは、[New Relicポータル](https://login.newrelic.com)に早速ログインしてみましょう。ショートカットの難しいところは、知っていること前提の機能というところ。どうやら、<strong>?</strong>を押すことでショートカットのヘルプが表示される様なので試してみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/01660712-d6b1-9856-c855-81034f77c7cc.jpeg" width="70%">


重要なショートカットは、**g**ボタンに合わせて**数字**を入力することで、左側のメニューナビゲーションのメニューにアクセスできるようです。この数字部分はメニューの並び順にそのまま従っている様です。例えば、自分の環境だとBrowserは4番目に配置されているので、**g**に続いて**4**と押すとBrowserのentity一覧を表示することができました。ちなみに、データをクエリするために**Query Your Data**を起動する場合は、数字部分は**1**となりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/65daf8d8-47af-9764-10bd-7f47daccc6c0.jpeg">


**Tips:** マウスのポインタをメニュー部分に持ってくるとメニューの横にショートカットが表示されるので、最初にショートカットを確認すると良いかもしれません。

参照しているページのURLを取得するには、**Ctrl**-**.**(ドット)あるいは、**Command**-**.**(ドット)を押すことで実施できる様です。これは便利です。是非手癖にしてください。
あまり頻繁に使うことがないことを祈っていますが、テクニカルサポートケースを作成するためのページには、**g**の後に<strong>?</strong>を押すことでジャンプできる様です。こちらも覚えておくと便利かもしれません。

# もうひとつ!!
是非覚えて欲しいショートカットがもう一つあります。まずは、手元で**Ctrl-k**/**Command-k**を試して下さい。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534647/f9e8be5b-bacb-08b7-22b5-6856134525b7.jpeg" width="70%">


New Relicポータル上で設定しているアラートやダッシュボード、監視対象といった情報を検索して、関連ページにジャンプすることができます。非常に多くの管理対象がある環境や、トランザクションが大量にありすぎて探すのが大変・・・といった環境で悩んでいた方は是非今すぐにこのショートカットを手癖にしてください。New Relicポータル上での必要な情報へのアクセススピードが信じられないくらいに加速しますよ。

# まとめ
覚えておくと便利そうなショートカットが揃っていますね。この機能はあくまでも便利機能ですが、実際に活用できる機能もどんどんリリースされています。そんな情報をキャッチするためにも、是非New RelicのQiita Organizationのフォローをお願いします。そんな機能を試すための[無料アカウント](https://newrelic.com/jp/sign-up-japan)も利用可能です!!


:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、
新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::

:::note info
無料アカウントの詳細は[こちら](https://docs.newrelic.com/jp/docs/accounts/accounts-billing/account-setup/create-your-new-relic-account/)です。
:::
Vu３で画面遷移後に画面スクロールをしようとしてハマった


### 背景
Vue3での開発中、画面遷移後に表示位置が画面最上部にならなかった。
原因として、SPA（[Single Page Application](https://e-words.jp/w/%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html)）であるため、画面遷移時に前画面の画面表示位置が引き継がれてしまっていた。
画面遷移後に画面最上部までスクロールさせようとしたが、すんなりと実装できなかったため備忘録として残します。

### 試したこと

#### mounted
mountedにscrollTo()を入れ、DOM読み込み後にスクロールさせる。
意図した動作はしなかった。ざっと調べたが、DOMの更新が非同期処理なのが原因らしい。
```vue3:mounted
mounted() {
    window.scrollTo({top: 0, left: 0, behavior: "instant"}); 
}
```

#### nextTick
DOMの更新完了後に処理を実行したい場合に使うものらしい。が、意図した動作はせず、、、

```vue3:nextTick
mounted() {
  this.$nextTick(() => {
    window.scrollTo({top: 0, left: 0, behavior: "instant"}); 
  });
}
```

#### setTimeout
単純に少し待ってみる。想定に近い動作はするが、読み込みが遅いケース等を考慮すると適切な待ち時間がどの程度なのかわからない。何より力技すぎてイカしてないので最終手段とすることに。

```vue3:setTimeout
mounted() {
  setTimeout(() => {
    window.scrollTo({top: 0, left: 0, behavior: "instant"}); 
  },10);
}
```

### 結論
#### afterEach
ページの遷移後に実行したい場合に使うものらしい。想定通りの動きをしているし公式ドキュメントを読んだ限りこれがベストっぽい。

```vue3:afterEach
mounted() {
  $router.afterEach(() => {
    window.scrollTo({top: 0, left: 0, behavior: "instant"}); 
  });
}
```

### おわりに
SPAのページ遷移については気をつけないといけないと改めて感じた。また、Vueのライフサイクルについての知識が乏しいので気が向いたら勉強しないと、、、
setTimeoutに妥協せず最適解に辿り着けたのは満足。
Splunkの基本用語をざっくり説明

### Splunkの用語を理解しよう
※画像はイメージ、数値は一例です。
　　
__・マシンデータ__：各種機器から生成されたデータ（各種サーバ、ネットワーク機器、セキュリティ機器、アプリケーションetc）
![スクリーンショット (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3501557/13718e74-c3b9-1e7d-7f47-961f27567798.png)

　　
__・rawデータ__(生データ)：インデックス化処理前のマシンデータ。最初に記録された状態のままのデータのこと。
![スクリーンショット (29).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3501557/02250620-2550-6b78-506d-41e0e0b87b86.png)
　　

__・イベント__：rawデータをタイムスタンプ(時間)ごとに分割させたデータのこと。
![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3501557/28f6fc1b-4069-0afd-f212-ef663ea8bb21.png)


　　
__・インデックス__：イメージでいうと本の索引みたいな感じ、ほしい情報に素早くアクセスできる機能、イベントを参照してアクセスしてる。
rawデータをインデックス化処理して生成されたデータ

例：
splunkサーチ入力部分に調べたいログの機器名(例:index ="機器名")を入力して検索する。
検索すると対象機器のイベントへアクセス処理(インデックス化)して、膨大なデータ(ビックデータ)の中から必要な情報をピックアップしてくれる。

　　
__・フィールド__：サーチできる「名前と値」の組み合わせのこと。
※SQLでいうカラムと呼ばれる部分に近いです。
![スクリーンショット (28).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3501557/59e11d34-bc66-1857-2c07-426dc5a91e45.png)
【初心者向け】エンジニアになってからよく聞くIT用語を簡単にまとめてみた

## はじめに
こんにちは、2年目のエンジニアです。
エンジニアになってからIT用語をよく耳にして、知らない言葉がちょこちょこ出てきて
実際に勉強をしてみたら、IT用語多すぎる。。。ってことで
エンジニアになってから実際によく耳にするIT用語を簡単にまとめてみようと思いました！
職場によって変わるとは思いますが、是非みてください

## 概要
この記事は私がエンジニアになってから実際によく聞くなと感じたIT用語とその意味を簡単にまとめた記事となります。
これからエンジニアとして働く人たちは是非参考にしていただきたいと思います。

# IT用語一覧
ここでの紹介ではざっくりと簡潔に説明をしていくのでもっと知りたいと思ったら、是非調べてみてください！
では、早速紹介します。

### ソフトウエア
コンピュータを動かすプログラムの総称。
パソコンや機器に読み込ませることで作業を実行させることができるデータのことです。

### ハードウエア
装置や機械、設備といった、システムの物理的な部分のことです。

### iOS
Apple社がiPhone向けに開発提供しているOSです。

### Android
Googleが携帯情報端末向けに開発したOSです。

### アジャイル開発
システムやソフトウェアを開発する方法の一つ。
実装とテストを短期間で小さな単位で繰り返すスピーディーな開発方法です。

### ソースコード
ソースコードとはコンピュータープログラムを表現するテキストのことです。

### コーディング
プログラムの設計書通りにソースコードを記述していく作業のことです。

### インタプリンタ型
プログラミンをする時は、人間の言葉で記述します。
その人間の言葉をコンピューターの言葉に翻訳する時にソースコードを一行ずつ翻訳しながらプログラムを実行するものが「インタプリタ型」です。

### コンパイラ型
プログラミンをする時は、人間の言葉で記述します。
その人間の言葉をコンピューターの言葉に翻訳する時にソースコードを全てまとめて翻訳してからプログラムを実行するものが「コンパイラ型」です。

### インフラ
一般的なインフラの意味とは異なり、IT業界ではサーバーやPCといったハードウエアと、OSやインターネット、データベースなどのソフトウエアの二つを指します。

### SI
システムインテグレーションの略称。
情報システムの要件定義、設計、開発、導入、運用保守、管理などをまとめて担うサービスです。

### SES
「System Engineering Service」の略称。
システム開発の業務に関して技術者を派遣するサービスのことです。

### API
「Application Programming Interface」の略称。
Webサービスやソフトウエア、アプリケーション同士をつなぐインターフェースのことです。

### クライアント
ビジネス用語で使われるものと意味は異なり、情報を受け取るコンピューターやソフトウエアのことを表します。

### デバッグ
プログラムなどのバグを見つけて、修正していく作業のとこです。

### フロントエンド
Webサイトなどでユーザーが直接目にする部分のことです。

### リリース
新しいサービスや商品、アプリなどの開発を発表することです。

### UI
デザインのことです。
テキストフォント、ボタンなどビジュアルで認識できるものは全てUIです。

# 最後に
以上となります。
まだまだありますが、今回はこのくらいで。


### 参考サイト
https://type.jp/et/feature/15949/
Vue.jsのprovideとinjectの使い方

## 初めに
provideとinjectは、親コンポーネントから子コンポーネントへデータや関数を直接渡すことなく伝達を行うことができます。
ですので、基本的には値を腹持ちさせておいて、後からその値を使うような場合に使用します。

## 使用例
```:ファイル構成
.
.
├─ store
|  └─ index.js (伝達元の親)
├─ pages
│  └─ test.vue　(伝達先の子)
└─ main.js

```
親の```storeData```を、子の```test.vue```で使えるようにしたいと思います。

まず```provide```と```inject```は同じキーで紐づける必要があるため、キーが他のものと衝突しないように、```Symbol```を用いてユニークなキーを作成します。

そしてexportでstoreDataとtestKeyをセットします。

```javascript:index.js
const storeData = "hogehoge"

export default {storeData};
export const testKey = Symbol("testKey");
```

次に全ての子コンポーネントで利用可能にするために、main.jsで以下を設定します。
importの際、defaultでexportされたものは{}なしで良くて、それ以外は{}ありでimportします。
また、fromでファイル名を指定しない理由は、ファイルの指定がない場合その階層のプライムファイル名がimportされ、index.jsは親フォルダのファイル名としてimportされる為です。

```javascript:main.js
import test, { testKey } from "@/store";
createApp(App).provide(testKey, test);
```
子コンポーネントで使用します。
```javascript:test.vue
import { inject } from "vue";
import { testKey } from "@/store";

const store = inject(testKey);
console.log(store.storeData);
```
Laravel Seeder 実行前に全テーブルデータを削除する

## 環境

- PHP: 8.2.11
- Laravel: 10.16.1
- MySQL: 8.0.32

## 背景

```shell-session
$ php artisan db:seed
```

連続して実行すると場合によっては重複レコードが生成されて困る。

```shell-session
$ php artisan migrate:fresh --seed
```

これで解決するがマイグレーションファイルが増えるとすごく時間がかかってしまう。

## 解決方法

シーダー実行前に全テーブルをtruncateする。

### 準備

```shell-session
$ composer require doctrine/dbal
```

このライブラリがないとデータベースの全テーブル名を取得できずエラーになります。

### DatabaseSeeder.php を編集

```php:database/seeders/DatabaseSeeder.php
<?php

declare(strict_types=1);

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Foundation\Application; // 追記
use Illuminate\Foundation\Testing\DatabaseTruncation; // 追記

final class DatabaseSeeder extends Seeder
{
    use DatabaseTruncation; // 追記

    public function __construct(protected readonly Application $app) // 追記
    {
    }

    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        $this->truncateTablesForAllConnections(); // 追記
        $this->call(UserSeeder::class);
    }
}
```

## 使い方

```shell-session
$ php artisan db:seed
```

## 補足: DatabaseTruncation トレイト

https://github.com/laravel/framework/blob/10.x/src/Illuminate/Foundation/Testing/DatabaseTruncation.php

テストの時に使用するトレイトです。
データベースの全てのテーブルデータを削除してくれます。(`migrations` テーブルを除く)

## 参考

https://qiita.com/ucan-lab/items/55ec5c341fb5c228fe14

昔書いた記事のアップデートです。
Java 条件分岐

## 条件分岐

### 比較演算子  
| 値 | 内容 | 読み方 |
|:-:|:-:|:-:|
| a == b | aとbが等しいか | イコール |
| a != b | aとbが等しくないか  | ノットイコール |
| a < b | aよりbが大きいか | 小なり  |
| a > b | aよりbが小さいか | 大なり  |
| a <= b |  aがb以下か | 小なりイコール |
| a >= b |  aがb以上か | 大なりイコール |

### 論理演算子  
| 値 | 内容 |
|:-:|:-:|
| a && b | aかつb  |
| a \|\| b | aまたはb  |

### if文

#### 1. if
```
if ( 条件1 ) {
    条件1がtrueの処理
}
```

#### 2. else if

```
if ( 条件1 ) {
    条件1がtrueの処理
} else if (条件2) {
    条件1がfalseかつ条件2がtrueの処理
} else if (条件3) {
    条件1がfalseかつ条件2がfalseかつ条件3がtrueの処理
} ・・・以降いくつでも連結可
```

#### 3. else

```
if ( 条件1 ) {
    条件1がtrueの処理
} else if (条件2) {
    条件1がfalseかつ条件2がtrueの処理
} else {
    すべての条件に当てはまらないときの処理
}
```

### switch文

#### java14前
```
switch (比較元の値) {
  case 比較する値1: 
      値1に一致した際の処理
      break;
  case 比較する値2: 
      値2に一致した際の処理
      break;
  default : 
      すべて値に一致しないときの処理
      break;
}
```


#### java14以降
```
switch (比較元の値) {
  case 比較する値1 -> 値1に一致した際の処理
  case 比較する値2 -> 値2に一致した際の処理
  default -> すべて値に一致しないときの処理
}
```


### 3項演算子

```
条件 ? 条件がtrueの場合の処理 : 条件がfalseの場合の処理
```
【Anaconda】Windows版Jupyter Notebookでライブラリが見つからないときの対処法

# エラーの概要

先日私がWindows版anacondaからJupyter Notebookを使用していた際、インストールしたはずのPythonのライブラリが見つからずModuleNotFoundErrorエラーになってしまったのでその対策を書いておきます。

# 環境

> OS : Windows 11 Insider Preview 
> PC : ROG Flow X13
> 使用ソフト・ライブラリ : Anaconda Navigator, Anaconda Prompt, Jupyter Notebook

# 対策手順

Windows版では基本的にPowerShellではなくAnaconda Promptを使っています。基本的にはCommand Promptみたいなものです。

## pip install ではなくconda installコマンドを使う

Windows版では基本的にanacondaないしjupyterでpythonのライブラリを使う場合はAnaconda Prompt上でconda installコマンドでライブラリをインストールします。pipでインストールするとanacondaが認識できなかったりするので💦

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2081812/1ae77c1b-c9d5-c412-ee45-fb735eaac538.png)

またjupyterやanaconda自体もここからでないと上手く起動しなかったです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2081812/9cc12542-87ed-b3c0-5cf8-0da5255113c7.png)

ためしにleadmapを動かしてみて、上記の対処法で何とか動かすことができました💦

それではよきjupyterライフを(?)
Apex 「System.LimitException: Too many SOQL queries: 101」エラーが出る前に気を付けること

どうもTABEです！

salesforceの開発をやっていると
よく出るエラーとして「System.LimitException: Too many SOQL queries: 101」があると思います。
これは一つのトランザクションでクエリを100件以上発行している時に発生するエラーです。

ガバナ制限というsalesforceには制限があり
それに沿ってクエリやCRUDの回数を一つのトランザクションで制限されています。

有名なのがForループにSOQLやInsert、Update、Deleteを入れることは最悪です。
これはほぼ何処かしらでエラーになると言っても過言ではないので、Apex開発をする方は必ず押さえておきましょう。

そこでずっと前から思っているApexを書くときにガバナ制限を考慮する書き方として
以下の2点は気をつけたいなと思っています。


①何も条件なしにSOQLを発行していないか？

これはかなりやりがちなのですが、商談のレコード情報が欲しいからすぐにSOQLを作って取得してしまう。ちょっと待ってください！！！それって何かの条件の上で起動する処理ではないですか？

対象のレコードを更新した時に起動と単純な起動にしていると、開発を重ねていくと、フローや色々なトリガーが重なって、新しい処理を追加した時に、1年前に作ったApexやフローを修正しないといけなくなります。

なのでなるべく、そのSQOLを発行する前に何か条件はないか？要件を確認して調整しましょう！
必ず、、、保守をやっていたら1年後に絶対に痛い目を見ます。。。


②UserInfoメソッドを最初に必ず起動する様にしない

これもかなり良くやる処理だと思います。。。
```UserInfo.getProfileId()```
を使ってログインユーザのプロファイルのIDを取得することが出てくると思います。

これってSQOLを裏で発行しているんですよね。何も考えずに最初にこのコードを書きまくっていると、それが重なってそこかでクエリの発行数が簡単に100件を超えます。
テストクラスとかでも、これのせいでデータを作れなくなったり結構しました。あー既存の処理変更しないと。。。って


他にもあると思いますが、自分が結構気にしているのはこの二つです！

少しでも参考になれば幸いです！
ではまた！


salesforceの解説用動画をUdemyで作っています。
興味のある方は見てもらえたら嬉しいです。
よろしくお願いします！

https://www.udemy.com/course/salesforce-basics-j/?referralCode=4200CF5D86BBE3ABF2D4
Kotlin の例題　(OpenWeather から気温を取得）

こちらのプログラムの App.kt を改造しました。
[Kotlin の例題　（HTTP クライアント と JSON)](https://qiita.com/ekzemplaro/items/6e378bd4ebafd87089ef)

## 例題

[OpenWeather](https://openweathermap.org/) から APIKey を取得して下さい。

宇都宮の今の気温を取得

```bash:get_temp.sh
URL="https://api.openweathermap.org/data/2.5/weather"
KEY="fff12345********"
#
http $URL"?q=Utsunomiya&units=metric&appid="$KEY | jq .main.temp
```

実行結果

```text
$ ./get_temp.sh 
16.42
```

## プログラム

```kt:app/src/main/kotlin/try03/App.kt
/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package try03


import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

import com.google.gson.JsonObject

class App {
    val greeting: String
        get() {
            return "本日は晴天なり!"
        }
}

fun main() {
	println("*** start ***")
    val baseUrl = "https://api.openweathermap.org/data/2.5/"

    // Retrofitを設定
    val retrofit = Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    // Retrofitサービスを作成
    val service = retrofit.create(ApiService::class.java)

    // HTTPリクエストを送信
	val cityName = "Utsunomiya"
	val apiKey = "********"
	val units = "metric"
    val response = service.fetchWeather(
	cityName,
	apiKey,
	units
	).execute()

    if (response.isSuccessful) {
        val jsonData = response.body()
        val data = jsonData?.getAsJsonObject("main")
        println(data)
	val temp: String? = data?.get("temp")?.asString
	println("temp = $temp")
    } else {
        println("HTTPリクエストが失敗しました。ステータスコード: ${response.code()}")
    }
	println("*** end ***")
}

// Retrofitインターフェースを定義
interface ApiService {
    @GET("weather")
    fun fetchWeather(
    	@Query("q") cityName: String,
        @Query("appid") apiKey: String,
    	@Query("units") units: String
	): Call<JsonObject>
}
```

## 実行結果

```text
$ ./gradlew run

> Task :app:run
*** start ***
{"temp":16.42,"feels_like":15.5,"temp_min":16.42,"temp_max":16.42,"pressure":1008,"humidity":53,"sea_level":1008,"grnd_level":993}
temp = 16.42
*** end ***

BUILD SUCCESSFUL in 1s
2 actionable tasks: 1 executed, 1 up-to-date
```
2023 Supership サマーインターン 広告コースに参加しました

# はじめに
Supershipはマーケティングテクノロジー事業(インターネット広告事業など)とデータイネーブラー事業(検索事業など)を手掛けている企業で、今回私が参加したのはマーケティングテクノロジー事業のほうのアドテクチームの広告コースになります。

# 自己紹介
普段はセキュリティに関することをやっていて、Webに関しては、Web開発を少しやったことがあり、CTFのWeb問も何度かCTFに参加して解いたことがあったりするという感じのレベルです。
今回は広告技術やWeb開発を勉強する目的でインターンに参加させて頂きました。

# 目標
今回は2人1組のチームでSSPを実装することを目標としており、技術選定から行いました。
開発目標として、Level1からLevel3までレベルを分けて課題内容が用意されていました。

# 課題内容
課題内容はこちらの[リンク](https://docs.google.com/document/d/1INGuGGwCETo1T_QKxEkzDOjzOqQ0swf9Ni1GQi7ciIw/edit?usp=sharing)から参照できます。
ざっくりとした内容を先程のリンク先から引用すると次のような内容となります。


> 1. 前準備: 技術選定
> 2. Level1: 媒体とSSP 間とSSP と DSP 間のやり取りの実装
> 3. Level2: アドテクの基本的な集計指標である売上、impression 数、click 数をレポートする UI を実装
> 4. Level3: 不正課金対策を行いつつ、より多くのリクエスト捌けるように SSP を改修

# 1日目
自己紹介、開発準備などを行いました
また、チーム分けの発表がされ、パートナーが決まりました。

# 2日目
開発が本格的に始まり、まずは課題の理解や技術選定などに取り組み始めました。

# 3～4日目
技術選定に関して、Level3におけるパフォーマンスの点で、Golangが優れているだろうとのことでGolangが候補の一つにありました。また、パートナーが実装経験があり、実装が比較的容易であると考えられたPHPも候補になりました。我々のチームではこの2つの候補で迷い、中々決めることができず、2つの言語で並行して実装することで、どちらにするかを決定しようとしましたが、この並列はチームの力を分散してしまい、あまり効率的ではありませんでした。最終的には4日目の昼にPHPと決定したのですが、技術選定と並列開発にかなり時間をかけてしまいました。
PHPを採用した理由としては、Golangに関する経験はお互いにあまりなく、限られた期間内に最後まで実装しきる自信が得られなかったためです。また、広告技術は今回のインターンなどでしか学ぶことができないので、PHPを採用することで最後まで実装しきり、広告技術を学ぶことを重要視しました。

私はPHPの経験がなかったので、パートナーに親切に教えてもらいながらLevel1の開発をしました。

# 5日目～9日目
最終的には、Level2及びLevel3の途中までやりきりました。
Level2の実装をしている頃にはPHPやLaravelにもある程度慣れてきました。
Level3に関しては、まずはパフォーマンスチューニングから取り掛かり、NginxやPHPの設定ファイルなどが開発用のものであったので、色々調べながら設定を変更しました。
不正対策としては、クッキーなどを用いてセッション管理を行ったりして行う予定でしたが、時間の関係上実装しきれず時間を迎えてしまいました。

# 感想
完走した感想としては、まず、土日やインターン終了後も大学院のほうの演習などが入っており、ほぼ休みがない中で取り組んだので体力的に少し大変な面もありましたが、結果として、Level3の途中まで到達でき、スキルとしても、広告技術、PHP/Laravel、Git/GitHub、Docker、パフォーマンスチューニングなどを学ぶことができ、非常に満足する結果を得ることができました。
途中、コードレビューを社員の方々から頂くことができたのですが、様々なことを指摘して頂き、非常に参考になりました。やはり、プロのエンジニアの方々からアドバイスなどを頂ける機会は学生にとって貴重なことだと思います。また、技術選定から開発まで適宜相談しながらではありますが、基本的に僕らが方針を決めることができたので、自由度の高さもこのインターンの魅力だと思いました。

# 最後に
2週間にわたって様々な面でサポートしてくださったSupershipの社員の方々に感謝申し上げたいと思います。貴重な機会を頂き、本当にありがとうございました。

チームのパートナーに関して、僕がPHP/LaravelやGit/GitHubの知識が足りず、様々な面で迷惑を掛けてしまったなと少し反省しています。また、PHPを採用したことで、当初、僕があまりタスクをこなせないことなどを心配してくださっていたことは非常に優しい方だなと感じました。自分としては、サポートのお陰でタスクもある程度こなすことができたので全く問題なかったと思っていますし、やはりPHPを採用してよかったと思いました。今回のインターンでは、最高のパートナーと組めたと思っています。ありがとうございました。


# フィードバックを受けて
インターンの最後にフィードバックを頂くことができました。
自分としては、今回のインターンでWeb開発に関する知識などを数多く得ることができましたが、開発の世界の知識や技術はまだまだあるのでこれからもそれらを勉強していければなと思いました。
KitsuをDockerで試してみる

# Kitsu (キッツ)とは
[https://www.cg-wire.com/kitsu](https://www.cg-wire.com/kitsu)
[CGWire](https://www.cg-wire.com/)社が開発しているオープンソース (AGPLv3) のプロダクション管理プラットフォームです。
制作チームとワークフローをコラボレーションするもので、界隈ではパイプラインツールとも呼ばれます。
このジャンルで有名なのは Autodesk の ShotGrid (旧 Shotgun)、ライセンス料が高いことでも有名。

# Kitsu を試してみる
Docker を使用して Kitsu を実行して試してみることができます。

```
docker run -d -p 80:80 --name cgwire cgwire/cgwire
```

これで、 http\://localhost 経由で Kitsu にアクセスできるようになります。

次の情報でログインします。

- Email：admin<span>@</span>example.com
- Password：mysecretpassword

# Kitsu の日本語表示
Kitsu の表示言語はすべて英語ですが、ログイン後に Profile から LANGUAGE を変更することで日本語表示になります。
※この時に TIMEZONE も変更しておくと良いでしょう。

# ドキュメント
Kitsu Documentation
[https://kitsu.cg-wire.com/](https://kitsu.cg-wire.com/)

Kitsu API Documentation
[https://zou.cg-wire.com/](https://zou.cg-wire.com/)


# さいごに
Kitsu を試すにあたり、日本語の情報が見つからなかったため、取っ掛かりとしてこのページを書きました。
【Flutter】Cloud functionsの「the data couldn't be read because it isn't in the correct format」というエラーの解消法

# はじめに
Cloud  functionsの関数をFlutterから呼び出す際に、`the data couldn't be read because it isn't in the correct format`というエラーが出て、解決方法を調べたので共有します。

# 前提

Flutterで呼び出し側のコードは下記を想定しています。
```dart
try {
  final result = await FirebaseFunctions.instance.
    httpsCallable('helloWorld')
    .call();
  print(result);
} catch (e) {
  print(e.toString());
}
```

# 解決方法
サンプルのコードは以下のようになっていると思います。
```index.ts
export const helloWorld = functions.https.onRequest((request, response) => {
  functions.logger.info("Hello logs!", {structuredData: true});
  response.send("Hello from Firebase!");
});
```

上記のコードを流用して使っていると、onRequestが使われているのでエラーになります。
エラーを解消するには、onCallを使うと解消できます。
戻り値は、`response.send`ではなく、Jsonを返す必要があります。
```index.ts
export const helloWorld = functions.https.onCall((request, response) => {
  functions.logger.info("Hello logs!", { structuredData: true });
  return {
    message: "Hello from Firebase!"
  };
});
```

https://stackoverflow.com/questions/62577983/flutter-firebase-cloud-functions-the-data-couldn-t-be-read-because-it-isn-t-in

https://stackoverflow.com/questions/51066434/firebase-cloud-functions-difference-between-onrequest-and-oncall
JavaScript オプション引数のデフォルト値を指定したい

JavaScript の オプション引数的にオブジェクトのvalue側の値をデフォルト値で指定したい．
よくやりたくなるけど，すぐ忘れるのでメモ．

```javascript
// 呼び出し
func1()

// 定義
function func1({a: 100, b: 200}) {
  // a => 100 になってる
}
```

こんな感じでやりたい．

そもそも MDN に書いてある．

```javascript
function func1({a = 100, b = 200} = {}) {
  console.log(`${a}, ${b}`)
}

func1() // => 100, 200
func1({a: 20}) // => 20, 200
```

## Refs

- [デフォルト引数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Default_parameters)
    - > 既定値のある分割代入の引数
      > 既定値の代入を、分割代入表記で行うことができます。
      > 
      > これを行う一般的な方法は、空のオブジェクト/配列をオブジェクト/配列に分割代入することです。例えば、 [x = 1, y = 2] = [] とします。 このようにすることで、空の配列/オブジェクトを関数に渡しても、あらかじめ設定した値を保持することができます。

- [分割代入 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
nvmでnode16からnode18にするときエラー発生

nvmでnode18を入れようとしたらエラーが発生した。
nvmを再インストールしたら解決したので記録として残す。

# nvmでnode18を利用しようとしてエラー

```console
> nvm version
1.1.9
```

```console
> nvm install 18
Downloading node.js version 18.18.2 (64-bit)... 
Extracting...
Complete


Installation complete. If you want to use this version, type

nvm use 18.18.2
```

インストールまではできたが、`nvm use 18.18.2`で利用しようとするとエラーが発生した。

```console
> nvm use 18.18.2
exit status 5: �A�N�Z�X�����ۂ����܂����B

exit status 1: ���ɑ��݂����t�@�C�����쐬���邱�Ƃ͂ł��܂����B
```

#### 補足：エラーの文字化け

以下の方法でPowerShell文字コードを変えてみたが文字化けが解消しなかった。

```console:文字コード確認
> chcp
現在のコード ページ: 932
```

```console:文字コード変更
> chcp 65001
```

# nvmの最新を再インストールしたら解決した。

1. Windowsの「インストールされたアプリ」からインストール済みのnvm v1.1.9をアンインストール
1. nvm v1.1.11を再インストール

https://github.com/coreybutler/nvm-windows/releases

```console
> nvm version
1.1.11
```

```console
> nvm install 18.18.2
Downloading node.js version 18.18.2 (64-bit)... 
Extracting node and npm...
Complete
npm v9.8.1 installed successfully.


Installation complete. If you want to use this version, type

nvm use 18.18.2
```

```console
> nvm use 18.18.2
Now using node v18.18.2 (64-bit)
```

```console
> node --version
v18.18.2
```
GoでヒープやメモリやGCの状態を出力してみた

## 今回のゴール

ヒープやメモリやGCの状態を関数内に配置して、数値で観測してみた。

## 実装

最終的なコードは以下です。

```go
package main

import (
	"fmt"
	"runtime"
)

// 状態を出力する関数
func printMemStats() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	// 現在のヒープの状態を出力
	fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
	// ヒープに割り当てられた累計量
	fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
	// システムがGoランタイムに割り当てたメモリ量
	fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
	// そしてガベージコレクションの回数
	fmt.Printf("\tNumGC = %v\n", m.NumGC)
}

// バイトをメガバイトに変換するヘルパー関数
func bToMb(b uint64) uint64 {
	return b / 1024 / 1024
}

// メイン関数
func main() {
	printMemStats()

	// 思い処理なので注意
	data := make([]int, 1<<25) // 2^25要素のスライスを作成
	for i := range data {
		data[i] = i
	}
	printMemStats()
}

// Alloc = 0 MiB   TotalAlloc = 0 MiB      Sys = 6 MiB     NumGC = 0
// Alloc = 256 MiB TotalAlloc = 256 MiB    Sys = 267 MiB   NumGC = 1
```

1. `func printMemStats()`  : `printMemStats`という名前の関数を定義しています。この関数は引数を取らず、何も返しません。
2. `var m runtime.MemStats` : `runtime.MemStats`型の新しい変数`m`を宣言しています。この型はGoランタイムが使用しているメモリに関する統計情報を保持します。
3. `runtime.ReadMemStats(&m)` : `ReadMemStats`関数を呼び出して、現在のメモリ統計情報を取得し、それを先ほど宣言した変数`m`に格納しています。
4. `fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))` : `Alloc`フィールド（現在ヒープに割り当てられているバイト数）の値をメガバイト単位で表示しています。これは`bToMb`関数を使用してバイトからメガバイトに変換されます。
5. `fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))` : 同様に、`TotalAlloc`フィールド（ヒープに割り当てられた累計バイト数）の値も表示しています。
6. `fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))` : `Sys`フィールド（Goランタイムがシステムから取得した合計メモリ）の値も表示しています。
7. `fmt.Printf("\tNumGC = %v\n", m.NumGC)` : 最後に、`NumGC`フィールド（これまでに実行されたガベージコレクションの回数）の値を表示しています。
8. `func bToMb(b uint64) uint64 { return b / 1024 / 1024 }` : バイトをメガバイトに変換するための補助関数`bToMb`を定義しています。この関数は64ビット符号なし整数を引数に取り、同じく64ビット符号なし整数を返します。
9. `func main() { printMemStats()` : メイン関数で、最初に`printMemStats()`関数を呼び出して現在のメモリ統計情報を表示します。
10. `data := make([]int, 1<<25)` : 2^25要素（約3300万要素）のスライスを作成し、それを変数`data`に格納します。これは大量のメモリを消費する処理です。
11. `for i := range data { data[i] = i }` : 作成したスライスの各要素にそのインデックスと同じ値を設定します。
12. `printMemStats() }`: 最後に再度`printMemStats()`関数を呼び出して、メモリ消費が多い処理後のメモリ統計情報を表示します。

## ヒープとは

> 
> 
> - Goコンパイラでメモリを確保できない値がヒープにエスケープされる。
> - GCされる。
> - Goコンパイラとランタイムによって、いつ使用され、いつクリーンアップされるか仮定できない。
> - サイズが動的に決定される。

## スタックとは

> 
> 
> - ローカル変数で、ポインタではないGoの値が割り当てられる。
> - GCされない。
> - GCを使わないので効率的。
> - レキシカルスコープに結びついたメモリが割り当てられる。
> - Goコンパイラが、メモリを確保する。
> - goroutineスタックに格納される。

## 所感
GC観測できて、すごってなりました。発言できたのは、プログラムが思ったより重い処理だったのでメモリ解放を起こしたのかなと思っています。

## スタックも出力できる

[Go 製ソフトウェアでメモリ使用量の多い関数を特定する - Cybozu Inside Out | サイボウズエンジニアのブログ](https://blog.cybozu.io/entry/2019/06/11/170000)

## 参考記事

[Goのスタックとヒープについて - SO Technologies 開発者ブログ](https://developer.so-tech.co.jp/entry/2022/07/28/112845#スタック)

[runtime package - runtime - Go Packages](https://pkg.go.dev/runtime)
Mavenのアップデート可能なライブラリ一覧を表示する

# はじめに

チームではストーリー着手前になにかライブラリをバージョンアップするという週間があるのですが、そこで使うコマンドを毎回調べていたのでまとめます

# 問題

`pom.xml`に書いているライブラリでどのライブラリがアップデート可能で、最新版がどのバージョンなのか一覧で出したいと思いました

# 解決方法

```
$ mvn versions:display-dependency-updates
```

とくにプラグインなどインストールは不要で使えました！

# おわりに

ぱっとみQiitaになかったり、情報が古く不安があったので載せてみました！
Vueのwatchがどーしても効かない時。そんな時にはココをチェックしてくれ

## 対象とする読者
Vueのwatchが色々試したけど効かなくて困っているひと

## まえおき
もうVueを使うようになって7年は経つだろうか。
自分で言うのもなんだが、もうだいぶ慣れている。

コードが美しいだとか、仕様に対する造形が深いとかそういう観点では未熟者ではあるけれど
Vueは僕にとって日曜大工する時の工具みたいなもので、「こういうWeb画面を作りたいなー」と思った時にだいたい実現出来る素晴らしいツールだ。

とはいえ使い方の分からない機能も多く、プラスドライバーがあるのにマイナスドライバーを使うなんて事もしょっちゅうである。

しかし、いざ道具をちゃんと使おうとすると、見つからなかったり、うまく使えないなんてトラブルにでくわす。

僕にとって Vue の watch というのは、そこそこ頻繁に使うわりに上手く使えなくなる時がある道具の一つなのだ。

長年使っていることもあって watch を使用するうえで注意しなければならない事はある程度心得ているつもりだったが、久々にしっかり悩まされたので共有したい。

## watchの心得
僕が普段から watch を使う時に気をつけているのはこのあたりだ。

+ 対象のプロパティは最初から定義しておく。
+ pushとか$setとかそういうのを使う。
+ deepを使う。
+ deepを使うときは handler を使う。

すぐ見つかる情報なので本記事では詳細は省くことにする。 
（こういった情報を紹介してくれている人には感謝してもしきれない。何度も救われたし、これからもお世話になる。）

## いよいよ本題
僕はいつものようにwatchを実装したものの、うんともすんとも言わなくて困った。
そのときのコードっぽいものを書いてみたので眺めてみて欲しい。 


##### 問い合わせフォームをイメージして書いたコード
```javascript:toiawase.js
  // ＜＜ 省略 ＞＞

export default {
  name: 'toiawase_form',
  components: {},
  data () {
    return {
      dataLoading: true,
      faq_list: [],
      input_form: {
        category: 1, // 問い合わせ種別
        message: "", // 問い合わせ内容
        placeholder: "", // 入力例
      },
    }
  },
  props: {
    customerId: Number,
  },
  mounted () {
    this.init()
  },
  watch: {
    'input_form.category': {
      handler: function (newVal) {
        // 種別が変更されたら入力例を変えてあげようかな
        console.log(newVal) // いったんログを出すか。。。しかし、ここが実行されない、、
      },
      deep: true,
    },
  },
  filters: {
    numberFormat (num) {
      // よくコピペして用意するやつ。数字に3桁ごとにカンマを付ける。本記事の主旨とは直接関係ない。
      if (num) {
        return num.toString().replace(/(\d)(?=(\d{3})+$)/g , '$1,')
      }
      return num
    },
  },
  computed: {
    filteredFaqList () {
      // 読み込んだFAQの中から問い合わせ種別に関係あるものだけ表示しよう
      let list = []
      for (let row of this.faq_list) {
        if (row.category == this.input_form.category) {
          list.push(row)
        }
      }
      return list
    },
  },
  watch: {
    customerId (newVal, oldVal) {
      this.loadCustomerData()
    },
  },
  methods: {
    init () {
      // FAQデータを読込む
      this.loadFaqList()
    },

  // ＜＜ 省略 ＞＞

```

コメントに書いてある通り、問い合わせ種別に変更が発生してもログが出なかった。

問い合わせ種別というのは セレクトボックスで指定できるイメージだ。
v-modelでプロパティと紐づいていると思ってほしい。

すこし無理やりだが、下記のように値を変更してもダメだった。
```javascript
this.$set(this.input_form, 'category', '2')
```

なぜダメなのかお分かりだろうか。
エラーは出てなくてwatch以外はしっかり動作していた。

すぐに分かった人はすごい。
同様の経験をしたことがある人かもしれない。一緒に酒を飲みたい。

僕はあの手この手で値を変更してみたり、watchについて調べ直したり
functionの書き方を変えてみたり、ただの文字列型にしてみたり、ブラウザのキャッシュを消してリロードしているかとか、スペルミスが無いかとか、関係ないコードを更新していないかとか、ブラウザを変えてみたり、馴染むのに時間がかかるのかなとか呟いてみたり。

ざっと半日は費やしてしまった。

で、ようやく気づいたのが 末尾付近。 **methodsの手前**
<font color="#808080">watchを2回書いてしまっている。。。</font>
エラーとか出ないから注意して欲しい。


少しだけ言い訳させてほしい。実際のコードはもっと色々と書いてあって、だいーーーぶ離れていたのだ。

僕は半日を棒に振ってしまった。。
しかし今日は金曜日。こういった不具合を来週に持ち越さなかったのはエンジニアにとって素晴らしいことだと思う。

この記事を読んでくれた方々にも、いつもより良い週末が訪れますように。
Antrea CNI をインストール・アップデートする

# Antrea とは

Antrea とは、オープンソースの Kubernetes CNI で、L3/4/7 のネットワーキングとセキュリティ機能を Kubernetes クラスターに提供するものです。オープンな仮想スイッチとして長い実績を誇る Open vSwitch をデータプレーンに利用しています。

https://github.com/antrea-io/antrea

本記事では、Antrea を Kubernetes クラスタにインストール、アップデートする方法をご紹介します。

# Antrea のインストール

## 新しい K8s クラスタを準備  

今回は `kubeadm` を使って Antrea 用の Kubernetes クラスターを新たに準備しました。このあたりを参考にしています。  
https://thinkit.co.jp/article/18188

Master 1台と Worker 2台を構成しましたが、CNI を適用する前は以下のように `NotReady` となります。

```bash
$ kubectl get node
NAME             STATUS     ROLES           AGE   VERSION
k8s-master-201   NotReady   control-plane   1d    v1.25.5
k8s-worker-202   NotReady   <none>          1d    v1.25.5
k8s-worker-203   NotReady   <none>          1d    v1.25.5
```

## クラスターに Antrea を適用

CNI として Antrea を適用します。Antrea の初期セットアップについてはこちらもご参照下さい:  
https://github.com/antrea-io/antrea/blob/main/docs/getting-started.md

今回は Antrea v1.12.0 を使うので、以下のように指定して適用します。

```bash
$ kubectl apply -f https://github.com/antrea-io/antrea/releases/download/v1.12.0/antrea.yml
```
Latest を適用したい場合は以下でも構いません。

```bash
$ kubectl apply -f https://raw.githubusercontent.com/antrea-io/antrea/main/build/yamls/antrea.yml
```

Antrea CNI を適用すると Node が `Ready` になりました。

```bash
$ kubectl get node
NAME          STATUS   ROLES                  AGE   VERSION
k8s-master    Ready    control-plane,master   1d    v1.25.5
k8s-worker1   Ready    <none>                 1d    v1.25.5
k8s-worker2   Ready    <none>                 1d    v1.25.5
```

### antctl のインストール  
`antctl` は Controller を介して Antrea の設定や状態を確認するためのコマンドラインツールです。今後必要になるかもしれないので最新バージョンをインストールしておきます。以下は 1.12.0 Linux 版の場合です。   

```bash
$ curl -Lo ./antctl "https://github.com/antrea-io/antrea/releases/download/v1.12.0/antctl-linux-x86_64"
$ chmod +x ./antctl
$ mv ./antctl /usr/local/bin
```
`antctl` でバージョンを表示してみます。インストールした `antctl` と Antrea Controller のバージョンが表示されます。
```
$ antctl version
antctlVersion: v1.12.0
controllerVersion: v1.12.0
```

# Antrea のアップデート

## K8s クラスタの確認

以前用意した Antrea クラスターを最新の Antrea にアップデートする手順の例をご紹介します。
現在のクラスタの状況は以下のようになっています。
```bash
$ kubectl get nodes
NAME             STATUS   ROLES                  AGE    VERSION
k8s-master-201   Ready    control-plane,master   118d   v1.25.5
k8s-worker-202   Ready    <none>                 118d   v1.25.5
k8s-worker-203   Ready    <none>                 118d   v1.25.5
```

## Antrea のアップグレード

ここでは、Antrea を　1.9.0 から 1.12.0 にアップグレードします。念のため、`anctl` コマンドで現在のバージョンを確認します。
```bash
$ antctl version
antctlVersion: v1.9.0
controllerVersion: v1.9.0
```
Antrea v1.12.0 を使うので、以下のように指定して適用します。

```bash
$ kubectl apply -f https://github.com/antrea-io/antrea/releases/download/v1.12.0/antrea.yml
```
antctl も同じようにアップグレードします。(Linux用の場合)
```
$ curl -Lo ./antctl "https://github.com/antrea-io/antrea/releases/download/v1.12.0/antctl-linux-x86_64"
$ chmod +x ./antctl
$ mv ./antctl /usr/local/bin
```
antctl で新しいバージョンが適用されていることを確認します。 
```bash
$ antctl version
antctlVersion: v1.12.0
controllerVersion: v1.12.0
```
Vue.jsで定数を切り出して使うやり方

## 定数を複数のコンポーネントで使いたい

Vue.jsでTodoアプリを作っていた時に、「未実施」などのステータスを定数で管理したいなと思った。

自分が作っていたコンポーネントの構成では、ステータス定数を複数のコンポーネントで使用するため、外に切り出すことにした。

そのやり方のメモ

## 定数ファイル

まず、/srcディレクトリの下に/constディレクトリを作成した。
その下にstatuses.jsというJSファイルを作成し、その中で定数を定義

```javascript:/src/const/statuses.js
export const statuses = {
    NOT_START: { "id": 0, "value": "未実施" },
    DOING: { "id": 1, "value": "処理中" },
    COMPLETED: { "id":2, "value": "完了" }
}
```

## コンポーネントで読み込む

さっき定義した定数ファイルをコンポーネントでimportする。

```js:/src/components/Todo.vue
import { statuses } from ../const/statuses
```
この時、{}を付けないとエラーになったので注意

これで、コンポーネントの中で定数を使うことができる！

```js:/src/components/Todo.vue
const firstStatus = statuses.NOT_START;
```
Xcode15 iOSアプリiPadをサポートから外す方法

初めてリリース作業をした際に、ストアのスクリーンショットでiPadを対象としていないアプリなのに、スクリーンショット必須となっていた為、何かしら設定しなくて良い方法がないか探しました。

iPadをサポートから外す方法です。


Xcode１５です。

![スクリーンショット 2023-10-20 14.21.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/740834d2-80d0-0658-fecd-c7719ade73aa.png)

Generalを開き、Supported Destinationsを見ます。
青くなっているiPadをクリックして下のマイナスをクリックするとiPadをサポートから外せます。


こちらを行うとiPadのスクリーンショットは必須ではなくなりました。
MFCで画面を画像取得するようなソフトウェア作成メモ書き

との事でメモしたけど
別でMFCインストールしないとイケナイのね(^_^;)

でそこで出来たMFCにOKってボタンつけて画像取得ってしたいけど

http://www13.plala.or.jp/kymats/study/MULTIMEDIA/ScreenCapture.html

これ使えるのかな？？？？