OmniAICreator/Qiita-1.07M huggingface dataset:
Provide/Injectの使い方/コードサンプル/注意点【備忘録】

親から孫など、離れたコンポーネント間で値を渡す場合は、provide/injectを使うことができます。

## 公式Doc

https://ja.vuejs.org/guide/components/provide-inject.html

## 親側（Provide：提供）
```ParentPage.vue

<template>
  <ChildComponent />
</template>

<script setup lang="ts">
import ChildComponent from 'src/components/ChildComponent.vue';
import { provide } from 'vue';

const func = (val:ArgsType):ReturnType => {
  ...
}

provide('key1', 'params');
provide('key2', func);
provide('key3', (): void => {
    console.log('fugafuga')
  }
);

</script>
```

## 子側（Inject：注入）
```ChildComponent.vue

<template>
  {{ key1Inject }}
  {{ key2Inject!(hogehgoe) }}
  {{ key3Inject }}
  {{ key3Inject!() }}
</template>

<script setup lang="ts">
import { inject } from 'vue';

const key1Inject = inject<string>('key1');
const key2Inject = inject<(val:ArgsType) => ReturnType>('key2');
const key2Inject = inject<() => void>('key3');
const hogehoge: ArgsType = ...;

if (key1Inject) {
  key1Inject;
  ...
}
if (key2Inject) {
  key2Inject(hogehoge);
  ...
}

</script>

```

## TypeScript環境で使う場合の注意点
### 親子間で型の同期が取れない
TypeScript側では親子の型情報を見てくれません。
書き間違えてもエラーの指摘がされないので、慎重に使う必要があると思います。

### Inject側の型情報は書くべき
子で受け取る際に、ジェネリクスで型情報を入れることができます。
これをやらないと子の中で型指定の恩恵が受けられません。

無くても動きはしますが。。。

### undefinedの可能性を指摘される（if文や非nullアサーション演算子で回避が必要）
子コンポーネントでは、確実に値が渡ってくるか判別できません。
そのため型情報としては、```Type | undefined```となります。
undefinedを回避するための記述が必要です。

### template内での使い方にはいくつか種類がある
引数を取らず、値をそのまま使う場合は、非nullアサーション演算子が不要なようです。
Python ココフォリアClipBoardAPI用データ作成クラス

ココフォリアのコマを外部から入力する手段としてClipboard APIが提供されているのですが
まいかいこのClipboard APIのフォーマットに合わせた辞書形式のデータを手打ちしており、結構面倒だったので
最低限このデータは絶対入力するものをある程度簡単にまとめてクラス化しました。

使用方法としては下記クラスをインスタンス化したら頭にset_が付いている各メソッドから
データを書き込んでいき、データの書き込みが終わったところでtxt_outで出力という流れです

ステータスとパラメータは辞書を格納した配列を入力するのでそこだけ注意が必要です。
なぜかココフォリアのドキュメントは英語でしか解説されていないので少しばかりてこずりました。


```python cocofolia_api.py

import json


class ClipApi:
    # ココフォリアClipboard APIのテンプレートをインスタンス化
    def __init__(self):
        self.data = {
            "kind": "character",
            "data": {
                "name": "no-name",
                "memo": "",
                "initiative": 0,
                "status": [{'label': 'HP', 'value': '4', 'max': '4'},
                           {'label': 'AP', 'value': '4', 'max': '4'}],
                "params": [{'label': '持ち物', 'value': '財布'},
                           {'label': '性格', 'value': 'ツンデレ'}],
                "active": True,
                "secret": False,
                "invisible": False,
                "hideStatus": False,
                "color": "#ffffff",
                "commands": "",
            }
        }
        

    # キャラクター名
    def set_name(self, name: str):
        self.data['data']['name'] = name

    # メモ（改行がそのまま反映されるので文字列でデータを用意する）
    def set_memo(self, memo: str):
        self.data['data']['memo'] = memo

    # イニシアティブ（整数型でないとデータが反映されないので注意する）
    def set_initiative(self, inis: int):
        self.data['data']['initiative'] = inis

    # ステータス（次の形の配列を用意するキーは固定なのでほかのキーは使用しない
    #   {'label': 'ラベル名', 'value': '現在値', 'max': '最大値'})
    def set_status(self, status: []):
        self.data['data']['status'] = status

    # パラメータ（次の形の配列を用意するキーは固定なのでほかのキーは使用しない
    #   {'label': 'ラベル名', 'value': '値'})
    def set_params(self, params: []):
        self.data['data']['params'] = params
    # チャットパレット（改行込みの文字列でデータを用意する。１行ごとにコマンドとして認識されるので改行文字列でOK）
    def set_commands(self, commands: str):
        self.data['data']['commands'] = commands
    # ステータスを非公開にする
    def set_secret(self, secret: bool):
        self.data['data']['secret'] = secret
    # 発言時キャラクターを表示しない
    def set_invisible(self, invisible: bool):
        self.data['data']['invisible'] = invisible
    # 盤面キャラクター一覧に表示しない
    def set_hide_status(self, hide_status: bool):
        self.data['data']['hideStatus'] = hide_status
    # キャラクター表示文字色の設定
    def set_color(self, color: str):
        self.data['data']['color'] = color
    # 入力されたデータをClipBoardAPIの対応書式で文字列出力
    def txt_out(self):
        return json.dumps(self.data, indent=4)
```

ステータスとパラメータは辞書を格納した配列を入力するのでそこだけ注意が必要です。
```python
#※ネクロニカのデータでのサンプルです
 # ステータスのサンプル
 [{'label': 'たからものへの未練', 'value': '3', 'max': '4'},
  {'label': 'PC1への未練', 'value': '3', 'max': '4'},
  {'label': 'PC2への未練', 'value': '3', 'max': '4'}
  ]
 # パラメータのサンプル
 [ {'label': 'ポジション', 'value': 'アリス'},
   {'label': 'メインクラス', 'value': 'ステーシー'},
   {'label': 'サブクラス', 'value': 'ステーシー'},
   {'label': '武装', 'value': '2'},
   {'label': '変異', 'value': '2'},
   {'label': '改造', 'value': '1'}
  ]
```
なぜかココフォリアのドキュメントは英語でしか解説されていないので少しばかりてこずりました。
2つのCSVファイルから対数スケールの散布図を作る方法

# プログラムについて
ChatGPTを使って，2つのCSVファイルから対数スケールの散布図を作るプログラムを作りました．

# 環境
- MacBook Air(M1, 2020)
- Python 3.8.8

# プログラム
```python:ScatterPlot.py
import pandas as pd
import matplotlib.pyplot as plt
import sys
import numpy as np

# コマンドライン引数からファイル名を取得する
file1_name = sys.argv[1]
file2_name = sys.argv[2]

# CSVファイルを読み込む
df1 = pd.read_csv(file1_name)
df2 = pd.read_csv(file2_name)

# 軸名をCSVファイルから取得する
x_label = df1.columns[0]
y_label = df1.columns[1]

# 散布図を作成する
plt.scatter(df1[x_label], np.log10(df1[y_label]), label='1', s=6)
plt.scatter(df2[x_label], np.log10(df2[y_label]), label='2', s=6)

# グラフのタイトルと軸ラベルを設定する
plt.xlabel("x")
plt.ylabel("$log_{10}(r)$")

# 凡例を表示する
plt.legend()

# PNG形式で保存する
plt.savefig('test.png')
```

# 実行結果
今回はテストとして，大きさの異なる２つのデータ(test1.csv, test2.csv)を用意しました．
そのため，対数表示にしています．必要なければ，np.log10()を削除してください．


```:実行例
$python3 ScatterPlot.py test1.csv test2.csv 
```
作成された図は以下のようになっています．

![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2758310/f1ae239d-85c9-9faa-48bd-53bd2da32de9.png)
トラウマだったハッカソンにUnityでリベンジし、結果残した話


# はじめに
春休みはハッカソン沢山参加し、エンジニアだけでなく、プランナー&ディレクターにも挑戦したかったため、一年前に参加したハックツハッカソンに参加しました。ハックツの特徴は、十分な技術力を持ってないと結果が残せない点。去年参加したときは、初めてのチーム開発で特に役割も決めず、とりあえずコードを頑張って書いていこう！という意気込みで参加しました。しかし、Xcode上でgitの管理する段階でつまずき、コンフリクトやデータの復旧に費やすことしかできませんでした。そんな中、周りはAIや機械学習など、とんでもなくハイレベルな技術を扱っていて、発表するのがとても恥ずかしかった覚えがあります。

今回参加したイベントの詳細

https://cup.hackz.team/allo/



# 前回のハッカソンから改善したこと
改善したところは、スプレットシートやNotionでタスクの優先順位を明確にし、ひとつひとつの機能をメンバーと擦り合わせしたことです。この方針を採用した理由は後述します。

![スクリーンショット 2023-03-15 15.00.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609178/e11f5b0d-7758-d954-c974-062805df37d2.png)


![スクリーンショット 2023-03-15 15.01.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609178/605957f2-c08d-a747-b538-8e959e8a682e.png)



# 結果＋作品に対する評価書のコメント
プロジェクト管理＋使った技術が評価され、**最優秀賞**を頂くことができました。

作った作品はこちら

https://topaz.dev/projects/5c984db734864ea4d073

