OmniAICreator/Qiita-1.07M huggingface dataset:
日本語wikipedia情報(タイトル＋本文)をBigQueryに投入する

# 1.はじめに
* 日本語wikipediaのデータをBigQueryに投入した。
* [wikiextractor](https://github.com/attardi/wikiextractor)というライブラリと、pandasではなくて [polars](https://www.pola.rs/)を利用した。

# 2.日本語wikipediaデータを使いたい
* [「最も「ありそうで存在しない漢字」は何か？」](https://qiita.com/hakatashi/items/e5f803e3476fd4a75b55)を読んで「ありそうでない熟語」をどう作ればいいかなと実験したくなり、その中で日本語wikipediaデータをBigQueryに投入したくなった。
* 他の投稿を見るとMySQLデータをcsvにしてから投入するのが楽そう、と思ったけど、python（というかColaboratory）でやるとしたらどうするのかと検討して下記のような方法を思いついた。


# 3.日本語wikipediaデータを取得する。
* いろいろなメタデータもあるみたいだけど、本文と見出しがあればいいので、下記のファイルを指定してダウンロード。
```python
!curl -o jawiki-latest-pages-articles.xml.bz2 https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2
```

でOK。

# 4.データ加工（ライブラリ）
*  [wikiextractor](https://github.com/attardi/wikiextractor)を使う。
* 直接bz2を指定できるので楽。コマンド一覧を見て、のちの利用を考えて--jsonを指定しておくのがミソでした。抽出に少し時間がかかった。

```python
!pip install wikiextractor
!python -m wikiextractor.WikiExtractor /content/jawiki-latest-pages-articles.xml.bz2 --json

```

このような感じに抽出結果が適当なサイズに分かれてtextフォルダ以下に入っている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/53d86b69-0d84-bcb2-bc1a-ee9f6f3820af.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/6aece624-f0a8-d662-b3e8-55af5c92f20f.png)


# 5. データフレームに入れてcsvに吐き出す。
* 抽出結果が、textフォルダ以下に入っているので、１jsonファイルに集めていく。

```
!cat text/*/* > alljson.json
```

* これをpandasで入れようとするとクラッシュするので、[polars](https://www.pola.rs/)で実行。

```python
#!pip install polars
import polars as pl

df = pl.read_ndjson("alljson.json")
df.write("wikidata20230113.csv")
```


# 6. BigQueryに投入

```python
#from google.colab import auth 
#auth.authenticate_user()

#GCSにコピー
!gsutil cp /content/wikidata20230113.csv gs://**適当な場所**/wikidata20230113.csv

```

あとはGCSからBigqueryに投入。220万記事くらいあった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/da0a79c0-2dc1-aadf-32fe-2483b5f1f219.png)


* その後、抽出されたjsonファイルを見るとjsonlだったので、ばそのままBigQueryに投入できる？と思ったので試してみたらできた!ステップ５が不要でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/6754f882-16fe-de1a-f2d1-633099d4cfcc.png)
【AWS】SESのBounce Rate とComplaint Rate についてまとめる

## はじめに
AWSのSESの Bounces Rate と Complaint Rate についてまとめたいと思います。

## Bounce Rate とは？
- 配信されたメールのうち、受信サーバーから戻されたために届かなかったメールの割合のこと
- **Bounce** とは、日本語に訳すと「跳ね返る」「バウンドする」という意味

バウンスは、以下の2種類があります。

- **Hard Bounce(ハードバウンス)**
    - 永続的なEメールの障害
        - 例: ドメインそのものやメールアドレスが存在しない宛先不明の場合
- **Soft Bounce(ソフトバウンス)**
    - 一時的なEメールの障害
        - 例: メールボックスが容量を超えている、接続が多い、接続のタイムアウト

### Bounce Rate が高まると？
- アカウントのEメール送信機能を一時的に停止される可能性がある
    - Bounce Rate が **10%** を超えた場合に一時停止される可能性がある
    - AWSの推奨としては、Bounce Rate を **5%** 未満に保つこと

## Complaint Rate とは？
- アカウントから送信され、受信者によってスパムと報告されたメールの割合のこと
    - 受信者から迷惑メールだと報告されたメール
- **Complaint** は、日本語に訳すと「苦情」という意味

### Complaint Rateが高まると？
- アカウントのEメール送信機能を一時的に停止される可能性がある
    - Complaint Rate が **0.5%** を超えた場合に一時停止される可能性がある
    - AWSの推奨としては、Complaint Rate を **0.1%** 未満に保つこと

## 参考
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ses-reputation-dashboard-bounce-rate/

https://docs.aws.amazon.com/pinpoint/latest/userguide/channels-email-deliverability-dashboard-bounce-complaint.html

https://tech.connehito.com/entry/2020/09/17/152126
[Python] PyAutoGUI 複数画像のどれかが表示されたらクリックする

作ったプログラムの備忘録

# はじめに
PyAutoGUIにおいて画像認識でクリックさせる場合に、ソフトウェアの前回使用時の設定によって表示される画像が異なる状況が発生したので、複数画像のどれかが表示された場合にクリックできるようにした。

単純な待機処理とクリック処理は以下に記載。

https://qiita.com/takafi/items/48f146e1315ff19444bb

## 動作テスト環境
OS: Windows 10 Pro 64bit
言語： Python 3.9.13
ライブラリ：PyAutoGUI 0.9.53


# ソースコード
```Python:
import pyautogui
from time import sleep

def plural_search_click(images):
    for i in range(300):
        for img in images:
            try:
                if pyautogui.locateOnScreen(f'./img/{img}', grayscale=True, confidence=.8):
                    get_img = img
                    break
            except pyautogui.ImageNotFoundException:
                pass
        if 'get_img' in locals():
            click_img(get_img, 0.1)
            break
        sleep(0.2)
        
def click_img(img, sleeptime):
    p = pyautogui.locateOnScreen(f'./img/{img}', grayscale=True, confidence=.8)
    x, y = pyautogui.center(p)
    pyautogui.click(x, y, button='left')
    sleep(sleeptime)

plural_search_click(['image01.png', 'image02.png'])
```

* PyAutoGUIのlocateOnScreenは1つの画像しか認識できない＋try文での例外処理も1つしか補足できないので、for文でlocateOnScreenを複数画像分回して、存在したときだけ変数格納させます。

* その後`if 'get_img' in locals():` で変数が定義されたときだけ、その画像でクリックする関数を呼び出して、待機処理ループを抜けます。

* ここでは関数の引数として画像のファイル名をリストで渡すようにしています。`['image01.png', 'image02.png']`
命名って難しい - 命名で気をつけてること

# はじめに
突然だが、世のエンジニアは変数名をいとも簡単につけているのだろうか？少なくとも私はいまだに変数名やメソッド名、カラム名などの命名に苦悩する日々を送っている(センスがない)。

つい先日、自分が不特定多数の別ユーザーに対してアクションを行った履歴データをDBから取得し、インスタンス変数に詰める際にその変数の命名で1時間ほど迷った。

頭の中「自分のアクションだからmyActionHistoryか？でも別ユーザーから自分に対してアクションした場合の変数も必要になった時を考慮して、actionByMeHistoryにすれば、actionBy◯◯Historyとできるから拡張性が少しは上がる？いや、actionToOtherUsersHistoryか？いやでも...」

こんなことをぐるぐる考えて約1時間。。。1時間もたってる！？このとき、命名の難しさを改めて感じた。
今回はこんな私でも命名する上で、気をつけていることを列挙してみようと思う。

## dataやinfoは使わない
dataやinfoという単語はソース上で数多く見るが、これらは使わないようにしてる。
ユーザー情報を格納する変数として、userData,userInfoを例に挙げてみよう。、、、データ(data)なのは当たり前だし、情報(info)なのも当たり前なのでは？それならuserやusersのような命名にすべき。

## Listはなるべく使わない
これは正直どちらでもいいと思うが、Listという単語をあまり変数名などで使わないようにしている。
例えば以下のコードでは、Userクラスでユーザー情報を管理していて、リストに詰めている。ただこの場合、何度もListが出てくる。userListと命名するなら、usersの方がスッキリしているし、複数のユーザー情報が格納されていることが伝わると思う。
```sample1.kt
List<User> userList = new ArrayList<User>();

List<User> users = new ArrayList<User>();
```

ちなみに前述のものと合わせ技で、dataListなどという命名は絶対にしないようにすべき。なんのデータなのか、なんのリストかが何も伝わらない。読み手のことを考えた命名を意識すべき。

## 真偽値でFlagは使わない
例えば、その要素が有効なデータかどうかを管理する際の命名を、validFlagのような命名にはしない。この場合は、isValidにすべき。なぜならフラグにすると、複数解釈ができてしまうから。事実、フラグのonとoffが逆なのではないかと思う変数やカラムを数多くみてきた。
また、isInValidのような否定的な語句の変数名もよくない。これだと以下のような条件式の際に否定の否定で訳が分からなくなるから（私だけ？）。isValidの方がパッと見で伝わる。

```sample2.kt
val isInValid = true
if (!isInValid) { // 無効ではない場合　＝　有効
}

val isValid = true
if (!isValid) { // 有効ではない場合
}
```

ちなみにisから始まる命名で真偽値を全てつけようとするとisExistのように意味は通るけど、英語的にダメなものもある。existは動詞なのでisとくっつけられない。存在するかどうかの場合はexistでもいいと思う。

is以外で始める場合は、動詞か助動詞を使えばいい。何かを所持しているかどうかはhas、含まれているかどうかはcontains、できるかどうかはcan（もしくはis〜able）。有効であるかどうかは、isValid。
よく使われるのはこの辺かと。

## 日付を取り扱うカラム名は過去形にする
変数名というよりはDBのカラム名に特化した話だが、日付情報をDBに登録する際には、過去形にすべきだと思う。理由としてはDBに情報が登録された段階で、処理が完了した時点の日付なので、過去形で作成であり、前置詞はatにする。例としてはcreated_atとかupdated_atなど。

## masterは使わない
海外では、masterという単語は主人という意味が強くなるらしい。制御する側がmaster(主)、制御される側がslave(奴隷)という印象が残るようだ。また、blackListなども変数名としては向かない（あまり使わない命名だと思うが）。グローバルサービスなどでは、この辺りも気をつけるべき。
代替案としては、main/replicaなどだろう。Githubのデフォルトのメインレポジトリ名もmasterではなく、mainである。DBのテーブル名は、user_masterやitem_masterよりもusersやitemsなどの命名にすべき。

## 意味が伝わらないくらいなら、長くなってもいい
どれだけ長く考えても、いい命名が思いつかない場合がある。短くて分かりやすい命名がベストだと思うが、短くして意味が伝わらない変数名より長くてもこういうデータを格納してる、ということが分かる命名の方がいいはずだ。
最初に例に挙げた「自分が不特定多数の別ユーザーに対してアクションを行った履歴データ」を詰めた変数名に、私は最終的に「actionFromMeToOtherUsersHistory」と名付けた（なげー名前。。。）
正直もっと良い命名があっただろう、それでも頭を悩ませずに適当につけた命名よりは分かりやすいはず。

# 最後に
人から見たときに伝わりやすいこと、格納しているデータを分かりやすく表現できているかどうか、その命名が英文法としておかしいかどうか、命名においてはこの辺が重要だと思う。命名の分かりやすさは、コードの読みやすさやバグの防止につながる。たかだか命名などと考えず、熟考すべき。

そんな私もここ数年は命名について気をつけるようになったが、それ以前に私がなんとなくつけた変数やメソッド名、カラム名はどうなったのだろう。その後、あの変数たちがどうなったのかもう知る術はない。。。
kintoneプラグインでbootstrapを適用するとメニューにアンダーラインが入る問題をcssで解消

最近はkintoneプラグインばかり作っている本橋です。今回は小ネタ。

プラグインで画面を作るときにスタイル指定とかはあんまり凝りたくないのでbootstrapを使います。

そうすると、bootstrapのcssがあらゆるアンカーリンクにアンダーラインを入れてしまう問題に遭遇します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13915/c6470207-2d16-cbdf-6d35-782395379a00.png)

