OmniAICreator/Qiita-1.07M huggingface dataset:
AirSimにおけるUnreal 環境のセットアップ

# Unreal プロジェクトのセットアップ
自分の学習用に日本語に翻訳したものです。下記に元のURLを載せておきます。
https://microsoft.github.io/AirSim/unreal_proj/#option-1-built-in-blocks-environment
## オプション 1: 組み込みブロック環境
AirSim に付属している Blocks プロジェクトを使用することで、迅速に立ち上げることができます。これはレポのサイズをリーズナブルに保つためにあまり詳細な環境ではありませんが、私たちは常に様々なテストにこれを使用しており、この見知らぬ土地に足を踏み入れる最も簡単な方法です。

この[簡単なステップ](https://microsoft.github.io/AirSim/unreal_blocks/)に従ってください。

## オプション 2: 独自の Unreal 環境を作成する
写真のようにリアルな高品質の環境をセットアップしたい場合は、独自の Unreal プロジェクトを作成する必要があります。
これは少し複雑ですが、価値があります。

この[ガイド](https://microsoft.github.io/AirSim/unreal_custenv/)に従ってください。

## コードと開発ワークフローの変更
AirSimコードの変更とテストの方法については、[推奨される開発ワークフロー](https://microsoft.github.io/AirSim/dev_workflow/)をご覧ください。
「Googleプロジェクト管理プロフェッショナル認定証」に挑戦してみた話(2023年1月5日修了証取得)

# はじめに

はじめまして。
私は、ベトナムのオフショアでスクラムチームのプロダクトオーナー（PO)をしています。

↓標題のとおり、私は「Google プロジェクト管理　プロフェッショナル認定証」を2022年11月後半から受講し、2023年1月5日に認定証を取得できました。

https://jp.coursera.org/professional-certificates/google-project-management

今回、受講内容や良かったことなど、ご紹介します。

# 受講キッカケ

私のバックグラウンドですが、アジャイル開発およびスクラムに精通しています（Scrum.inc社のLSPO取得済）。また以前、プロジェクト・マネージャー（PM)の経験もあります。

私としては、開発手法に特別にこだわりを持っているわけではなく、プロジェクトを成功させることに一番の興味を持っています。

今はアジャイル開発のPOを担当していますが、案件によってはウォーターフォール開発のプロジェクトマネージャー（PM）が求められることもあります。

そして、POもPMの役割は異なりますが、根本的にはプロジェクトを成功させるためのキーマンであり、共通した概念を1から勉強したいというのが受講した１番の理由でした。

また、私は昨年「Google UXデザイン プロフェッショナル認定証」を受講しました。そのカリキュラムがとても素晴らしかったため、Googleの認定証を再び受講にすることに決めました。↓

https://qiita.com/masami-atwvn/items/7a0d0a3d4661c50f8bec

:::note info
この「Google プロジェクト管理 プロフェッショナル認定証」には、POおよびPMのどちらにとっても、役立つカリキュラムが含まれています。
:::

# 受講内容

大きく6つのコースで構成されています。

1. Foundations of Project Management
1. Project Initiation: Starting a Successful Project
1. Project Planning: Putting It All Together
1. Project Execution: Running the Project
1. Agile Project Management
1. Capstone: Applying Project Management in the Real World

:::note info
日本語対応していませんが、翻訳ツールや字幕を使えば、それほど苦労はしませんので安心してください。
:::

そして、各コースには、次のような種類のカリキュラムが含まれています（Google UXデザイン プロフェッショナル認定証と同じ）

- Google社員（コースごとに異なる）によるビデオ動画
- テキストによる教材
- 簡単の選択式テスト(５〜10問）
    - 一定のポイントを獲得しなければならないが、何度もやり直せる
- 自分で作成した成果物を他の受講者にレビューしてもらう
    - 一定のポイントを獲得しなければならないが、何度もやり直せる
- テーマに対して、自由書き込み（任意）

# 受講料金

まず7日間の無料トライアルがあります。

その後、毎月39USDとなりますが、円での支払いの場合には、為替に影響されます。私の場合は、下記のとおり（円安・・・）

![スクリーンショット 2023-01-06 15.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/2801686e-0e9b-59ec-7da5-fedce53b624b.png)

:::note info
無料トライアル期間中に、ある程度、自分に合うかどうか見極められると思います。
:::

# 受講期間

私の場合は、最初から一気に勉強することを決めていたので、１ヶ月強というかなり短い期間で修了できましたが、通常であれば、もっと時間がかかると思います。

このカリキュラムは上記のとおり6つのコースごとに、Week1〜Week4 or 5 or 6で構成されているので、このペースに合わせると、最低でも概ね半年はかかる計算になります。

ただ、あくまでも目安なので、自分のペースで進めて行けば良いと思います。とは言え、月額が発生するので、早く終わらせるに越したことはないですね。。

# よかったこと

まずは全体の感想として、やはり受講して ***<font color="MediumVioletRed">本当によかった</font>*** です。

理由は次のとおりです。
- プロジェクトの成功の鍵を握るのは、開発初期フェーズ。その初期フェーズは、アジャイル開発でもウォーターフォール開発でも共通となる思想があり、今後現実のプロジェクトの初期に参加するときに、きっと見る世界が異なると言えるでしょう。
- 開発初期フェーズの前段階において、お客様にアジャイル開発もしくはウォーターフォール開発のどちらが最適化を提案しやすくなる。
- Google社員ならではの現実世界での体験を知ることができ、多くの学びが得られる。
- １から体系的に学べる。私がこれまで独自のやり方でやってしまっていたことがあったことに気づけた。現実世界ではカリキュラム通りいく訳ではないが、正しい基本となる知識を持つことで、柔軟に応用しやすくなる。
- 将来、開発プロセス全体を通じて、アジャイル開発でもウォーターフォール開発のどちらでも、自信を持って対応することができる。また、案件によっては、ハイブリッド対応することもできる。
    - 例えば、スコープ、リスクマネジメント管理、予算管理は、ウォーターフォールの手法を活用し、通常の開発はアジャイル開発を取り入れるなど。
- この修了証を持つことで、日本国内だけではなく世界の企業で働けるチャンスは広がる。


# さいごに

今回得られた知識を活かすためには、今後より多くのプロジェクトに参加し、経験を積み重ねていきたいと考えています。

また、今回学んだことを復習するために、今後Qiitaでテーマごとに簡潔にして投稿していく予定です。
Tableau リレーションシップで INNER JOIN 問題の回避方法


# これは何

Tableau でテーブル同士を（結合ではなく）リレーションシップでつないでいる場合、
LEFT JOIN 的な動きを期待しているのに、たまに INNER JOIN 的な動きになってしまい、
困ることがある。
ので、その回避策。

アドホック的な回避策な気もしますが、
これに気づく前は、毎回LODで計算フィールドを作っていたので、これで回避できるのであればお手軽で便利。

# 概要

結合で明示的に LEFT JOIN をしたり、リレーションシップのまま LOD 計算を使って回避していたけど、以下の方法で割と簡単に期待する動きになることが多いのでメモ。

回避方法は、
JOIN の相手レコードがいない場合でも表示したいテーブル側（LEFT JOINなら左側、RIGHT JOIN なら右側）の（既定で用意されている）レコードカウント数のフィールドを表の「詳細」または「テキスト」として入れてあげる、
というもの。

それにより、そのテーブルが（相手側のレコードの有無に関わらず）（フィルタをかけた後の）レコード全件が対象となり、求める結果となる。

# 例

簡単なテーブルを例に動きを見る。

## テーブル

テーブル1
![テーブル1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/0e1b9dcc-30b8-a971-725d-c8ba2180c105.png)


テーブル2
![テーブル2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/141dc534-5e93-49c0-519c-ea931d7d4fec.png)


## リレーションシップ
JOIN KEY
`サブID`
![リレーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/ebeae7be-f90c-95c7-4855-454d03667146.png)

ID 3,5 は サブID が NULL のため、テーブル2 と JOIN されるレコードがない。
また、逆に テーブル2 の サブID 13 は、テーブル1 に該当するレコードがない。

## ビューを作成

- テーブル1 の「ID」と「氏名」を行に入れる
    - 5行が表示される
![ID氏名のみ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/9a7aa373-fe55-4df6-0333-eb36cfd2f34e.png)


- 続いて、テーブル2 の「趣味」を行に追加する
    - 表示が 3行になる
        - INNER JOIN 的に動き、テーブル1 と テーブル2 両方に存在している 3行だけになる
![趣味追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/bf34fb6f-5f01-8632-e771-d0eb0a4679a8.png)

いや、そうじゃない。
ID1〜5 の5人の趣味が見たかったんだ。
趣味のレコードがないなら、NULLとして表示して欲しいんだ。

ということで、ここから回避策

- テーブル1 の「テーブル1 (カウント)」をマークとして入れる
    - ID 3,5の行が「趣味」が NULL として表示される
![テーブル1カウント追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/ddc63dac-d33e-f870-b0a3-9c980b1aa3a2.png)

- ちなみに、上図では「テキスト」として入れて表示させているが、マークの種類を「詳細」として表に出さなくても回避はできる
![テーブル1カウント詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/f49ffb89-8e42-4002-107b-8495d76009ad.png)

### 参考
- テーブル1 ではなく、「テーブル2 (カウント)」を入れると、テーブル1 にはないが、テーブル2 のみに存在しているレコードが表示される
    - つまり RIGHT JOIN
![テーブル2カウント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/7e027ded-d9a9-9855-978d-cd076c3a511d.png)


- テーブル1、2 の両方の「(カウント)」をマークに入れると、OUTER JOIN の結果になる
![テーブル12カウント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81599/a13b032d-065a-bcc2-e3c3-6cdc7d27f072.png)


# まとめ

リレーションシップを使っている時に、特定のテーブルのディメンションをビューの要素として追加した際に、
LEFT JOIN として動いてほしいのに INNER JOIN になってしまい必要な行が表示されない（対象レコードに含まれない）場合に、
LEFT側のテーブルのカウントフィールドをマークに追加することで明示的に LEFT JOIN にすることができる。

こういうやり方もあるよ、こういうケースの場合だと回避できないよ、といったことがあればコメントいただけるとうれしいです。
Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure ADユーザアカウントの管理」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Azure ADユーザアカウントの管理」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure での ID とガバナンスの管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-identities-governance/)
◇対応するモジュール
[ユーザー アカウントを管理する](https://learn.microsoft.com/ja-jp/training/modules/configure-user-group-accounts/3-manage-user-accounts)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure ADユーザアカウント」](https://qiita.com/fsd-jume/items/c97ad09e960edf6ef483)

## Azure ADユーザアカウントの管理
### ユーザアカウントの管理方法
・Azure ADにクラウドIDアカウントを追加可能な方法
　-Azure Portal
　-Microsoft365管理センター
　-Microsoft Intune管理コンソール
　-CLI(PowerShell/Azure CLI)

### クラウドIDアカウントの定義について
**◆ユーザアカウント作成時に「表示名」と「ユーザ名」が必要**
・表示名：Azure上などで表示される名前
・ユーザ名：Azureにログインする際のID
　-`名前`@`ドメイン名`の形で指定
　-既定の初期ドメイン名は「`yourdomainname`.onmicrosoft.com」
　-カスタムドメイン名を追加することで、ユーザ名のドメイン部分を変更可能

**◆ユーザアカウントプロファイル**
・ユーザの情報と設定が格納
・役職や連絡先のメールアドレスなどの他の設定も含めることが可能
・グローバル管理者などの特権を持つユーザは会社のメイン電話番号などを事前に設定可能
・管理者以外のユーザは自分のプロファイルデータの一部を設定可能
⇒表示名やアカウント名の変更は不可

### クラウドIDアカウント管理の考慮事項
**◆ユーザプロファイルデータの考慮**
・ユーザの画像や役職、連絡先情報など一部のデータは省略可能
・組織の要件に基づいて、ディレクトリ内のすべてのユーザに設定することも可能

**◆削除されたアカウントの復元オプションを考慮**
・ユーザを削除するとそのアカウントは30日間中断状態
⇒その30日の期間中であれば復元可能

**◆収集されたアカウントデータを考慮**
・ユーザアカウントのサインインと監査ログ情報を収集
⇒インフラの分析と改善に利用可能

## 次の学習内容
**◆Azure ADユーザアカウントの一括操作**

https://qiita.com/fsd-jume/items/c80821f5dc17449cee14

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

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
AccessのVBAで日付の日数差などを取得

# やり方

```DateDiff()``` でできる。

```vb:イミディエイトウィンドウにコピペして動作確認できるコードサンプル
?DateDiff("d", "2020/01/01", "2020/01/01")
```

上記の結果は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4cbf344c-fb40-6bb3-d2f1-4501a4966a61.png)

```vb:イミディエイトウィンドウにコピペして動作確認できるコードサンプル
?DateDiff("d", "2020/01/01", "2020/01/02")
```

上記の結果は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/812e1adb-76fa-91bb-1909-76e441cb098c.png)