イベント主催者からのFB([こちら](https://hackz.team/news/3iMxZIYdwhlaNkH31P592Q)からの引用)

:::note info
＜どりーからのコメント＞
watnowから参戦の3人チーム！
プロダクトはUnity上の3Dワールド内を歩き回り、お題の写真が撮影された場所を探し出すというゲーム！
国交省が出している新宿区の３Dモデルを利用して、新宿のエリア内を探すというものになっている。
このチームはなんと言ってもプロジェクト管理が素晴らしく、優先順位付の仕様書や進捗ボード(Notion)を用意していた。
3Dモデルが重いので、Occlusion Cullingを用いて見えていない部分は描画しないように作っていたところも偉かった。
:::



企業様・メンターさんからのFB

:::note info
2日目の段階で、基本的なところは動作しており、そこそこゲームとして成立していた(?)。現場経験のあるメンバーがいて工程管理を違和感なくやっていそうのもok　デモがよかった カメラにうつっていない部分を消すという技術を組むなど、ゲームのUX向上に必要な技術を考え実行しているのもgood
:::

:::note info
プレゼン技術・完成度が非常に高かった。 技術領域がわからなすぎたが、完成度の高さとコードを見て推測した。 プロジェクト管理がちゃんと行われていることの効果が強く出ていると感じた。
:::

:::note info
デモの見せ方含めてプレゼン上手。 成果物含めて、中間発表での細かい報告、機能を小分けにして実装する計画力等素晴らしいと思った。 普通に1ユーザーとしてプレイしてみたい。
:::

:::note info
クオリティが高い！ プロジェクト仕様書から作成して、管理までメンバー内で行って1次、2次開発と現場と遜色ない開発ができているのが素晴らしいです。
:::

:::note info
技術は申し分なく、ゲームの完成度もとても高かったです。
:::

:::note info
パフォーマンス改善に注力した部分など、工夫したポイントを分かりやすく発表されており良かったと思います。 幅広く様々な技術に取り組んでおり、スムーズな動作を実現させた様子が素晴らしかったです。
:::

:::note info
ゲームとしてちゃんと成り立っている，UIなども凝っている点がいいなと思いました パフォーマンスを維持するための工夫などもされており，ゲームにおいて技術的に重要な部分も考慮されているのが良かったです
:::

https://twitter.com/YY_Frank27/status/1636009568085090304


# ハックツハッカソンから学んだこと
メンバーのモチベーションの管理がいかに重要かを学びました

実は事前開発の段階では、全く異なるアイデアでプロジェクトを進めていました。

そこで、今回の学びを得るきっかけともなった一本のDMが届きました。そのDMでは、プランナーの自分に向けて、「**今置かれてる環境がつまらなく、タスク内容や作品の方向性をもう少し変えて欲しい**」という内容でした。

原因は、アイデア出しの会議をDMをくれたメンバーを除く2人でやってしまったため、これから作るゲームが明確でなく、何を作るのかもわからないまま、ハイレベルなタスクを課していたからだと考えています。

ここから行ったアクションとしては、３人で改めて企画会議を改めて行い、タスクの優先順位をメンバーにも明確化し、自分でタスクを決める方式を採用した（スプレットシートにコア機能、α・β機能一覧を載せた）。

1. **タスクの詳細を誰でも見れる**
2. **周囲の人がどのレベルをこなしているのかを見せる**
3. **タスクを自分で選ぶことができる**

これら3つを採用したおかげで、質の高いモチベーションを維持でき、短い期間でも完成まで持っていくことができました。

# 次の目標
日本ゲーム大賞への挑戦！！！
HALの学生さんたちのレベルがとても高かったため、一緒に参加できるのが楽しみです！
TypeScript vs JSDoc という対立は存在しない、と思った話

# はじめに

[Svelte] の開発者 Rich Harris さんの Twitter にて、[SvelteKit] は JavaScript で書かれているという話が話題になっていました。

https://twitter.com/Rich_Harris/status/1639344836766576640

:::note info
> Svelte は TypeScript から切り替えていますか？これは間違いですよね？
> https://thenewstack.io/rich-harris-talks-sveltekit-and-whats-next-for-svelte/

いや、この記事は正しい。SvelteKitはJSで書かれ、ソースコードとして配布され、ビルドステップはなく、生産性に奇跡的な効果をもたらしています。
:::

じゃあ無理して [TypeScript] を使わなくても [JSDoc] で代用できるってこと？
と思ったら勘違いでした。

※2023/4/6 追記：[こちらの Dev Vlog](https://www.youtube.com/watch?v=MJHO6FSioPI&t=95s) でも言及されていました。

# TL;DR

- 製品コードは [TypeScript] で書かないほうが都合が良い場合がある。
- でも、[TypeScript] の型定義は使いたい。
- だから、JavaScript + [JSDoc]、必要であれば .d.ts ファイルで型定義。

# TypeScript で書かないことによる利点

https://twitter.com/Rich_Harris/status/1639367285205880833

:::note
トランスパイルせずにテストを実行できる。コードスニペットをdevtools/node REPLにコピーペーストすれば、そのまま動作する。
:::
確かに！コピーしたコードから型情報を削除する手間を省けますね。



https://twitter.com/Rich_Harris/status/1639367359155650561

:::note
バグを修正する場合、reproをクローンしてパッケージをリンクし、修正されるまでrepro/node_modules/@sveltejs/kitの中でソースコードを直接編集し、修正したものを直接コミットすればいいのです。
:::

私は [SvelteKit] の開発者ではないのでよくわからなかったけれど、node_modules 内のソースコードを修正してそのままコミットする、ということが開発効率アップにつながってるみたいですね。

# TypeScript による型チェックの利点を捨てる必要はない

https://twitter.com/Rich_Harris/status/1639651923128209408

:::note
> 私は同意しているわけではありません。例えば私のIDBライブラリはLOCの観点でほとんどが型であり、それらの型をエクスポートできることは便利であり（JSDocでそれができるか）、それらの型のためのテストを書くことは問題を捕らえた https://github.com/jakearchibald/idb/blob/main/src/entry.ts
>
> ただ、JSDocのタイピングが過小評価されていることには同意します。

.d.tsファイルにインターフェイスなどを記述し、tscでエクスポートされた関数などの型を生成することができます（example config https://github.com/Rich-Harris/devalue/blob/master/tsconfig.json#L5-L7 )。SvelteKitには、その型に対するテストがあります。

失うものは何もない、鎖だけだ！
:::

.d.ts ファイルであれば製品コードとは関係なく [TypeScript] の機能をフルに利用できますね。


# 私が思う TypeScript の嫌いなところ

私が [TypeScript] の素人だからかもしれませんが、型情報が複雑に混在しているせいで、肝心のビジネスロジックが読みづらく感じています。まぁ、これは私の能力の問題の可能性が高いですが...。

いずれにせよ、JavaScript + [JSDoc] + .d.ts パターンであれば、この点も解消できます。

# まとめ

[JSDoc] は製品コードをトランスパイルせずに出荷できるにもかかわらず型チェックも可能な仕組み、と捉えればその利点を理解できました。また、[TypeScript] と対立するものではなく .d.ts ファイルを使用することで共存できることも理解できました。

そして、`TypeScript vs JSDoc` という対立は存在しないこと。あるとすれば、製品コードファイルにおける `.ts vs .js` であると理解しました。

今後は、検証の意味も込めて、JavaScript + [JSDoc] + .d.ts パターンで実装してみようと思います。:smiley:


[Svelte]:https://svelte.dev/
[SvelteKit]:https://kit.svelte.dev/
[TypeScript]:https://www.typescriptlang.org/
[JSDoc]:https://www.typescriptlang.org/ja/docs/handbook/jsdoc-supported-types.html
Maltego Transform 開発メモ setNote(str)

```python
output_entity.setNote("これはメモです。<i>テスト</i>")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325297/940ec952-c7d8-462b-389e-82ce790de738.png)

* Officeのコメントのような吹き出しがつく
* 右ペイン上の「Notes」はHTMLがレンダリングされる
ESP32 UARTについて

# これまでの知識
これまで様々なマイコンを使ってきました。古くはi8080 , Z80 , m6809 等で、この頃は各種インターフェイスはSIO , PIO , i8255 , i8251 等の外部デバイスを使っていました。
決まったIOアドレスで動作する様ハードウェアを設計するので一度決めたらそのアドレスは変わりません。
その後、uPD7810 , HD64180 , H8/300H , ATmega , PIC等のワンチップマイコンを使用する様になり、外部にインターフェイス用のデバイスを配置することはほぼなくなりました。使い方は色々ですが、デバイスメーカーが決めたピンで決められたレジスタを操作するという感じです。
つまり、一度決めたもの、或いはメーカーが決められたピン等はずっと固定ということ。
構成が変更になったりした場合は設計変更や修正作業等で大変でした。
# ESP32のUARTは？
最近ESP32をいじりはじめましたが、UART等の機能ピンはデフォルトではそのピン番号が決められていますが、ある程度自由にその場所を変更できるというものです。
右のサイトを見ると　https://picalittle.tech/esp32-devkit_uart_test/
『引用：UART1は別のピンにアサインして使用』とあります。
最初ここ読んだ時、へ？どゆこと？(・o・)と頭の上に？？が湧きました(^_^;)
UART0はDevKitの場合、USBに変換されデバッグ用のシリアルモニタに使用したりと、一部制約はありますが、ピンの位置を変更できるのですね。
昭和からマイコンを使ってるおじさんにとってはかなりびっくりです😲
例えば以下の Serial1.begin()では RxDを16、TxDを17にしていますが、22と23に書き換えるとちゃんとそのピンで通信する様になります！
`
Serial1.begin(9600, SERIAL_8N1, 16, 17);  // 制御基板との通信条件 RXD:16 / TXD:17
`
これまでATmega2560等IO点数の多いデバイスをよく使っていたのでESP32はピン数が少なくやりくりが大変そうだなぁという印象がありました。
IOが増やせるわけではないですが、ピンアサインの変更という機能は色々便利に使えそうです。
こういうことが出来るということは、内部に複雑なマルチプレクサ回路が構成されているということでしょう。超微細加工技術が為せる技と思います。
# 後記
IO点数は少ないという感が否めませんが、とにかく「速い」ということで、74HC165や74HC595等のシフトレジスタで入出力拡張することで対応できるかなと思っています。
PWM出力が必要なところはこの手は使えませんけどね。
ESP32アーキテクチャを理解するのにわかりやすいサイトがあったのでURLを貼っておきます。
（フランス語なので翻訳して見ていますｗ）
https://espacerm.com/webgen/esp32intro/
ChatGPTのAPIでリアルタイム出力した場合としない場合の体感速度の違いを比較する

以下は、OpenAIのWebサイトのようにChatGPTからの回答を「リアルタイム出力(逐次出力)」した場合と、「まとめて出力」した場合の体感速度の違いを比較するため(だけ)のPythonコードです。

プロンプトより質問文を入力すると、「リアルタイム出力(逐次出力)」でAPIを呼び出した後に「まとめて出力」のAPI(計2回)を呼び出すので、どの程度違いがあるかをご自身で比較体感いただけるかと思います。
(APIの負荷軽減のため間に3秒ウエイトを入れています)

```python
import openai
import time

# APIキー設定
openai.api_key = "Your Openai API Key"

# エンジンの種類
engine = "gpt-3.5-turbo"

# API待機時間(秒)
wait_sec = 3 

# 逐次出力版
def get_response_stream(prompt, engine):

    responses = openai.ChatCompletion.create(
        model=engine,
        messages=[
            {"role": "user", "content": prompt}
        ],
        stream=True # ストリームアクセス
    )

    # ストリーミング処理
    message = ""
    for response in responses:
        chunk = response['choices'][0]['delta'].get('content')

        if(chunk==None):
            pass
        else:
            print(chunk, end='', flush=True) # 逐次出力
            message += chunk

    return message.strip()

# まとめて出力版
def get_response(prompt, engine):

    response = openai.ChatCompletion.create(
        model=engine,
        messages=[
            {"role": "user", "content": prompt}
        ]
    )

    message = response["choices"][0]["message"]["content"]
    print(message) # まとめて出力

    return message.strip()

# ユーザーとの対話を続ける
while True:

    # 質問入力プロンプト
    user_input = input("ChatGPTへの質問入力(Enterで終了):\n")
    if not user_input:
        break

    # 逐次出力
    print("\n↓↓↓ ChatGPTの回答を逐次出力(ctrl+cで強制終了) ↓↓↓\n")

    get_response_stream(user_input, engine)

    print("\n\n↑↑↑ ChatGPTの回答を逐次出力 ↑↑↑\n")

    # API待機時間
    time.sleep(wait_sec)

    # まとめて出力
    print("\n↓↓↓ ChatGPTの回答をまとめて出力 ↓↓↓\n")

    get_response(user_input, engine)

    print("\n↑↑↑ ChatGPTの回答をまとめて出力 ↑↑↑\n")

    # API待機時間
    time.sleep(wait_sec)
```
※APIキーの書き換えとOpenAIライブラリのインストール(```pip install openai```)を忘れずに！

ChatGPTは呼び出すたびに出力結果や出力形式が結構異なる(内容的には概ね同じ)のでレスポンス時間だけを測定しても、あまり意味が無いので、実際に速度の違いを体感するためのコードを用意しました。

(比較用質問文の例)「〇〇の良いところ悪いところ」「〇〇の特徴５つあげて」等

当たり前ですがChatGPTの回答文が長くなればなるほど出力完了までの待ち時間が長くなってしまうので、リアルタイム出力(逐次出力)は必須ですね。ちなみに、ChatGPTが教えてくるサンプルコードやネット上で紹介されているサンプルコードの多くは「まとめて出力」する方のタイプが多いので、ChatGPTのAPIをはじめて触る方のご参考になればと思います。
Node.jsで使用中のOSSバージョン一覧を作成するライブラリ


```bash
$ npm install -g license-checker
$ license-checker --production --csv
"module name","license","repository"
"async-retry@1.3.3","MIT","https://github.com/vercel/async-retry"
"async@3.2.4","MIT","https://github.com/caolan/async"
"asynckit@0.4.0","MIT","https://github.com/alexindigo/asynckit"
...
```

https://github.com/davglass/license-checker


* ライセンスも出してくれる
* プロダクションのみで指定できる
* package.jsonに指定しているライブラリが使っているライブラリまで表示される
* CSVなど色々な形式で出力できる

便利です。
[Rails][Render.com] render-build.shの読込みに失敗した場合の対処


render.comでデプロイを(手動で)実行した際、
`/usr/bin/env: ‘bash\r’: No such file or directory`
というエラーが出た場合の対処案です。
render-build.shのファイルフォーマットを`unix`にします。
(改行コードをLFにします。)
ログに上記のようなエラー(bashの後に`\r`がある)場合は、ファイルフォーマットを見直してみてください。

## 環境
- OS: Windows11
- rails
- editor: gVim9

## 不具合内容
Railsチュートリアルの第６章をやっているときに発生しました。
Render.comのサイト上でBuild Commandを設定し、シェルスクリプトを渡した際にデプロイが失敗しました。
この作業は本番環境のRender.comで自作したWebアプリを実際に構築する、手順書をbinに入れたrender-build.shに指定しています。
この状態でデプロイが失敗し下記のログが出力されました。

```renderのログ
(日時)  ==> Cloning from https://github.com/...
(日時)  ==> Checking out commit ... in branch main
(日時)  ==> Downloading cache...
(日時)  ==> Running build command 'bin/render-build.sh'...       // bin/にあるrender-build.shを実行します。
(日時)  /usr/bin/env: ‘bash\r’: No such file or directory        // ん？そんなファイル(or ディレクトリ)はないよ。
(日時)  ==> Build failed 😞                                      // 残念ながら失敗です。
(日時)  ==> Generating container image from build. This may take a few minutes...
(日時)  ==> Transferred 99MB in 8s. Extraction took 3s.
```

ログの下から4行目に
/usr/bin/env: ‘bash\r’: No such file or directory
とあります。bashの後ろに`\r`とありますので、ここがエラーの原因だと思われます。
bashを呼び出すようにこちらは指定しているつもりですが、bash\rを呼び出そうとしてそんなファイルはないよと言っているようです。

render-build.shをWindowsのgVimで作成しました。改行コードはWindowsに合わせてCR+LFにしています。
Render.comはLinuxなのかはわかりませんが、CRLFのLFのみが改行として認識し、CRが残されたというのが私の推測です。

## 解決策
render-build.shの改行コードをCR+LFからLFにします。
vimではファイルフォーマットを(dosから)unixにすることで改行コードが変更されます。
```vim
:set fileformat?        " 現在のファイルフォーマットを確認します。

:set fileformat=unix    " dosになっていたらunixに変更する
:w                      " ファイルフォーマットの変更は保存したタイミングで行われるので保存します。
```

修正したファイルをGitHubにpushし、Render.comでデプロイを実行します。

## おわり
上記に記したデプロイが失敗する原因はあくまでも私の推測です。
詳しい方がいらっしゃいましたらご教授いただければ幸いです。

もしかしたら改行コードが問題ではなかったかもしれませんが、何度かファイルフォーマットをdosとunixを切り替えてデプロイをしてみましたが、dosだと失敗し、unixだと通ることは確認しています。

## 追記
Railsチュートリアルは最後まで行い、完成版のデプロイも済んでいますが、render-build.sh以外にファイルフォーマットが問題になったことはありませんでした。他のファイルはすべてdos形式です。

また、ファイルフォーマット(fileformat: 改行コード)に似ている、エンコーディング(fileencoding)についてですが、私はすべてutf-8にしています。
Windowsのvimでは設定によってはファイルがcp932やutf-8が自動で設定されることがあります。
日本語が含まれていないファイルはutf-8になり、一文字でも日本語(全角文字)が入るとcp932になってしまうなどです。
cp932だとrailsのテストの段階で指摘されると思いますので、デプロイの失敗にはつながらないと思いますが、文字化けが発生したらエンコーディングを疑ってみてください。
IBM Cloud: Classic Infrastructureの新規に作成したsubnetにSSL-VPN(IBM Cloud提供のVPN)経由でアクセスできない時の解決方法


# 問題

SSL-VPNを利用しているにも関わらず、新規に作成したsubnetに接続できない。例えば、確かにClassic Infrastructure上のサーバーにこの`10.44.35.2`というIPアドレスを割り当てているのに、SSL-VPN経由で通信できない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/04c9c5ba-9186-5e95-4134-7f9260ecfcd8.png)

```
syasuda@mymac ~ % ping 10.44.35.2
PING 10.44.35.2 (10.44.35.2): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
Request timeout for icmp_seq 4
```

# 解決方法

1. Manage -> Access(IAM) -> User -> 自分のユーザー における、`Classic Infrastructure`タブにおいて、VPN subnetsが`Auto-assign`になっていることを確認。きっとこの`Auto-Assign機能`が正しく機能していないのだと思われる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/7acd9121-c4cd-114c-d2fb-b8bde5cedf25.png)
2. `Auto-Assign`をOffにしてSave ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/38bd8b39-de60-4acf-2744-26dc2542950c.png)
3. 再度`Auto-Assign`をOnにしてSave ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/61bcb4a6-0d4c-24d3-5ad5-fb2be9d29026.png)
4. SSL-VPNが起動中の場合は一旦切断した後に、再度SSL-VPNを接続


```
syasuda@mymac ~ % ping 10.44.35.2
PING 10.44.35.2 (10.44.35.2): 56 data bytes
64 bytes from 10.44.35.2: icmp_seq=0 ttl=53 time=111.749 ms
64 bytes from 10.44.35.2: icmp_seq=1 ttl=53 time=28.980 ms
64 bytes from 10.44.35.2: icmp_seq=2 ttl=53 time=35.189 ms
64 bytes from 10.44.35.2: icmp_seq=3 ttl=53 time=26.882 ms
64 bytes from 10.44.35.2: icmp_seq=4 ttl=53 time=33.647 ms
```
スプレッドシートで自動で更新日付を入れる方法

# はじめに
Googleスプレッドシートをタスク管理等で使用していて、自動で更新日付を入れてくれる方法ないかな～と思っていて
プログラミングに無知な方でも簡単に出来る方法がございましたので記事にします。


# 手順

①まずGoogleスプレッドシートを開きます。(もちろん既存のファイルでもOK)

②メニューの [拡張機能] から [App Script] を選択します。

③以下の画面が開きますので、画面に表示されている「function myFunction() { }」は全て削除します。

![AppScript.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/9c1ac299-7ca7-15f2-78d4-78f2d26d43c7.png)

④以下のコードをコピペします。
　「シート名」と「列」と書いてあるところは任意のものに変更してください。
　今回はシート名はシート1、列はCに変更したとします。

```javascript:

function autoUpdateDate()
{
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート名');
  var currentRow = sheet.getActiveCell().getRow();
  var currentCell = sheet.getActiveCell().getValue();
  var updateRange = sheet.getRange("列" + currentRow);
  if (currentRow > 1) {
    if (currentCell) {
      updateRange.setValue(new Date());
    }
  }
}
```

⑤[プロジェクトを保存] を押します。
![スクリーンショット 2023-03-28 145822.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/8ae3b765-56be-c178-8527-5575291cb6ba.png)

⑥一番左のメニューの目覚まし時計マークの [トリガー] を押し、画面右下の [トリガーを追加] を押します。

⑦[イベントの種類を選択]で 「編集時」を選択し、保存を押します。
![イベントの種類を選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/a14e551e-6cb1-09f4-93fe-769e135f8a55.png)

⑧保存を押すとGoogleアカウントへのアクセス許可のダイアログが表示されますのでアカウントを選択し、[許可] を押します。

⑨トリガーに設定が追加されたことが確認出来たら、スプレッドシートの画面に戻り、文字を入力してみると指定した列に入力したときの日時が自動で入力されました。
![完成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/e3d61b7f-9627-7d1e-151f-fd40f95ded82.gif)


# 最後に
コピペで設定できてしまうので、プログラミングが分からない方でも参考になれば幸いです。
Hexabase Flutter SDKの使い方（リンクデータの取得）

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業向けのBaaS（Backend as a Service）を提供しています。認証やデータストア、ファイルストレージ、リアルタイム通知などの機能があり、企業向けのシステム開発に必要な機能をまるっと提供しています。

APIはREST APIとGraphQLを提供しています。そのAPIをラップしたSDKも開発を進めています。SDKは現在、TypeScriptとDart向けに開発しています。Dart向けのSDKは、もちろんFlutterでも利用できます。

この記事ではFlutter SDKについて、インストールとデータストアでのリンクしたデータの取得方法について解説します。

## パッケージとソースコード

パッケージはpub.devで公開しています。

[hexabase | Flutter Package](https://pub.dev/packages/hexabase)

ソースコードはGitHubにて公開しています。ライセンスはMIT Licenseです。

[hexabase/hexabase-dart: Hexabase SDK for Dart & Flutter](https://github.com/hexabase/hexabase-dart)

## インストール

インストールは `dart pub get` で行えます。

```
dart pub get hexabase

```

## インポート

SDKをインポートします。

```dart
import 'package:hexabase/hexabase.dart';

```

## 初期化

まずインスタンスを作成します。

```dart
var client = Hexabase();

```

別なファイルで再度インポートした場合には、以下でインスタンスを取得してください。

```dart
var client = Hexabase.instance;
```

## リンクについて

リンクはいわゆるリレーションです。データ同士を紐付けることで、関連データとして一度のクエリーでデータを取得できます。

![0979 app.hexabase.com - 0328114856.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/7beb6f41-10a5-cf84-17d2-1f51cf749934.jpeg)


まず最初に管理画面にて、データベース関連を設定します。

1. マスター側のデータベース設定を開く
2. 「データベース関連の設定」タブを開く
3. 「データベース関連」でリンクを張るテーブルを指定する

詳しくは [データベースの関連付け | Hexabase 開発ガイド](https://devdoc.hexabase.com/docs/admin_reference/db_relation/) をご覧ください。

## 関連データの取得

関連データを取得する際には、HexabaseQueryでincludeを指定してください。

```dart
await client.setWorkspace('YOUR_WORKSPACE_ID');
var project = await client.currentWorkspace.project(id: 'YOUR_PROJECT_ID');
var datastore = await project.datastore(id: 'YOUR_DATABASE_ID');
// HexabaseQueryオブジェクト
var query = datastore.query();
// include(true)で関連データを取得します
query.per(100).include(true);

// データを取得
var items = await datastore.items(query: query);
```

## 関連データの取り出し

関連データを取得する際には、 `getAsItem` を利用します。これは `items` と同じく `HexabaseItem` オブジェクトです。以下は一例です。

```dart
item.getAsItem('FIELD_NAME').title
```

なお、関連データの内容を変更したい場合には以下のようにしてください。

```dart
var parent = item.getAsItem('FIELD_NAME');
parent.set("name", "New name");
await parent.save();
```

## まとめ

Dart SDKはFlutterでも利用できます。Flutterで使えると言うことは、iOS/Androidといったスマートフォンアプリやタブレットアプリはもちろん、Webやデスクトップアプリ開発でも利用できます。ぜひHexabaseをDart SDKとともに活用してください。

関連データを用いると、一般的なデータベースのようなリレーションとしてデータを扱えるようになります。現状は取得のみですが、ぜひ活用してください。

[hexabase | Flutter Package](https://pub.dev/packages/hexabase)
Xcode Cloudのアーカイブで`Command exited with non-zero exit-code`が出るようになった（解決済み）

# 結論
Cocoapodsを利用しており、Xcode 14.3でアーカイブするとアーカイブエラーとなる。
Cocoapods1.12.1を利用すれば解決する。

# 背景
Xcode Cloudでビルド・アーカイブを実行したところ、ビルドは通りますが、アーカイブでエラーが出るようになっていました。

`Command exited with non-zero exit-code`
ログを追いかけてみると、怪しそうな記述が。

```
Run custom shell script '[CP] Embed Pods Frameworks'

0秒
mkdir -p /Volumes/workspace/DerivedData/Build/Intermediates.noindex/ArchiveIntermediates/LiveDevelop/BuildProductsPath/Develop-iphoneos/live.app/Frameworks

Symlinked...

rsync --delete -av --filter P .*.?????? --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "../../../IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Sentry.framework" "/Volumes/workspace/DerivedData/Build/Intermediates.noindex/ArchiveIntermediates/LiveDevelop/InstallationBuildProductsLocation/Applications/live.app/Frameworks"

building file list ... rsync: link_stat "/Volumes/workspace/repository/../../../IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Sentry.framework" failed: No such file or directory (2)

done

sent 29 bytes  received 20 bytes  98.00 bytes/sec

total size is 0  speedup is 0.00

rsync error: some files could not be transferred (code 23) at /AppleInternal/Library/BuildRoots/97f6331a-ba75-11ed-a4bc-863efbbaf80d/Library/Caches/com.apple.xbs/Sources/rsync/rsync/main.c(996) [sender=2.6.9]

エラー
Command PhaseScriptExecution failed with a nonzero exit code
```

> Command PhaseScriptExecution failed with a nonzero exit code


## 可能性
普段はXcode Cloudのビルド環境にLatest Releaseを指定しているので、タイミング的にXcode Cloudが`14.3 RC2 (14E222b)`となったことが可能性としてありそう。


類似：
[Upgrade from xCode 14.2 to 14.3 PhaseScriptExecution failed with a nonzero exit code](https://stackoverflow.com/questions/75486713/upgrade-from-xcode-14-2-to-14-3-phasescriptexecution-failed-with-a-nonzero-exit)

## 解決
Xcode Cloudのビルド環境を`Xcode 14.2(14C18)とすることでアーカイブが通るようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245300/c5807684-e8ed-0947-61eb-f7c71d83a29f.png)

## 所感
類似の記事を見る感じ、原因はCocoapodsとXcode14.3の問題っぽい？

## 解決（確認日：2023/04/21）
CocoaPods 1.12.1で確認したところ、Xcode14.3のアーカイブで問題なく通るようになりました。
https://github.com/CocoaPods/CocoaPods/releases/tag/1.12.1
Maltego Transform 開発メモ addDisplayInformation

```python
output_entity=response.addEntity(Phrase, "テスト")
output_entity.addDisplayInformation("<a href='https://shinobot.com'>ShinoBOT</a><img src='http://shinobot.com/res/yougotpwned.png'>", "URL")
```

Display InformationはEntityをクリックしたときに右側に表示されるEntityの詳細である
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325297/c9182d0c-1e6f-31cb-a12d-940de33bb58a.png)
* Propertyと異なり、HTMLタグがレンダリングされる
* ハイパーリンクも動作する
* JavaScriptは試したが動作しなかった
Go言語で説明する「カプセル化」について

### はじめに
カプセル化とは、オブジェクト指向プログラミングにおける概念の1つで、クラス内で定義されたデータやメソッドに外部からアクセスすることを制限することです。この制限により、データやメソッドを意図しない方法で変更されたり、アクセスされたりすることを防ぐことができます。

### サンプル説明
以下のコードでは、`Person`構造体があり、`name`と`age`の2つのプライベートなフィールドが定義されています。また、`SetName`と`SetAge`の2つの公開されたメソッドがあり、これらのメソッドを通じてのみ、フィールドにアクセスできるようになっています。

```go
package main

import (
    "fmt"
)

type Person struct {
    name string
    age  int
}

func (p *Person) SetName(name string) {
    p.name = name
}

func (p *Person) SetAge(age int) {
    p.age = age
}

func main() {
    p := Person{name: "Alice", age: 30}
    fmt.Println(p) // {Alice 30}

    p.SetName("Bob")
    p.SetAge(40)
    fmt.Println(p) // {Bob 40}

    // p.name = "Eve" // エラー！フィールドnameはプライベートです
}
```

このコードでは、`main`関数の中で`Person`構造体を作成し、`SetName`と`SetAge`メソッドを使用して`name`と`age`フィールドを設定しています。しかし、フィールドに直接アクセスすることはできず、コンパイルエラーが発生します。

このように、カプセル化によって、プログラムの安全性や保守性が向上し、意図しない操作や不正なアクセスを防ぐことができます。

https://www.waytoeasylearn.com/learn/encapsulation-in-go/

https://www.geeksforgeeks.org/encapsulation-in-golang/
Laravel MVCの仕組みとWEB3層構造について

## Laravel MVCの仕組み
Laravelは、MVC（Model-View-Controller）アーキテクチャーを採用している。
MVCは、アプリケーションをモデル、ビュー、コントローラーの3つの要素に分割することで、アプリケーションの保守性、拡張性、テスト容易性を向上させることができる。

### Model（モデル）
モデルは、データベースとのやりとりを担当するコンポーネント。
モデルは、アプリケーションのビジネスロジックを定義するために使用されるメソッドを提供する。
Laravelのモデルは、Eloquent ORMを使用して、データベースのテーブルに対応するクラスを作成することができる。

### View（ビュー）
ビューは、ユーザーに表示される部分を担当するコンポーネント。
ビューは、HTMLやCSSなどのフロントエンド技術を使用して、データを表示するためのテンプレートを作成する。Laravelでは、ビューを作成するためのBladeテンプレートエンジンを提供している。

### Controller（コントローラー）
コントローラーは、リクエストの受け取りと処理を担当するコンポーネント。
コントローラーは、モデルを使用してデータを取得し、ビューを使用してデータを表示するためのレスポンスを生成する。Laravelのコントローラーは、ルーティングシステムと密接に結びついている。

## WEB3層構造
WEB3層構造については、Laravelに限らず、一般的にWebアプリケーションの構造に使用される。
WEB3層構造は、以下の3つの層で構成される。

### プレゼンテーション層（Presentation Layer）
プレゼンテーション層は、ユーザーとWebアプリケーションのインターフェースを提供するための層。
この層には、ビュー、テンプレート、スタイルシート、JavaScriptなどが含まれる。

### ビジネスロジック層（Business Logic Layer）
ビジネスロジック層は、アプリケーションのビジネスロジックを処理するための層です。
この層には、コントローラー、モデル、サービスクラスなどが含まれる。

### データアクセス層（Data Access Layer）
データアクセス層は、データベースやファイルシステムなどのデータストレージにアクセスするための層のことを言う。
この層には、データベースマッパーやORM、データベースクエリビルダーなどが含まれる。

Laravelは、このWEB3層構造に準拠しているため、ビューがプレゼンテーション層、コントローラーがビジネスロジック層、モデルがデータアクセス層に該当する。
Laravelでは、データベースアクセスのためにEloquent ORMを提供しており、データアクセス層の実装を容易にしている。
また、サービスプロバイダーと呼ばれる機能を使用して、アプリケーションの依存性の注入を容易にすることができる。これにより、アプリケーションの保守性や拡張性が向上する。

以上
ChatGPTの考える献立は実際の所良い物なのか

 ## はじめに ##
前の記事でカロリーについての記載がなかった為，今度はカロリーを考慮して献立を考えてもらう事にしました．

↓前の記事はコチラ
https://qiita.com/joshua_kanae/items/bfda95706ab658bf7f83

今回は成人男性に必要なカロリー，2400kcal~3000kcalを想定しています．

## 出力文 ## 

成人男性が必要なカロリーは1日に2400kcalから3000kcal程度とされていますが、個人差がありますので目安として考えてください。以下は、先ほどの献立をカロリーの観点から改善した例です。
1.	鶏肉と野菜の炊き込みご飯、お味噌汁、漬物
•	鶏肉と野菜の炊き込みご飯（600kcal）
•	お味噌汁（50kcal）
•	ぬか漬け（30kcal） 合計：約680kcal
2.	サーモンのムニエル、グリーンサラダ、ご飯
•	サーモンのムニエル（350kcal）
•	グリーンサラダ（100kcal）
•	ご飯（200kcal） 合計：約650kcal
3.	ささみのステーキ、青菜のお浸し、味噌汁、ご飯
•	ささみのステーキ（200kcal）
•	青菜のお浸し（50kcal）
•	お味噌汁（50kcal）
•	ご飯（200kcal） 合計：約500kcal
4.	カレイの唐揚げ、さつまいもの煮物、味噌汁、ご飯
•	カレイの唐揚げ（350kcal）
•	さつまいもの煮物（100kcal）
•	お味噌汁（50kcal）
•	ご飯（200kcal） 合計：約700kcal
5.	豚肉と野菜の炒め物、味噌汁、ご飯
•	豚肉と野菜の炒め物（300kcal）
•	お味噌汁（50kcal）
•	ご飯（200kcal） 合計：約550kcal
6.	かぶとトマトのスパゲティ、グリーンサラダ、スープ
•	かぶとトマトのスパゲティ（400kcal）
•	グリーンサラダ（100kcal）
•	スープ（50kcal） 合計：約550kcal

全体的に、食事の量を控えめにしたり、カロリーの高い食材を減らしたりして、1食あたりのカロリーを抑えました。また、バランスよく栄養素を取るように、野菜や魚を意識的に取り入れた献立になっています。

 ## レシピ ##
かぶとトマトのスパゲッティのレシピをご紹介します。

【材料（2人分）】
・スパゲッティ　160g
・かぶ　1/2個
・トマト　2個
・にんにく　1かけ
・オリーブオイル　大さじ2
・塩　少々
・こしょう　少々
・パルメザンチーズ　適量

【作り方】

かぶは皮をむき、縦に4等分に切ります。トマトは皮をむいて種を取り除き、小さめの角切りにします。
鍋にたっぷりの湯を沸かし、塩少々を加えてスパゲッティを茹でます。茹で上がったらザルにあけ、水けをきっておきます。
フライパンにオリーブオイルを入れ、みじん切りにしたにんにくを入れて炒めます。
にんにくの香りが立ったら、かぶを加えて中火で炒めます。かぶに火が通ったらトマトを加えてさらに炒めます。
スパゲッティを加えて全体を混ぜ合わせ、塩こしょうで味を調えます。
器に盛り、パルメザンチーズをかけて完成です。
ほんのり甘みのあるかぶと、トマトの酸味が合わさったスパゲッティで、食欲をそそる一品です。お好みでパルメザンチーズの代わりに、他のチーズを使ってもおいしくいただけます。

 ## 終わりに ##
白米のご飯1杯(140g)がおおよそ230kcal前後なのでおおよそ一般的なご飯の量で1食も600~700前後でカロリー面もお昼をしっかり食べ，晩を軽くする人には十分そうだと感じます．たまに謎の料理があったり品目が不足しがちな点を除けばおおよそ期待通りの献立表になっているのではないでしょうか．


 ## 参考 ##
農林水産省HP
https://www.maff.go.jp/j/syokuiku/zissen_navi/balance/required.html
ご飯の1杯のカロリー
https://fukuinokomeya.com/blog/%e3%81%94%e9%a3%af%e3%81%ae%e3%82%ab%e3%83%ad%e3%83%aa%e3%83%bc/
reCAPTCHAに関するお話（自分の理解）【はてなブログからの転載】

# はじめに
- 本記事は、reCAPTCHAに関して、まとめたものになります。
- 他の方の参考になる可能性も踏まえて、一般公開も行なっております。
- また記載内容はすべて、正しい内容が記載されているとは限りません。
- 誤った内容を見つけた場合は、ご指摘をお願いいたします。

# この記事は誰向けの記事か？
- reCAPTCHAについて簡単に知りたい人

# 背景
- この記事は、2022年11月頃に、はてなブログに掲載していた記事を修正し、Qiitaに掲載した記事になります。
- はてなブログのアカウント廃棄のため、こちらに転載しました。

# 本文はここから
初めての投稿となるので、投稿の仕方やデザインをどうしたら良いのか、試行錯誤してます（汗）未経験の人でもわかりやすい内容を書ければいいなと思いつつ、何を投稿しようか、考えていました。

たまたま、このはてなブログのアカウント登録をしている時に、reCAPTCHAが目に入ったので、それをここで発信できればと作成しています。reCAPTCHAの話をもとにお伝えしたい内容は、以下の通りです。

- Webページを作成する際は、そのページを運用していくことを前提に作ること
- reCAPTCHAを利用すれば、ロボットによる処理を防ぐことができる
- システムを正しく利用してくれる人ばかりではない

reCAPTCHAとは、アカウント登録する時などに「私はロボットではありません」とWebページに出てくるオブジェクトですね。他には「歪んだ画像に書かれている文字を回答する」オブジェクトや「パズルピースを完成させたりする」オブジェクトがあります。

![20220929234630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/065a97dc-2b8d-e0d5-14c0-0727591ac23c.png)
![20220929234645.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/67ed8c57-1b0d-9cf7-3ff6-5dd34c8e8a7f.png)

これは何をしているのか、大抵の人は意識したことがないと思います。これは本当にロボットでないことを確認しているんです。これがないと、大変なことになります。

例えば、youtubeのアカウント登録ページにreCAPTCHAがないと、悪い人がアカウントを、自動で大量に生成し、そのアカウントを使ってチャンネル登録やいいねをして、収益につなげようとするわけですね。

また自分が仕事で関わった例で言うと、Webページのボタンを押す動作を自動化されてしまうと、利用者に対してメールボム攻撃をされてしまう恐れがあったため、reCAPTCHAを実装しました。

他の例で言うと、お問合せページに実装するのもありだと思います。大量に問合せされると、問合せ窓口がパンク状態となり、運営に支障が出るので。

**いずれにせよ、システムを利用する人は全員がいい人とは限らないので、お気をつけください。**
アドミンコンソール画面の情報が変わらない？

# 発生内容
　アドミンコンソールに表示されるアクセスユーザーが3日前から変わっていない事に気づき、ファイルオープンや現在のアクセス数もおかしいことに気づく。
　サーバー再起動しても直らず。

# 原因特定の確認作業
1. アドミンコンソールに表示されている接続数と実際の接続数の確認。
接続クライアントの確認コマンド
```コマンド
fmsadmin LIST CLIENTS
```

2.　ファイルのオープン数も怪しかったのこちらも確認
ファイルリストの確認
```コマンド
fmsadmin list files -s
```
 
3.　ついでにコマンド上で開け閉め出来るかチェック
```コマンド
#ファイルを閉じる（ID指定）
fmsadmin close {ID}  
#ファイルを開ける（ID指定）
fmsadmin open {ID} 
```
　コマンドで問題なく、開け閉めも出来て、接続数もコマンドのほうが正しく。

# 解決した方法
管理サーバープロセスの再起動
```コマンド
fmsadmin restart adminserver
```

色々いじくってたけど、ヘルプにかいてありました。:persevere:
> Admin Console でタブ、コマンド、またはオプションをクリックしても Admin Console が応答しない場合は、管理サーバープロセスが停止している可能性があります。
https://help.claris.com/ja/server-help/content/trouble-admin-console.html
Pythonでfor文のループ内でAPIを呼び出す際のエラーハンドリング方法を考えてみた

APIを叩く時にエラーとなることがある。
for文でAPIのパラメータをインクリメントして叩いている時にエラーとなった場合にエラーハンドリングをどうしたらいいのか複数考えてみた。
※業務で同じようなことに出会したことがないため、同じようなことを業務でしている方がいらっしゃいましたら、エラーハンドリングの方法をコメントしていただけると勉強になります。

# エラーハンドリング案
## ①try-catch
```python:try-catch.py
import requests

for item in items:
    try:
        response = requests.get(api_url)
        # レスポンスの処理
    except requests.exceptions.HTTPError as errh:
        print('HTTPError:', errh)
    except requests.exceptions.ConnectionError as errc:
        print('ConnectionError:', errc)
    except requests.exceptions.Timeout as errt:
        print('Timeout Error:', errt)
    except requests.exceptions.RequestException as err:
        print('RequestException:', err)
```
APIを叩いた時にエラーが発生した場合にそれぞれのErrorに応じて処理を行う

## ②リトライ
```python:retry.py
import requests
import time

MAX_RETRIES = 3
RETRY_INTERVAL = 5

for item in items:
    for retry_count in range(MAX_RETRIES):
        try:
            response = requests.get(api_url)
            break
        except requests.exceptions.RequestException:
            if retry_count == MAX_RETRIES - 1:
                print('APIリトライ失敗')
            else:
                time.sleep(RETRY_INTERVAL)

```
APIのパラメータをインクリメントしない場合にはなりますが、エラーが起こった時に再試行する。
エラーが起こらなかった場合はbreakでfor文から抜ける。

# 終わりに
try-catchとリトライを組み合わせたり、ロガーを追加して保守しやすくするなり方法があると記事を書きながら思いました。良さそうな案があれば日々追記してきます。
Maltego Transform開発メモ AddUIMessage(msg, type)

# AddUIMessageのメモ

```python
from maltego_trx.maltego import UIM_FATAL, UIM_PARTIAL, UIM_INFORM, UIM_DEBUG
from maltego_trx.transform import DiscoverableTransform

class Experimental(DiscoverableTransform):
    @classmethod
    def create_entities(cls, request, response):
      response.addUIMessage("UIM_FATAL", UIM_FATAL)
      response.addUIMessage("UIM_PARTIAL", UIM_PARTIAL)
      response.addUIMessage("UIM_INFORM", UIM_INFORM)
      response.addUIMessage("UIM_DEBUG", UIM_DEBUG)
      #おまけ
      response.addException("Dummy Error")
```

上記を実行すると以下のように表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325297/e63c33ac-63f3-d7af-f7e4-c952cb8361a0.png)

