OmniAICreator/Qiita-1.07M huggingface dataset:
p5.js で正方形のキャンバスを縦長・横長の短辺ピッタリの長さにする（＋画面中央に表示させる）

## はじめに
この記事で扱う内容は表題のとおりです。p5.js を使った JavaScript の描画で正方形のキャンバスを表示する時に、そのキャンバスの長さを、縦長・横長の画面の短い方の辺の長さぴったりにする、という話です。

図で表すと、こんな感じになるかと思います。
![説明用の図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/85bacfef-051b-4416-e354-1ccb66cd07a6.png)

これをやってみたきっかけは、p5.js のコミュニティの Discord（[Processing Community Japan](https://processing.jp/) の Discord）で、「上記の内容を実現する実装方法は？」という質問があったことです。

### 質問された方のポスト（質問に回答した後の話）
上記の質問に、今回の記事に書いた内容を回答したところ、無事に質問者の方の思い通りの動作になったようで良かったです。

https://twitter.com/fumi_koba_twi/status/1697461024314806562

## 今回の内容
### あらためて今回の概要
質問で「やりたいこと」として話に出ていたのは、冒頭の図で示した内容でした。
さらに、キャンバスのサイズ調整のみ実装すると、正方形のキャンバスの表示位置が「縦長の画面の場合は上端」に、「横長の場合は左端」になってしまうため、その位置が中央になるように調整する、という内容も加えています。

その表示が行われている様子を実機でシンプルに示すと、こんな感じです。
![375765063_1354009411882006_7988783205860461908_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/c30743c4-61fb-e724-12a9-cd93d241622a.jpeg)

画面中の青い部分が「p5.js のキャンバス」で、緑の部分は「キャンバスが表示されている背景 ＝ スマホの画面の表示領域全体」にあたる部分です（※ HTML のスタイルに background を設定して、キャンバスの背景に当たる部分を緑に着色しています）。緑色の部分（画面全体）に対して青い部分（p5.js のキャンバス）が画面短辺ピッタリの長さになっており、なおかつ表示位置が中央になっているのが分かります。

これを実現する方法について、この後に説明していきます。

### 実装する内容
今回、実装する内容は、おおまかに以下となります。

1. キャンバス生成前に画面の短辺の長さを取得する
1. キャンバスの縦横の長さを上記1で求めた短辺の長さに設定
1. 正方形のキャンバスが画面中央にくるようにキャンバスの位置を調整
1. （やりたいことによっては必須ではないですが）キャンバスがリサイズされた際の対応

これらについて、この後に具体的なコードと簡単な補足を書いていきます。

### 実装した内容
それでは、実装内容とその補足を順に書いていきます。

#### JavaScript で実装した内容（p5.js の sketch.js にあたる部分）
必要最低限となる部分は、以下の通りです。

```javascript
let canvas;

function setup() {
  const canvasSize = min(windowWidth, windowHeight);
  canvas = createCanvas(canvasSize, canvasSize);
  centerCanvas(canvas);
}

function draw() {
  background(100, 150, 200);
}

function windowResized() {
  const canvasSize = min(windowWidth, windowHeight);
  resizeCanvas(canvasSize, canvasSize);
  centerCanvas(canvas);
}

function centerCanvas(cnv) {
  const x = (windowWidth - width) / 2;
  const y = (windowHeight - height) / 2;
  cnv.position(x, y);
}
```

上で、4つの実装のポイントを書いていましたが、対応関係は以下のとおりです。

1. キャンバス生成前に画面の短辺の長さを取得する
   - `min(windowWidth, windowHeight)` で画面の短いほうの長さを取得（canvasSize という変数に長さを格納）
1. キャンバスの縦横の長さを上記1で求めた短辺の長さに設定
   - `createCanvas(canvasSize, canvasSize)` としてキャンバスを生成
1. 正方形のキャンバスが画面中央にくるようにキャンバスの位置を調整
   - （後述）
1. （やりたいことによっては必須ではないですが）キャンバスがリサイズされた際の対応
   - 画面の短辺の長さを再取得して `resizeCanvas(canvasSize, canvasSize)` でキャンバスをリサイズし、キャンバスの表示位置の調整を行う

上で「（後述）」と書いた部分に関し、さらに補足を書きます。

この処理に該当するのは以下の部分です。
やっていることは、「画面の幅（または画面の高さ）とキャンバスの幅（またはキャンバスの高さ）の差の半分の長さ」を取得し、その長さの分だけキャンバスの表示位置をずらす、というものです。

```javascript
function centerCanvas(cnv) {
  const x = (windowWidth - width) / 2;
  const y = (windowHeight - height) / 2;
  cnv.position(x, y);
}
```

この処理を適用すると、画面の短辺方向のキャンバスの表示位置は変わらないですが、画面の長辺方向のキャンバスの表示位置は、画面の長辺方向にできる余白の半分の長さだけずれます。
つまり長辺方向で、キャンバスの左右の両側に、等しい長さの余白ができることになり、それでキャンバスの表示位置が画面中央になります。

## おわりに
今回の内容は、上で書いていた質問をきかっけに実装してみたものでした。
それについて、自分が今後スマホ画面での p5.js の描画を扱う際などに、必要になるかもしれないという感じがしたものでもあったため、今回の内容を試せて良かったです。
java.util.concurrent.CountDownLatchを使って別処理を待つ

## やりたいこと
「別スレッドの処理が終わるまで、メインスレッドの処理を待機する」的な処理を実装します。
### ちなみに
昔はAsyncTaskクラスがよく使われたらしいけど、APIレベル30で非推奨になったっぽい。公式ドキュメントは「java.util.concurrentを使ってね」って言ってるので素直にそっちを使いましょう。
## 使用例
AndroidでサーバーからJSONを取得する際など。AndroidではHTTPS通信をメインスレッドでは行なえないので、新しいスレッドを立てる必要があります。
1. Stringを定義する
2. https通信してInputStreamを取得
3. 別メソッドで文字列に整形
4. 整形した文字列を定義したStringに格納
5. Stringを返す。

みたいな処理を実装してみましょう。
` parseInputStreamToString`は別のところで自作したメソッドです。InputStreamを渡すと文字列に整形してくれます。
``` 
public String getJsonFromServer(String urlString){
        CountDownLatch latch = new CountDownLatch(1)
        String[] jsonString= new String[1];
        //ここで新しいスレッドを立ち上げる
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpsURLConnection connection = null;
                try {
                    URL url = new URL(urlString);
                    connection = (HttpsURLConnection) url.openConnection();
                    jsonString[0] = parseInputStreamToString(connection.getInputStream());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    connection.disconnect();
                    latch.countDown();
                }
            }
        }).start();
        latch.await();
        return jsonString[0];
    }
```
「別スレッドの処理が終わるまで、メインスレッドの処理を待機する」のような処理をしないと、通信が終わっていないのにreturn文までたどり着き、nullを返してしまうことがあります。
### 解説
CountDownLatchの`await()`メソッドは、引数で与えられた数が0になるまでスレッドの処理を中断してくれます。`countDown()`が呼び出されるたびに与えられた数が1ずつ減っていくので、for文と組み合わせると「配列内の要素すべての処理が終わるまで待つ」みたいな処理も実装することができます。
## 参考
https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/CountDownLatch.html

https://dev.classmethod.jp/articles/asyncronous-for-android/
ソーラ・システムを作る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/071e62bf-9a1c-9d58-874f-f7fab37860a9.png)

まじめな内容だとおもってこの記事を見てしまった方、ごめんなさい。
ネタ記事です。

ソーラ・システムとは、ガンダムに出てくる兵器です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/75cc22b9-2c7d-dc9d-e7bf-80257fdce16b.png)

宇宙空間にミラーをたくさん並べ、焦点を合わせることで敵を焼き尽くします。
今回はこれをUnityで作っていこうと思います。

原理はとても簡単で、```太陽からの入射角＝敵方向への反射角```になるように鏡を設置するだけです。

```SOL_Panel.cs
            Vector3 p2t = (targetGo.transform.position - transform.position).normalized;
            Vector3 p2s = (sunGo.transform.position - transform.position).normalized;
            Quaternion rot = Quaternion.LookRotation((p2t + p2s)*0.5f);
```

これをパネルの形のオブジェクトに貼り付けたものをPrefab化し、
縦横に並べます。
※太陽はDirectionalLightなので、遠くに置く必要があります。

焼かれる対象物からソーラ・システムをみると、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/fa660693-7d1a-13a0-6171-f25a6c6e5688.png)

焼かれるー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/9171a4ed-f868-29c5-3604-232e0dc0293d.png)

逃げても、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/3a9cc8d9-7451-354b-8452-7baceaf8f7a8.png)

