OmniAICreator/Qiita-1.07M huggingface dataset:
ufw有効下でDockerコンテナからローカルに立てたPostgreSQLに接続

# 概要

遊びで作ってる物をデプロイするにあたり、あまり運用にコストを掛けたくないのでVPSを借りて一台に全部ぶちこむ構成で作っていたのですが、単純なことに見事にハマりちらかして結構な時間が解けてしまったので備忘録です。

# 結論

私の環境ではufwを有効にしていたので、コンテナからのアクセスがufwに弾かれていて、ローカルのPostgreSQLへの接続ができていませんでした。ufwの許可ルールにdockerがデフォルトで使うアドレス範囲(172.16.0.0/12)からの接続を追加することで解決しました。
(もうすこし設定を絞ったほうが良いと思いますが、お遊びなのでヨシ！)

```console
# ufw allow proto tcp from 172.16.0.0/12 to any port 5432
```

# 背景

こんな雰囲気のdocker-composeで、DBを参照するアプリが起動するようにアプリケーションを作成しました。

```yml:docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
    environment:
      - DATABASE_CLIENT=postgres
      - DATABASE_HOST=host.docker.internal
      - DATABASE_PORT=5432
      - DATABASE_USERNAME=dbuser
      - DATABASE_PASSWORD=dbpass
      - DATABASE_NAME=dbname
      - DATABASE_SCHEMA=public
    extra_hosts:
      - host.docker.internal:host-gateway
    command: sh -c 'yarn run start'
    restart: always
```

PostgreSQLの設定をコンテナからアクセスできるように変更、追加して、サービスを再起動しています。

```conf:/etc/postgresql/15/main/postgresql.conf
# ...略
listen_addresses = '*'                  # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
                                        # (change requires restart)
port = 5432                             # (change requires restart)
max_connections = 100                   # (change requires restart)
# 略...
```

```conf:/etc/postgresql/15/main/pg_hba.conf
# ...略
# IPv4 Docker container connections:
host    all             all             172.16.0.0/12           scram-sha-256
```

その後、意気揚々と`docker compose up`するもDB接続エラーが出て、設定見直したりいろいろ試行錯誤するも解決せず。
最終的には、syslogを確認してufwが原因だったと気づくまで1.5日溶けました...
この記事がだれかの時間を救いますように...
changetypeディレクティブについて

●changetypeディレクティブ
LDIFファイルを利用してエントリの追加、削除および変更を行う

書式

dn: 対象エントリの識別名
changetype: 変更種別
変更内容
･･･

■変更種別

・add エントリの追加
・delete エントリの削除
・modify エントリ情報の変更(属性の追加、削除、変更など)
・modrdnRDN(相対識別名)の変更

●LDIFファイルの内容は、ldapmodifyコマンドを利用して反映。
間違ってpushをしてしまった場合の対象法

<h1>まず、なにが起きたのか</h1>
年があけて、作業開始しようとして画面の矢印部分を押してpullをしたら、知らないうちにコミットしていたものをpushしてしまった。矢印部分のマークはpullとpushを同時に実行してしまうことがわかっていなかくて、はずみで押してしまった。
<br>ミスを気がついてリバートをしたがうまく修復できないという事態になってしまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/2dddc950-5bf9-7ba6-913e-630f6da6c8e2.png)



<h1>調査</h1>
普通のpushミスならば
git revertコマンドを使えばpush前までの状態に戻すことができる。
状態を修正してミス前のソースコードと見比べていたが何かおかしい・・
<br>なぜか、revert済みソースコードと元々あった差分が生まれていた。
<br>上の画像にも表示されているが、VSCodeで矢印部分のマークはpullとpushを同時に実行する機能がありローカルにコミットが既に存在していて下のボタンを押すことでpushがされてしまったようだ。
<br>そのため、古い状態でのコミットがされている状態だった。


![096a5e993caabac78f9178eda92bb7b4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2702878/e0bd1104-337a-89ac-6700-0b72070c8afc.png)

<h1>調査結果</h1>
それを初めにミスってpushした状態は古いコミットを新しくしたので初めの段階では
既に存在していた内容と同じだった。
同じにも関わらず、revertをしたのでより前の状態に戻しpushしてしまった。
<br>というのが今回の全貌になると思う。
<br>
<br>
通常commitしてからすぐ打ち消したい場合にrevertをする流れは以下のようにすれば実行できます。

revertでは指定したコミットハッシュを打ち消すコミットを新たに行うことができます。
revertは指定したコミット自体はコミット履歴から消さず、そのまま残せることが特徴です。

```
git revert <対象のコミットID>
```


### 今回の原因
主な原因としては以下が原因だと思われる
・ローカルにコミットを一つ持っていた。
・pullしていない状況だった
・古い状態でコミットpushしてしコミットのみしている状態のものが存在した。
・ミスに気がついてリバートする時に元々あったものと違う状態でリバーとしてしまった。
（コミットをしている状態がリモートリポジトリにある状態と同じだった。）
・よくわからないコミットを持っていた
・リバートの時の差分を確認してなかった
・不用意なプッシュをしてしまった。
・下の矢印ボタンの意味を理解していないかった。

<h1>結果</h1>
git resetを使用して新たに作成したpushを二つとも消した。
既にややこしい感じになっていたため、pushを取り消しローカルで使用していた
ブランチも削除して再作成をした。
<dr>

以下のgit resetコマンドを使うことで直前のコミットを取り消す事ができます。
```
 git reset --hard HEAD^
```

resetで取り消したことはコミットログとして残りません。

<h1>まとめ</h1>
今回は色々なことが重なって起こってしまったような気もするが
やっぱり、不用意なコミットはしないというのが一番いいと思う。
gitでソースコードを管理していて大体がcommitとpushがセットで使われる
事が大半で変にcommitだけをすると今回みたいな事が起きかねないので気を付けよう。
【シェルスクリプト】回答によって処理を分岐する方法


## デフォルトでYes
```sample.sh
#!/bin/bash

echo -n "実行しますか？ [Y/n]: "
read ANS

case $ANS in
  "" | [Yy]* )
    # 「Yes」の場合の処理
    ;;
  * )
    # 「No」の場合の処理
    ;;
esac
```

## デフォルトでNo

```sample.sh
#!/bin/bash

echo -n "実行しますか？ [y/N]: "
read ANS

case $ANS in
  [Yy]* )
    # 「Yes」の場合の処理
    ;;
  * )
    # 「No」の場合の処理
    ;;
esac
```

## 必ず入力させる
```sample.sh
#!/bin/bash

function ask_yes_no {
  while true; do
    echo -n "$* [y/n]: "
    read ANS
    case $ANS in
      [Yy]*)
        return 0
        ;;  
      [Nn]*)
        return 1
        ;;
      *)
        echo "yまたはnを入力してください"
        ;;
    esac
  done
}

if ask_yes_no "実行しますか？"; then
    # 「Yes」の場合の処理
else
    # 「No」の場合の処理
fi
```
ChatGPTで行うコードレビューを日本語と英語で比較してみる

前に書いた機械学習の記事に使ったPythonのコードを、話題になっているChatGPTにコードレビューさしてみました。

https://qiita.com/dg4101/items/2968864714fe72b0d7bf

英語と日本語でどれくらい違いが出るか比べてみました。
使ったコードは`データの読み取り`の章で紹介した、以下のコードです。
行っているのは衛星画像のr種類のデータをファイルから読み込み、r個要素の入った3次元配列を返しています。それをさらにr個要素の入った１次元の配列にし直しています。