* UIM_FATAL はポップアップも表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325297/7a1ad3ae-7c8b-39d5-830a-281aaca34ee2.png)

* UIM_DEBUGはデフォルトの設定では表示されない。フィルターで表示させる必要がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325297/d2d92d07-3a72-5215-b442-e7f922e74aa7.png)

* addExceptionはどこに表示されるか不明。`var/log/messages.log`にも出てこなかった。
テックキャンプ受講生向け、ショートカットキーなどをこの記事でご紹介【はてなブログからの転載】

# 【全般】
- コピー・・・Command + C
- ペースト・・・Command + V
- リドゥ・アンドゥ・・・Command + Z または Command + Shift + Z
- 全選択・・・Command + A
- 保存・・・Command + S
- アプリケーション終了・・・Command + Q
- ペースト・・・Command + V
- 検索・・・Command + F

# 【ブラウザ関連】
※GoogleChromeを想定。
- アクティブアプリケーションの変更・・・Command + Tab
- ブラウザのリロード・・・Command + R
- ブラウザの新規タブ作成・・・Command + T
- ブラウザのタブ再読み込み・・・Command + Shift + T
- ブラウザのタブ削除・・・Command + W
- ブラウザごと削除・・・Command + Shift + W
- ブラウザのタブ移動・・・option + command + ← or →