このへんとか、


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13915/7315fc3d-d3a9-b208-83ce-a1777b32b623.png)

このへんとかにアンダーラインが入って嫌ですね。



# 対処法

cssに下記のスタイルを加えて解消しました。

```
/** bootstrap対策 */
.gaia-argoui-menuitem, .gaia-argoui-pulldown-item-text, .gaia-argoui-pulldown-item {
    text-decoration-line: none !important;
}
```

僕の場合は ./plugin/css の中に config.css とか desktop.css とか置いているので、それぞれに追記しています。

以上、小ネタでした。
【Vue3 + TypeScript】$storeがエラーになった件 

## エラー内容
よくわからないです。
![214758675-a1007b3a-fa6f-47a6-8e21-d880e6e8ffb9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610811/7cb97a84-d984-c3bb-cbbd-4032a93daeb3.png)


## 解決策
[参考サイト](https://github.com/vuejs/vetur/issues/2292)

- 以下のファイルをsrcフォルダに追加
```TypeScript:shims-vuex.d.ts

import { Store } from 'vuex';

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $store: Store<T>;
  }
}
```
Raspberry Pi の自動スリープ(画面ブランク)をコマンドなしでオフにする

# 環境
* Raspberry pi4 modelB
* Raspberry Pi OS with desktop(Release date: September 22nd 2022)

# 執筆の動機
ラズパイを新しく用意したとき、必ず画面ブランクをオフにすることになる。ネットで「ラズパイ　自動スリープオフ」と検索すると、ターミナルからシステムファイルにアクセスして設定を書き換える方法ばかり紹介されているが、システムを汚さないために、大事なファイルを編集するのはなるべく控えたい。
実際私もネットで一番上に出た方法で自動スリープをオフにすると、バグってデスクトップにたどり着けなくなってしまった。(ファイルを編集する際、誤って消してはいけない項目を消してしまったのだろうか)

# やり方
1\. デスクトップ左上のラズパイのロゴをクリック
2\. "設定"→"Raspberry Piの設定"→"ディスプレイ"→"画面のブランク"をオフにする

# デスクトップにたどりつけなくなったら
もしかしたら私のように自動スリープをオフにしたらデスクトップにたどり着けなくなった人がいるかもしれない。
私の場合、電源をつけると、１０行くらいの英文が表示されたあと、`raspberry@raspberrypi:~ $`と緑色の文字が表示されたあと、コマンドが打てるだけでうんともすんともいわなくなってしまった

まず自動スリープオフのために編集したファイルを書き換える前の内容に戻してみたが、何も変わらなかった
色々調べてみて、`startx`と入力するといつものデスクトップにたどり着くことができた。

# 参考
* コマンドを使う方法：https://rikoubou.hatenablog.com/entry/2020/06/11/133716
(この方法がダメなのではなく、ファイル編集をミスるリスクがあるというだけ)

* ラズパイの設定からオフにする方法：https://raspida.com/rpi-setup2021#:~:text=%E3%80%8C%E7%94%BB%E9%9D%A2%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%82%AF%E3%80%8D%E3%81%A8%E3%81%84%E3%81%86%E9%A0%85%E7%9B%AE,%E3%82%92%E8%90%BD%E3%81%A8%E3%81%99%E7%9C%81%E9%9B%BB%E5%8A%9B%E3%81%A7%E3%81%99%E3%80%82

* startxについて：
https://ja.stackoverflow.com/questions/50467/raspberry-pi%E3%81%AEgui%E3%81%8C%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%AA%E3%81%84
C#でDataverseのドキュメントテンプレートをエクスポートしてみた

# はじめに
PowerAppsのモデル駆動の設定が面倒なのでC#からDataverseを操作してみたくなった。
今回はdataverseに登録されているWordテンプレートをエクスポートするC#のコードを動かしてみる。

# 前提
参照ライブラリやCreateCrmService関数の中身は以前の以下の記事を参考に

C#でDataverseに接続してテーブル一覧を表示してみた
https://qiita.com/akihiroe_/items/2db8e2634d7962ef0df7

# コード
Wordのテンプレートはdocumenttemplateテーブル上に保持されています。コンテンツはcontent属性にBASE64エンコードされています。テンプレートはWord以外にExcelも登録できます。WordかExcelかはdocumenttype属性で確認できます。

```C#
var organizationService = CreateCrmService(user, password, url);

var tableName = "documenttemplate";
var columns = new string[] { "name", "content", "documenttype" };

QueryExpression query = new QueryExpression(tableName);
query.ColumnSet.AddColumns(columns);
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "documenttype";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(2); //	Microsoft Word

FilterExpression filter = new FilterExpression();
filter.Conditions.Add(condition);
query.Criteria.AddFilter(filter);

var entities = organizationService.RetrieveMultiple(query);
foreach (var entity in entities.Entities)
{
    var name = entity.GetAttributeValue<string>("name");
    var content = entity.GetAttributeValue<string>("content");
    var contentAsBinary =Convert.FromBase64String(content);

    System.IO.File.WriteAllBytes(name + ".docx", contentAsBinary);
}
```
# おわりに
Wordテンプレートをエクスポートするための画面が見つからなくて困ったことがありました。XrmToolBoxを使えばできそうですが、dataverseから直接取り出してしまう方法もありますね。

# 参照情報
https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/reference/entities/documenttemplate

https://www.xrmtoolbox.com/plugins/Futurez.Xrm.Tools.DocTemplateManager/
クロス集計表を作成する1＊2統計量(SPSS Modeler データ加工逆引き11-9)

# クロス集計表を作成する（1＊2_統計量の集計表）

![スクリーンショット 2023-01-31 11.52.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2da5cb99-e3f8-9728-35d9-67f3af38e3e5.png)

## 1.想定される利用目的

・データ理解のための基礎統計量確認
・固定帳票の作成


## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/cross_tabulation1_2s.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2023-01-23 10.29.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6e6b1a14-02c6-3d38-3f09-7462a640a2bc.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2023-01-16 14.06.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/894e6aa6-7f5b-1c9a-4c93-f4a5d1013f7d.png)

b.　[フィールド作成]ノードを編集します。　[血液型]と[年代]を　[ >< ]で文字列結合します。　
![スクリーンショット 2023-01-23 10.33.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ebfc37da-4ec7-3b1d-8de1-64b5c5f193c2.png)

[プレビュー]します。
![スクリーンショット 2023-01-23 10.33.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0a6199b6-9c99-30ae-3132-e1b62d2e1514.png)

c.[データ型]ノードで　[値の読み込み]ボタンを押して後続dのために合成変数の値を認識します。

d.[再構成]ノードを以下のように編集します。[合成変数]を[再構成フィールド]に移して[値フィールド]はブランクのまま[数値フラグを作成]を選択します。
![スクリーンショット 2023-01-31 13.32.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/541cdfef-c55a-22ca-92eb-24ae596847b5.png)

[プレビュー]します。
![スクリーンショット 2023-01-31 13.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5a1d3b2b-1a47-2ad5-f040-6b0c6853679d.png)

e.[レコード集計]ノードを以下のように編集します。
![スクリーンショット 2023-01-31 13.36.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1360a4cf-af14-ad17-5bda-4da85fcd4569.png)

f.[ソート]ノードで[年代]を[昇順]ソートします。

g.[フィルター]ノードで集計の過程で各フィールドに自動付与された[_体重_Mean]を取り除きます。

h.[フィールド順序]ノードで適宜表示する列の順番を変更します。

[デーブル]ノードを実行します。
![スクリーンショット 2023-01-31 13.38.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1ca836ce-a060-cae2-ee73-d13aab82c23c.png)

#### 注意事項

[再構成]ノードで列に展開するメンバーが表示されないときは前方でデータ型の[値の読み込み]を実行します。
Excelで表頭を入れ子にすると表が見やすくなります。

## 4.参考情報

####  SPSS Statistics Custom Tablesと連携して多重クロス集計を作成する

https://www.ibm.com/blogs/solutions/jp-ja/spss-stats-tips-06/

####  カテゴリ値を列に展開してIDで集約　縦持ちを横持ちへ

https://qiita.com/416nishimaki/items/2519553c7cce0fc0b0e0

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
CF7で選択項目（チェックボックス）にデフォルトで複数のチェックを入れる方法

CF7で選択項目（チェックボックス）にデフォルトで複数のチェックを入れる方法です。

ラジオボタンやチェックボックスであれば、 `default:1` などと追記することで、1番目にデフォルトでチェックを入れることができますね。

ただし、チェックボックスの場合、デフォルトで複数にチェックしたいこともあるでしょう。

以下のように書くことで解決します。

```	
[checkbox checkbox-1 default:1_3_5 "1" "2" "3" "4" "5" "6"]
```

`_` で繋ぐことで、デフォルトで複数チェックを入れられます。
GWTのファイル構造

GWTでは、プロジェクトをそのまま生成すると次のようになります。

パッケージ事に、役割が明確に分かれているので、
わりとすぐ理解できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132663/cbceb882-78c1-4231-abec-72ddde798eb3.png)
Nuxt.js 3 の動的ルーティングでハマったこと

