OmniAICreator/Qiita-1.07M huggingface dataset:
Cocos Creator 3 のインストール

# ページ一覧

__Cocos Creator 3 導入編__
- [Cocos Creator 3 ダウンロード](https://qiita.com/Hiro256/items/941b196f2e3f0db9e7da)
- Cocos Creator 3 インストール ← __本記事__

__Cocos Creator 3 カンタン2Dゲーム制作__
- [プロジェクト作成と画面の説明](https://qiita.com/Hiro256/items/ee21f1aa5dc452f8e992)
- [(1)【トゥイーンの使い方】](https://qiita.com/Hiro256/items/872f82fe7c875106faaf)
- [(2)【プレハブの使い方】](https://qiita.com/Hiro256/items/26c4da8b46565e319471)
- [(3)【衝突判定（コライダの使い方）】](https://qiita.com/Hiro256/items/153777d22a3e24e4bb5a)

# Cocos Dashboard の起動
:::note
`Cocos Dashboard`を利用するには、事前にアカウントの登録が必要です。
詳しい手順は下記のページで解説しています。
[Cocos Creator 3 ダウンロード](https://qiita.com/Hiro256/items/941b196f2e3f0db9e7da)
:::

デスクトップのショートカットを起動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271948/de17d9a9-24e7-4bfb-bb99-293082c6dfed.png)

登録したアカウントでLoginする。
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271948/d7a24513-5cda-bee6-c923-54ed16b88ad0.png">

左側メニューの`Editer`を押す。
まだCocosCreatorのどのバージョンもインストールされていないので右ペインはブランク。
右下の`Download`ボタンを押す。
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271948/791edcb9-05d0-0d07-ebfd-ed629069a9e2.png">

ダウンロード可能な各バージョンの`Cocos Creator`が一覧で表示される。
一番上に最新のバージョンがある（本記事随筆時の最新版は`3.6.0`）。
ダウンロードするバージョンの右端「↓」アイコンをクリックし、ダウンロードを開始する。
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271948/cf0539f6-046b-6cd9-01c7-1f1300e47d34.png">

ライセンスに同意し`Accept`ボタンを押す。
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271948/3a5805e8-d5d3-9d13-48a7-e285692d22ab.png">

ダウンロードが開始する。ダウンロードが終わると自動で展開が始まる。（実行中は右端に`unzip`のメッセージが表示される）展開が終わるまで待つ。
すべて終わると次の画面の状態になる。
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271948/97cbefbc-c014-6900-672d-6d4c353328ac.png">
以上でCocos Creatorのインストールは完了です。
SwiftUI: アプリの起動時に1回だけやりたい処理はどこに書けばいいのか

自分用の時刻表アプリを作ろう、という記事を以前書いたのですが、

https://qiita.com/tnar-f/items/1a95429cf5e8547f0b2f

これに復路のViewを追加しよう、と思った時に、Viewの.onAppearに起動時に1回だけやる処理を記述していたことが問題になりました。Viewがひとつだけなら問題ないのですが、複数のViewを行ったり来たりする場合、Viewが表示されるたびに.onAppearが実行されてしまいます。

ということで、起動時に1回(だけやりたい/しかやってはいけない)処理はどこに書けばいいのか、調べてみました。

Xcodeでプロジェクトを作った時に(プロジェクト名)App.swiftなるファイルが作られたと思いますが、あれの中に書くのが正解のようです。

```Swift
import SwiftUI

@main
struct MyProject1App: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```
上のようになっているコードを以下のように変えます。

```Swift
import SwiftUI

@main
struct MyProject1App: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate  // この行を追加する
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

// 追加
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        // 起動時に1回だけやる処理をここに記述する
        
        return true
    }
}
```
以下の環境で、動作を確認しました。
MacOS Monterey 12.5.1
Xcode 13.4.1
バッグドアについて調べてみた

## バッグドアとは
バッグドアとは悪意のある攻撃者が一度、攻撃先のシステム内部の侵入に成功した際に **継続的に侵入が可能** になるように、内部に仕込むプログラムのことを指します。

システム内部から外部に通信するための **裏口** として利用されるため **バッグドア** と呼ばれます。

## バッグドアを仕込まれる手口
バッグドアはクライアント・サーバーの両方に仕込まれる可能性があるが、それぞれ主要な手口が異なるみたいです。
代表的な手口はこちら。

##### クライアント側
- メールの添付ファイルにプログラムが仕込まれる
利用者と面識のある人物を装って、添付されたファイルを開くように誘導し、ファイルを開くことでバッグドアが設置される被害。

   多くは、ワードやエクセルなどのマイクロソフトの文書であり、そういった **ファイルを開くとマクロが実行されバッグドアが設置される** みたいです。

##### サーバー側
- システムの脆弱性から仕込まれる
Webアプリケーションなどの脆弱性を突いて侵入され、バッグドアが設置されてしまうケース。
一度バッグドアを設置されるとそこから様々な攻撃が行われるみたい。

##### 例外(ヒューマンエラー)
サーバー・クライアント共に開発中にテストや開発効率を上げるために意図的にバッグドアを仕込む場合(ログイン無しでサーバーに入れる等）もあるそうで、そういった **意図的に組み込んだバッグドアを消し忘れてリリースしてしまう** こともあるそうです。


### バッグドアを仕込まれるとどうなるのか
バッグドアを設置されるだけでは被害はありませんが、様々な攻撃の対象になりがちです。
主に以下のような被害の標的にされるみたいです。

#### 機密情報の流出
サーバー側にバックドアが仕組まれた場合、攻撃者の遠隔操作によって、ユーザーの重要な個人情報が盗まれる場合がある。。

#### DDoS攻撃等の踏み台にされ、加害者になってしまう
Webサイト等に一度に大量のアクセスをすることでサービスをダウンさせるDDoS攻撃等の踏み台にされる場合も多いみたいです。
そういった場合 **本来被害者である、バックドアを仕込まれた側が攻撃に加担する状況** になってしまうため、 **加害者としての責任を問われる場合もある** そうです。

また、バックドアを仕組んだ攻撃者からすれば **IPアドレスを偽装できる** ので常套手段として使われているそう。。

## バッグドアの被害例
##### Linuxディストリビューションに仕込まれた事例
Linuxディストリビューションの一つ、「LinuxMint」のWebサイトが何者かに改ざんされた。
この際に、バッグドアが仕込まれた「LinuxMint」にファイルが書き換えられており、改ざんが発覚するまでの間、バッグドアが仕込まれた「LinuxMint」が配布されていた。

##### パソコン遠隔操作事件
2012年に複数のパソコンから掲示板に殺害予告が書き込まれた事件があり、その際に **4人もの人物が誤認逮捕** に繋がるという事件があった。
真犯人は、[「トロイの木馬」](https://www.amiya.co.jp/column/trojan_20210113.html)に感染させ、バッグドアを設置し、そこから遠隔操作を行い書き込みを行っていたそうです。

## さいごに
最近サイバー攻撃について調べていますが、様々な攻撃手段があって怖いですね。。。
React + FastAPI で画像のアップロード&保存機能を実装


## はじめに
Reactの初学者です。

画像のアップロードと保存機能を実装する際に結構詰まったので、備忘録として残しておきます。
フロントエンドはReact、バックエンドはFastAPIで実装します。

コードは初心者っぽいところが多いと思われます。ご了承ください。

## React
まずは全体のコード。
formタグ内で画像を選択した後、Submitボタンを押すとAPIリクエストが送信されます。

```my-app/src/components/SubmitImage.jsx
import React from 'react'
import { useState } from 'react'
import 'bulma/css/bulma.min.css' // css

export const SubmitImage = () => {
    const [image, setImage] = useState()
    const [errorMessage, setErrorMessage] = useState('')
    const URL = 'http://127.0.0.1:8000/images/' //適宜設定

    const getImage = (e) => {
        if(!e.target.files) return
        const img= e.target.files[0]
        setImage(img)
    }
    const Submit=async()=>{
        const formdata = new FormData()
        formdata.append('upload_file', image)
        const requestOptions={
            method:"POST",
            body:formdata,
        }
        const response =await fetch(URL,requestOptions)
        const data=await response.json()
    }
    const handleSubmit=(e)=>{
        e.preventDefault()
        Submit()
    }
    

    return (
        <div>
        <form className="box" onSubmit={handleSubmit}>
            <label className="label" htmlFor="img">画像</label>
            <div>
                <input id="img" type="file" accept="image/*,.png,.jpg,.jpeg,.gif" onChange={getImage}/>
            </div>
            <br/>
            <button className="button is-primary" type="submit">Submit</button> 
        </form>
        <ErrorMessage message={errorMessage}></ErrorMessage>
        </div>
    )
}
```

ポイントはここ。
```jsx
const Submit=async()=>{
        const formdata = new FormData()
        formdata.append('upload_file', image)
        const requestOptions={
            method:"POST",
            body:formdata,
        }
        const response =await fetch(URL,requestOptions)
        const data=await response.json()
    }
```
- FormDataオブジェクトにuploadされた画像をappendする。
    - このときのkey='upload_file'はFastAPI側で使用します。
    
- requestOptionsにはheadersを指定しない。
    - ```"Content-Type":"multipart/form-data"```は記載しないほうが良い。
    - 指定すると 400 Bad Requestを吐かれます。

### 見た目
![スクリーンショット 2022-08-21 100044.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697721/fa778863-70f6-a751-a70b-0132ecd25581.jpeg)


## FastAPI
続いてバックエンド側
```api/main.py
from fastapi import FastAPI,UploadFile
import shutil

app=FastAPI()

# ~~~~~~　省略　~~~~~~~~

@app.post("/images/")
def get_uploadfile(upload_file: UploadFile): # フロント側のFormDataのkeyに合わせる(upload_file)
    path = f'api/files/{upload_file.filename}'# api/filesディレクトリを作成しておく
    with open(path, 'wb+') as buffer:
        shutil.copyfileobj(upload_file.file, buffer)
    return {
        'filename': path,
        'type': upload_file.content_type
    }
```

FastAPIに画像を保存する機能は無く、shutilでコピーして保存するようです。

### つまづいた点

フロント側とバックエンド側でformDataのkey値を揃える必要がある。
すなわち、
- React 
    ```formdata.append('upload_file', image)```
- FastAPI
    ```def get_uploadfile(upload_file: UploadFile): ```

のように、上記の例ではupload_fileと揃える。

これに気づかず、422 unprocessable entity　を永遠に吐かれていました。。。
DatabricksクラスターUIの変更

[Databricks Clusters UI changes \| Databricks on AWS](https://docs.databricks.com/clusters/cluster-ui-preview.html) [2022/8/19時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

新たなクラスターUIが導入され、以下の点が変更されました。

- これまでは**Advanced options**内にあった**Security mode**ドロップダウンが、**Access mode**で置き換えられました。
- **Cluster Mode**ドロップダウンメニューは2つの選択肢(**Multi node**と**Single node**)のラジオボタンで置き換えられました。
- 今後はスタンダードクラスターとハイコンカレンシークラスターには違いがなくなります。アクセスモードがクラスターにおけるアイソレーションを決定し、すべての共有クラスターでは複数ユーザーによるクエリーを最適化します。
- **Advanced options**において、アクセスモードが**Single user**か**Shared**の場合にクレディンシャルパススルーのチェックボックスが利用できます。クレディンシャルパススルーのチェックボックスを選択すると、クラスターではパススルーがサポートされ、Unity Catalogへのアクセスは無効化されます。

**Preview**オプションで新規のUIのオンオフを切り替えることができます。

# これらの変更によって後方互換性はどうなりますか？

後方互換性を維持するために、**Preview**を選択し、**New UI is enabled**をオフにすることができます。
![](https://docs.databricks.com/_images/cluster-preview.png)

すべての既存のインタラクティブクラスターやジョブクラスターの定義はそのまま動作し続けます。既存のクラスターを起動、再起動した際、既存のジョブ実行が起動された際には挙動は変わりません。

:::note info
**注意**
レガシーなクラスター定義は**Custom**アクセスモードとしてクラスターUIに表示されます。これは、後方互換性のためだけのものであり、ドロップダウンリストから選択することはできません。
:::

Unity Catalogが有効化されていない(すなわちUnity Catalogのメタストアが割り当てられていない)ワークスペースでは、新たなクラスターを作成する際に、オリジナルのクラスター設定から新規のアクセスモードに移行するためには以下の表を使ってください。

| オリジナルのクラスター設定 | アクセスモード |
|:--|:--|
|スタンダード   | No isolation shared  |
|スタンダード + クレディンシャルパススルーのチェックボックスがチェックされている   | Single user + クレディンシャルパススルーのチェックボックスをチェック  |
| ハイコンカレンシー(HC)  | No isolation shared  |
| HC + テーブルACLのチェックボックスがチェックされている  |  Shared |
| HC + クレディンシャルパススルーのチェックボックスがチェックされている   | Shared + クレディンシャルパススルーのチェックボックスをチェック |

Unity Catalogが有効化されているワークスペースにおいては以下の表を使ってください。

| オリジナルのクラスター設定 | アクセスモード |
|:--|:--|
|None   | No isolation shared  |
|Single user  | Single user  |
|User isolation   | Shared + Runtime 10.3以降  |
| Table ACL only (Legacy)  | Shared + Runtime 9.1以前  |
| Passthrough only (Legacy)  |  Shared + クレディンシャルパススルーのチェックボックスをチェック |

# 制限

:::note warn
**重要！**
プレビュー期間中、アクセスモードはUIからのみ利用できます。APIはサポートされていません。
:::

新規クラスターを作成する際、以下のセキュリティ関連のSpark設定は新UIでは使用することができません。クラスター設定をファインチューンしたい場合(例えば、PrivaceraやImmutaとのインテグレーションなど)には、これらの設定行うt前にカスタムクラスターポリシーを定義することができます。サポートについてはDatabricks担当にお問合せください。

- `spark.databricks.repl.allowedLanguages`
- `spark.databricks.acl.dfAclsEnabled`
- `spark.databricks.passthrough.enabled`
- `spark.databricks.pyspark.enableProcessIsolation`

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Djangoでアプリ開発する際参考にした記事まとめ


## はじめに
Djangoでチュートリアル以上の機能を実装したときに、参考にした記事の一覧です。
参考になれば幸いです。

## 参考

### メディアファイルをS3に保存する
https://qiita.com/okoppe8/items/7ecbc92187171926238f

### Googleログイン機能を実装する
https://qiita.com/moi1990sk/items/a849fca7acb29db95508

https://nwpct1.hatenablog.com/entry/django-oauth-twitter-facebook-github

### ログインしていなければできない機能を実装する
https://qiita.com/hayata-yamamoto/items/d0305942199acd63b7c9

### 投稿にユーザーを紐づける
https://qiita.com/Quest_love33/items/77c5cbf3acd2c09edd0a

https://qiita.com/K_SIO/items/dd9f556ae57780448ef0

### 投稿に対していいね機能を付ける
https://qlitre-weblog.com/django-iine-ajax-create/

### 投稿の並び替え機能を実装する
https://www.sejuku.net/plus/question/detail/15438

### 各ユーザごとにいいねした記事の閲覧ページを作成する
https://teratail.com/questions/265126

### 設定ファイルをenvファイルに書き、githubにpushしないように
https://qiita.com/moonwalkerpoday/items/9da47dda80d3ddac9a62

https://techacademy.jp/magazine/10179

### EC2で本番環境構築
https://tomato-develop.com/amazon-linux-2-django-python-nginx-gunicorn-postgresql/

### 独自ドメインを取得し、IPアドレスを変換する
https://avinton.com/academy/route53-dns-vhost/

### セキュリティ強化のためのHTTPS化
https://vector-ium.com/django-https/
Unityでよく使う初心者用コードサンプル集

# 0.この記事の目的
Unityのプログラミングを初心者に教える際、ぱっと簡潔なコードがなかったりするので、このへんでまとめておこうと思った。
あくまで初心者用だ、ということに留意してほしい。（もっとこうしたほうが処理が軽い、みたいなのは無視しています）
随時更新して拡張していく予定。

# 1.当たり判定
```c#:Test.cs
using UnityEngine;

public class Test : MonoBehaviour
{
    private void OnCollisionEnter(Collision collision) //なにかにあたった瞬間に呼び出される
    {
        if (collision.gameObject.tag == "Enemy") //Enemyというタグがついている敵に当たったら
        {
            //あたった後の処理を書く
        }
    }
}
```

# 2.シーン移動（ゲームクリアとか）
```c#:Test.cs
using UnityEngine;
using UnityEngine.SceneManagement; //追記必須

public class Test : MonoBehaviour
{
    private void Start()
    {
        SceneManager.LoadScene("GameScene"); //GameSceneに移動する
    }
}
```

ただし、これはコーディングだけではだめで、実行前に事前に該当シーンをBuild Settingで登録しておく必要がある。

![スクリーンショット (230).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1233990/431d9437-1d47-43d6-90de-2bf5146dfed8.png)

# 3.ToString()の使い方
```c#:Test.cs
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Start()
    {
        //int型からstring型に型変換したい
        int num = 7;
        string numSt = num.ToString();

        //float型からstring型に型変換したい
        float num2 = 0.7f;
        string num2St = num2.ToString();
    }
}
```

# 4.SetActiveの使い方
↓↓ここを変更するやつのコード。

![スクリーンショット (232).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1233990/0f961145-ca4f-78be-5aee-6769f38d6bce.png)

```c#:Test.cs
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Start()
    {
        //ゲームオブジェクトを表示したいとき
        this.gameObject.SetActive(true);
        
        //ゲームオブジェクトを非表示にしたいとき
        this.gameObject.SetActive(false);
        
        //実はこれが元の形。元の形をみたらSetActiveの理解が深まるかな？
        this.gameObject.active = true;
    }
}
```

# 5.効果音の鳴らし方
```c#:Test.cs
using UnityEngine;

public class Test : MonoBehaviour
{
    private AudioSource audioSource; //音を鳴らすコンポーネント
    [SerializeField] private AudioClip audioClip; //鳴らしたい音楽素材
    
    private void Start()
    {
        //AudioSourceコンポーネント取得
        audioSource = this.gameObject.GetComponent<AudioSource>();
        
        //効果音の鳴らし方
        audioSource.PlayOneShot(audioClip);
    }
}
```
二項係数を素数で割った余りを求める（Lucasの定理、中国剰余定理）

### 【例題】
 * **二項係数$C(2^{20},2^{10})$を$29 \times 113 \times 463$で割った余りを求めよ。**

これを素直に解こうとすると以下のようになりますが、残念ながらいくら待っても答えはでません。

```python 
from sympy import binomial
print(binomial(2**20, 2**10)%(29*113*463)
```

そこで以下の順番で考えて行きます。

1. Lucasの定理を使って分母の素因数で割った余りをそれぞれ求める
1. それらの余りから中国剰余定理を使って全体の余りを求める。

#### 1. Lucasの定理を使って分母の素因数で割った余りをそれぞれ求める

[Lucasの定理とその証明(高校数学の美しい物語)](https://manabitimes.jp/math/1324)で紹介されているように。以下の手順で計算します。

1. まず二項係数$C(n,k)$の$n,k$を$p$進数で表す(**baseRep**)
1. その対応する各桁を$n_i, k_i$としたとき$C(n_i, k_i)$を求めて$\pmod p$で掛け合わせる。

コードにすると、以下のようになり各素因数29,113,463で割った余りが求まります。

```python 
from sympy import binomial
from functools import reduce
def baseRep(n, b):   # n: number, b: base
  if n >= b:
    yield from baseRep(n // b, b)
  yield n % b

def lucas(n,k,p):    # return C(n,k) (mod p)
  np, kp = list(baseRep(n,p)), list(baseRep(k,p))
  kp[0:0] = [0]*(len(np)-len(kp))  # 0 fill to align the digits
  return reduce(lambda x,y:(x*y)%p,[binomial(ni, ki)%p for ni, ki in zip(np, kp)],1)

m, n = 2**20, 2**10
for p in [29,113,463]:
  print(f"p:{p}, C({m},{n})% {p}= {lucas(m,n,p)}")

#p:29, C(1048576,1024)% 29= 27
#p:113, C(1048576,1024)% 113= 101
#p:463, C(1048576,1024)% 463= 402
```

#### 1.それらの余りから中国剰余定理を使って全体の余りを求める。

次は各々の余りを中国剰余定理を使って全体の余りを求めます。まず$C(2^{20},2^{10})=X$と置くと。

```math 
\begin{align}
X &= 27 &\pmod {29} \\
X &= 101 &\pmod {113} \\
X &= 402 &\pmod {463}
\end{align}
```

となるので[PythonのSympyを使って中国剰余定理(CRT)を解く](https://qiita.com/masa0599/items/2c93189dcc6beee5d8c5)で紹介したsympyのcrtを使うと例題の答えが求まります。


```python
import sympy.ntheory.modular 
m = [29,113,463]
a = [27,101,402]
(x, y) = sympy.ntheory.modular.crt(m,a) 
print(f"Answer = {x}")
# Answer = 1476446
```

この考え方はProject Euler, Problem 365: A huge binomial coefficientを解くのに役に立ちます。

（開発環境：Google Colab）
SwiftUI: TabViewを使って2つのViewをスワイプ動作で切り替える

自分用の時刻表アプリを作ろう、という記事を書いた時に、往路と復路の時刻表画面をスワイプ動作で切り替えられたらいいな、と思ったのでやってみました。

https://qiita.com/tnar-f/items/1a95429cf5e8547f0b2f

Viewを2つ用意します。

Sub1View.swift
```Swift
import SwiftUI

struct Sub1View: View {
    var body: some View {
        Text("This is Sub1View")
    }
}

struct Sub1View_Previews: PreviewProvider {
    static var previews: some View {
        Sub1View()
    }
}
```

Sub2View.swift
```Swift
import SwiftUI

struct Sub2View: View {
    var body: some View {
        Text("This is Sub2View")
    }
}

struct Sub2View_Previews: PreviewProvider {
    static var previews: some View {
        Sub2View()
    }
}
```


次に、ContentViewを以下のようにします。

```Swift
struct ContentView: View {
    var body: some View {
        TabView {
            Sub1View()
                .tabItem {}.tag(1)
            Sub2View()
                .tabItem {}.tag(2)
        }.tabViewStyle(.page)
    }
}
```

.tabItemを空にして、.tabViewStyleを.pageにすると、Tabの表示が消えて、スワイプ動作でSub1ViewとSub2Viewが切り替わるようになります。

# .on(〇〇)に注意
Viewが一つしかない場合は気にしないでよかったのですが、複数のViewを行ったり来たりするようになるとViewの.on(〇〇)の扱いに注意が必要です。例えば.onAppearに起動時の処理を記述しているような場合。コードを以下のようにしてみるとわかるのですが、Viewが切り替わるたびに、.onAppearが呼び出されていることがわかります。.onAppearに起動時に一回だけやる(べき)処理を記述している場合などは注意が必要です。

```Swift
struct Sub1View: View {
    var body: some View {
        VStack {
            Text("This is SubView1")
        }.onAppear(){
            print("SubView1 .onAppear called!")
        }
    }
}
```

起動時に1回だけやる処理をどこに記述すべきか、を以下の記事に書きました。

https://qiita.com/tnar-f/items/9bef6d171f58dd13c152

以下の環境で、動作を確認しました。
MacOS Monterey 12.5.1
Xcode 13.4.1
ARCore Geospatial API Terrain anchors（地形アンカー）のサンプルを見る

# 概要
2022/08/19 に ARCore Geospatial API の Terrain anchors（地形アンカー）が公開されました。

https://twitter.com/GoogleARVR/status/1560343083299979264

この Terrain anchors によって、今まではアンカーを作成する時に高さ情報が必要でしたが、高さ情報が必要なくなりました。高さは Terrain anchors の API を使用すると、緯度/経度から高さを自動的に入ります。

本記事ではこの Terrain anchors のサンプルを見てみようと思います。

# 実際に動かしたところ

https://twitter.com/fit51/status/1560379254407196672

https://twitter.com/fit51/status/1560413034593800192

# Geospatial API とは、サンプルの環境構築方法
Unity で環境構築する方法が記事にありますので、こちらを参考にしてください。
こちらと同じ方法で、Terrain anchors の環境構築が可能です。

https://zenn.dev/tkada/articles/04b44474149130

# 環境
Unity 2021.3.4f1
AR Fundation 4.2.3
ARCore XR Plugin 4.2.3
ARKit XR Plugin 4.2.3
ARCore Extensions 1.33.0

# ドキュメント
## 公式ドキュメント

https://developers.google.com/ar/develop/unity-arf/geospatial/terrain-anchors

## GitHub Release
ARCore Extensions for AR Foundation v1.33.0

https://github.com/google-ar/arcore-unity-extensions/releases/tag/v1.33.0

## Terrain anchors の API
ResolveAnchorOnTerrain

https://developers.google.com/ar/reference/unity-arf/class/Google/XR/ARCoreExtensions/ARAnchorManagerExtensions#resolveanchoronterrain

# Terrain anchorsの使い方
GeospatialController.cs の PlaceGeospatialAnchor() で、Terrain anchors を使用しています。
ここ以外は他と変更なく Terrain anchors を利用できます。つまり`AnchorManager.AddAnchor`を`AnchorManager.ResolveAnchorOnTerrain`に変更するだけです。

```cs
        private ARGeospatialAnchor PlaceGeospatialAnchor(
            GeospatialAnchorHistory history, bool terrain = false)
        {
            Quaternion quaternion =
                Quaternion.AngleAxis(180f - (float)history.Heading, Vector3.up);
            var anchor = terrain ?
                AnchorManager.ResolveAnchorOnTerrain(
                    history.Latitude, history.Longitude, 0, quaternion) :
                AnchorManager.AddAnchor(
                    history.Latitude, history.Longitude, history.Altitude, quaternion);
            if (anchor != null)
            {
                GameObject anchorGO = terrain ?
                    Instantiate(TerrainPrefab, anchor.transform) :
                    Instantiate(GeospatialPrefab, anchor.transform);
                anchor.gameObject.SetActive(!terrain);
                _anchorObjects.Add(anchor.gameObject);
            }

            return anchor;
        }
```

実際には、`AnchorManager.ResolveAnchorOnTerrain(history.Latitude, history.Longitude, 0, quaternion)`の部分で、緯度/経度を引数に渡すと緯度/経度に応じた高さが設定されたアンカーを作成することができます。

以前の API では、`AnchorManager.AddAnchor(history.Latitude, history.Longitude, history.Altitude, quaternion);`のように`Altitude`を指定する必要がありましたが、`ResolveAnchorOnTerrain`にはありません。
代わりにあるのは`altitudeAboveTerrain`で、緯度/経度に応じた高さからの相対値を指定します。地面/床より 1m 高い位置にアンカーを設置したい場合は 1 を指定します。サンプルは 0 ですので地面/床の高さにアンカーが設置されます。

# サンプルアプリの動作
実際に動かすと下図のような画面が表示されます。
`SET TERRAIN ANCHORS`をタップすると、Terrain anchors を作成できます。`SET ANCHOR`をタップすると、今までのアンカー（スマホの高さ）を作成できます。

![](https://storage.googleapis.com/zenn-user-upload/8580ea12e611-20220820.png)

# まとめ
- 国土地理院などから高さを取得する必要が無くなったのでかなり実装は楽になります。
- 今までの実装とほとんど変更なく Terrain anchors を利用できるのでかなり移行も楽です。
Live2D　口の形を楽をして作る

口の形は使用するプラットフォームによって異なりますが概ね７～９パターンの口の形を用意しておく必要があります。
例：https://mobile.twitter.com/nonon_yuno/status/1496802091171524609

そのため、元の素材の形を除いた8パターンをすべて手作業で作らなければならないと思うと少し面倒に感じますが、ある程度省略することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704221/b0f8c820-8228-6870-fb88-12f606de2c5b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704221/fca464bc-c6a8-4860-92a8-94cd94eef6dc.png)
まず閉じた口と開いた口を作り

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704221/595f4e52-8d61-4ea0-faa2-dec19f68410d.png)
中間としたい別の状態を指定して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704221/baad247a-2401-4bf7-4308-270fc6437310.png)
［モデリング→フォームの編集→フォームのブレンド］を選ぶ（事前にコピーが必要）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704221/2600927c-5223-5938-bb98-7462c75e2180.png)
あとは適用度を変えていくと・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704221/9c8c4581-5750-8171-9cfa-7289bfca02ac.png)
良い感じの中間のバリエーションができるので、あとはこれを微調整

他にも前述した［モデリング→フォームの編集→フォームのコピー］を使って近い形を引っ張ってきて調整するなどすれば作業の手間はグンと減らせます。
Simulatorに保存されているアプリと設定を全削除したい!!

# はじめに
XCodeでアプリを製作していると、やりたい機能だけを切り出したテストアプリがものすごい量になっていたので、削除したいと思いました。

結果から言うと、**一発で全削除する方法がありました**ので、紹介します。😁
削除する方法をまとめました。

### 1.アプリを長押しする

実機Iphoneと同じ容量です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/972446b8-9be0-8c69-f5ee-a63ad206cec0.png" width=40%>

一つずつアプリを長押しで消していくのはかなり労力が入りますね😭
実機でも結構ストレスですよね。
### 2. メニューのErase All Content and Settingsで削除

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/82dad8eb-31ac-faec-8776-8c1276f6080d.png" width=40%>

この方法だとシミュレーターのデバイスを一発で初期化してくれます😆
ただ、選択しているデバイスだけに適応されますので、一つ一つのデバイスごとに実行しないと全てのシミュレーターのデータを削除できません。

これもなかなか手間ですね😂

### コマンドで一発で削除🥹
一発で削除できる方法、ありました!!

ターミナルで、下記のコマンドを実行してください。
```
xcrun simctl erase all
```

この一行で、全てのシミュレータのデータを初期化出来ます😄
ストレージの節約にもなりますので、定期的に削除して、快適なmacライフを送っていきたいと思います!!

以上です😁
ARC146参加記 (兼 A,B解説)

# はじめに

2完だった。ARCは考察が大事だと思うので、その整理と解説を兼ねて書く。


# A - Three Cards

## 問題

https://atcoder.jp/contests/arc146/tasks/arc146_a

## 当時の考察

「数字を連結する」という操作が発生することを考えると、無理にintにするより、
文字列のままのほうが扱いやすそうだな、と思って文字列のまま考え始めた。

「出来上がった数字が一番大きくなる」を文字列として考えると、
まず、文字数が最も多くて、次に辞書順で最も遅いものである。

※なお、辞書順で遅い≠文字列が長いではないので注意が必要である。
```py
>>> "2" < "12"
False
```

これは材料となる数字も同じなので、文字長順→辞書降順でソートする。
これの上位3つを上位順にくっつければ答え、と思ったらWAした。

https://atcoder.jp/contests/arc146/submissions/34162876

このままだと、上位３つで桁が異なるケースで、桁数が大きいが先頭行の数字が小さい場合に問題になる。
具体的には、入力が下記のケースにおいて、
```
3
9 111 21
```
`911121`が最も大きくなるが、桁順が優先でソートされると`111219`になってしまう。
よって上位3個抽出した後に、さらに辞書降順にソートした上で結合するようにした。

### 2022/8/21 8:40　追記

再度提出したらafter_contestでWAがでた。

https://atcoder.jp/contests/arc146/submissions/34186082

3個の候補を全探索してベストを探す実装に変更。


## AC提出

https://atcoder.jp/contests/arc146/submissions/34186195

# B - Plus and AND

## 問題

https://atcoder.jp/contests/arc146/tasks/arc146_b

## 当時の考察

まず、M回の操作の使いどころについて考える。

ANDの最大値ということを考えると、上位bitを立てずに操作を温存して下位bit全てを立てたとしても、出来上がる値は改善することはない。

例:`1000 > 111` 

従って、上位桁から順に操作を行えばよい。

また、操作はKより多い要素に対しても行うことができるが、要素選択に選ばない要素に操作をすることは無駄である。よって、一度操作および最後の選択対象の要素を決めた後は、それ以外の要素は忘れて、決定した要素のみに操作を行うようにすればよい。




さて、これらを踏まえてとりあえず実装を始めた。
上位bitから見ていくが、場合分けとして、

1. 元からK個以上着目するbitが立っている時
1. 立っていない時
    A. K個以上bitが立つように要素に加算できる時
    B. 操作回数が足りず加算できない時

が考えられる。

1.の時、そもそも操作が必要ないので、回答のbitに含めることができる。また、該当bitが立っている要素は、選択対象の候補になる。逆に該当bitが立っていない要素に関しては、選択対象にはなりえないので、処理対象から外してよい。

2.の時、補充するために必要な操作数を数えよう。この操作対象の要素は元の値が大きければ操作回数を削減できるので、現在の着目bitより下のbitを見たときに、数字が大きい値ものから上位K個だけを見てあげればいい。（実装上は、全体のbit走査毎にに上位bitは都度消して降順ソートしているので、上位K個を見ている）

2-Aの時、累積の操作回数を合算し、後続の2-A,Bの判定に利用する。
なお、操作後の要素は、着目bitより下は0埋めされたものになる。（実装上は0、すなわち上位も含めて0にしている）


## AC提出

309msでコンテスト時pythonだと最速だった。

~~たぶん計算量は、各bit走査`O(log(A)`× 要素のソート`O(NlogN)` = `O(N logN logA)`で公式解説より速そう。~~
Aのbit数に依存したbitマスクをしてるので、結局 O(N logA (logA+logN))っぽい。（やりたいことは単一bitを0にしたいだけだけど）

~~更に~~K個より多いのは対象から外すとかしているので、枝切りされて定数倍にも効いているっぽい。
違ってたら教えてください。


https://atcoder.jp/contests/arc146/submissions/34173792
[atom] platformio-ide-terminalのtoggleキー変更

atomでplatformio-ide-terminalが良さそうなので(修正頻度が多い、利用者多い、ショートカットキーでエディタと切り替えできそう)インストールを試みた。

設定＞インストールでインストール初回、なんかエラーメッセージがでていたが、atomを再起動したらbusy-signalのインストールダイアログが出たのでインストールすると、platformio-ide-terminalもインストールされていた

インストール後、toggleのショートカットキーが効かない(ctrl + `)
左下のプラスアイコンから起動できるので起動してみる
WindowsだとデフォルトPowerShellになってるので、[ここ](https://fuchiaz.com/atom-wsl/)を見てWSLに修正する(plat~の設定から、Shellの上書き項目でC:\Windows\System32\bash.exeを指定すればOK)

ショートカットキーでToggleしたいのでCtrl+\`を押すが、何も起こらない..
結果、Toggleのショートカットキー用のキーバインドを設定したら、他のショートカットキーで使えるようになった
設定＞キーバインドで、検索窓にplatformio-ide-terminalと入力するとplat～関連のキー一覧がでるので、ctrl+\`の:toggleの左端のクリップボードコピーアイコンをクリックして、キーマップファイル(setting.cson)にペーストし、ctrl+`部分を適当なものに変更して保存すればOK(以下ではCtrl+0)

```
'.platform-linux atom-workspace, .platform-win32 atom-workspace':
  'ctrl-0': 'platformio-ide-terminal:toggle'
```
STM32G031のPWMを使う



x 超超重要 なぜか秋月STM32G031J6M6がうり切れていた。注意!!(2022/8/27現在)

x 過去ログを見よ!!

x Mbedでのボード設定は、NUCLEO-G031K8
x ここで言うSTM32G031は、秋月で売っているSTM32G031J6M6の事


目的
STM32G031J6M6で遊ぶ
使ってみたかった
LED等を繋げる
sg90でためしていないけど


![o_con697.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4111bacf-8804-9578-3a31-2d26ff6cd8de.jpeg)



参考



https://os.mbed.com/users/okini3939/notebook/PwmOut_jp/




http://carefreework.blog.fc2.com/blog-entry-14.html



```c++



//pwm_test1_031_1

#include "mbed.h"


//data SG90
// 2400us 2.4ms
#define s_max  2400
// 500us 0.5ms
#define s_min  500 
#define s_r    (2400-500)
#define s_c    ((2400-500)/256)
#define SN(n6) (500+(((2400-500)/256)*n6))


//PWMのピンの設定
PwmOut servo(PA_11); //5PIN   //031


//メイン関数
int main() {

    //周期の設定    
    //servo.period(0.020);          // servo requires a 20ms period
    servo.period_ms (20);

    //無限ループ
    while (1) {

        //0から256までループ
        //for(float offset=0.0; offset<0.001; offset+=0.0001) {
        for(int offset=0; offset<256; offset++) {

            //pc.printf(" -S=%d\t%d\r\n", offset , SN(offset) ); //767

            //オン時間の設定
            //servo.pulsewidth(0.001 + offset); // servo position determined by a pulsewidth between 1-2ms  　　　
            servo.pulsewidth_us( SN(offset) );

            //250ミリ秒まつ
            //wait_us(250*1000);
            wait_us(4*1000);
        }//for
    }//while
}//main






```
#プログラミング #Javascript #nodejs # #twitter の #推しNHKドラマを3つ貼る見た人もやる を集計

本内容を利用した場合の一切の責任を私は負いません。

# 概要
7月末にNHKが下記のtweetをしたのでAPIを使って集計してみた。
https://twitter.com/NHK_DVD/status/1553228894316023808

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/0f86abe0-9853-43f6-1dda-fa37bdcb54ed.png)

# バージョン
・node-v10.16.0-win-x64
・needle@3.1.0
・columns　Version: 2.2.2

# 集計ルール
・NHKのtweetの日以前に作成されたユーザーのtweetが対象
　(=新しいユーザーは除外。)
・1アカウントの最新のタグ有りtweetのみ対象
　(=複数の場合は最新のみ。)
・タグの直前直後の空行を除く3行を、1行当たり20文字分
　直前直後は直前が優先で、直前が無いか空行のみの場合のみ直後を採用する。
・#等記号と空白を無視
　#等記号は、
　・#
　・「」
　・『』
　・「・」
　・①②③
　・✓
　・📺
　・'
　・"
　・’
　・”
　・!
　・！
・主なカテゴリー名を無視
　主なカテゴリは、
　・連続テレビ小説
　・海外ドラマ
　・大河ドラマ
　・銀河テレビ小説

# リポジトリ
https://github.com/github895439/NhkDramaTotalling

主なファイルは、
・nhk_drama_totalling.js
　本体。
・totalling_result_top1000.csv
　集計結果。
・nhk_drama.csv
　カテゴリ名が含まれていると集計精度が落ちる。
　どんなカテゴリーがあるか下記を解析して確認した。
　https://www2.nhk.or.jp/archives/search/index.cgi?type=index&genre=drama&subgenre=0&year=all&view=0#page=1
　解析時に取得したデータ。

# 使用
node.jsでnhk_drama_totalling.jsを動かし、ブラウザからlocalhost:8081にアクセスする。
twitter APIの認証はBearerを使用してるので、twitterの開発者ページで発行し、「token」環境変数に設定しておく。
そうすると、nhk_drama_totalling.js#L24の下記で使用される。
`const token = process.env.token;`
実行は1リクエストごとに停まるようなブレークポイントをかけること。
停めないとAPIのRateを超えて途中で止まることになると思う。
(下記のAPIのページにRateが載っている。)

# 備考
自分のtwitterリストチェッカー( https://qiita.com/qiita21409102/items/b1acef8b270b502838aa )を流用した上に、APIの使用回数上限により何度も実行できないため、全く精査されていないソースになった。
ただ、個人情報を除いて、動作実績のあるものが良いと思ったので、このまま挙げた。

50件取得で215リクエストなので該当tweetは10750程あったもよう。
ちなみにAPIでは100件取得までできる。
何故100件にしないかというと、needleライブラリの受信バッファがどうやら0.7MBくらいしかないっぽい。
レスポンスが正常終了なのにデータが中途になっている。
(HTTPのレスポンスのcompleteを見るとfalseになっているのでわかる。)
twitter APIは厳密には下記のSandboxのlast30dayを使った。
https://developer.twitter.com/en/docs/twitter-api/premium/search-api/overview
本当のPremiumは有料。
Standardサーチは直近7日(自分の動作実績では10日)しか取得できない。
V2APIのRecentも7日で、FullはAcademic用。
https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference

集計結果はJSONをWeb表にするjqueryライブラリの下記を使った。
[columns]
https://github.com/eisenbraun/columns

上記のtwitterリストチェッカーで使っていたtwitterライブラリはBearerに対応していないようだったので、今回は下記のneedleを使った。
[needle]
https://github.com/tomas/needle
上記のストリームの説明に「from 0.7+」とあるのは0.7MB制限のことかも。
実働もそのくらいの大きさで中途になる。
ただ、ストリーム等のメソッドはクエリーをオブジェクトで渡せず、URL指定になる。
自分がやった時はURL指定ではうまく動作しなかった。

※追記(2022/08/21)
最初に考えた集計方法は違った。
tweetが主ではなく、NHKのサイト解析で得たドラマリストが主。
これをtweetにマッチングしていって票を集める。
ただ、これだとリストが2500くらいあり、かなり時間がかかると思ったため。
けど、この方法なら不要な語句のことを考える必要もないし、集計精度は高い。
この集計方法が先にあったため、リストを取得した。
というか、解析でリストが取得できたから、集計してみようと思った。
ちなみにリストは管理情報的なものもあるらしく、放送日が載っていないものもあるので、まず、リストを精査する必要があるとは思う。
#2 【 Unity の教科書 】 をマスターするまでの記録

**【今日の目標】**
<dl>
    <dt>① Chapter 4 UIと監督オブジェクト にプラスの機能を作る</dt>
    <dd>（1）マウスのクリック数で加速度が変化する車を作る<br>⇒実装できた</dd>
　　<dd>（2）クラクション音を入手して，B を押すとクラクションが鳴るようにする<br>⇒実装できた</dd>
　　<dd>（3）スタートから，旗の位置までのタイムを測定できるようにする<br>
⇒タイムを測定する機能は作れたが，車と旗の衝突判定が作る事が出来なかった
</dd>
<p>
  <br>  
</p>
<dt>② Unity の教科書 を31ページ進める（P224まで）</dt>
</dl>

**【成果・所感】**
(1) 今日の目標 ① の(3) に多く時間を使ってしまった。
⇒ 勉強のペースの配分を間違えた
⇒課題に取り組む際に，取り組む前に使って良い時間を設けるようにする
(2) 疑問があった際に「検索ワード」「URL」「得た事」をワークシートに書くようにしたが，ワークシートの書き方に不慣れで，活用が上手くできなかった
⇒ 使い方に慣れて，学びに生かす
(3) ブログの書き方を工夫することで，学習効率を上げるようにする
⇒ 目標に対して，「実装できた」だけでなく，どうした事で達成できたのか書くようにしたい。
(4) ブログを日付が変わる前に投稿する。夜に急な予定が入ったときなど，書いていないと投稿できないので，細目に書いて保存するようにする。
僕が勘違いしてた仮想DOMのメリット

# 経緯
DOMについて調べてた時に気づいたので、備忘録として。
（この備忘録ではReactベースで書いてます）

# 結論
仮想DOMの真のメリットは「パフォーマンスが良いこと」ではなく、「<strong>宣言的UIの実現と現実的なパフォーマンスを両立できること</strong>」にある。

# 命令的UIと宣言的UIってなんだろう...

### 命令的UI
「イベント・変更が発生するたびに、どのように処理を実行し、状態を反映するのか」を記述する必要がある
```javascript
const checkbox = document.querySelector(".checkbox");

const button = document.querySelector(".button");

checkbox.addEventListener("click", () => {
  if (checkbox.checked === true) {
    button.disabled = true;
  } else {
    button.disabled = false;
  }
});

```

### 宣言的UI
状態に応じて何を行うかは問わず、「この状態であればこのように表示する」ということをあらかじめ宣言しておく。

```jsx
<button disabled={is_checked ? true : false}>ボタン</button>
```

# 宣言的UIにするメリット
- 状態に応じて求めているUI表示を一緒にしているので、一目で把握できる
- 圧倒的にコード量が減らせる

# Reactでの仮想DOM
<strong>[React公式 「差分検出処理」](https://ja.reactjs.org/docs/reconciliation.html)</strong>

> あるツリーを別のものに変換するための最小限の操作を求めるというアルゴリズム問題については、いくつかの一般的な解決方法が存在しています。しかし、最新のアルゴリズムでもツリーの要素数を n として O(n3) ほどの計算量があります。

単純にツリーの変換を行おうとすると、現実的でない時間がかかってしまう。そこで、Reactは次の仮説を立てた上で、計算量を現実的なものとするアルゴリズムを作成している。このアルゴリズムの要となるのが、仮想DOM。

> 1.異なる型の 2 つの要素は異なるツリーを生成する。
2.開発者は key プロパティを与えることで、異なるレンダー間でどの子要素が変化しない可能性があるのかについてヒントを出すことができる。

Reactは変更を検知した際に、「変更前の仮想DOM」と「変更後の仮想DOM」の差分を実DOMに反映することで、効率的にUIの変更を反映してくれる。
このようにすることで、今までjQueryで命令的に一部の要素を変更していた実装を、宣言的に実装することが可能となる。

ただし、先述した仮説を無視するような実装を行なってしまった場合、パフォーマンスは悪化してしまう。
特に、keyは子要素の変更を効率的に行う大事な属性なので、<strong>各子要素を判別できるような一意の値（例えばidなど）を使うべき。</strong>
```jsx:keyの悪い例
<ul>
  <li key={Math.random()}>BAD</li>
  <li key={2}>OK</li>
  <li key={3}>OK</li>
</ul>
```

# おわりに
これに気づくの遅過ぎた...😇
よく「仮想DOMのメリットは速いこと！」みたいな記事を見かけてたので、それをすっかり鵜呑みにしちゃってた感があります。
パフォーマンスもメリットの一つですが、<strong>それを踏まえた上で公式ドキュメントを読み込んで、情報を精査しないとですね。</strong>（と言いつつ、理解できてるか微妙）

宣言的UIはReactやVueだけじゃなく、最近だとSolidJSなんかもそうですよね。
SolidJS、仮想DOM無しで宣言的にコードを書くことを実現してるので、その辺りもちゃんと調査しておきたいですね。

とはいえ、従来のjQueryを混ぜた命令的でレガシーなフロント事情を、宣言的にコードを書くことを可能にして解決したReactやVueの功績は大きく感じました。

# 参考文献

- [React公式 「仮想DOMと内部処理」](https://ja.reactjs.org/docs/faq-internals.html)
- [React公式 「差分検出処理」](https://ja.reactjs.org/docs/reconciliation.html)
- [なぜ仮想DOMという概念が俺達の魂を震えさせるのか](https://qiita.com/mizchi/items/4d25bc26def1719d52e6)
VSCodeのPR見る拡張機能をGitHub Enterpriseで使う


# 🚀 TL;DR
> 設定にGHEの`URI`と`PersonalAccessToken`を入力すると読み込めるようになる

# 手順

<dl>
  <dt>1. GHEのURIを設定する</dt>
  <dd> 『⌘,』コマンドでSettingsを開く</dd>
  <dd>検索窓に`github-enterprise.uri`を入力</dd>
  <dd>GHEのURIを入力してVSCodeを再起動する</dd>
</dl>

![スクリーンショット 2022-08-21 2.43.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968526/79b6ca34-9788-53c2-e88e-cb886b69cfbf.png)


<dl>
  <dt>2. PersonalAccessTokenを発行する</dt>
  <dd>GHEからTokenを発行*</dd>
</dl>

:::note info
Tokenの発行方法については以下のドキュメントを参照
https://docs.github.com/ja/enterprise-server@3.4/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
:::

![スクリーンショット 2022-08-21 2.44.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968526/f2b24bd0-6c2b-1d0f-03cb-2cc5198187bf.png)




<dl>
  <dt>3. PersonalAccessTokenを設定する</dt>
  <dd>GHEにホスティングされているプロジェクトを開く</dd>
  <dd>tokenの入力をサジェストされるので②で発行したtokenを入力して適用</dd>
</dl>

**GHEのPRが見れるようになってる🎉**



![スクリーンショット 2022-08-21 2.36.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968526/ebb5104b-acea-3811-77ff-fd9868016f41.png)

![スクリーンショット 2022-08-21 2.37.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968526/594a8ef8-ef0b-79cc-2bd1-25a1fb48d9dd.png)

# まとめ
エディタ上でコードレビューできないとしんどいから助かった
[PR出してくれた方](https://github.com/microsoft/vscode/pull/115940)に感謝🙌

https://github.com/microsoft/vscode/pull/115940

# 参考

https://stackoverflow.com/questions/69765741/how-to-connect-my-github-enterprise-account-with-visual-studio-code
【Next.js】Firebaseホスティングでドメイン変更時のリダイレクト設定

最近サイトのドメインを変更しました。
その際、元のサイトから新しいサイトへリダイレクトするように設定したのでその時の備忘録を残しておきます。

## 設定方法
設定はとっても簡単です。

firebase.jsonファイル内のredirectsに、以下のように記述するだけです。

```
{
  "hosting": {
    "site": "hogehoge",
    "public": "out",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "redirects": [
      {
        "source": "/:path*",
        "destination": "https://hogehoge.com/:path",
        "type": 301
      },
      {
        "source": "/",
        "destination": "https://hogehoge.com/",
        "type": 301
      }
    ]
  }
}


```


以上！Firebaseでよかった！！
標準入力をN行ずつカンマ区切りにする

# やりたいこと
入力 (標準入力)
```:stdin
A
B
C
D
E
F
```

出力 (標準出力)
```:stdout
A,B,C
D,E,F
```

# 結論

こちで回答したもの。
https://superuser.com/a/1738053/1722949

```bash
$ cat split.sh
#!/bin/bash -x
<input.txt pr -3tas,
<input.txt paste -d, - - -
<input.txt awk 'ORS=NR%3?",":"\n"'
<input.txt perl -pe'$.%3&&s/\n/,/'
<input.txt split -l3 --filter=paste\ -sd,
<input.txt perl -l0pe '$_.=$.%3?",":"\n"'

$ ./split.sh
+ pr -3tas,
A,B,C
D,E,F
+ paste -d, - - -
A,B,C
D,E,F
+ awk 'ORS=NR%3?",":"\n"'
A,B,C
D,E,F
+ perl '-pe$.%3&&s/\n/,/'
A,B,C
D,E,F
+ split -l3 '--filter=paste -sd,'
A,B,C
D,E,F
+ perl -l0pe '$_.=$.%3?",":"\n"'
A,B,C
D,E,F
```

# 解説
## `<input.txt`
コマンドの標準入力に input.txt を流し込む (リダイレクト)。
リダイレクトはどこにあってもいい。
以下は等価 (サブプロセス起動とかで厳密には違う)
```bash
$ <input.txt command arg1 arg2
$ command <input.txt arg1 arg2
$ command arg1 <input.txt arg2
$ command arg1 arg2 <input.txt
$ cat input.txt | command arg1 arg2
```

## `pr -3tas,`
- `pr`: プリンタ出力用整形コマンド
- `-3`: 3段組みで
- `-t`: ヘッダなしで
- `-a`: 下方向ではなく横方向に (後述)
- `-s,`: カンマ区切りで

`-a` が無い場合、段組みの挙動となる
```bash:
$ seq 9 | pr -3ts,
1,4,7
2,5,8
3,6,9
```

## `paste -d, - - -`
`paste` はファイルを行単位に結合する。
今回はファイルとして標準入力 (`-`) を3回指定している。

```bash:paste
$ paste -d, a.txt b.txt c.txt
a1,b1,c1
a2,b2,c2
a3,b3,c3
a4,b4,c4
```

## `awk 'ORS=NR%3?",":"\n"'`
```bash:awk の基本1 (基本形式)
$ awk '条件式{処理}'  # 条件式 が 真 の場合 {処理} を実行する。
$ awk '{処理}'        # 条件式 が暗黙的に 真 となる。
$ awk '条件式'        # {処理} が暗黙的に {print $0} となる。<- 今回のパターン
```

```bash:awk の基本2 (代入演算子)
### 代入演算子 = は演算結果として代入後の結果を返す。
### 以下の () 内は最終的に a への代入結果の 4 に評価される。
$ awk 'BEGIN{print (a=2+2); print a}'
4
4
### 今回は ORS 変数への代入結果が "," or "\n" なので 条件式 は必ず 真 となる。
```

```bash:awk の基本3 (ORS)
### ORS 変数で print の改行記号が変更可能。
$ awk 'BEGIN{print 1; ORS="@"; print 2; ORS="/"; print 3}'
1
2@3/
```

- まとめ
    - awk の基本形は `awk '条件式{処理}'`
    - `条件式` は `ORS=NR%3?",":"\n"` (=引数全体)
    - `{処理}` は `{print $0}` (暗黙的に指定)
    - `ORS` 変数への代入結果は `","` か `"\n"` なので `条件式` は必ず真
    - `ORS` 変数を3行おきに `"\n"`、それ以外の行は `","` とし、`print` の改行記号を調整している

## `perl -pe'$.%3&&s/\n/,/'`
- `-p`: 行ごとに暗黙的に `print($_)` を実行
    - `$_`: 入力行 (awk の `$0`)
- `-e`: コマンドを指定
- `$.`: 現在の行番号 (awk の `NR`)
- `s/\n/,/`: s 演算子で置換
    - 暗黙的に `$_ =~ s/\n/,/` となり、`$_` が置換される
- `&&` で短絡評価され、`$.%3` が真の場合に限り `s/\n/,/` が実行される

## `split -l3 --filter=paste\ -sd,`
```bash:split
### -l3: 3行ずつに分割
### --filter=command: 分割結果それぞれに対して command を実行
$ seq 6 | split -l3 --filter='cat -n'
     1  1
     2  2
     3  3
     1  4
     2  5
     3  6
```

```bash:paste
### -s なし: 行ごとに結合
$ paste -d, a.txt b.txt c.txt
a1,b1,c1
a2,b2,c2
a3,b3,c3
a4,b4,c4

### -s あり: ファイルごとに結合
$ paste -sd, a.txt b.txt c.txt
a1,a2,a3,a4
b1,b2,b3,b4
c1,c2,c3,c4

### 標準入力を1つのファイルとして読む
$ cat a.txt | paste -sd,
a1,a2,a3,a4
```

## `perl -l0pe '$_.=$.%3?",":"\n"'`
- `-l0`: `print()` の改行を無効化
- `-p`: 行ごとに暗黙的に `print($_)` を実行
    - `$_`: 入力行 (awk の `$0`)
- `-e`: 実行するコマンドを指定
- `.=`: 文字列結合代入演算子 (python3 の `+=`)
- `$.`: 現在の行番号 (awk の `NR`)
【javascript】特定の要素が含まれているか検索する | includes()

# はじめに
ある変数が、複数の値のどれかに存在するかどうかを判定したい時、何も知らず今までずっと以下のように記載していた。
```js
if(testStr == "a" || testStr == "b" || testStr == "c" || ... ){
    ...
}
```
条件が数えられるほどの数ならこれでもよいが、これが10を超えてきたあたりから正直書くのがだるくなってくる。（またはコードが汚くなってくる）
そこで、このような状況下でコンパクトにコードが書ける方法があることを知ったので、メモ。

# 内容
`includes()`メソッドを使用する。
```js:使用例
let okList = ["a", "b", "c", ... ];
if(okList.includes(testStr)){
    ...
}
```

# 詳細
条件として認められる要素を配列にし、それに対して`includes()`で特定の要素が含まれているか検索する。この時、`includes()`に引数として渡すのは**検索対象となる値**であり、**検索対象となる配列**ではないことに注意。
```js
// これは間違い
testStr.includes(okList);
// これが正解
okList.includes(testStr);
```

ちなみに、文字列に対しても有効で、その場合は以下のように記載する。
```js
okString = "abcdefg";
okString.includes(testString);
```
【Golang】文字列と数値の変換(strconv)

Goの勉強中にstring型の型変換で少し詰まったので、調べてわかったことを簡単に紹介します。

## strconv パッケージ
文字列を数値に変換したいときは、strconvパッケージを使用します。この記事では、文字列と数値の変換しか紹介していませんが、bool型との変換なども存在します。また、違ったやり方もあるので、もっと詳しく知りたい方は[公式ドキュメント(strconv)](https://pkg.go.dev/strconv@go1.19)を読んでみてください。

## string <-> intの変換
- strconv.Atoi(s string)： string型 -> int型
引数で指定された文字列を数値(int型)に変換して返します。
また、2番目の返り値としてerror型を返します。

- strconv.Itoa(i int)： int型 -> string型
引数で指定された数値(int型)を文字列に変換して返します。

Atoi関数は、２番目の返り値としてerror型を返しますが、今回はエラー処理を省略するため使用しません。Atoi関数ではint型に変換されるため、数値の加算ができています。一方で、Itoa関数ではstring型に変換されるため、s1とs2が連結されています。

```main.go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	a, _ := strconv.Atoi("7")
	b, _ := strconv.Atoi("-3")
	fmt.Printf("a_type:%T\n", a) // => a_type:int
	fmt.Printf("b_type:%T\n", b) // => b_type:int
	fmt.Println(a + b)           // => 4

	s1 := strconv.Itoa(7)
	s2 := strconv.Itoa(-3)
	fmt.Printf("s1_type:%T\n", s1) // => s1_type:int
	fmt.Printf("s2_type:%T\n", s2) // => s2_type:int
	fmt.Println(s1 + s2)           // => 7-3
}
```
## string -> floatの変換

- strconv.ParseFloat(s string, bitSize int)： string型 -> float型
引数で指定された文字列を数値(float型)に変換して返します。
2番目の引数 bitSize で精度を指定します。float32の場合は32、float64の場合は64と指定します。
2番目の返り値としてerror型を返します。
```main.go
	a_f64, _ := strconv.ParseFloat("3.14", 64)
	b_f64, _ := strconv.ParseFloat("-1.41", 64)
	fmt.Printf("a_f64_type:%T\n", a_f64) // => a_f64_type:float64
	fmt.Printf("b_f64_type:%T\n", b_f64) // => b_f64_type:float64
	fmt.Printf("%.2f\n", a_f64 + b_f64)    // => 1.73
```

# 終わりに
冒頭でもお伝えしましたが、float型 -> string型の変換などここでは紹介していない変換もあるので、詳しくは[公式ドキュメント(strconv)](https://pkg.go.dev/strconv@go1.19)を読んでみてください。
ubuntuのスピーカ出力をzoomの画面共有時の音声入力にする際の備忘録

ubuntuのスピーカ出力をzoomの画面共有時の音声入力にする際の備忘録

### 結局..

結局、zoomの画面共有時に`コンピュータの音声を共有`にチェックを入れてから共有するだけでOKでした。。


## 以下、試してもダメだったもの

注) 私の環境でダメだっただけであり、以下の記事様に問題があるといわけではありません


#### pavucontrolを利用したsound loopback設定を試みるも断念

pulseaudioでloopback設定を試みるも断念。できるはずだが、、

> Ubuntu上のデスクトップ音声出力をZoomの音声入力にする（PulseAudio）
https://blog.aoirint.com/entry/2020/ubuntu_desktop_audio_output_to_zoom_input/

#### sound loopback設定用のアプリ使用を試みるも断念

macでいうところのAnalog Sorround のようなものを使おうとするも断念。

> USBマイク外す
Teamsのスピーカー 内部オーディオ Analog Sorround 7.1
pavucontrol
録音--> Monitor of 内部オーディオ Analog Sorround 7.1
https://aoirint.hatenablog.com/entry/2020/05/19/123527

#### 外部スピーカーを物理的につけたり外したりした

外部スピーカーを物理的に付けてない場合、ダミー出力デバイスしか選択できず`/dev/null`に音声が出力されているのでは？と思いつけたり外したりした。意味ない気がするが、これをした後にLINE入力が見つかり、その後`コンピュータの音声を共有`が有効になったような気もする。。がよく分からない。。
ひとまず今後の自分の備忘録として残しておく。。雑な記事ですみませんm(_ _)m
for文の中でリストの要素を削除するのは危険

新人エンジニアが書いたコードでバグが発生していました。

下記のようなプログラムでした。
リストから「2」がすべて消えることを期待していました。「2」は5個あります。

```python
test_list = [1, 2, 1, 3, 4, 2, 1, 3, 3, 2, 2, 2, 3, 1]
print('要素数:' + str(len(test_list)))
for ele in test_list:
    if ele == 2:
        test_list.remove(ele)

print('要素数:' + str(len(test_list)))
print(test_list)
```

しかし実行結果↓
```
要素数:14
要素数:10
[1, 1, 3, 4, 1, 3, 3, 2, 3, 1]
```

test_list.remove(ele)を実行するとi番目の要素が削除されるので、i+1番目以降の要素は1つずつ前にずれます。removeによって要素数＝for文の回数に影響が与えられ、上記の場合、10回しか回っていません。

「2」（＝削除対象値）がひとつだけの場合や、「2」が複数個あっても連続していなければ全ての「2」がremoveされます。しかし、データ内容に依存するようなプログラムはバグの温床になり、適切とは言えません。

別途リストを初期化し、削除対象外の要素をそちらにappendしていく対応が良いでしょう。

【補足】
Javaのリストで拡張forで同じことをやってみたら、java.util.ConcurrentModificationExceptionになりました。それについての詳細は[こちら](https://nuxtblog.work/blog/rjga-emxt0/)を参照。
Linuxで区切り文字付きテキストファイルの空入力有無チェック 

## 概要
Linuxにて区切り文字で区切ったファイルにて、
全行全項目が漏れなく文字が入っているか確認したかったんですが、ありそうで見つからなかったので作成しました。
なお、制限として/bin/shを条件として作成しています。bashなどであれば、別の方法もあるでしょう。

※本稿ではあくまで文字列や値が入っているかの確認のみで入力された文字列内容などの判定はありません

## 例(区切り文字がカンマかつ1行1つの区切り文字の場合)
ファイルの例(1行1つの区切り文字)
```
AAA,BBB
CCC,DDD
EEE,FFF
```

```.sh
FILE=<ファイル名>

 # ファイル内の区切り文字全数 # Total number of delimiters in file
CNT1=$(grep -oR "\," $FILE |wc -l)
 # 区切り文字を改行に変換した行全数。それを1/2。 # The total number of lines with delimiters converted to newlines. 1/2 it.
CNT2=$(expr $(cat $FILE |tr '\,' '\n' | grep . |wc -l) / 2)
 # 行全数 #all lines
CNT3=$(grep . $FILE |wc -l)

# 
if [ $CNT1 -ne $CNT2 ] || [ $CNT1 -ne $CNT3 ] ; then
 echo "The comma in the File is incorrect."
fi
```

基本上記3つのカウントは同数となります。(同数にならなければエラーメッセージということで)

## 説明1(CNT1)

```
 # ファイル内の区切り文字全数 # Total number of delimiters in file
CNT1=$(grep -oR "\," $FILE |wc -l)
```
以下のように余計な区切り文字がある場合の判定に利用しています。(連続していたり末尾にあったり)
1行に1区切り文字の前提なので、全行数=ファイル内の全区切り文字です。
以下の場合だとCNT1の数だけ多くなって、CNT2,CNT3と一致せずエラーです。
```
AAA,BBB,
CCC,,DDD
EEE,FFF
```

## 説明2(CNT2)

```
 # 区切り文字を改行に変換した行全数。それを1/2。 # The total number of lines with delimiters converted to newlines. 1/2 it.
CNT2=$(expr $(cat $FILE) |tr '\,' '\n' | grep . |wc -l) / 2)
```
以下のように区切り文字で区切ったのに未入力だった場合の判定です。

```
AAA,
CCC,DDD
,FFF
```
↓ 区切り文字を改行に変換後
```
AAA

CCC
DDD

FFF
```
「grep . |wc -l」で空白行は除外した行数がカウントされるので、4行。そこから1/2すると2となり、全行数と一致せずエラーとなります。
5 /2 でも expr は切り捨てで2になるので、問題なし。




## おまけ　例(区切り文字がカンマかつ1行2つの区切り文字の場合)
```
AAA,BBB,CCC
DDD,EEE,FFF
GGG,HHH,III
```

```.sh
FILE=<ファイル名>

 # ファイル内の区切り文字全数。それを1/2。 # Total number of delimiters in file.  1/2 it.
CNT1=$(expr $(grep -oR "\," $FILE |wc -l) / 2)
 # 区切り文字を改行に変換した行全数。それを1/3。 # The total number of lines with delimiters converted to newlines. 1/3 it.
CNT2=$(expr $(cat $FILE |tr '\,' '\n' | grep . |wc -l) / 3)
 # 行全数 #all lines
CNT3=$(grep . $FILE |wc -l)

# 
if [ $CNT1 -ne $CNT2 ] || [ $CNT1 -ne $CNT3 ] ; then
 echo "The comma in the File is incorrect."
fi
```
    

## 注意事項
ファイルの改行コードがLFの場合は問題なく動作しますが、WindowsやMacからアップロードしたファイルを利用する際は改行コードがCRLFやCRとなり、想定動作とならないので、お気を付けを。
CRが"grep ."で空白行と見なされないのが原因で1行と認識されることに起因されるので、実行前にLFに置換する処理を入れれば問題ありません。
用語メモ

IT用語メモ（自分用）

| 1 | 2 | 3 | 4 | 5 |
|:-:|:-:|:-:|:-:|:-:|
|インタプリタ   |interpreter   |通訳者。<br>プログラムをパソコンが解釈できるようにする為のソフト。   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
ブレンダーで任意の大きさの立方体を作りアンリアルエンジン5にインポートする

## 経緯
以下の要求から、最近アンリアルエンジンとブレンダーを触り始めた。
* マンガの背景の作画資料をCGで作りたい
* 出来合いのアセットを使って楽に建築物なんかを作りたい
* ちょっとした3D素材なら自作したい

しかし、CGの世界には現実世界のような絶対的な長さの単位がないので、ヴァーチャルな世界の大きさ感覚がつかめなくて混乱する。
アンリアルエンジンにインポートした素材のプロパティに「Approx size（おおよその大きさ）」という項目があり、ドアだとかの大きさを見たところどうもこの数字が現実世界でのセンチメートルと対応しているらしい。
  * 100x100x100だったら100cmの立方体

そこで、身近な物体で建築物の大きさの理解の基準となる畳の大きさ（90cm×180cm）の板をブレンダーで自分で作り、それをアンリアルエンジンにインポートしたいと考えた。これができれば6畳とか8畳とかの床をコピペで作ることができ、アンリアルエンジンの世界での建物の大きさの基準を得ることができるはず。

## 目的
* ブレンダーで任意の大きさ、例えば畳約一畳分といえる90cm×180cm×10cmの大きさの立方体をブレンダーで作りたい

## 問題
* イラストレーターのように、キューブを選択して「大きさ」のプロパティの欄に縦横高さの希望の数字を入力するとその大きさになってくれる、ということがない
* 縦横高さのプロパティは元のポリゴンをどれくらいの比率で変形させるかというスケールの数字のみであるらしく、絶対的な大きさを示すプロパティがない

## 方法論
* ブレンダーのグリッドの大きさを設定し、メートル単位と対応するようにする
* オブジェクトをグリッドに吸着させ、グリッドで数えて任意の大きさの物体を作る
* アンリアルエンジンに書き出してインポート

### ブレンダーのグリッドの設定
* ブレンダーの設定にグリッド表示があり、このグリッドの大きさが現実世界のどれくらいの大きさと対応するのかという設定ができる
* これをメートル法のグリッドにしておく
  * シーン設定＞単位（Units）からやるらしい

![スクリーンショット 2022-08-21 002231.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/fe7bbb25-1ad1-6e55-c273-7f3f5a83559b.png)

* ブレンダーで新規ファイルを作成する
  * 立方体がディフォルトで配置されてるはず
  * これをそのままfbxファイルにエクスポートする
  * Geometory > Smoothing 設定を「Face」 にしておく
* 書き出したfbxファイルをアンリアルエンジンにインポートする
* アンリアルエンジンでインポートしたアセットのプロパティ ＞ Approx size を確認する
  * およそ 200x200x200になっていた
    ![スクリーンショット 2022-08-21 002255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/73a99991-a7b8-58dc-c0ca-c36d0e4de376.png)
  * ブレンダーでのグリッド数を数えると1辺あたり20マス
    ![スクリーンショット 2022-08-21 002127.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/5b158885-e9be-0704-a042-33b595036eb7.png)

↓
* ブレンダーの1グリッド＝アンリアルエンジンでのApprox size 10 ＝現実世界での10センチメートルだと言える

### ブレンダーで立方体を編集しやすいようにする
* モードをエディットモードにして、立方体の頂点を編集できるようにする
* さらに選択対象が「頂点」「エッジ」「面」とみっつの規模から設定できる。面選択のモードにする
  ![スクリーンショット 2022-08-21 002350.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/86e0fd68-5659-7ac1-8339-6216309e978b.png)
* 面を選択し、表示をXYZのまっすぐ視点からのものにし、矢印で伸ばしたり縮ませたりする
  ![スクリーンショット 2022-08-21 003310.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/eef2e215-3c70-40d6-730e-a655b2898e02.png)

### グリッド吸着モードにする
* U字磁石のアイコンをクリックするとスナップのON/OFFを切り替えられる。ONにする
* さらに、吸着の詳細設定ができ、「Absolute Grid Snap」をオンにする
  ![スクリーンショット 2022-08-21 002411.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/b0209aec-c1c7-a867-12bf-581153f5297b.png)
* キューブの大きさ編集で伸び縮みさせるとき、グリッドに吸着するようになる

## アンリアルエンジンでの利用例
* 1畳の立方体をアンリアルエンジンにインポートし、6畳の床を作ったところ
  ![スクリーンショット 2022-08-21 002058.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/52fa4815-2a8a-b11e-e052-5c694fed964a.png)
* アセットのプロパティ
  ![スクリーンショット 2022-08-21 003429.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159641/2bb7e410-7779-6464-65af-27da101eca60.png)



## バージョンメモ
* Blender 2.93.4
* UnrealEngine 5.0.3
Python I/Oの再考(2): ioモジュールの高レベルインターフェース

##### [前回] [Python I/Oの再考(1): ストリームの種類と比較検証](https://qiita.com/mingchun_zhao/items/130c802ce564822b45ce)

## はじめに

前回は、Python I/Oの基本をおさらいしました。
今回は、`io`モジュールの高レベルインターフェースです。

## `io`モジュールが提供する高レベルインターフェース

バッファと文字コードに関係するインターフェースを取り上げます。

### そもそもI/Oになぜバッファ(メモリ領域)が必要か

- Rawストリーム(バッファリングなし)
    - ストリームの読み書きで、1バイトずつ処理するため性能が落ちる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/7804c57c-c762-939f-b244-20f58d93daed.png)

- バイナリストリーム(バッファリングあり)
    - バッファにデータをためて、一度に処理
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/b422bfb7-fa34-5293-1b4f-65c34a2d5a2b.png)


### `io.DEFAULT_BUFFER_SIZE`インターフェース

※ 参照: https://docs.python.org/ja/3/library/io.html#io.DEFAULT_BUFFER_SIZE

- バッファリング付きI/Oクラスで利用されるバッファの、デフォルトサイズを表す

- `open()`時のバッファサイズには、ファイルの`blksize`値が使用される(os.stat()で取得可)
    - AlmaLinuxで取得した結果、`4KB`

```python
>>> import os
>>> os.stat("ファイル名").st_blksize
4096
```

### テキストストリームの操作で、文字コード(encoding)指定を忘れず

- テキストストリームのデフォルト文字コード
    - OSのロケールに依存
        - Windowsで取得してみると、`cp932`
        ```python
        >>> import locale
        >>> locale.getpreferredencoding(False)
        'cp932'
        ```
        - AlmaLinuxで取得してみると、`UTF-8`
        ```python
        >>> import locale
        >>> locale.getpreferredencoding(False)
        'UTF-8'
        ```

- テキストファイルを開くときは、文字コードを明示的に指定する必要あり
    - 理由は、Windowsはロケールの文字コードがUTF-8でないため
        - UTF-8でエンコードされたテキストファイルが文字化けする
    - 文字コードの指定方法
        - UTF-8を使用する場合、`encoding="utf-8"`を渡す

- Python 3.10以降で、現在ロケールの文字コードを使用する方法
    - `encoding="locale"`を渡す

### `io.text_encoding(encoding, stacklevel=2, /)`

※ 参照: https://docs.python.org/ja/3/library/io.html#io.text_encoding

- Python 3.10以降で使用可能な、文字コード指定をチェックしてくれるヘルパー関数
    - `open()`または`TextIOWrapper`で、`encoding=None`パラメーターを指定する場面で使用

- 関数の戻り値
    - `encoding`が`None`でない場合
        - `encoding`を返す
    - `encoding`が`None`の場合
        - `locale`を返す

- デフォルト文字コードが使用される場合、`EncodingWarning`を発行するように設定可能
    - `EncodingWarning`の発行条件
        - `sys.flags.warn_default_encoding`が`true`で、`encoding`が`None`の場合
    - `stacklevel`は、警告が発行される場所を指定
        - 下記例では、`read_text()`の呼び出し元に対し、`EncodingWarning`が発行される

```python
def read_text(path, encoding=None):
    encoding = io.text_encoding(encoding)  # stacklevel=2
    with open(path, encoding) as f:
        return f.read()
```

## おわりに

`io`モジュールの高レベルインターフェースを理解しました。
次回をお楽しみに。


##### [次回] [Python I/Oの再考(3): I/Oストリームのクラス階層](https://qiita.com/mingchun_zhao/items/9d68b18a0ea2041251da)