# 参考サイトさん

https://daitaideit.com/vba-datediff-datepart/

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2364
Microsoft Access for Microsoft 365 MSO (バージョン 2211 ビルド 16.0.15831.20098) 32 ビット
プログラミング初学者　API/エンドポイントについて

### APIとは

APIはアプリの機能を提供するインターフェース(仕様)を指します！
特にHTTPリクエストで操作するAPIはREST API, Web APIと呼ばれます。
例えば「ブログ機能を提供するREST APIを作っている」という使い方です！


###  エンドポイントとは

特定のAPIの接続先(URL)を指すので、
例えば「ブログ記事を取得するためのエンドポイントは/posts/:idです」という使い方になります。
AWS SAMでJavaScript v3のLambdaをデプロイする（Node16以下）

この記事は Lambda の Runtime が Node16 以下で`SDK for JavaScript v3`を AWS SAM でデプロイする方法について記述しています。

:::note info
Node18以降はv3に対応しているので、v3で書かれたソースだけをデプロイしても動きます。代わりに、Node18以降でv2で書いている場合はv2のSDKをソースに含めてデプロイする必要があります。
:::

プロジェクトを`sam init`で作成した場合、ルートパスでデプロイすると`template.yaml`や`__tests__`などのファイルもアップロードされてしまい見た目が悪いです。そのため`template.yaml`で`CodeUri`を指定すると思います。

```yaml:template.yaml
  SampleFanction:
    Type: AWS::Serverless::Function
    CodeUri: src/
```

このようにすると、v3のSDKが`sam build`の対象に含まれなってしまいます。この場合は`package.json`を`CodeUri`で指定したパスのルートに置くことでビルドに含まれるようになります。

```
SAMルート
  |- __tests__
  |- events
  |- src
  |   |- handlers
  |   |   |- program.js
  |   |- package.json
  |- template.yaml
  ...
```
↓ ビルド後
```
SAMルート
  |- .aws-sam
  |   |- build
  |   |   |- SampleFanction
  |   |   |   |- handlers
  |   |   |   |   |- program.js
  |   |   |   |- package.json
  |   |   |   |- node_modules
  |   |   |- template.yaml
  |   |- build.toml
```

node_modulesがビルドに含まれるようになりました。