```python
def k_get_raw_data(city,dataset,r,x,y,h,w):
    mimage = np.zeros((h, w, r), dtype=int)
    for i in range(r):
        b = i + 1
        with rasterio.open(city + '\\' + dataset + str(b) + '.tiff') as src:
            data = src.read()
        img = data[0][y:y+h, x:x+w]
        mimage[:, :, i] = img

    new_shape = (mimage.shape[0] * mimage.shape[1], mimage.shape[2])
    X = mimage[:, :, :r].reshape(new_shape)
    return X
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/1e1169e0-ff43-3ce5-ed4c-afd2bcb5c3c4.png)

素晴らしいですね。拡張子でTIFFと使っていたりしているからかもしれませんが、TIFF画像の読み込みをしていることも分かっているようです。

次に英語で同じコードをレビューしてもらいます。新しいChatを開いて、英語で聞いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/331adfcd-2d97-644d-41d4-da164de7e834.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/83b4b3d0-d47d-7076-164e-a1801927978d.png)

日本語の時よりさらに詳細に解説してくれています。
* ただTIFFだけでなくGeoTIFFと言い切っている
* パラメータの詳細な解説をしている。それぞれの属性までもStringなのかIntegerなのかなど説明している。
* 読み込んだデータから一部を切り出しているのですが、それがx,y地点から始まり高さh、幅wで切り出していることも説明。
* いくつかの注意事項も説明している。読み込むソースデータがフォルダーにあることを前提にしていることも指摘。これによって本来はエラーハンドリングなどを追加する必要性も考えられる。

ちなみに、英語でレビューしてもらったものを日本語で返答するように聞いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/14e10469-cb78-484b-e410-ce5a7b4906b6.png)

これは、英語で一度返しているのでそれを翻訳した感じのように見受けられます。

それにしても完成度は驚きです。
Golangのgoto文に関して

### Golangのgoto文に関して興味を持った背景
[こちらの記事](https://www.includehelp.com/golang/goto-aptitude-questions-and-answers.aspx)でコーディングテストの勉強をする際に、恥ずかしながら初めてgoto文を知ったのでこちらの記事でまとめようと思います。
### 具体的にgoto文が使われている箇所
実際にgolangのgithubを覗くと、[こちらの箇所](https://github.com/golang/go/blob/master/src/math/rand/rand.go#L188)などで使われているようです。
```rand/rand.go
func (r *Rand) Float64() float64 {
	// A clearer, simpler implementation would be:
	//	return float64(r.Int63n(1<<53)) / (1<<53)
	// However, Go 1 shipped with
	//	return float64(r.Int63()) / (1 << 63)
	// and we want to preserve that value stream.
	//
	// There is one bug in the value stream: r.Int63() may be so close
	// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
	// that the result is always less than 1.0.
	//
	// We tried to fix this by mapping 1.0 back to 0.0, but since float64
	// values near 0 are much denser than near 1, mapping 1 to 0 caused
	// a theoretically significant overshoot in the probability of returning 0.
	// Instead of that, if we round up to 1, just try again.
	// Getting 1 only happens 1/2⁵³ of the time, so most clients
	// will not observe it anyway.
again:
	f := float64(r.Int63()) / (1 << 63)
	if f == 1 {
		goto again // resample; this branch is taken O(never)
	}
	return f
}
``` 
forで書くとこんな感じですね。

```rand/rand.go
func (r *Rand) Float32() float32 {
    f := float32(r.Float64())
    for f == 1 {
        f = float32(r.Float64())
    }
    return f
}
```

使い所がいまいちわからずfor文で良いのでは？とは思ってしまいました。
ちなみにgoto文はメソッド外では`Compile Error`になります。
[GoPlaygroundリンク](https://go.dev/play/p/Xq0eLXvMij0)
```hoge/hoge.go
func main() {
	var val int = 0
	val = val + 2
	if val < 5 {
		goto XYZ
	}
}

func PrintHello() {
XYZ:
	fmt.Printf("Hello World\n")
}

// putput:
// ./prog.go:9:8: label XYZ not defined
// ./prog.go:14:1: label XYZ defined and not used

```

### 個人的な所感
う〜ん。正直for文でいいんじゃないのかなと思いますが、処理速度などが違うんですかね。

参照
https://qiita.com/weloan/items/29018c8d0049abbe6199
OpenFOAMの結果をblenderで可視化してみる#02 OpenFOAMの実行

# はじめに
前回までに，openfoamのインストールを行ったので，
可視化する元データを作成する。
例として, interIsoFoamのチュートリアルを試してみる。

::: note info
interIsoFoamはinterFoamの拡張版で，2相流（水と空気）を扱うソルバー
:::

# 解析ケース
対象は下記の2ケースいずれも計算時間は10分もかからない程度の問題
- damBreak
- iobasin

# 実行方法
``` bash
mkdir ~/openfoam
cd openfoam
#チュートリアルのデータをもってくる
cp -r $FOAM_TUTORIALS/multiphase/interIsoFoam/damBreak .
cp -r $FOAM_TUTORIALS/multiphase/interIsoFoam/iobasin .

#チュートリアルの実行
cd damBreak
./Allrun

cd ../iobasin
./Allrun
```

::: note warn
interIsoFOAMは並列計算するように設定されているため，下記のようｒに
`Allrun`を修正している。

``` sh
#!/bin/sh
cd "${0%/*}" || exit                                # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
#------------------------------------------------------------------------------
restore0Dir
runApplication blockMesh
runApplication createPatch -overwrite
runApplication setFields
runApplication $(getApplication)
#runApplication decomposePar
#runParallel $(getApplication)
#runApplication reconstructPar
#------------------------------------------------------------------------------
:::

# 実行結果
各フォルダーでこんな感じで，0.01,  0.02といったフォルダが生成されていればOK。フォルダ名が時間を表していて，そこに計算結果が入っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/82161440-b5ac-3c60-81d8-50271e93b737.png) 

各ケースでの計算期間はそれぞれ下記のとおり。iobasinsが一応3次元なのに，思ったより時間かからなかった。
|  case  |  計算期間  |  計算時間  |
| ---- | ---- |---- |
|dambreak  |  1.0s  | 133s|
|  iobasins  |  3.0s  | 483s|
VSCODE remote explorerが権限情報をキャッシュしてしまう件

VSCODEでファイル権限がない状態で一度接続してしまうと、その後グループ書き込み権などを付与してSSHなどでは書き込みできるようになった後も、VSCODEを開きなおす(接続しなおす）だけでは解決しない。

```
Visual Studio Code – NoPermissions (FileSystemError): Error: EACCES: permission denied
```

解決策
https://github.com/microsoft/vscode-remote-release/issues/3399
サーバー側で稼働しているvscode-serverを落とす

```bash
ps aux | grep .vscode-server | awk '{print $2}' | xargs kill -9
```

ありがとう。
Treasure Data CDP から Azure Blob StorageにWorkflowを使用してデータをエクスポートする。

# Treasure Data CDP とは

https://www.treasuredata.co.jp/

Customer Data Platformというジャンル（？）のデータ分析基盤です。
顧客視点での分析ができる様々な機能も魅力ですが、豊富なコネクタを兼ね備えており、柔軟なアーキテクチャを構成することができます。

# Azure Blob Storageにデータを連携する

データをBlobにおいておけば、Power BIでの可視化・分析、Azure MLでの機械学習など、さらに様々なシナリオを実現することができます。

# 実践

## コネクタ構成をする

1. **Integrations Hub**の**Catalog**から**Microsoft Azure**をクリック
1. Blob に必要な情報を入力（画像参照）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/ed4dfb1f-961d-b55c-e13d-73ca77072d3b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/4a807b0c-46e1-960a-2ae6-cbf8def6d294.png)

https://docs.treasuredata.com/display/public/INT/Microsoft+Azure+Blob+Storage+Export+Integration

ここまでやると、**Integrations Hub**の**Authentications**に**Microsoft Azure**ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/8cc458c1-c9f1-91fd-ca6e-f3ef792fa4f8.png)

:::note
Authenticationsは一度つくっておくと、インポート／エクスポート先の接続文字列を共有せずに、組織内のデータソースなどへの接続権限管理ができるようになります。
:::

## Workflowの作成をする

Authenticationsを作成したら、次はWorkflowの作成です。

次は**Data Workbench**内の**Workflows**をクリック。右上の**New Workflow**を押してWorkflows作成を開始します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/8eac4da3-5bb7-d8f8-7580-0029db757ddc.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/84a46ffb-5e76-fc18-162e-24366598bed5.png)

エクスポート用の書き方は、Treasure Data CDPのベストプラクティスがつまっているGitHub、「Treasure Boxes」を参照します。

https://github.com/treasure-data/treasure-boxes

今回は下記URLにAzure Blob Storageの記述例があるので、これをもとにいじっていきます。
事前にAzure側でContainerを作成しておきましょう。

https://github.com/treasure-data/treasure-boxes/blob/master/td/microsoft-azure-blob-storage/td_azure_blob_storage.dig

```digdag
_export:
  td:
    database: <your_database>

+export_to_azure:
  td>:
  query: select * from <your_table>
  result_connection: <your_Authentications_name>
  result_settings: 
    container: testtd
    path_prefix: /file_${moment(session_time).format("YYYYMMDD")}
    file_ext: csv.gz
    format: csv
    delimiter: ","
    null_string: ""
    newline: CRLF
```

これで最低限のものが作成できました。
フォルダパス及びファイル名はTreasure Data CDPに組み込まれているmoment.jsを使用して、実行時の日付がファイル名になるようになっています。

https://momentjs.com/

## 実行結果