https://nuxt.com/docs/getting-started/routing

例えば `/posts/1`, `/posts/2` のようにアクセスしたい場合
Nuxt.js 2では以下の書き方でした
```
pages/
--| about.vue
--| posts/
----| _id.vue
```

Nuxt.js 3では以下のように `[]`で囲む必要があります
```
pages/
--| about.vue
--| posts/
----| [id].vue
```

`[id].vue`内でid値にアクセスする場合は以下で可能です([Vue.js 3のsetup](https://v3.ja.vuejs.org/guide/composition-api-setup.html)使用時)
```
<script setup lang='ts'>

const route = useRoute()
const id = route.params.id

</script>
```
composerのインストールとautoload対応

# composerのインストール

composer.jsonを自動生成
```
composer init
```
ファイルが生成される

```json:composer.json
{
    "name": "フォルダ名",
    "autoload": {
        "psr-4": {
            "フォルダ名": "src/"
        }
    },
    "authors": [
        {
            "name": "名前",
            "email": "メールアドレス"
        }
    ],
    "require": {}
}

```

もしcomposer initで下記のようなエラーが出力されたら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/43f6cc44-61f9-ae50-4a42-907e990b8ec6.png)

php.iniを編集
```
extension_dir = "ext"
extension=openssl
```

下記コマンドを実行
```
composer config -g -- disable-tls true
composer init
```

# aoutload対応

composer.jsonを書き換える
"app/"は実行するファイル
```json:composer.json
{
    "autoload": {
        "psr-4": {
            "App\\" : "app/"
        }
    }
}

```
ファイルの書き換えが完了したら
```
composer install
```

vendorフォルダ、composer.lockが生成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/fa596921-0227-8446-e7bc-f6bcf99250df.png)


もしファイルの内容を書き換えた場合は
```
composer update
```
または
```
composer dump-autoload
```
condaってなんですか？帰ってきたよpart3(くらい)

お久しぶりです墨色レイです。
完全に忘れていたqiita投稿。condaってなんですかです。多分パート3です。
本日はcondaの環境管理についてです。

----
はい<strong>環境管理</strong>についてです。
まず環境ってなんですか、最近流行りのSDGsですか？ってなるかとも思いますが、少なくともpythonにおける環境管理とは仮想環境の管理を指します。
python japanでは
「Python を使って開発や実験を行うときは、用途に応じて専用の実行環境を作成し、切り替えて使用するのが一般的です。こういった、一時的に作成する実行環境を、「仮想環境」 と言います。」
と説明されています。
なんか小難しいですが、これの一番わかり易い例がWindowsの仮想デスクトップ(多分macもあった)ですね。
こちらWin＋tabを押すと下の方で
新しいデスクトップ
と開くとまるで別のPCを持ってるかのように新しい画面が表示されます。そしてそこで開いたりするアプリは最初に使っていたデスクトップには反映されません。
これと同様にpythonでは仮想環境ごとに別の設定やpythonのバージョンを使用して実行することが可能になります。
この仮想環境ですが、venvというライブラリがpythonには標準装備されています。
ただ今回はcondaの話なのでcondaの管理法。
大きく２つありますが、今回はanaconda公式に書いてある方法です。
それがanaconda navigatorを用いる方法。
anacondaをインストールした際、こんなアプリが入ったかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738461/386f3fbd-0196-0360-1c9c-06f1ee68b4aa.png)
このアプリのenvironmentって欄から環境管理を行うことができます。
詳細は<link>https://qiita.com/code0327/items/fe22dd1c4ff8c385f7a8</link>こちらを参照していただければと思います。

----
以上です。お疲れ様でした。多分これで一通りanacondaの概要の概要は取り扱ったかなと思います。
少なくとも
「anacondaなにそれ怖い」
状態ではなくなったんじゃないかなと思います。
いつも通り間違い等あったらコメで指摘お願いします🙇‍♂️
以上墨色レイでした。
[Django REST framework] 対象フィールドをOR条件で複数検索したい。


下記リクエストで3件の結果を得たい。
`GET /api/v1/incident/?id=1,2,3`


```python:models.py
from django.db import models

class Auther(models.Model):
    author_name = models.CharField()

class Book(models.Model):

    book_name = models.CharField()
    book_author = models.ForeignKey(Auther)
```



```python:serializers.py
from rest_framework import serializers

class BookSerializer(serializers.ModelSerializer):

    class Meta:
        model = Book
        fields = '__all__'
```

```python:views.py
from rest_framework import viewsets

class BookViewSet(viewsets.ModelViewSet):

    queryset = Book.objects.all()
    serializer_class = serializers.BookSerializer
    filterset_class = filters.BookFilter
```

```python:filters.py
from django.db.models import Q
from django_filters import rest_framework as filters

class MultiValueFilter(filters.Filter):

    def __init__(self, *args, **kwargs):
        self.lookup_expr = kwargs.pop('lookup_expr')
        super(MultiValueFilter, self).__init__(*args, **kwargs)

    def filter(self, queryset, value):
        q = Q()
        url_args = value.split(',') if value else []

        for arg in url_args:
            q = q | Q(**{self.lookup_expr: arg})
        return queryset.filter(q)

class BookFilterFilter(filters.FilterSet):

    id = MultiValueFilter(lookup_expr='id__exact')

    class Meta:
        model = models.Book
        fields = '__all__'

```