:::note info
Node.jsは実行中のファイルと同じ階層に`node_modules`ディレクトリがあるか検索し、無ければ親ディレクトリとルートのパスまで遡り`node_modules`ディレクトリを探してインポートします。
[Loading from node_modules folders](https://nodejs.org/api/modules.html#loading-from-node_modules-folders)
:::

Lambda Layerがベストプラクティスかもしれませんが。
Rails - permit params (Strong Parameter) でハッシュを許可する

permit対象としてハッシュを書けばいけるはず

```rb
params.require(:foo).permit(bar: {})
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
FastAPIのValidationの挙動に気をつけよう

本業ではないですが、部署内で小さなアプリを開発したりしています。
今回、あまり知らなかった仕様と避けるべきコードの仕様を組み合わせてしまったことで、エラーが出てしまったので書き記します。

# 何が起こったのか

FastAPIで入力されたデータから結果を返すREST APIを作成しています。
ざっくりと書けば、下のようにとてもシンプルなプログラムです（本当はもう少し複雑ですが、議論の単純化のためにシンプルに書いています）。

```py
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

class Answer(BaseModel):
    age: int
    q1: int
    q2: int
    q3: Optional[int]



app = FastAPI()

@app.post("/calc/")
async def calculation(answer: Answer):
    answer_dict = answer_score.dict()
    return calc.main(answer_dict)
```
フロントエンド側では、年齢により回答する必要のない項目はそもそも入力しないという設定になっています。
そのため、上の例で言えば下のようにq3の回答がないjsonが入力される可能性があります。

```json
{"q1": 2, "q2":1}
```
それで稼働していたら、同僚より計算ができないという連絡があり確認。
元々の計算ファイル(answer.py)には問題がなかったので、なにかおかしな挙動をしていないか確認してみることにしました。
fastAPIでありがたいのはAPIドキュメンテーションが自動生成されること。早速http://localhost:8000/docs/ を確認してみます。
誤った値がanswer.pyに渡っていないかを確認するため、

```py
@app.post("/calc/")
async def calculation(answer: Answer):
    return answer
```

としてみました。すると返ってきたjsonは
```json
{"q1": 2, "q2": 1, "q3": null}
```
となっていました。
answer.pyにはageによって条件分岐を記載しており、その場合はq3が入力されていない前提で処理を書き進めてしまっており、そのためにエラーが起きたようでした。

# 解決策
そもそも入力される値を信頼しすぎたコードを書くべきではないのかもしれません。q3が入力されていたら削除したり、他の入力があっても問題のないようなコードを書くべきでした。fastAPIとフロントエンド側でValidationされているから大丈夫だろう、と思ったがために起こった罠でした。
今回は時間がないので力技でなんとかしました。処理速度は落ちそうだけど気にしないことにしました。


```py
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

class Answer(BaseModel):
    age: int
    q1: int
    q2: int
    q3: Optional[int]


app = FastAPI()

@app.post("/calc/")
async def calculation(answer: Answer):
    answer_dict = answer_score.dict()
    answer_dict_ = {k: v for k, v in answer_dict.items() if v is not None}
    return calc.main(answer_dict_)
```

このようにNoneの値を削除した辞書を用意することで問題なく動くようになりました。
# 学んだこと
FastAPIのValidation SchemaでのOptionalは、値が入力されていないときはnullが返ってくるので注意
**そもそもdictの中身にnull(None)が入ってくるだけでエラーが起こるようなコードを書いてはいけない。**
プログラミング超初心者によるゲーム作りの基礎解説　シーン


はじめまして、プログラミングというもに触れ始めて約10ヶ月の筆者です。
とある事情でゲームを作ったのですが、
よくわかんねぇ！！
ってなった~~というよりもかってに勘違いしていた~~シーンについて
初心者ながら書いていこうと思います。
マジで始めたばかりなのでもっと素晴らしい書き方があるはず(絶対にある)ですが、
 **動けばよし！**

# 目次
+ シーンについて大雑把に理解！
+ シーンの中身ってどうなっている?
+ シーンマネージャーの中身ってどうなっている?
+ 実際にどう作ったのか
## シーンについて大雑把に理解！
まずは、シーンについて理解していきたいと思います。
ゲームをプレイしている時を思い返してみてください。
タイトル画面やキャラメイク、戦闘シーンなどなど様々な画面がありますね。
その一つ一つの画面で、できることが変わってきます。
そして、その画面一つ一つが**シーン**になります。
シーンにはその画面に必要なシステムを持っています。
さらに、そのシーンを管理しているものが**シーンマネージャー**と呼ばれます。
シーンマネージャーによってシーンが切り替わっています。

## シーンの中身ってどうなっている?
システム内部の話に移りましょう。
シーンを作るのに必要なものを考えていきます。
**シーンには表示したい画面で動かしたいシステムを組み込みます。**

>例
選択画面　　→　選択方法、アイコン、画像など
>ゲーム画面　→　プレイヤー操作、敵の動き、時間表示など

これらをメインループの中に呼び出すことで、制作したシステムが動きます。

## シーンマネージャーの中身ってどうなっている?
今度はシーンマネージャーの中身です。
ここには、呼び出すシーンを切り替えるシステムを作ります。
![例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3013078/a875efb3-f20f-7f8f-5db2-f4d3521e7f81.png)
シーンマネージャーがシーンで行った"次のシーンに移る行為"を感知して、次のシーンに移す行為を行います。
~~ややこしいですね~~

## 実際にどう作ったのか
さて、コードの話に移りましょう。
今回は
`シーンによってスペースキーを押したときに表示される図形が異なる`
というものを以下に載せたいと思います。

:::note warn
このコードは **Visual Studio 2022** かつ **Dxライブラリ** を使用して書かれたものです。
:::

まずは、シーンを簡単に作っていきましょう。
今回、シーン1は`スペースを押すと円が表示される`ようにしました。

```php
/* シーン1 */
void Scene_No_1() {
	/* "ここはシーン1です"と表示する */
	DrawString(10, 10, "ここはシーン1です", GetColor(255, 255, 255));

	/* スペースキーが押されていたら円を表示する */
	if (CheckHitKey(KEY_INPUT_SPACE) == true) {
		DrawCircle(500, 350, 100, GetColor(255, 255, 255), TRUE);
	}
}
```
次に、シーン2は`スペースを押すと四角が表示される`ようにしました。

```php
/* シーン2 */
void Scene_No_2() {
	/* "ここはシーン2です"と表示する */
	DrawString(10, 10, "ここはシーン2です", GetColor(255, 255, 255));

	/* スペースキーが押されていたら四角を表示する */
	if (CheckHitKey(KEY_INPUT_SPACE) == true) {
		DrawBox(400, 250, 600, 450, GetColor(255, 255, 255), TRUE);
	}
}
```
そして、肝心のシーンマネージャーです。
今回は、`SceneNumberという変数を用意し、その値によって呼び出されるものが変わる`ようにしました。
ゲーム内で起こった事柄を感知して値を変えるプログラムを組むことで
決定した後にシーンを変えたり、ゲームオーバーになったらゲームを終わったりできます。

```php
/* シーンマネージャー */
int Scene_Number = 1;
void Scene_Manager() {
	/* 1キーが押されるとScene_Numberが1になり、2キーが押されるとScene_Numberが2になる */
	if (CheckHitKey(KEY_INPUT_1) == true) {
		Scene_Number = 1;
	}
	if (CheckHitKey(KEY_INPUT_2) == true) {
		Scene_Number = 2;
	}
	/* Scene_Numberが1の時Scene_No_1が呼び出され、2の時Scene_No_2が呼び出される */
	if (Scene_Number == 1) {
		Scene_No_1();
	}
	if (Scene_Number == 2) {
		Scene_No_2();
	}
}
```
さて、ここまで出来たら`Scene_Manager()`をメインループの中にいれたら完成です。

******
いかがだったでしょうか。
ゲーム制作の助けになれば幸いです。
ここまで読んでいただきありがとうございました。
Unity count mesh

```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class CountMesh : MonoBehaviour {

	[MenuItem("Tools/MESHS")]
    static void LogMeshF()
    {
        List<MeshFilter> mesh = new List<MeshFilter>();
        GameObject[] gameObjects = Selection.gameObjects;
        for (int i = 0; i < gameObjects.Length; i++)
        {
            MeshFilter[] meshFilters= gameObjects[i].GetComponentsInChildren<MeshFilter>();
            for (int j = 0; j < meshFilters.Length; j++)
            {
                if (!mesh.Contains( meshFilters[j]))
                {
                    mesh.Add(meshFilters[j]);
                } 
            }
        }

        int virtices=0;
        int tris=0;
        for (int i = 0; i < mesh.Count; i++)
        {
            virtices += mesh[i].sharedMesh.vertexCount;
            tris += mesh[i].sharedMesh.triangles.Length/3;

        }
        Debug.Log("virtices:"+ virtices + " tris:"+tris);
    }
}
```
unity vs Unreal ゲーム開発するならどっち？

## unity
https://unity.com/ja
### メリット
- アセットストアが充実で価格が安い
- 情報が豊富
- モバイル端末を使ったアプリにはUnityが適している
- 直観的操作が可能
- 1年間で約1,000万円以上の収益がなければ無料

### デメリット
- 起動が遅い
- デフォルトで便利な機能が少ない
- 変なコードを書くと実行時に画面が固まる

## unreal
https://www.unrealengine.com/ja/
### メリット
- デバッグコマンドがデフォルトである
- 近年アセットストアが充実してきていたが価格が高いものが多い
- 高品質のグラフィック表現
- エンジンのソースコード公開
- グラフィックのクオリティや再現性が高い
- プログラミングなしでゲームが作れる（ブループリント）

### デメリット

- ハイスペックのPCが必要
- 動作が重い
- GPUがボトルネックになることが多く、グラフィックのカスタムが必要になる（得にモバイルでは）
- 月額性のサポートに登録していないと情報不足
- 1タイトルあたりの粗収入が約1億円を超えると5％のロイヤリティが必要
- 全体的にバグが多い
- 機能が豊富なため慣れるのに時間がかかる

## まとめ
個人開発なら断然Unity!
とっつきやすく直観的な操作、情報量で圧倒的です。
しかし、プログラムの知識が乏しいならunrealのブループリントから始めるのもあり。

大人数開発でロングスパンで使うならunrealがありです。
なぜならエンジン自体の改造もできてその会社やチームならではの構造にしやすいからです。
ローカルディレクトリから直接GitHubリモートリポジトリを作成する

GitHubにリポジトリを作成する場合、https://github.com にアクセス → GUIコンソールでリポジトリを作成 → ローカルからプッシュ が面倒だったので、ローカルのディレクトリをそのままGitHubに直接リポジトリとして作成するプログラムを作りました。
コード：https://github.com/shunak/wfh

## 使い方

こちらの[README](https://github.com/shunak/wfh)にも書いていますが、こちらでは日本語訳を掲載します。

### GitHub のPersonal access tokenを取得する

ここから作成 -> https://github.com/settings/tokens
Personal access token (classic)を選択してください。

### ローカルシェルの環境変数にパーソナルアクセストークンを設定する

ローカルシェルの環境変数に、Personal access token を GITHUB_PAT という名前で設定します (すでに GITHUB_PAT という環境変数を使っている場合は、そちらを変更してください。)

### インストール
```
git clone https://github.com/shunak/wfh.git
```
### 使用方法
```
cd wfh
cp wfh.sh ../"あなたがGitHubに新規リポジトリとしてアップロードしたいローカルディレクトリ"
cd "あなたがGitHubに新規リポジトリとしてアップロードしたいローカルディレクトリ"
実行(例：シェルはbash)
bash wfh.sh "第一引数：あなたのGitHubユーザー名" "第二引数：あなたのリポジトリの可視性 public か private か"
```
第一引数にGitHubユーザー名、第二引数にあなたのリポジトリの可視性 public か private を入力します。作業中のローカルディレクトリ名でGitHubに新しいリポジトリが作成されますので、好きな名前のディレクトリを設定してください。
動作確認済：bash, zsh

ではでは
ちなみに、[技術ブログ](https://kihor.com)もやっています
悪いコード

この記事はついつい書いてしまうが、プログラムの保守性や可読性を下げてしまう悪いコードについてまとめていく。

<h4>・意味不明な命名</h4>
    はじめに考える悪いコードは「意味不明な命名」です。

```Java:myst.java
 class Memorydoing {
    void changeMemory(int memoryValue) {
        intValue1 = memoryValue;

        if (intValue1 == 0) {
             changeMemory();
          }
    ]
}
```

このように'Memorydoing'や'changeMemory'など具体的に何をするのかがわからない命名は悪いコードである。
<b>Point.　命名する際は具体的に何をするのかが他人から見てわかるように命名する。


さらに'intValue1'のような数字で区別する命名は上と同じく、数字だけでは具体的に何をするのかがわからないことやメソッド同士での区別が難しいことから悪いコードである。

<b>Point. intValue1, intValue2などの数字で区別しようとするのは他人から見てなにをするプログラムなのか理解できないのでやめよう。

最後に、`changeMemory`や`intValue`などのようなプログラミング用語やコンピュータ用語にもとづいた命名（＝技術駆動命名）も作成者の意図を読み取ることができないため悪いコードである。

<b>Point. 技術駆動命名は、作成者の意図を読み取ることができない悪いコードになるためやめよう。

<h4>・コードを見にくくするネスト</h4>
    次に考えるのは、コードを見にくくするネストです。ネストとは、if文の中にif文を入れることです。

```Java:badNest.java
    if( id < 100) {
        System.out.println("100以上ではありません。");
        if( id < 50) {
            System.out.println("50より小さいです。");
            if(id == 10) {
            System.out.println("10です。");
        }
    } 
}
```

このようにif文の中に何重もif文を入れる行為は、コードの内容をすぐに理解することを難しくするためやめよう。

<h4>・悪いコードを生みやすいデータクラス</h4>
 最後に考えるのがデータクラスです。データクラスは使いたいデータを羅列するような単純な構造になっているが、それを人間が複雑にしてしまうパターンが数多くある。

<h5>・データだけのデータクラス</h5>
はじめに考える悪いコードは「データだけのデータクラス」です。

```Java:dataOnly.java
public class dataOnly {
    private int includingTax;
    private BigDecimal salesTaxRate;
}
```

データクラスは多くの場合、なにか計算などのロジックを組み込むが、そのデータとロジックを別のクラスに分けて実装するコードが悪いコードです。

<h4>・データとロジックを分けるとなぜいけないのか。</h4>
<h5>・仕様変更</h5>
データとロジックを分けるとダメな理由は、仕様変更の際にすべてのロジックの仕様を変更しなければならないことです。ロジッククラスの数が少なければ問題はないのですが、数多くロジッククラスが存在していた場合、そのすべてを変更しなければならず、そもそもその作業が大変だったり、変更漏れによってバグを引き起こしてしまう可能性があるためです。さらにロジックが数多くあることによってプログラムの可読性を低下させてしまいます。

<h4>・未初期化状態(生焼けオブジェクト)</h4>
未初期化状態(生焼けオブジェクト)とは、コードが初期化されておらず、初期化されなければ常にnull状態になってしまうコードのことです。

```Java:uninitializedCode.java
public class ContractAmount {
    public int amountIncludingTax;
    public BigDecimal salesTaxRate;
}
    
    Contract amount = new ContractAmount();
    System.out.println(amount.salesTaxRate.toString());
```

このプログラムは最終行においてsalesTaxRateをString化したものを出力しようとしていますが、最初に初期化がされていないためこのプログラムはエラー(NullPointerException)が出てしまいます。
このように初期化が必要であるコードであると知らなければ使うことができない、未初期化状態のコードはバグを生じさせる可能性がある悪いコードであるといえます。

<h4>・不正値を許してしまうコード</h4>
最後に考える悪いコードは不正な値を許してしまうコードです。注文数がマイナスになってしまう値や消費税の計算の際マイナスを許してしまうようなコードが挙げられます。
このようなことを許さないために、バリデーションを入れて不正な値をはじくようにしようとしますが、データクラスとロジックが分けられ、数多くのロジッククラスが存在してしまっている場合、見落とす可能性があるので注意しなければなりません。
<br>
<br>
【参考】良いコード/悪いコードで学ぶ設計入門 著 仙塲大也
https://www.amazon.co.jp/dp/4297127830
Next.jsでfaviconの設定方法

[https://realfavicongenerator.net/](https://realfavicongenerator.net/)
↑ファビコンジェネレーターに画像をアップロードする
細かい設定はお好みで。


その後、ファイルとコードが作成されるのでファイルをダウンロード

ダウンロードしたファイルをpublicフォルダに持ってくる

pagesフォルダに_document.jsファイルを作って公式どうりに記述↓。

[https://nextjs.org/docs/advanced-features/custom-document](https://nextjs.org/docs/advanced-features/custom-document)

<Head>にファビコンジェネレーターで作成したコードをコピペする

以上！
wslでnerves その4

# 概要
wsl(wsl2じゃない)でnervesやってみる。
qemu(x86_64エミュレータ、ラズパイじゃない)でやってみた。
shell server、実装してみた。
c#から、叩いてみた。

# qemu起動手順

port 5300

```
"C:\Program Files\qemu\qemu-system-x86_64.exe" -drive file="hello_nerves.img",if=virtio,format=raw -net nic,model=virtio -net user,hostfwd=tcp::10022-:22,hostfwd=tcp::5300-:5300 -serial stdio

```

# 実行結果

```
>tcp0

>
pwd
/srv/erlang


>tcp0

>
ls
releases
lib
erts-13.1.3


>tcp0

>
dmesg
Linux version 5.4.204 (buildroot@buildroot) (gcc version 11.3.0 (crosstool-NG 1.25.0.37_618affc)) #1 SMP PREEMPT Sun Dec 18 19:56:03 UTC 2022
Command line: BOOT_IMAGE=(hd0,msdos2)/boot/bzImage root=PARTUUID=04030201-02 rootwait console=tty1
x86/fpu: x87 FPU will use FXSAVE
BIOS-provided physical RAM map:
BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
BIOS-e820: [mem 0x0000000000100000-0x0000000007fdcfff] usable
BIOS-e820: [mem 0x0000000007fdd000-0x0000000007ffffff] reserved
BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
BIOS-e820: [mem 0x000000fd00000000-0x000000ffffffffff] reserved
NX (Execute Disable) protection: active
SMBIOS 2.8 present.
DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
e820: remove [mem 0x000a0000-0x000fffff] usable
last_pfn = 0x7fdd max_arch_pfn = 0x400000000
MTRR default type: write-back
MTRR fixed ranges enabled:
  00000-9FFFF write-back
  A0000-BFFFF uncachable
  C0000-FFFFF write-protect
MTRR variable ranges enabled:
  0 base 0080000000 mask FF80000000 uncachable
  1 disabled
  2 disabled
  3 disabled
  4 disabled
  5 disabled
  6 disabled
  7 disabled
x86/PAT: Configuration [0-7]: WB  WC  UC- UC  WB  WP  UC- WT
found SMP MP-table at [m


```

以上。
Rust でネストしたクロージャを関数の戻り値にする

Rust でネスト（入れ子）にしたクロージャを関数の戻り値にしてみました。

* Rust 1.66

# はじめに

まず、クロージャを関数の戻り値として使う場合の（戻り値の）型としては以下のような表現方法があります。

* (a) ```fn``` を使う（move クロージャには使えない）
* (b) ```impl Trait``` を使う
* (c) ```Box``` を使う

この 3パターンをそれぞれ実装してみると次のようになります。

##### サンプル1
```rust
// (a)
fn a1() -> fn(i32) -> i32 {
    |x| x * 2
}
println!("a1 = {}", a1()(11));

// (b)
fn b1() -> impl Fn(i32) -> i32 {
    |x| x * 2
}
println!("b1 = {}", b1()(12));

// (c)
fn c1() -> Box<dyn Fn(i32) -> i32> {
    Box::new(|x| x * 2)
}
println!("c1 = {}", c1()(13));
```

##### 実行結果1
```
a1 = 22
b1 = 24
c1 = 26
```

# move クロージャの場合

次に、クロージャ外の変数をクロージャ内で使用する場合です。

外部の変数（下記サンプルの ```y```）をキャプチャするには、クロージャに move を付ける必要がありますが、(a) は move クロージャには適用できず、(b) か (c) を用いる事になりそうです。

##### サンプル2
```rust
/* コンパイルエラー: closures can only be coerced to `fn` types if they do not capture any variables

fn a2(y: i32) -> fn(i32) -> i32 {
    move |x| x * y
}
println!("a2 = {}", a2(2)(21));
*/

// (b)
fn b2(y: i32) -> impl Fn(i32) -> i32 {
    move |x| x * y
}
println!("b2 = {}", b2(2)(22));

// (c)
fn c2(y: i32) -> Box<dyn Fn(i32) -> i32> {
    Box::new(move |x| x * y)
}
println!("c2 = {}", c2(2)(23));
```

##### 実行結果2
```
b2 = 44
c2 = 46
```

# ネストしたクロージャの場合

それでは本題のネストしたクロージャの場合です。

まず、クロージャとしては以下のように普通にネストさせる事が可能です。

```rust
let c = |x: i32| move |y: i32| x * y;
println!("c = {}", c(10)(20)); // c = 200
```

これを関数の戻り値として使う場合、```impl Fn(X) -> Y``` の Y の部分に ```impl Fn・・・``` は使えないようなので、次のような方法が考えられます。

* (bc) ```impl Trait``` と ```Box``` を組み合わせる
* (cc) ```Box``` をネストにする

##### サンプル3
```rust
/* コンパイルエラー: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return

fn bb() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
    |x| move |y| x * y
}
*/

// (bc)
fn bc() -> impl Fn(i32) -> Box<dyn Fn(i32) -> i32> {
    |x| Box::new(move |y| x * y)
}
println!("bc = {}", bc()(3)(32));

// (cc)
fn cc() -> Box<dyn Fn(i32) -> Box<dyn Fn(i32) -> i32>> {
    Box::new(|x| Box::new(move |y| x * y))
}
println!("cc = {}", cc()(3)(33));
```

##### 実行結果3
```
bc = 96
cc = 99
```

ちなみに、実用性はともかく move クロージャにしなければ fn が使えるので、以下のようにする事も一応は可能でした。（クロージャ外の変数を使えないので微妙ですが）

```rust
fn ba() -> impl Fn(i32) -> fn(i32) -> i32 {
    |_x||y| y
}
println!("ba = {}", ba()(3)(31)); // ba = 31
```

最後に、ネストを増やして関数の引数を使った場合の例（impl Trait と Box の組み合わせ）です。

##### サンプル4
```rust
fn bcc(d: i32) -> impl Fn(i32) -> Box<dyn Fn(i32) -> Box<dyn Fn(i32) -> i32>> {
    move |a| Box::new(move |b| Box::new(move |c| a * b * c + d))
}
println!("bcc = {}", bcc(2)(3)(4)(5)); // bcc = 62
```

今回のサンプルコードは https://github.com/fits/try_samples/tree/master/blog/20230106/rust_nested_closure
[Terraform] terraform で CloudFront に BASIC 認証追加

Terraform で CloudFront Functions を作って、CloudFront に BASIC 認証追加する方法。

terraform の [template_file](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) プラグインを使うと、変数を受け取って展開してくれるので便利です。

```tf:template_file.tf
variable basic_user           { default = "basic_user" }
variable basic_password       { default = "basic_password" }
variable unauthorized_message { default = "Unauthorized" }

data template_file basic_auth {
    template = file("${path.module}/function.js")

    vars = {
        basic_auth_string    = base64encode("${var.basic_user}:${var.basic_password}")
        unauthorized_message = var.unauthorized_message
    }
}
```

function.js は、こんな感じで書いておけば `basic_auth_string` や `unauthorized_message` を terraform の `variables` で動的に設定可能。

```js:function.js
function handler(event) {
    var request = event.request;
    var headers = request.headers;
  
    var authString = "Basic ${basic_auth_string}";
  
    if (
      typeof headers.authorization === "undefined" ||
      headers.authorization.value !== authString
    ) {
      return {
        statusCode: 401,
        statusDescription: "${unauthorized_message}",
        headers: { "www-authenticate": { value: "Basic" } }
      };
    }
  
    return request;
}
```

CloudFront Functions を作成するには [aws_cloudfront_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_function) リソースを使います。


```tf:aws_cloudfront_function.tf
variable function_name  { default = "basic_auth" }
variable runtime        { default = "cloudfront-js-1.0" }
variable comment        { default = "" }

resource aws_cloudfront_function basic_auth {
    name    = var.function_name
    runtime = var.runtime
    comment = var.comment
    publish = true 
    code    = data.template_file.basic_auth.rendered
}
```


CloudFront にアタッチするには、`ordered_cache_behavior` や `default_cache_behavior` の中に `function_association` を追加します。

```tf
default_cache_behavior {
    :

    function_association {
        event_type   = "viewer-request"
        function_arn = aws_cloudfront_function.basic_auth.arn
    }
}
```

CloudFront Functions のコードは、以下の記事を参考にしています
[TerraformでCloudFront Functionsを環境ごとに有効化/無効化してみた](https://dev.classmethod.jp/articles/cloudfront-functions-per-env-terraform/)
GCP Cloud Buildにて Failed opening required 'srv/vendor/google/cloud-error-reporting/src/prepend.php'

# GCPでエラーレポーティングを設定する際にprepend.phpがうまく読み込めずハマったので記事にしておきます。

php.iniに正しいパスを指定しても`Failed opening required 'srv/vendor/google/cloud-error-reporting/src/prepend.php'`のようにファイル読み込みエラーが出てしまう場合には、参考になると思います。


App Engineのインスタンスでエラーが発生した場合にGCP Error Reportingにエラー内容を出力することができ、
その手順については[PHP 用 Error Reporting の設定](https://cloud.google.com/error-reporting/docs/setup/php)に以下の説明があります。

>エラーの報告
>次のコマンドを使用して、クラウド ライブラリをインストールします。
>```
>$ composer require google/cloud-error-reporting
>```
>次の行を php.ini に追加します。ここで、WORKSPACE はワークスペースのルート ディレクトリの絶対パスです。
>```
>auto_prepend_file='/WORKSPACE/vendor/google/cloud-error-reporting/src/prepend.php'
>```

とありますが、WORKSPACEを正しく設定しても以下のエラーが出るようになりました。


```
Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0

Fatal error: Unknown: Failed opening required 'srv/vendor/google/cloud-error-reporting/src/prepend.php' (include_path='.:/layers/google.php.runtime/php/lib/php') in Unknown on line 0
PHP Warning:  Unknown: failed to open stream: No such file or directory in Unknown on line 0
PHP Fatal error:  Unknown: Failed opening required 'srv/vendor/google/cloud-error-reporting/src/prepend.php' (include_path='.:/layers/google.php.runtime/php/lib/php') in Unknown on line 0
```

# 対策方法
php.iniから**auto_prepend_file**のパスを記述している行を**削除**し、プロジェクトの**ルート**フォルダにあるphpファイル（なければ作成）に以下を追加
```
require_once __DIR__ . '/vendor/google/cloud-error-reporting/src/prepend.php';
```

以上です。

<参考ページ>
- [Stackdriver Error Reporting on App Engine Standard for PHP 7.2](https://github.com/GoogleCloudPlatform/php-docs-samples/tree/6609166f71b1049f45360480963c2327b00b7959/appengine/standard/errorreporting)
- [PHP 用 Error Reporting の設定](https://cloud.google.com/error-reporting/docs/setup/php)
shellscript で、（RHEL）hostnaem, IP and サブネット, ゲートウェイ, DNSを設定

# 使い方
・引数に、「ホスト名」「IP & サブネット」「ゲートウェイ」「DNS」を入れて使用します。
![スクリーンショット (579).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478380/df8b6091-6573-bdb7-5a4e-165fbe37f669.png)
# ソース
```shell

#!/bin/bash

### 変数一覧
VAR1=$1 # ホスト名
VAR2=$2 # IPアドレス & サブネットマスク
VAR3=$3 # ゲートウェイ
VAR4=$4 # DNS

# ホスト名
sudo hostnamectl set-hostname "$VAR1"

### 固定IP
nmcli con mod enp0s3 ipv4.method manual
# IPアドレス
nmcli con mod enp0s3 ipv4.addresses "$VAR2"
# ゲートウェイ
nmcli con mod enp0s3 ipv4.gateway "$VAR3"
# DNS
nmcli con mod enp0s3 ipv4.dns "$VAR4"

### 設定反映 ###
nmcli connection up enp0s3

######### 作：夏目 智徹, Toshiyuki Natsume 2023 01 06

```
# ソース内容
それぞれのコマンドに、引数を割り当てているだけです。
サーバーリプレイスがあるので、これから色々シェルスクリプトを作っていくのが楽しみです。
Cプログラマーがnull文字と空文字の違いを理解する

違いをはっきりさせたいのですが、
以下の理解であってます？

### null文字を代入する

```
char *null_str;
null_str = 0;
```

### 空文字を代入する

```
char void_str[1];
void_str[0] = 0;
```
Salesforceサイトにファビコンを設定する

### サイトに設定する
`設定 > サイト`
編集画面の「サイトのお気に入りアイコン」に静的リソースにアップロードしたicoファイルを指定する。
静的リソースのキャッシュコントロールは公開に設定しておく。

### コミュニティサイトに設定する
`コミュニティビルダー > 設定 > 詳細 > ヘッドマークアップを編集`
下記を追加

```html
<link rel="icon" href="{basePath}/sfsites/c/resource/静的リソースのパス/favicon.ico?{versionKey}" type="image/x-icon">
<link rel="apple-touch-icon-precomposed" href="{basePath}/sfsites/c/resource/静的リソースのパス/apple-touch-icon-precomposed.png?{versionKey}">
```

`rel="apple-touch-icon-precomposed"`はiPhoneのWebクリップ用のアイコン。サイトのリンクをiPhoneのホーム画面に追加した際、表示される。


## 参考
- head マークアップ
    - [Experience Cloud サイトでカスタムファビコンを作成する | Help](https://help.salesforce.com/s/articleView?id=000383315&type=1)
    - [headへのマークアップの追加 | Help](https://help.salesforce.com/s/articleView?id=sf.community_builder_page_head.htm&type=5)
    - [Head Markup in LWR Sites | Developers](https://developer.salesforce.com/docs/atlas.en-us.exp_cloud_lwr.meta/exp_cloud_lwr/template_differences_markup.htm)
    - [エクスペリエンス ビルダーの「ヘッド マークアップの編集」と「ヘッド タグの編集」で追加されたメタ タグの違い | Help](https://help.salesforce.com/s/articleView?id=000380736&type=1)
- SEO
    - [Advanced SEO for Lightning Communities | Developers](https://developer.salesforce.com/blogs/2018/01/advanced-seo-lightning-communities)
    - [エクスペリエンスビルダーサイトの SEO | Help](https://help.salesforce.com/s/articleView?id=experience.networks_seo.htm&type=5)
- Apple
    - [Configuring Web Applications | Safari Web Content Guide](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html)
    - [App Icons | Apple Developer](https://developer.apple.com/design/human-interface-guidelines/foundations/app-icons#ios-ipados/)
- Google
    - [検索結果に表示されるファビコンを定義する | Google検索セントラル](https://developers.google.com/search/docs/appearance/favicon-in-search?hl=ja)
    - [Google 検索での構造化データのマークアップの仕組み概要 | Google検索セントラル](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data?hl=ja)
    - [URL の再クロールを Google にリクエストする | Google検索セントラル](https://developers.google.com/search/docs/crawling-indexing/ask-google-to-recrawl?hl=ja)
        - Google検索結果にファビコン等の変更を反映させるために必要
React – Uncaught Error: xxx is a void element tag

# エラー例

`react-dom.development.js:2942 Uncaught Error: input is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.`

# コード例

```js

function App() {
  return (
    <>
      <input>AAA</input>
    </>
  )
}

export default App;
```

# 解決

他の要素を囲えないタグには他の要素を入れてはいけない
単一で利用しよう

```js

function App() {
  return (
    <>
      <input value="AAA"/>
    </>
  )
}

export default App;


```

# 環境

next@13.1.1

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
giboで簡単に適切な.gitignoreを作成

## 概要
- [gibo](https://github.com/simonwhitaker/gibo)は、Gitの.gitignoreファイルのテンプレートを簡単に示してくれるシェルスクリプト。
- [gibo](https://github.com/simonwhitaker/gibo)を使用して、特定の環境用の.gitignoreを作成する。

## 前提
- OSはmacOS Venturaを使用する。　※OSの相違はインストールにだけ影響

## giboをインストールする。

```shell
% brew update     # Homebrew本体およびformulaを最新版に更新
% brew upgrade     # Homebrewでインストール済みのパッケージを最新版にアップグレード
% brew install gibo     # giboをインストール
```

## giboが対応しているboilerplates（テンプレート）を調べる。

boilerplatesのリストを更新する。

```shell
% gibo update
```

対応しているすべてのboilerplateを表示する。

```shell
% gibo list
Actionscript			Red						LibreOffice				Lua
Ada						ROS2					Linux					Magento
Agda					SPFx					LyX						Maven
AL						Splunk					macOS					Mercury
     （途中省略）
Puppet					JetBrains				Leiningen				Yeoman
JupyterNotebooks		Kate					LemonStand				Yii
Nikola					KDevelop4				Lilypond				ZendFramework
Racket					Lazarus					Lithium					Zephir
```

キーワードが含まれるOSやプログラミング言語等のboilerplateを検索する。　※大文字・小文字は区別されない

```shell
% gibo search キーワード
```

## .gitignoreファイルを新規に作成する。

例えば、macOSでHugoのリポジトリを作成する場合。

```shell
% cd ~/GitHub/リポジトリ名     # .gitignoreファイルを作成したいリポジトリに移動
% gibo dump macOS Hugo > .gitignore     # 「>」なのでファイルを新規作成（あるいは既存ファイルを上書き）
```

## 既存の.gitignoreファイルに追記する。

例えば、XcodeとSwift関連ファイルを追記する場合。

```shell
% cd ~/GitHub/リポジトリ名     # 追記したい.gitignoreファイルがあるリポジトリに移動
% gibo dump Xcode Swift >> .gitignore     # 「>>」なので既存ファイルに追加（ファイルがなければ新規作成）
```

## その他の主なコマンド

```shell
% gibo help     # ヘルプを表示
% gibo root     # boilerplatesが保存されているディレクトリ名を表示　※文例を自分で修正可能
% gibo version     # バージョンを表示
```
Salesforce Dynamo Connectorを試す

# AWS Dynamo
1. aws.amazon.comにサインアップ/ログイン
1. コンソールのホームからDynamoDBサービスへ移動
1. テーブルの作成
    1. テーブル名：member
    1. パーティションキー：no、数値
1. memberテーブルに入り、右上のアクションから項目を作成
    1. no：1
    1. 新しい属性の追加
        1. 文字列、name、鈴木一郎
        1. 文字列、birthdate、2000-01-17
1. 項目を作成
    1. no：2
    1. 新しい属性の追加
        1. 文字列、name、佐藤二郎
        1. 文字列、birthdate、(空欄)
    1. 左ペインのPartiQLエディタでクエリを試してみる
        1. ```select * from member```
        1. ```select * from member where birthdate = ''```

# AWS ユーザー、アクセスキー
1. AWSコンソールのホームからIAMサービスへ移動
1. 左ペインのユーザー
1. 右上のユーザーを追加
    1. ステップ1
        1. ユーザー名：from_salesforce_to_dynamo
        1. AWS 認証情報タイプを選択：アクセスキー
    1. ステップ2
        1. アクセス許可の設定：既存のポリシーを直接アタッチ
        1. ポリシー：AmazonDynamoDBFullAccess
        1. アクセス権限の境界の設定：アクセス権限の境界を設定せずに user を作成する
    1. ステップ3、4
        1. なし
    1. ステップ5
        1. .csvのダウンロード ★1

# Salesforce 指定ログイン情報
1. trailhead.salesforce.comにサインアップ/ログイン
1. 右上のアイコンからハンズオン組織
1. Playgroundを作成、起動
1. 右上の歯車アイコンから設定
1. 左上のクイック検索から指定ログイン情報
1. ▼から新規(従来)
    1. 表示ラベル：Dynamoログイン情報
    1. 名前：DynamoLoginInfo
    1. URL：https://dynamodb.ap-northeast-1.amazonaws.com ※Dynamoが東京リージョンの場合
    1. ID種別：指定ユーザ
    1. 認証プロトコル：AWS 署名バージョン 4
    1. AWS アクセスキー ID：★1
    1. AWS シークレットアクセスキー：★1
    1. AWS リージョン：ap-northeast-1 ※Dynamoが東京リージョンの場合
    1. AWS サービス：dynamodb ※固定値

# Salesforce 外部データソース
1. Salesforceの設定の左上のクイック検索から外部データソース
1. 新規外部データソース
    1. 外部データソース：Dynamoデータソース
    1. 名前：DynamoDataSource
    1. 種別：Amazon DynamoDB
    1. 指定ログイン情報：Dynamoログイン情報
    1. 書き込み可能外部オブジェクト：TRUE
1. 検証して同期

# Salesforce 外部オブジェクト
1. Salesforceの設定の左上のクイック検索から外部オブジェクト
1. 新規外部オブジェクト
    1. 表示ラベル：会員
    1. 名前：Member
    1. 外部データソース：DynamoDataSource
    1. テーブル名：member ※Dynamo側のテーブル名と大小文字まで一致

# Salesforce 外部データソースの同期
1. Salesforceの設定の左上のクイック検索から外部データソース
1. DynamoDataSourceに入る
1. 検証して同期
    1. Memberをチェックして同期

# Salesforce 外部オブジェクトに項目作成
1. Salesforceの設定の左上のクイック検索から外部オブジェクト
1. 会員オブジェクトに入る
1. カスタム項目 & リレーションの新規
    1. ステップ 1. データ型の選択
        1. データ型：外部参照関係
    1. ステップ 2. 関連外部オブジェクトの選択
        1. 関連先：会員
    1. ステップ 3. 参照項目の表示ラベルと名前を入力
        1. 項目の表示ラベル：氏名
        1. 文字数：255
        1. 項目名：Name
        1. 外部列の名前：name
        1. 子リレーション名：Name
    1. 以後、デフォルト
1. カスタム項目 & リレーションの新規
    1. ステップ 1. データ型の選択
        1. データ型：外部参照関係
    1. ステップ 2. 関連外部オブジェクトの選択
        1. 関連先：会員
    1. ステップ 3. 参照項目の表示ラベルと名前を入力
        1. 項目の表示ラベル：生年月日
        1. 文字数：10
        1. 項目名：Birthdate
        1. 外部列の名前：birthdate
        1. 子リレーション名：Birthdate
    1. 以後、デフォルト

# 動作確認
1. Salesforceの右上の歯車アイコンから開発者コンソール起動
1. 画面下部のQuery Editorタブを開き、以下のクエリーを実行 → AWSのレコードが表示される
    1. ```select Id, ExternalId, Name__c, Birthdate__c from Member__x```
1. 空欄のBirthdate__cをダブルクリックし、なにか値を入力し、Save Rowsボタン押下
1. AWSの左ペインのPartiQLエディタでクエリーを実行 → Salesforceでの入力内容が表示される
        1. ```select * from member```

# 疑問
1. Dynamoのパーティションキーに対するSalesforceのカスタム項目を作成すると、Salesforceでの検索時に```外部データソース「DynamoDataSource」の外部オブジェクトレコードを作成できません。主キーの値を確認してください。```エラーになってしまう、当該カスタム項目を削除すると治る
1. Salesforceでの検索時に「生年月日が無い」との条件で検索できない。whereに```= null```とか```= ''```とか指定しても検索結果なしになってしまう
Fcitx5で左シフトキーを単押したら入力方法が切り替わる設定をやめるには

fcitx5-configtool(GUIで表示したら分かりやすい)のGlobal OptionsのHotkeyにおいてTemporally switch between first and current Input Method:のキーがLeft Shiftになっていないか確認してみてください。

1行記事となってごめんなさい。

# この症状が気になった経緯
Fcitx5でSKKを使うようになったところで、シフトキーを多用して見出し語の定義をしようとした際で、見出し語の始まりに迷いシフトキーを単押ししたら「入力方法がSKKから直接入力に戻ってしまう」症状が生じました。
パッケージマネージャyayで認証用コマンドをsudoじゃなくてdoasにする方法

# TLDR
1. `yay --sudo doas --save`(参考文献1のスレ主Klutzy-Ad-6528の冒頭の投稿から引用)

または

1. `$XDG_CONFIG_HOME/yay/config.json`(ファイル名は参考文献2から引用)を編集して`"sudobin": "doas",`とする。

# 参考文献
1. [How do I make yay use doas instead of sudo? (/r/archlinux)](https://teddit.net/r/archlinux/comments/vnoqg6/how_do_i_make_yay_use_doas_instead_of_sudo/)
2. man 8 yay
[CircleCIのセキュリティインシデント対応] Railsのmaster keyをローテーション(再生成)する

大した情報ではないですが、
circle ciでRailsを使っている人への注意喚起になればと思います。

## 話の発端
2023/04/01 CircleCIで管理しているセキュア情報が漏洩したかもらしい

https://circleci.com/blog/january-4-2023-security-alert/

## 環境
- Ruby on Rails: 7.0.2
- Ruby: 3.1
- ruby:3.1.0 をベースイメージにしたコンテナ内で作業

## 再生成していく
今回は例として、production用のcredentialsを再生成します。

#### ① 現状のcredentialsをメモする
```bash
# 現状のcredentialsをメモ帳などにコピー
$　rails credentials:show -e production
db:                        
  username: hoge               
  password: huga
```

#### ② credentialファイルとmaster.keyを削除する
```bash
# 念の為バックアップしておく 
$　cp -r config/credentials config/credentials_bkup

# keyファイルとcredentialファイルを削除
$ rm config/credentials/production.key
$ rm config/credentials/production.yml.enc 
```

#### ③ credentialファイルとmaster.keyを生成して書き込む
```bash
# EDITOR=vim rails credentials:editで新しいcredentialファイルとkeyを生成し、
# 先ほどメモした情報を貼り付ける
$ EDITOR=vim rails credentials:edit -e production
db:                        
  username: hoge               
  password: huga


# 保存をして、vimを閉じると以下のようなメッセージが出れば成功
adding config/credentials/production.key to store the encryption key: xxxxxxxxxxxxxxxxxxxx

Save this in a password manager your team can access.

If you lose the key, no one, including you, can access anything encrypted with it.

      create  config/credentials/production.key
```

#### ④ CircleCIの情報を更新
`RAILS_MASTER_KEY` の環境変数で保存しているはずなので書き換える

## 正常に複合できるか確認
`Rails.application.credentials.config`を表示できれば成功です。
　余計な空白などないか確認しておきましょう。

```bash
$ RAILS_ENV=production rails c
Loading development environment (Rails 7.0.2)

irb(main):001:0> Rails.application.credentials.config  # 確認
=> 
{:db=>{:username=>"hoge", :password=>"huga" }}
```


## 参考
https://qiita.com/naokit-dev/items/5e09b2fb4b64a29712e4

https://linyclar.github.io/rails_memos/commands/credentials/
RPKMとTPM

RPKM (reads per kilobase per million mapped reads) とTPM (transcripts per million) はいずれも次世代シーケンサー (Next Generation Sequencer, NGS) で測定したカウントデータの正規化法です。

参考ページ:
* https://bi.biopapyrus.jp/rnaseq/analysis/normalizaiton/fpkm.html
* https://bi.biopapyrus.jp/rnaseq/analysis/normalizaiton/tpm.html
* https://gikenbio.com/look-up/tpm/

縦方向に転写産物、横方向にサンプルが並んでいるとします。列毎に正規化してから行毎に正規化するのがRPKM、行毎に正規化してから列毎に正規化するのがTPMです。


列毎の正規化は、サンプル毎のリード数の違いを揃えるために行います。行毎の正規化は、転写産物毎の遺伝子長の違いを揃えるために行います。

Pythonのコードを以下に示します。カウントデータ (2次元配列、データフレーム) と遺伝子長データ (1次元配列) を用意します。
```
# INPUT:
#   count_df: count data (row: transcripts, columns: samples)
#   len_sr: length data (1-dim sequence (pd.Series, np.Array, etc.))
# OUTPUT:
#   rpkm_df: RPKM data
#   tpm_df: TPM data

# count > RPKM
rpkm_df = count_df / count_df.sum()
rpkm_df = rpkm_df.divide(len_sr, axis=0)
rpkm_df *= 10**9

# count > TPM
tpm_df = count_df.divide(len_sr, axis=0)
tpm_df = tpm_df / tpm_df.sum()
tpm_df *= 10**6
```
自動型変換　キャスト

***型変換***
「+」などの操作は同じデータ型同士じゃないとできません。
型の違うものを演算するときは、型を変換し同じ型にする必要があります。
javaでは自動変換あります。

```java:Main.java
System.out.println("佐藤さんは"+20+"歳です");
```

`String型`と`int型`を足すと、`int型`が自動で`String型`に変換されて、文字列として結合されます。
```
"佐藤さん" + "20" + "歳です"
```
こんな感じです。
なので、出力は
```text:java.コンソール
佐藤さんは20歳です
```
***計算時の自動変換***

`int型`と`double型`の計算結果は`double型`になります。
計算の過程でint型がdouble型に変換されます。

ここで、今まで触れてなかったので補足です。
`double型`とは、小数を表すデータ型です。
```
5     int型
3.14　　　　double型
```
他にも多くのデータ型があります。それを全て説明するのは、今の私にはまだ無理なので、
リンク貼っておきます。
[基本のデータ型](https://www.javadrive.jp/start/var/index4.html)

では、話は戻ります。
`5 / 2.0`もしくは`5.0 / 2`の結果は`2.5`になります。`5`を`5.0`にするように、Javaが自動で型変換を行ってくれます。
```java:Main.java
System.out.println(5.0 / 2);
```
上記が下記のように`double型`に変換される。
```java:Main.java
System.out.println(5.0 / 2.0);
```
```text:java.コンソール
2.5
```
ここで注意点です。
int型同士の計算は結果もint型になり、double型同士の計算は、結果もdouble型になります。特に、int型の5をint型の2で割ると、結果は「2.5」ではなく「2」となり出力結果が変わるので注意しましょう。  
            
```java:Main.java(int型)
System.out.println(5 / 2);
```
```text:java.コンソール
2
```

```java:Main.java(double型)
System.out.println(5.0 / 2.0);
```
```text:java.コンソール
2.5
```
となります。

さっき見た通り`int型`同士は正確な値を割り出せません。
```java:Main.java
int number1 = 13;
int number2 = 4;
System.out.println(number1 / number2);
```
```text:java.コンソール
3   //正しい値は3.25
```
これを強制的に変換し、正しい値を出力することができます。
この方法を,```キャスト```と言います。
int型同士の値から、最終的にdouble型の計算結果を得たい場合、どちらか1つをキャストします。
```java:Main.java
int number1 = 13;
int number2 = 4;
System.out.println((double)number1 / number2);
```
この様に、どちらか一つを`double型`にキャストすれば結果は、`double型`になります。

```text:java.コンソール
3.25
```
Google ColaboratoryでGoogle Driveからcsvファイルなどを読み込む

# 概要
Colab上でのファイルの読み込みや、自作pyファイルのインポートなどのやり方を備忘録のために記します。

# Google Driveへファイルをアップロード
自分がプログラムで読み込ませたいcsvやtxt,pythonなどをDriveへアップロード。
Colabで継続的に使うものであれば専用フォルダを作って整理するとよい。

# Google Driveをマウント
Colab上で以下を実行
```
from google.colab import drive
drive.mount('/content/drive')
```
初回はいろいろと許可が求められる。

# パスのコピー
画面左のフォルダのアイコンをクリックすると、自分のGoogleDriveが接続されている。


![スクリーンショット_20230106_135708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782857/762e35bc-ece9-c136-5b96-bdc9484933f4.png)

後はMyDriveから任意のファイルにたどり着き、ドット3つのアイコン→「ファイルのパスをコピー」を選択。
プログラムに張り付ける

```
import pandas as pd
df = pd.read_csv("/content/drive/MyDrive/Colab Notebooks/score.csv", encoding="SHIFT-JIS")
df.head()
```
OracleでSELECT時にデータと同時にレコード数も取得

# 概要

OracleのSELECT結果をそのまま画面表示。
さらに取得結果が〇レコード超えていたら警告。
といったことをしたい。

2回SELECTしたり、アプリケーション内でレコード数カウントせずに、1回のSQLでやりたい。

# やり方

```COUNT(*) OVER()``` で『レコード数のカラム』を用意できる。

```sql:サンプルSQL
SELECT
COUNT(*) OVER() AS record_count,
テーブル名.*
FROM テーブル名 
```

```COUNT(*)``` だけだと結果が1レコードだけになってしまい、『データと同時に』が満たせない。
```OVER()``` を付けてあげることでその条件を満たせる。

# WHEREで絞り込んだ結果に対するレコード数なので注意

例えば下記の場合、テーブル名のレコード数が999でも『record_count』の値は100。
（999ではない）

```sql
SELECT
COUNT(*) OVER() AS record_count,
テーブル名.*
FROM テーブル名 
WHERE ROWNUM <= 100
```

行数を絞り込みしつつ、『絞り込みしなかった場合のレコード数』を取得したい場合はサブクエリを使う。

# 参考サイトさん

https://oracle.programmer-reference.com/oracle-select-count-data/

# バージョン

Oracle Database 11g Release 11.2.0.1.0 - 64bit Production

TODO:MAX(ROWNUM) OVER()でも実現可能だが、どの方法が一番処理軽い？
【Vue3】コンポーネント間の受け渡し

つい忘れてしまうので備忘録として。

- バージョン：Vue 3 
- ` <script setup>` 構文（https://v3.ja.vuejs.org/api/sfc-script-setup.html）


```vue: 親コンポーネント名
<parent-hoge>
```

```vue:parent-hoge
<script setup lang="ts">
    //ここに処理
</script>
<template>
    <child-fuga></child-fuga><!-- 子コンポーネント -->
</template>
```
### 親→子にデータの受け渡し
```vue:parent-hoge
<child-fuga :data-gohan=“`ごはん`” :gohan-type="15">
```
```vuejs:child-fuga
<script setup lang="ts">
    //受け取るデータの型を定義
    interface Props {
      gohanType?: number;
      dataGohan?: string|null;
    }
    //withDefaults: propsのデフォルト値を定義
    const props = withDefaults(defineProps<Props>(), {
      gohanType: 1
      dataGohan: null
    });
    
    console.log(“data-gohan:”, dataGohan) //ごはん
    console.log(“gohan-type:”, gohanType) //15
</script>
```

### 親→子のイベント実行
```vue:parent-hoge
<template>
    <!-- 名前をつける -->
    <child-fuga ref=“childFugaRef">
</template>

<script setup lang="ts">
    const childFugaRef = ref();
    const testEvent () => {
        childFugaRef.value.fugafugaEvent()
    }
</script>
```

```vue:child-fuga
<script setup lang="ts">
    const fugafugaEvent () => {
    	console.log(“子コンポーネントのイベント発火”)
    }
    // 親に渡す
    defineExpose({
      fugafugaEvent
    })
</script>

```


### 子→親のデータの受け渡し
```vue: child-fuga
<script setup lang="ts">
interface Emits {
  (e: 'get-fuga-gohan', v: string): void
}
const emit = defineEmits<Emits>()

const gohanName: string = "しらすごはん"

//親にdataを渡す
emit('get-fuga-gohan', gohanName)
</script>
```

```vue: parent-huga
<template>
    <child-fuga @get-fuga-gohan="fugaGohan">
</template>

<script setup lang="ts">
    const fugaGohan = (e) => {
        console.log("get-fuga-gohan:", e) //しらすごはん
    }
</script>
```
IT系独り言（日々更新中）

# 12/30　棚卸し
* 英語スキル　★★★★　→　Audible　今年は七本ぐらい聞きました。
* FOREX　★★　→　ボーナス５万を投じて、いま７万。OandaでAutochartist使ってます。システム化したい
* Youtube ★★★★★　→　Suno.Ai、最高です。これからの音楽シーンが怖すぎ！
* Redmine　★　→　Jira,Asana,Backlogいろいろ有りすぎ。個人的には以下がおすすめ

Easy MindMup plugin
https://www.easysoftware.com

Easy WBS plugin
https://www.easysoftware.com


# 12/08
* 横浜に転勤、今はソフト開発部門にいます。車載システムなどのＶ字開発モデルについて学習中

# 9/22
* 2か月ほどＩＴエンジニアから遠ざかる　→　10月から部門が変わり、現職で書き続けていた意味が無くなりそうである。

# 7/9
* ITエンジニアとしてのモチベーションがどんどん低下している
→　自分はやはりクリエーターなのかもしれない。
* 物事を作り出す快感に生成ＡＩは使える　→　https://www.youtube.com/watch?v=cth072gMqqQ

# 6/27
* Github copilot https://qiita.com/flutter_daisuki/items/6d6e663a089c1a26fa56
⇒　社内で進められて再度サブスク契約　→　しかしCHATGPTの方が10000倍使いやすいのは気のせい?

# 6/20 流れてきた情報
* https://github.com/AntonOsika/gpt-engineer 
→　CHATGPTでコンテンツを生成する。コード、スクリプト、音楽、電子メール、手紙などを生成

# 6/5-6/8 
* 人工知能学会に参加しました　→　配信のZOOMを片っ端から録画（ぜんぶで９５０以上・・・って、無理やわ）

# 6/2
* Redmine-view-customize →　HTML要素のID名について質問している
→　ここがクリアにならないと、カスタマイズが面倒になる（ID名をブラウザ開発ツールで調べないと分からないのは、ハードルが高くなってしまう）

# 5/28
* Redmineカスタマイズの仕方　→　redmine-view-customize-scripts　⇒　便利！
→　いろいろとJQueryでカスタマイズできて、楽しくなってきた
* CHATGPTプラグイン　→　プラグイン to プラグイン(Fastapi)で実現する方法に行きついた！

# 5/25
* OutlookからREDMINEチケットの登録　→　VSTOにてリボンメニューに投稿ボタンを作るところまで完成
* ゆっくり動画エディタ　→　テント画像の作成　https://youtu.be/u0CsKraiMUg
* Redmineプラグインの作り方（CHATGPT)を調べている

# 5/20
* Redmineからoffice365へのSMTPサーバー構築　→　ようやく解決案まとまる
* 少しFXのプログに集中　→　楽天ポイントを投資に回す　　https://motochan1969.hatenadiary.jp/entry/2023/04/17/080557

# 5/14
* Fastapiでのログイン認証とデータベースのマルチユーザー化について学ぶ。
* REACT+FASTAPIをセットにしたような、Pythonフレームワークは無い物か　→　Chatgpt先生の回答

>PythonでReactを使う場合は、通常は前述したDjango REST frameworkやFastAPIなどのフレームワークを使用して、RESTful APIを提供しつつ、フロントエンドは別途ReactなどのJavaScriptフレームワークを使用する方法が一般的です。

→　無いみたい・・・ がっくし

# 4/20
* 期が変わり上期の計画表を作る必要があり、急遽であるがMindmap（Redmineフロントエンド開発）に着手
→　ＪＳライブラリの選定に時間を要するが、ようやく技術選定を終了

# 3/22
* この2か月ばかり、かなりCHATGPTから派生したタスクで、右往左往していた。
→　ようやく正気を取り戻し、通常業務に戻れる状態になった。😥やれやれ

# 1/24
* CHATGPTで遊んでいたらサーバーがパンクした。
→　こっちが使えるらしい　https://beta.openai.com/playground?model=text-davinci-003

# 1/22 React / Next / Parcel

(REACT)　https://create-react-app-yamap-y6hp.vercel.app/
(NEXT)　https://nextjs-yamap.vercel.app/

若干だがREACTよりも、NEXTの方が読み込みが速かった。
Staticデータの保存先がよく分からずに、結局、PARCELは動かなかった。

# 1/17
* JupyterLab Windows版で、JavaScript/TypeScript が書ける環境を構築しました。
→　ポイントはminicondaの仮想環境を使う事でした。

# 1/15
* JavaScript学習　PARCELを使い始めました。
　https://www.youtube.com/watch?v=D3EZ9dvjuHI

# 1/7
* PC購入　→　PCWRAPで格安PCを入手(13800円)
* AMAZONエコー  →　スキル作成に時間がかかる　→　AMAZONもエコー縮小の話がある
* MP3ポッドキャスト　→　ヘッドホンなど耳元で聞くのは、耳を傷めるのでやめた。　→　外出と就寝時は仕方ない・・・
* ノートPC　→　音声を流し、同時にGoogleドキュメントでテキスト化

# 1/6
* 仕事はじめ　→　Redmineで目標を決めて、今年こそは使いこなそうと決意する
* Outlook　→　メールの堀起こし。スパムメールに埋もれながら、あくせく新規メールを探す。なんてＩＴ奥手な会社なんだろうか・・・（ちなみに東証一部上場の超一流メーカーです）

# 1/5
新年が明けたので、スレッドを更新することにした。

過去データ（2022）

https://qiita.com/EasyCording/items/b4f4e8874a31fa76e5c6