Azure Blob StorageにFileがエクスポートされているのが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/48fd6689-1e24-68dc-ab98-ba58cf312b49.png)

# 今後の方針

* 定期実行をcronでコントロールする。
* Queryを直書きではなく、別ファイルに分けて管理。
* 1つのワークフローで複数のデータベースをエクスポートするようにしたい。

# おわりに

触ってみるのが一番理解が進みますよね。教科書ばかり読んでもできるようにはならないね🤔
[正規表現]小数値が指定のケタ数・指定の範囲内を判定する

## 要件（やりたいこと）
* 小数値で0~99.999の範囲かを判定したい。
  * 実現方法は問わないが、今回は正規表現を使うことにした。
* 数字は半角数字のみ。全角はNG。
* 小数は第3桁まで。

## 要件の例示
* OK例
  * `0`, `0.1`, `0.01`, `0.001`, `99`, `99.9`, `99.99`, `99.999` 
  * これも許容してOKとする。`0.0`, `0.00`, `0.000`
* NG例
  * 3桁以上の数
    * `100`, `1000`
  * 小数第4桁以上の数
  　* `0.0001`, `99.9999`, `0.0000`
  * 負の数
    * `-1`
  * 数字以外の文字
    * `あ`, `日本`
  * 全角数字
    * `０`, `０。１`
  * .から始まる数字
    * `.99`
  * 0から始まる数字
    * `00`,`000`,`01`, `001`

## Code

Javascriptで定義して、使用する画面で`toThreeDecimalPlaces.test(value)`をするイメージ。

```Javascript
const toThreeDecimalPlaces = /^(0|[1-9]\d{0,1})(\.\d{1,3}|)$/;
```
JavaScriptモダンプログラミング完全ガイドの演習問題の解答


# 演習問題の解答作成中です
以下のgitレポジトリにJavaScriptモダンプログラミング完全ガイドの演習問題の解答を自作しています(現在2章まで、今後全部解いていく予定です)。
[JavaScriptモダンプログラミング完全ガイドの演習問題の解答](https://github.com/sobatha/modern_javascript_solutions)


 
解答に不正確な点、別解などあればご指摘いただけますと幸いです。

出版社様のサイト https://book.impress.co.jp/books/1120101055
Rails×MySQL　dockerで開発環境を構築する

# 今回指定したバージョン
- Rails version 6.1.7.1
- Ruby version 2.7.7
- MySQLは最新version
- nodejsは互換性のある version16
# 条件
- docker-compose upでrails serverを起動できるようにすること
- ホストのファイルシステムとコンテナのファイルシステムを同期させること

## Dockerfile
- まずは、apt-getでyarnを入れたもの
```ruby
# Node.js & Yarn
FROM node:16-buster-slim
RUN yarn install

FROM ruby:2.7.7
RUN apt-get update
RUN apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs \
    default-mysql-client \
    yarn
    default-mysql-client 

WORKDIR /rails-docker-mysql
COPY Gemfile Gemfile.lock /rails-docker-mysql/
```


- 　そしてこちらがyarnをマルチステージビルドで別途入れたもの
```ruby
# Node.js&yarn
FROM node:16 as node
FROM ruby:2.7.7

COPY --from=node /opt/yarn-* /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
RUN ln -fs /opt/yarn/bin/yarn /usr/local/bin/yarn \
  && ln -fs /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg

# Rails
RUN apt-get update
RUN apt-get install -y \
    build-essential \
    default-mysql-client

WORKDIR /rails-docker-mysql
COPY Gemfile Gemfile.lock /rails-docker-mysql/
RUN bundle install
```
- yarnをapt-getで入れるとapt-getのバージョンに引っ張られるといった指摘を受けましたのでシンボリックリンクを作成し修正しました。
　※シンボリックリンクとは、オペレーティングシステム（OS）のファイルシステムの機能の一つで、特定のファイルやディレクトリを指し示す別のファイルを作成し、それを通じて本体を参照できるようにする仕組みのことです。
- `docker compose run --rm web bin/setup`を実行することでyarn installされるようにしました
## docker-compose.yml
```ruby
version: "3"

volumes:
  data:

services:
  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"

    ports:
      - "3000:3000"
    volumes:
      - ".:/rails-docker-mysql"
    environment:
      - "DATABASE_PASSWORD=password"
    tty: true
    stdin_open: true
    depends_on:
      - db

  db:
    image: mysql
    volumes:
      - "data:/var/lib/mysql"
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
```
- docker-compose upでrailsプロセスとdbが起動し、http://localhost:3000 でアクセスできるようにしました
- 起動2回目で
```ruby
A server is already running. Check /rails-docker-mysql/tmp/pids/server.pid.
```
とエラーになってしまう事があるのでcommandに
```
/bin/sh -c "rm -f tmp/pids/server.pid 
```
と記述しwebサーバー起動時にpidファイルのキャッシュを削除されるようにしました

# 参考
https://docs.docker.jp/compose/rails.html

https://www.udemy.com/course/aidocker/

udemyの教材はおすすめです！
AdGuard Homeをインストールして特定のサイトをブロックしてみた

AdGuard Homeという特定のDNSレベルでブロックするツールを知りました
実験してみたいと思います

僕の場合は、なんとなく見たくないサイトを入れて抑制するによいかなーとこのようなツールを探してました
ただ、IPアドレスをhostsで書き換えるだけだとipが順番に書き換わるだけで実際はブロックできません
そのためDNSで判断するしか方法がありませんでした
それを解決できます


インストール
Ubuntu Softwareからインストールします
![Screenshot from 2023-01-29 22-27-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/c169372a-a44e-857d-900f-286ec2fcdf31.png)
インストールをして初期設定をする（スクショ取り忘れたが、インターフェースの設定をするぐらい）


ネットワークの設定のDNSを書き換えます
本来はルータのDNS設定を書き換えますが、実験のために実行してるコンピュータのネットワーク設定を書き換えました
![Screenshot from 2023-01-29 22-29-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/2a68e7a7-36ed-ca59-9749-5f83eec76ea3.png)

上流のDNSサーバの設定
今回は8.8.8.8を使ってみました
![Screenshot from 2023-01-29 22-42-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/991203a1-9787-77e7-f695-b02bbdfc3e4e.png)


実験に下記のDNSをブロックしてみます
![Screenshot from 2023-01-29 22-28-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/d17b2f9e-f503-42c7-bbb8-0c8cf3fe7f19.png)

実際に対象のサイトを見ようとするとブロックされました
ブロック対象は127.0.0.1（ローカルホスト）に変換される
![Screenshot from 2023-01-29 22-30-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/63c1a7c8-3182-a52d-132e-7dad62e81b10.png)

対象外のサイトは正しく見れました
![Screenshot from 2023-01-29 22-31-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/1ad9987e-0d38-c02c-795b-75d8907fb657.png)
Javaプログラムからwindowsバッチファイルを実行する

実務でJavaプログラムからバッチファイルを実行する処理が実装されていたので備忘録として簡単なサンプルを残しておく。

今回はA5M2.exeを起動するバッチファイルをJavaから起動する処理を実装した。

なぜA5M2なのは特に理由はない。

実装する処理の流れは以下の通り。

①バッチファイルを起動するJavaプログラムを実行

②バッチファイルからA5M2.exeを起動



# Javaプログラムの実装

Javaのソースは下記の通り

``` sample.java
public class Sample {

	public static void main(String[] args) {
		try {
			ProcessBuilder pb = new ProcessBuilder("C:\\Users\\User\\Desktop\\hello.bat");
			Process process = pb.start();

			int result = process.waitFor();
			System.out.println("戻り値：" + result);
		} catch(Exception e) {
			System.out.println(e.toString());
			System.out.println("プロセス起動失敗");
		}
	}
}
```

ProcessBuilderはプロセスの起動などに使用することができるクラスである。

インスタンスを宣言するときに引数で実行したいコマンドを文字列でセットする。

インスタンス生成後にstartメソッドでコマンドを実行する。

戻り値が返ってくるのでProcessクラスの変数に代入する。

process.waitForメソッドは起動したプロセスが終了するまでの間、現在のスレッドを待機させることができるメソッド。

戻り値としてプロセスの終了コードが返ってくる。
0の場合は正常に終了している。




# バッチファイルの実装


A5M2を起動するだけなので、startでディレクトリを指定するだけで起動できる。

``` sample.bat
start "" C:\任意のディレクトリ\A5M2.exe

```

# 実行してみる

実際にJavaプログラムを実行してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/82dc8fa1-81f5-7a8f-a061-3a039971d89f.png)