| 検索条件 | 説明 |
| --- | --- |
| exact | 完全一致 |
| iexact | 大文字小文字を区別しない完全一致 |
| contains | 指定の値を含む |
| icontains | 大文字小文字を区別しない指定の値を含む |
| startswith | 指定の値で始まる |
| istartswith | 大文字小文字を区別しない指定の値で始まる |
| endswith | 指定の値で終わる |
| iendswith | 大文字小文字を区別しない指定の値で終わる |
| gt | 指定の値より大きい |
| gte | 指定の値以上 |
| lt | 指定の値より小さい |
| lte | 指定の値以下 |
| in | 与えられたリストまたはタプルのいずれかの値と一致 |
| range | 指定の範囲内の値と一致 |
| year | 日付フィールドの年と一致 |
| month | 日付フィールドの月と一致 |
| day | 日付フィールドの日と一致 |
具体的なテーブル正規化の話

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はテーブルの正規化について更に詳しく調べてみましょう！

![インスタスライド_202301224.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/3c592b89-b69b-e785-efd6-39fbcad586ee.gif)


# 正規化具体例１
正規化前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/58e9f5b2-7d3f-dddb-cb84-20f7474e4cad.png)
正規化後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/a69a51ce-956f-c3e3-0955-d53461e3196e.png)

# 正規化具体例２
正規化前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/3bf6a609-5b76-4977-a8fc-af9cdd716c5a.png)
正規化後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/2891a8d5-afaf-fba9-02f7-4645cbaf5a82.png)

# まとめ
ー正規化すると更新対象に冗長性がなくなる

ー繰り返し項目が解消される

ー正規化すると論理歴にシンプルになる

ーこの考え方は、プログラムをキレイに書くことにも役立つ

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
macOS Ventura  にしたら ssh で「Permission denied (publickey)」になった

macOS Ventura にした所、OS 更新前まで問題なく接続できていた ssh が「Permission denied (publickey)」になった問題について確認した際の自分用メモです

# 原因

[MacOS Ventura system ssh no longer supports ssh-rsa reasons and solutions](https://www.sobyte.net/post/2022-12/macos-ventura-ssh-rsa/)

`ssh` のバージョンが上がり、`RSA/SHA1` アルゴリズムが deprecated になったことが原因のようです

# 解決方法

`~/./ssh` 配下を一旦バックアップなどしておき、以下のようにしてよりセキュアな key を作成し、利用する

```
ssh-keygen -t ecdsa
```

# 一時的な回避方法

[Git SSH "permission denied" in macOS 13 Ventura](https://superuser.com/questions/1749364/git-ssh-permission-denied-in-macos-13-ventura)

検証していませんが、`~/.ssh/config` を編集して `RSA/SHA1` を許可するような回避方法もあるようです

```
Host your-old-host.example.com
  HostkeyAlgorithms +ssh-rsa
  PubkeyAcceptedAlgorithms +ssh-rsa
```

ただし、一時的な回避方法であり、基本的には「解決方法」に記載した方法での対応が良いと考えられます
再帰関数で木を生成

* 友人が再帰関数がどうのいってたので再帰関数で木を作りたくなった
* Unity内で長さ1m(ScaleYが0.5)のシリンダーに始点(pivot)を設定し、そこから終点までのベクトルを求めて再帰的に2本ずつはやしていった
* はやした後20度程度曲げて、生える前の枝のベクトルを回転軸としてランダムな角度を与えて回転させた
* 3Dオブジェクトのpivotが自由に移動できないので空のゲームオブジェクトを作ってどうにかした(Unityの機能でほしい・・・)
* 以下コード
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RecursiveTree : MonoBehaviour
{
    [SerializeField]
    GameObject mBranch;

    // Start is called before the first frame update
    void Start()
    {
        CreateRecursiveTree(9, transform);
    }

    /// <summary>
    /// 再帰関数で木を生成するプログラム
    /// </summary>
    /// <param name="n">nには分岐したい回数を入れる</param>
    /// <param name="trans">transには原点のTransformを入れる</param>
    void CreateRecursiveTree(int n, Transform trans)
    {
        for (int i = 0; i < 2; i++)
        {
            GameObject obj = Instantiate(mBranch, trans.position + trans.up * trans.localScale.x, trans.rotation);
            //まず生成した枝を傾ける
            obj.transform.Rotate(0, 0, -20, Space.World);
            //生えてきた元の枝に沿ってランダムに回転
            obj.transform.rotation = Quaternion.AngleAxis(Random.RandomRange(10f + 180f * i, 170f + 180f * i), trans.up) * obj.transform.rotation;
            //生成した枝の大きさ調整
            obj.transform.localScale *= 0.6f;
            if (n > 0)
            {
                //再帰
                CreateRecursiveTree(n - 1, obj.transform);
            }
        }
    }
}

```
* 結果:
![再帰関数ツリー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3093671/21e18ef5-afc8-917e-94d6-f8b9b28da235.png)
* ちゃんと木っぽくてすごい
* でも乱数によってはバランスの悪い木になるので要改良
* 自然って案外規則的・アルゴリズム的にできてるのかもしれない
(2023/02/08)PhotonFusionにおける公式ドキュメントの間違いについて

  * PhotonFusionのチュートリアルにおけるこちらの公式ドキュメント https://doc.photonengine.com/ja-jp/fusion/current/fusion-100/fusion-102 (現在2023/02/08)がそのまま書いても動作しないので備忘録
  * 1.`INetworkRunnerCallbaks`インターフェイスをクラスに追加する際、`OnInput`メソッドと`OnHostMigration`メソッドも実装しなければならない。正しくは以下
```
public class BasicSpawner : MonoBehaviour, INetworkRunnerCallbacks
{
  public void OnPlayerJoined(NetworkRunner runner, PlayerRef player)    {    }
  public void OnPlayerLeft(NetworkRunner runner, PlayerRef player)    {    }
  public void OnInputMissing(NetworkRunner runner, PlayerRef player, NetworkInput input) { }
  public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason) { }
  public void OnConnectedToServer(NetworkRunner runner) { }
  public void OnDisconnectedFromServer(NetworkRunner runner) { }
  public void OnConnectRequest(NetworkRunner runner, NetworkRunnerCallbackArgs.ConnectRequest request, byte[] token) { }
  public void OnConnectFailed(NetworkRunner runner, NetAddress remoteAddress, NetConnectFailedReason reason) { }
  public void OnUserSimulationMessage(NetworkRunner runner, SimulationMessagePtr message) { }
  public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList) { }
  public void OnCustomAuthenticationResponse(NetworkRunner runner, Dictionary<string, object> data) { }
  public void OnReliableDataReceived(NetworkRunner runner, PlayerRef player, ArraySegment<byte> data) { }
  public void OnSceneLoadDone(NetworkRunner runner) { }
  public void OnSceneLoadStart(NetworkRunner runner) { }

  //ここが必要！
  public void OnInput(NetworkRunner runner, NetworkInput input) { }
  public void OnHostMigration(NetworkRunner runner, HostMigrationToken token) { }
}
```
* また`StartGameArgs`に定義されているメンバ変数は`ObjectSceneProvider`ではなく`SceneManager`である
```
async void StartGame(GameMode mode)
    {
        // Create the Fusion runner and let it know that we will be providing user input
        _runner = gameObject.AddComponent<NetworkRunner>();
        _runner.ProvideInput = true;

        // Start or join (depends on gamemode) a session with a specific name
        await _runner.StartGame(new StartGameArgs()
        {
            GameMode = mode,
            SessionName = "TestRoom",
            Scene = SceneManager.GetActiveScene().buildIndex,

            //ここが変更！
            SceneManager = gameObject.AddComponent<NetworkSceneManagerBase>()
        });
    }