# 【VSCode】
- 最後尾または先頭へのフォーカス移動・・・Command + ← or →
- コード一行分の移動・・・option + ↑ or ↓
- コードの複製・・・option + Shift + ↑ or ↓
- フォーカスを増やす・・・option + command + ↑ or ↓
- ターミナルの開閉・・・command + j
- サイドバーの開閉・・・command + b
- 変数の一括リネーム・・・F2
（変更したい変数上にカーソルを持っていき、F2キーを押すことで変数名を一括で変更できる）

# 【Commandキーが押しづらい場合】
自分の場合、CommandキーとCキーが近く、左手で押しづらいと感じました。そのため以下の設定画面からCommandキーの配列を変えていました。

- システム設定＞キーボード＞キーボードショートカット＞修飾キー

下の画像では、Caps LockキーにCommandキーを配置している例になります。
![20221202145352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/8a61f15d-efc1-ac85-1d3b-8a1d815a95b4.png)

# コメント
私は先日、テックキャンプを受講し終え、卒業した者です。後輩受講生向けに、便利だったショートカットキーなどをご紹介します。**もし他に便利なものがあれば、ご連絡をお願いします。**

自分は受講した際に、以下のショートカットキーを駆使し、効率的に作業をしていました。
（結構、左手だけで解決できるショートカットキーばかりです）
（なお自分が受講で使用していたPCはMacBook AirのノートPCになります）

