OmniAICreator/Qiita-1.07M huggingface dataset:
ラムダ式でtry-with-resources文にクローズ処理以外の後片付けをさせる方法

# 概要
try-with-resources文の自動クローズを利用するにはリソースにAutoCloseableインターフェースが実装されている必要があるが、このインターフェースを持たないクラスに対してもラムダ式を使って自動クローズするさせる方法についてメモ

# try-with-resources文で自動クローズされる仕組み
ドキュメントを確認してみたところ、try-with-resources文の中でオープンされたリソースのAutoCloseabelインターフェースがtry文を抜ける際に呼び出されてクローズ処理が行われるからという理解でよさそう

https://docs.oracle.com/javase/jp/7/technotes/guides/language/try-with-resources.html


# `HttpURLConnection`と自動クローズ
AutoCloseableインターフェースを持っているリソースの自動クローズをしてくれるtry-with-resources文だが、例えばHttpURLConnectionのようなclose処理があるがこのインターフェースを持っていないクラスでは利用できない
（HttpURLConnectionで行うのはConnectからのDisconnect処理なので、そもそもClose処理ではないけれど・・）
~~~
try(この中でオープン出来るリソースはAutoCloseableインターフェースを持っていないといけない) {
  ～～
}
~~~
# `AutoCloseable`とラムダ式
AutoCloseableインターフェースは、単一のメソッドのみを持つため以下のようなラムダ式で記述することができる
~~~java
AutoCloseable autoCloseabel = () -> httpURLConnection.disconnect();
~~~

# try-with-resources文とラムダ式
これがわかれば、以下の様にしてHttpURLConnectionを~~自動クローズ~~自動切断することができる
~~~java
HttpURLConnection httpURLConnection = new HttpURLConnection();
httpURLConnection .connect();

try(AutoCloseable autoCloseabel = () -> httpURLConnection.disconnect();) {
  ～～
}
~~~

もう一工夫して、以下の様に接続処理を実行して、それを切断するラムダ式を返すメソッドを用意することで
~~~java
AutoCloseable connect(HttpURLConnection conn) {
  conn.connect();
  return () -> conn.disconnect();
}
~~~
それをtry-with-resources文の中で呼び出だせば、見た目をすっきり記述することもできる
~~~java
try(AutoCloseable autoCloseable = connect(conn);) {
  ～～
}
~~~

ここまでするくらいなら、try文にfinally句を追加して終了処理を記述した方が手っ取り早いが・・
PythonでSeleniumを使用してスクレイピングを行うための準備

# 色々試行錯誤したので備忘録として残す
ちなみに最近はpyppeteer使えば、感覚的に使えるしChromeDriverのインストールも勝手にやってくれて便利だけど、古いやり方の方がネット資料も多いので。

pyppeteerの使い方関連に関してはこちらを参照
参考：<a href="https://qiita.com/loach/items/c881f7d9ef5add132c7b" target="_blank">Pythonでスクレイピング - Seleniumなんてもう古い！？・・・Pyppeteerの使い方</a>
参考：<a href="https://rinoguchi.net/2020/08/pyppeteer-manual.html">pyppeteerの使い方</a>

この記事では、表題の通りPythonでSeleniumを使用してスクレイピングを行うための準備について記載する。

## やる事リスト
１．pyenvのインストール
２．venvで環境を汚さないようにする。
３．ChromeDriver-binaryというモジュールをpipでインストールする


### １．pyenvをインストールする為の準備と設定
#### １．１．必要モジュールのインストール
```
# Ubuntuの場合
sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
```

```
# CentOSの場合
sudo yum install gcc zlib-devel bzip2 bzip2-devel readline \
readline-devel sqlite sqlite-devel openssl openssl-devel git \
libffi-devel
```

#### １．２．pyenvをインストール
```
# ソースをカレントディレクトリに配置
git clone https://github.com/pyenv/pyenv.git ~/.pyenv

# .bashrc に下記の内容を記述
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```
再読込（いらないかも）
```
. .bashrc
```

※忘れるのでメモ（pyenvに任意のバージョンをインストールし、使用する）
```
# インストール可能なバージョン一覧を表示
pyenv install -l

# インストール
pyenv install 3.9.10

# 使用する
pyenv global 3.9.10

# ローカルにインストール済のバージョン確認
pyenv versions

# 現在使用中のバージョン確認
pyenv version

# 使用可能状態になると、今までpython3コマンドで打たないと駄目だったのが、pythonコマンドで使えるようになる。
python --version
```

### ２．venv設定を行う
```
python -m venv <好きな名前>

例）
python -m venv 3.9.10

# venv環境に入る時
. 3.9.10/bin/activate

# venv環境から抜ける場合
deactivate
```

### ３．ChromeDriver-binaryをインストール
```
# Seleniumも入れる
pip install selenium chromedriver-binary
```
※これは、ChromeDriverとは別物でpipを使用してインストールする
※ローカル環境にすでに通常版Chromeが入っているとバージョンの違いでPythonで動かした時、下記のようなエラーが出るので注意
```
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 99
Current browser version is 98.0.4758.102 with binary path /usr/bin/google-chrome
```
ChromeDriver-binaryの一覧は下記URLで確認出来る
https://pypi.org/project/chromedriver-binary/#history

バージョンを指定してインストールする場合のコマンド
```
pip install chromedriver-binary==98.0.4758.102.0
```

※ChromeDriver-binaryをインストールするとChromeDriverとは違ってimport文だけで使用出来る
```
# ChromeDriver-binaryを使用した場合
import chromedriver_binary
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.yahoo.co.jp')

###########################################

# ChromeDriver-binaryを使用しない場合
from selenium import webdriver
driver = webDriver.Chrome(executable_path='/home/vagrant/chromedriver')
driver.get('https://www.yahoo.co.jp')
```

スクリピングにはSeleniumだけでなくScrapy？やらrequests？やら構造解析用にBeautifulSoupやら色々モジュールがあってちゃんと頭の中でまとまってないので、そこは別の方にお任せ（他人任せ）
ISO 8601とJavaScriptのDate

備忘録的にメモ

## ISO 8601

時刻を表すフォーマットはたくさんありますが、よく使用されるISO 8601。
ISO 8601では以下のように時刻を表します。

| 拡張表記 | 基本表記 | タイムゾーン | 表す時間 |
|:-:|:-:|:-:|:-:|
| 2022-02-27T15:08:10+09:00  | 20220227T150810+0900  | JST（日本時間）  | 日本時間2022年2月27日15時8分10秒  |
| 2022-02-27T06:08:10Z  | 20220227T060810Z  | UTC（協定世界時）  | 2022年2月27日6時8分10秒  |

拡張表記が結構APIとかで使われる気がする。

*（"+09:00"はローカル時であることを表すだけなので、そこから9時間引いて計算し直す必要は無い...！）*

## Dateでの扱い方

すべてUTCに変換すると、タイムゾーンを気にする必要は特にない。
`getTime()`をメソッドを用いると協定世界時の1970年1月1日00:00:00からの経過ミリ秒が得られる。
なので一度getTime()を通せば経過時間などを簡単に計算できる。

```
> const date = new Date(); //現在の時刻を表すDateオブジェクト
> date.getTime();
1645880642927
> new Date(date.getTime());
2022-02-26T13:04:02.927Z
```

```
> const date = new Date('2022-02-26T22:04:00+09:00'); //タイムゾーンを用いたDateオブジェクト
> date.getTime();
1645880640000
> new Date(date.getTime());
2022-02-26T13:04:00.000Z
```

なので、経過時間を計算するには以下の文だけでOK（時差考慮必要なし）

```
const start = new Date('2022-02-26T22:04:00+09:00');
const now = new Date();
// 経過時間をミリ秒で取得
const elapse = now.getTime() - start.getTime();
```

*（`Date.now()`や`new Date()`を使う際、これはちゃんとタイムゾーンを考慮しなきゃいけないんだっけ...？と思うけど結局UTC基準に変換しているので、特に考慮する必要は無い...！）*