焼かれるー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/4a5f3380-3f9d-92cb-b716-693f3f126617.png)

https://youtu.be/xkzLpgbeAu0

https://github.com/misawa2048/Unity_solarSystem

以上です。
Dockerのコンテナ同士をネットワーク接続できるようにする（extra-hosts & host-gateway）

# はじめに
コンテナ同士で通信するときに、docker composeで １つのymlでコンテナ構築したり、あとからdocker networkで設定入れる必要があると思っていたのですが、コンテナ構築時にextra-hosts で簡単に追加設定できることを知りました。。。
もうちょっと早くに知りたかったという自戒も込めてメモ残しです。。。

# 確認環境
- windows10 pro 
- wsl2(20.04.5 LTS (Focal Fossa))
- Dockerのバージョン
    - Docker version 20.10.18, build b40c2f6
    - docker-compose version 1.29.2, build 5becea4c
※Docker Desktop ではありません

# 構成イメージ図
![extrahost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541739/8594d6ca-f074-6ff5-9391-babf50524335.png)



# 設定方法例
```yml:コンテナA
services:
  app:
    image: tempimage1
    # ↓ リクエストする側に以下の設定を入れる
    extra_hosts:
      - host.docker.internal:host-gateway 
```
```yml:コンテナB
services:
  app:
    image: tempimage2
    # 受信ポート指定
    ports:
      - 50001:50000
```

# 設定概要
- `host.docker.internal`については、ホスト名で使える文字列なら何でもよいが、公式のドキュメントでこの名前がつかわれているので、特に変更する必要はないかと
- 上記の設定を共通で入れていると、コンテナ内部で (上記の場合であれば、`host.docker.internal:50001`)で通信できる
- 外部と内部で違う場合は、外部から接続できるポート番号を指定する
- 上記からわかることではあるが、`ports`等で外部から接続できる設定についてはやり取り可能ではあるが、`expose` 設定のようにDocker内部のみの接続設定のみを可能にしている場合は、この設定で通信することはできない（この場合はnetworkグループの設定が必要）
- ちゃんと設定が入っているかを確認するときは、コンテナ内で `cat /ect/hosts` を実行し、ファイルに設定が追加されていれば問題ない
    ```
    $ cat /etc/hosts
    
    127.0.0.1       localhost
    <省略...>
    172.17.0.1      host.docker.internal
    172.30.0.2      f5e65b3fb6ae
    ```

# 余談
socket通信でbindするときのIP設定で、`0.0.0.0` を使っていたが、 環境変数の hostname を使用すると内部のIPで名称解決できる(上記の`f5e65b3fb6ae`が設定されている)ので、このあたりもうまく使っていきたい

# さいごに
知らなくても何とかなっていたが、効率的に管理できる仕組みは積極的に取り入れないと…と思っている次第です。。
Clocを導入する


コードステップ解析ツールClocのDockerイメージを用いて解析を実施する方法を調べたので備忘録を残しておきます
下記手順はDocker環境が作られていることが前提です

### clocの準備

### clocのDockerイメージをpullする
``` ex.bat
sudo docker pull aldanial/cloc
```

#### ローカルにpullされたclocのDockerイメージを確認
``` ex.bat
sudo docker images
```

### clocで解析を実施する
事前にgit　Cloen等で資産を配置しておく

``` ex.bat
docker run --rm -v 「ファイルが配置されているディレクトリ」:/code aldanial/cloc /code
```
※上記は「run」で実施しているためイメージ作成＋起動まで実施している

設定例
```bash
docker run --rm -v /path/to/your/code:/code aldanial/cloc /code
```
説明
1. `docker run`: Dockerコンテナを実行します。
2. `--rm`: コンテナが終了したら削除します（一時的なコンテナを使用します）。
3. `-v /path/to/your/code:/code`: ローカルのコードが存在するディレクトリ（`/path/to/your/code`）をコンテナ内の`/code`にマウントします。
4. `aldanial/cloc`: CLOCを実行するDockerイメージを指定します。
5. `/code`: マウントしたディレクトリ内のコードを対象としてCLOCを実行します。


## 【参考】

#### ホストマシンのファイルをコンテナ内でも使う（-vオプション）
```
docker run -v #{ホストマシンの任意のディレクトリ}:#{Dockerコンテナ内の任意のディレクトリ} -it IMAGE /bin/bash
```

### Dockerをイメージからコンテナを作成し起動する
Dockerをイメージから起動を確認したい場合（上記で動かないとかで原因を探る場合とかで使用）
```
sudo docker run -itd aldanial/cloc
```
※確認対象が指定されてないため、すぐに終了となる

#### 作成されたコンテナを確認する
```
sudo docker ps -a
```
※「-a」オプションで停止中のこんてなも含め確認する


※ Mint環境だとGitがはいっていない、インストールもうまくいかない




参考
https://github.com/AlDanial/cloc


https://hangstuck.com/bash-cloc/

Git install
https://qiita.com/manjiroukeigo/items/467959b4a1b28c70d21f
Pythonが嫌いなのでC++版のPytorchで画像認識をやってみる 17日目 OpenCVの謎 

# よく分からない挙動
OpenCVで作ったソフトで社内のネットワークカメラに繋いでみると、ちょっと理解しにくい挙動がみられた。一部のネットワークカメラが有線LANのときだけ受信できない。カメラの設定か、ネットワークの設定か、ファイアウォールの設定か、怪しい所を調べたが変な所はない。
試してみると、ffplayやffmpegでも同じ挙動がみられる。どうもOpenCVそのものが臭い。

# デバッガで挙動を見る
デバッグバージョンのOpenCVのバイナリがあったので、簡単なコードを書いてOpenCVのそのものの動作を見てみることにした。

```C++:check_opencv.cpp
#include <iostream>
#include <opencv2\opencv.hpp>
int main()
{
    int ret;
    cv::Mat frame;
    cv::VideoCapture capture;
    capture.open("http://hogehoge/cgi-bin/mjpeg");
    while (true) {
        capture >> frame;
        if (frame.empty()) {
            break;
        }
        cv::imshow("Capture", frame);
        ret = cv::waitKey(1);
        if (ret == 'q') {
            break;
        }
    }
}

```
↑これを、capture.open()のところから、ひたすらステップインで実行していく。capture.open()がコケている所を見つけようと思ったのだが、コンストラクタとオーバーロード関数とテンプレートの嵐で、何がどうなっているのかさっぱり分からない。が、何度も動作させているうちに、capture.open()の動作が上手くいく時と行かない時で動作が切り変わる少し手前で気になる所を一つ見つけた。
拡張子の無いvectorというファイルの中の↓このコード。

```C++:vectorの一部
_Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal()));
```

PROXY? ビルドやPythonでpipするときにProxyの設定が必要なのは知っているけど、OpenCV自体がProxyの設定を見に行くというのは意外だった。でいろいろ調べると、OpenCVの公式でProxyに言及しているところは見つからなかったが、stackoverflow↓に環境変数のHTTP_PROXYの値を見に行くというコメントが有った。
https://stackoverflow.com/questions/56325448/how-to-capture-a-video-behind-proxy-with-opencv
確かにこの環境変数にProxyのurlを入れてある。半信半疑でHTTP_PROXYの設定を消してみる。(_を付けて無効にする)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464633/85cfc0db-16c4-7435-2f7d-e8ec94f28962.png)

**映像が受信できた!!**
HTTP_PROXYはffmpegやPythonのツールが使うようだが、OpenCVそのものも参照するらしい。とっかかりが見つかったので、いろいろ試すと次の法則があるらしい。

**OpenCVのcapture.open()は、指定アドレスが「グローバルIPアドレスぽい」だと環境変数HTTP_PROXYに指定してあるProxyサーバーを見に行く。**

「グローバルIPアドレスぽい」というのは、ローカルでないIPアドレスのことだ。10.*.*.*とか192.168.*.*のようなアドレスはローカルIPである。そうではないアドレスはグローバルIPであると推測できるのでProxyを見に行くということだ。ウチの会社は、32bitのネットマスクを割り当てられていて、社内のかなりのセグメントがグローバルIPになっている(なんと贅沢な)。なのでグローバルIPを割り当てられたネットワークカメラは、Proxyの外側と判定され、接続できなかったということらしい。
じゃあなんでWIFIで繋いだ時は問題なかったのか、という謎は残るのだが、これは社内のProxyの自動設定に問題があるらしい。こちらはまだ謎のまま。

# まとめ
* OpenCVのcapture.open()は、指定アドレスが「グローバルIPアドレスぽい」だと環境変数HTTP_PROXYに指定してあるProxyサーバーを見に行く。
* 挙動が怪しいときはプロキシの設定と、環境変数HTTP_PROXYをチェックする。
【React】JSXで条件分岐を記述する方法