# この記事は誰向けの記事か？
- Techcampの受講生向け
- プログラミング未経験者
- IT未経験者
- ショートカットキーについて知りたい方
- キーボード操作を効率よくしたい方

# 注意事項
- この記事は、2022年12月頃に、はてなブログに掲載していた記事を修正し、Qiitaに掲載した記事になります。
- はてなブログのアカウント廃棄のため、こちらに転載しました。
- 本記事は、ショートカットキーに関して、まとめたものになります。
- 他の方の参考になる可能性も踏まえて、一般公開も行なっております。
- また記載内容はすべて、正しい内容が記載されているとは限りません。
- 誤った内容を見つけた場合は、ご指摘をお願いいたします。
デイトラ「Web制作コース」　受講内容をアウトプット 22日目


学んだことをアウトプットしています。完全に自己満足ですので悪しからず。
以下の点を確実にアウトプット
①何で学んでるか
②日々の学習内容
③学びのポイント
④制作物
⑤+αで参考にした記事
⑥+αでやってみたこと

①デイトラ「Web制作コース中級編」　JavaScript・jQuery学習編
②JavaScriptの基本文法②
　・配列
　　　scores = [89,29,31]　で複数のﾃﾞｰﾀを扱うもの。構成する１つのﾃﾞｰﾀを要素という。
　　　index番号で管理され最初の要素は「0」なことに注意。
　　　配列名.push(要でも素)で要素追加可能。文字列でも数値でもブーリアンも追加可能。
　　　配列名.lengthで要素の個数を表示できる。
　　　配列名.POP()で配列最後の要素を削除できる。
　　　配列名.shift()で配列最初の要素を削除できる。
　・オブジェクト
　　｛プロパティ名：値、・・：・・、｝で定義できる。
　　　配列の中にオブジェクトを定義可能
　　　オブジェクトの中に関数を定義可能
　　　メソッドの使い方
　・繰り返し処理
　　　for(let 変数名 of 配列名）
　　　配列名.forEach(function(変数名) {
　　　この二つをよく使う
③なし
④なし
⑤なし
⑥プロゲートのJavaScriptコース閲覧
[SQLServer] NULL置換する方法

# NULL徹底攻略

# 前書き
こんにちは。かわんちゅです。
前回、NULLの定義と簡単なNULLの使い分けについて解説しました。

https://qiita.com/kawanchu3/items/9be80734e6e719519dd9

今回はSQL文における天敵：**NULL**を適切に処理できる関数などをまとめたいと思います。
**NULL**で困ったときに、読んでほしいです。

今回使うテーブルは以下になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3296700/f55626c4-0e06-c9cd-8083-b8aef2919df3.png)




# 目次
[NULLを置換する関数](#nullを置換する関数)
・[ISNULL関数](#isnull関数)
・[COALESCE関数](#coalesce関数)
・[CASE関数](#case関数)


# NULLを置換する関数

### ISNULL関数

**メリット**
・**NULLの値を指定した文字列に変換することができる。**
・**一時的に文字列に変換される、中のテーブルデータが変更されるわけではない。**
　※IS NULL 演算子とは違うので注意が必要

```sql:ISNULL文法
ISNULL(列,変換したい文字列)
```

実例
```sql:名前列がNULLの時に、ヌル太郎に変換するSELECT文
SELECT ISNULL(Name,'ヌル太郎') as 'Name' FROM LIBRARY
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3296700/b54ce4c5-f07d-9013-dc56-1da7633ecf97.png)

ただ、本来の全行の名前はNULLのままです。
**ISNULLにより、中の値が変わるわけではないので、どんどん使っていきましょう。**

```sql:全行の名前を取得するSELECT文
SELECT Name FROM LIBRARY
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3296700/f37e58f2-3dc8-cfba-1be9-ad2c731a4915.png)


### COALESCE関数
・**NULLの値を指定した文字列に変換することができる。**
・**一時的に文字列に変換される、中のテーブルデータが変更されるわけではない。**
・**ISNULLよりデータ型に厳しい**


```sql:COALESCE文法
COALESCE(列名,変換したい文字列)
```

実例
```sql:NameのNULLをヌル太郎に変換し、出力するSELECT文
SELECT COALESCE(Name,'ヌル太郎') AS 'Name' FROM LIBRARY
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3296700/b54ce4c5-f07d-9013-dc56-1da7633ecf97.png)


### CASE関数
**メリット**
**・条件を指定することでNULLをほかの値に変換できる。**
**・ISNULL同様、中のデータが変換されるわけではない。**
**・条件の設定次第では、NULL以外の数字の返還も可能である**
**・if文のような感じである**

```sql:CASE文法
CASE WHEN 条件 THEN 結果1 ELSE 結果2 END
```

実例
```sql:[Name]列がNULL場合に置換を行うCASEを用いたSELECT文
SELECT CASE WHEN [Name] IS NULL THEN 'ヌル太郎' ELSE [Name] END as 'Name' FROM LIBRARY
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3296700/b54ce4c5-f07d-9013-dc56-1da7633ecf97.png)
vue.jsの雛形

タイトル通り、vue.jsの雛形です。
本当はその都度公式ドキュメントを開いて読みながら進めていくのがいいようです…！

・hemlの雛形にスクリプトタグを追加
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>vue-todo</title>
    <link rel="stylesheet" href="css/styles.css">
</head>
<body>
    <div id="app">

    </div>
    <script src="js/main.js"></script>
    <script src="https://unpkg.com/vue@3.1.5"></script>
</body>
</html>
```

・main.jsは以下のように記述
```js:main.js
const app = Vue.createApp({
    data: () =>({

    })
})
app.mount('#app')
```
ChatGPTにIQテストさせてみた

ChatGPTのIQは天才、200だ！

と言い張る専門家たちが増えてきたので

実際にIQテストを解いてもらいました！

今回使用させて頂いたのはハイレンジIQテストです。
こちらのIQテストを利用させて頂きました。

URL:http://free.ultimaiq.net/numerus_basic.htm

標準偏差は15となっており、MAX160まで計測可能、160の知能を持つ人物は3万人に一人だそう

本来IQテストは論理的思考力や言語能力様々な側面で測りますが、そこまで扱うと難しいため論理的思考力の側面だけとしました。

目指せアインシュタイン

結果は！！

![20230328_140838.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291317/90a40ccd-8d0f-db4a-c9d4-4e8d64757c32.jpeg)

中途半端な結果となりました。

ChatGPTには問題の出し方によって違った答えが変わってくるということが言われているので、問題の出し方を変えて今度挑戦してみます！
【VueJS/】bl2br自作

DBから値を改行ありで表示したいのですが、
phpのbl2brメソッドがJavaScriptには存在しないので自作します。

jsフォルダ直下に作成し、importで使い回すことにしました。
今回はVueを扱っているので、変数の中で定義することにします。

```javascript:js/common.js
const nl2br = (str) => {
    str = str.replace(/\r\n/g, "<br />");
    str = str.replace(/(\n|\r)/g, "<br />");
    return str;
}

// 関数を別ファイルで使い回すための記述
export { nl2br }
```

v-htmlを使用し、<br>をHTMLとして処理・表示します。

```vuejs:
<script setup>
    import { nl2br } from '@/common'
</script>


<template>
    <textarea v-html="nl2br(DBから取得する値)">
        
    </textarea>
</template>

```

これで完了です。
作成したDockerイメージを配布＆共有する方法 ＜最終版＞

OrbStackというフレームワークを使い回しております。
https://qiita.com/naiveprince0507/items/090bb79cc85eea2d230f

その過程で、表題の件も含めて、色々と躓いたので、纏めておきます。

1
例えば、ローカルマシン環境で、Dockerイメージを作成して、それを他人に共有する際にどうするか？ と言うだけの話なんだけど、色々と調べました。
私のMac PC環境では、以下の場所に、Imageが保存されます。
```
~/Library/Containers/com.docker.docker/Data/vms/0/
```
（参考）　https://qiita.com/amuyikam/items/938781ff5898e654fd7c

ただ、ISOイメージみたいな単一ファイルで保存される訳ではなく、隠しファイルも含めた複数ファイルで構成されているので、簡単に、「Dockerイメージをメール転送しますね。」とか「ファイルサーバにアップしておきますね。」とは出来ないと理解してます。

2
そんな訳で、Docker　Hubの登場です。
https://hub.docker.com/

Docker　Hubと言う名前が秀逸。（ネットワークレイヤーで使うHubと言う名称は非常に分かりやすい。）
例えば、他人と共有する際は、自分でDocker　Hubにアップして、そのリンクを相手にメールして、その相手がDocker Hubにアクセスして、DLすると言うイメージになります。

3
下記では、実際にやってみます。

＜気を付ける点＞
Docker　Hubに登録してあるユーザー名に、Docker　Imageの名前を変えないと、HubにPushできません。

例えば、aplpineと言う、DockerイメージをHubにアップしたいとします。
```
User_A@User_A-mac Downloads % docker images                                
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
alpine                   latest    d74e625d9115   6 weeks ago    7.46MB
```

普通に、下記の様にやると、エラーになります。
```
% docker push alpine:latest
denied: requested access to the resource is denied
```

🔳 手順１
原因は、下記サイトに書いている通りですが、Dockerイメージの名前を、Docker　Hubのユーザー名に合わせる必要があります。
docker pushができないときの対処方法【M1 Mac Apple silicon】
https://hitori-sekai.com/tool/error-dokcerpush/

つまり、準備として、一旦、"alpine:latest" を、"Docker Hubユーザー名/apline"みたいに変更する必要があります。
ここでは、Docker Hubユーザー名は、"dockerhub_usrX"としております。

```
docker image tag alpine:latest dockerhub_usrX/alpine
```

ローカルで、この準備が終了した上で、もう一回、Imagesを見てみましょう！

```
User_A@User_A-mac Downloads % docker images                                
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
alpine                   latest    d74e625d9115   6 weeks ago    7.46MB
dockerhub_usrX/alpine           latest    d74e625d9115   6 weeks ago    7.46MB
```
この様に、dockerhub_usrX/alpineでイメージが作成されていることが確認できます。

🔳 手順２

Docker Hubにログインする。

```
User_A@User_A-mac ~ % docker login -u dockerhub_usrX
Password: 
Login Succeeded

```
🔳手順３
Pushする。
```
User_A@User_A-mac ~ %　docker push dockerhub_usrX/alpine
The push refers to repository [docker.io/dockerhub_usrX/debian]
7806df21f4c4: Mounted from dockerhub_usrX/alpine 
latest: digest: sha256:97f195aa3c20b62ad004df27fd89cc771048317565c58da819a24705d74042 size: 529
```

と言うわけで成功です！


尚、別のマシンから、DLするには、下記の様にpullします。

```` 
User_A@User_A-mac java_code % docker pull dockerhub_usrX/alpine
Using default tag: latest
latest: Pulling from dockerhub_usrX/alpine
Digest: sha256:97f195aa3c20b62ad004df27fd89cc771048317565c58da819a24705d74042 size: 529
Status: Downloaded newer image for dockerhub_usrX/alpine:latest
```
S3 Transfer AccelerationとGlobal Acceleratorの違いについて

# はじめに
S3 Transfer AccelerationとGlobal Acceleratorの違いが良くわからなかったので
ChatGPT先生に聞いてみた。

# S3 Transfer Accelerationについて
 AWSのS3（Simple Storage Service）にファイルをアップロードする際に使用されます。S3 Transfer Accelerationは、AWSのグローバルネットワークを利用して、転送ルートの最適化を行います。つまり、S3 Transfer Accelerationを使用することで、S3にファイルをアップロードする際に通常よりも高速な転送速度を実現できます。
　　
# Global Acceleratorについて
 AWS内の異なるリージョン間の通信を高速化するために使用されます。Global Acceleratorは、AWSのグローバルネットワークを利用して、異なるリージョン間の通信を最適化します。つまり、Global Acceleratorを使用することで、異なるAWSリージョン間の通信を高速化できます。

# まとめ
　S3 Transfer AccelerationはS3にファイルをアップロードする際に高速な転送速度を実現するために使用され、Global AcceleratorはAWS内の異なるリージョン間の通信を高速化するために使用されます。
Unity 2021.3 と Vuforia Engine 10.13 で猫の顔を認識するARアプリを作る

# 背景
- 猫カフェに行ったときに猫の名前が覚えられない
- 常連さんや店員さんは見分けがつくようだけど…
- 猫の名前や情報を知れれば、より猫カフェを楽しめるのでは？

# 問題
- 写真や冊子で紹介はしてくれてるけど、似てる柄だと自信持てない
- 知りたいときに手元にない
- 情報が最新化されてない(入ってきたばっかりの猫の情報がない)

# アプローチ
「スマホカメラで認識してARで情報出せたら面白そう」というアイデアがあがったので実装してみた。

参考記事

https://onetech.jp/blog/how-to-create-an-ar-app-with-unity-8292

https://qiita.com/hanapage/items/8f7883809c76734c0333

# 必要なもの
- Unity Hub (無料)
- Unityアカウント (Personalライセンス、無料)
- Vuforiaアカウント (Basicプラン、無料)
- Unity動かすPC
- PCに付けるカメラ(内臓でも可)

# 成果物
Unity上でPC接続したカメラ映像からマーカーを認識してオブジェクトを表示できました。

マーカーに指定した画像をスマホで表示している
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/9bf7535e-e8aa-d369-3189-d19ca6ce544b.png)
認識した部分にオブジェクトを表示している
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/a4f14bd8-51f9-871f-f8d6-57707fec1241.png)

実環境ではマーカーが認識されず、課題が残りました。

マーカーと同じような顔をしてくれない
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/81d3fd7c-36d8-2a65-bdb1-8dfe8f22eecd.png)
照度や角度を近づけようと頑張っても限度がある
![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/9499f483-8d34-8cf2-4490-d9c35d9cfe6e.png)

# 作り方
基本的には冒頭にあげた参考記事を読めばOK
バージョン差分で手順が異なる部分があったので、Unity2021の場合は以下で実施
## Vuforia環境
1. [開発アカウントを作成](https://developer.vuforia.com/)
1. License Managerで新規ライセンスを作成
1. Target ManagerでDatabase(Type:Device)を作成
1. DatabaseにTargetを追加(マーカー画像をアップロード)
1. DatabaseをDownload
    1. Unity Editor

## Unity環境
1. Unity Hub 3.4.1 をダウンロード
1. アカウントを新規作成
    1. Install Editorで「2021.3.18f1」を選択 (2021.3系なら良いと思われる)
1. New Projectで「Unity」「3D Core」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/d91e640c-5bda-c486-3869-c2f4b8d5b3fc.png)
1. [Unity Asset StoreでVuforia Engineを取得](https://assetstore.unity.com/packages/templates/packs/vuforia-engine-163598)
1. Unityの Window > Package Manager > Vuforia をDownloadしてImport

## 結合
1. UnityのGameObject > Vuforia Engine > AR Camera
    1. Vuforia Behaviour(Script)
        1. Open Vuforia Engine Config
        1. App License Key にVuforiaのライセンスを記載
1. UnityのGameObject > Vuforia Engine > Image Target
    1. Image Target Behaviour(Script)
        1. Type: From Database
        1. Database: VuforiaでDownloadしたDatabase
1. UnityのGameObject > 3D Object > Cube
1. Unityの再生ボタンをクリック

# 課題
成果物の通り、ARマーカーとして猫の顔を登録した場合、同じ画像を認識させることはできました。一方、カメラの角度や照度、猫の表情などの影響を受けて認識精度が実用的ではありません。（Vuforiaはテンプレートマッチングに近い手法で識別されている？）

今後の展開として以下のような実装を検討中です。
- マーカーの識別精度を高める
    - 首輪にマーカーを付ける、あるいはQRコードを使用する
- マーカー以外の情報を活用する
    - 汎用的な検出器で猫を検出し、特化した識別器で個体名を判定する
マテリアルアイコンの表示（Google Fontsで使用する方法）

初投稿です！
動画で習った内容ですが、見返しやすいよう記事にしてみました。
手順を分けましたが、htmlを一行追加するだけ！

①マテリアルアイコンガイドからコードを探しコピーする
※ガイドの中の『設定方法1 Google Fontsで使用』というやり方です
https://developers.google.com/fonts/docs/material_icons?hl=ja#setup_method_1_using_via_google_fonts

②以下をhtmlに貼り付け
```ruby:マテリアルアイコン
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
```

③以下のリンクでアイコンを検索
※マテリアルシンボルとアイコンがあるので注意
https://fonts.google.com/icons?hl=ja
![スクリーンショット 2023-03-28 13.50.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3082238/076fa4fb-bc1d-5794-c148-80b9df7d7fee.png)
Gitを個人開発で使う(初心者向け)

備忘録も兼ねて､Gitを個人開発で使うときの流れとか注意点について､よく使うコマンドを交えて書いていきます｡
最小限これさえ知っとけばとりあえずgitで個人開発できる､くらいの初心者向けの内容です｡

### 1. リポジトリの作成
~~~
$ git init
~~~
現在のディレクトリに.gitという隠しディレクトリが作成され、Gitで管理できるようになります。

### 2. ブランチの作成､切り替え
~~~
$ git switch -c <ブランチ名>         # -cオプションで作成と切り替えを同時に行う
~~~

面倒かもしれませんが､mainブランチで作業するのはやめましょう｡(自戒)
個人開発でも

- 安全なコード管理
開発中のコードやバグ修正が途中でも、安定しているメインブランチから分離されるので､常に安定した状態のコードがメインブランチに維持できる。
- 変更履歴の追跡が簡単
各ブランチで独立してコミットが行われるため、どの機能追加やバグ修正に関する変更かが明確になり､後で変更履歴を追跡しやすくなる。

というメリットがあります｡

### 3. ファイルの追加､コミット
~~~
$ git add .　　　　#すべてのファイルを追加
$ git commit -m "コミットメッセージ"
~~~

- コミットメッセージはわかりやすく。例: "〇〇の不具合の修正"､"〇〇を追加"など
- 特定のファイルを追加する場合、git add <ファイル名>で特定のファイルだけ追加できます。
- .gitignoreファイルを作成してgitの管理下に置きたくないファイルはあらかじめ分離しておきましょう｡

#### 3.1 直前のコミットを取り消したいとき
~~~
$ git reset --soft HEAD^　
~~~
- `--soft`はコミットだけを取り消すオプション。（`--hard`はコミットを取り消した上に変更内容も取り消される。）
- HEAD^は直前のコミットを表す
- n個前のコミットを取り消す場合は`HEAD~n`(3つ前を取り消す例：`HEAD~3`)

#### 3.2 コミットの上書き
~~~
$ git commit --amend 
~~~
コミットメッセージを変えたいときに`git commit --amend -m "コミットメッセージ"`としてよく使う｡

### 4. ブランチのマージ
~~~
$ git switch main
$ git merge <ブランチ名>
~~~
作業が完了したらメインブランチに戻り､作業ブランチをメインブランチにマージ(統合)します。
### 5. リモートリポジトリ(GitHubなど)へのプッシュ
~~~
$ git remote add origin <リモートリポジトリのURL>
$ git push -u origin main
~~~
GitHubなどのリモートリポジトリを利用している場合はプッシュして反映させます。
### 6. ブランチの削除
~~~
$ git branch -d <ブランチ名>
~~~
マージし終わった作業のブランチは削除しておきましょう。

**あとは2~6のブランチを作っては消す作業を繰り返すだけ!**
### 今の状況がわからなくなったとき

`$ git status`でプロジェクトファイルのステージング状態を確認したり､
`$ git log`でコミット履歴を確認できます｡
また、`$ gitk`でGUIに表示するのもわかりやすいです｡
vscodeの拡張機能だとGit GraphやGitLensがおすすめです｡
# コツ
- ブランチをちゃんと切る。
- 定期的にこまめにコミットする。
- わかりやすいコミットメッセージを書く。