## 参照
- [Date - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date)
- [ISO 8601 - Wikipedia](https://ja.wikipedia.org/wiki/ISO_8601)


間違いがあったらご指摘ください。
Mac(M1)+Lima+docker compose

DockerDesktop有償化にともない、MacでLimaを試した時のメモになります。


## Limaとdockerのインストール
既存のDockerをアンインストールしてから実施しました。

```
arch -arm64  brew install lima docker
```
Limaとdockerを同時にインストールしないと、あとでリンクをはる作業が発生するかもしれません。確証はありません。
（同僚がはまってたポイント）

## 設定ファイルの準備
[Github](https://github.com/lima-vm/lima/blob/master/examples/docker.yaml)から設定ファイルをダウンロードします。
このyamlファイルを利用して、Dockerが動作するホストを起動します。今回はlima.yamlで保存しました。

## Dockerが動作するホストの起動
```
lima start lima.yaml
```
以下の出力が出れば起動が完了です。

```
中略
INFO[0057] READY. Run `limactl shell lima` to open the shell.
INFO[0057] Message from the instance "lima":
To run `docker` on the host (assumes docker-cli is installed):
$ export DOCKER_HOST=unix:///Users/***/.lima/lima/sock/docker.sock
$ docker ...
```
イメージを削除しなければ次回からは以下のコマンドで起動可能です。（yamlファイルの指定が不要になる）
```
lima start lima
```
ホストの状態確認コマンドは以下。
```
limactl  list
```
停止のコマンドは以下
```
 limactl stop lima
```

## MacOSから直接Dockerコマンドを実行
以下の設定で直接Dockerコマンドを実行できるようにします。
```
export DOCKER_HOST=unix:///Users/***/.lima/lima/sock/docker.sock
```


## docker composeのインストール
docker composeのバイナリを取得してプラグインとして認識させます。

```
mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-darwin-x86_64 -o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-compose
```
認識しているか確認。バージョンが表示されたらOK。
```
docker compose version
```

## 実際に起動させてみる
簡易ですが以下のような設定ファイルを準備します。
```docker-compose.yml
version: '3'

services:
    php:
        image: php:7.2-fpm
        container_name: loma-php
    nginx:
        image: nginx
        container_name: lima-nginx
        depends_on:
            - php
```

起動してみます。
```
docker compose up -d
```

dockerコマンドで起動を確認します。

```
docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                       NAMES
45a168202f74   nginx             "/docker-entrypoint.…"   50 seconds ago   Up 19 seconds   80/tcp                                      lima-nginx
da588b9ce87e   php:7.2-fpm       "docker-php-entrypoi…"   50 seconds ago   Up 20 seconds   9000/tcp                                    loma-php
```

以上でMac(M1)+Lima+docker composeの環境ができました。
ワーシャルフロイド法

[最短経路問題](https://qiita.com/sibata_yuna/items/9d3f03288422c96af632)

[問題](https://atcoder.jp/contests/abc079/tasks/abc079_d)　:　[動作確認済み](https://atcoder.jp/contests/abc079/submissions/29760792)

(条件)
頂点数 n のグラフ
頂点a, b 間の距離を求める

```c++
int c[10][10];
int H, W, A, res;

int main()
{
	cin >> H >> W; //縦、横のマス
	rep(i, 0, 10) rep(j, 0, 10) cin >> c[i][j]; // i から j の変換に必要な魔力


	//ワーシャルフロイド法
	rep(k, 0, 10) rep(i, 0, 10) rep(j, 0, 10)
		if (c[i][j] > c[i][k] + c[k][j]) c[i][j] = c[i][k] + c[k][j];


	rep(i, 0, H) rep(j, 0, W)
	{
		cin >> A;
		if (A >= 0) res += c[A][1]; // 数字A から 1 に変える魔力の和
	}

	cout << res << endl;
}
```
OpenModelicaでDXFファイルを読み込むときの注意点

OpenModelicaには3D CADデータ(.dxf)を表示する機能があります。
(読み込み方法などの詳細は[こちらを参照](https://qiita.com/UedaShigenori/items/1d438d9576bfd45fc768))

私はファイル形式やグラフィックスに詳しくありませんが、OpenModelicaでdfxファイルを読み込むときの注意点が経験的に分かってきたのでメモ代わりに記載致します。
補足として、dxfファイルはテキストエディタで開けるため、内部構造を確認することが出来ます。

## dxfファイルの構造次第では読み込めない
詳しくは分かりませんがdxfには様々な構造があるようです。
FreeCAD0.14で出力した球体のdxfファイルは読み込めませんでした。
本記事の一番下にそのファイルのテキストデータを貼っておきます。
3DFACEというエンティティを使用していた場合、読み込めるようです。
詳しいフォーマットの解説は以下のサイト様が参考になりました。
https://www.hiramine.com/programming/3dmodelfileformat/dxffileformat.html

## 読み込んだdxfファイルが真っ黒で表示される
上記のサイト様の一番下にサンプルとして立方体形状のdxfファイル(cube.dxf)があります。
これを読み込むと形状は定義されていますがすべての面が真っ黒となってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244254/ee34483e-a47e-7e0f-a903-8f2705d01dce.png)
(OpenModelica1.17で表示)

これは面の色情報が定義されていないためで、色情報を定義することで任意の色にすることが出来ます。

- 色情報付与前のdxfファイルの3DFACEエンティティの記述

```cube.dxf
3DFACE
  8
0
 10
0
 20
0
 30
・
・
・

```

- 色情報付与後のdxfファイルの3DFACEエンティティの記述


```cube2.dxf
3DFACE
  8
default   ←追加
62        ←追加
3         ←追加
0
 10
0
 20
0
 30
・
・
・

```

「62」は色番号のグループコードで、この下に色番号を記載します。
dxfファイルの色情報はRGBに応じて番号が割り振られています。
詳細は以下のサイト様をご参照ください。
https://web2.official.jp/dxf-color

すべての3DFACEエンティティに対して上記のように色を付与することで各面に任意の色を指定することができます。
以下が各面に色を付与したアニメーション結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244254/3cf86519-3160-e5cc-e848-ff04f4b5424a.png)


## その他のCADデータについて
OpenModelica1.14ではstl形式も読み込むことが出来ましたが、OpenModelica1.17などの近年のバージョンではstl形式では読み込めなくなっています。

### サンプル - 読み込めなかった球体のdxfファイル

FreeCAD0.17からエクスポート

```
  0
SECTION
  2
HEADER
  9
$ACADVER
  1
AC1009
  9
$INSBASE
 10
0.0
 20
0.0
 30
0.0
  9
$EXTMIN
 10
0.0
 20
0.0
 30
0.0
  9
$EXTMAX
 10
0.0
 20
0.0
 30
0.0
  0
ENDSEC
  0
SECTION
  2
TABLES
  0
TABLE
  2
VPORT
 70
0
  0
ENDTAB
  0
TABLE
  2
LTYPE
 70
1
  0
LTYPE
  2
CONTINUOUS
 70
0
  3
Solid line
 72
65
 73
0
 40
0.0
  0
ENDTAB
  0
TABLE
  2
LAYER
 70
1
  0
LAYER
  2
0
 70
64
 62
7
  6
continuous
  0
ENDTAB
  0
TABLE
  2
STYLE
 70
1
  0
STYLE
  2
STANDARD
 70
0
 40
0
 41
1.0
 50
0.0
 71
0
 42
1
 3
ARIAL.TTF
 4

  0
ENDTAB
  0
TABLE
  2
VIEW
 70
0
  0
ENDTAB
  0
ENDSEC
  0
SECTION
  2
BLOCKS
  0
BLOCK
  8
0
  2
BODY
 70
0
 10
0.0
 20
0.0
 30
0.0
  3
BODY
  0
ARC
  8
0
 62
0
 10
-0.134419
 20
-0.0668745000002
 30
0.0
 40
10.1658212259
 50
-89.2423764243
 51
89.2423764243
  0
POLYLINE
  8
0
 62
0
 70
0
 66
1
 10
0.0
 20
0.0
 30
0.0
  0
VERTEX
  8
0
 10
7.46069872548e-14
 20
10.098058
 30
0.0
  0
VERTEX
  8
0
 10
-3.81688927076
 20
9.29961552308
 30
0.0
  0
VERTEX
  8
0
 10
-7.05237412277
 20
7.12297565149
 30
0.0
  0
VERTEX
  8
0
 10
-9.23039076573
 20
3.88841000452
 30
0.0
  0
VERTEX
  8
0
 10
-10.030456395
 20
0.0718542423694
 30
0.0
  0
VERTEX
  8
0
 10
-9.33484658239
 20
-3.76511048289
 30
0.0
  0
VERTEX
  8
0
 10
-6.83684534597
 20
-7.46589522669
 30
0.0
  0
VERTEX
  8
0
 10
-1.7763568394e-15
 20
-10.231807
 30
0.0
  0
SEQEND
  8
0
  0
ENDBLK
  0
ENDSEC
  0
SECTION
  2
ENTITIES
  0
INSERT
  2
BODY
  8
0
 62
0
 10
0.0
 20
0.0
 30
0.0
  0
ENDSEC
  0
EOF

```
コロナで大学を1年休学して、ソースコード売買プラットフォームを作りました

![top_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/3859222b-4701-f035-02c6-0007b0744b6b.png)


# はじめに
プログラミングに興味を持ち出してから、調べれば調べるほどITのすごさに気付かされ大学の授業より実際会社で働いて世の中のITサービスがどのように作られているか知りたいと思い、インターンの求人を長いこと探していました。そして運よく一社だけ面談をさせていただけることになり運よく採用していただきました。その瞬間に休学を決意しました笑
2021年2月から9月まで受託開発会社、9月から1月末まで自社開発会社でエンジニアとして働いていました。そこで得た知識の集大成となったWEBサービスになります。

https://codepick.jp/

# 制作物
プログラミングのソースコード売買プラットフォーム


## なぜ作ったのか？
僕はこのサービスを作るときもそうですが、ハッカソンなどでもわからないことはqiitaに書いてある内容をそのままコピペしたり、ドキュメントのサンプルをそのままコピペしたりして実装をしていました。僕が駆け出しの頃は検索能力も著しく低かったので、フレームワークやライブラリの強みを全く活かしきれずにいました。
優秀なエンジニアが書いたライブラリの選定から正しい拡張の仕方などがみれるソースコードプラットフォームがあったらなと思い作りました。


### 何ができるか
・優秀なエンジニアが書いたソースコードを無料または有料で購入することができます。また、自分が作っているサービスと似ているソースコードを購入して、開発効率をあげることもできます。
・売り手は自分が作ったアプリのソースコードに値段をつけて販売することができます。

# サービス紹介

## 売り手
### 検索機能
・ワード検索
・並べ替え（新着・最安値・最高値）
・絞り込み（言語・トピック・レベル・評価）
![スクリーンショット 2022-02-26 23.29.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/1de73694-3f74-c1c1-e772-2c914891aff1.png)


### リッチテキストエディタ
h1タグや太字、アンダーライン、リンク、リスト、画像、動画のアップロードをしてソースコードの概要を記入します。
![screencapture-localhost-1234-products-11-manage-2022-02-26-23_56_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/83369223-b48f-c77e-927a-b56803d3ee99.png)



### Gitサーバーにpush
githubのように下記のコマンドでリポジトリをpushします。
![スクリーンショット 2022-02-27 0.40.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/07baf7d5-4a54-0abf-d45f-e807f4275947.png)

pushをしたらpasswordを聞かれるので、入力します。
![スクリーンショット 2022-02-27 0.46.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/c897b08a-30d2-fade-ada9-78799144e51c.png)

すると、ソースコードがちゃんとアップされていますね。
![スクリーンショット 2022-02-27 0.48.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/22b6e2c7-9995-4003-06d7-23a83d20f72d.png)

## 買い手
### 購入する
クレジットカードを登録し、購入します
![スクリーンショット 2022-02-27 0.55.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/4c5cdbfc-11a6-f124-7b2c-d4907c94ff43.png)

### 購入ずみのソースコード
zipファイルをダウンロードボタンを押すと、画像のようにソースコードをダウンロードできます。
![スクリーンショット 2022-02-27 0.58.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195442/8e918733-3f2d-c55d-d315-eba12fe23e2b.png)



# 使用技術
バックエンド： Rails、Nginx
フロントエンド： Nextjs
インフラ： Docker、ECS(Fargate)、EFS、RDS(Mysql)、ALB、S3、Route53 、ACMなど
その他： Rollbar、Stripe、Git



# 特に苦労したところ3選

### 決済機能(Stripe)の追加
決済機能にStripeを採用しました。理由は一番stripeの記事が多かったからです。それでも手数料を取るアプリの記事は少なく、何度も問い合わせをして何度もテストをしてエラーモニタリングのツールも使い、お金回りはバグがないように最新の注意を払い実装しました。

### 独自のGitサーバーの構築
アプリを作る割と最初の段階でソースコードを何を経由して取引しようかを考えた時、シンプルにファイルのアップロードしてしまうと、node_modulesなどのファイルが大きすぎて処理が遅生くなってしまったり、余計なリソースを撮られてしまうため、独自のgitサーバーを構築しました。これもまた、記事が少なく大変苦労しました笑

### インフラ(AWS)の構築
インフラ周りは自分が苦手なのもあって、3週間ほど時間をかけてしまいました💦
構築の際に技育CAMPのエンジニアの方に質問ばかりして、すごく迷惑をかけながら（ごめんなさい🙇‍♂️）なんとか動くようになりました。


# 今後の展望
・全体的にUIをいい感じにしたい
・ソースコードが増えてきたら、ユーザーに応じたレコメンド機能をつけたい
・バッジやランキングなどのゲーム要素を加えていきたい
・Codepickを宣伝して、広めていきたい

こうだったらみたいな要望があればなんでも言ってくれたら嬉しいです。

# まとめ
半年以上かけながらやっと完成したので、達成感がすごいです。最初はProgateでヒーヒー言ってた自分が1年ちょっとでバックエンド(Rails)、フロントエンド（Nextjs）インフラ（AWS）このくらいまでできるようになりました。

最後に、ぜひ拡散お願いします！！！！！
最後まで見ていただきありがとうございました🙇‍♂️
【WineHQ】Linux Mint 20.3とUbuntu Studio 20.04にターミナルでWineHQをインストール/日本語表示

Linux Mint 20.3でWindowsのアプリ「Music Studio Producer」と「Synthesia」を使って音ゲーで遊ぼうと思いました。WineHQ7.0でそれらを実行しようと思います。

# 短く言うと

Linux Mint 20.x と Ubuntu 20.04 ではターミナルで以下のコマンドを入力することで __WineHQのインストール→日本語化__ ができます。

:::note info
ターミナルを使ってWineHQ7.0をインストールします。
:::

```:Terminal
sudo dpkg --add-architecture i386
```
```
wget -nc https://dl.winehq.org/wine-builds/winehq.key
```
```
sudo apt-key add winehq.key
```
```
sudo add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main'
```
```
sudo apt update
```
```
sudo apt install --install-recommends winehq-stable
```
:::note info
Winetricksを使って、cjkfontsをインストールします。
:::

```:Terminal
sudo apt install -y winetricks
```
```
winetricks
```

__「●Select the default wineprefix」「OK」→「●Install a font」「OK」→「cjkfonts」にチェック「OK」__ ※インストール中いろいろ言われますが、すべて「はい」「OK」

# はじめに

LinuxなPCをつかって音ゲーで遊ぼうと思いました。いろいろと検索したところ目的のアプリの一部はWindowsにしか対応していないようなのでそれらをWineHQ7.0から起動しようと思います。MIDI対応のWindowsアプリは安定させるのにとても手間がかかり(失敗もするので)、なんどもWineのインストールからはじめることになりました。ターミナルを使って簡単にインストールできるようにまとめておきます。

:::note warn
なお、MIDIを鳴らすにはLinux Mint / Ubuntu側でTiMidity++ / Fluidsynthの設定が必要です。
:::

# 今回の環境

* NEC LaVie LS350/A
* Linux Mint 20.3 cinnamon または Ubuntu Studio 20.04.3

# WineHQをインストール

:::note info
Windowsアプリを使えるように、ターミナルを使ってWineHQ7.0をインストールします。
:::

「Ubuntu - WineHQ Wiki」[^41]を編集して引用します。

システムが64bitの場合、32bitアーキテクチャを有効にします。

```:Terminal
$ sudo dpkg --add-architecture i386
```

***

リポジトリキーをダウンロードして、追加します。

```:Terminal
$ wget -nc https://dl.winehq.org/wine-builds/winehq.key
$ sudo apt-key add winehq.key
```

***

リポジトリを追加します(Ubuntu 20.04 と Linux Mint 20.x の場合)。

```:Terminal
$ sudo add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main'
```

***

パッケージを更新します。

```:Terminal
$ sudo apt update
```

***

WineHQ の安定版パッケージをインストールします。

```:Terminal
$ sudo apt install --install-recommends winehq-stable
```

以上で、WineHQ7.0がインストールできました。

# Winetricksを使ってcjkfontsをインストール

:::note info
WineHQで日本語を表示できるように多言語フォント「cjkfonts」をインストールします。
:::

Winetricksをインストールして、起動します。

```:Terminal
$ sudo apt install -y winetricks
$ winetricks
```

「Wine MONO インストーラー」が立ち上がりインストールすると、WinetricksのGUIが開くので、

__「●Select the default wineprefix」「OK」→「●Install a font」「OK」→「cjkfonts」にチェック「OK」__

※インストール中いろいろ言われますが、すべて「はい」「OK」

以上で日本語表示が可能となります。

# おわりに

Windowsアプリ「Music Studio Producer」と「Synthesia」を使いたいのでさらにMIDIの設定をしていきます。

[^41]: https://wiki.winehq.org/Ubuntu

# 参考サイト

https://www.winehq.org/
Gradle: Task 完了時に処理を実行する (Task の実行情報取得)


OperationCompletionListener を使うと Gradle のタスク完了時にタスク実行に関する情報を受け取って処理をすることができます。

## 前提

* Gradle 6.1 以上
    * [OperationCompletionListener](https://docs.gradle.org/6.1/javadoc/org/gradle/tooling/events/OperationCompletionListener.html) は Gradle 6.1 から対応しています

## 別のタスクを実行するなら finalizedBy

特定のタスクのあとに他の処理を実行したい場合は、finalizedBy を使用してください。

https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:finalizer_tasks

OperationCompletionListener は別のタスクを実行するのではなく、タスクの実行完了時にそのタスクの情報を取得するなどの計測などが目的のときに利用できる仕組みです。

## 実装

`build.gradle.kts`

```kotlin
import org.gradle.tooling.events.OperationCompletionListener

abstract class TaskCompletion : BuildService<BuildServiceParameters.None>,
    OperationCompletionListener {
    override fun onFinish(event: FinishEvent) {
        println("onFinish: ${event.displayName}")
    }
}

project.serviceOf<BuildEventsListenerRegistry>().onTaskCompletion(
    gradle.sharedServices.registerIfAbsent("taskcompletion", TaskCompletion::class) {}
)
```

## 解説

[BuildEventsListenerRegistry](https://docs.gradle.org/current/javadoc/org/gradle/build/event/BuildEventsListenerRegistry.html) に OperationCompletionListener を実装した [Shared Build Service](https://docs.gradle.org/current/userguide/build_services.html) を登録します。

onTaskCompletion() を登録するとすべての project のすべてのタスクの実行完了時にイベントを受け取ります。

[FinishEvent](https://docs.gradle.org/current/javadoc/org/gradle/tooling/events/FinishEvent.html) は以下の情報を含みます。

| 項目　| 値 |
| --- | --- |
| event.result | DefaultTaskSuccessResult など、実行時間やキャッシュヒット状況などが取れるようです |
| event.eventTime | Task の実行完了時刻 |
| event.displayName | Task 結果文字列 (`Task {task name} UP-TO-DATE` など) |
| event.descriptor | DefaultTaskOperationDescriptor など、タスクの簡単な情報が取れるようです |

![event.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/63f376d0-548e-84b0-552a-460f7fdd272e.png)

## TaskExecutionListener は使えない

以前は TaskExecutionGraph に TaskExecutionListener を登録することができましたが、これは　Configuration Cache を有効にしていると機能しないため非推奨となりました。

* https://docs.gradle.org/current/userguide/upgrading_version_7.html#task_execution_events
* [TaskExecutionGraph#addTaskExecutionListener](https://docs.gradle.org/current/javadoc/org/gradle/api/execution/TaskExecutionGraph.html#addTaskExecutionListener-org.gradle.api.execution.TaskExecutionListener-)
* [TaskExecutionListenr](https://docs.gradle.org/current/javadoc/org/gradle/api/execution/TaskExecutionListener.html)
go mod tidyの役割

[公式サイト](https://go.dev/doc/tutorial/getting-started)でgoの学習をしていてわからなかったことがあったのでメモ書きとしてまとめようとおもいます。

## go mod tidy

結論からいうと、モジュール管理していて使わなくなったり必要なくなったパッケージを削除するためのコマンドです。

実際に```go mod```コマンドを打って確かめてみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/69f3c0b7-0bd5-cf1a-bd6f-a9d533d02965.png)

「add missing and remove unused modules」と書かれています。
不足していたり、使われていないモジュールに良しなに対応してくれるコマンドみたいですね。
ちなみに、tidyは「几帳面」という意味なのでそれも覚えとくと役割も理解できると思います。

短いですが、以上です。何か間違いがございましたら、ご教示いただけますと幸いです。

【参考文献】
https://qiita.com/k-kurikuri/items/609141727320eb1a6d2b
PenTest.ws ～ペネトレーションテストでのクレデンシャル情報、攻略の進捗のメモ用サービス～

# 前置き
今後、なるべく記事を書く事を継続するために、
ちょっとした調べものの内容などもQiita記事にしていこうかと思います。

本記事は、今日から使い始めた[Pentest.WS](https://pentest.ws/)についての記事です。

# Pentest.WS便利そう

ペネトレーションテストに際してのメモが書けるだけでなく、ポートスキャンの結果、クレデンシャルの管理ができる模様。

使い心地が分かったら、スクショを張っておきます。

参考
https://emaragkos.gr/ctfs/penetration-testing-workshop/

# （追記：2022/03/15）Pentest.WSの使い心地

とりあえず、TryHackMeのBlueマシンにてnmapの結果をエクスポート
　↓
PenTest.wsにインポート
した状態で「Hosts」タブを開いた状態のスクショです。

視覚的に非常に分かり易くまとめられており、ここからさらに各々のポートの詳細や状況を書き込めるようになっています。すごい便利。

![blue_PenWs.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653289/1add0d2f-394f-30d0-3bc8-bcf29ec1fd21.jpeg)
Windowsでポート疎通確認

## はじめに
Windowsサーバ上でポートの疎通確認を行う必要があり、UDPも確認可能な PortQry というツールがあったのでメモ。
（PowerShell の Test-NetConnection コマンドでは UDPは確認できません）

## PortQryを入手
[PortQryのサイト](https://www.microsoft.com/en-us/download/details.aspx?id=17148) からダウンロードする

## PortQryを展開
**PortQryV2.exe** を実行し展開する  
デフォルトの展開先は **c:\PortQryV2**

## 実行してみる
```
c:\PortQryV2>PortQry.exe -n 192.168.128.1 -e 53 -p UDP

Querying target system called:

 192.168.128.1

Attempting to resolve IP address to a name...

Failed to resolve IP address to name

querying...

UDP port 53 (domain service): LISTENING
```

## コマンドラインオプション（よく使いそうなもの）

| オプション | 意味 |
| :-- | :-- |
| -n [address] | IPアドレス又はホスト名を指定 |
| -e [port] | ポート番号を指定 |
| -r [start:end] | ポート番号の範囲を指定 (例 -r 21:445) |
| -o [x,y,z] | ポート番号を順番に指定 (例 -o 25,445,8080)
| -p [protocol] | プロトコルを指定 (TCP, UDP, BOTH) |
iOSのNSTimeZoneのUTCってnameがGMTなんだ..

![GMT_UTC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152641/ac5ea486-92d4-d55f-c618-9febbf5f2194.png)

AndroidとiOSでTimeZoneのUTCにまつわる調査をしていたところ想定外の結果になったので書き残しておきます。誰か真相を知っていたら教えて下さい。

# GMTとUTCの違い
GMTとUTCの違いをググるとCITIZENの用語集とよくある質問リストが最初に出てくる

https://citizen.jp/faq/detail/id1363

>両者は、目的も概念も算出方法もまったく異なりますが、日常生活に不都合のない精度の時間測定(整数の秒)であれば、ほぼ差がないと考えて問題ありません。

そう、ほぼ一緒と考えてよいということ。日本のAsia/Tokyo(+9:00)より9時間前のタイムゾーンということだ。

# Android(Kotlin)の場合

```kotlin
import java.util.TimeZone

fun main() {
    var tz1 = TimeZone.getTimeZone("Asia/Tokyo")
  	println("The id of Asia/Tokyo is ${tz1.id}")
    
    var tz2 = TimeZone.getTimeZone("UTC")
  	println("The id of UTC is ${tz2.id}")
    
    var tz3 = TimeZone.getTimeZone("GMT")
    println("The id of GMT is ${tz3.id}")
}
```
結果
> The id of Asia/Tokyo is Asia/Tokyo
The id of UTC is UTC
The id of GMT is GMT

idはそれぞれインスタンス化したidがそのまま出力されているので想定どおり。

対して、iOSの場合は..
# iOS(Swift)の場合

```swift
    func testExample() {
        let tz1 = NSTimeZone(name: "Asia/Tokyo")!
        print("The name of Asia/Tokyo is", tz1.name);
        
        let tz2 = NSTimeZone(name: "GMT")!
        print("The name of GMT is", tz2.name);
        
        let tz3 = NSTimeZone(name: "UTC")!
        print("The name of UTC is", tz3.name)
    }
```

<!--
```c
#import <Foundation/Foundation.h>
- (void)test {
    NSTimeZone *tz1 = [NSTimeZone timeZoneWithName: @"Asia/Tokyo"];
    NSLog(@"The name of Asia/Tokyo is %@", tz1.name);
    
    NSTimeZone *tz2 = [NSTimeZone timeZoneWithName: @"GMT"];
    NSLog(@"The name of GMT is %@", tz2.name);
    
    NSTimeZone *tz3 = [NSTimeZone timeZoneWithName: @"UTC"];
    NSLog(@"The name of UTC is %@", tz3.name);
}
```
-->
結果
> The name of Asia/Tokyo is Asia/Tokyo
The name of GMT is GMT
The name of UTC is GMT

一番最後のUTCでインスタンス化したtimezoneのnameがGMTになっているのがわかる。
一緒と考えていいといっても、インスタンス化の元に使ったname変えたらダメでしょうに。
これはなんでだ..?
なぜこんな仕様になっているのか知っている人は教えて下さい🙏
Rails コメント機能　コード解説（ビューの作成）

# ビューの作成
```ruby:posts/show.html.erb
<%= form_with(model: [@post, @comment], local: true) do |f| %>
<textarea name="content"><%= @comment.content %></textarea>
<input type="submit" value="コメントする">
<% end %>
<p>コメント件数：<%= @comments.count %></p>
<% @comments.each do |c| <div>
<a href="/users/<%= c.user.id %>"><%= c.user.name %></a>
<%= c.content %>
<%= link_to("削除", "/comments/#{c.user.id}/destroy", {method: "post"}) %>
<% end %>
<%= paginate @comments %>
```
# コードの解説
１行目・・postコントローラーにcommentコントローラーのルーティングがネストしている。
[(親)@インスタンス変数, (子)@インスタンス変数]の順で記述するようにする。
local: trueと引数を渡す事で、これが通常のHTTPリクエストになり、ページ全体が返ってくる
２行目・・コメントの内容の表示
３行目・・<input>タグのtype属性の値にsubmitを指定すると、フォームの送信ボタンを作成します。
５行目・・コメント数の習得
６行目・・要素を1つずつ取得してcに代入
７行目・・c.user.id=comment.user.id,c.user.name=comment.user.nameと同義
８行目・・c.content＝comment.contentと同義
１1行目・・viewでページネーションを表示させたい
# 引用記事
[ネストした form_withの理解を深める](https://qiita.com/k_u/items/4f5a503da50b9144ddf9)
[[Rails] form_with の２種類の書き方](https://qiita.com/k_u/items/4f5a503da50b9144ddf9)
[form_withのlocal: trueって必要なん？これ何なん？（Ruby on Rails）](https://qiita.com/kakudaisuke/items/e032c7705db00e8081dc?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items)
[HTML5タグリファレンス](http://www.htmq.com/html5/input_type_submit.shtml)
[【初心者向け】コメント機能作成追加](https://qiita.com/A__Matsuda/items/5dc66de9f96fd5d02c41)
[【Rails】 世界で一番分りやすく詳しいcountメソッドの使い方](https://pikawaka.com/rails/count)
[【Rails初心者】ページネーションを実装して自分好みにデザインを変える](https://qiita.com/rio_threehouse/items/313824b90a31268b0074)
AWS Amplify CLIのインストール時にエラッた件

# はじめに
AWSが公開しているチュートリアルである[AWS Amplifyを利用したReactアプリケーションの構築](https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/)を進めていたところ、つまずいた点がありましたのでその解決までをまとました。
※一旦解決した、という状況なので理由等は後で整理したいと思います。

# では見ていきます！

## 今回使用するツールなどのバージョン
- Windows 10 Pro：21H1
- WSL2：Ubuntu 20.04 LTS
- vscode：1.61.2
- Node.js：v16.14.0
- npm : 8.3.1
　Node.jsをWSL2にインストールするときに参照した情報
　[Node.js を Linux 用 Windows サブシステム (WSL2) にインストールする](https://docs.microsoft.com/ja-jp/windows/dev-environment/javascript/nodejs-on-wsl)

## どこでエラーとなったか
チュートリアルにある[Amplify CLIをインストールする](https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/module-two/)時に下記のような①②のエラーが発生しました。

* Amplify CLIをインストールする

```
npm install -g @aws-amplify/cli
```

```:エラー①
npm ERR! code ERR_SOCKET_TIMEOUT
npm ERR! network Socket timeout
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network 
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'

npm ERR! A complete log of this run can be found in:
```

```:エラー②
npm ERR! code ENOTEMPTY
npm ERR! syscall rename
npm ERR! path /xxx/.nvm/versions/node/v16.14.0/lib/node_modules/@aws-amplify/cli
npm ERR! dest /xxx/.nvm/versions/node/v16.14.0/lib/node_modules/@aws-amplify/.cli-LTvuxHj1
npm ERR! errno -39
npm ERR! ENOTEMPTY: directory not empty, rename '/xxx/.nvm/versions/node/v16.14.0/lib/node_modules/@aws-amplify/cli' -> '/xxx/.nvm/versions/node/v16.14.0/lib/node_modules/@aws-amplify/.cli-LTvuxHj1'

npm ERR! A complete log of this run can be found in:
```

## 対応した内容
グーグル先生に頼った結果、下記コマンドを実行することによりエラーは無くなりました！

```
npm config set fetch-retry-maxtimeout 120000
npm config set proxy false
npm cache verify
rm -fr /xxx/.nvm/versions/node/v16.14.0/lib/node_modules/@aws-amplify
```

# 私の事象は解決したけど・・・
バージョン問題や、WSL2利用などが問題だったのかはもう少し調査必要ですが
同じ問題で悩んでいる人の手助けになればと思い、すぐ投稿しましたｗ
解決したよって人はイイネ待ってます^^
SNS管理者試験

SNSを管理する人に資格があると嬉しいという声を聞いたことがある。

実際に、

初級SNSマネージャー養成講座[認定試験]

https://www.waca.associates/jp/study/courses/expert/snsmanager/


>1章 SNS運用とは	SNSマーケティングの考え方や運用方法をはじめ、炎上、危機管理などの基本事項を学びます。
2章 戦略立案	SNSのさまざまな活用方法や運用企画について学びます。
3章 Twitter	Twitterの運用方針や機能をはじめ、コミュニケーション事例やアナリティクスの見方について学びます。
4章 Instagram	Instagramの運用方針や機能をはじめ、コミュニケーション事例やクリエイティブについて学びます。
5章 Facebook	Facebookの運用方針や機能をはじめ、コミュニケーション事例やFacebookインサイトの見方について学びます。
6章 LinkedIn	LinkedInの利用状況をはじめ、企業ページの運用について学びます。
7章 TikTok	TikTokの運営方針や機能をはじめ、広告やインサイトについて学びます。
8章 そのほかのSNS	LinkedInやPinterest、YouTubeなどのSNSの概論を学びます。
9章 SNSの広告運用	SNS広告における基礎知識から戦略設計、広告の出稿方法などを学びます。
10章 キャンペーンとインフルエンサー活用	SNSキャンペーンの目的や種類、そして注意事項などについて学びます。
11章 レポートの作成と活用方法	SNSレポートの活用方法や作成方法について学びます。

# 法律

何がよいことで、何がよくないことかを、どの法律に照らして判断するかがわからないまま、いろいろな行動を取るSNS管理者が問題だということに、業界として気が付いていないのかもしれません。

1980年代以降にに、パソコン通信などでの議論がありました。３０年の歴史があります。
学会などができたのですが、企業の興隆が激しく、入れ替わるため、知見の継承が１０年ごとに途切れるようです。

情報ネットワーク法学会

http://www.in-law.jp/index-base.html

# 通信技術

通信規約、セキュリティ、トンネル、５G、Wi-Fi6、SoftEther、Ethercat、車載Ethernetなど、新しい通信規約に、どういう仕組みを埋め込むといいか、利用者側の姿勢を示すことが大切かも。

# 文字コード、文字フォント、文字処理

文字化けは、サービスの根幹を揺るがす現象です。
文字化けを発生させないためには、対応する文字コード、文字フォント、文字処理をどのゆに組み立て、どのような文字の使用を許諾するかの仕組みが大切かも。

# 社会

利用者をどう組織すると多様性を保持できるかを考えることが大事です。

特定の偏った考えで利用者を組織されることがないように気をつけることはたくさんあります。
1980年代以降に、パソコン通信で議論した成果は、１０年ごとに途切れ、消えてしまっているかもしれません。
freezedで*.g.dartファイルが生成されない

# 状況
freezedを使用していて、build_runner build → エラー発生 → 修正　を繰り返していました。
何度もビルドをしていたがために発生した事象だと思います。
# エラー内容
生成しようとしたクラス
```
import 'package:freezed_annotation/freezed_annotation.dart';

part 'todo.freezed.dart';　// エラーあり　ファイルが生成されていないのだから当然

part 'todo.g.dart'; // エラーあり　ファイルが生成されていないのだから当然

@freezed
class TODO with _$TODO{
  const TODO._();
  const factory TODO({
    required String code,
    required String name,
  }) = _TODO;

  factory TODO.fromJson(Map<String, dynamic> json) =>
      _$TODOFromJson(json);
}
```
このクラスをfreezedで生成しようとしたら以下の[WARNING]が発生した。
```
TODO.g.dart must be included as a part directive in the input library with
part 'todo.g.dart';
```
Succeededは表示されているのに、todo.g.dartが生成されず、
todo.freezed.dartのみが生成されるという状況。

# 解決方法
以下を一度消して、もう一度書く。
```
part 'todo.g.dart';
```


# まとめ
一回消して追加しただけなのに直った、、、。
わからない、、、。
初めてのOSSコントリビューションの選び方

# 対象となる読者

- OSSのコントリビュートって何から始めればいいのかわからない
- OSSのコントリビュート先の選び方がわからない
- そもそもOSSのコントリビュートの手順がわからない



# たった5分でOSSコントリビュータになれる「First Contributions」

![first-contributions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529362/6dec5ca9-24b8-2c17-a162-a61b010d627a.png)

https://firstcontributions.github.io

文字通り、OSSのコントリビューションデビューをする人のために用意されているリポジトリです。

著者も初めてのコントリビューションを、「First Contributions」でやってみましたが、本当に5分程度で完了しました。



# 手順

日本語で手順が載っています。

https://github.com/firstcontributions/first-contributions/blob/master/translations/README.ja.md

1. レポジトリをフォーク
2. レポジトリをクローン
3. ブランチを作成
4. コードを変更してその変更をコミット
5. GitHubに変更をpushする
6. レビューのためにプルリクエストを送る

Gitを使ったことがあれば、サクサクできると思います。

尚、コードの修正もマークダウンファイルに自分の名前を追加するというものなので技術的に難しいことは特にありません。



# 次のコントリビューション

「First Contributions」は初めてのコントリビューションだけでなく、2回目以降のコントリビューションもサポートしてくれます。
![search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529362/a09d4e31-55bc-d8da-1d1f-e5da2ec76762.png)

上記のようにサイト内から検索することが可能です。



# おまけ
初めてのOSSコントリビューション達成。
![my-first-contribution.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529362/7ebe9237-1e07-67d5-15db-e12fbdd9dd49.png)

# 謝辞
下記の記事を見て「First Contributions」を知りました。ありがとうございました。
[5分でOSSコントリビュータになってみた。"First Contributions"](https://qiita.com/e99h2121/items/a5c7b9a71555d064c687)
mayaの環境を構築していく 7日目

骨打ちツールとスクリプト読み込みツール2つできた訳ですが、さて起動方法をどうしよう。

- シェルフに登録
- メニューバーにメニュー追加して起動
- ツールボックス的な物に登録して起動

シェルフに登録
--
個人的にシェルフへの登録はあまりやらないのですね。
終了。


メニューバーにメニュー追加して起動
--
userSetup.pyを作っておいたので、これをやっていこうかと。


まずはメニューバーに項目追加

    cmds.menu(label= "hogeTools", tearOff=True, p = "MayaWindow")

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/fe87301c-b3eb-74b7-55ee-66710d86ccb1.png)

このメニューにさらに項目を追加していく。

```
rootMenu = cmds.menu(label= "hogeTools", tearOff=True, p = "MayaWindow")
cmds.menuItem(
                label= "sourceScriptTool", 
                parent = rootMenu, 
                c = "import TTLib.gui.sourceScriptTool;reload(TTLib.gui.sourceScriptTool);TTLib.gui.sourceScriptTool.main()"
                )

cmds.menuItem(
                label= "skeletonEditTool", 
                parent = rootMenu, 
                c = "import TTLib.gui.skeletonEditTool;reload(TTLib.gui.skeletonEditTool);TTLib.gui.skeletonEditTool.main()"
                )
```

※ここにきて突然ライブラリ名を **TTLib** と仮決め。　何の略かは内緒

これを毎回実行させる為に、userSetup.pyに追記する。

```
#!python2.7
# -*- coding: utf-8 -*- 
import maya.cmds as cmds
import maya.utils
import sys
sys.dont_write_bytecode = True


def addMenu():
    rootMenu = cmds.menu(label= "hogeTools", tearOff=True, p = "MayaWindow")

    cmds.menuItem(
                    label= "sourceScriptTool", 
                    parent = rootMenu, 
                    c = "import TTLib.gui.sourceScriptTool;reload(TTLib.gui.sourceScriptTool);TTLib.gui.sourceScriptTool.main()"
                    )

    cmds.menuItem(
                    label= "skeletonEditTool", 
                    parent = rootMenu, 
                    c = "import TTLib.gui.skeletonEditTool;reload(TTLib.gui.skeletonEditTool);TTLib.gui.skeletonEditTool.main()"
                    )

def setPref():
    cmds.evaluationManager(mode = "off")
    cmds.optionVar(intValue = ["gpuOverride",0])
    cmds.savePrefs(general =True)

maya.utils.executeDeferred(setPref)
maya.utils.executeDeferred(addMenu)
```

mayaを起動しなおして確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/0f04cdc9-eb0a-31dd-fa9f-0622841f0571.png)

ツールボックス的な物に登録して起動
--
ツールボックス的なモノに集約しておくとそれはそれで便利なのですが、
結局そのツールボックスをシェルフかメニューに登録しておかないと呼び出しづらいの
今回は一旦見送り。


さてそろそろリグを組み始めたいな
【 Javaの条件式 】

現在Javaを独学で学習中です。
この投稿はその備忘録になります。

## 制御構造
変数や型・リテラル・演算子などを利用した文を実行させる順番のことを`制御構造`とよびます。
制御構造の代表的なものとして、

①順次
②分岐
③繰り返し

があります。

### ①順次
「単純に次の文を実行する。」
下図のように上からした下にソースコードを実行します。
```java
public class Main{
 public static void main(String[] args){
  int age = 23;
  System.out.println(age);
 }
}
```

### ②繰り返し
「条件によって違う文を実行する。」
下図のように、条件によって実行する内容が異なります。
```java
public class Main{
 public static void main(String[] args){

 }
}
```
Let's noteをSSDに換装するときに地味にハマった話

# はじめに
　8年前に購入したLet's note(CF-LX3)の起動に15分程かかっていた。昨今はSSDがだいぶお安くなっているとのことだったので、試してみることにした。
 過程で地味にいくつかハマったので備忘録的に残すことにした。

# 購入したもの
・crucial　クルーシャル
CT500MX500SSD1/JP [500GB SATA 2.5インチ 7mmSSD(with 9.5mm adapter)]

・Owltech　オウルテック
OWL-SA23EI-U2 [2.5/3.5インチHDD/SSD用 SATA-USB2.0 変換ケーブル ブラック]
　ちょいと転送速度は遅くなるが、何度も使うものでもないのでコスパ重視で選んだ。

# やったこと

1.クローン作成
　大学の包括ライセンスを利用して手に入れたWindowsを失いたくなかったので、クローンを作成することにした。まず、windowsのディスク管理からssdを初期化し、「Acronis True Image for Crucial」でクローンを作成した。因みに、crucial製品を使う場合このソフトウェアは無料で利用できる。サイトでインストールファイルをダウンロードし、インストーラ(setup.exe)を起動した。しかし、ここで発行されたファイル(AcronisTrueimageMicron_39200.exe)を管理者権限で実行して起動すると、修復かアンインストールしか選べない画面が出てきて困った。結局、デスクトップに作成されていたショートカットから起動するとクローンを作成することができた。
　設定の過程で特殊なことはしていないので詳細は他のページに譲るが、クローン作成中には絶対に電源やUSB接続を切断をしないよう気をつけてほしい(理由は後述)。
　時間に関しては、クローンソフトで設定項目を選ぶごとに1時間程、クローン自体には5時間ほどかかった。

2.SSD装着
　Let's noteはバッテリーの奥にHDDが入っているので、そこから引っ張って出して交換した。なんとなく裏蓋の全てのネジを取って分解を試みたが、うまく外れなかった上に時間がかかったのでお勧めしない。

3.起動(1回目)
　上手く起動しなかった。BIOS設定画面でSSDを選択する項目が見当たらなかった。ブート領域の再構築とやらが必要なのか？と思い、「bootrec /RebuildBCD」を実行したところ、windowsのインストールが認識されなかった。この辺りで2週間ほどハマったが、ないものはないんだろうなと思い再度クローンを作成することにした。

4.ディスク管理を確認
　再度クローンを作成する前にディスク管理を確認したところ、HDD(転送元)でwindows(C:)となっているパーティションが、SSD(転送先)ではRAWとなっていた。恐らく、以下のようなことが起こっていたようだ。
https://www.crucial.jp/support/articles-faq-ssd/ssd-shows-raw-partition
これにより、上手く起動できなかった原因は、クローン時に電源やUSB接続を切断したことによるパーティションの破損にあるらしい、と分かった。

5.disk clean
　再度クローンを作成するためには現在SSDに入っているデータを消去する必要がある。詳細は他に譲るが、コマンドプロンプトを管理者権限で実行してlist diskでディスク番号を確認、select diskでディスクを選択、cleanで対象ディスクのデータを消去した。しかしその後、ディスクの管理画面でディスクを確認すると、1GBというありえない容量が表示されていた。更に、ディスクを再度初期化しようとしたところ、
「ディスクの管理コンソールのビューが最新の状態でないため、操作を完了できませんでした。タスクの最新の情報に更新を使ってビューを最新の情報に更新してください。問題が解消されない場合は、ディスクの管理コンソールを閉じてからディスクの管理またはコンピュータを再起動してください。」
と表示された。
　原因は恐らく接続不良だった。デバイスマネージャー→ユニバーサルシリアルバスコントローラー→大容量記録装置で右クリック→デバイスのアンインストール→SSDのUSB接続を切断→SATA変換ケーブルや電源の抜き差し→PC再起動で上手く認識されるようになった。

6.クローン作成(2回目)
　手順は1回目と全く同じだが、電源やUSB接続の切断に細心の注意を払った。1回目のクローンと違い、ソースディスクとターゲットディスクの選択画面がなく、本来ソースディスクがdisk0、ターゲットディスクがdisk1であるにも関わらず、クローンソフト上ではソースディスクがdisk1、ターゲットディスクがdisk2と表示されたので心配したが、問題なくクローンできた。また、ディスク管理で確認したところwindowsのパーティションもRAWではなくNTFSと表示されていた。

7.SSD装着&起動
　てっきりBIOS設定が必要かと思っていたが、普通にOSのログイン画面が表示されたので驚いた。起動にかかる時間も1分程となりとても満足している。

# 最後に
　なんとも言えないところにハマってしまい想定以上に時間がかかってしまった。同じようなハマり方をする人が少なくなれば幸いである。
Position:fixed :sticky違い

fixedとsticky対する理解
**・fixed:ウインドウに固定される。**
**・sticky:親要素の中で固定される。**
親要素から飛び出して欲しくない要素を固定したいなと思った時はstickyを使って親要素の範囲内にとどめられる。
コンテナの中にサイドとメインの要素を配置。さらにサイドにナビゲーションバーを配置して動かないようにしたい時はstickyを使う事でバーをサイドの中に留めつつ固定できる。fixedを使ってしまうとサイドから出てしまい各要素のサイズなど調整が面倒になりそうかなと個人的に感じました。
【Rails】nil? empty? blank? present? exists?メソッドについて【Ruby】

## はじめに
　本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## nil? empty? blank? present? exists?メソッドについて

### nil?
対象がnilの時は`true`をそうでなければ`false`を返します。
nilは「何も存在しない」状態です（nullと同じ）。

```ruby:trueを返す例
sample = nil
p sample.nil?
# true
```

```ruby:falseを返す例
sample1 = ""
p sample1.nil?
# false

sample2 = 0
p sample2.nil?
# false

sample3 = []
p sample3.nil?
# false
```

### empty?
empty?メソッドは対象が空の文字列や空の配列の場合に`true`を返します。
また、`NilClass`に定義されていないため対象がnilの場合には`NoMethodError`となります。
そのためnilの判定に使用することはできません。

```ruby:trueを返す例
sample1 = ""
p sample1.empty?
# true

sample2 = []
p sample2.empty?
# true
```

```ruby:falseを返す例
sample = " "
p sample.empty?
# false
```

```ruby:対象がnilの場合
sample = nil
p sample.empty?

# Traceback (most recent call last):
# sample.rb:2:in `': undefined method `empty?' for nil:NilClass (NoMethodError)
```


### blank?
blank?メソッドは、`nil`,`false`,`""（空文字）`,`" "(空白)`,`[](空配列)`,`{}(空ハッシュ)`の場合に`true`を返します。
blank?メソッドはRailsで拡張されているメソッドなので使用する場合は、`active_support`と `active_support/core_ext`を記述する必要があります。Rubyのみでは使えません。

```ruby:trueを返す例
require 'active_support'
require 'active_support/core_ext'

sample1 = nil
p sample1.blank?
# true

sample3 = " "
p sample3.blank?
# true

sample2 = ""
p sample2.blank?
# true

sample4 = []
p sample4.blank?
# true
```

```ruby:falseを返す例
require 'active_support'
require 'active_support/core_ext'

sample1 = 0
p sample.blank?
# false

sample2 = "サンプル"
p sample2.blank?
# false
```

### present?
present?メソッドは!blank?を実行します。
すなわち、`nil`,`false`,`""（空文字）`,`" "(空白)`,`[](空配列)`,`{}(空ハッシュ)`の場合に`false`を返します。
また、後述のexists?メソッドとは異なり、条件に該当するレコードを全てデータベースから取得して、（Rails上のモデルの）配列として評価します。
そのため、使い所を間違えるとパフォーマンスに影響します。
present?メソッドでレコードの存在確認を行った後に、インスタンスを使って何か処理をしたいときに使用します。

```ruby:present?の使用例
user = User.find_by(name: params[:user][:name])
if user.present?
  redirect_to user_path(user), notice: "ようこそ！#{user.name}さん！！"
else
  redirect_to root_path, alert: "#{params[:user][:name]}さんは見つかりませんでした。"
end
```

### exists?
exists?メソッドは、指定した条件のレコードがデータベースに存在すれば`true`を返します。
present?メソッドとは異なり、条件に合致するレコードが1件でも見つかればその時点でtrueを返します。
exists?メソッドレコードの存在チェックだけを行う場合に使用します。

```ruby:exists?の使用例
if User.exists?(name: params[:user][:name])
  "#{params[:user][:name]}さんは登録済みです。"
else
  "#{params[:user][:name]}さんは登録されていません。"
end
```
へんすうの名前を変える「こども向けのSnap!かいせつ」


へんすうの名前を変えるには、名前を変えたいへんすうのブロックの上で右クリックをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/a2eec7b7-49fb-f17e-24e3-e9a16b7cc2cf.png)
「なまえをへんこう」と「rename all（すべての名前をへんこう）」の二つがあります。
「なまえをへんこう」の場合は、そのへんすうブロックの名前<b>だけ</b>が変わります。このため、これまでその名前のへんすうブロックを使っていたところは変わりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/23f21c5d-38cd-9cc6-fda1-6896d1cf4c24.png)
ここでは、「まわす方向」という名前を「かいてん方向」という名前に変えましたが、他の「まわす方向」という名前のブロックは変わっていません。このためスクリプトは<b>エラー</b>になります。

一方、「rename all（すべての名前をへんこう）」を使って名前をかえると、その名前のへんすうブロック<b>すべて</b>が変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671164/356753ae-5098-2261-ac1b-894e6714bcea.png)
ここでは、「すすむ数」という名前を「うごかす数」に変えました。その名前の変数ブロックすべての名前が変わったので、スクリプトは<b>エラーなく動きます</b>。

へんすうの名前を変えるわけはいくつかあります。
<ol><li>forの"i"やスクリプトへんすうの"a"のように、あらかじめ名前が決まっているから</li>
<li>例えば一つの名前のグローバルへんすうを別のスプライトで同じスクリプトを使いたいときのように、ほかの名前と重なるから</li>
<li>もっと別の名前のほうがわかりやすくなるから</li></ol>
1番目と3番目の場合、「rename all（すべての名前をへんこう）」を使って、スクリプトの名前をすべて変えたいと思うでしょう。
一方で、2番目の場合、同じ名前のへんすうを別のスクリプトで使用していたようなときは、それぞれのスプライトをよく見比べて名前を変えるかどうかを決めなければなりません。
そのときは、「なまえをへんこう」で一つずつ名前を変えたほうがいいかもしれません。

<a href="https://qiita.com/wordplugin/items/102d2cac8e4c8c3bbbb9">戻る</a>
PowerAutomate: 日付・時刻の文字列の変換（解析）は parseDateTime で楽になりますよ

# 背景
API の時刻文字列を処理しようとしたら、見かけない関数があったので調査した記録


日本語版の Document は、今日付の更新だが記載無しなので、最近追加されたってとこかな？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/5e3e9c5e-fb4b-4b1d-5f1b-bf9efab09bd3.png)

https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#date-and-time-functions

# 概要
面倒だった日付・時刻文字列の DateTime への取り込み（変換）が
簡単に出来る parseDateTime の紹介

# [parseDateTime](https://docs.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference#parseDateTime) の使い方（英語版）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/243963ac-b2a3-c624-4a4f-2083f1104b47.png)

そのうち翻訳される筈

https://docs.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference#parseDateTime

# 利用例
parseDateTime({Parse したい文字列}, {locale}, {Parse したい文字列の Format 指定})

ってところなので、重要なのは、最後の部分
Parse したい文字列に合わせて <code>yyyy-MM-ddTHH:mm:ss.ffffffK</code> のを当て込めばOK
hh (12h) で、AM/PM を拾う方法は未調査

```automate:Formatのエスケープ含有
parseDateTime('02/20/2022 15h', 'jp-Jp', 'MM/dd/yyyy HH\h')
```

解析結果は、以下
2022-02-20T15:00:00.0000000

```atuomate:よくある日付時刻形式
parseDateTime('2022/02/26 13:34:56', 'jp-Jp', 'yyyy/MM/dd HH:mm:ss')
```

解析結果は、以下
2022-02-26T13:34:56.0000000

```automate:ファイル名とかによく使う形式
parseDateTime('20220226 133456', 'jp-Jp', 'yyyyMMdd HHmmss')
```

解析結果は、以下
2022-02-26T13:34:56.0000000

# 最初から ISO 8601 だった場合に書式変えたい時は？
一番簡単なのは、標準コネクターの [ConvertTimeZone](https://docs.microsoft.com/ja-jp/troubleshoot/power-platform/power-automate/converting-time-zone-power-automate) を使うことだと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0e02c758-9ab9-e146-e795-b16ea50a2f15.png)

Format String 選択だけでもかなり楽。自分で書いても OK だったはず

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3e350ba4-9f20-00df-b874-d2dbe0affeae.png)


# あとがき
これで、Qiita の自己記事目次に日付を付けやすくなったので、仕上げられそう。
特定文字列を含む行のみを抽出しdf化/グラフ化

実験で得られるログデータについて、必要箇所のみを抽出し、グラフ化するまでを備忘録としてまとめる。

```
import pandas as pd
import japanize_matplotlib #日本語文字化け回避

path = 'log.txt'

#テキストファイルの中身をリストとして取得
#ファイルを開き、readlines()で各行を要素とするリストを取得する
with open(path) as f:
    lines = f.readlines()
#readlines()で取得できるリストは行末の改行文字\nを含んでいる。除去したい場合はリスト内包表記で各要素（各行）にstrip()メソッドを適用する。
lines_strip = [line.strip() for line in lines]
print(lines_strip)
#各行がリスト形式で表示される


#各行を要素とするリストからリスト内包表記で条件を満たす行のみを抽出
#今回はTempを含む行を抽出
Temp = [line for line in lines_strip if 'Temp' in line]
print(Temp)
#Tempを含む行のみがリストとして表示される

#リストをデータフレーム化
df = pd.DataFrame(Temp)
#dfをテキストファイルに出力
df.to_csv("test_pd.txt", header=False, index=False)
#解析するデータの出てくる位置が固定(fixed width format)なので、read_fwfを使う
df = pd.read_fwf(
    'test_pd.txt',
    colspecs=[(2, 30), (48, 51), (56, 59), (64, 67), (72, 75), (80, 83)], #ファイル区切り位置を定義
    header=None,
    names=['日時', '温度(00)', '温度(01)', '温度(02)', '温度(03)', '温度(04)'],
    parse_dates=['日時'])

df[['温度(00)', '温度(01)', '温度(02)', '温度(03)', '温度(04)']] /= 10 #今回使用するデータの都合
df.set_index("日時",inplace=True) #index指定
df
#必要な箇所のみのデータフレームの完成

#グラフ化
df.plot()

```

以下、参考にしたリンク先：
https://sohatach.hatenablog.jp/entry/2016/09/29/000547

https://note.nkmk.me/python-grep-like/

https://funmatu.wordpress.com/2018/09/21/python%E3%81%A7%E3%83%AA%E3%82%B9%E3%83%88%E3%82%92%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E5%87%BA%E5%8A%9B/
【Rails】sendメソッドメモ

RailsコンソールでRubyのオブジェクトに対してsendメソッドを実行し、配列の長さを得るとします。

```
$ rails console
>> a = [1, 2, 3]
>> a.length
=> 3
>> a.send(:length)
=> 3
>> a.send("length")
=> 3
```

このときsendを通して渡したシンボル:lengthや文字列"length"は、いずれもlengthメソッドと同じ結果になりました。つまり、どちらもオブジェクトにlengthメソッドを渡しているため、等価なのです。もう１つ例をお見せします。データベースの最初のユーザーが持つactivation_digest属性にアクセスする例です。

```
>> user = User.first
>> user.activation_digest
=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae"
>> user.send(:activation_digest)
=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae"
>> user.send("activation_digest")
=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae"
>> attribute = :activation
>> user.send("#{attribute}_digest")
=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae"
```

最後の例では、シンボル:activationと等しいattribute変数を定義し、文字列の式展開（interpolation）を使って引数を正しく組み立ててから、sendに渡しています。文字列'activation'でも同じことができますが、Rubyではシンボルを使う方が一般的です。

"#{attribute}_digest"
シンボルと文字列どちらを使った場合でも、上のコードは次のように文字列に変換されます。

"activation_digest"
これは、シンボルが式展開されて文字列になったのと同じ仕組みです。
【C#】nameofって何？

個人の備忘録です。

# 結論
- nameof演算子に変数名、型、メンバー、メソッド名などの識別子を与えると、同等の文字列を得られる
- 文字列を指定する場面でnameofを使うことで、コードの修正漏れを防ぎ保守性の高いコードにすることができる
- nameof演算子はコンパイル時に評価され、実行時には影響を与えない

```cs
Console.WriteLine(nameof(System.Collections.Generic));  // output: Generic
Console.WriteLine(nameof(List<int>));  // output: List
Console.WriteLine(nameof(List<int>.Count));  // output: Count
Console.WriteLine(nameof(List<int>.Add));  // output: Add

var numbers = new List<int> { 1, 2, 3 };
Console.WriteLine(nameof(numbers));  // output: numbers
Console.WriteLine(nameof(numbers.Count));  // output: Count
Console.WriteLine(nameof(numbers.Add));  // output: Add
```


# メリット
- メンバなどが変更された際に、コンパイルエラーを表示してくれるため、コードの修正漏れを防ぎ保守性の高いコードにすることできる。
	- 文字列リテラルはコンパイラによって検証されない
	- nameofは式なので指定した変数名やメソッド名が正しいかどうかコンパイル時にチェックされる

```cs:例
switch (property.Name)
{
    case nameof(Model.Field1):  // 修正などされて一致しなくなればエラーが出る
    case nameof(Model.Field2):  // 修正などされて一致しなくなればエラーが出る
        Console.WriteLine("hoge");
        break;
    default:
        break;
}
```

# 文献
- https://tomisenblog.com/c-sharp-nameof/
- https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/nameof
Next.js + Chakra UI でGoogle Fontsのフォントを利用する方法

# やりたい事

Next.js + Chakra UIのプロジェクトでGoogle Fontsのフォントを利用したい。

# やり方

まずは、Google Fontsから使いたいfontのリンクをコピーする。今回は例としてInterを設定します。
```html
<link
  href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
  rel="stylesheet"
/>
```

コピーしたリンクをHead内に貼り付ける
```_app.tsx
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
  return (
    <>
      <Head>
        // 以下を追加
        <link
          href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
          rel="stylesheet"
        />
      </Head>
      <ChakraProvider>
          <Component {...pageProps} />
      </ChakraProvider>
    </>
  )
}
```

ChakraProvider をインポートしている箇所で以下のように theme を上書きする。

```_app.tsx
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
  return (
    <>
      <Head>
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
        <link
          href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
          rel="stylesheet"
        />
      </Head>
      <ChakraProvider
        // 以下を追加
        theme={extendTheme({
          fonts: {
            heading: 'Inter, sans-serif;',
            body: 'Inter, sans-serif;',
          },
        })}
      >
        <Box bgColor={'gray.100'}>
          <Component {...pageProps} />
        </Box>
      </ChakraProvider>
    </>
  )
}
```

最後に next.config.js に以下を追加してGoogle Fontsの読み込みを最適化。
```next.config.js
module.exports = {
   // 以下を追加
   optimizeFonts: true,
}
```

## 参考にした記事

Next.jsのFont Optimizations（Webフォントの最適化）を試してみる
https://zenn.dev/catnose99/articles/bb943c3dc99d89

Google fonts integration · Discussion #2287 · chakra-ui/chakra-ui
https://github.com/chakra-ui/chakra-ui/discussions/2287