ReactのJSX(TSX)の中で条件分岐を使うと、propsやstateの値に応じてレンダリング内容を変更できるようになります。
JSX内で条件分岐を行う際の注意点や方法について、備忘録として残しておこうと思います。
間違った点があればご指摘いただけますと幸いです。

## JSX内にif文やswitch文を書くとエラーになる
条件分岐といえば、**if文**や**switch文**等の命令文を記述したくなるが、JSX内は出力する値を記述する場所なので、値を返さないif文やswitch文等の命令文を記述するとエラーになってしまう。
使用したい場合は、後述で紹介するように即時関数や外部で定義した関数の中に処理を記述することで実行できる。

## JSX内に複雑な処理はなるべく書かない
JSXは本来HTMLライクで画面に出力したい内容を記述する場所。
この中に条件分岐を含む複雑で長い処理を書き込んでしまうと、コードを見返した時にレンダリング内容が分かりにくくなってしまう。
短い処理であればJSXに直接書いても良いが、長い処理はなるべく外部で定義した関数内で処理を行うようにして、JSXからその関数を呼び出すのが良いと思う。

## 短い処理の場合
短い条件分岐の処理であれば、演算子を用いるとシンプルに記述することができる。

#### 三項演算子「? :」
　**「条件 ? true時の処理 : false時の処理」**
if...else文のような条件分岐を書くことができる。
```jsx
    let isCorrect = true;
    return(
        <div>
            { isCorrect ? '正解です。' : '不正解です。' }
        </div>
    )
```

#### 論理積演算子「&&」
　**「条件 && true時の処理」**
指定した条件がtrueの時だけ出力してfalseの時は出力しない。
```jsx
    let isApple = true;
    return(
        <div>
            { isApple && 'リンゴです。' }
        </div>
    )
```

### Null合体演算子「??」
　**「A ?? B」**
　Aがnullかundefined以外の場合はAを出力し、AがnullかundefinedのときBを出力する。
　正常な値を受け取れない可能性があることを想定した処理で使用される。
　if文を使うと「if(A == null || A == undefined)...else...」となるため、Null合体演算子を使うとより短く記述できる。
```jsx
    let fruits = 'リンゴです。';
    return(
        <div>
            { fruits ?? '値がnullもしくはundefinedです。' }
        </div>
    )
```

## 長い処理の場合
if文やswitch文等を用いて更に複雑な条件分岐を行いたい場合、**関数内に処理を定義して条件分岐を行う**。
主に、関数は即時関数を用いてJSX内に直接記述する方法と外部に定義してJSX内から呼び出す方法の２通りがある。

### 即時関数を使う
即時関数を用いるとJSX内に直接記述することができる。
記述したロジックと反映される場所が近いので分かりやすいと思う。
ただし、即時関数はカッコの数が多く、最後にセミコロンを付けるとエラーになるため記述ミスも起きやすい。
また、処理が長くて複雑になるほどJSX内のコードが全体的に膨らんで読みにくくなる。
直感的には分かりやすいが、多用しすぎるのは良くないと思う。

```jsx
    return(
        <div>
            {(() => {
                if(fruits === 'apple'){
                    return 'リンゴです';
                }else{
                    return 'バナナです';
                }
            })()}
        </div>
    )
```
### 外部の関数を呼び出す
条件分岐の処理をJSXの外部で関数として定義して、JSX内から呼び出すこともできる。
即時関数を使用する方法と比較すると、JSX内のレンダリング位置と実際の処理を行う関数の位置が離れてしまうので人によっては少し読みにくいと感じるかもしれない。
しかし、JSX内がスッキリしてシンプルになり記述ミスも起きにくくなり、処理も関数ごとにまとめられるので管理しやすいと思う。

```jsx
    let fruits = 'apple';
    // JSX外部で関数を定義
    const isApple = () => {
        if(fruits === 'apple'){
            return 'リンゴです';
        }else{
            return 'バナナです';
        }
    }
        return(
        // JSX内
            <div>{ isApple() }</div>
    )

```

## まとめ
・JSXの中に値を出力しないif文やswitch文などの命令文を書くとエラーになる。
・JSXの中に長くて複雑な条件分岐処理を書きすぎないようにする。
・短い処理の場合、演算子を用いてJSX内に直接記述する。
・長くて複雑な処理の場合、外部の関数内で条件分岐を行いJSX内で呼び出す。