```
* さらに`Player`関数を書く際、`NetwowrkCharacterController`で入力を受け渡しているが、これは非推奨であり、正しくは`NetworkCharacterControllerPrototype`でなければならない。
```
public class Player : NetworkBehaviour
{
    //ここが変更！
    private NetworkCharacterControllerPrototype _cc;
    private void Awake()
    {
        //ここが変更！
        _cc = GetComponent<NetworkCharacterControllerPrototype>();
    }
    public override void FixedUpdateNetwork()
    {
        if (GetInput(out NetworkInputData data))
        {
            data.direction.Normalize();
            _cc.Move(5 * data.direction * Runner.DeltaTime);
        }
    }
}
```
このとき、アタッチするコンポーネントも`NetworkCharacterControllerPrototype`にすることを忘れないこと。
* なお1,2番目は日本語・英語ドキュメント両方で間違っており、3番目は日本語ドキュメントのみ間違っている。うまくいかないときは英語ドキュメントをまず調べることも重要そうだ
Webサービスでどうやって稼ぐのか？  [広告モデル編]

# 広告モデル - 最も手軽なマネタイズ方法　

マネタイズで最も簡単で手間がかからないのが、この広告モデルと言えるでしょう。広告モデルには、さまざまな種類のものがる。それは**クリック報酬型**、**成果報酬型**、**インプレッション報酬型**の３つです。これらは総じて、アフィリエイトと呼ばれ、アフィリエイト業者が用意したタグを、Webサービスに貼り付けるだけで、収入を得ることができます。　

### 広告モデル　>　クリック編　 
有名なクリック報酬型の広告には、**Googleアドセンス**があります。自動でWebサイトにマッチする広告を選んで表示してくれるため手間がかからないのがポイントです。サイトの訪問者によって広告がクリックされると報酬につながります。　

### 広告モデル　 > 成果報酬型　
次に、成果報酬型があります。これは、商品の広告を掲載し、商品が実際に購入されると、商品の数%が報酬うとして支払われる方式のアフィリエイトです。**Amazonアソシエイト**や、**楽天アフィリエイト**などが有名です。　

### 広告モデル　> インプレッション型　
広告の表示回数に応じて報酬が支払われるのがインプレッション報酬型です。一般的に、料率が低いのが特徴です。
Webサービスでどうやって稼ぐのか？[ECモデル編]

# ECモデル - 堅実なマネタイズ手法　
これは、実際に商品を販売することです。ECモデルの代表例が、大手販売サイトのAmazonや楽天です。また、商品の販売を主なサービスとするのではなく、Webサービス自体は無料で提供するものの、そのサービスのファンのためにグッツを販売したり、特別企画として記念グッツや別企画とのコラボ商品を販売する方法もあります。
Webサービスでどうやって稼ぐのか？[課金モデル編]

# 課金モデル 
Webサービスを利用するために、利用料や年会費を受け取るのが、この課金モデルです。最初から有料のサービスを打ち出しても、なかなか使って貰えないため、体験版を出したり、フリーミアム方式で最初は無料で使ってもらい、サービスの一部だけを有料にするなど、さまざまな方法があります。　

### 課金モデル　>　フリーミアム　　
オンラインストレージの**Dropbox**やメモアプリの**Evernote**などのWebサービスは基本的に無料で使えるものの、保存量が大きいプランを選ぶには有料で年会費を払う必要があります。このように普段は無料で使えるが、付加価値のあるサービスを利用するにはお金を払う必要がある課金モデルを**フリーミアム**と言います。　

 ### 課金モデル　>　サブスクリプション　
従来型では、アプリやサービスを売り切り型で販売するのが普通でした。しかし、最近では、サブスクリプションの方式で提供するサービスが増えてきています。　これは、利用期間に応じて使用料を徴収する課金スタイルを指します。定期的に利用するアプリケーションに向いてます。　
ユーザーにとっても、利用期間に応じた費用を払うことで、最新のアプリやサービスが利用できるのが利点でもあり、企業や提供側にしても導入に対する敷居が低く、安定した収益が見込めるというメリットがあります。　
　
### 課金モデル　>　アイテム課金　　
アイテム課金は、ゲーム内で利用できるアイテムや、追加コンテンツを課金してユーザーに販売するというモデルです。アイテム課金には、さまざまなな形態があります。　

##### アイテム購入に関するもの　
課金することで、性能の高いアイテムが入手できるようになります。無料で遊ぶだけでは入手不可能、入手困難なアイテムを購入できます。　
##### ランダムにアイテムがもらえるもの　
ランダムにアイテムが貰えます。低確率でアイテムを入手できるようにすることで、ユーザーが何度も挑戦してくれます。いわゆる「ガチャ」と呼ばれるものですね。　
##### ゲームの継続に関するもの　
課金することで、スタミナが回復したり、ゲームオーバーになっても継続してゲームを楽しめるようにします。
Webサービスでどうやって稼ぐのか？

## キーワード
- マネタイズ
- アドセンス
- フリーミアム
- サブスクリプション　
　
# どんなWebサービスを開発するにしても、お金は必要

いきなりですが、皆さんはなぜWebサービスを開発しようと思っているのでしょうか。色々な目的、野望があることでしょう。しかし、残念ながらどんなに大きな志があったとしても、Webサービスを無料で運営することはできません。例えば、毎月のサーバー費用、電気代、インターネットの接続代、、、パッと思いつくだけでもこんなにに、、、つまり、お金を稼がないことには、サービスを安定に運営することはなかなかできないというのが現状です。しかし、Webサービスをつくって、それが大衆に気に入られて使われるようになれれば話は別です。ここではどうやってお金を稼ぐことが出来るのか代表的なマネタイズ方法を具体例を挙げながら紹介していきたいと思います。　


追記：ここでは本などの参考文献をはじめとする確かな情報を元に発信していますが私個人のアウトプットも含みます故、温かい目でこの記事に目を通していただけたらなと思います。　

この記事は以下のような情報を参考にして執筆しました。　
- [Webサービス&スマホアプリの書き方、作り方](https://www.socym.co.jp/book/1251) 


# まずマネタイズとは　

ネットの無料サービスから収益を得ることをマネタイズと呼びます大きく分けて、マネタイズには四つの種類があります。　

##### 1.[広告モデル](http://qiita.com "Webサービスでどうやって稼ぐのか？ [広告モデル編]")　
##### 2.[ECモデル](http://qiita.com "webサービスでどうやって稼ぐのか？　[ECモデル編]")　
##### 3.[課金モデル](http://qiita.com "webサービスでどうやって稼ぐのか？　[課金モデル編]")
##### 4.[仲介モデル](http://qiita.com "webサービスでどうやって稼ぐのか？　[仲介モデル]")
これを１つずつ確認していきましょう。
Airtableの簡易APIクライアント作ってみた

# 前書き
AirtableのテーブルデータをJSONでダウンロードしたのち、適切に加工して自作アプリに組み込みたかった。
どうせなら勉強を兼ねて自作してみた。
# 前準備
APIを叩くには、アカウント自身のPersonal Access Tokenと baseidが必要です。下記からコピーしてください。

1. Personal Access Tokenを作成
[GUIDE Personal access tokens](https://airtable.com/developers/web/guides/personal-access-tokens)をよく読んで操作したいbaseに対応するアクセストークンを作成する。Scopesはこのライブラリを使うだけならdata.records:readだけでよい。作成時にしかトークンをコピーできないので気を付けよう。
1. baseIDをコピー
[API Reference](https://airtable.com/developers/web/api/introduction)から操作したいbaseを選んでIDをコピーする。以下の画像の赤枠の部分から遷移して黒塗りの所にbaseIDがあるのでコピーしてください。最後の色違いピリオドは無関係なので気を付けよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49578/7b6ec58d-a5db-7735-2dca-0b1ea8e265e9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49578/287b07ce-911d-d60f-8a1c-07c0a335fe65.png)

# 使い方
```csharp

    readonly string appKey = YOUR_PERSONAL_ACCESS_TOKEN;
    readonly string baseId = TARGET_BASE_ID;
    
    string table = TARGET_TABLE;
    string view = TARGET_VIEW;          //Optional
    string path = TARGET_FILE_FULLPATH;

    //Init HttpClientFactory
    var services = new ServiceCollection();
    services.AddHttpClient<IAirtableServices, AirtableServices>()
            .SetHandlerLifetime(TimeSpan.FromMinutes(5));
    var provider = services.BuildServiceProvider();
    var api_service = provider.GetRequiredService<IAirtableServices>();

    //指定のテーブルの特定のビューのJSONテキストをファイルに書き込み
    var result1 = await api_service.DownloadTableToFile(path,appKey,baseId,table,view);
    //指定のテーブルの特定のビューのJSONテキストを取得
    var result2 = await api_service.DownloadTableJson(appKey,baseId,table,view);
    //指定のテーブルの特定のビューをDataClassにマッピング
    var result3 = await api_service.LoadTable<DataClass>(appKey,baseId,table,view);