実行後、A5M2を起動することに成功。

eclipseのコンソールでも終了コード0が返ってきていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/bec56eb0-a68b-3abf-87d9-149336d252e8.png)


今回は非常に簡単だが、うまく活用すればいろんなことを効率化できそうなのでいろいろやってみると良いかもしれない。
CSV Populateを試してみた

### 本記事について
Figmaのプラグイン機能CSV Populateを試した経緯や手順について書いています。
※Figmaのプラグインとは、Figma内でデザイン制作する際に利用できる拡張機能の総称です。


### 誰のための記事？
「KA法などを使ってリサーチ結果を分類、分析している方」
「csvやExcel、GoogleSpreadSheetなどのデータを付箋に起こすのが面倒な方」
「作業の時間を減らして頭で考えたり、構想を練る時間が欲しい方」

### CSV Populateを試してみた
試してみようと思ったのは、UXデザインのイベントでCSV Populateを使用して一瞬でFigma上の付箋にデータ起こせていたのがすごいと思ったのがきっかけです。私はUXリサーチャーというお仕事をしています。お仕事の中で、ユーザーインタビューやアンケート結果をKA法などを使用して分析することがあります。その際、GoogleSpreadSheetなどに入った大量のデータを分類するのはSheet上では見辛く、やりづらいです。以前、FigmaのGoogle Sheet　Syncというプラグインを試しましたが、それよりも便利だと思いました。

#### CSV Populateとは？
CSVデータをテキストレイヤーに入力し、新しい要素を自動生成するFigmaのプラグインです。
![スクリーンショット 2023-01-29 20.53.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/6beeb0d2-4bf1-a054-4cb8-89b808f037a6.png)
[参考：CSV Populateサイト](https://www.figma.com/community/plugin/875365065394448755/CSV-Populate)

### 準備するもの
- 分析分類したいcsvデータ(インタビューやアンケートのデータ）
- FigmaのDesign File

### 手順

* CSV ファイルを作成またはExcelやGoogleSpreadSheetからエクスポートします。
参考：元データ（内容はフィクションです。）
![スクリーンショット 2023-01-29 22.07.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/65679b72-c0c8-2fa9-aaf5-790a05fa2cce.png)
CSVダウンロード方法
![スクリーンショット 2023-01-29 21.15.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/c7d39b30-20d3-ad41-f444-f08ce88c6fca.png)

* FigmaのプラグインからCSV Populateを選択します。
![スクリーンショット 2023-01-29 21.16.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/ab4ec34e-3d4f-ec64-d8b9-a3d8e13e0b39.png)

* Figmaのテキストレイヤーの名前をCSVのヘッダーに合わせて変更し、データを適用させたい場所の頭に "#"を付けます。
![スクリーンショット 2023-01-29 21.17.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/b2254940-538a-339b-f9b0-898111649a3a.png)

* クローンしたい要素のトップレベルとテキストレイヤーを検索するプラグインを選択し、反映させたいCSVファイルを選択します。
![スクリーンショット 2023-01-29 21.20.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/7244fb19-5d22-faa8-426b-421114e04ace.png)

* Populateボタンを押します。
  ※一瞬なので瞬きせずにご覧ください。
![csvpopulate_test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/f66dcabd-5cef-ca43-e1c6-f2336831a917.gif)

後は書き出した付箋に対して、コード化、カテゴリー化を行っていきます。
少しでもリサーチや作業工数が膨大になっている方のヒントになれば幸いです。

### 注意点
- 情報が同期している必要がないもの(後から元データの値が変わるものには向いていません）
- 後から元データと照合して振り返れるようナンバリングいただくことをおすすめします。


以上。
【Java基礎】入力フォームを使おう

［問題］　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksBasic.html)
数値を入力させ、その入力値を表示するプログラムを作成しなさい。

# コード
```php
import java.util.*;
public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        System.out.println(t);
    }
}
```

↓　入力フォームに「56」と入力

# 結果
```
56
```

文字列の場合は
```java
import java.util.*;
public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        String t = sc.next();//intがStringに、nextIntがnextになる
        System.out.println(t);
    }
}
```
少し異なるので注意。


★import java.util.*;　＝これから使用する関数を宣言
★Scanner　＝入力フォームの値を持ってくる
【Ubuntu】Terminalでvboxuser is not the sudoers file. This incident will be reported.とエラーが出る / Ubuntu上でIPアドレスを確認すると10.0.2.15になっている

最近友達といつでもマイクラを遊べるように、Ubuntuでマイクラサーバーを構築しました。
構築手順などは先駆者様の記事が非常に参考になりましたが、エラーの解消法については、あまり記載がありませんでしたので実際に起きたエラーと解消法についてまとめました。

# sudoコマンドが使えないときの解消法
```
vboxuser is not the sudoers file. This incident will be reported.
```
sudoコマンドが使えないとき上記のようなエラーが出ます。
原因としてvboxuserがsudoできるグループに所属していないため起きているエラーです。
対処として、まずrootユーザーに切り替えます。

```
vboxuser@Ubuntu2204:~$ su
```
するとパスワードを求められるため、Ubuntuにログインする際に使用したパスワードを入力してください。
次にsudo権限をユーザーに付与します。

```
root@Ubuntu2204:~$ usermod -G sudo vboxuser 
```
指定のユーザーに権限を付与されているか確認します。
```
root@Ubuntu2204:~$ cat /etc/group
sudo:x:27:vboxuser
```
上記のように表示されていたらsudoを使えるようになっています。
最後に指定のユーザーに戻ります。
```
root@Ubuntu2204:~$ su vboxuser 
vboxuser@Ubuntu2204:~$ 
```
以上で完了です。


# Ubuntu上でIPアドレスを確認すると10.0.2.15になっている
サーバーを立ててローカルで接続テストを行うと、サーバーに接続できずIPアドレスを確認したところ謎のアドレスが表示されていました。
これはVirtualBoxの初期設定でネットワークアダプタの割当がNATになっており、ゲストOSとホストOSが同一ネットワークとして認識されていないのが原因でした。
解消法として、ネットワークの割り当てをブリッジアダプターに変更すると接続できるようになります。
**VirtualBox設定 → ネットワーク → 割り当てをNATからブリッジアダプターに変更**
以上で完了です。
![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2280983/e821981c-06b8-2e6b-0e5d-2417de974d6d.png)

以上になります。
VirtualBox・Ubuntu初学者の方の参考になれば幸いです。
mocopi のアニメーションデータbvhをfbxに変換する

## はじめに
Sony製モーションキャプチャデバイス「[mocopi](https://www.sony.jp/mocopi/)」はモーションデータをbvh形式で保存できます。
Unityでモーションデータを読み込むにあたり、Blenderを使用してbvhをfbxに変換します。
毎回同じ手順を繰り返すのは面倒なのでスクリプトを作成しました。

## モーションデータの保存場所
> ヒント
> データ（BVHファイル）は、スマートフォンの下記の場所に保存されます。
> iPhone：mocopiフォルダのMotionData配下
> Android：ユーザーが初回保存時に指定したフォルダ配下

https://helpguide.sony.net/mobile/qm-ss1/v1/ja/print.pdf

## スクリプト
https://gist.github.com/afjk/8bf1dd3eb6c42af7dcae76246ad9401b

## 実行方法
Blenderのインストールパスは実際のパスに読み替えてください。
* mac
```
/Applications/Blender.app/Contents/MacOS/Blender -b -P mocopi_bvh_fbx_converter.py -- MCPM_yyyyMMdd_HHmmss.BVH
```
* windows
```
"c:\Program Files (x86)\Steam\steamapps\common\Blender\blender.exe" -b -P mocopi_bvh_fbx_converter.py -- MCPM_yyyyMMdd_HHmmss.BVH
```

実行すると、bvhファイルと同名の.fbxファイルが同一フォルダに保存されます。

## 解説
Blenderをコマンドライン/Terminalから実行しています。
* オプション
-b、--background
バックグラウンドで実行します
-P、--python <filepath>
指定された Python スクリプト ファイルを実行します。

スクリプトでは、frame rateを50fpsに変更し、指定したbvhファイルをインポート、fbxへARMATUREのみを指定してエクスポートしています。


## 参考
https://docs.blender.org/manual/en/3.3/advanced/command_line/arguments.html

https://docs.blender.org/api/current/bpy.ops.import_anim.html#bpy.ops.import_anim.bvh

https://docs.blender.org/api/current/bpy.ops.export_scene.html#bpy.ops.export_scene.fbx

https://nn-hokuson.hatenablog.com/entry/2016/07/21/212313
iPhoneの画像ファイル(HEIC)をコマンドラインでJPEGに変換する

## 免許証を更新したかった

久しぶりにカーシェアのマイページを覗いたところ、免許証の期限切れとの文言。
そういえば去年免許更新してたな…ということで、

* iPhoneで新しい免許証を撮影
* Google Photosに連携
* MacにDL
* サイトにアップロード ← 失敗

よくよく見ると、拡張子が.heicになっていた。なんやそれ…

## HEICとは

* HEIF (High Efficiency Image File Format) という画像用メディアフォーマットがあり、それの拡張子がHEIC
* iOS11以降で利用されるようになったっぽい

参考: https://support.apple.com/ja-jp/HT207022

うーん知らない子ですが、iOS11って言えばだいぶ前ですねｗ

## Let's convert HEIC to JPEG

ググるとフリーソフトだったりオンライン変換だったり色々出てくるのですが、
昨今の画像AI・編集アプリの流行→実は利用規約に「アップロードした画像は全部こっちで勝手に使うやで（・∀・）ﾆﾔﾆﾔ 」
みたいなのが散見されるし、コマンドラインで一発で出来ないかなぁとググった結果、
Macの標準コマンド(sips)で行けそうだったのでメモ。

### sipsコマンド
以下で変換できます

```bash:
sips -s format jpeg IMG_hoge.HEIC --out IMG_hoge.jpg
```

オプション

* -s format [出力形式] → 出力する画像フォーマットの指定。 jpeg | tiff | png | gif | jp2 | pict | bmp | qtif | psd | sgi | tga に変換できるっぽい(環境によって違うかも)
* --out [出力ファイル名] → 出力ファイル名を指定。

## 最後に
アプリとかSNSとか色々便利な世の中だけど、個人情報の扱いは慎重にね！！！(気にしすぎるとクラウドもどうなんって話になりますが)
SIMの中身(EF)を読めるようになろう！

SIMの中身はASN.1という古の言語で書かれていて、読めないのでまずは標準から確認したいと思います。。

https://qiita.com/nekokane/items/3d2e33f9b834b2412ab0
上記のIIJ mioミーティングでおすすめされていた標準を読みたいと思います。
SIM初心者はまず下記を読むといいらしい。
　3GPP TS 23.038 (SIM)
　3GPP TS 31.102(USIM)
　ETSI 102.221(基本)

# 参考文献
[1]esim.me(物理eSIMカード)を試してみた&中身を覗いてみた omusubi5g
　https://omusubi5g.hatenablog.com/entry/2023/01/20/160150
[2]3GPP TS31.101 V16.2 (2021-06)　	UICC-terminal interface
　https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1802
[3]ETSI TS 102 221 V15.0.0 (2018-07) 
　https://www.etsi.org/deliver/etsi_ts/102200_102299/102221/15.00.00_60/ts_102221v150000p.pdf
[4]ITU-T  E.118 
  https://www.itu.int/rec/T-REC-E.118-200605-I/en
[5]ETSI TS 31.102 	Characteristics of USIM 16.13.0
  　https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1803
[6]IIJ eSIMについて
　https://www.iij.ad.jp/dev/tech/techday/2018/pdf/TD2018_6.pdf

# サマリ
　鍵情報が入っているEFが見つからない。


# 詳細

## 3GPP TS31.101 
あまり中身は無くて、TS 102 221の参照がほとんど。
### 4.2. platform over view
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/67f3dbeb-be48-0e69-f4d3-0c0bc1ce632f.png)
>図は[2]より引用

### 11 Command
 SELECT, STATSU, READ, UPDATE等
 
## ETSI TS 102 221
　SIMのデータの中身EFの定義は一部ここにある
### 13 Application independent files 

#### 13.2 EFICCID (ICC Identification) 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/91953ee6-519b-7ee2-43c8-f4f789951c9d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/e50c951f-2de3-676d-06f0-084c31cc5cf0.png)

値： ITU-T E.118 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/8b19beb9-c3e5-6d7e-184b-5af8dae2d49a.png)
19文字
先頭から
89：テレコム向け、3桁Cuntry code 日本:440、Issure id、識別番号

## 3GPP TS31.102
### 4.2.2	EFIMSI (IMSI)
1Byte : Length of IMSI
2 to 9 byte : IMSI

　IMSIの1Byte目はLengthだったのか納得。

Coding 
 1 0 0 Prity IMSI
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/1f4cb4f6-484a-b0c4-da03-b4c84e73226a.png)

