OmniAICreator/Qiita-1.07M huggingface dataset:
rails new で指定するフラグによって生成されるコードの違いを確認するリポジトリを作った

`rails new` するとき、いつも `--skip-xxx` するのとしないとのでどのような違いがあるんだっけ? と気になってしまって毎回調べるのが面倒なのでリポジトリを作りました。

## 作ったもの

- https://github.com/snaka/rails_new_flags

このリポジトリでは、 `Rails version` × `flag` という組合わせで `rails new` を実行して出力されたコードを git の tag で参照できるようにしています。

tag の名前は `{Rails version}-{flag}` の形式になっています。

例えば、 Rails 7.0.1 で `--minimal` を指定して出力されたコードは `7.0.1-minimal` という Tag で参照することができます。

現時点で対応している Rails のバージョンは以下です。

- 6.0.x
- 6.1.x
- 7.0.x

## 使い方

見ればわかりそうですが、念のため使い方を書いておきます。



例えば Rails 7.0.1 において、 `--api` というフラグがあり、それを指定することによって生成されるコードがどのように変わるのかを調べたいとします。

[README.markdown に掲載されている表](https://github.com/snaka/rails_new_flags#summary)(以下は抜粋)から `--api` の flag の行で `7.0.1` の位置の :mag: をクリックすると、GitHub 上で差分を確認することができます。

| flag | 6.0.4.4 | 6.1.4.4 | 7.0.1 |
| --- | --- | --- | --- |
| --api | [🔍](https://github.com/snaka/rails_new_flags/compare/6.0.4.4..6.0.4.4-api) | [🔍](https://github.com/snaka/rails_new_flags/compare/6.1.4.4..6.1.4.4-api) | [🔍](https://github.com/snaka/rails_new_flags/compare/7.0.1..7.0.1-api) |

(2022-01-08 時点の差分表示)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8219/cf8ebd7b-c969-2b2c-ba67-f2185d890fe8.png)

上記から、 `--api` を指定することで出力結果に以下の違いがあることがわかります。

- Gemfile に `sprockets-rails`, `importmap-rails`, `turbo-rails`, `stimulus-rails`, `jbuilder`, ... (省略) ... が取り除かれる
- `ApplicationController` の親クラスが `ActionController::Base` から `ActionController::API` に変わる
- `config.api_only = true` の設定が追加されることでミドルウエアの構成が必要最小限のものに変わる
- などなど...

また、自分で URL を記述することで任意の Tag 同士を比較することができます。 GitHub での Tag 間の比較方法については以下のドキュメントを参照すると良いでしょう。

- [Comparing commits - GitHub Docs](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/viewing-and-comparing-commits/comparing-commits)
Unable to resolve AWS account to use. ~ がでた時の対処法

## Unable to resolve AWS account to use. ~ がでた時の対処法

### 環境
```
SiroUz simple-app % cdk doctor
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!                                                                                  !!
!!  This software has not been tested with node v17.3.0.                            !!
!!  You may to encounter runtime issues, and should switch to a supported release.  !!
!!                                                                                  !!
!!  As of the current release, supported versions of node are:                      !!
!!  - ^12.7.0                                                                       !!
!!  - ^14.5.0                                                                       !!
!!  - ^16.3.0                                                                       !!
!!                                                                                  !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ℹ️ CDK Version: 2.3.0 (build beaa5b2)
ℹ️ AWS environment variables:
  - AWS_ACCESS_KEY_ID = ASIA<redacted>
  - AWS_SECRET_ACCESS_KEY = <redacted>
  - AWS_SESSION_TOKEN = <redacted>
  - AWS_STS_REGIONAL_ENDPOINTS = regional
  - AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  - AWS_SDK_LOAD_CONFIG = 1
ℹ️ No CDK environment variables
```
### 事象
以下の記事を参考にして、AWS_ACCESS_KEY, AWS_SECRET_KEY, AWS_SESSION_TOKENを設定した上で、`cdk bootstrap`を実行した結果、タイトル通りのエラーが出た。
https://qiita.com/ShiroUz/items/1827e026c12d2ce3334b

```
Unable to resolve AWS account to use. It must be either configured when you define your CDK Stack, or through the environment
```

### 対処法
上記、参考記事とは別に、AWS_DEFAULT_REGIONを環境変数に設定し、`cdk bootstrap`実行時に、どこにデプロイすれば良いのかを指定することで回避できた。
具体的には以下。

```
ShiroUz simple-app % export AWS_DEFAULT_REGION=us-east-1
ShiroUz simple-app % cdk bootstrap aws://ACCOUNT_ID/REGION
```
ACCOUNT_ID: 自分で所有しているAWSのACCOUNT IDを入力する。マネージメントコンソールで確認できる。
REGION: AWS_DEFAULT_REGIONで設定したリージョンを入力する。

### 原因分析
おそらくbootstrap実行時に、regionの選択が必要なのと、そのリージョンのデフォルト設定であるAWS_DEFAULT_REGIONの設定がされていなかったから通らなかったのだと思っています。
Macでport:5000が使えないときの対処

基本は以下の3つのどれかの方法で解決するはず．
## エラー例
```shell
# もうすでに該当のポートは使用されている
Error response from daemon: Ports are not available: listen tcp 0.0.0.0:5000: bind: address already in use
```

## 1. kill コマンドを実行する
```shell
kill -9 $(lsof -t -i:7000)
```
- `lsof -ti`で稼働しているポート番号を取得
- `kill -9`で強制終了
## 2. MacのPreferenceの確認をする
- ポートを停止しても勝手に立ち上がる
```shell
# 停止
kill -9 $(lsof -t -i:7000)
```

```shell
# 確認
lsof -i:7000
ControlCe 18356 username   18u  IPv4 000000000000000004      0t0  TCP *:afs3-fileserver (LISTEN)
ControlCe 18356 username   19u  IPv6 000000000000000006      0t0  TCP *:afs3-fileserver (LISTEN)
```
- MacOSアップデートによる __AirPlay機能__ の追加によって，5000/7000ポートを占拠することがある
- `ControlCe `てやつが使われているらしい．

System Preference > Sharing > AirPlay Receiver > チェックを外す
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557072/3c24a22f-dab3-ced1-2890-3d27328c4d52.png" width="500">

## 3. pkill後にすぐに接続して停止する
- 最終手段
- すぐ立ち上がるので立ち上がる前に接続
- macのsharingの設定項目がない場合があるとき
- `nc -l`で接続後, `ctrl + c`で接続を停止
```shell
pkill ControlCenter; nc -l 5000
```


#### 参照
https://developer.apple.com/forums/thread/682332
MIRACLE LINUXをWSLで動かす

## MIRACLE LINUXを選んだ理由

CentOS8の避難先として名乗りを上げた、日本製Redhat Enterprise互換ディストリビューションのMIRACLE LINUX。

20年以上の長きにわたり、互換ディストリビューション(有償)として運用されてきた実績を考えても、無償化したMIRACLE LINUXはほかの互換ディストリビューションよりも安心できると思い、使用をすることに。

せっかくだから、WSLもMIRACLEにしたいなということで、WSLのパッケージがないか探したものの、見つからず。
どうしようと思っていた矢先、閃いた。

CentOS8.4のWSLならあるので、そこから移行ツールでいけばいいのか！
試してみることに。

上手くいった（たぶん）ので、共有したい。

## 移行方法

https://blog.yamk.net/posts/20200607-wsl2-centos8/

などを参考に、WSLでCentOS8環境を整える。
この時、

```powershell
wsl --import MILACLELINUX ${env:LOCALAPPDATA}\Packages\CentOS8 rootfs.tar --version 2
```

とすると、起動するときにCentosの名前にならないので、良いかも。

WSLでインポートした、CentOSを実行する。

まず、WSLからDNSの関係でネットができないので、下記を参考に修正

https://qiita.com/kkato233/items/1fc71bde5a6d94f1b982


```bash
vi /etc/wsl.conf
```

```vim
[network]
generateResolvConf = false
```

```bash
vi /etc/resolv.conf
```

```vim
nameserver 8.8.8.8
```

で、一旦、Powershellなどで、

```powershell
wsl --shutdown
```

したあと、WSLに再接続

```bash
dnf -y update
```

して、

https://miraclelinux.hatenablog.com/entry/2021/10/08/120830

を参考に移行ツールをダウンロード＆実行！

```bash
curl -OL https://repo.dist.miraclelinux.net/miraclelinux/migration-tool/migrate2ml.sh
./migrate2ml.sh --core
```

完了!

下記で確認。

```bash
cat /etc/redhat-release
```

して、

```
MIRACLE LINUX release 8.4 (Peony)
```

と表示されれば移行完了。
最後に

```bash
dnf -y update
```

をかけて、最新の状態にします。

以上で完了です。
お疲れさまでした。

## 最後に

MILACLE LINUX 9 が出たら
wslMilacle　とか出ないかな…。
Julia: Genie で MariaDB を使う

こちらと同様のことを Genie で行いました。
[Flask で MariaDB を使う](https://qiita.com/ekzemplaro/items/a5e38772e0fa94323da6)
![genie_mariadb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/3ec11d20-6036-9e37-0bf9-8c6246aaafcc.png)

```julia:routes.jl
using Genie.Router
using MySQL
using DotEnv
# --------------------------------------------------------------------
function mariadb_read_proc()
	DotEnv.config()
	user=ENV["user"]
	password=ENV["password"]
	data_base=ENV["data_base"]

	conn =DBInterface.connect(MySQL.Connection, "127.0.0.1", user, password)
	command = "select * from " * data_base * ".cities;"
	stmt = DBInterface.prepare(conn,command)
	results = DBInterface.execute(stmt)
	rowid = DBInterface.lastrowid(results)
	str_out = ""
	for row in results
		str_out *= row[1] * '\t' * row[2] * '\t'
		str_out *= string(row[3]) * '\t' * string(row[4]) * '\n'
	end
#
	DBInterface.close!(stmt)
	DBInterface.close!(conn)
	str_out
end
# --------------------------------------------------------------------
route("/") do
  serve_static_file("welcome.html")
end

route("/mariadb") do
	str_out = "<pre>"
	str_out *= mariadb_read_proc()
	str_out *= "</pre>"
end
# --------------------------------------------------------------------
```

```text:.env
user='****'
password='******'
data_base='city'
```

フォルダー構造

```text
$ tree -aL 1
.
├── bin
├── bootstrap.jl
├── config
├── .env
├── .gitattributes
├── .gitignore
├── Manifest.toml
├── Project.toml
├── public
├── routes.jl
├── src
└── test
```
enebular editorでダッシュボードが開かない場合の対処方法 (TIPS)

# はじめに

enebularを利用する場合、時間制限(1時間)のあるインターネット上のウェブエディタを使用する選択肢と時間制限のないローカル環境のenebular editorを使用する選択肢があります。
macOS(Monterey)でenebular editorを使用した際にダッシュボード(node-red-dashboard)機能がブラウザで正常に表示されない事象を確認しました。

# 問題

パレットの管理からダッシュボード(node-red-dashboard)機能を追加します。
ダッシュボードのリンクをクリックするとブラウザが起動します。

![editor.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/526a25ce-3811-13ab-9544-039003ba8fb2.jpeg)

しかし、ブラウザにはダッシュボードが表示されませんでした。(Chrome、Firefox、Safari)

![NG.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0af3e45c-a03c-72e6-7823-8812b7a6ec0a.jpeg)

# 解決方法
URLのlocalhost部分を127.0.0.1へ変更します。

```bash
http://localhost:1888/ui/
```

↓↓↓

```bash
http://127.0.0.1:1888/ui/
```

![OK.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/e3762961-1915-ffe1-c992-263a3e519470.jpeg)
LambdaでGlueジョブの実行履歴をひたすら表示する

# 背景・目的
- GlueAPIのget_job_runsは、デフォルト100件（最大200件）しか返さないので、それ以上の結果を知りたい場合は、何度も実行する必要があったのでプログラム化しました。

# 結論
- NextTokenを使う。

# 内容
## APIリクエスト
- NextTokenがある場合と、それ以外で分ける必要がある。

### 初回もしくは、NextTokenがない場合
```
response = glue_client.get_job_runs(JobName=job_name)
```
### NextTokenがある場合
```
glue_client.get_job_runs(JobName=job_name, NextToken=next_token)
```

## コード全体

```
import json
import boto3
import time
import os
import logging
import subprocess

logger = logging.getLogger()
logger.setLevel(logging.INFO)

glue_client = boto3.client('glue')

job_name =""

def init(event):
    logger.info('## ENVIRONMENT VARIABLES')
    logger.info(os.environ)
    logger.info('## EVENT')
    logger.info(event)
    
    global job_name
    job_name = event['job_name']
    
def lambda_handler(event, context):
    init(event)
    response = glue_client.get_job_runs(JobName=job_name)
    response_cnt = 0

    while (True):
    
        for line in response['JobRuns']:
            logger.info(line)
            response_cnt = response_cnt + 1

        logger.info(response)
        
        if response.get('NextToken'):
            next_token = response['NextToken']
            logger.info(next_token)
        else:
            break

        response = glue_client.get_job_runs(JobName=job_name, NextToken=next_token)

    print(response_cnt)

    return {
        'statusCode': 200,

    }

```
## 考察
- 他のAWSのAPIでも同様に、NextTokenの考えはあるので流用可能。

## 参考

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/glue.html#Glue.Client.get_job_runs
HDDクラッシュからのベクトルタイル高速生産

2021年末から2022年始にかけて、FTS Kitを構成していたハードディスクドライブがクラッシュしたことの対策をしていました。

![ 2021-12-30 10.03.46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102082/b6768648-8199-ba98-11a2-a3683c992c54.jpeg)

# 起こったこと
https://x.optgeo.org/ をホストしている Raspberry Pi 4B (m354) には SATA HDD を USB 経由で接続し、そこにベクトルタイルなどのコンテンツを入れていました。この HDD はバスパワーで動かしていました。

今後、ホストするコンテンツを増強することを考えていたため、USB 接続の SSD ドライブを隣の USB ポートに接続したところ、しばらくディスクを回しているうちに HDD から異音が出るようになり、だんだんと壊れていきました。

原因を憶測してみます。二つの USB ドライブに対して必要な電流を Raspberry Pi が供給しきれず、HDD が設計外の動作をしたのではないでしょうか。

壊れた HDD を調べてみると、2011年の製造でした。よく回ってくれたと思います。

# 対策
HDD のファイルシステムの修復も試みつつ、ベクトルタイルは SSD の上に生産し直してみることにしました。optgeo は既存のオープン[ジオデータの運搬活性示数](https://qiita.com/hfu/items/0d53f62e9c1548ea197b)を増すことをする活動なので、何度でも生産し直せますね。

## MacBook Air でのベクトルタイル生産
ただし、Raspberry Pi で生産し直していたのでは、またかなりの長時間がかかってしまいます。そこで、手元の MacBook Air (M1, 2020)　で生産をしてみることにしました。

### NFS
m354 にぶら下がっている SSD に MacBook Air からデータを書き込めるようにするために、NFS で接続をしました。

古くから問題ですが、macOS では初期作成のユーザーについて、uid 501, gid 20 になります。Raspberry Pi OS では　uid 1000, gid 1000 です。

今回は、私は macOS 側に uid 1000, gid 1000 のユーザ fts を作って対応しました。

ちょっと怪しいところはありますが、おそらく問題なく動いています。

### 速度の比較（体感）
やはり、Apple M1 と BCM 2711 では格が違うようで、MacBook Air での生産は Raspberry Pi 4B と比べて格段に速度が速いです。

あまりきっちりと計測する余裕はないので、とりあえず体感の報告をします。

タスク一個の処理速度については、ざっくり 10 倍程度速い気がします。

さらに、タスクを 10 くらい並行で投入しても、この Qiita エントリがストレスなく書ける程度には安定して動いてくれます。

とはいえ、マルチコアを十分に活用してくれる Tippecanoe や tile-join を含むタスクを 10 も並行で投入していると、CPU のアイドルタイムはありません。キーボードがちょうど良い程度に温まり、この季節にはちょうど良い感じになります。

# 今後やりたいと思うこと

- ストレージが失われやすいということを前提としてみると、ベクトルタイルをファイルシステム展開することを避け、SQLiteファイル（.mbtilesファイル）からホストする方法の方がスマートであるように思えます。UNVT には　onyx に代表されるようなそういったサーバの運用実績があるので、これをもう少し汎用化して、気軽に使えるようにしてみたいと思います。すでに通られた道を通り直すような作業になるので、面白いだろうと思っています。ただ、とりあえず現状復帰を優先して、こちらの開発は後回しにしています。

あらゆる持続するウェブサービスはそうだと思いますが、障害があるたびに良くなりますし、障害があるたびに良くなることが重要です。よくしていきたいと思います。

2022年もよろしくお願いします。
CommonLispでExcelファイルを読み込む方法

# はじめに
CommonLispでExcelファイルを読み込む方法です。
Excelファイルの編集は対象外です。
まだ、いろいろと制約がありますが、データを読み込むことは可能です。

# 動作確認環境
AmazonLinux2
roswell
処理系 sbcl

# 使用パッケージ
lisp-xl
https://github.com/defunkydrummer/lisp-xl

このlisp-xlパッケージを使用するのですが、2022年1月1日現在、正常に動作しないようです。
ですので私がforkしたこちらのパッケージを使用してください。
https://github.com/waku893/lisp-xl

※PullRequestしているのですが、反応がない状態です。。

roswellでこのパッケージを使用する場合は、```~/common-lisp/lisp-xl```ディレクトリ内にパッケージ一式を置けば使用できます。

# サンプルExcelファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356164/4fd4301f-d3f9-2dea-b956-3d9050de5c42.png)

# 使用方法
まずは、quickloadします。

```common-lisp
CL-USER> (ql:quickload :lisp-xl)
CL-USER> (in-package :lisp-xl)
```

## データの読み込み方法
```common-lisp
LISP-XL> (defparameter *f* "Book1.xlsx")
*F*
LISP-XL> (with-open-excel-sheet (*f* "Sheet1" sheet)
	   (process-sheet sheet))
Lisp-xl warning: File has no number format information. Proceed with caution! 

"Finalizing rows..." 
(("セルA") ("1+2"))
```
数式のセルは、このように値ではなく数式自体が入ってきてしまいます。
~~値を取得する方法はなく、対策を検討中です。~~ (2022/1/3対応済み）

with-open-excel-sheetマクロを使用しない場合はREADMEにありますように次のように読み込むこともできます。

```common-lisp
(defparameter *s* (read-sheet *f* 1)) ; read first sheet of file *f*
(process-sheet *s* :max-row 100) ;; obtain some rows as cons

;; delete temp file / close sheet
(close-sheet *s*)
```

### process-sheetオプション

|オプション|説明|設定値|
|--------|----|----|
|max-row|読み込み最大行|t|
|initial-row|最初の行|t|
|row-function|行の値をリストとして引数を渡すLambda関数を指定できます。|function|
|silent|process-sheet実行時の標準出力を表示しないようにできます。|t|
|debug-print|デバッグ表示|t|
|output-value|数式ではなく値を表示|t|

例

```common-lisp
LISP-XL> (with-open-excel-sheet (*f* "Sheet1" sheet)
	   (process-sheet sheet :debug-print t))
Lisp-xl warning: File has no number format information. Proceed with caution! 

Row Number = 1 || |A1 (style NIL, type s, value 0)
Row Number = 2 || |A2 (style NIL, type NIL, value 1+2)
"Finalizing rows..." 
(("セルA") ("1+2"))
```
## シート一覧の取得方法

```common-lisp
LISP-XL> (list-sheets *f*)
((1 "Sheet1" "worksheets/sheet1.xml"))
```

## 全シートのデータ取得

```common-lisp
(with-all-excel-sheets (file sh index name) ;bind sheet index and name 
    (format t "~% Working on sheet ~A ~%" name)
    ;; do stuff...
    )
```
これもREADMEからそのまま

# Invalid index 551 for (SIMPLE-ARRAY FIXNUM (512)), should be a non-negative integer below 512. とエラーが出た場合
このエラーが出た場合は、1シートのデータの上限に引っかかって切り落とされています。
```col-process.lisp```の次の値を大きくして回避します。

```common-lisp
(defparameter *expected-number-formats-max-size* 512)
```
Vue.js Vuexで状態を管理する （値を永続化して保存する)

<!-- wp:paragraph -->
<p>前回(<a href="https://www.mkhs.work/wordpress2/?p=223" data-type="URL" data-id="https://www.mkhs.work/wordpress2/?p=223">https://www.mkhs.work/wordpress2/?p=223</a>)で、値を設定しましたが、再描画すると値はクリアされてしまいました。storeで設定した値は永続化されていませんでした。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>永続化するために、vuex-persistedstate（プラグイン）を使います。インストールします。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"bash","langName":"Bash"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-bash" data-lang="Bash"><code>[root@localhost hell_app]# npm install  vuex-persistedstate
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {&quot;os&quot;:&quot;darwin&quot;,&quot;arch&quot;:&quot;any&quot;} (current: {&quot;os&quot;:&quot;linux&quot;,&quot;arch&quot;:&quot;x64&quot;})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/webpack-dev-server/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {&quot;os&quot;:&quot;darwin&quot;,&quot;arch&quot;:&quot;any&quot;} (current: {&quot;os&quot;:&quot;linux&quot;,&quot;arch&quot;:&quot;x64&quot;})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/watchpack-chokidar2/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {&quot;os&quot;:&quot;darwin&quot;,&quot;arch&quot;:&quot;any&quot;} (current: {&quot;os&quot;:&quot;linux&quot;,&quot;arch&quot;:&quot;x64&quot;})

+ vuex-persistedstate@4.1.0
added 3 packages from 2 contributors and audited 1345 packages in 16.238s

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

found 14 vulnerabilities (10 moderate, 4 high)
  run `npm audit fix` to fix them, or `npm audit` for details</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:paragraph -->
<p>store.jsへ vuex-persistedstateを組み込みます。store.jsを修正します。コンポーネントは修正不要です。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-plain"><code>import { createStore } from &#39;vuex&#39;
// vuex-persistedstate を追加
import  createPersisted from &#39;vuex-persistedstate&#39;

export const store = createStore({
    state() {
        return{
            message: &#39;store dataです!!&#39;,
            counter: 0,
        }
    },
    mutations: {
        count_plus: (state) =&gt; {
            state.counter++
        },
        count_reset:(state) =&gt; {
            state.counter = 0
        }
    },
    //追加
    plugins: [
        createPersisted()
    ]
})</code></pre></div>
<!-- /wp:loos-hcb/code-block -->
<!-- wp:paragraph -->
<p>ブラウザで実行、再描画しても値が保持されている事を確認できます。</p>
<!-- /wp:paragraph -->
Kotlinで地図アプリ（ゴミ拾いアプリ）作成。（9日目）


Kotlinで制作している、GoogleMapを使った、自作のゴミ拾いアプリ。制作9日目。

最近は、サーバーサイドでMySQL + PHPや、GoogleMapAPI + JavaScript をやってました。

実機の方で、入念にテストをしてなかったので、確認したところ実機のみでエラーで強制終了するようなので、デバッグ作業をしてみました。



#実機でERROR

実機で試した頃、ERROR発生。

調べるとAPI21の端末で、LocalDateTimeを使ってる事が原因。

ThreeTenABPを使えば解決？

# ThreeTenABPを使う

```gradle:build.gradle
dependencies {
    implementation 'com.jakewharton.threetenabp:threetenabp:1.3.0'
```

```kotlin:MapsActivity.kt
   override fun onCreate(....){
        ....
        AndroidThreeTen.init(this)
```

これで動くように


参考にさせていただいたサイト

https://teratail.com/questions/296435


https://qiita.com/yass97/items/8f449f59eaf1747970d8

実機でちゃんとテストしないと駄目ですね…。



#WEBにGoogleMAP表示


昨日と、今朝、合間でやってますが、どうも上手く動かないです。

公式サンプルや、qiitaで公開されてる方のサンプルなど試していますが、APIキーを変更しただけでは駄目なんですかね…。

Google Cloud PlatformのAPI制限も特にしてるわけでもなく...

ただ、JavaScript のリクエスト回数が増えてないのが興味深い所…。
呼び出されてない？
もしかしたら、ファイヤーウォールなどが原因？
インラインフレームから試しに呼び出すと動くようになって、リクエスト回数も増加しました。

![イメージ7461.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ba92f3b0-1489-5ad2-a4ce-176748f832ba.jpeg)





#まとめ

昨日は、Kotlinで制作したアプリの、実機（API21）のエラー原因の特定に時間がかかってしまい、余り作業が進みませんでした。

Kotlinの勉強を兼ねた、自分用のアプリなので、APIレベルをあまり意識して開発してなかったので、今後は、その辺りも意識したいと思います。

今日は、初詣に行きつつも、JavaScript ＋ GoogleMapAPIで、WEB上で地図表示できるようにしたいところ。。
VueプロジェクトをGitHub Pagesに公開

GitHub Pagesは静的WEBサイトを無料公開できるサービスです。
今回、Vue CLIで作成したプロジェクトをビルドし、GitHub Pages公開するまでの手順をご紹介します。

# 環境
|ソフト|バージョン|
|---|---|
|Vue/CLI| 4.5.12 |
|Node.js|15.3.0|
GitHubのアカウントは取得していることを前提に話を進めます。

# Vueプロジェクトの作成とビルド
任意のプロジェクトを作成して下さい。今回は`test`としました。プリセットの選択はお好みで。

```
vue create test
```
プロジェクトが立ち上がることを確認します。localhostにVueプロジェクトの初期画面が表示されます。

```
npm run serve
```
![スクリーンショット 2022-01-01 8.19.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128611/ea0872ab-c9f3-7c9f-7619-3bcb3cb6d120.jpeg)

プロジェクト直下に`vue.config.js`ファイルを作成し、以下の通り記述します。

```vue.config.js
module.exports = {
  outputDir: 'docs',
  publicPath: './'
}
```

プロジェクトをビルドすると、ファイル群がまとめられた`docs`フォルダが生成されます。
なお、デフォルトのビルド先は`dist`フォルダですが、今回設定で`docs`に変更してます。

```
npm run build
```


#GitHubにレポジトリを作成

　Github上でレポジトリを作成します。レポジトリ名は任意（今回は`test`）の名前を付けます。無料で公開したい場合はPublicにする必要があります。

![スクリーンショット 2022-01-01 7.48.44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128611/b6a92cfd-ff2e-bccc-7a77-91ba3c36aa16.jpeg)
![スクリーンショット 2022-01-01 7.49.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128611/027928b0-3053-26b0-f8e2-9e1d69738d9e.jpeg)


プロジェクトをgit管理して、GitHub上に作成したレポジトリにpushします。

```
git init
git add -A
git commit -m "first commit"
git branch -M main
git remote add origin <リモートレポジトリＵＲＬ>
git push -u origin main
```
GitHub管理画面のSettingsからPagesを選びbranchは`main`、folderは`docs`を選んで保存します。
![スクリーンショット 2022-01-01 9.56.36のコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128611/979d9af8-30e8-ef78-0492-c4a10a04ac1c.jpeg)

https://<アカウント名>.github.io/<レポジトリ名>/に公開されます。
（反映には若干の時間を要します）

![スクリーンショット 2022-01-01 10.07.18のコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128611/6ab7993a-ef40-a11b-1dc3-7f53c224d023.jpeg)
iPhoneで写真を撮るだけで３Dモデルをつくれる。すごいぞアップル。

#写真を撮るだけでリアルな3Dモデルをつくる方法
Appleのツールをつかって、かんたんに３Dモデルをつくります。

![IMG_0248.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/227beb1c-1f37-ede2-6d23-3065515c9bb2.png)<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/8f3affcc-7695-6afd-cd9d-19b7badf4985.png"width=300>


<img src="https://user-images.githubusercontent.com/23278992/147841824-66e4d5b3-e3ce-4931-b7fb-6c772db8534b.gif">
【かめとキャプチャされたかめ】

#リアルな３Dモデルをつくりたい
使える３Dモデルがたくさんあれば、ARやゲームのアプリケーションに使えます。
だけど、ARやゲームなどで自由に使える３Dモデルは、探してもなかなか少なかったりします（個人的見解）。
ダウンロードサイトなど見ても、綺麗なコンテンツは有料だったり。

#３Dモデルをつくるのは大変そう
と言って自分で作るには、３Dソフトでモデリングしたり変換したり、と、むずかしそう。

#AppleのRealityKitをつかえば写真を撮るだけでモデルができる
というところで、2021年にAppleが写真を撮るだけで3Dモデルをつくってくれるツールを出しました。
これがわりとかんたんで、リアルなオブジェクトをつくれます。
顕著な物体を認識して、背景や床からもきちんと分離してくれます。

#手法

###１、写真を撮る
手持ちのカメラ（iPhoneでオッケー）で、３Dにしたいものの写真を全方向から撮ります。
![IMG_0248.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/227beb1c-1f37-ede2-6d23-3065515c9bb2.png)
僕は普通にカーペットの上にぬいぐるみを置いて、横から360度、上からも半球型に覆うように撮りました。
条件は、
・なるべく明るいところで
・対象の全体がなるべく大きく写るように
・写真と次の写真の間で対象が７０％以上オーバーラップするように、こまめに撮りました。

200枚撮りました。
macに送ってフォルダにまとめます。

###２、アップルのツールをダウンロードする

開発者サイトから入手できます。

https://developer.apple.com/documentation/realitykit/creating_a_photogrammetry_command-line_app/

Xcodeでビルドすると、HelloPhotogrammetryというファイルがproductフォルダにできますので、ファインダーで開いて場所を確認します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/48feb220-099a-d121-daa2-823f3d8f0ce0.png" width=400>


###３、実行

```shell
<HelloPhotogrammetryのパス>　<入力画像のフォルダ> <出力ファイルのパス　.usdzをつける>
```

*ルートからの絶対パスが必要です。

これでUSDZモデルが生成されます。
200枚の写真で20分ぐらいかかりました。リンクをiPhoneでクリックすると、かめのUSDZモデルをARで試せます。

https://firebasestorage.googleapis.com/v0/b/sincere-nirvana-292404.appspot.com/o/model.usdz?alt=media&token=96083418-ed43-435c-bce4-6fed085bbd7b

#３Dコンテンツの充実を
この手法で作ったモデルを３Dモデル共有サイトにアップしている人もいますし、
いろんな人がいろんなものをスキャンすることで、３Dモデルやコンテンツが充実していけばいいですね。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
【Project Euler】Problem 3: 最大の素因数

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 ３： 最大の素因数

原文 [Problem 3 Largest prime factor](https://projecteuler.net/problem=3)

**問題の要約：600851475143の最大の素因数を求めよ**

本来は素数を生成するプログラムから書くところなのでしょうが、ちょっと安易にsympyのnextprimeを使って書きました。このnextprimeは使い勝手が良いので覚えておくと便利だと思います。

```python
from sympy import nextprime 

N = N1 = 600851475143
p = 1
while N1 > 1:
  p = nextprime(p)
  if N1 % p == 0:
    N1 //= p
print(f"Answer : {p}")
```

さらに楽をするのであればfactorintを使えば一発です。

```python
from sympy import factorint

print(list(factorint(600851475143).keys())[-1])
```
（開発環境：Google Colab）
Nodejs で利用できる WebRTC SFU ライブラリの mediasoup の デモを AWS で動かしてみる

## 経緯

- 音声通話の技術検証として、WebRTC SFUに着目
- リモート勤務の人にもデモを触ってもらうため AWS 上で構築

## mediasoup-demo

- mediasoup のデモ版 (https://github.com/versatica/mediasoup-demo)
- クライアント、バックエンドがセットになっている
- https://v3demo.mediasoup.org/ でオンラインデモが試せる(カメラ、マイクの接続あり)

## 構築

1. EC2で Ubuntu を起動し、必要モジュールをインストール
2. GitHub から mediasoup-demo を clone する
3. ドメインの取得及び証明書の取得を行う
4. mediasoup-demoを起動する

### EC2で Ubuntu を起動し、必要モジュールをインストール

- Ubuntu 20.04 LTS を利用
- t3.medium / SSD 10GBで起動
- Google Chrome で動作確認
- UDPを解放する必要があるので、AWSのセキュリティグループに注意
- 必要なモジュールは以下の通り (https://mediasoup.org/documentation/v3/mediasoup/installation/)
  - nodejs 12.0 以降
  - python 3.6 以降 & python3-pip
  - build-essential (make 及び gcc)
  - yarn (npm で install)
  - nginx
  - certbot-nginx

```bash
sudo apt update
# npm install
sudo apt install npm -y
# nvm install
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
# node 14.x install
nvm list-remote | grep v14
# v14.x latest
nvm install v14.18.2
nvm use v14.18.2
# 確認
node -v

# python3
sudo apt install python3 python3-pip -y

# build-essential
sudo apt install build-essential -y

# yarn
sudo npm -g install yarn

# nginx
sudo apt install nginx -y

# certbot
sudo apt install certbot python3-certbot-nginx -y
```

セッション落として再接続

### GitHub から mediasoup-demo を clone する

```bash
cd ~
git clone https://github.com/versatica/mediasoup-demo
```

### ドメインの取得及び証明書の取得を行う

- セキュリティグループの設定でTCP/UDPを解放する
  - TCP/80, TCP443
  - TCPとUDPの well-known ポート以外(1024-65535)を解放 (こんなに開けなくても良い)
- AWS で Elastic IP を取得。起動した EC2に割り当て
- 自由に利用できるドメインがあれば A レコードで 取得した Elastic IP を追加。
  - 手頃なドメインが無ければ freenom とかで取得
- nginx の設定を変更
  - /etc/nginx/sites-available/default を変更
  - TCP/3000 がクライアントアプリ待ち受けになるので、ポートフォワードしたいひとはしてください

```bash

sudo vim /etc/nginx/sites-available/default

### ここを変更
server_name xxx.example.com
```

- certbot で証明書を取得
  - 対話は良い感じに設定してください。省略します

```bash
sudo certbot --nginx
```

- certbot で取得した証明書を mediasoup-demo/server/certs にコピー

```bash
# certbot で取得した証明書のパスはドメインで変わります
mkdir ~/mediasoup-demo/server/certs
sudo cp /etc/letsencrypt/live/xxx.example.com/fullchain.pem ~/mediasoup-demo/server/certs/fullchain.pem
sudo cp /etc/letsencrypt/live/xxx.example.com/privkey.pem ~/mediasoup-demo/server/certs/privkey.pem
sudo chown ubuntu:ubuntu ~/mediasoup-demo/server/certs/fullchain.pem
sudo chown ubuntu:ubuntu ~/mediasoup-demo/server/certs/privkey.pem
```

### mediasoup-demoを起動する

- server と app (クライアント) の両方を起動する必要がある
  - セッション2つ開くなりしてください

```bash
# サーバ
cd ~/mediasoup-demo/server
cp config.example.js config.js
yarn install
```

- サーバ側はconfig.jsの書き換えが必要
  - domain を 自分のドメインに変更
  - listenIp を 0.0.0.0 に変更
  - 以下のような箇所が二つあるので両方変更

```js
listenIps : [
  {
    ip          : process.env.MEDIASOUP_LISTEN_IP || '0.0.0.0',
    announcedIp : '1.2.3.4' // ここをelastic ip に変更
  }
]
```

- サーバ側の起動

```
yarn start
```

- クライアント側の起動

```bash
# クライアント
cd ~/mediasoup-demo/server
yarn install
yarn start
```

- エラーで怒られた場合は、モジュールが足りてない可能性が高いので追加でインストール
- 起動確認
  - https://あなたのドメイン:3000 で https://v3demo.mediasoup.org/ と同じ画面が出てくれば OK
  - 左上が CONNECTになっていればOK
MicroPythonを使ってみる（その３：mp3ファイル再生）

# DFPlayer miniを使ってmp3ファイルを再生
秋月電子などで売られている[DFPlayer mini](https://akizukidenshi.com/catalog/g/gM-12544/)をMicroPythonを使って制御する。

## DFPlayer mini
DFPlayer miniは、YX5200-24SSというmp3ファイルをデコードするチップ、8002というアンプ、マイクロSDスロットなどを搭載しており、マイコンなしでもmp3ファイルの再生が可能である。が、ここでは、ESP32を使ってmp3ファイルを再生する。[Wiki](https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299)にあり。データシートもそこからたどれる。

## Micropythonソースコード
だいたいこの手のものは、githubなどを探せば見つかる。いくつか見つけたが、[ここ](https://github.com/lavron/micropython-dfplayermini)にあるものを利用した。

## 解説
### UART
マイコンからはUART経由で制御を行う。用いるESP32には3つのUARTがある。MicroPython的には、UART0、UART1、UART2である。そのうち1つ（UART0）はPCとの接続用（USB経由）に使われており利用不可。UART1またはUART2とが使える。ハードウェアシリアルとしては、UART1ではTX=10/RX=9（GPIO番号）、UART2ではTX=17/RX=16となっているが、使用した[ESP32用Micropython Firmware](https://micropython.org/resources/firmware/esp32spiram-20210902-v1.17.bin)では、ハードウェアシリアルを使うことができなかった。詳細は調査していないが、無理やりセットしてもリセットがかかってしまう。今回は、ソフトウェアシリアルを使うことにし、
- TX = 4
- RX = 2
と設定した。

### SDカードのフォルダ及びファイルの構成
DFPlayer miniにて、mp3ファイルをSDカードに置く構成については、[このサイト](http://markus-wobisch.blogspot.com/2016/09/arduino-sounds-dfplayer.html)の”Modes of Operation”の説明がわかりやすい。今回は、mp3というフォルダーを作り、その配下に、再生する順に0001.mp3、0002.mp3、0003.mp3、、、のようにファイルを置く。

### ソースコード
#### ライブラリ（dfplayermini.py）
まずはコアである[dfplayermini.py](https://github.com/lavron/micropython-dfplayermini/blob/master/dfplayermini.py)の補足説明。

```python
class Player:
    def __init__(self, pin_TX, pin_RX):
        self.uart = UART(1, 9600, tx=pin_TX, rx=pin_RX)
        self.cmd(0x3F)  # send initialization parametres
        self._fadeout_timer = Timer(-1)

        self._volume = 15
        self._max_volume = 15
        self._fadeout_speed = 0
```
- ここでは、UART1を利用。UART2を使いたいときは”2”を指定する。
- ボーレートは9600bps固定。
- max_volumeは0-30まで指定可能。

このファイルに記載されているコマンドについては、[YX5200-24SSデータシート](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjf4bLe_8PzAhXHwosBHTEDBlQQFnoECAMQAQ&url=https%3A%2F%2Fcdn.hackaday.io%2Ffiles%2F936504006721600%2FYX5200-24SS%25C3%258A%25C2%25B9%25C3%2593%25C3%2583%25C3%258B%25C2%25B5%25C3%2583%25C3%25B7%25C3%258A%25C3%25A9V1.6.zh-CN.en.pdf&usg=AOvVaw2IuX8-Sm2bgy7Mk0mM8URN)を参照するとよい。

#### 再生サンプルコード
[こちら](https://github.com/lavron/micropython-dfplayermini/blob/master/example.py)の簡略版である。

```python
from dfplayermini import Player
from time import sleep
import sys

music = Player(pin_TX=4, pin_RX=2)

sleep(1)
music.volume(10)
sleep(1)
music.play(2)
sleep(10)

music.play(6)
sleep(30)

sys.exit()
```

### 実験
下記写真の中央に位置するのが、DFPlayer miniである。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/bc800712-c8d8-2c71-3972-30bf63b55ee8.jpeg", width=70%>

結果的には動作したのであるが、コマンド設定（含む音声再生）前に、ある程度Sleepを入れないと動作しないことがしばしば発生。Pythonはインタープリターなので、対話形式でコードを入力したときは、ほぼ問題なく設定および再生ができていた。また、ハードウェア不良らしき状況もあった（DFPlayer miniの電源入れ直しが必要だったこともあり）。上記ライブラリ内にある、module_reset()なども試すとよいかと思われる。個体の問題なのか、YX5200-24SSの制御の仕方が不適切なのか、詳細は未調査。
Re:Viewの表紙が拡大表示されてしまう

# Re:Viewの表紙が拡大表示されてしまう

## 問題

config.ymlに
coverimage: cover.jpg
と入れると、pdfを作成時に、images/cover.jpgを表紙にしますが、なぜか拡大した画像になります。

![スクリーンショット 2022-01-01 8.21.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263486/89958844-595a-353a-44df-fa0709ea7974.png)

templeteにtechboosterさんのものを使っていると、

```config.yml
# TechBooster Re:VIEW-Template独自設定
techbooster:
  # 表紙および裏表紙を実寸ではなく仕上がりサイズにリサイズするか
  # texdocumentclassでcover_fit_page=trueを付けるのと同じ
  cover_fit_page: true
  # 裏表紙画像指定。画像はimages/から探索される
  # backcoverimage: backcover.jpg
```

表紙をfitする機能がありますが、アスペクト比が合いません。

![スクリーンショット 2022-01-01 8.28.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263486/f0eda4db-4c42-2258-db72-ad4e49bd86fd.png)

## 解決策

sty/review-custum.styに以下の処理を追加します。

```review-custom.sty
% for user-defined macro
% 縦横比を変えたくない（ずれた部分は白くなる）場合は以下を利用
\def\review@coverimageoption{width=\paperwidth,height=\paperheight,keepaspectratio}%
```

これで正常なアスペクト比で拡大表示できます。

![スクリーンショット 2022-01-01 8.32.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263486/417ef691-e234-c09d-5beb-3eda1eb75445.png)
プロパティ記述子って何ですか？

JavaScript オブジェクトのプロパティは、「書き込み禁止かどうか」とか「各種設定可能かどうか」といった、いくつかの属性を持っています。
これらを**プロパティ属性**といいます。

プロパティ属性は、**プロパティ記述子**というオブジェクトのプロパティとして保持されています。
プロパティ記述子は、**データ記述子**と**アクセサー記述子**があります。

# データ記述子

|属性|説明|
|---|---|
|value|プロパティに設定された値|
|configurable|プロパティ記述子の設定変更可否|
|enumerable|for...inループの列挙可能性|
|writable|値の変更可否|

# アクセサー記述子

|属性|説明|
|---|---|
|get|ゲッターと呼ばれる関数を格納する場所|
|set|セッターと呼ばれる関数を格納する場所|

# データ記述子の確認
```javascript
const obj = {prop: "値"};
const propDesc = Reflect.getOwnPropertyDescriptor(obj, "prop");
console.log(propDesc); // => { value: '値', writable: true, enumerable: true, configurable: true }

const obj2 = ['りんご', 'バナナ'];
const propDesc2 = Reflect.getOwnPropertyDescriptor(obj2, 'length');
console.log(propDesc2); // => { value: 2, writable: true, enumerable: false, configurable: false }
```
Vue.js Vuexで状態を管理する （値の設定)

<!-- wp:paragraph -->
<p>前回(https://www.mkhs.work/wordpress2/?p=213)では storeで設定した値を返すサンプルを作成しました。今回は値を設定するサンプルです。値の管理はstore側で実施していますので、store.jsに設定します。counterを増やすサンプルです。mutationsを定して、counterを増やす、クリアするオブジェクト定義をします。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"js","langName":"JavaScript"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-js" data-lang="JavaScript"><code>import { createStore } from &#39;vuex&#39;

export const store = createStore({
    state() {
        return{
            message: &#39;store dataです!!&#39;,
            counter: 0,
        }
    },
    mutations: {
        count_plus: (state) =&gt; {
            state.counter++
        },
        count_reset:(state) =&gt; {
            state.counter = 0
        }
    },
})</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:paragraph -->
<p>store.jsを呼び出すコンポーネントのサンプルです。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"js","langName":"JavaScript"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-js" data-lang="JavaScript"><code>&lt;template&gt;
  &lt;div class=&quot;alert alert-primary&quot;&gt;
    &lt;p&gt; {{ $store.state.message }}&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;btn btn-secondary&quot; v-on:click=&quot;$store.commit(&#39;count_plus&#39;)&quot; v-on:ctrl=&quot;$store.commit(&#39;count_reset&#39;)&quot;&gt;
    &lt;a class=&quot;h5&quot;&gt;
      clicked: {{ $store.state.counter }}
    &lt;/a&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
  import {reactive} from &#39;vue&#39;

  export default {
    setup(){
      const data = reactive({
      })
      return {
        data
      }
    }
  }
&lt;/script&gt;
</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:paragraph -->
<p>ブラウザで動作確認します。</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":228,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="https://www.mkhs.work/wordpress2/wp-content/uploads/2022/01/image.png" alt="" class="wp-image-228"/></figure>
<!-- /wp:image -->
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146872/1378fdae-7418-31f1-5ed2-f86f676a0889.png)

<!-- wp:paragraph -->
<p>値は永続化されていないので、リロードするとゼロにクリアされます。</p>
<!-- /wp:paragraph -->
Focus

Code

```Python:focus.py
import tkinter
import matplotlib.pyplot as plt
from matplotlib.colors import rgb2hex
import time
import sched

cmap = plt.get_cmap("jet")
def score_to_rgb(score):
    return rgb2hex(cmap(1-score/10))
    
pad_font=(None, 70)
main_font=(None, 13)
text_di={'title':'title','x':'x axis', 'y':'y axis'}
mins=30
current_target=None
target_text=None

main = tkinter.Tk()
main.geometry("500x500")
 
hist_scores=[]

ninekeys='789456123'
pad_text="{} {} {}\n{} {} {}\n{} {} {}".format(*[s for s in ninekeys])
key_to_n={k:v for k, v in zip([s for s in ninekeys], [3,4,5,2,3,4,1,2,3])}
label_title=tkinter.Label(master=main, font=main_font, text=text_di['title'])
label_y = tkinter.Label(master=main, font=main_font, justify='left', anchor="w", text=text_di['y'])
label_pad = tkinter.Label(master=main, font=pad_font, text=pad_text)
label_x = tkinter.Label(master=main, font=main_font, justify='right', anchor="e", text=text_di['x'])
label_setting = tkinter.Label(master=main, font=main_font, text='pop up every {} mins'.format(str(mins)))

label_title.place(relx=0.05, rely=0)
label_y.place(relx=0.05, rely=0.05)
label_pad.place(relx=0.1, rely=0.1)
label_x.place(relx=0.15, rely=0.8)
label_setting.place(relx=0.2, rely=0.9)

def text_pad_reset():
    label_pad["text"]=pad_text
    main.deiconify()
    label_pad.focus_set()
    
def input_key(event):
    key_name = event.keysym
    if key_name in [s for s in ninekeys]:
        score=key_to_n[key_name]
        hist_scores.append(score)
        avg_score=sum(hist_scores[-5:])/len(hist_scores[-5:])
        event.widget["bg"]=score_to_rgb(score)
        event.widget["text"]='{}:{}\navg:{:.2f}'.format(key_name,score,avg_score)
        main.configure(bg=score_to_rgb(avg_score))
        label_pad.after(300, main.withdraw)
        label_pad.after(2000, text_pad_reset)
        
def when_click(event):
    popupwin(event)
    
def close_win(top, entry, event):
    event.widget["text"]=entry.get()
    top.destroy()

def popupwin(event):
    top= tkinter.Toplevel(main)
    top.geometry("750x100")
    entry= tkinter.Entry(top, width= 25)
    entry.pack()
    button= tkinter.Button(top, text="OK", command=lambda:close_win(top, entry, event))
    button.pack(pady=5, side= tkinter.TOP)

def close_win_mins(top, entry, event):
    global mins
    mins=int(entry.get())
    event.widget["text"]='pop up every {} mins'.format(str(mins))
    top.destroy()

def popupwin_mins(event):
    top= tkinter.Toplevel(main)
    top.geometry("750x100")
    entry= tkinter.Entry(top, width= 25)
    entry.pack()
    button= tkinter.Button(top, text="OK", command=lambda:close_win_mins(top, entry, event))
    button.pack(pady=5, side= tkinter.TOP)
    
def when_click_mins(event):
    popupwin_mins(event)

def on_closing():
    main.destroy()

label_pad.bind("<KeyPress>", input_key)
label_title.bind("<Button>", when_click)
label_y.bind("<Button>", when_click)
label_x.bind("<Button>", when_click)
label_setting.bind("<Button>", when_click_mins)
main.protocol("WM_DELETE_WINDOW", on_closing)
main.attributes("-topmost", True)

label_pad.focus_set()
main.mainloop()
```
PowerShellの色を変える

## 現象
Windows PowerShellからsshで接続後、lsすると全く文字が見えない。
オプションで背景色や一部の文字色を変更可能だが、細かく設定できない上に
変更できない文字色がクソ配色なせいで、どんな色にしても何かの文字が見えなくなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490864/deaaf54e-53b0-e71d-7679-252bab3511f9.png)

## 解決方法
MicrosoftがPowerShellの色変更ツールを提供している。
GitHubからzipファイルがダウンロードできる。

https://github.com/microsoft/terminal/tree/main/src/tools/ColorTool

zipの中身はexeファイルとschemesフォルダ（配色セットのファイルが格納されている）。
zipを適当な場所に解凍し、PowerShellで下記コマンドを実行。

```shell
$ .\path\to\ColorTool.exe -b campbell.ini
```

設定後の配色はこんな感じ。PowerShellウィンドウを閉じると、設定はクリアされるため注意。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490864/f1c9cda9-957f-5a34-4c65-95c2d37170b9.png)


## 永続化について
PowerShell起動時に実行されるファイル（.bashrcみたいなもの）で前述のコマンドを実行すれば
起動するたびに自動で設定反映することができる。

以下、作業手順。

1. 起動時に実行されるファイルを調べる
    下記コマンドで調べられる。
 
    ```shell
    $ $profile
    C:\Users\xxxxxxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
    ```

1. 格納フォルダを作成
    自分の環境にはWindowsPowerShellフォルダが存在しなかったため、フォルダを新規作成。

1. ps1ファイルを作成
    ひとまず空のテキストファイルでMicrosoft.PowerShell_profile.ps1を作成。

1. ColorToolを配置
    C:\Users\xxxxxxx\Documents\WindowsPowerShell\ColorTool\ColorTool.exe に配置。
    schemesフォルダもzipの構成のまま配置した。
    ColorToolはどこに置いてもよいが、ps1ファイルと一緒に置くのがよいと判断した。

1. ps1ファイルを記述

    ```
    C:\Users\xxxxxxx\Documents\WindowsPowerShell\ColorTool\ColorTool.exe -b campbell.ini
    ```    

1. ps1ファイルの実行権限を付ける
    Linuxみたいにファイルに付けるのではなく、PowerShellがps1ファイルを実行する・しないを設定する。
    管理者モードでPowerShellを起動し、下記コマンドを実行する。

    ```shell
    Set-ExecutionPolicy RemoteSigned
    ```

1. 動作確認する
    新たにPowerShellを起動し、ColorToolが自動で動けば成功。

---
フォルダ構成まとめ

```
C:\Users\xxxxxxx\Documents\WindowsPowerShell
├───Microsoft.PowerShell_profile.ps1
└───ColorTool
    ├───ColorTool.exe
    └───schemes
        ├───campbell.ini
        ├───   :
        ├───
```
【React】ライフサイクルについて【入門】

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

##React 入門

###ライフサイクルとは
ライフサイクルとはコンポーネントが画面に登場してから退場するまでの「時間の流れ」を指します。

大きく分けて3つの期間があります。

- Mounting（配置期間）
- Updating（変更期間）
- Unmounting（破棄期間）

それぞれの期間で必要な処理を行いたい場合に、ライフサイクルメソッドが必要になります。

###それぞれの期間で使用できるメソッド
それぞれの期間においてクラスコンポーネントで以下のメソッドが使用できます。

#### Mounting（配置期間）
Webページへアクセスした時など、UIがコンポーネントに配置される期間です。

`constructor()`
stateの初期化時に実行されます。

`render()`
仮想DOMを描画する時に使われます。

`componentDidMount()`
最初のrender()が呼ばれた後の1度だけ呼ばれます。
リスナーの設定やAPI通信に使われます。

#### Updating（変更期間）
ユーザの操作などにより、コンポーネントのデータやUIが変更される期間です。

`render()`
2回目以降のrender()はupdating時になります。
stateやpropsの変更がトリガーとなりレンダーが行われます。

`componentDidUpdate(prevProps, prevState, snapshot)`
再render()後に呼ばれます。
引数は省略できます。
スクロールイベントや条件付きイベントで使われます。
setState（）をするときには、無限ループにならないように条件をつける等注意が必要です。


#### Unmounting（破棄期間）
別のWebページへ遷移する前など、現在のコンポーネントを破棄するための期間です。

`componentWillUnmount()`
現在のコンポーネントを破棄する直前に呼ばれます。
タイマーの停止処理等、リスナーの解除やリソースを開放するために使われます。



## まとめ

- ライフサイクルにはMounting・Updating・Unmountingの期間がある。
- ライフサイクルメソッドはクラスコンポーネントで使用する（関数コンポーネントでは、React Hooksを使用）
- 主要なライフサイクルメソッドは、constructor(),componentDidMount(),render(),componentDidUpdate(),componentWillUnmount()の5種類
Windowsショートカットキー

| 処理内容 | ショートカットキー |
|:-:|:-:|
|スクリーンショット(切り抜き)	|Shift + Windows + s|
|コピー履歴	|Windows + v|
|消したタブを復活	|Ctrl + Shift + t|
|画面録画	|Windows + Alt + r|
|スクリーンショット	|Windows + Alt + PrintScreen|
|全て最小化	|Windows + d|
|画面ロック	|Windows + L|
|スリープ	|Windows + x →U→S|
|シャットダウン	|Windows + x →U→U|
|仮想デスクトップ	|Windows + Ctrl + d|
|仮想デスクトップ削除	|Windows + Ctrl + F4|
ElixirでCLIを作るときに静的ファイルの扱いで気をつけること

## はじめに
magical_makeというmake commandを叩くときに魔方陣が描画されるCLIを作りました。
その時に静的なファイル諸々の扱いを学べたので、記しておきます。

https://github.com/tashirosota/magical_make

## 静的ファイルの配置場所
### 目撃したpath
```
 - lib/assets/*
 - lib/hoges/* ※ imagesやtexts等
 - assets/*
 - public/*
 - priv/*
```

### 採用path
```
 - priv/assets/
```

Phoenix等のライブラリでは`priv/*`への配置が多かったです。多分Erlangの作法だと思います。

> priv - Optional. Used for application specific files.

https://www.erlang.org/doc/design_principles/applications.html

`:code.priv_dir(:my_app)` というfunction（Erlangから参照）も用意されている為、こちらの構成がよさそうでした。Phoenixだとmigration系のファイルもここに配置されます。

### `priv/assets/aaa.txt` |> File.read が落ちる
こちらのコマンド、開発中のときは問題ないのですが、hexやescript等でコンパイルしてしまうとpathの参照ができなくなってしまいます。
escriptの方でもサポートはしていないようです。

> Note: escripts do not support projects and dependencies that need to store or read artifacts from the priv directory

https://hexdocs.pm/mix/1.4.5/Mix.Tasks.Escript.Build.html

### コンパイル後のライブラリで静的ファイルを上手く参照するには
調べてみると ` Application.app_dir` や　`:code.priv_dir` を用いた参照であれば上手くいきそうな情報がありましたが、なんともうまくいきません。

さらに探すと以下forumに辿り着きました。

https://elixirforum.com/t/is-it-possible-to-include-resource-files-when-packaging-my-project-using-mix-escript/730

この中で José Valiam の回答で答えを発見。

> To confirm: although priv is the appropriate place, we can’t load files from priv inside escripts. What I usually do is to load the file at compilation time and store it as a module attribute:

```elixir
@external_resource "priv/foo/bar"
@bar_contents File.read! "priv/foo/bar"
def bar_contents, do: @bar_contents
```

https://elixirforum.com/t/is-it-possible-to-include-resource-files-when-packaging-my-project-using-mix-escript/730/11

同じ方法で確認

```elixir
defmodule MagicalMake.Make do
  @text elem(File.read("priv/assets/aaa.txt"), 1)

  def text do
    @text
  end
end
MagicalMake.Make.font
=> aaa
```

成功！！！
Qiitaの基本的な記述方法

#見出しを書くとき
「#」を先頭に持ってくる

↑のは「#見出しを書くとき」って書いてる．
「#」の数を増やすと見出しが小さくなる（6段階）
#1個のとき
##2のとき
###3個のとき
####4個のとき
#####5個のとき
######6個のとき
5と6は大きさ同じらしい．なぜだ．

#####これは太字にしたい時に使うのかな（#*5）
↑そんなことはない、太字は別にある
これだと自動目次に表示されてしまう

#枠：部分的なやつ
部分的に背景色をグレーで使いたい時は
こんな感じでバックオート`「shift+@」`でくくる
`｀こんなかんじに｀`←これは全角だけど．．．

このバックオート使った後に表示が変になる時は改行入れたりするとなおる．


#枠：めっちゃよく見るやつ
```
｀｀｀
ここにテキスト
｀｀｀
```
バックオート3つでテキストをくくる（改行してテキストを挟むこと）
これがあるとめっちゃQiitaっぽい

#枠上部にファイル名などのタブを表示
```:こんなかんじ
↑タブの表示．
```
```:記述方法
｀｀｀:任意のタブ名
テキスト
｀｀｀
```

:の前に言語を指定すればいい感じにライティングしてくれる
例えば．．．

```python:helloworld.py
print("Hello world")
```

こんな感じに色付けてくれる
書き方は↓

```
｀｀｀python:helloworld.py
print("Hello world")
｀｀｀
```

**数式を書くには**

```
｀｀｀math
e^{i\pi} = -1
｀｀｀
```

というように、`math`をつける

```math
e^{i\pi} = -1
```
これでtexライクに数式がかける

`$2^3$`みたいに"$"で囲えば数式埋め込みもできる

> x^2 + y^2 = 1をインラインすると$x^2 + y^2 = 1$になる

※バックスラッシュは2本（Markdownのエスケープと衝突するため）
例
> $a = \\{ 1, 2, 3\\}$

```
$a = \\{ 1, 2, 3\\}$
```


#注釈
本文中に`[^1]`や`[^example]`のように文字列を記述すると, 注釈へのリンクを表現できる．
本文中に`[^1]: ...`と記述すると注釈内容を記述できる[^1]
[^1]: 注釈内容を記述する位置は,本文の途中でも末尾でもok


#箇条書きについて

`冒頭に「- 」を入れる`
黒点/白点でこんな感じに表示される↓↓

- apple watch
    - series 7
- iPad
    - iPad pro 11インチ
    - iPad mini
- mac
    - MacBook air M1


実際に書いてるのはこんなかんじ

```:箇条書きの書き方
- apple watch
    - series 7
- iPad
    - iPad pro 11インチ
    - iPad mini
- mac
    - MacBook air M1
```

#番号付きリスト
1. 「番号. テキスト」
1. 番号は関係ない
    1. 毎回1番でもいいし，
    1. でたらめな番号にしても
1. 上から順番にしてくれる

```:番号付きリストの書き方
1. 「番号. テキスト」
1. 番号は関係ない
    1. 毎回1番でもいいし，
    1. でたらめな番号にしても
1. 上から順番にしてくれる
```


#引用
>こんな感じになる．
>「>こんな感じになる．」って打ってる
>>「>」を連続で重ねると入れ子にできる
>>「>>こんなかんじ」

#リンク
[ここ](https://www.google.com)をクリックするとgoogleに飛ぶよ
記述方法は`[title](URL)`でtitle文にリンクを紐づけられる

ちなみにこの記事は[こちら](https://qiita.com/shizen-shin/items/a997bc228fa2850c9fce#%EF%BC%95%E8%A6%8B%E5%87%BA%E3%81%97)を参考にさせていただいています．


#太字

大事な部分は`**`で囲って**太字にできる**

```:太字
**ここが太字になる**
```

#打ち消し
テキストを`~~`で囲って打ち消すことができる
~~こんなかんじ~~

```:打ち消し
~~ここが打ち消される
```

#チェックボックス
こんな機能もあるんですね

- [ ]  腰が痛い
- [x]  背中が痛い
- [x]  腕が痛い

ボックスのあとにスペースを入れたほうがきれいに見えるかも

- [ ]  チェックなし`- [ ] text`
- [x]  チェックあり`- [x] text`


#水平線
書き方は３つあるらしい
1. `*`を連続３つ以上（３つ以上ならいくつでも同じ）
2. `-`を連続３つ以上（３つ以上ならいくつでも同じ）
3. `<hr>`

*****
***
---
<hr> <hr>

```:水平線
*****
***
---
<hr> <hr>
```

#最後に
[公式のMarkdown記法チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
HCL Notes 12 の高度なプロパティボックス

# アイディアポータル
HCL Notes/Domino の機能改善リクエストを投票する [Product Idea Portal](https://domino-ideas.hcltechsw.com/) に寄せられたアイディアが次々と実現されています。
今回は HCL Notes クライアントの新機能で高度なプロパティボックス（Advanced Properties）が 12.0.1 から追加されたので試してみました。
# Advanced Properties
機能改善の要望は、プロパティボックスのサイズを大きくできるようにして欲しいというものでした。
[Enlarge the document properties window in Notes, or make it resizable.](https://domino-ideas.hcltechsw.com/ideas/NTS-I-11)
![2021-12-31_15-13-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2437712/451ab8f9-d238-253a-9574-277ea72043ce.png)
実際に Notes 12.0.1 Standard 版で採用された機能を確認してみました。

- プロパティボックスの新しいデザイン
- プロパティボックスのサイズを変えられる
- アイテムや値を検索できる
- 値をコピーする
- 値をCSV形式でコピーする

# 起動方法
今までのプロパティボックスとは、別の機能として実装されています。
呼び出し方は、ファイルメニューやビューで右クリックから Advanced Properties の各項目を選択します。![2021-12-31_15-09-42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2437712/631b1a12-f205-685a-5d3d-85e21a6d3aa4.png)

ちなみにショートカットキーで Document Propaties は以下の様に呼び出します。
**Windows ショートカットキー**

- Ctrl+Alt+L：高度なプロパティボックス（文書プロパティ）
- Alt+Enter：今までのプロパティボックス

**Mac ショートカットキー**

- command⌘+option⌥+L:高度なプロパティボックス（文書プロパティ）
- option⌥+Return：今までのプロパティボックス

# 便利な点
今までのプロパティボックスより大きく、サイズが可変になったことで調べやすさが格段にあがっただけではなく、値の検索が軽快で間違いも防げていい感じ。![2021-12-31_15-13-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2437712/4e6cf741-0e4f-2fef-c1a0-2f31a9011854.png)
クリップボードに CSV 形式でコピーできるので、表計算ソフトに持ち込んで調べるのもかなり楽になると思います。

# 注意が必要な点
Advanced Properties - Profile Documents というメニューが追加されて、ユーザーから簡単に見える様になってしまったので、今まで開発者のみの特権として様々な変数の格納場所として使われていたプロフィール文書へ苦労せずにアクセスできる様になってしまいました。
エンドユーザーに見せたくない値を格納しているアプリは注意が必要です。

# まとめ
この機能をさわった最初の印象としては、とても使いやすい [NotesPeek](http://hnagasim.blog8.fc2.com/blog-entry-51.html) ができた感じでした。プロパティの一覧をクリップボードにコピーできる機能がとても使いやすくて、想定外のアプリケーションの挙動が起きたときの調査にも活かせそうです。
アイディアポータルに寄せられた機能改善リクエストがオリジナルの要望を越えた機能で搭載されるのはとてもいい傾向だと思います。
これから欲しい機能ができたら、アイディアポータルに投稿するだけではなく人のアイディアを検索して投票することが実現に近づくので、積極的に活用して製品を活性化させたいですね。