```
# ソースコード
https://github.com/reniris/AirtableDownload

# Nuget
https://www.nuget.org/packages/AirtableDownload/

# 参考
* [Airtable.Net](https://github.com/ngocnicholas/airtable.net)
* [AirtableClient](https://github.com/yKimisaki/AirtableClient)
* [IHttpClientFactory を使って今はこれ一択と思った話](https://qiita.com/TsuyoshiUshio@github/items/7092fbc510772ce5db63)
【Unity】Android 端末での負荷計測

# 目的
Unity を利用した Android 端末の負荷計測を行う方法を備忘として残す。
今回古いAndroidの端末でやけに処理が重かったので調べたついでに情報をまとめておく。

# 環境
* Mac mini (M1, 2020) macOS Big Sur
* Unity 2021.3.18f1
* HUAWEI nove lite
* Android Logcat 1.3.2

# 準備
* Unity の Package Manager から Android Logcat をインストール
    * Debug.Log などが大量に出て負荷になっている場合もあるため準備
    * adb logcat でもいいが一応 Unity 側でログを見れるツールを用意してくれている
* 端末とPCをUSBで繋ぐ
* Unity の Platform を Android に Switch する
* Addressables をビルド
    * 一応 Clean Build
    * からの New Build -> Default Build Script
    * Play Mode Script から Use Existing Build(Android) で Editor 上で動作確認

# ビルドして実行
* Build Settings を開く
* Build Scene に今回計測するシーンを入れる
* Development Build にチェック
* Autoconnect Profiler にチェック
* Build And Run を押す
* すると、Unity の Profiler で CPU と GPU の負荷がざっくりわかる

# あとがき
今回は、古い端末で負荷が異常にかかっていたので、上記の方法で計測した。結論としては、ボトルネックになっていたのはGPUでPostprocessing。Development なので厳密なCPUの負荷計測には向かない。相対的なボトルネックを探すには使える。GPUならDevelopmentでも割と正確な負荷が出るかもしれないが、ハードウェアの会社が提供しているツールなどの方がもっと正確にわかると思う。ただ、ざっくりでもボトルネックを探すのにこの方法は結構使えると思う。今回問題となった、GPUのPostProcessing部分については後日別の記事でまとめる。
C# 勉強メモ Unityでキャラクターの表情操作するスクリプト

Unityで使用するC#スクリプトを書いていて、メモっておきたいと思ったことを書き記しています。
自分が困った時のメモなので、コードが汚かったり、もっといい方法があると思います。
初心者の勉強で独学ですので、もっといい方法があればご教授いただけますと幸いです。

# ・表情操作のスクリプト
今回はVRMモデルを利用しています。
FBXの場合はSkindmeshrendererを参照することで表情の操作が可能です。
VRMの場合も同様の操作が可能ですが、今回はVRMblendShapeProxyを利用します。

## VRMblendShapeProxyを利用して表情を操作する場合、
Void Update()の段階で、
if(proxy == null)
{
    proxy = model.GetComponent<VRMBlendShapeProxy>();
}
else
{
この文章ではmodelの中にVRMBlendShapeProxyが含まれているかを確認しています。
nullは含まれていない場合、含まれている場合は次のステップに進みます。


次にGetKeyでキーボードの入力を取得します。

if(input.GetKey(KeyCode.X))
{
    proxy.SetValue("Face1",1.0f);
}
else
{
    proxy.SetValue("Face1",0);
}

公式ドキュメントでSetValueが推奨されているこちらを使用します。
Xを入力することでFace１の表情プリセットの出力をします。
VRMのモデルに元々用意されている表情を使用したかったのですが、
名前がblendshape.joyなどになっているためか、うまくいきませんでした。
なので、使用する場合はFace１など新しくプリセットを制作して使う。
animationにJoyを用意して、切り替える方法も考えましたがpresetをあたらしく準備した方が早かった。。。



## ・表情操作をしているときにblink（瞬きを切りたい）
blink操作をするためのスクリプトは先人の方の力を借りました。
書き換えたのはスクリプトに　namespace AutoBkink　これを書き足しました。
using AutoBlinkを書きAutoBlinkをスクリプトで操作することができるようになります。

XでFace1の表情を操作しているときに、AutoBlinkを停止したいので、
スクリプトを非アクティブ状態にするスクリプトを書く。

enabledはスクリプトを操作できるようにします。
非アクティブにしたい場合は
enabled = false
アクティブにしたい場合は
enabled = true
これをif文を使い。

if(Input.GetKey(KeyCode.X))
{
    AutoBlink.enabled = false;
}
else
{
    AutoBlink.enabled = ture;
}

using AutoBlink　の書き忘れに注意。


## ・口パクに対しての表情操作
口についてはモデル自体の表情に口の変化を入れないようにすることで、
リップシンクとバッティングしないようにする。


以上が今回勉強したメモです。
次はMidiを利用した操作やChinemaShineについて学んでいきたいと考えてます。
nostr-relay を改造して event のログを出すところまで

# 概要
軽量 python nostr リレー の nostr-relay を改造して event のログを出すと通信内容が見えて勉強になるかもと思って。

- nostr-relay: https://pypi.org/project/nostr-relay/
- nostr: https://github.com/nostr-protocol/nostr

# checkout
```bash
mkdir nostr-relay
cd nostr-relay
fossil clone https://code.pobblelabs.org/fossil/nostr_relay nostr_relay
fossil open nostr_relay
```

fossil は git みたいなやつみたい
ぜんぜんわからん
diff すらできんけども。

# 改造
本当に改造した方が動いてるか確認するために \_\_init\_\_.py を編集してバージョン名を変えとく
```diff_python:nostr_relay/\_\_init\_\_.py
- __version__ =  "1.9.1"
+ __version__ =  "1.9.1.1"
```

web.py の event を取得してるところで event を全部ログ出力
```diff_python:nostr_relay/web.py
self.log.info(
    "%s added %s from %s", client_id, event.id, event.pubkey
)
+ self.log.info(
+     "event=%s", event
+ )  
```

# ビルド＆起動
```bash
pip3.9 install -e ./ && nostr-relay serve
```

# 結果
- [iris.to](https://iris.to) とかのクライアントでログイン
- 設定>nostr>新しいRelay URL に ```ws://127.0.0.1:6969``` と入力して connect ボタンを押す [^1]
- そのあと自分のアカウントで「テスト」とかを post してみる
- (下記のログが見れます)

```json:
2023-02-08 01:23:54,986 - nostr_relay.web - INFO - event =
{
    "id":"78e7161490d6a364119a9b46c1c3395aa3b2e9a3f4a6369c62b24dfda839b2c3",
    "pubkey":"4c5d5379a066339c88f6e101e3edb1fbaee4ede3eea35ffc6f1c664b3a4383ee",
    "created_at":1675787034,
    "kind":1,
    "tags":[],
    "content":"テスト",
    "sig":"6236c608e34cf67fac6bf35895c397fe017ef0f040276
        4c82e5b73342edf3d27a0bfba43ea97ffb6743e0a8fb6
        03b61ae54b1b79be3a28871de28432129550ac"
}
```

もっと通信全部見れるとこあるのかもしれないけど
"REQ" とかも見たいね
cf. https://github.com/nostr-protocol/nips/blob/master/01.md

[^1]: 他のサーバーが全部 ```wss://``` なのでそれが正しいと思っていたら ```ws://127.0.0.1:6969``` じゃないと通らなかった(s が 1 つ)。```syslog:[2023-02-08 00:19:56 +0900] [17683] [WARNING] Invalid HTTP request received.``` と出るときはそれを要確認。ws と wss は http と https みたいな関係ですね
mysqldumpを使用したバックアップ・リストア

## 概要

mysqldumpを使用したバックアップ・リストア方法についてコマンドを備忘録として残しておきます。今回は、バックアップファイルの容量も考慮して圧縮する方法で実施します。

## バックアップ

普通に`mysqldump`でバックアップを取得して、パイプでつなぎ圧縮も一緒にしていまいます。サーバのストレージに優しいです。

```
# database指定でバックアップ ＆ 圧縮
mysqldump -uusername -ppassword db_name | gzip > /tmp/db-back.gz

# table指定
mysqldump -uusername -ppassword db_name table_name | gzip > /tmp/db-back_table.gz
```

## リストア

先程取得したdumpをリストアしていきます。リストア用のコマンドというのは存在しないので、sqlファイルをmysqlに読み込ませる。

```
# database
zcat /tmp/db-back.gz | mysql -uusername -ppassword db_name

# table
zcat /tmp/db-back_table.gz | mysql -uusername -ppassword db_name
```
※`mysql>`は、mysqlに入って実行する。
[初心者向け]競プロで使う言語の決め方

競技プログラミングをこれから始めてみようかな、となったときに最初に迷うポイントの一つが「どの言語で参加すべきか」という問題です。この問題を解決する完璧なフローチャートを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15320/6426588f-88d5-51f9-ac58-176062284a45.png)

半分はジョークですが半分は本気です。
ポイントは **特に強いこだわりがなければ C++ にしておくべき** という点です。理由はいくつかあります:
* 参加人数が多いので、強い人のACコードを参考にしようと見てみると、だいたいC++
* 競プロ参考書、解説ブログでのデファクトスタンダード
* 競プロをやるうえで便利なライブラリが標準でそろっている
* アルゴリズムが正しいのにTLE[^tle]してしまうことがほぼない