---
参考サイト
　- [条件付きレンダー](https://ja.legacy.reactjs.org/docs/conditional-rendering.html)
　- [【React】JSXでif文を利用して要素を出し分ける（条件付きレンダー）方法](https://nishinatoshiharu.com/conditional-rendering/)
Notion プロジェクト管理　ステータスをリリースver別にしたビューを追加すると便利

https://note.com/dinii/n/n719577c996e8

diniiさんの記事を見つけました。

非エンジニアの方にとってはとても便利だなと思いました。
どのバージョンで何の機能追加、バク修正をしたかがすぐに分かります。
エンジニアにとっても良いなと思いました。
参考になりました。ありがとうございました。

# 宣伝させてください！
https://recruit.iimon.co.jp/
【SwiftUI】 SwiftUIView(init: UIView(init: SwiftUIView))

# はじめに
タイトルのように、皆んさんこんな画面を作るような時がありますか？
例えば下記のような場面。

- **TextFieldをタップして、キーボードではなく、SwiftUIで書いたカスタムのPickerを出したい**

SwiftUIにはUIKitにある[inputView](https://developer.apple.com/documentation/uikit/uiresponder/1621092-inputview)のような仕組みがないようです。

ここでタイトルのような作りを考えました。

# アプローチ

1. SwiftUIでカスタムのPicker(CustomPicker_SwiftUI)を作成
1. UITextFieldを継承したクラス(CustomTextField_UIKit)を作成
1. UIHostingControllerでCustomPickerをラップする(`let wrapperView = UIHostingController(rootView: CustomPicker_SwiftUI)`)
1. CustomTextFieldのinputViewにwrapperView.viewを設定する
1. UIViewRepresentableでCustomTextFieldをラップして、SwiftUIで呼び出す

# 実際のコード
```swift
import SwiftUI
import UIKit

// Step1
struct CustomViewPicker: View {
    var tapHandler: (String) -> Void
    
    var body: some View {
        Button {
            tapHandler("Hello World")
        } label: {
            Text("Hello World")
        }
        
    }
}

// Step2
class CustomTextField: UITextField {
    override init(frame: CGRect) {
        super.init(frame: frame)
        initSubView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initSubView()
    }
    
    private func initSubView() {
        self.placeholder = "Tap here!"
        // Step3
        let wrapperView = UIHostingController(rootView: CustomViewPicker(tapHandler: setText)).view
        if let wrapperView {
            wrapperView.translatesAutoresizingMaskIntoConstraints = false
            // Step4
            self.inputView = wrapperView
            self.inputAccessoryView = createToolbar()
        }
    }
    
    private func createToolbar() -> UIToolbar {
        let toolbar = UIToolbar()
        toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: 44)
        
        let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(didTapDone))
        
        let toolbarItems = [flexibleSpace, doneButton]
        toolbar.items = toolbarItems
        return toolbar
    }
    
    @objc private func didTapDone(_ sender: UIButton) {
        resignFirstResponder()
    }
    
    private func setText(text: String) {
        self.text = text
    }
}

struct CustomTextFieldRepresentable: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        return CustomTextField()
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {}
}


struct ContentView: View {
    var body: some View {
        // Step5
        CustomTextFieldRepresentable()
            .frame(height: 44)
            .background(.red)
    }
}

```
# 動き
![Simulator Screen Recording - iPhone 14 Pro - 2023-09-09 at 13.37.12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962200/fdad98a3-0059-9e1d-1b6d-515907bbb064.gif)

# 終わり
今SwiftUIではinputViewのような仕組みがまだないですが、今後Appleの対応に期待しています。
GoogleカレンダーIDの調べ方

中々触れる機会がないので、メモ
画面仕様が変わる可能性があるので、2023.9.9時点での情報

# 手順
1. Googleカレンダーへアクセスします。
   [Googleカレンダー](https://calendar.google.com/calendar/)

1. 画面右上の歯車マークをクリックします。
![スクリーンショット 2023-09-09 132119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/6314e6bd-ebeb-78f2-0a93-4f403eb2a3af.png)

1. プルダウンメニューから、`設定`をクリックします。
![スクリーンショット 2023-09-09 132324.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/81e938d2-a0b2-1805-fc54-047e9c2502a1.png)

1. 左メニュー内に、`マイカレンダーの設定`があるので、カレンダー名をクリックします。
![スクリーンショット 2023-09-09 132538.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/67f4f90b-d06b-b9db-ffd7-3906cfe64b9e.png)

1. カレンダーの設定画面が表示されるので、`カレンダーの統合`までスクロールします。
   `カレンダーID`がこのカレンダーのIDです。
![スクリーンショット 2023-09-09 133238.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/17bf4ddb-bf78-6217-0f0b-56495e89226a.png)
Render.comでSeleniumを動かしたい

# はじめに
Seleniumで動くアプリケーションをどこかにデプロイして動かしたいと思いました。
しかし、調べてもHerokuに関する情報ばかり出てきます。
Herokuは無料枠がなくなってしまったので、その代替として[Render.com](https://render.com/)がよく候補に上がっています。
RenderでSeleniumを動かすのに苦戦したので、その方法をまとめておきます。
dockerを使用する方法もあるみたいですが、これは直接Chromeをインストールしています。

# 手順
サンプルコードは[こちら](https://github.com/clcl777/render_selenium)です。

https://github.com/clcl777/render_selenium

Chromeを展開するためにrender-build.shが必要です。
自動でChrome driverをダウンロードしてくれるPythonライブラリのwebdriver-managerを使用しています。
以下の記事を参考に、renderでGithubのリポジトリを読み込む。

https://qiita.com/matsutogen/items/f29ad5c244fdca24e4cf


renderのSettingsのBuild Commandを以下にする。
```
pip install -r requirements.txt; sh render-build.sh
```
Start Commandを以下にする。
```
export PATH="${PATH}:/opt/render/project/.render/chrome/opt/google/chrome";gunicorn app:app
```

# 動作確認
~~以下が実際にデプロイしたサンプルです。~~
~~読み込みに結構時間がかかりますが、表示されます。~~
サーバーを閉じました。

https://render-selenium-nlg3.onrender.com/
Javaで「スーパークラスのメンバへのアクセス」の動作を確認してみた

# 概要
Javaで「スーパークラスのメンバへのアクセス」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/extends/index2.html

# 実装
以下のファイルを作成しました。
```CTest11.java
class CTest11{
  public static void main(String args[]){
    Soarer soarer = new Soarer();

    soarer.openRoof();
    if (soarer.roofOpenFlag){
      System.out.println("屋根が開いています");
    }else{
      System.out.println("屋根が閉じています");
    }

    soarer.accele();
    System.out.println("現在の速度は" + soarer.speed + "キロです");
  }
}

class Car{
  int speed = 0;

  public void accele(){
    speed += 5;
  }

  public void brake(){
    speed -= 5;
  }
}

class Soarer extends Car{
  boolean roofOpenFlag = false;

  public void openRoof(){
    roofOpenFlag = true;
  }

  public void closeRoof(){
    roofOpenFlag = true;
  }
}
```
以下のコマンドを実行しました。
```
$ javac CTest11.java 
$ java CTest11 
屋根が開いています
現在の速度は5キロです
```

# まとめ
何かの役に立てばと。
LINE Notifyでトークンを発行する

発行の仕方を忘れることがあるので、備忘録（2023.9.9時点）

# LINE Notifyへアクセス
1. まずは、LINE Notifyのサイトへアクセスします。
   [LINE Notify](https://notify-bot.line.me/ja/)

1. 画面右上からログインをクリックします。
   ![スクリーンショット 2023-09-09 014442.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/c7726918-d079-5372-52cb-661b657537a0.png)

1. ログイン画面が出てきますので、LINEアカウントでログインします。
   ![スクリーンショット 2023-09-09 014633.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/5087088a-3cc6-ea17-e9e6-322f1a60864e.png)

1. アカウント名から、`登録サービス管理`をクリックする。
   ![スクリーンショット 2023-09-09 015319(モザイク).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/ae9e96ec-9a4d-48ed-4f3d-5f3625c4c1cf.png)

# トークン発行
1. 画面下側に`アクセストークンの発行(開発者向け)`がありますので、`トークンを発行する`をクリックします。
   ![スクリーンショット 2023-09-09 122643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/22aa75f2-4734-d9b7-efa3-1c47a18d5d31.png)

1. クリック後、発行するための情報が表示されますので、トークンに紐づく情報を登録します。
   - トークン名
     - LINE Notifyから送られてくるヘッダーとしても利用されます
   - トークルーム
     - 選択可能なのは、以下2つです
       - LINE Notifyとの1対1のトーク
       - LINEグループ 
:::note info
送付先１つに対して1つのトークン発行になります。
:::
:::note warn
登録した内容は後から変更できません
:::
![スクリーンショット 2023-09-09 123316(モザイク).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/475a8f6b-5f44-6857-45c4-ddff6cdb90e2.png)

1. トークンが表示されますので、**必ず**コピーして持っておいてください。
:::note alert
再発行はできません。
不要となった「連携中サービス」を削除し、[トークン発行](#トークン発行)からやり直してください
:::
   ![スクリーンショット 2023-09-09 130334.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3175117/960b66f4-2fa3-fa5d-8a75-87e072d856fc.png)
【Java】eclipseをインストールして「Gitリポジトリー」のウィンドウを表示させるまでの環境構築方法

# 背景
Javaで開発をするためにeclipseの環境構築を進めていました。
eclipseにおけるGit設定の知見がなかったため調べながら環境構築を行いました。
本記事はその環境構築方法をまとめてます。

# 本記事の対象
- eclipseのインストールは終わっているがGitの設定が分からない方
-  eclipseのインストールは終わっているがGitのウィンドウが表示されていない方
- タイトルが気になった方

# version
- eclipse version: 2023

# 手順１
eclipseを起動し「ヘルプ」→　「新規ソフトウェア」のインストール」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/c8bcafb7-8cc5-34f0-26b2-c1ae279e7411.png)

# 手順2
「追加」ボタンをクリック→以下の内容で入力。
- ロケーション：https://download.eclipse.org/egit/updates
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/0348fccb-45ce-316c-363d-f552e47afbe1.png)

# 手順3
全てにチェックを入れ「次へ」をクリック→「完了」ボタンをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/7a279c6e-3b7a-05f4-b25d-0ae2ef1e6fc2.png)

# 手順4
「ウィンドウ」→「ビューの表示」→「その他」をクリックすると「Git」が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/efe2a97a-74b7-8cec-f856-8092f3fe68aa.png)

# 手順5
「Git」→「Gitリポジトリー」を選択し「開く」ボタンをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/718f2560-9aec-b240-73c4-53a0a404079e.png)

これにより「Gitリポジトリー」のウィンドウが表示されるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/2ef73102-9363-50c7-2303-32ab99e2604e.png)
Pythonでファイル名に目的の文字列を含むデータファイルを取得

## 背景
他チームからデータファイルを連携されて集計や分析を依頼されることがある。
その際にファイルが1つにまとまっていると扱いやすいが、データの種類でファイルが分かれていたり、データ件数が多いために分割されて連携されることがあるので、それらをひとまとめにする作業の備忘録。
ファイル名を直接打ち込むことなく、条件に合ったファイルのみ取得しまとめることで、入力ミスや読み込みの漏れを解消することが目的。
ここでは簡易的に、Google Driveに格納されたIDごとのスコアのデータファイル複数とセグメントのデータファイル複数をひとまとめにすることを考える。
![data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/bde5bb26-b0c8-cd2c-65f0-bced99450831.png)



## コード
```py
import pandas as pd
import os
```

```py
# データの格納場所を設定
PATH = '/content/drive/MyDrive/data'
```

```py
# データの格納場所からファイル名の一覧を取得
files = os.listdir(PATH)
files
```

['data_score_1_20.csv',
 'data_score_21_40.csv',
 'data_score_41_80.csv',
 'data_segment_41_80.csv',
 'data_segment_1_20.csv',
 'data_segment_21_40.csv']


```py
# scoreのデータファイルのみファイル名を取得
target = 'score'
file_name_list = [file for file in files if target in file]
file_name_list.sort()
file_name_list
```
['data_score_1_20.csv', 'data_score_21_40.csv', 'data_score_41_80.csv']

```py
# scoreのデータのみ読み込み、縦結合、id列をインデックスに設定
score_data = pd.DataFrame()
for read_file in file_name_list:
    tmp = pd.read_csv(os.path.join(PATH, read_file))
    score_data = pd.concat([score_data, tmp])

score_data.set_index('id', inplace=True)
score_data
```
| id | score |
| :-- | --: |
| 1 | 14 |
| 2 | 32 |
| 3 | 24 |
| 4 | 10 |
| 5 | 60 |
| ... | ... |
| 76 | 51 |
| 77 | 32 |
| 78 | 80 |
| 79 | 26 |
| 80 | 49 |

```py
# segmentのデータファイルのみファイル名を取得
target = 'segment'
file_name_list = [file for file in files if target in file]
file_name_list.sort()
file_name_list
```
['data_segment_1_20.csv', 'data_segment_21_40.csv', 'data_segment_41_80.csv']

```py
# segmentのデータのみ読み込み、縦結合、id列をインデックスに設定
segment_data = pd.DataFrame()
for read_file in file_name_list:
    tmp = pd.read_csv(os.path.join(PATH, read_file))
    segment_data = pd.concat([segment_data, tmp])

segment_data.set_index('id', inplace=True)
segment_data
```
| id | segment |
| :-- | --: |
| 1 | 5 |
| 2 | 1 |
| 3 | 2 |
| 4 | 4 |
| 5 | 5 |
| ... | ... |
| 76 | 2 |
| 77 | 3 |
| 78 | 5 |
| 79 | 5 |
| 80 | 5 |

```py
# scoreのデータとsegmentのデータを横結合
merge_data = pd.concat([score_data, segment_data], axis=1)
merge_data
```
| id | score | segment |
| :-- | --: | --: |
| 1 | 14 | 5 |
| 2 | 32 | 1 |
| 3 | 24 | 2 |
| 4 | 10 | 4 |
| 5 | 60 | 5 |
| ... | ... | ... |
| 76 | 51 | 2 |
| 77 | 32 | 3 |
| 78 | 80 | 5 |
| 79 | 26 | 5 |
| 80 | 49 | 5 |
Android アプリ　アニメーション　ローテーション

[Reference: Android Developers](https://developer.android.com/develop/ui/views/animations/drawable-animation)


@animator/path_morph.xml
```
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <objectAnimator
            android:duration="3000"
            android:propertyName="pathData"
            android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
            android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
            android:valueType="pathType" />
    </set>
```

@animator/rotation.xml
```
<set　xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="6000"
        android:propertyName="rotation"
        android:valueFrom="0"
        android:valueTo="360" />
</set>
```
@drawable/animated_vector_drawable.xml
```
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_drawable" >
    <target
        android:name="rotationGroup"
        android:animation="@animator/rotation" />
    <target
        android:name="v"
        android:animation="@animator/path_morph" />
</animated-vector>
```
@drawable/vector_drawable.xml
```
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>
```

MainActivity
```Java

import androidx.appcompat.app.AppCompatActivity;
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;

import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.widget.ImageView;

import com.google.android.material.animation.AnimationUtils;

public class MainActivity extends AppCompatActivity {
AnimationDrawable arrowAnimation;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //using drawable vector and rotating with xml files
        AnimatedVectorDrawableCompat avdCompat = AnimatedVectorDrawableCompat.create(this, R.drawable.animated_vector_drawable);
        imageView.setImageDrawable(avdCompat);
        if (avdCompat != null) {
            avdCompat.start();
        }
    }
}
```
肥大化した Anaconda の不要ファイルを整理・削除する＿備忘録

●Anaconda を整理整頓
○現存する環境を確認
conda info -e

・不要になった環境(env)の削除
conda remove -n test -all

・不要になったパッケージやキャッシュを削除
conda clean --all

anacondaがメモリを食いすぎて動作が重くなっていたので、不要な環境や、キャッシュを削除するコマンドをまとめました。
完全に自分用のvue環境構築メモ

# はじめに
はじめまして。
マークダウンの練習がてら自分の環境構築メモを残します。
恐らくもう少し効率の良い構築方法はあると思うのであまり参考にしないでください。

# 前提
windowsでvscode + vite + vue3(js) + vuetifyの環境を作ります。
node.jsとvscodeはインストール済みです。

# 手順
構築手順をざっくり書いていきます。

## 1.ターミナルを叩く

環境を作ります。
名前は暫定で**frontEnd**にしておきます。
```shell
npm init vue frontEnd
```
実行すると色々設定した状態で環境を構築してくれます。すげえや。
今回はjsで作りたいのでこんな感じの設定にしました。
>・Add TypeScript? ... No
>・Add JSX Support? ... No
>・Add Vue Router ... Yes
>・Add Pinia ... Yes
>(以下全部No)

完了後、この後叩くコマンドを教えてくれるのですがついでに**vuetify**と**mdi/font**も入れておきます。

```shell
cd frontEnd
npm install
npm install vuetify
npm install @mdi/font -D
```
※mdi/fontは重いですが色々作りこんでいくうちは好きにMaterial Design Iconsを使いたいのでこれで行きます。
公開時にmdi/jsにします。

## 2.vuetifyの設定をする
### 1.src内にpluginsフォルダを作ります
```shell
cd src
mkdir plugins
```
※コマンドではなくクリックで作成でよいと思います

### 2.pluginsフォルダ内にvuetify.jsファイルを追加します
```shell
cd plugins
code vuetify.js
```
※コマンドではなくクリックで作成でよいと思います

### 3.vuetify.jsに下記コードを貼り付けます
```js:src/plugins/vuetify.js
import "vuetify/styles";
import '@mdi/font/css/materialdesignicons.css'
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
import { aliases, mdi } from "vuetify/iconsets/mdi";

const vuetify = createVuetify({
  components,
  directives,
  icons: {
    defaultSet: "mdi",
    aliases,
    sets: {
      mdi,
    },
  },
});
export default vuetify;
```


## 3.main.jsを修正する
```js:src/main.js
//import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

// Vuetify
import vuetify from './plugins/vuetify'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.use(vuetify)

app.mount('#app')
```
Vuetify関連の行を追加しました。
ついでにVuetify関連の動きがおかしくなるのでmain.cssのインポートをコメントアウトしました。

# 最後に
とりあえず完成です。
これからワイヤーフレームを作って何か作っていこうと思います。
ありがとうございました。
Laravel10のプロジェクトにBootstrapを適用するまでの手順

## 前提
- composer をインストールしていること
- npm をインストールしていること

## 手順1. laravel/ui のパッケージをインストール
Bootstrapをインストールしたいプロジェクトに移動
```
cd {プロジェクト名}
```

下記コマンドを実行
```
composer require laravel/ui
```

## 手順2. Bootstrap をインストール
下記コマンドを実行
```
php artisan ui bootstrap
```

実行結果として、 `package.json` にBootstrapが追加される
```json
"devDependencies": {
    ・・・
    "bootstrap": "^5.2.3",
    ・・・
}
```

## 手順3. プラグインのインストール
下記コマンドを実行
```
npm install
```

実行結果
```
-> % npm install

up to date, audited 39 packages in 619ms

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

## 手順4. bladeファイルにBootstrapを適用
CSSを適用するために、 `<head></head>` 内に
`@vite(['resources/sass/app.scss', 'resources/js/app.js'])`を追加

```php
<!DOCTYPE html>
<html lang="ja">
<head>
    ・・・
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
    ・・・
</head>
```
Laravel10では、Laravel MixではなくViteを使用しているため、`public/css/app.css`にスタイルが出力されない
したがって、bladeファイルでは `resources/sass/app.scss` のファイルパスを指定している

## 手順5. Viteの実行
下記コマンドを実行し、CSSやJSをHTMLに適用
```
npm run dev
```
ちなみに上記コマンドは、ファイルの変更を自動的に検知して開いているブラウザへ即時に適用してくれる
Laravel Mixでいうところの `npm run watch` と同じ意味合いですかね

手順5までを実行すると、CSSやJSが画面上に反映されているはずです

## 参考資料
- Laravel 10.x アセットの構築（Vite）
    - https://readouble.com/laravel/10.x/ja/vite.html
- Laravel 10.x + ViteでBootstrapを使う
    - https://qiita.com/Hotari/items/45fe9927d33dc79b6059
すぐに使えるVimの基本操作について

初学者がvimに着手する心構え
何はともあれテキストエディタであることは間違いないのだから
①動かして
②書く
この基本をできればまずは良いはずだ。

導入
まず３つのモードがあることを理解する。

Normal 	基本となるモード      esc
Insert	文字入力のときに使う	a/A/i/I
Visual	範囲選択のときに使う	v

vimで挙動がおかしいな、と思ったらとりあえず「esc」でリセット。
落ち着いて行いたい操作に戻ろう。

①動かす
h j k l
このキーボードでまとまった一帯が
左・下・上・右
に対応している。

時計回りでもなんでもないので、左右がh l
下上がj kで覚える。

大きな移動は
一番上ならgg
一番下ならG
単語ごとの移動なら前進wと後進b

一文字消すならx
一行消すならdd
カットならyy
ペーストならp
やり直しctrl＋Zの代わりはUndoのuが担当する

②書く
文字を入力したいときは簡単！
挿入insertのiを押せばできる。
挿入モードの終了はescで終われる。

※加えてaでもできるが現在カーソル位置の一つ後ろと使い所が微妙。
余裕があれば文頭のI、文末のAを使って早く入力していけそうだ。

まとめ
vimには数百種類のコマンドがあるようでvimerなる熟練者の称号があるようだが、
初学者としては深淵に近づかずとも上記の基本操作を覚えた後に、
あんな操作、こんな操作があれば便利～を調べて行くと良いのではなかろうか。

私は普段から操作に馴れるために、
AutoHotKeyを使って普段の操作もホームポジションから離れず設定してみたのだが、
そういう記事との連携も改めて記事にしてみようと思う。
Linux基礎コマンド

# *Linux基礎コマンド*

## ＄ cd  (change directry) ディレクトリ移動
ディレクトリ＝フォルダのこと
| 記号 | 名前 | 説明 |
|:-:|:-:|:-:|
|/ | ルートディレクト | コンピュータの一番の源となる
|~ | ホームディレクトリ | 一番つかうもの。デスクトップみたいな
|..| 一つ上のディレクトリ | 一つ上の階層に
|. | カレントディレクトリ | 現在の階層。.dirは隠しフォルダ

## $ pwd  (print working directory)

 今いるディレクトリ場所・階層を表示

## ＄ ls  (LiSt) 表示

正規表現が使える
| 記号 | 説明 | 例 |
|:-:|:-:|:-:|
|＊|パス名 |*.html →index.html home.html job.html|
|？|任意の一文字 |z??? → zcat zcmp zcom|

- オプション
-l ファイルの詳細情報
-a 隠しファイル含めすべて表示 
-F ファイル種別を表す


＠シンボリックリンク
*実行可能ファイル
通常リンク

## $ mkdir  (make directory) ディレクトリ作成

- オプション
-p test/2023/08 深いディレクトリを一度に作成できる


## $ rmdir  (remove directory) 空のディレクトリを削除

rm -rコマンドで代用することが多い

## $ cat (Concatenate) ファイルの中身を表示

cat ファイル名
- オプション
-n 行番号を表示
-cat /aaa/bbb /aaa/ccc

## $ less (List Editing Screen) 長いファイルの中身をスクロール表示

less ファイル名

内部はvim的に似た挙動

## $ tail 最終行から数行を表示する

tail ファイル名

## $ touch 空のファイルを作成

touch ファイル名
出来上がるのは中身のないファイル

## $ rm ファイルの削除

rm ファイル名
- オプション
-r   中身も含めてまとめて削除
-f  ファイル削除に警告文を出さない
-i  ファイル削除に警告文を出す

## $ mv ファイルの移動・名称変更

mv AA BB

mv  ファイル名(名称変更)

mv  ディレクトリ名(移動)
- オプション
-i 上書きする前に確認する。(安全に使いたい場合)

## $ cp ファイル・ディレクトリのコピー

cp AA BB ファイル名AA→ファイル名BBに

cp AA dir ファイルをdirにコピー
- オプション
-i 上書き前に確認
-r ディレクトリをコピー (通常dirはコピーできない)

## $ ln リンクを貼る

Linuxにおけるリンクとはwinでいうショートカット(シンボリック)のようなもの

ハードリンクは消しても元ファイルがずっと残ったまま。

ln file1 file2 (オプションなしだとハードリンク)
- オプション
-s シンボリックリンクにする

## $ find ファイルの検索

find . -検索条件 -アクション
- オプション
-name 検索条件ファイル名(大小文字区別)
-iname (大小文字区別なし)
-type ファイルの種類で検索
-f 通常ファイル
-l シンボリックリンク
-d ディレクトリ
-a 複数指定(省略可)

*’任意の文字列’  ￥バックスラッシュ 任意の文字列でも可能
?任意の一文字


## $ chmod (change mode) パーミッションを設定する

chmod [ugoa] [+-=] [rwx] ファイル名     ex) chmod u+r

u 所有者
g グループ
o その他
a 全

\+ 権限追加
\- 権限削除
= 記述した権限にする

※数値で指定することもできる  ex) chmod 755 ファイル

## $ chown (change owner) ユーザー・グループの所有権を変える
- オプション
    -R  ディレクトリの所有者を全てのファイル・ディレクトリに変更

## $ ps (process status) 実行中のプロセスを表示

 aux すべてのユーザーすべてのプロセス(’-’なし)

## $ kill ジョブやプロセスを終了させる

kill %ジョブID

kill プロセスID

kill -TERM(終了) ID

kill -SIGKILL(強制終了) ID

## リダイレクト

入力 ＜ ファイル

ファイルから入力を受ける

出力 ＞ ファイル.txt

ファイルに出力する

/dev/null

結果を消す。沢山シェルに出てくるのを事前に防ぐ。処理の中断など。

## パーミッション

複数のユーザーを管理する。オーナー-グループ-その他 

-r  Read
-w Write
-x  execute(実行)

```jsx
yuta@LAPTOP-RHLUIGKD:~$ ls -l
total 64
-rw-r--r-- 1 yuta yuta 44063 Aug 21 15:00 TEST
drwxr-xr-x 2 yuta yuta  4096 Aug 22 10:21 code
drwxr-xr-x 3 yuta yuta  4096 Aug 23 16:28 newtest
drwxr-xr-x 3 yuta yuta  4096 Aug 23 16:28 test
-rw-r--r-- 1 yuta yuta     0 Aug 23 16:11 test.md
drwxr-xr-x 3 yuta yuta  4096 Aug 23 16:16 test1
drwxr-xr-x 2 yuta yuta  4096 Aug 22 10:44 work
```

sudo (super user do) 管理者権限

## ジョブ 一連のプロセス

プロセスはOS全体で統一管理

ジョブはシェルで管理。バックグラウンドで実行したいときに使う。

(バック⇔フォア)

## $ jobs 現在のジョブ一覧を表示

fg  %id フォアグラウンド

bg %id or $ コマンド & バックグラウンド
WEB技術入門

WEBアプリケーションというとなにかネットに繋がる系で、
スマホでダウンロードして使うようなものを想像していたけれど、
普段使っているブラウザも立派なアプリケーションのひとつみたい。

ブラウザ(ウェブクライアント)からこのページが見たい！
などの要求を送ることをリクエスト。
そのリクエストを受けてサーバー側が返すことをレスポンスという。

普通のWEBサイトはコンテンツを表示するだけの静的(ステートレス)なサイトと分類され、
ログインフォームなど”状態”を持つものは動的(ステートフル)なサイトという。

状態を持つっていうのは、
毎度毎度ご新規様な大衆居酒屋(ステートレス)
マスター、いつもの。で通じる行きつけのバー(ステートフル)
のような違い。
「あらお客さんまた来てくれたね。」
これを人間なら脳みそのがやるけど、
WEBではクッキーというテキスト情報データとしてやり取りする。

クッキーに保存？というのがなんとも一般人には疑問の感覚。
調べても所以は定かにはならなかったけれどなにがしかの物語があったのでしょうな。

ただ、このクッキーをそのままやり取りしてると情報が流出してしまう危険性が高いので、
情報を暗号化して送る仕組みができた。
銀行やケータイショップなどで単純な整理番号をもらうのと同様に、
クッキーの中にIDを格納してやりとりする、その一連の流れをセッションという。


こういった情報のやり取りについてのルールをプロトコルという。
TCP/IPという情報を分割して送るのが一般的。
情報をパケットにして分割し分割されたパケット元に組み上げて伝達する。


また、情報を受取るための港をポートといい、
ポートには番号が振られて、
どの情報がどこへ行けば良いのかそれぞれ分けられる。
よく使うポート番号(Well-known ports)は以下の通り。

| ポート番号 | プロトコル |
| --- | --- |
| 20,21 | FTP(ファイル転送) |
| 22 | SSH(暗号化されたリモートコンピューターとの通信) |
| 23 | Telent(リモートコンピューター)との通信 |
| 25 | SMTP(メール送信) |
| 53 | DNS |
| 80 | HTTP(WEBブラウジング) |
| 110 | POP3(メール受信) |
| 443 | HTTPS(暗号化されたHTTP) |
Dockerコマンドチートシート：よく使うコマンドまとめ

## コンテナ管理

### 1. コンテナのリスト表示

- **稼働中のコンテナのリスト表示**
  ```sh
  docker ps
  ```

- **全てのコンテナのリスト表示（停止中を含む）**
  ```sh
  docker ps -a
  ```

### 2. コンテナの起動と停止

- **コンテナの起動**
  ```sh
  docker start CONTAINER_ID
  ```

- **コンテナの停止**
  ```sh
  docker stop CONTAINER_ID
  ```

- **稼働中のコンテナをすべて停止**
  ```sh
  docker stop $(docker ps -q)
  ```

### 3. コンテナの作成と削除

- **新しいコンテナを作成**
  ```sh
  docker create IMAGE_NAME
  ```

- **コンテナの削除**
  ```sh
  docker rm CONTAINER_ID
  ```

- **すべてのコンテナの削除**
  ```sh
  docker rm $(docker ps -a -q)
  ```


## イメージ管理

### 4. イメージのリスト表示

- **利用可能なイメージのリスト表示**
  ```sh
  docker images
  ```

### 5. イメージの取得と削除

- **新しいイメージの取得**
  ```sh
  docker pull IMAGE_NAME
  ```

- **イメージの削除**
  ```sh
  docker rmi IMAGE_NAME
  ```

## ボリュームとネットワーク管理

### 6. ボリューム管理

- **利用可能なボリュームのリスト表示**
  ```sh
  docker volume ls
  ```

- **新しいボリュームの作成**
  ```sh
  docker volume create VOLUME_NAME
  ```

- **ボリュームの削除**
  ```sh
  docker volume rm VOLUME_NAME
  ```
- **未使用のボリュームをすべて削除**
  ```sh
  docker volume prune
  ```

### 7. ネットワーク管理

- **利用可能なネットワークのリスト表示**
  ```sh
  docker network ls
  ```

- **新しいネットワークの作成**
  ```sh
  docker network create NETWORK_NAME
  ```

- **ネットワークの削除**
  ```sh
  docker network rm NETWORK_NAME
  ```

## Docker Composeコマンド

Docker Composeを使用して複数のコンテナを管理

- **サービスのビルド**
  ```sh
  docker-compose build
  ```
- **Composeプロジェクトの起動(Ctrl+Cで中断)**
  ```sh
  docker-compose up
  ```
- **Composeプロジェクトの起動(バックグラウンド実行)**
  ```sh
  docker-compose up -d
  ```

- **Composeプロジェクトの停止**
  ```sh
  docker-compose down
  ```
paiza.ioでelixir その252

# 概要
paiza.ioでelixirやってみた。
zundoko書いたけど、バグってる。
見逃すときが、ある。

# サンプルコード

```

defmodule Zundoko do
	def start() do
		Stream.repeatedly(fn ->
			["ズン", "ドコ"]
			|> Enum.random
		end)
		|> run
	end
	def run(input) do
		match = ["ドコ", "ズン", "ズン", "ズン", "ドコ"]
		eol = "キ・ヨ・シ！"
		input
		|> Stream.transform([], fn item, acc ->
				if List.last(acc) == eol do
					{:halt, nil}
				else
					if Enum.count(acc) < Enum.count(match) do
						{[item], acc ++ [item]}
					else
						if acc == match do
							{[eol], acc ++ [eol]}
						else
							{[item], [item]}
						end
					end
				end
				|> IO.inspect
			end)
		|> Enum.to_list
		|> Enum.reduce("", fn v, s ->
			s = s <> v <> " "
		end)
	end
end



defmodule Zundoko2 do
	def start() do
		Stream.repeatedly(fn ->
			["ズン", "ドコ"]
			|> Enum.random
		end)
		|> run
	end
	def run(input) do
		match = ["ドコ", "ズン", "ズン", "ズン"]
		eol = "ドコ キ・ヨ・シ！"
		doko = "ドコ"
		input
		|> Stream.transform([], fn item, acc ->
				if List.last(acc) == eol do
					{:halt, nil}
				else
				    if item == doko do
				    	{[item], [item]}
				    else
    					if Enum.count(acc) < Enum.count(match) do
	    					{[item], acc ++ [item]}
		    			else
			    			if acc == match do
				    			{[eol], acc ++ [eol]}
					    	else
						    	{[item], [item]}
					    	end
					    end
					end
				end
				|> IO.inspect
			end)
		|> Enum.to_list
		|> Enum.reduce("", fn v, s ->
			s = s <> v <> " "
		end)
	end
end


Zundoko.start
|> IO.inspect

Zundoko2.start
|> IO.inspect




```

# 実行結果

```
{["ズン"], ["ズン"]}
{["ドコ"], ["ズン", "ドコ"]}
{["ドコ"], ["ズン", "ドコ", "ドコ"]}
{["ドコ"], ["ズン", "ドコ", "ドコ", "ドコ"]}
{["ドコ"], ["ズン", "ドコ", "ドコ", "ドコ", "ドコ"]}
{["ズン"], ["ズン"]}
{["ズン"], ["ズン", "ズン"]}
{["ズン"], ["ズン", "ズン", "ズン"]}
{["ドコ"], ["ズン", "ズン", "ズン", "ドコ"]}
{["ズン"], ["ズン", "ズン", "ズン", "ドコ", "ズン"]}
{["ズン"], ["ズン"]}
{["ドコ"], ["ズン", "ドコ"]}
{["ドコ"], ["ズン", "ドコ", "ドコ"]}
{["ズン"], ["ズン", "ドコ", "ドコ", "ズン"]}
{["ドコ"], ["ズン", "ドコ", "ドコ", "ズン", "ドコ"]}
{["ドコ"], ["ドコ"]}
{["ズン"], ["ドコ", "ズン"]}
{["ズン"], ["ドコ", "ズン", "ズン"]}
{["ズン"], ["ドコ", "ズン", "ズン", "ズン"]}
{["ドコ"], ["ドコ", "ズン", "ズン", "ズン", "ドコ"]}
{["キ・ヨ・シ！"],
 ["ドコ", "ズン", "ズン", "ズン", "ドコ", "キ・ヨ・シ！"]}
{:halt, nil}
"ズン ドコ ドコ ドコ ドコ ズン ズン ズン ドコ ズン ズン ドコ ドコ ズン ドコ ドコ ズン ズン ズン ドコ キ・ヨ・シ！ "
{["ドコ"], ["ドコ"]}
{["ドコ"], ["ドコ"]}
{["ドコ"], ["ドコ"]}
{["ドコ"], ["ドコ"]}
{["ズン"], ["ドコ", "ズン"]}
{["ドコ"], ["ドコ"]}
{["ドコ"], ["ドコ"]}
{["ズン"], ["ドコ", "ズン"]}
{["ドコ"], ["ドコ"]}
{["ドコ"], ["ドコ"]}
{["ズン"], ["ドコ", "ズン"]}
{["ズン"], ["ドコ", "ズン", "ズン"]}
{["ズン"], ["ドコ", "ズン", "ズン", "ズン"]}
{["ドコ キ・ヨ・シ！"],
 ["ドコ", "ズン", "ズン", "ズン", "ドコ キ・ヨ・シ！"]}
{:halt, nil}
"ドコ ドコ ドコ ドコ ズン ドコ ドコ ズン ドコ ドコ ズン ズン ズン ドコ キ・ヨ・シ！ "
```
# 成果物

https://paiza.io/projects/G4m_8Ym8I6VB1De0Ru3nSg



以上。
LeetCodeのGroup Anagrams解いてみた

# 始めに
今回はLeetCodeのGroup Anagramsに挑戦してみた
難易度はMediumだけどポイントさえ掴めれば解けるはず
この記事はメガベンを目指すよわよわエンジニアによるものなので間違えがあればビシバシご指摘下さい！
ではやっていこう

今回挑戦した問題

https://leetcode.com/problems/group-anagrams/

# 問題
この問題は複数の単語が格納されたstrsという配列をアナグラム毎にグループ分けをする問題。
アナグラムとは文字を入れ替えたら同じ文字列になる単語のことです。
例えば、
```
abc, cba, bac
```
↑は文字を入れ替えると全て同じ単語になりますよね
```python
strs = ["abc", "cba", "bac", "tab"]
```
上記をアナグラム毎に分けると以下のようになる
```python
ans = [[abc, cba, bac], [tab]]
```

多分直感的に理解できる人が多いけどこれをプログラムにしていくと意外と頭がこんがらがるんよね...

# 考察
まずこの問題を解く上で重要なのは
- ハッシュマップを使って効率的に解く
- ソートを使い、アナグラム判定ができるようにする
- ハッシュマップの構造を適切な形にする

適切なハッシュマップ構造が作れればほぼ勝ち。
今回の場合で言うと以下の形にできればOK
キーの部分は各単語をソートした値です
```
# ハッシュマップの中身
{
    abc: ["abc", "cba", "bac"],
    abt: ["tab"]
}
```


# 解法
ではコードを書いていく

まずはハッシュマップを作成していく
defaultdictを使うことで存在しないキーにアクセスしてもエラーにならないので不要なif分を排除できる。
と言っても大きな支障はないから通常の辞書型を使っても問題ないと思う。
```python
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
    anagram_map = defaultdict(list)
```

## 適切なハッシュマップを作成していく
各単語をソートし、ソートした値をハッシュマップのキー設定。
そしてソート前の値をバリューに追加していく。
```python
for word in strs:
    sorted_word = "".join(sorted(word))
    anagram_map[sorted_word].append(word)
```

実はここまでで既に目標のハッシュマップ構造にになっている↓
```
# ハッシュマップの中身
{
    abc: ["abc", "cba", "bac"],
    abt: ["tab"]
}
```

## 適切な形式にして返す
完成したハッシュマップの値のみを配列に格納して返せば完成！
```python
return list(anagram_map.values())
```

以下は全文です
この問題の計算量はO(n×mlogm) となります。
一般的なfor文でO(N)
sortはO(mlogm)
よってO(n×mlogm)となる訳です。（間違ってたらご指摘お願いします）
```python
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
    anagram_map = defaultdict(list)
    for word in strs:
        sorted_word = "".join(sorted(word))
        anagram_map[sorted_word].append(word)

    return list(anagram_map.values())
```

# まとめ
- アルゴリズムの選定(ハッシュマップ)
- ソートすることでアナグラム判定をしやすくする（アナグラムの性質理解）
- ハッシュマップでソートした値をキーにする(適切なハッシュマップ構造)

上記を問題を読んだ時点で自然と出てくるレベルになればサクッと解ける
ちなみに自分は結構時間かかった...


# 感想
やってることは今までのハッシュマップ問題と変わりないが、ハッシュマップを適切な形式にするのが少し苦手なのがわかった。
ここら辺は解いた問題数とかで変わってくるのかな？

まあどちらにしてもまだまだ修行が足りないな〜
vmware ESXii 8.0 で centos 8 のインストールに失敗する

vmware ESXi 8.0に、centos 8をインストールしようとすると、centosのインストールが開始しません。


**事象１：** CDROMが認識しない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/9d5496e6-6e76-613d-65f0-db9d235ead1c.png)

```text:error
EFI VMware Virtual SATA CDROM Drive (0,0) ... Not Found.
```

**事象２：** UFEI-BIOS画面でCDROMで起動しない（何度Enterを押下してもインストールに進まない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/77218c80-6005-a210-8c80-c293ccf9947d.png)



# ■環境
ESXi:`VMware-VMvisor-Installer-8.0U1a-21813344.x86_64.iso`
centos:`CentOS-8.4.2105-x86_64-dvd1.iso`
仮想マシンバージョン:`ESXi 8.0 以降(version 20)`


# ■解決策
・UFEIセキュアブートの無効化(vm再作成しない)
・仮想マシンバージョンの変更(vm再作成する)
・[非推奨]ファームウェアのBIOS変更(vm再作成しない)

## UFEIセキュアブートの無効化(vm再作成しない)
仮想マシン設定にて、UFEIセキュアブートを無効化します。

`仮想マシンオプション` - `起動オプション` - `ファームウェア`からUFEIセキュアブートを無効化します（チェックを外す）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/6e01943a-697a-0a32-1925-781e1c1ff41b.png)

再度VMを起動すると、問題なくcentosのインストールに進みました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/97309c6f-10d8-680d-71bb-1f28468b3de2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/8bebd9a8-70d3-b689-01fd-9f4f2ab4e542.png)



## 仮想マシンバージョンの変更(vm再作成する)
VM作成時、仮想マシンバージョンを`ESXi 7.0 U2 仮想マシン`（仮想マシンバージョン19）にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/bc67d1a3-a4dc-3398-512e-a674d56265b1.png)

VM起動後、問題なくcentosのインストールに進みました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/33567b54-08ce-5a46-d271-ab464a444ea5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/40fc7312-ab2a-3012-6225-f39370ae5d2c.png)

:::note info
ESXi 7.0 U2 仮想マシン（仮想マシンバージョン19）では、ファームウェアは`BIOS`になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/650db78f-6793-7e5a-da54-0c2b1e507f34.png)
:::

## [非推奨]ファームウェアのBIOS変更(vm再作成しない)
:::note warn
仮想マシンのハードウェア設定を多く変更するため、ハードウェア相性問題や性能問題を引き起こす可能性があります。
:::

非推奨のため、要点だけ記載します。
・vmxファイルついて、`chipset.motherboardLayout`を`acpi`から`i440bx`に変更
・仮想マシンオプションより、ファームウェアをEFIからBIOSに変更
・仮想ハードウェア設定にて、ハードディスク、CD/DVDについてIDEコントローラに変更(再作成)



# ■参考
**仮想マシンの UEFI セキュア ブートの有効化または無効化**
https://docs.vmware.com/jp/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-898217D4-689D-4EB5-866C-888353FE241C.html


**仮想 NUMA 制御**
https://docs.vmware.com/jp/VMware-vSphere/8.0/vsphere-resource-management/GUID-3E956FB5-8ACB-42C3-B068-664989C3FF44.html


**VirtualHardwareMotherboardLayoutEnum**
https://developer.vmware.com/apis/vi-json/8.0.1.0/data-structures/VirtualHardwareMotherboardLayout/enum/


**Error "ACPI motherboard layout requires EFI" when setting ESXi 8.0 VM to BIOS**
https://communities.vmware.com/t5/ESXi-Discussions/Error-quot-ACPI-motherboard-layout-requires-EFI-quot-when/td-p/2945906


**Problem Booting Win10 in VMWare Workstation for First Time**
https://communities.vmware.com/t5/VMware-Workstation-Player/Problem-Booting-Win10-in-VMWare-Workstation-for-First-Time/td-p/1363890
くらしTEPCO VS おうちモニター

Bルートのデータを使った自作の「おうちモニター」の時間別の使用量のJSがバグってたので、直しました。バグは恥ずかしくて書けません。^ ^;

![filename(13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/1c860465-6dd6-bf94-17f9-a2c4daf38c01.png)

おそらく朝トーストを焼いたのと、夕方炊飯したのがピークになってるのではないかと思います。

~~実はこのグラフは日が変わった時の集計ができてなくて、ちょっと少なくなることがあります。sqlite3からSQLでデータを吐き出してjsonにしてるのですが、SQL詳しくないので、制限事項です。~~ 覚えていないのですが、ちゃんとできてました。

東京電力のAルートの「くらしTEPCO」のグラフはこんなです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/3dbfb5a4-e984-1128-e576-3dc5788ee652.png)

他のグラフはけっこうちゃんとできてるのですが、このグラフはちょっといけてないので、そのうち作り直してくださいね。
#0021 pythonからコマンド実行

### はじめに
- pythonからコマンド実行したいときの`subprocess`モジュールについて書きます。

### `subprocess`モジュールの使い方
- `subprocess`モジュールを使えば、pythonからコマンドを実行できます。
- https://docs.python.org/3/library/subprocess.html
- `subprocess.run([<実行したいコマンド>]`でpythonからコマンドを実行できます。
- コマンドは複数の場合は配列で渡します。

```
環境：Python 3.11.4

import subprocess

>>> subprocess.run(["ls", "-l", ""])
total 16
total 16
drwx------@   3 xxxx  staff    96B  9  6  2021 Applications
drwx------@  32 xxxx  staff   1.0K  8  6 08:52 Desktop
drwx------+   4 xxxx  staff   128B 10 11  2022 Documents
drwx------@ 163 xxxx  staff   5.1K  9  3 21:26 Downloads
drwx------    7 xxxx  staff   224B  3 18  2022 Movies
drwx------+   5 xxxx  staff   160B  7 19  2022 Music
drwx------+  13 xxxx  staff   416B  8 17 19:33 Pictures
...
```

#### 結果の取得
- 結果を取得するにはrun()の引数に`capture_output=True`を入れます。
- 結果の属性は以下です。
    - `arges`
    - `returncode`
    - `stdout`
    - `stderr`
- また、結果はバイナリ形式のため、文字列にするにはrun()の引数に`text=True`を入れます。

```
>>> res = subprocess.run("ls", capture_output=True, text=True)

>>> print(res.stdout)
Applications
Desktop
Documents
Downloads
Movies
Music
...
```

#### shell実行
- run()の引数に`shell=True`を入れればshell実行ができ、shellの機能使えます。
- パイプやワイルドカードを利用できます。

```
>>> subprocess.run("ls | grep Do", shell=True)
Documents
Downloads
CompletedProcess(args='ls | grep Do', returncode=0)
```


### 終わりに
- `subprocess`を学んでから、pythonでコマンド実行できると思い、unzipをsubprocessで書いたら、「pythonに標準モジュールがある」と指摘されました。
- まだまだ勉強不足です。