Ki/OPC はどこだー
[6]より、PE-AKAParameterにありそう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/4ef6173a-9c76-9ce5-7979-4e2fa19b23e2.png)
任意のポートを Listen しているプロセス名を特定する

BSD 系 netstat はポートを listen しているプロセス名の特定が出来ないため、 `lsof` コマンドを使用する。
```zshsh
$ netstat -ant | grep 9150
tcp4       0      0  127.0.0.1.9150         *.*                    LISTEN
tcp4       0      0  127.0.0.1.55383        127.0.0.1.9150         TIME_WAIT
```

調べたいポート番号を特定したら、 `lsof -n -P -i {:port_number}` で実行する

```zsh
$ sudo lsof -n -P -i :9150
Password:
COMMAND    PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
tor.real 15823 centipede   30u  IPv4 0x58bcd40ad1745305      0t0  TCP 127.0.0.1:9150 (LISTEN)
```

とする。

| オプション | 効果 |
|:-:|:-:|
| -n | IPアドレスを表示する（名前解決しない） |
| -P | ポート番号をサービス名に変換しない |
| -i | ポート番号を指定する |
【Android】Groupについて

# はじめに
前回、前々回とXML上で利用できるGuidelineとBarrierという補助線についての記事を書きました
[【Android】Guidelineとは【Kotlin】](https://qiita.com/Tsubasa12/items/04a3676922cbfe2a7ba3)
[【Android】Barrierとは【kotlin】](https://qiita.com/Tsubasa12/items/a73448cf2ca261ff4d87)
それと関連したもので、今回はGroup　について記事にしようと思います。

# Group
Groupとは、簡単に言うと いくつかのViewを一つの指示で同時に操作できるようなものです。
例えば、画面に表示されたViewをすべてGONEにしたい場合にそれぞれのViewにGONEの指示を出すのではなく、けしたいView達を一括りにしたGroupに対してGONEの指示を出すだけでそれらを画面上から非表示にすることができます。


使用方法は

```
<androidx.constraintlayout.widget.Group
　　　　　　 android:id="@+id/group"
            app:constraint_referenced_ids="" />

```
""内にGroupにしたいViewのidを追加します。

```
findViewById<Group>(R.id.group).visibility = View.GONE
```

とするとViewをGONEにすることができます。

# 参考

https://tech.excite.co.jp/entry/2021/04/22/141007

https://developer.android.com/reference/androidx/constraintlayout/widget/Group

# おわりに
Groupを知ったことでConstraintLayoutでの入れ子問題やそれぞれのViewに対して指示を書かなくてはならないということが減って　コードは簡潔にできすることができますね。
Layout関係は以前 一から触る機会があったのでもっと早く勉強しておけばよかったと思った内容でした！
expoで作成したテンプレートが何もしていないのに動かない！

# 問題

エラーが出てExpo startが失敗する
`
Error: Cannot find module '@expo/config/paths'
`
# 原因

エラーの詳細を見ると
```
Error: Cannot find module '@expo/config/paths'
Require stack:
- /Users/hogehoge/node_modules/@expo/webpack-config/webpack/index.js
- /Users/hogehoge/node_modules/@expo/webpack-config/webpack.config.js
- /Users/hogehoge/Documents/Expo/nest-navigation/node_modules/@expo/cli/build/src/start/server/webpack/resolveFromProject.js
- /Users/hogehoge/Documents/Expo/nest-navigation/node_modules/@expo/cli/build/src/start/server/webpack/WebpackBundlerDevServer.js
- /Users/hogehoge/Documents/Expo/nest-navigation/node_modules/@expo/cli/build/src/start/server/DevServerManager.js
- /Users/hogehoge/Documents/Expo/nest-navigation/node_modules/@expo/cli/build/src/start/startAsync.js
- /Users/hogehoge/Documents/Expo/nest-navigation/node_modules/@expo/cli/build/src/start/index.js
- /Users/hogehoge/Documents/Expo/nest-navigation/node_modules/@expo/cli/build/bin/cli
```
こんなかんじでした．途中までローカルにインストールされたモジュールを参照しており，
@expo/webpack-configからグローバルのモジュールを参照していますね．
/Users/hogehoge/node_modules/@expo/webpack-config/webpack/index.js をみてみると
```
const paths_1 = require("@expo/config/paths");
```
となっており，@expo/configが無いぞということで確認したら，
グローバルには存在していませんでしたのでインストール
今回は，ローカルのみのインストールなので以下を実行すると解決しました
```
npx expo install @expo/webpack-config
```
アセットパイプラインについてと、Railsの画像保存場所

# はじめに


#### <font color="red">※以下の内容には誤りが含まれる可能性があります</font>

Railsで画像を使った際、アセットパイプラインについて調べたことをまとめました。


# 具体的な内容




## アセットパイプラインとは


JavaScriptやCSSのアセットの最小化または圧縮して連結する工程のことです。


この機能でブラウザがWebページをレンダリングするためのリクエスト数を減らすことができます。


Webブラウザが同時に処理できるリクエスト数には限りがあるので、同時リクエスト数を


減らすことができればその分読み込みが高速になります。


## Sporocketsとは


Gemの１つで、Sporoketsを使いアセットパイプラインをしています。


ですが、Rails6系からはwebpackというモジュールバンドラを使用することが多くなっ


ています。役割としてはSporoketsと同じで複数あるJavaScriptファイルを１つにま

とめることができます。


違うのはJavaScriptの依存関係を考慮しながら管理してくれるところです。


そしてRails６からはデフォルトでWebpackerというGemが用意されているので導入しなくてもいいです。プリコンパイルもJavaScriptの依存関係も管理してくれます。



# 補足として


Railsのアプリケーション内で使用する画像の設置場所はassets配下とpublic配下があります。このとき、assets配下に置く場合はアセットパイプラインの対象となります。



# まとめ



- アセットパイプラインをすることでブラウザの読み込みが早くなる。
- Sporoketsを使いアセットパイプラインをしている。
- Rails6からはデフォルトでWebpackerが用意されている。
- 画像をassets配下に置く場合は、アセットパイプラインの対象となる。


## 最後に


Webpackerについてはまだ知識が深まっていないので詳細は省きます。
その他、モジュールバンドラ、Webpackなども同様です。
Swift iPad設定、ディスプレイ拡大表示「スペースを拡大」のサイズは？



![](https://kumonosu.cloudsquare.jp/wordpress/wp-content/uploads/2023/01/ipad_space_max.png)

## サイズ表示コード
```swift
print("Device:\(UIScreen.main.bounds.size)")
```

## サイズ
iPad Pro 12.9 横向き
デフォルト：Device:(1366.0, 1024.0)
スペースを拡大：Device:(1590.0, 1192.0)
学び カスタムオブジェクト

今日の学び
オブジェクトとは？
標準オブジェクトとカスタムオブジェクト


1.オブジェクトとは
→Salesforce上で管理したい概念のこと(直訳は物体だが概念がしっくりくる。なんでもオブジェクトになりうる)

2.標準オブジェクトとカスタムオブジェクト
標準オブジェクトはSalesforceで元々設定されているオブジェクト。toBの営業支援を想定されているので「取引先」や「取引先責任者」等がある。
カスタムオブジェクトは、ユーザー側で新しく作れるオブジェクト。必須項目のIDや名前やシステムの項目があるが、それ以外には自分で管理する項目やデータの持ち方を設定できる。
例えば、訪問看護事業所でSalesforceを導入するなら、患者を中心に、様々なステークホルダーを作る必要がある。 患者Obj/病院obj/居宅介護支援事業所obj/介護施設obj

ベストプラクティスは管理するためによく考えて名前をつけること
Strix Cloudのログレベルが適切に設定出来ない時

Strix Cloudって何？という方は、前にStrix Cloudについての記事を投稿したのでそちらを御覧ください。

https://qiita.com/HarumaroJP/items/cf9034bcf7f5e73d2b5e

記事で使用しているバージョン
- Unity 2020.3.5f1
- StrixUnitySDK 1.5.0

## Strix Cloudのログシステムについて

Strix Cloudにはログシステムという便利なログ機能があります。

https://www.strixengine.com/doc/unity/guide/ja/unitysdk/debugging/loglevel.html

ログシステムは個別の機能ごとにロガーを作成することが出来ます。
即ち、**一部のStrixの機能のロガーのみを有効化**し、ログの可読性を向上させるといったことが可能です。

また、ロガーには**ログレベル(Filter)** が設けられていて、警告レベル以上のログのみ表示することもできます。
しかし、このログレベルの設定が厄介だったので、ここでしっかりまとめておきます。

## ログレベルが適切に設定出来なかった

以下のコードでログレベルを警告レベルに引き上げようとします。
`LogManager.Instance.Filter = Level.WARNING;`
ですが、設定後のログでも、それ以下のINFOレベルのログが表示されてしまいました。

ログシステムの内部実装を追ってみます。

### LogManagerとLogger
それぞれのLoggerはLogManagerクラスによって管理されています。
- LogManager
    - Logger: StrixReplicator
    - Logger: StrixBehaviour
    - Logger: AbstractNetworkStrategy 
    - etc.. 

そして、それぞれのロガーにもログレベルが設定されています。
ロガーごとのログレベルは、**ロガーを作成した時点での`LogManager.Filter`が適用されます**。

従って、今回の問題は以下の流れで発生していたようです。
1. `LogManager.Filter`に`Level.INFO`が設定される。(初期値は`INFO`)
2. StrixCloudの機能のロガーが作成される。
3. ロガーのログレベルに`Level.INFO`が適用される。
4. `LogManager.Filter`に`Level.WARNING`を設定し、ログレベルを引き上げる。
5. ログを出力するが、**作成時に`Level.INFO`が設定されていたため**、それを優先して出力する。

## 解決策

StrixCloudの機能を用いる前に初期化するべきでした。
機能を用いた時点でロガーが生成されてしまうため、起動時にAwake()などの初期化関数でログレベルを設定すれば、正常に動作します。

任意のタイミングで設定したい場合は、ロガー全てのログレベルを書き換えるのも手です
```C#
public void SetLoggersLevel(Level logLevel)
{
    foreach (Logger logger in LogManager.Instance.GetLoggers().Values)
    {
        logger.Filter = logLevel;
    }
}
```

### これでも思い通りにならない場合は
> 5.ログを出力するが、**作成時に`Level.INFO`が設定されていたため**、それを優先して出力する。

優先して出力すると書いたのは、ロガーのログレベルよりLogManagerのログレベルが優先される場合があるからです。
Loggerクラスに書かれているログの出力条件は以下です。
```C#
logLevel >= this.Filter || logLevel >= LogManager.Instance.Filter
```
Loggerのログレベル以上または、LogManagerのログレベル以上のときに出力されるようです。
常にログレベルが低い方が優先されるので、
`Logger.Filter == Level.WARNING && LogManager.Filter == Level.INFO`の時は`LogManager.Filter`が優先され
`Logger.Filter == Level.INFO && LogManager.Filter == Level.WARNING`の時は`Logger.Filter`が優先されるということですね。

ドキュメントには詳細に書かれていないので、初見だと詰まりそう...
【Java基礎】割り算の余りを求める

［問題］　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksBasic.html)
15000を7で割った余りを表示するプログラムを作成しなさい。

# コード
```php
public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(15000 % 7);
    }
}
```

# 結果
```
6
```

★ a % b ＝aをbで割った余り
【2023年版】【GAS, LINE Notify, Gmail】gmailの特定のメールをLine通知する方法

## 結論
下記コードをGASに記述するとokです
```javascript
//LINEにメッセージを送信する
function sendLineMessage(message) {
  // lineのtokenをhogeの代わりに入れる
  const LINE_NOTIFY_TOKEN = "hoge";
  const Authorization = `Bearer ${LINE_NOTIFY_TOKEN}`
  // エンドポイントが変わったら下記変更
  const LINE_ENDPOINT = "https://notify-api.line.me/api/notify"

  const option = {
    "method": "post",
    "headers": {Authorization},
    "payload": {message}
  }
  let response = UrlFetchApp.fetch(LINE_ENDPOINT, option);
}

//メールをチェックし条件に該当するメールをLINEに通知する
function main() {
  let now = new Date();
  let monthStartDate = new Date(now.getFullYear(), now.getMonth(), 1);
  let monthEndDate = new Date(now.getFullYear(), now.getMonth() + 1, -1);
  let firstDay = Utilities.formatDate(monthStartDate, 'Asia/Tokyo', 'yyyy/MM/dd')
  let endDay = Utilities.formatDate(monthEndDate, 'Asia/Tokyo', 'yyyy/MM/dd')

  let query = "is:unread subject:{(検索タイトルA)(検索タイトルB)} after:" + firstDay + "before:" + endDay + "";
  console.log(query)

  //指定した条件でスレッドを検索して取得 
  let myThreads = GmailApp.search(query);
  let threads = GmailApp.getMessagesForThreads(myThreads);
  // threadsは2次元配列
  threads.forEach(messages => {
      // 良くわからないが0番目取得w
      let msg = messages[0]
      // msgはclass
      console.log(msg.getSubject())
      sendLineMessage(msg.getSubject())
      // 既読にする
      // msg.markRead()
    })
  })
}
```
僕の環境で動いたコード載せときます。
![スクリーンショット 2023-01-29 21.11.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121605/e1d03ef4-2d19-96a4-01ab-db1133f04d58.png)


## lineに通知するためのすること
1. line notifyでtoken取得
2. Lineアプリで通知したいline グループに「LINE Notify」を追加
![スクリーンショット 2023-01-29 21.14.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121605/784e09e7-c51b-bf00-90e9-ecc1d64a0afb.png)
3. gmailの特定のメールがどの検索でマッチするか探す
4. gasコーディング


## 参考にしたサイト
// 参考 コードを参考にしたのはこのひと
https://pg-log.com/gas-gmail-to-line/

// 参考 Gmailの検索条件
https://www-creators.com/archives/5841#:~:text=%E3%81%A6%E3%81%84%E3%81%8D%E3%81%BE%E3%81%97%E3%82%87%E3%81%86%E3%80%82-,%E3%80%8C%E3%81%BE%E3%81%9F%E3%81%AF%20(or)%E3%80%8D%E6%9D%A1%E4%BB%B6%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E3%83%A1%E3%83%BC%E3%83%AB,%E3%81%AE%E6%8B%AC%E5%BC%A7%E3%82%92%E4%BD%BF%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

// 参考 Line token取得するところ
https://notify-bot.line.me/ja/

// 参考 GmailApp class参考
https://tonari-it.com/gas-gmail-search-thread/#toc5


## 注意点など
### 1. threadsの中身見ないと時間ロスするかも知れない説
main関数の最後付近でthreadsをfor文回してますが、2次元配列になってたり中身が辞書でvalueのところが関数になってる感じなのでlog見ながらが進めた方が良かったです。

### 2. 迷ったら「var」でok
かっこつけてjavascriptの新しいの使ってます。ですが他の人のコードは「const」や「let」を「var」で記述しています。ほぼ同じ意味ですが、varで問題ないので良くわからない人はvarでokです。
【Java基礎】数値の入力と文字列の入力の違い

［問題］　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksBasic.html)
1789+1758を計算して結果を表示するプログラムを作成しなさい。

# コード
```PHP
１． 数値として数字を入力する場合
public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(1789+1758);
    }
}

２．文字列として数字を入力する場合
public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("1789+1758");
    }
}

```
# 結果
```
１．　3547
２．　1789+1758
```

★数値として表示させたい、計算させたい時は、'　'を付けない。
Ruby Dateクラス

# Dateクラス
Dateクラスは、Rubyの標準ライブラリの機能です。
これを使うには、下記一文を記述する必要があります。

```ruby
require "date"
```



# Dateクラスを使ったプログラムの例を紹介

```ruby
require "date"
day = Date.today.wday
puts day
```

```
0
# ターミナル出力例
```

***wday***は、曜日を0（日曜日）から６（土曜日）の整数で取得する、Dateクラスに用意されているメソッドです。
上記の記述を実行すると、その日の曜日に合わせた数字がターミナルで出力されます。
今日が日曜日だったら、0が出力されます。

## 0から6の整数ではなく、日曜日, 月曜日, 火曜日, 水曜日, 木曜日, 金曜日, 土曜日　で取得したい場合はどうする？

```ruby
require "date"
day = Date.today.wday
days = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"]

puts days[day]
```

```ruby
日曜日
# ターミナル出力例
```
TerraformでAWSのS3をデプロイする

Terraformシリーズ第六弾は**S3**です。**CloudTrailデータイベント**の設定も含めて記述していきます。:wastebasket:

※過去のTerraform記事はこちら
第一弾：[TerraformでAWSリソースをデプロイしてみる](https://qiita.com/hiyanger/items/ca337f70ad4801072850)
第二弾：[TerraformでAWS環境をデプロイする前に認識しておくべきこと](https://qiita.com/hiyanger/items/9efdc570e6cfed5aab13)
第三弾：[TerraformでAWSのIAMまわりをデプロイする](https://qiita.com/hiyanger/items/8f925e21166461a5ddb1)
第四弾：[TerraformでAWSのネットワークまわりをデプロイする](https://qiita.com/hiyanger/items/cabb1697c29d2ba93b5a)
第五弾：[TerraformでAWSのEC2まわりをデプロイする](https://qiita.com/hiyanger/items/cabb1697c29d2ba93b5a)

## S3
```terraform
#KMS作成（必要なら）
resource "aws_kms_key" "KMS名" {
  policy = templatefile("ディレクトリ/ファイル名.json")
  enable_key_rotation = true #キーローテ（必要なら）
}

#KMSエイリアス作成
resource "aws_kms_alias" "KMS名" {
  name = "alias/KMS名"
  target_key_id = aws_kms_key.example.key_id
}

#バケット作成
resource "aws_s3_bucket" "バケット名" {
  bucket = "バケット名"
  depends_on = [aws_kms_key.example] #KMSキーの指定
  
  #サーバーサイド暗号化（KMS）
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = aws_kms_key.example.arn
        sse_algorithm = "aws:kms"
      }
    }
  }
  versioning {
   enabled = true #バージョニング（必要なら）
  }
}

#パブリックアクセスのブロック（全てOFF前提）
resource "aws_s3_bucket_public_access_block" "バケット名" {
  bucket                  = aws_s3_bucket.example.id
  block_public_acls       = true #パブリックACLをブロック
  block_public_policy     = true #パブリックバケットポリシーをブロック
  ignore_public_acls      = true #S3がこのバケットのパブリックACLを無視
  restrict_public_buckets = true #S3がこのバケットに対してパブリックバケットポリシーを制限
}

#バケットポリシー設定
resource "aws_s3_bucket_policy" "バケット名" {
  bucket = aws_s3_bucket.example.id
  depends_on = [aws_s3_bucket.example]
  policy = templatefile("ディレクトリ/ファイル名.json") #jsonを外だしして指定
}

```

※参考

https://cloud5.jp/terraform-s3/

## AWS CloudTrail データイベント
CloudTrailでオブジェクトログを取得させたい場合は以下を設定します。ログは**データイベントが設定された各バケット→Trail→Trail出力先バケット**の順で流れます。

```terraform
#CloudTrail
resource "aws_cloudtrail" "s3accesslog" {
  name                          = "Trail名-s3accesslog"
  s3_bucket_name                = aws_s3_bucket.example.id #Trail出力先バケット
  kms_key_id                    = aws_kms_key.example.arn #Trail出力先バケットKMS
  include_global_service_events = true #IAMなどのグローバルサービスからログファイルにイベントを公開するか
  is_multi_region_trail         = false #マルチリージョンでの証跡作成
  enable_log_file_validation    = true #ログファイルの整合性検証
  depends_on    = [aws_s3_bucket_policy.example]

  #S3オブジェクトログ取得設定
  event_selector {
    read_write_type           = "All" #Tarilの記録対象
    include_management_events = true #管理イベントの記録

    #オブジェクトログ取得対象バケット（複数前提）
    data_resource {
      type = "AWS::S3::Object"
      values = [
        "arn:aws:s3:::バケット名1/",
        "arn:aws:s3:::バケット名2/"
      ]
    }
  }
}
```

※参考

https://runebook.dev/ja/docs/terraform/providers/aws/r/cloudtrail
仮想スクロール (VirtualScroll) を作ってみる

記載日:2023/1/29

勉強として、Angularを使って仮想スクロールを作ってみました。
仕組みは理解していましたが、実際に作ることで理解が深まったと思います。本ページの最後の方で、デモやソースコードのリンクものせているので、普通のスクロールとの応答差も確認できます。

## 流れ
まず、仮想スクロールとは何かを簡単にふれます。
次に、今回作った仮想スクロールの仕組みの概要を書きます。
最後に、具体的な作り(作成環境、作業の流れ、デモとコード)を記載します。

## 仮想スクロールとは
仮想スクロールは、表示速度を改善するための技術です。
大量のデータを表示しようとすると、画面の表示時にDOM生成に時間がかかることで、ユーザ体験が悪くなることがあります。仮想スクロールでは、表示範囲+αのみをDOM生成することで、画面表示を早くすることができます。

## 作りの概要
仮想スクロールを実現するやり方には色々あると思いますが、今回は以下のものを作りました。

・表示領域の高さを２Xとし、表示領域の上下２Xずつ、計６XのDOMを常に用意する。
　（厳密に言うと、一番上にスクロールされたときは４Xにしています。）
・X分のスクロースが行われる毎にDOMを更新する。
・１行の高さは固定値とする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381309/21b23d2c-2289-5804-2c05-7aafb0910596.png" width=100%>


## 環境
OS : Ubuntu
node.js : 12.22.9
Angular CLI : 15.0.4
Gitインストール済
Githubアカウント作成済
VSCodeインストール済（拡張機能からGit Graphをインストール済）


## 作業の流れ
### 0.高さを決める
以下の高さを決める。
最後に記載のサンプルでは、H=32px、X=160pxとした。
1行の高さ(H)
表示領域の高さ(2X)
表示領域を更新する高さ(X)

### 1.表示領域の、ページトップからの位置を取得する
スクロールイベントをトリガーにするメソッドを用意する。そこでページトップからの位置を取得する。
サンプルでは、高さX分だけスクロールする毎にトップからの位置を取得する。

### 2.表示領域の更新
DOM生成領域オブジェクト(viewport)はページトップからの位置を持つ。html側のコードでは、このオブジェクトのプロパティを参照することで、スクロールに合わせてDOMを更新してくれる。

苦労した点は、DOM生成領域を更新する高さ(X)毎に処理を実行すること。


## デモ、ソースコード
以下、デモページとソースコードのリンクです。
仮想スクロールと通常のスクロールの２つのページを用意しました。(ソースコードでの仮想スクロール部分がある場所は、src/app/pages/virtualscroll/virtualscroll内。)
スマホとかで見た場合には、通常スクロールの方の画面は表示までに結構な時間がかかるかと思いますので、ご承知おきください。
私のスマホでは、表示されるまでに5～10秒ほどかかりました。

デモは[こちら](https://middle-aged-rookie-programmer.github.io/Angular_Sample/)  (リンク先から、"Go VirtualScroll Page" ボタンを押してください。)
ソースコードは[こちら](https://github.com/middle-aged-rookie-programmer/Angular_Sample/tree/main/src/app/pages/virtualscroll/virtualscroll)


## 参考にさせて頂いたサイト
なし
firebase cloud functionsのtypescriptソースをファイル分割する

備忘録。
moduleAとmoduleBをindex.tsで読み込みre:exportする。

~~~typescript:moduleA.ts
import * as functions from "firebase-functions";

export const helloWorldA = functions.https.onRequest((request, response) => {
  functions.logger.info("Hello logs! I'm from module A");
  response.send("Hello from module A");
});

export const waitFunction = functions.https.onRequest(async (request, response)=>{
  functions.logger.info("waiting...");
  await new Promise((resolve)=>setTimeout(resolve, 3000));
  functions.logger.info("done!");
  response.send("ok");
});
~~~

~~~typescript:moduleB.ts
import * as functions from "firebase-functions";

export const helloWorldB = functions.https.onRequest((request, response) => {
  functions.logger.info("Hello logs! I'm from module B");
  response.send("Hello from module B");
});
~~~

~~~typescript:index.ts
import * as functions from "firebase-functions";
export * as moduleA from "./moduleA";
export * as moduleB from "./moduleB";
~~~

exportでas句を用いなければunpackしてexportできる。
動作テストにはfunctions:shellを用いると良い。デフォルトでnpm run shellでビルドと同時にできる。

ちなみにrequire句を用いたりすると型情報が失われるので注意。
typescriptのexportについては下記を参考。
[TypeScript: 38の具体例から学ぶnamed export](https://qiita.com/suin/items/6a1f1a6aba4207c8d632)
WSL2でSMBv1のネットワークドライブをマウントする

WSL2/UbuntuでSMBv1(SMB 1.0/CIFS)を使った古いNASのネットワークドライブをマウントする方法を記載します。

# 環境
今回は2012年頃に発売されたNETGEAR社製の古いNAS「[ReadyNAS DUO v2](https://www.netgear.jp/products/details/RND2000-200AJS.html)」をWindows11上で動作しているUbuntuにマウントします。

| 項目 | 内容 |
|--|--
| ホストOS | Windows 11 Pro | 
| ネットワークドライブ | NAS (ReadyNAS DUO v2 + CIFS/SMB) |
| ネットワークドライブパス | \\\NAS-AA-BB-CC\media |
| WSL2(OS) | Ubuntu 22.04.1 LTS |
| WSL2(マウントポイント) | /mnt/nas |


# ポイント
- cifs-utils をインストールする
- mount コマンドで「-t cifs」と「-o vers=1.0」を指定する

```
$ sudo apt install cifs-utils
$ sudo mkdir <マウントポイント>
$ sudo mount -t cifs -o vers=1.0,username=<ユーザー名>,password=<パスワード> <デバイス名> <マウントポイント>
```

# 例

以下は ReadyNAS DUO v2 のファイルシステムのマウント時に実行したコマンドです。
ReadyNAS DUO v2 のファイルシステムの文字コードがUTF-8のため、「-o iocharset=utf8」を指定しています。

```
$ sudo apt install cifs-utils
$ sudo mkdir /mnt/nas
$ sudo mount -t cifs -o vers=1.0,username=user,password=passwd -o iocharset=utf8 '\\NAS-AA-BB-CC\media' /mnt/nas
```

dfコマンドやlsコマンドで正しくマウントされていることが確認できます。

```
$ df -h /mnt/nas
Filesystem            Size  Used Avail Use% Mounted on
\\NAS-AA-BB-CC\media  2.8T  2.7T   12G 100% /mnt/nas

$ ls /mnt/network
Music  Pictures  Videos
```

以上です。
301リダイレクトはサイト移転などでは絶対にやったほうがいい-杉村恒

サイトを移転するときに

301リダイレクトで転送かける事を忘れている人が少なすぎる。


よくあるのが

shopify や　wix で運営していたサイトを

別のCMSにしたりする場合です。


shopify ⇒　ワードプレスにする場合



shopify のURL

https://abc.com/itemA/  

https://abc.com/itemB/


https://abc.com/itemC/      

とあった場合

何も設定せずに

ワードプレスで同じドメインで移動すると

https://abc.com/itemA/  

https://abc.com/itemB/


https://abc.com/itemC/ 

それぞれにリンクが貼られていない場合

SEO効果が引き継げないし


移転元のURLを知っている人や検索エンジンで認識されたURLがある場合

https://abc.com/itemA/  　に対して　https://abc.com/itemarea/itemA/


などときちんと認識されていないと

コンバージョンするかもしれないユーザーを逃してしまい

大きな損失となります。

ユーザーが来なかったとしても、
リンクが貼られていた場合、　リンクパワーを引き継げないのでもったいないです。


必ずリンクを貼るようにします。

https://rakko.tools/tools/28/

こういうツールをつかって設定するのもいいので

SEOやユーザーを意識する人は、旧URLから新URLの転送をしてみてください。


杉村恒
立ち上げたMySQLコンテナにログインできない時の対処方法

## 状況

`web`というrubyのimageを元にして作られたコンテナから`db`というMySQLのコンテナに`mysql -u root -p`のコマンドを試したところ

```
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")
```

となってログインできなかった。

## 環境

```yml
version: '3'

volumes:
  db-data:

services:
  web:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - '.:/opt'
    environment:
      - DB_USER=root
      - DB_NAME=${DB_NAME}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_HOST=db
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db

  db:
    image: mysql:5.7
    restart: always
    volumes:
      - 'db-data:/var/lib/mysql'
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
    ports:
      - "3306:3306"

```

## 解決策
`web`と`db`のコンテナが違うIPアドレスで起動していた。その為`-h`オプションでhostを指定する。

```bash:コンテナのIPアドレスを表示
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
```

```bash:結果
/rails-docker-mysql_web_1 - 172.30.0.3
/rails-docker-mysql_db_1 - 172.30.0.2
```

以下のコマンドでMySQLにログインできた

```bash
mysql -h 172.30.0.2 -P 3306 --protocol=tcp -u root -p
```

___

[参考にした記事](https://www.baeldung.com/docker-cant-connect-local-mysql)

### 追記

dbのサービス名でアクセス出来ます。

```bash
docker compose run --rm db bash -c "mysql -u root -p -h db"
```