[^tle]: TLE（Time Limite Exceeded の略）とは提出したコードに対してジャッジシステムが返す状態（判定結果）の一つで、問題で指定された実行時間以内にプログラムが終了しなかったという意味です。[用語集(atcoder.jp)より](https://atcoder.jp/contests/yahoo-procon2019-qual/glossary?lang=ja)

図中の注1ですが、あなたの使っている言語だけ想定解法でもTLEで落とされるような問題が出たとしても「よしよし、この言語はここが苦手なんだね。大丈夫、次のコンテストまでには自前のライブラリを整備しておいてあげるから、また次回頑張ろうね」と考えられるよ、くらいを想定してもらえればオッケーです。

ちなみに私は3年間くらい Go で競技プログラミングに参加したあと、とある理由から現在は C++ にスイッチして現在まで C++ で参加しています。C++ にスイッチはしましたが、特にネガティブな理由ではないのでまた Go に戻すかもしれません。 競技プログラミングに参加するうえでは Go にもいくつか気を付けるポイントがあり、それは下記の記事にまとめてありますので興味がある人は読んでみてください。

https://qiita.com/ktateish/items/ab2df3e0864d2e931bf2 

以上です。
LEGOシティのトレインを複数操作できるページを作成

LEGOシティのトレイン(https://www.lego.com/ja-jp/themes/city/train)
のリモコンやアプリでは一つの電車しか操作できないので、
電車を複数台動かそうとすると都度リモコンやスマホを用意する必要があります。

少し調べた限りだとサードパーティでも複数台動かせるアプリなどが見つからなかったので（ご存知でしたら教えて下さい）
作ってみました。

当初スマホアプリで作成しようとしたものの、
[Web Bluetooth API](https://developer.mozilla.org/ja/docs/Web/API/Bluetooth)というブラウザでbluetooth接続するライブラリがあることを知ったので、
インストール不要のブラウザで操作できるものにしました。

完成品は[こちら](https://kametter.github.io/lego_train_bluetooth/)です。

# 内容

対応ブラウザであれば`navigator.bluetooth`クラスが用意されているので、それを使用。

実装自体は[JavaScriptを介したBluetoothデバイスとの通信](https://web.dev/i18n/ja/bluetooth/)などのドキュメントを参考に、
かなり簡単にbluetoothに接続できます。

# つまづいたポイント

LEGOの電池([LEGO Powered UP ハブ](https://www.lego.com/ja-jp/product/hub-88009))に接続するための情報が中々無く、
下記サイトを参考に、少しずつ情報を集めていきました。

[LEGO Wireless Protocol 3.0.00 Doc v3.0.00 r17 documentation](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#document-index)
[undera/pylgbst](https://github.com/undera/pylgbst)
[LEGO Power Function 2.0 and BLE](https://scrapbox.io/LEGO-PF2-BLE/)

# 所感

bluetooth機器に対してはバイナリで信号を送るので、そのバイナリ情報さえ分かれば比較的簡単に実装できることが分かりました。
ただ、iPhoneではそもそもAPIが用意されておらず、PCまたはAndroidスマホ限定になってしまいました。(macであればGoogle ChromeからはOK)

あと、こういうライブラリだと当然ながら非同期処理が多く、
今回は実装に時間をかけたくなかったのでasync/awaitを多用したコードになりES6対応のブラウザオンリーになってしまいました。
※そのためかiPhoneでbluetoothが使えるブラウザ「[コネクトブラウザ](https://apps.apple.com/jp/app/%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6/id1535410551)」で動きませんでした。

次はスマホアプリで作ろうと思います。
djangoで素のSQLを実行する

## 概要

djangoを使用していて複雑なクエリでDBからデータを取得したとき、ORMだけではどうにもできない時があります。そんなときのためにSQLを直接実行する方法を紹介します。
素のSQLを実行する方法としては、以下の方法が考えられます。
* extra
* raw
* cursor(これは、モデルを迂回してSQLでUPDATEなどもできます)

:::note warn
警告
これは最終手段なので、ORMで取得できるならそうした方がいいです。SQLインジェクション攻撃の種になる可能性があります。ユーザーが制御できるパラメータはエスケープする必要があります。
:::

以下は、例で使用するモデルです。
```python
class MyUser(AbstractBaseUser):
    email = models.EmailField(max_length=255, unique=True)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
```

## extra

以下構文になります。先程あげた3つの中では一番素のSQLからは遠い存在です。（一番マシだと思います。）

```python
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
```

**例**（あくまで例なので、下のように簡単なものでは、extraを使用するべきではありません。）
```python
queryset = MyUser.objects.extra(where = ['id in (1, 2, 3, 4) AND email = %s'], params = ['test@mail.local'])  
# printすると以下のように取得できていることが確認できます。
print(queryset)
<QuerySet [<MyUser: test@mail.local>]>     
```

## raw
SELECTだったら`raw`で実装すると良いと思います。UPDATE文は流せませんが、SELECTなら可能です。（取得はできる）
UPDATEまで、SQLで流したい場合は後述の`cursor`を使用するべきです。
※rawは`RawQuerySet`で返ってくるので、注意が必要です。

```python
raw(raw_query, params=(), translations=None)
```

**例**
```python
rawqueryset = MyUser.objects.raw('SELECT * FROM user_myuser WHERE id in (1, 2, 3)')
# こちらもprintで取得結果が確認できます。RawQuerySetで取得している事がわかります。
print(rawqueryset)
<RawQuerySet: SELECT * FROM user_myuser WHERE id in (1, 2, 3)>
```
rawを使用して`QuerySet`で取得する方法も記載しておきます。（selectでprimary keyを指定してfilterでquerysetを取得しています。）
```python
from django.db.models.expressions import RawSQL

queryset = MyUser.objects.filter(id__in=RawSQL('SELECT id FROM user_myuser WHERE id in (1, 2, 3)', []))
# これならquerysetで取得できます。
print(queryset)
<QuerySet [<MyUser: test@mail.local>]>
```

## cursor

rawでも要求を満たせないときは`cursor`を使用します。これは、モデルにマップできないクエリを扱ったり、UPDATE、INSERT、DELETEも直接実行することができます。
※cursorでは、dict型ではなくlist型で返されるので、dictで取得したいときは、別途関数を用意する必要があります。

**例**
```python
from django.db import connection

cursor = connection.cursor()
cursor.execute("UPDATE user_myuser SET email = 'testcursor@mail.local' WHERE email = 'test@mail.local'")

# selectなどの結果を取得したいときは、以下の様にします。
cursor.execute("SELECT * FROM user_myuser WHERE id in (1, 2, 3)")
list = cursor.fetchone()
# printしてみるとlistで取れている事がわかります。
print(list)
(1, 'test@mail.local', 'テスト', '太郎')
```

dictで取得したいときは、関数を定義する必要があります。以下が例になります。
```python
def dictfetchall(cursor):
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]

# 上記の関数を定義してlistの時と同様に取得します。
from django.db import connection

cursor = connection.cursor()
cursor.execute("SELECT * FROM user_myuser WHERE id in (1, 2, 3)")
dictfetchall(cursor)
# 上記実行するとdictで取得できていることがわかります。
[{'id': 1, 'email': 'testcursor@mail.local', 'first_name': 'テスト', 'last_name': '太郎'}]
```

## まとめ

こんな感じでdjangoでも素のSQLを実行することができます。何度も言うようですが、**素のSQLを実行するのは、最終手段です。** 基本はDjango ORMのツールを利用してください。もし今回のような手段でデータ操作を行う場合は、SQLインジェクションにくれぐれも注意してください。
また、記事内で誤記ありましたらご指摘よろしくお願いします。

[公式ドキュメント](https://docs.djangoproject.com/en/4.1/topics/db/sql/)
【備忘録】開けなくなった ipython (jupyter) notebook からコード（cell）を抽出するコード

jupyter notebook を雑に使っていると，適当に for 文中で書いた print 文のせいで開けなくなってしまうノートブックが生まれることがあります．
そんなときの方法として，いくつかオプションがありますが中身は json なのでコードを書けば解決可能です．

というわけで，以下のコードで解決可能です．
```[python]
import json

# Load the IPython notebook as a JSON file
with open("filename.ipynb", "r") as f:
    ipynb = json.load(f)

# Extract the code cells from the JSON file
code_cells = [cell["source"] for cell in ipynb["cells"] if cell["cell_type"] == "code"]

# Save the code to a file
with open("code.py", "w") as f:
    for cell in code_cells:
        for line in cell:
            f.write(line)
        f.write("\n")
```

#### ありがとう chatGPT
上記のコード，chatGPT君が書いてくれました．そのため，コードの出どころ（著作者，著作権？）はわかりません．
私からお願いしたことは以下の通りです．

`Please tell me how to get the code from ipython notebook by my own.`
`I cannot open ipynb file because it is too much to do.`
`Can you write an code to extract?`

私は普段，vim で stdout を削っていました．
ちなみに，jupyter nbconvert も使いましたが依存関係のチェックのせいか全然終わらなかったです．
退屈なことは AI にお願いしましょう（自分でも書けますが，楽をしたいときにいいですね）．
Lambdaのトリガーでフィルタリングを使う

# Lambda のイベントフィルタリング
Lambdaをトリガーする際、イベントに含まれるデータをフィルタリングしてトリガーを制御できる。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-eventfiltering.html


# Dynamodb Streamのイベントをフィルタリング

DynamoDBに新規レコードが追加された場合、下記の３つのイベントが発生する。
- INSERT - a new item was added to the table.
- MODIFY - one or more of an existing item's attributes were modified.
- REMOVE - the item was deleted from the table

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/APIReference/API_streams_Record.html

今回は新規登録（INSERT）の場合だけLambdaをトリガーしたいので、INSERTでフィルタリングする。
```
{
    "eventName": [ "INSERT" ]
}
```

Lambdaのトリガー設定から、追加設定を開く。
![スクリーンショット 2023-02-08 0.03.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659784/e42be752-9cfc-b1fd-ee1c-a743b917ba6f.png)

フィルタリング条件にフィルタしたい内容を記載する。
![スクリーンショット 2023-02-07 23.53.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659784/db6ed0a3-229c-b78e-16a7-cfb91e928d73.png)

完。
複数の半角スペースが1つにトリムされてしまう

# 複数の半角スペースが1つにトリムされてしまう

```入力値.
あい     うえお
```

```表示.
あい うえお
```

HTMLのルール上、複数の半角スペースは1つにトリムされてしまいます

上記の例では、5つの半角スペースを入力したにも関わらず、表示上は1つに。

実際に入力したスペースの分表示されるようにしたいと思います

# 解決策1：white-spaceでcssをあてる

@juner さんの[ご指摘](https://qiita.com/baby-0105/items/a31d1c989753c9212106#comment-e9fe0482eff4f967fc66)より `解決策1` 追記

`white-space: pre-wrap;`

> 連続するホワイトスペースはそのまま残されます。行の折り返しは、改行文字や <br> 要素のあるときか、行ボックスを埋めるのに必要なときに行います。

jsでゴニョゴニョする必要は無く、割と簡単に正しく表示できました

```入力値.
あい     うえお
```

```表示.
あい     うえお
```

https://developer.mozilla.org/ja/docs/Web/CSS/white-space

# 解決策2：`<pre>`を使用する

```sample.html
<pre>あい     うえお</pre>
```

> 要素内のホワイトスペース文字はそのまま表示します

https://developer.mozilla.org/ja/docs/Web/HTML/Element/pre

# 解決策3： jsでfilterをかける

```sample.js
function replace_space(s) {
  return s.replace(/ /g, "\xa0");
}
```

`replace`で半角スペースを`&nbsp;`（[ノーブレークスペース](https://ja.wikipedia.org/wiki/%E3%83%8E%E3%83%BC%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9)）として表示します
`\xa0`は、Unicodeでプログラム内のハードスペースまたはノーブレークスペースを指します

ちなみに、`"\xa0"`ではなく,`"\u00A0"`でも同じ結果です。
どちらも、表記が異なるだけで`&nbsp;`を表します

![Screenshot 2023-02-08 11.22.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536974/12a3c277-954c-d2dd-2e97-4b063c6f2cba.png)

(引用: https://www.task-notes.com/entry/20160703/1467539106)

また、textareaで以下のように改行を入れて入力した場合、

![スクリーンショット 2023-02-07 23.52.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536974/04c18ed5-bb9c-2f67-ee6b-6671a12fe459.png)

表示時には改行も半角スペースとして判断されてしまいます。
そのため、

```sample.html
<p style="white-space: pre-line;"></p>
```

で行の折り返しも判断できるようにする必要があります

https://developer.mozilla.org/ja/docs/Web/CSS/white-space

# ダメだった例

## 1. `&nbsp;`を使用

```sample.js
function replace_space(s) {
  return s.replace(/ /g, "&nbsp;");
}
```

~~特殊文字の`&nbsp;`でも試してみたのですが、表示では~~

```
あい&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;うえお
```

~~となってしまいます。~~

2023/2/8 @ss8826 さんより[ご指摘](https://qiita.com/baby-0105/items/a31d1c989753c9212106#comment-56a6575c215eb7186053)

>HTMLタグ同様、HTMLエンティティが生きた状態で更新するには、innerHTMLプロパティを使います 

## 2. `\s`を使用

`\s` だと、半角スペース以外にも改行も含まれるので×

```sample.js
function replace_space(s) {
  return s.replace(/\s/g, "\xa0");
}
```
【Git】submoduleの追加と削除

## 追加

リポジトリにサブモジュールを追加するには次のコマンドを実行します。

```terminal
git submodule add サブモジュールのリポジトリURL サブモジュールのディレクトリ
```

```
git submodule add https://github.com/user/sample-submodule.git sample/sample-submdules
```

上記を実行した後に`.gitmodules`ファイルが作成され`sample/sample-submodules`の中に`https://github.com/user/sample-submodule.git`の内容がcloneされます。

## 削除

削除する際には次の手順を実行します。

```terminal
$ git submodule                           
 4a3a41a70aeeb503f56cf7ba486235b6fao28af2 sample/sample-submodules (4a3a41a)
$ git submodule deinit sample/sample-submodules
$ git rm -f sample/sample-submodules
```
レンタルサーバとドメイン管理サーバが別々の場合に、Let's Encrypt SSL証明書を利用する方法

# はじめに
個人的なメモにはなりますが、記事にして残すことで、同じ内容で困っている人がすぐに解決できますように。

# 環境
レンタルサーバ：さくらのレンタルサーバ
ドメイン管理：ムームードメイン

# どんな時？
SSL証明書として無料の「Let's Encrypt」を使う場合、何もしなければ更新エラーになり、メールが届きます。

# どんな設定が必要？
ドメイン管理側（ムームードメイン）のDNS設定がちょっとややこしかったので、メモとして残しておきます。
以下の設定を行ってから、レンタルサーバ側（さくらのレンタルサーバ）でSSL証明書更新を実行する必要があります。

| サブドメイン | 種別 | 内容 |
|:-----------:|:-----------:|:------------:|
|  | CAA | 0 issue "letsencrypt.org" |
|  | MX | 初期ドメイン(例：◯◯.sakura.ne.jp) | 
| あれば(例：www) | CNAME | 初期ドメイン(例：◯◯.sakura.ne.jp) |
クラス図とは

## クラス図とは
クラス図はUML（統一モデリング言語）のひとつで、特徴は「システムの静的な構造・関係性を視覚的に表現するための図」であることです。視覚的に表現するというのがポイントです。

## クラス図のメリット
クラス図のメリットは、複雑度にかかわらず情報システムのデータモデルを図式化できる点になります。 システムによっては構造が非常に複雑になるケースもあるでしょう。構造が複雑なシステムは、説明や理解も難しくなります。しかし、クラス図なら複雑なシステムのデータモデルもシンプルに図式化して表現できるのです。

## クラス図の書き方
今回はこちらの画像のクラス図を参考にして説明していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/ac004df5-6778-7915-5125-a3e402f7eac5.png)

### クラス名
四角で囲まれている一番上の名前みたいなものがクラス名です。
ここだとユーザーやショッピングカートになります。この四角の中に属性(フィールド)と操作(メソッド)を記述していきます。

#### 属性(フィールド)
クラスのインスタンスが持っているデータの定義のことです。例えば、ショッピングカートクラスでいうと、ショッピングカート機能を作る上で必要になる要素になります。

#### 操作(メソッド)
操作(メソッド)は、クラス内で実際に行われる操作になります。ショッピングカートであれば、カートに商品を追加したり、カートから削除したりなど、そのクラスが持つ機能を言語化したものです。

#### 矢印について
この矢印は、クラスの関連性を表したものになります。例として、下記の画像の社員と会社の関係性を見てみましょう。
会社から見て、１つの会社にはたくさんの社員がいます。逆に社員から見て、会社は1つしかないです。
このように、社員と会社には一対多の関係が成り立ちます。
この画像の「1..*」というのは数が1つではないことを表し、会社の「1」は社員から見て1つしか存在していないことを表しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/fd914464-6849-00d7-68a2-6f6611f6288d.png)

以上になります。また追記します。
TypeScript入門：JavaScriptのSupersetとしての利点と特徴

# TypeScriptについて

TypeScriptはJavaScriptの拡張言語です。静的型付けとクラスベースのオブジェクト指向プログラミングをサポートすることで、より大規模な開発に適した言語となっています。

## JavaScriptとの互換性

TypeScriptはJavaScriptのすべての機能をサポートしており、JavaScriptと同様に動作します。また、JavaScriptと互換性があるため、既存のJavaScriptのコードをそのままTypeScriptに移行することもできます。

## 静的型付けのメリット

TypeScriptには、静的型付けによりバグの検出や予防ができるというメリットがあります。また、型情報を付与することで、IDEやエディターの支援が強化され、開発効率が向上します。

## クラスベースのオブジェクト指向プログラミング

TypeScriptはクラスベースのオブジェクト指向プログラミングをサポートしているため、より大規模な開発に適した言語となっています。

## 利用範囲

現在、TypeScriptはWebフロントエンド開発だけでなく、Node.jsなどのバックエンド開発にも利用されています。また、Angularなどの大規模なJavaScriptフレームワークもTypeScriptを採用していることから、将来性も高い言語となっています。

## おすすめ

開発に携わる方にとっては、是非一度試してみることをおすすめします。