OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu20.04で"google-chrome-stable has no capability of surrounding-text feature"

# 事象

Ubuntu 20.04 でGoogle Chromeでキーボードをタイプするたびに、`/var/logs/syslog`に"google-chrome-stable has no capability of surrounding-text feature"ワーニングが出力される。

```bash:/var/logs/syslog
May 24 20:07:29 <server_name> gnome-shell[73920]: (google-chrome-stable:73901): IBUS-WARNING **: 20:07:29.454: google-chrome-stable has no capability of surrounding-text feature
May 24 20:07:32 <server_name> gnome-shell[73920]: (google-chrome-stable:73901): IBUS-WARNING **: 20:07:32.216: google-chrome-stable has no capability of surrounding-text feature
...
```

# 環境

動作環境は以下の通り。

```bash
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```

# 原因調査

[IBus](https://ja.wikipedia.org/wiki/IBus) のissueを確認したところ、google chromeとgnome terminalの既知のバグであることがわかった。

ここで、IBusはUnix系のインプットメソッドの1つである。インプットメソッドとは、コンピュータに文字を入力するためのアプリケーションである。インプットメソッドは、ユーザがタイプしたキーの情報を文字に変換する。たとえば、キーボードで"aiueo"と入力した情報を"あいうえお"に変換する。

IBusのissueには次のように書かれていた。

https://github.com/ibus/ibus/issues/2271

> OK, you mean both gnome-terminal and chrome does not work with surround text feature.
> OK、つまり、gnome-terminalとchromeの両方がサラウンドテキスト機能で機能しないということです。
> 
> I didn't check chrome but from your log, you have to report the issue to chrome.
> 私はクロームをチェックしませんでしたが、あなたのログから、あなたはクロームに問題を報告しなければなりません。
> 
> We have already reported the issue to gnome-terminal.
> この問題はすでにgnome-terminalに報告されています。
> 
> https://gitlab.gnome.org/GNOME/vte/-/issues/214

gnome-terminalは1年前に処置済だが、google chromeはどうも処置されていないようだ。

# 回避策

インプットメソッドをIBusからfcitxに変更する。fcitxは中国語系のインプットメソッドであり、前述のGoogle Chromeのバグを回避できる。

まず、以下のコマンドでfcitx-mozcをインストールする。

```bash
sudo apt update && sudo apt -y install fcitx-mozc
```

次に、言語サポート画面を開く。

![言語サポートを検索](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/8e0580b3-2416-bd39-4d4a-b2f092efd4f8.png)

そして、`キーボード入力に使うIMシステム`をfcitxに設定して、閉じるボタンを押す。

![fcitxを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/2596c357-d40a-07d9-be10-e51182b89e3e.png)

最後に、Ubuntuを再起動する。

# まとめ


原因は、Google ChromeのIBusに関するバグ。本記事執筆時点で未処置。

インプットメソッドをIBusからfcitxに変更することで本事象を回避可能。
Google I/O 2021 まとめ(更新中)

#初めに
Google I/Oが先週オンラインで開催されてました。
結構なレベルで最先端がここに詰まっていると思っているので情報をキャッチアップしないといけないと思い、Youtubeを見始めたのですが、あまりに多くどこかにアウトプットしないと、とてもインプットできないと思ったので書きます。
#おことわり
私は、応用数理のバックグラウドを持つWebのエンジニアなのでApp&Androidの話はあまりわかりません。
Webだけでもこれだけ動画が上がっていて見るの大変です...(弱音)
![Screen Shot 2021-05-24 at 19.21.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/64ddb1b8-50a8-78b6-ba2b-e46fbc3813e0.png)


#まずはこちらの動画をどうぞ
https://youtu.be/L7c4wS7T_T8

ざっくりだと、

Google WorkSpaceがすごくなって、
![Screen Shot 2021-05-24 at 20.01.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/c3bf2e51-2192-fb4c-c6fd-8b01dd07bef1.png)

めちゃくちゃすごい自動応答AIができて
![Screen Shot 2021-05-24 at 20.02.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/f783054a-e13e-2bbb-56df-28cd7b041ac6.png)




スマホに入っている画像からショッピングできるようになって（すげー）、
![Screen Shot 2021-05-24 at 20.03.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/9519cf97-4d93-5d4d-fc60-fe17681172a8.png)

デザインがアップデートされてされて、
![Screen Shot 2021-05-24 at 20.04.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/a5bc4d96-c9d8-3d06-eabc-307019869752.png)

脱酸素も頑張る。
![Screen Shot 2021-05-24 at 20.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/a2f1776b-86bf-720c-734e-def5b449441b.png)



そして、身体性を持つようなDisplay作っているんだって、本当にすごいよ。Google先生。
![Screen Shot 2021-05-24 at 20.07.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/68465168-4a78-4eb3-d49d-8df5dda691dd.png)

他にもTPUが進化したり、Google Mapが進化したりしたそうです。

#【驚いたこと①】Google WorkSpaceがすごいんじゃね？？？
https://www.youtube.com/watch?v=SDBbFETGiA4

この動画見るとなんか今の勤務時間中ずっとZoomに入ってみたいなことアホらしくなるんじゃね？？？

#【驚いたこと②】Fullter Flowって半端なくすごいんじゃね？？？

https://www.youtube.com/watch?v=5j82wxzwFyI

↑この動画によるとスマホアプリ1時間とかできるらしいよ。

#【驚いたこと③】Vertex AIを使うと前処理とかサーバのこととか全部１箇所で管理できてめちゃくちゃ便利なんじゃね？？？

https://youtu.be/gT4qqHMiEpA

#【驚いたこと④】え、SEOのコアロジックまた変わるの？？？
よりエンジニアリングが求められそう...
![Screen Shot 2021-05-24 at 20.27.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/df48d24c-19ea-8b80-5b04-76f36eca363b.png)

#【驚いたこと⑤】Project Fuguって初めて知りました。
https://www.chromium.org/teams/web-capabilities-fugu
「AppでできることはWebでもできないといけない!!!」との思想のもと（この思想めちゃくちゃ共感できるぜ）、Webの機能を抜本的に追加しようとするProjectがあるそうで、Project　Fuguというそう。
なんでも、フグは「毒を持っているけど、ちゃんと処理すれば美味しい」ってのが、「Webって安定性とかセキュリティとかに不安があるけど、ちゃんとやればめちゃくちゃ便利なはず」ってのをなぞっているそう。


#今後
全部は見れないので自分の本業に関わる主にWebのところを見てびっくりすることがあったらこちら更新します。
今回はQAの動画が上がっていて、「Google DocsってDomを使わずにCanvasに移行するって発表していただけどこれからDomはどうなるの？？？」みたいな激アツな質問がされていて、量が多いけど見るのてちゃくちゃ楽しみ。
「ローカルとGitHubでgitレポジトリを作成して、エディタで開く」を1行で実行

## はじめに
自分はプログラミングを学習する際、サンプルコードを独立したレポジトリで管理しGitHubに上げています。
応用的なコードを書きたくなったら、さらに新規のレポジトリを作成します。

このルーティンが楽になると、学習が捗りそうです。

ということで、1行で以下を実行できるシェル関数を定義しました。

- ローカルにgitレポジトリを作成
- その内容でGithubにもレポジトリを作成しpush
- VSCodeでローカルのレポジトリ内容を開く

## 前提
* ghq
* GitHub CLI
    * v1.9.2
    * これのおかげでGitHub Enterpriseにも対応しています
* zsh/bash

## 方法
#### zshの場合

```zsh
function ghrc {
  local GITHUB_ORG_URL=github.com/your_userid
  mkdir -p $(ghq root)/${GITHUB_ORG_URL} &&
  cd $(ghq root)/${GITHUB_ORG_URL} &&
  gh repo create $argv --confirm &&
  cd ${argv[1]} &&
  echo "# ${argv[1]}" >> README.md &&
  git add . && git commit -m "first commit" && git push --set-upstream origin master &&
  code .
}
```
を`.zshrc`に書き足します。`your_userid`はあなたのユーザidに書き換えてください

`ghrc hogehoge`で、以下が実行されます。

* ghqの形式に合ったディレクトリ構成で、ローカルに`hogehoge`レポジトリを作成
* Githubに`hogehoge`レポジトリを作成
* README.mdを適当に書き足しGitHubにpush
* VSCodeで開く
    * `code .`部分を、お好みのエディタで起動するように変更可能です
        * `idea .`だったり
        * `open . -a "sublime text"`だったり

#### bashの場合

```bash
function ghrc {
  local GITHUB_ORG_URL=github.com/your_userid
  mkdir -p $(ghq root)/${GITHUB_ORG_URL} &&
  cd $(ghq root)/${GITHUB_ORG_URL} &&
  gh repo create $@ --confirm &&
  argv=("$@")
  cd ${argv[0]} &&
  echo "# ${argv[0]}" >> README.md &&
  git add . && git commit -m "first commit" && git push --set-upstream origin master &&
  code .
}
```
`argv=("$@")`の行が追加されただけです。`your_userid`はあなたのユーザidに書き換えてください

#### (fishの場合)
https://qiita.com/ryo2132/items/2a29dd7b1627af064d7b で「ghcr」と検索してカスタマイズする

## push時にエラーが出る人へ
こんなエラー

```
fatal: The current branch chore/logdir has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin some
```

https://qiita.com/YumaInaura/items/c493471db12c342e5256

が参考になります


## 参考url
* ghqについてhttps://qiita.com/udzura/items/255d6e29dabad575c3a5
* GitHub CLI https://qiita.com/ryo2132/items/2a29dd7b1627af064d7b
* `code`コマンドの導入 https://qiita.com/naru0504/items/c2ed8869ffbf7682cf5c

## 感想
人によっては、`npx create-react-app`とか`vue create`とかプロジェクト作成CLIと組み合わせても良いかも？
golangの場合は、`go mod init ${GITHUB_ORG_URL}/${argv[0]}`の1行足すのもアリ
重複したデータを除外するdistinct

distinctメソッドの返り値はActiveRecord::Relationオブジェクト


```rb:コンソール/catsテーブルの一意のspecies列を取得する
cats_species = Cat.select(:species).distinct
SELECT DISTINCT `cats`.`species` FROM `cats`
```


```rb:
user_ids = UserCheckin.pluck(:user_id).uniq
```

uniqメソッドとは？distinctとの違い
-
uniqメソッドとは、Railsで取得した重複レコードを1つにまとめるためのメソッドです。
uniqメソッドを実行すると、Railsは内部的にSQLのDISTINCTを実行します。
その他に、uniqメソッドとまったく同じ働きをするdistinctメソッドも存在します。

両者の違いは、

|uniqメソッド|Rails5以降で非推奨(または使えなくなる)|
|--|--|
|distinctメソッド|Rails5以降で正式メソッド|
Ruby 問題④ if,else問題

##はじめに

現在はオリジナナルアプリの作成しつつ、毎朝送られてくるrubyドリルを復習しております。
本日もrubyドリルのアプトプットをします！

##問題
19時から翌朝6時までにオウムに喋られると近所迷惑なのでその場合は「NG」、
それ以外は「OK」と出力するメソッドを作成します。
オウムが喋る時をtrue、喋らない時をfalseと入力することにし、時刻も同時に入力します。

```.rb
#呼び出し方
parrot_trouble(talking, hour)

#出力例
parrot_trouble(true, 5) → NG
parrot_trouble(true, 7) → OK
parrot_trouble(false, 6) → OK
```

##ヒント

〜だった時、かつ〜だった時

19時〜６時をどのように記述するか


##解答

```.rb
def parrot_trouble(talking, hour)
  if talking && (hour < 6 || hour >= 19)
    puts "NG"
  else
    puts "OK"
  end
end
```

オウムが喋ろうとしているときの時間帯が、19時から翌朝6時の時はNGを表示し、それ以外の時にOKを表示させます。
 *if talking* と記述する事で*ture*の場合と判断されます。

```.rb
(hour < 6 || hour >= 20)
# || という記述で「または」を意味します。（orのような感じ）
# 言葉にするとhourが6より小さい時、または20か、それより大きい時
```

どちらとも条件が成り立つ時に「NG」を出したいので

```.rb
if talking && (hour < 6 || hour >= 19)
# && 短終論理演算子で左辺かつ右辺がtureの時
```

trueだった場合にif文の全ての条件が真になり、”NG”が表示されます

演算子はwebアプリを作る際に何度も何度も使うので必ず理解が必要です。
M1搭載Macでnpmコマンドを使用出来るようにする

# はじめに
M1チップを搭載したmacでnpmコマンドを使用出来るようにする方法です。何番煎じになるかはわかりませんが、自身の備忘録を目的に書き留めておきます。

# homebrew のインストール
はじめにhomebrewをインストールします。homwbrewは公式でM1に対応しているため、公式そのままの方法でインストールします。

``` bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

処理が完了したらパスを通します。

```zsh
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/takuay/.zprofile
```

# nodeをインストール
次にnodeをインストールします。

```zsh
brew install node
```

```zsh
npm
```

と打って、次のように表示されれば完了です。

```
npm <command>

Usage:

npm install        install all the dependencies in your project
npm install <foo>  add the <foo> dependency to your project
npm test           run this project's tests
npm run <foo>      run the script named <foo>
npm <command> -h   quick help on <command>
npm -l             display usage info for all commands
npm help <term>    search for help on <term>
npm help npm       more involved overview

All commands:

    access, adduser, audit, bin, bugs, cache, ci, completion,
    config, dedupe, deprecate, diff, dist-tag, docs, doctor,
    edit, exec, explain, explore, find-dupes, fund, get, help,
    hook, init, install, install-ci-test, install-test, link,
    ll, login, logout, ls, org, outdated, owner, pack, ping,
    prefix, profile, prune, publish, rebuild, repo, restart,
    root, run-script, search, set, set-script, shrinkwrap, star,
    stars, start, stop, team, test, token, uninstall, unpublish,
    unstar, update, version, view, whoami

Specify configs in the ini-formatted file:
    /Users/takuay/.npmrc
or on the command line via: npm <command> --key=value

More configuration info: npm help config
Configuration fields: npm help 7 config

npm@7.13.0 /opt/homebrew/lib/node_modules/npm
```
TCPのストリーム通信・起動順序・接続の一意性



#目次
[1.目的](#1-目的)
[2.用語](#2-用語)
[3.ストリーム通信](#3-ストリーム通信)
[4.サーバとクライアントの起動順序](#4-サーバとクライアントの起動順序)
[5.接続の一意性](#5-接続の一意性)


#1. 目的
実務でTCP通信によるデータの送受信を扱ったとき、理解したところや誤解があったところを備忘録として残します。

#2. 用語

###### ３ウェイハンドシェイク
　TCP通信は、通信相手の応答があって初めて通信を開始する。
　このため、データ転送を行う前に接続の確立をする。
　この接続の確立を、３ウェイハンドシェイクという。

https://www.infraexpert.com/study/tcpip9.html


###### SYN
SYNパケットはクライアントからサーバへ接続を開始したいときに最初に送るパケット。

https://e-words.jp/w/SYN%E3%83%91%E3%82%B1%E3%83%83%E3%83%88.html

###### ACK
IPネットワークで標準的に用いられるTCP（Transmission Control Protocol）で伝送制御に用いられるパケットの種類の一つで、相手に何らかの応答をするときに送られるパケット。

https://e-words.jp/w/ACK.html

###### シーケンス番号
TCPで送信されるパケットにつけられる通し番号。

https://e-words.jp/w/%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E7%95%AA%E5%8F%B7.html#:~:text=%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E7%95%AA%E5%8F%B7%E3%81%A8%E3%81%AF%E3%80%81TCP,%E3%82%92%E7%9F%A5%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%82%8B%E3%80%82

###### ソケット通信
> そのTCP/IPを プログラムから利用するには、プログラムの世界とTCP/IPの世界を結ぶ特別な 出入り口が必要となります。その出入り口となるのがソケット (Socket)であり、TCP/IPのプログラミング上の大きな特徴となっています。 このため、TCP/IP通信をソケット通信と呼ぶこともあります。
引用元: http://research.nii.ac.jp/~ichiro/syspro98/socket.html


https://qiita.com/megadreams14/items/32a3eed4661e55419e1c


#3. ストリーム通信

TCP通信はストリーム型であり、送信データと受信データが１対１ではない場合がある。
例えば送信データ１つに対し、受信データが１つ未満の場合がある。

###### どういうことか

```javascript
//【例】データ情報
2021-04-30,hogehoge,Tokyo 
```

上記のデータをまるまる送受信するのではなく、複数回に分けて送受信する場合があるということ。

受信側がどれだけの情報量を受付できるのか、状況によって異なる。
このため、送信側に対し、受信側は受付可能な情報のサイズをwindowフィールドにセットし、知らせる。
送信側はwindowフィールドにセットされた以上のデータ送信をしない。

> 受けての処理能力やバッファ用メモリ領域などの理由で、送信量を制限する必要もでてくる。 [セグメント・ヘッダ](https://www.infraexpert.com/study/tcpip8.html)にあるWindowというフィールドはそのため（これをフロー、つまり流量制御という）に用意されている。基本的に受けてはこれからどれだけまでのデータが受付可能かをこのフィールドにセットすると、送信側はそれ以上のデータを相手がACKを返す前に送信することを控える。
引用元：https://www.cresc.co.jp/tech/network/NET_TUTORIAL/Section_46.htm


```javascript

//受信データが1未満の場合。
2021-04-30,hogeho //1回目受信
ge,Tokyo //2回目受信

```

例えば送信データが2つの場合は、受信データが1つ以上2つ未満の場合もある。


```javascript
//【例】データ情報
2021-04-30,hogehoge,Tokyo 
2021-05-01,piyopiyo,Osaka

//受信データが1つ以上2つ未満
2021-04-30,hogehoge,Tokyo　2021-05-01,pi //1回目受信
yopiyo,Osaka //2回目受信

```

###### どのようにして、データの切れ目を判断するか。
複数回に分けて受信するなら、どこからどこまでが1つのデータなのかを判断できるように実装する必要がある。
メッセージの長さを取得し、その長さ分がきたら切データの切れ目と判断するなど。

https://qiita.com/Gin/items/620f4a7bec246004ee89

> * 特定の文字をデータの終わりにつけて判別できるようにする（CRLFなど）
* メッセージを固定長にする（固定長データが届いたらそれで完了という判断）
* パケット内のヘッダ（L7）にてデータのサイズを書き込んでしまう
* 送信側が書き込みをshutdownする→このとき受信側は今来ているものをrecvするだけでよい
* アプリケーションで制御する

#4. サーバとクライアントの起動順序

TCPクライアントの要求を受けるため、TCPサーバは受信待ち受けの状態でいる必要がある。
このため、TCPサーバはTCPクライアントよりも先に起動する。

（TCPクライアントからTCPサーバに接続要求をするときが、TCP通信起動シーケンスの最初と誤解していた。）


#5. 接続の一意性

* ポート番号１つにつき、TCPセッションは1つ。 ※ [「セッション」と「コネクション」は違うの？](https://xtech.nikkei.com/it/article/COLUMN/20090327/327307/)
* TCPというプロトコルに対して割り振られるIPとポートの組み合わせがある。
* プロトコルが違えば、IPとポートの組み合わせが同じものも使用できる。

> このように、ひとつのサーバは複数のクライアントからのTCP接続を受け付けることができます。
TCPによる接続は、
> * 相手のIPアドレス
* 自分のIPアドレス
* TCP宛先ポート番号
* TCP送信元ポート番号
を利用して一意性が保たれます。
TCPにポート番号の組があるのは、同一の機器同士が複数のTCP接続を同時に張れるようにするためです。
引用：[TCP通信の基礎 P34](https://sbcr-dl-old.s3-ap-northeast-1.amazonaws.com/books/img/Linuxnet_02.pdf)
Word2Vecのモデルのロード方法を理解する

#Word2Vecのモデルのロード方法を理解する

##1, モデルをロードする二つの方法

```
(1) gensim.models.Word2Vec.load("xxx.bin")
(2) gensim.models.KeyedVectors.load_word2vec_format("xxx.bin", binary=True)
```

( 1 ):
　隠れた重み、語彙頻度、および二分木など学習に用いられるデータを含めてロードする
( 2 ):
　隠れた重み、語彙頻度、および二分木が欠落しているため、ベクトルのトレーニングを続行することはできない。トレーニングを続行するには、KeyedVectorsだけでなく、save（）によって保存された完全なWord2Vecオブジェクトの状態が必要((1)の形式でロードする必要があるよ、ということ)。

##2, DeprecationWarning: Call to deprecated `__getitem__` (Method will be removed in 4.0.0, use self.wv.__getitem__() instead).の対処法

日本語訳

```
DeprecationWarning：非推奨の `__getitem __`を呼び出します（メソッドは4.0.0で削除され、代わりにself.wv .__ getitem __（）を使用します）。
```

この警告は上記の(1)の形式を用いて得たモデルに対して誤った参照をした場合に出るもの
4.0.0というのはWord2Vecの親パッケージであるgensimの古いバージョンことを指していて、プログラム内で用いようとしているメソッドが古いバージョンで用いられていたものであることを示している。新しいバージョンでは非推奨であるため、今回のような警告が出てしまった。

ちなみにそのメソッドが

```
wv = model["xxx"]    #非推奨(ダイレクトモデルビューア)
wv = model.wv["xxx"] #推奨(ヘルパーメソッド)
```

※ちなみに、model.wv[ ]は[ ]内の単語をベクトル化するメソッド
しかし、警告なので無視

###2.1, gensim3.8.3

```
for word in model.wv.index2word:
```

のようにこのバージョンではwvメソッドを用いることができた
index2wordには単語のリストが入っていて、そこから単語を取り出している様子。
詳細: https://www.pytry3g.com/entry/gensim-word2vec-tutorial

###2.2, gensim4.0.1
最新のバージョンでやってみる
まず(1)の形式でモデルをロード

```
AttributeError: Can't get attribute 'Vocab' on <module 'gensim.models.word2vec' from '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/gensim/models/word2vec.py'>
```

どうやら"Vocab"という属性がないらしい
というのも、モデルのバージョンが古く、新しいバージョンのWord2Vecではロードできない様子
詳細: https://github.com/RaRe-Technologies/gensim/issues/3013

そこで(2)の形式でロードしてみた。

```
AttributeError: The index2word attribute has been replaced by index_to_key since Gensim 4.0.0.
#下は日本語訳
AttributeError：Gensim 4.0.0以降、index2word属性はindex_to_keyに置き換えられました。
```

エラーの通り、index2wordをindex_to_keyに書き換えてみると

```
VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
TypeError: only size-1 arrays can be converted to Python scalars
#下は日本語訳
VisibleDeprecationWarning：不規則なネストされたシーケンス（リストまたはタプルのリストまたはタプル、または長さや形状が異なるndarray）からのndarrayの作成は非推奨になりました。これを行う場合は、ndarrayを作成するときに「dtype = object」を指定する必要があります。
TypeError：サイズ1の配列のみをPythonスカラーに変換できます
```

ジャグ配列からndarrayオブジェクトを生成することは非推奨らしい。
そもそもndarrayはNumpyの計算用の多次元配列であるため、わざわざジャグ配列にすることは理にかなっていない
しかし、警告なので無視
詳細: https://teratail.com/questions/297263
dtype=objectを実際に入れていきます

```
return numpy.array(w_ls, dtype=object).astype(numpy.float32), vocab　#エラーが出ている箇所
#下記エラー
TypeError: only size-1 arrays can be converted to Python scalars
#下は日本語訳
TypeError：サイズ1の配列のみをPythonスカラーに変換できます
```

これはどうやら、object型でnumpy配列に入れたり、object型にキャストしたりすると配列扱いされないか空配列になってしまう模様...

##3, 結論
4.0.0以降のgensimでは古いモデルをロードできない(？)
古いモデルを利用する場合は3.8.3が推奨されてる様子
[AtCoder] ARC 120 B - Uniformly Distributed

https://atcoder.jp/contests/arc120/tasks/arc120_b

AtCoderを始めて思うのは、解法は合っているのに実装を間違えて不正解になることが多いので、これをどうしたらいいかということです。
実際にコンテストに参加すると、不正解だとしてもどんなテストケースに対して不正解なのかわからないので、どこが間違っているのか見当をつけるのがまず難しい。
ほとんどのテストケースは正解して一部だけ不正解の場合は、解法は正しく後は詰めの問題だと思うのですが、そこから正解に持っていくのが結構大変だったりします。
こればかりは経験を積むしかないのでしょうか。
今回は昨日のARC 120の問題です。
悩みましたが、以下の図のアルファベットで分けられたマスについて、それぞれのアルファベットのマスの組に対して高々1マスしか通らないことに気付きました。

|  | 1 | 2 | 3 | 4 |
|:-:|:-:|:-:|:-:|:-:|
| 1 | a | b | c | d |
| 2 | b | c | d | e |
| 3 | c | d | e | f |
| 4 | d | e | f | g |

上の図だと、$(1, 1)$ から $(4, 4)$ に移動するには、例えば $c$ のマスは3個のうちのどれか1個しか通れません。他のアルファベットも同様です。
そしてそれぞれの組に対して、全て赤か全て青でないといけません。
とすると解答の初期値を1として、あるアルファベットのマスの組に対して以下の条件で答えが導き出せます。

* 赤マスと青マスの両方が存在するならば条件を満たさないので0。
* 色が塗られてないマスと赤マスのみの場合は塗られてないマスは全て赤に塗る。したがって赤1通り。
* 同様に色が塗られてないマスと青マスのみの場合は塗られてないマスは全て青に塗る。したがって青1通り。
* 赤マスも青マスもなく全てが色が塗られてないマスの場合は全て赤に塗るか全て青に塗るかの2通りなので、解答を2倍する。

これを全てのアルファベットのマスの組に対して行います。
この解法で実装したのですが、数問だけ不正解になってしまいました。
マスを調べるときのループがおかしいのだろうと予想しましたが、どうしてもわからなかったので後で解説を読みました。
解法の大まかな筋は自分と同じで、ただ自分がアルファベットで分けたマスの組に対して、
解説では行数を $i$ 、列数を $j$ とした場合にそれぞれのマスの $i + j$ が等しいという共通点を見つけて解いてました。
その解説を参考に自分のソースコードを修正したら一発で正解しました。。
しかも最初に書いたものよりもかなりシンプルになって、実装のセンスの無さに凹んでいます。。。
その正解したソースコードが以下です。
言語はC++(GCC 9.2.1)でAtCoderのコードテストで確認しています。

```c++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
  int H, W;
  cin >> H >> W;
  vector<string> S(H);
  vector<int> RCount(H+W-1, 0), BCount(H+W-1, 0), ECount(H+W-1, 0);
  ll ans = 1, m = 998244353;

  for (int i = 0; i < H; i++) {
    cin >> S[i];
  }
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (S[i][j] == 'R') RCount[i+j]++;
      else if (S[i][j] == 'B') BCount[i+j]++;
      else if (S[i][j] == '.') ECount[i+j]++;
    }
  }
  for (int i = 0; i < H+W-1; i++) {
    if (RCount[i] && BCount[i]) {
      ans = 0;
      break;
    } else if (!RCount[i] && !BCount[i] && ECount[i]) {
      ans *= 2;
    }
    ans = ans % m;
  }
  cout << ans << endl;
}
```
f.collection_select

<%= f.collection_select 第一引数, 第二引数, 第三引数, 第四引数, 第五引数, オプション %>
-
|引数|具体値|役割
|--|--|--|
|第一引数（メソッド名）|:name_eq|・カラム名・name属性やid属性を決める|
|第二引数（オブジェクト）|@products|配列データを指定する|
|第三引数（value）|name|表示する際に参照するDBのカラム名|
|第四引数（name）|name|実際に表示されるカラム名|
|オプション|include_blank|何も選択していない時に表示される内容|
使っていない大きなファイルを探すときのために

使っていない大きなファイルを探すときのために。

WindowsのCドライブ以下を探す場合を想定しています。

```py:search_big_file.py
import os
import pathlib

def get_path_recursive(path):
    for p in path.iterdir():
        try:
            if p.is_dir():
                get_path_recursive(p)
            elif p.is_file():
                s = os.path.getsize(p)
                if s > 1024*1024*1024:
                    print(f'{s}:{p}')
        except PermissionError:
            print(f'PermissionError:{p}')
        except OSError:
            print(f'OSError:{p}')

path = pathlib.Path('C:\\')
get_path_recursive(path)
```
Active Model Serializerを使用してAPIのJSONを指定のハッシュにネストしたい

Active Model Serializerを使ってAPIを生成してみました。
しかし、一部で少し詰まったので記録しておきます。


### やりたいJSONの形
```json
{
    "data": [
        {
            "id": 1,
            "category_name": "study",
            "body": "hoge"
        },
        {
            "id": 2,
            "category_name": "study",
            "title": "hogehoge"
        }
    ]
}
```
こちらで指定したハッシュ（data）の中にネストしたい。


### 問題

コントローラでrenderを行い、jsonにtodosの変数を渡す。
その際に、"data"というハッシュの中にそれらの値を入れたい・・・が、
変数を直接dataハッシュの中に入れると、Serializeで整理したはずが全部表示されてしまう・・・

```rb:controller
def index
  todos = Todo.where(type： 'animal')
  render json: {data: todos}, each_serializer: TodoSerializer
  # jsonに渡すデータが複数の(where等で取ってきた)場合はeach_serializer、単数の(find等で取ってきた)場合はserializer
end
```

```json
{
    "data": [
        {
            "id": 1,
            "category_id": "1",
            "body": "hoge"
            "created_at": "2021-05-24T17:52:32.917Z",
            "updated_at": "2021-05-24T17:52:32.917Z"
        },
        {
            "id": 2,
            "category_id": "1",
            "title": "hogehoge"
            "created_at": "2021-05-24T18:10:49.294Z",
            "updated_at": "2021-05-24T18:10:49.294Z"
        }
    ]
}
```


### 解決方法

adapterというオプションを使用して、引数としてルートキーを指定すると実現可能に！
（もしかしたら他にもやりようがあるかもしれないが）

```
json: todos, root: 'data', each_serializer: TodoSerializer, adapter: :json
```

⏬ Overriding the root key
https://github.com/rails-api/active_model_serializers/blob/v0.10.6/docs/general/rendering.md#overriding-the-root-key


最初スルーしてしまっていたけど、ドキュメントはちゃんと読もう。。
【LINEログイン】外部ブラウザでSSOをある程度無効化して自動ログインを行う

こんにちは。

LINEが提供するOAuth 2.0の認可コード付与のフローとOpenID Connectに準拠する
Webログインの仕組みであるLINEログインで提供される、
"自動ログイン"と呼ばれるユーザーに違和感を与えにくいWebログインの
仕組みについて解説したいと思います。


# 自動ログインとは

この動作のことです。
※外部ブラウザにおける自動ログイン

<img width="200"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620553/999341dd-cf6d-9af4-7146-b9198c96e9b8.gif">


# この動作の何がいいか

以下のようなメールアドレス、パスワードの入力をスキップでき、
ユーザーの離脱を防止できる点がCOOLです。

<img width="200"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620553/a745660e-0996-af7f-3195-26322b68f879.png">


# 何が問題なのか

自動ログインは、LINEのアプリ内ブラウザ、もしくは外部ブラウザ（iOSであればSafari、AndroidであればChrome）のみに対応しており、また外部ブラウザではシングル・サインオン（SSO）と呼ばれる仕組みにより、
毎回自動ログインを行わせることができないという問題があります。
https://developers.line.biz/ja/faq/#how-does-auto-login-work
https://developers.line.biz/ja/docs/line-login/integrate-line-login/#line-auto-login


# SSOとは
以下のような画面のことです。

<img width="200"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620553/9a041a7a-2104-372d-be1d-3aacef66817f.png">


**外部ブラウザでは、 （自分の管理していないチャネルでの）自動ログインを含めて一度でもLINEログインを行い、
LINEログインのセッション情報（Cookie）が残っている場合、自動ログインよりも
優先してSSOが動作する** ことが明記されてます。
https://developers.line.biz/ja/docs/line-login/integrate-line-login/#line-sso-login

# SSOを動作させないためには

SSO機能は無効にできないようなので、
どのような場合においでもSSOを動作させたくないということであれば、
**LINEログインをLINEアプリ内ブラウザで行う**しか方法はありません。

ただし、少なくとも自分の管理しているLINEログインの導線のみを
利用するユーザーに対しては、外部ブラウザでのSSOを無効化する方法があります。

# ワークアラウンド
"max_age"を0にすることで、LINEログインのCookieの有効期限を0にすることができるため、
これを用いてSSOを無効化することができる場合があります。
max_ageについては以下のドキュメントに記載があります。

>ユーザー認証後に許容される最大経過時間（秒）。OpenID Connect Core 1.0 の「Authentication Request」のセクションで定義されているmax_ageパラメータに相当します。

https://developers.line.biz/ja/docs/line-login/integrate-line-login/#making-an-authorization-request  

>OPTIONAL. Maximum Authentication Age. Specifies the allowable elapsed time in seconds since the last time the End-User was actively authenticated by the OP. If the elapsed time is greater than this value, the OP MUST attempt to actively re-authenticate the End-User. (The max_age request parameter corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] max_auth_age request parameter.) When max_age is used, the ID Token returned MUST include an auth_time Claim Value.

https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest  

**注意点として、max_ageを0にした場合でも、LINEログインを行うユーザーが他のLINEログインチャネルに対してすでにLINEログインを行っており、そのCookieが残っている場合、このパラメータを利用してもSSOを無効化することはできません。**

ユーザーがmax_ageを0ではないLINEログインを行う可能性があるため、
この方法ではどのような場合においても確実にSSOを無効化できるわけではありませんが、
より多くのユーザーが外部ブラウザで自動ログインを行われるように対応するという意味では、
検討の余地もあるのではないでしょうか。

## おまけ

LINEログインをパラメーターを変えて試すことができるテストアプリ作りました。
よかったらmax_ageを0にして動作を確認してみてください。
https://myucy-login.herokuapp.com/
※上記アプリでの情報の取得や保存はしていないのでご安心ください。
またherokuなのでしばらくアクセスが無いと起動に時間がかかります。
[Symbol] PythonでCatapult REST Endpointsからウォレット情報の取得

# 概要
- デスクトップウォレットに表示されるような内容をプログラム（Python）から取得する方法を残しています。
- 全コードは[Githubにて公開中](https://github.com/ancte0721/symbol-python-training)
    - バグや次回の要望あればコメントください
- 投げXYMは「**NDLS6GYOIPHATATNAVVOUNJXBD6X4BXU6IRBHIY**」まで
- あなたの委任お待ちしております。
    - **symbol-node.takagi-tech.com**
    - ハーベスト報酬は技術検証や記事執筆、ノード維持費に使わせていただきます。

# 事前準備
公式ドキュメントはこちら。v1.0.0で動作確認しています。

https://docs.symbolplatform.com/symbol-openapi/v1.0.0/

## ウォレットの基本情報の取得

https://docs.symbolplatform.com/symbol-openapi/v1.0.0/#operation/getAccountInfo
こちらを叩きます。

```python
import urllib.request
import json

# パブリックネットで安定しているノードURL
NODEURL = "http://00fabf14.xym.stir-hosyu.com:3000"
# 確認対象ウォレットアドレス
ADDRESS = "NDLS6GYOIPHATATNAVVOUNJXBD6X4BXU6IRBHIY"

# APIコール
req = urllib.request.Request(NODEURL + '/accounts/' + ADDRESS)
with urllib.request.urlopen(req) as res:
    accountInfo = json.load(res)

# 内容全件表示
print(json.dumps(accountInfo, indent=2))
```

結果

```
{
  "account": {
    "version": 1,
    "address": "68D72F1B0E43CE09826D056AEA353708FD7E06F4F22213A3",
    "addressHeight": "143022",
    "publicKey": "5DB471481B3A39AC5CEEE949B64A577C0D5CA67176BE4462145CAD6ABD84CEBC",
    "publicKeyHeight": "143146",
    "accountType": 1,
    "supplementalPublicKeys": {
      "linked": {
        "publicKey": "24120E20A7958457691D15200387F62EA5A3A0FE8349302F9D42C96FF2C233DC"
      },
      "vrf": {
        "publicKey": "F7827E7465E72A19BD4169E2D26FC2B02E0DBE6674A4F77FD5999EA294D70A95"
      }
    },
    "activityBuckets": [],
    "mosaics": [
      {
        "id": "6BED913FA20223F8",
        "amount": "79786493"
      }
    ],
    "importance": "0",
    "importanceHeight": "0"
  },
  "id": "609A55A52A6F02C06E5BB3C9"
}
```

モザイクの情報が欲しければ、

```python
# 保有XYM -> 可分性が6(小数点以下6桁)なので1000000倍した数値
print(int(accountInfo['account']['mosaics'][0]['amount']) / 1000000)
```

結果 `79.786493`

という感じで保有XYMを取得することができました。

全コードは[こちら](https://github.com/ancte0721/symbol-python-training/blob/master/01_getAccountInfo.ipynb)
CloudWatchのログイベントが出力されない時の対処法

みなさん、CloudWatchを頻繁に使っていると思います。

ある日、Lambdaでバグが起きていた時にCloudWatchでログを見て解決しようとした時のことです。

![スクリーンショット 2021-05-24 16.07.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633297/e231202a-4a07-d330-ade4-cc6987a7e1fd.png)

####あれ！？ メッセージが何も表示されていない！！！

ある期間からログイベントにメッセージが表示されていなかったのです。
ログイベントがそもそも無かったり、エラーが出ている、という訳でもなくメッセージのみが出ていないのです。

この現象は初めてでハマりました。

##結論
![スクリーンショット 2021-05-24 16.21.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633297/b8b2f8e8-aad2-e893-f86b-467bc2298a56.png)

ログの保持期間が30日に設定されていたため、30日を超えて遡るとメッセージが表示されなくなっていました。

こんなことに気付かなかったなんて...
ショック....

ちなみにどうやって変更するのかというと
#####ロググループの「アクション」から「保持期間の設定」で期間を設定できます。

Lambdaのバグは、特定の期間で起こっていたということもあり、この保持期間の設定だとは全く思いつきませんでした。


##他にも
今回の問題とは関係ありませんが、ログについての記事もありました。

[CloudWatch-LogsにLogが出力されない！そんな時にまずやること](https://qiita.com/shinichi-takahashi/items/3f845e4042f6122174b3)
Next.jsのLinkとStorybookで出るCannot read property 'prefetch' of nullエラーの対処

Next.jsのLinkをStorybookで使おうとすると、

`Cannot read property 'prefetch' of null`

というエラーになる。

これの対象法についてです。

画面はこんな感じです。
![スクリーンショット 2021-05-24 17.57.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307699/6953a95b-0026-979a-eace-fc7d361e542c.png)


## 環境

```
$ node -v
v14.11.0

$ npm -v 
6.14.8

$ npm list --depth=0 ※関係ありそうなやつのみ抜粋
├── @storybook/react@6.1.3
├── next@10.0.2


```
## prefetchとは

プリフェッチというのは、利用が予想されるものを読み込んでおくことです。
Next.jsのLinkコンポーネントではデフォルトでリンク先のページのコードをバックグラウンドで読み込むことで、素早いページ遷移を実現しています。

## 解決方法1
```LinkSample.tsx
import React, { VFC } from "react";
import Link from "next/link";

const LinkSample: VFC = () => {
  return (
    <Link href={"/"} prefetch={false}>
      <span>サンプル</span>
    </Link>
  );
};

export default LinkSample;
```

`prefetch`はデフォルトだと`true`になっているのですが、不要であれば`false`にしてしまうことで解決できます。

## 解決方法2

```LinkSample.tsx
import React, { VFC } from "react";
import Link from "next/link";

const LinkSample: VFC = () => {
  return (
    <Link href={"/"} prefetch={!process.env.STORYBOOK}>
      <span>サンプル</span>
    </Link>
  );
};

export default LinkSample;
```

もう1つの解決方法はstorybookの環境変数を利用するパターンです。
`process.env.STORYBOOK`はstorybookで動かしている場合に`true`になります。
これを利用して、storybookで動かしている場合のみに`false`にする方法です。

## 最後に

最初に見た時は、なんだこれ？と思ったので、同じような問題に詰まっている人の助けになれば幸いです。

### 参考
[https://github.com/vercel/next.js/issues/19825](https://github.com/vercel/next.js/issues/19825)
[https://github.com/storybookjs/storybook/pull/12997](https://github.com/storybookjs/storybook/pull/12997)
[https://nextjs.org/docs/api-reference/next/link](https://nextjs.org/docs/api-reference/next/link)
Javascript 基礎


Javascriptを使用してコードを書いていくにあたり、アルファベットの大文字、小文字は明確に区別されるようです。

```javascript

let name = "Taro";
//変数 name を呼び出し
console.log(name);

```

例えば上記のように、変数 name は Taro という形で定義をします。
そしてconsole.log()で変数 name を呼び出し、値として Taro を出力しています。

前述したとおり、

```javascript

let name = "Taro";
//変数 Name を呼び出し
console.log(Name);

>> Uncaught ReferenceError: Name is not defined

```


同様に、変数 name は Taro という形で定義していますが、console.log()では Name という定義をしていない変数を呼び出しています。　

name と Name は同じような物に見えますが、前述したとおりアルファベットの大文字と小文字は区別をされてしまうので、別の変数として扱われてしまいます。

ですので、console.log()で Name を呼び出しても 変数として Name を定義していないのでエラーが吐かれてしまうということです。
Veturでは.vueのRename Symbolができないので、Volarに移行した！

## TL;DR
これ入れましょ！
https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar

注意点は、このあたり。

* Veturと共存はできない
* TypeScriptか、それに準じた設定が必要
  * `<script lang="ts">`とTSビルド環境があればスムーズ
  * `<script lang="js>`の場合、以下のどちらかが必要
      * tsconfig.json作って`"allowJs": true`を明記
      * [jsconfig.json](https://code.visualstudio.com/docs/languages/jsconfig)作る


## 以下、ポエム

VSCodeでVue.jsの開発するとき、機能拡張はVeturが定番です。
https://marketplace.visualstudio.com/items?itemName=octref.vetur

しかし、このVeturさんは致命的な機能不足がございまして、
シンボルの名前変更（Rename Symbol）ができないのです！
2017年に立てられたこのIssueが、ずっとOpenなままになっております。
https://github.com/vuejs/vetur/issues/610

リファクタリング中に変数名をエディタの機能で変えたいこと、めっちゃありますよね。
Vue.jsでも.js拡張子で書いてればあればできるんですが、
単一ファイルコンポーネント.vueにした途端、構文解析など難しいんでしょうね。
当たり前に使っていたRename Symbolが出来なくなってしまうのです :sob:


ぶっちゃけ、このせいで僕はVueよりReactをよく使うようになりました。
それほどRename Symbolは重要だったんですが！

この度！Volarという機能拡張でそれができることをが判明しました！！！
（読み方は"ヴォラー"で良いのかな？）
https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar

@aki77 さんが見つけてくれました。感謝！
よく見ると、前述のIssueでもコメントされてますね。
https://github.com/vuejs/vetur/issues/610#issuecomment-765347938

これで、またVue.jsも使おうかな～って思ってます。
どうしてもvimを勉強したくない人のための最低限コマンド集

vimって自分から使っても見ようと思うことってほとんど無いんじゃないでしょうか？業務上どうしても使わざる負えない状況になって仕方なく勉強する人が多いと思います。

本稿ではそんな**vimを使わなければいけない状況になってしまった、でも勉強にあまり時間をかけたくない**という方のために、最低限覚えておくべきコマンドをまとめました。

# vimを立ち上げる
```
vi ファイル名
```

# 文字を書き込みたい時
```
i
```
iキーを入力すると画面左下に`-- INSERT --`という文字が現れ、コードを自由に編集できるようになります。

# 保存しないで閉じる
```
[esc]を押してから
:q!
```

# 保存して閉じる
```
[esc]を押してから
:wq
```

# 1行コピー
```
[esc]を押してから
yy
```

# 複数行コピー
```
[esc]を押してから
5yy
```
上記の例ではカーソルから5行分コピーすることができます。数値を変えて任意の行数をコピーできます。

# ペースト
```
[esc]を押してから
p
```

# 1行削除
```
[esc]を押してから
dd
```

# 複数行削除
```
[esc]を押してから
5dd
```
上記の例ではカーソルから5行分削除することができます。数値を変えて任意の行数を削除できます。

# 全テキストを削除
```
[esc]を押してから
:%d
```

# 1つ戻す
```
[esc]を押してから
u
```

# 1つ進める
```
[esc]を押してから
Ctrl + r
```

# 行末へ移動
```
[esc]を押してから
$
```

# 行頭へ移動
```
[esc]を押してから
0
```

# おわりに
これだけで大抵のやりたいことはできると思います。
読んでいただきありがとうございました。
VS CodeとAnacondaの設定で初めにした環境設定

# 初めに
環境設定......なにそれおいしいの？
そんな自分が出会った，やらなければいけない事orzについて，__備忘録__として記載していきます．
（備忘録といいつつ既に忘却してる記憶多数）

# Pythonを使うために
VS CodeとAnacondaを既にインストールした前提に進めます．
（インストールした時の事忘れてしまった　ﾃﾍｯ）

### 1. 仮想環境の構築
Pythonはバージョンによって動く/動かないなどがあると聞き，やっておいて損はないだろうとの事で仮想環境を構築しました．
出来る限りGUIでやってます．

__初めに__，Anaconda Navigatorを開き，_Environments_から_Create_を押します．
名前入力とPythonのバージョンを選択し，_Create_！これで仮想環境完成です！
__後は__，上の方にある_installed_ってところを_Not installed_に変えて，右の検索バーから_anaconda_と入力し，
_anaconda_にチェックを入れて_Apply_！
こんな感じで仮想環境は作れるみたいでした．

因みに__削除するとき__は，削除する仮想環境をクリックし，_Remove_を押すと消えます．
__が！__このままだと同じ名前で仮想環境を作れません．（仮想環境のフォルダがまだ残っているため）
そのため，エクスプローラーから，"C:\ユーザー\自身のユーザー名\anaconda3\envs”（←環境：environment）
この中にある，先ほど削除した環境と同じ名前のフォルダを削除します．これで無事に作った環境は無くなるはずです！

### 2. 環境変数の設定
これは正直未だに良くわかってないですが，他の人がやっているのでやりました（雑）

左下の_Windowマーク_を押し，環境変数を編集と記載し選択します．
上の枠にある，_Path_→_編集_→_新規_を順に押し，以下を追加します．
・”C:\Users\自身のユーザー名\anaconda3”
・”C:\Users\自身のユーザー名\anaconda3\Scripts”

最後に_OK_押して完了！

# 最後に
この後VS Codeでプログラムを書いて行く訳ですが，__Githubと連携させたい場合__は，先に連携させたフォルダを作成した上でその中にPythonのファイルを作っていくといいかもです．
[OpenCVとGitHubの連携について](https://qiita.com/thinknee/items/52481209820167534eeb)

_conda activate_でエラーが起きたので，それについては以下に記載しました．
[conda activateでエラーが出る件](https://qiita.com/thinknee/items/ba19898a051176cfab69)
【Ruby】cover?とinclude?の違い

## 概要

`cover?`と`include?`は，ともに範囲内に値が含まれるかを判断するメソッドです。

両者の挙動の違いについて調べることがあったので，メモとしてまとめます。

## 結論

`include?` は原則として**離散値**を扱い、`cover?`は**連続値**を扱う。
ただし，**数値**に関しては`include?`も**例外的に連続値を扱う**ので，`cover?`と同じ挙動になる。

※離散値は，連続していない状態の値，連続値は切れ目がなく連続している値のこと。

## 数値を扱う場合
```ruby
(1..5).cover?(3) # => true
(1..5).include?(3) # => true
```
挙動は同じ。

## 数値以外を扱う場合


```ruby
("b".."d").cover?("ba")  # => true
("b".."d").include?("ba")   # => false
```
`cover?`は`<=>` メソッドによる演算により`"ba"`が`"b"`から`"d"`の範囲内にあるかを確認しています。

※すみません，ここは確証が持てないのですが，2つの文字列をASCII コード順で比較しており

```ruby
"ba" >= "b"  # => true
"ba" <= "d"  # => true
```
であるため`true`になると解釈しました。
（参考：https://docs.ruby-lang.org/ja/latest/method/String/i/=3c=3d=3e.html ）

一方，`include?`は**「`"ba"`が範囲内に完全に一致する値が含まれるかどうか」**を確認しています。
数値以外については，離散値を扱うので，`"b".."d"`は`"b", "c", "d"`となり，この中には`"ba"`に一致するものがありません。

なので`false`になります。

以下の例のほうがさらに分かりやすいかも？

```ruby
("a".."z").cover?("yellow") # => true

("a".."z").include?("yellow") # => false
("yellaa".."yellzz").include?("yellow") #=> true
("aaaaaa".."zzzzzz").include?("yellow") #=> true
```
※ちなみに↑こちらの一番下のコードは実行すると50秒くらい掛かりました。
地道に一致する値を探しているのがよく分かります。
（参考：https://stackoverflow.com/questions/21608935/what-is-the-difference-between-rangeinclude-and-rangecover/21609473 ）

##【補足】include?の他の使い方

`include?`については，以下のように配列や文字列に対して使うものもあります。

配列
https://docs.ruby-lang.org/ja/latest/method/Array/i/include=3f.html

文字列
https://docs.ruby-lang.org/ja/latest/method/String/i/include=3f.html

ちなみに，現役エンジニアの方は**「`include?`は離散的なものに使用するイメージがある（とびとびのもの，Arrayに使うことが多く，Rangeには普通使わない）」**とおっしゃっていました。

## 【参考】ちなみにbetween?は・・・

``between?``は比較演算子 `<=>` をもとに値が範囲内にあるかを判断します。

内容を見る限り，`<=>`をもとに範囲内にあるかを判断している点から，書き方は違えど`cover?`と同じ挙動をすると思っていますが，確証が持てません^^;

```ruby
# 以下は同じ意味?
3.between?(1, 5) # => true
(1..5).cover?(3) # => true

# 以下は同じ意味?
('a'..'z').cover?('yellow') # => true
('yellow').between?('a','z') # => true
```
（上記以外にも色々な値を検証したところ，同じ結果は返ってきましたが・・）
もしご存知の方がいらっしゃったら，教えていただけたらとても嬉しいです。



## 終わりに

以上，調べた内容をまとめました。
もし間違いがありましたら，ご指摘いただけますと幸いです☺️

## その他参考サイト

- cover?
https://docs.ruby-lang.org/ja/latest/method/Range/i/cover=3f.html

- Rangeクラス（範囲を扱うクラス）のinclude?
https://docs.ruby-lang.org/ja/latest/method/Range/i/include=3f.html

- between?
https://docs.ruby-lang.org/ja/latest/method/Comparable/i/between=3f.html
【Javascriptの基本的な文法を学ぼう②】変数定義編


#はじめに

今回は変数定義についてみていきたいと思います！プログラミングを学習する上で変数は基本的な内容となりますので、しっかり押さえておきましょう！

#変数とは？
まず変数について解説したいと思います。変数とはよくデータを保存するための箱と言われています。この変数にデータを入れておくことで、データを短い記述で使い回す事ができます。
Javascriptで変数を定義する方法は、`const, let, varの3つがあります。`以下ではそれぞれの特徴と合わせて具体的に見ていきましょう。

###const
constは、後から書き換えることができない変数を定義する書き方です。正確には定数と言います。`constの特徴として、再代入、再定義ともに不可という制約があります。`


```javascript
const sample = "おはよう"

sample = "おはよう"
// 再代入NG →エラーが起こる

const sample = "おはよう"
// 再定義NG →エラーが起こる
```


###let
letは、後で書き換えることができる変数を定義する書き方です。`letの特徴として、再代入は可能ですが、再定義は不可という制約があります。`


```javascript
let sample = "おはよう"

sample = "おはよう"
// 再代入OK

let sample = "おはよう"
// 再定義NG →エラーが起こる
```


###var
varは再定義、再代入可能な古い書き方です。`varの特徴として、再代入、再定義ともに可能です。`


```javascript
var sample = "おはよう"

sample = "おはよう"
// 再代入OK

var sample = "おはよう"
// 再定義OK
```

#const, let, varの使い分け
さて、上記のようにJavascriptでは3つの方法で変数を定義できるということが分かったと思います。しかし私も最初に思った疑問なのですが、どのように使い分ければいいのかという疑問が生まれました。そこで今回は簡単に使い分けについても触れたいと思います。結論から言うと`基本的にはconstを使用する。constがダメならletを使用する。基本的にvarは使用しない。`と言う結論になります。なぜならばプログラミングは基本的に厳密な指示を出さなければなりませんので一番厳密に定義されるconstを使用します。ですので変数を使用する際は基本的にはconstを使いましょう。

#おわりに
今回はJavascript編2回目と言うことで、基本的な変数の定義について見ていきました！
次回もJavascriptの基本文法をみていきたいと思いますので、次回の記事も是非見てください！
Vue-devtools が Chrome で動作しない 備忘録

# 環境
Vue,js 2.ｘ
Google Chrome バージョン: 90.0.4430.212（Official Build） （64 ビット）

# 何をしたいのか

Google Chrome ＋ Vue-devtools で、Vue.js のデバックがしたい。が、Vue-devtools が、Chrome の Developer tool に表示されない。

# 結論

~~本家 ガイドにある CDN を使うのをやめ、本家ガイドにある開発モードの Vue.js をダウンロードして使う。~~（2021/25/25 間違い）

```html:index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
    </head>
    <body>
        <div id="app">Hello vue.js</div>
        <!-- Vue.js を読み込み -->
        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    </body>
</html>
```

# なぜか

~~Vue.js には、以下の Version？ ビルド？ がある~~

* ~~本番 Version ( production Version )~~
* ~~開発 Version ( development Version )~~

~~で、開発バージョンでしか vue-devtools は有効化されないので、開発バージョンの Vue.js を使う必要があるが、[CDN は、本番｜縮小ビルドしか提供されていない。らしい。](https://github.com/vuejs/vue-devtools#important-usage-notes "vue-devtools - Important Usage Notes | Github")~~(2021/05/25 該当の記載は見当たらない)


#参考リンク

Vue-devtools | chrome ウェブストア

https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd

本家 ガイド｜

https://vuejs.org/v2/guide/installation.html#Vue-Devtools

本家Github

https://github.com/vuejs/vue-devtools#important-usage-notes
Flutterのカメラ実装をする時にnullsafetyで困った


##はじめに
ある日、とあるWebサイトを参考にFlutterのカメラ機能を実装したのですが何故だかうまく行きませんでした。

本日はそのときに試した方法を示していきます。非常に簡単なことでしたのでもし同じようなところで詰まっている人がいれば参考にしてください


##結論
```
dependencies
  flutter:
    sdk: flutter
       ・
       ・
       .
  image_picker: ^0.7.0-nullsafety

```
はい、上記の通りです。これは私の認識ですが画像がNullによるエラーが出ないようにするために必要な項目であり、この項目がないとnullが許容されてしまいます。そうならないために、開発者にとって優しい仕様にしようということなんだと思います。
ちなみに書かれている場所はpubspec.ymlです


##参考サイト
https://qiita.com/konatsu_p/items/eb0e8a7ab62ab9d31315
Githubにpush しても草が生えない？原因と対処法

タイトル通り、ちゃんと手順を踏んでGithubにpushをしたのに草が生えないということがあったので、原因と対処法を残しておきます。
さっそく原因ですが、十中八九ちゃんとメールアドレスが登録されていないことが原因です。
画像のコマンドで、メールアドレスを登録しましょう。
![スクリーンショット 2021-05-24 165505.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532817/51ed5df5-8d86-815f-8e43-6aed8c1089f1.jpeg)
Githubを確認するとちゃんと草が生えているか確認してみましょう。
うん。ちゃんと草が生えていますね。
![スクリーンショット 2021-05-24 170128.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532817/ad3702e0-41dc-66bc-ca0c-fa582abb2354.jpeg)
今回は以上になります。
下記のＵＲＬを参考にさせて頂きました。

https://qiita.com/ryosuketter/items/2f0152b32007ac8351f3
画像があったら表示されるようにしたい

#概要#
Sequel Proに画像が保存されているのに表示されない

Sequel Pro
https://gyazo.com/38c3b30151a6655dd1c79b2fd4ecfa53
localhost:3000/
https://gyazo.com/b5af69a52d4c7a625accbebf4e84d39a

#コード#

```
<% if @items.nil? %>
      <% @items.each do |item|%>
      <li class='list'>
        <%= link_to item_path(item.id),method: :get do %>
        <div class='item-img-content'>
          <%= image_tag item.image, class:"item-img" if item.image.attached? %>
<% end %>

```

```
  <%= image_tag item.image, class:"item-img" if item.image.attached? %>
```
画像を表示させるのはこの記述で画像が存在する場合のみimage_tagが読み込まれるようになります。
記述に問題がないのになぜ表示されない？

#結果#
今回問題だったのはimage_tagではなく

```
<% if @items.nil? %>
```
に問題があった！！
今回は画像がある時にtrueだったら表示されるがこれだと画像がなかったらtrueという記述になってしまうので表示されなかった！！

```
<% if @items.present? %>
```
に変えると値があるものに対してtrueを返すのでこちらを使います。
https://gyazo.com/806c0b2ea77bfe28588df64bf9980c89
Oracle Analytics Cloud ことはじめ 面白い表現方法１

皆さんこんにちは。
今回はOracle Analytics Cloudを利用した分析画面の表現方法についてご紹介します。

１．自分の画像の上にデータをマップできる。
一般的にBIツールを使うときには、ピポット表形式各種グラフなどを利用してデータを表示すると思います。
今回はそれに加えて、画像データに売上データなどの情報をマッピングさせて利用できる機能についてご紹介します。
完成された画面をご覧ください（開発用の画面

![Bike_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1251127/563e79d9-7539-e2dd-df2b-927489f74aac.png)
）

バイクの上に色がついている箇所がデータベースのデータと連携している部分となります。
このように自由な画像に自由に事実データを重ねることで表現できる範囲は大きく広がります。

２．設定方法：画像のアップロード
まずは画像をアップロードします。
画像はコンソール画面のマップからアップロードすると、このように表示されるため分割したいエリアをマーキングしていきます。

![Bike_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1251127/e87f0171-bf48-84ef-a09a-a4c5753748a4.png)

３．設定方法：データのマッピング

画像のデータとどのデータがマッピングされているのかを設定します。
そのためあまり細かく分類してしまうと設定が手間取ります。

![Bike_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1251127/73960d5c-4b2e-470a-6c54-6cc7198ab476.png)

４．設定方法：連携されたデータと画像を表示します
後は項目をドラッグ＆ドロップするだけで色分けされた画像データが表示されます。

![Bike_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1251127/1b1f8229-bf17-07a7-d500-c8c4d55baf85.png)

思った以上に簡単に設定できます。
画像は英語版で作成されていますが、もちろん日本語対応しています。

この機能を利用して、工場内のレイアウトを使って色分けしたり、小売店の売り場を分析しても面白いかもしれません。

作成は非常に簡単ですので、皆さんもぜひやってみて下さい。
詳細の手順は以下の動画で紹介されています。
https://www.youtube.com/watch?v=BhV2479QQZo
AWS ssh鍵を登録する

# 目的

- AWSにssh鍵を登録する方法をまとめる

# 方法

1. AWSコンソールにログインする。
1. 「サービス」をクリックし検索欄に`iam`と入力する。

    ![AWS_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3986c25b-8cf1-116c-b7f7-24c8b35c2ab2.png)
    ![AWS_Management_Console_と_register_blade_php_—_j-project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/75ac9d21-22f8-8cef-0573-27e3d123f257.png)

1. 「IAM」をクリックする。

    ![AWS_Management_Console_と_register_blade_php_—_j-project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/c0f2034d-08df-deb5-ca86-6f32535bab67.png)

1. サイドバーで「ユーザー」をクリックする。

    ![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/abfeeb53-aba5-9cbf-8c66-8b0f2d5b5934.png)

1. ssh鍵を登録したいユーザーのユーザー名をクリックする。
1. 開いたページの概要の中の「認証情報」をクリックする。
1. 「SSHパブリックキーのアップロード」をクリックする。
1. 出現したウインドウに公開鍵の内容を記載して「SSHパブリックキーのアップロード」をクリックする。
【MacOS】のコマンド操作でUSBメモリにアクセスする (Linux,場所)

Macのコマンド操作でUSBメモリにアクセスする方法をメモ。

```
cd /Volumes/[USBメモリ名]
```

入れない場合は、USBメモリ名が間違っている可能性があるため、


```
cd /Volumes/
ls
```
で確認すれば確実です。

以上。
basercms4系のセッション管理にRedisを利用する

baserCMS4.4.6のSession管理にRedisを利用しました。

1. baserCMSについて
1. Redisについて
1. 設定方法
1. 実装内容について

# baserCMSについて
国産のOSSでウェブサイト管理ツールになります。
詳しくは[公式](https://basercms.net/)へGO。

# Redisについて
インメモリなKeyValue型データベースです。
Qiitaにも[【入門】Redis](https://qiita.com/wind-up-bird/items/f2d41d08e86789322c71)て記事がありますのでGO。

# 設定方法
流れとしては下記です

1. Redisサーバを準備
1. Redis用のSessionHandlerを配置
1. install.phpに追記

## Redisサーバを準備
省きます

## Redis用SessionHandlerを配置
[github](https://github.com/gondoh/basercms-redis-session)に実装済みソースがありますので下記に配置してください [zip](https://github.com/gondoh/basercms-redis-session/archive/refs/heads/master.zip)
app/Model/Datasource/Session/RedisSession.php

## install.phpに追記
app/Config/install.phpの最後に下記を追記します。

```
Cache::config('redis', [
	'engine'      => 'Redis',
	'server'      => '127.0.0.1',
	'port'    => 6379,
]);
Configure::write('Session.handler', ['engine' => 'RedisSession']);
```

serverやportはRedisへのアクセス情報に合わせて変更してください。

# 実装内容
実装内容として、CakePHP2が利用されたbaserCMSにはフレームワーク側でRedisをキャッシュエンジンとして利用できるライブラリが備わっています。
そのキャッシュエンジンを利用したCakeSessionHandlerInterfaceを実装しているだけです。

install.phpでは、キャッシュエンジンにredisという標準キャッシュとは別のキャッシュ設定を追加しています。
さらに、Session.handlerでCakeSessionHandlerInterfaceを実装したRedisSessionをセッションで利用する指定を行っています。

以上、誰かの助けになれば幸いです。
BUFFALO製無線AP WSR-1166DHPL2 NTP時刻取得が失敗する

BUFFALO製無線アクセスポイント WSR-1166DHPL2 を再起動したら時計が狂っていたので調査したメモです。
結局ファームウェアの問題だったようです。

# 問題・環境
NTPでの時刻取得が失敗している（時刻取得完了ログが出ない）
`2020/01/01 00:00:10	NTP	NTP Server Start`
オンラインアップデートができない

* 問題の機器: BUFFALO WSR-1166DHPL2
    + アクセスポイントモードで使用
    + IPアドレス、デフォルトゲートウェイ、DNSサーバ手動設定
* 上位機器: NEC BL1000HW
    + auひかりのホームゲートウェイ
    + 回線はIPv6対応

# 解決方法
ファームウェアを1.04にアップデート

# 試したこと
### Ver1.04リリース以前
LAN > LAN側IPアドレスを「DHCPサーバーからIPアドレスを自動取得」
デフォルトゲートウェイ、DNSサーバーを空欄に設定（DHCPから取得）すると時刻取得が成功。
IPアドレスが変わらないようにDHCPサーバ（ホームゲートウェイ）側でDHCP固定割り当てを設定した。

`2021/01/28 23:39:09	NTP	NTP Connection Success => adjusting +34039913.499 seconds`

ファームウェアを1.03にアップデートし、リリースノートの説明通りにNTPサーバの設定を`ntp.nict.jp`に変えるとオンラインアップデートができるようになった。

https://www.buffalo.jp/support/download/detail/?dl_contents_id=62180
> Ver.1.03[2020/11/16]
IPv6の回線でもオンラインアップデートができるように修正しました。IPv6の回線でオンラインアップデートするには、「ntp.nict.jp」など、IPv6とIPv4の両方で時刻取得できるNTPサーバーを指定する必要があります（「ntp.jst.mfeed.ad.jp」では、IPv6に対応しておりません）。

### Ver1.04リリース
ファームウェアが自動で1.04にアップデートされていた。
IPアドレス、デフォルトゲートウェイ、DNSサーバを手動設定に戻してもNTPが成功するようになった。
また、NTPサーバ`ntp.jst.mfeed.ad.jp`でもNTP時刻取得とアップデートができた。（=元通りの設定のままファームウェアアップデートで解決する）

オンラインバージョンアップの問題を修正したと書いてあるが、NTPの問題も治っているらしい？
> Ver.1.04[2021/02/24]
・本商品背面のROUTER/APスイッチを「AP」にした状態で、IPアドレス取得方法を「手動設定」にすると、オンラインバージョンアップができない問題を修正しました。
PHP8.0.6 / Xdebug3.0.4-8.0/ Eclipse の環境構築 

# はじめに
PHP上級試験とは関係ないのだけど、
なんとか仕事もらってPHPの環境構築することになり、
昔やったことを思い出しながらやった結果、なんとかできたので備忘録としてメモ。

# やること
「php eclipse 環境構築」で調べたらたいてい出てくるのと同じ。
０） Xamppをインストール
そもそもなぜEclipseにXamppあるのになぜ当時の自分はXamppを分けてインストールしたのか考えたのだけど、
どうやらEclipseじゃなくて、PHPStormをインストールする記事と読み間違えてたようです。
↑
そこから環境変数PathにXamppを通しておいたりとかして、Eclipseで起動できるかどうかやっていた気がします。
本来は、１）からスタートすればよかっただけなのに。。。

1) Eclipseのインストール
https://mergedoc.osdn.jp/
私はEclipse２０２１＞PHPのWindows64ビットをDL。
32ビットか64ビットかはWindowsのバージョンによっても異なるので確認してから
それぞれの環境に合うものをDLすればいいと思う。
２）XamppでApacheを起動させる（これは電源切るたびに毎回します）
　これインストールしたときはやっていても、続きやるときにApache切れてて使えなかったという
　ようなことがあります
３）Eclipse起動
　ここで、Workspaceは日本語名書いたらハマります
　デフォルトが日本語なので英語で作成しておくとよいかと。
４）よほどのことがない限りここまでは順調にいけると思います
　ここで、phpinfo()をやっておいて、コードをコピーしておきます。


５）次にXdebugのインストールへ。
  ここで、４）でコピーしたコードを貼り付けます
　https://xdebug.org/wizard.php
６）出てきた指定のXdebug.dllをダウンロードします。

ここで、デバッグをしてみようと思ったら、
57％あたりで止まってしまったり、ブレークポイントで止まらなかったりというような現象が起き、
調べていたら、日が暮れて、その日は終了。

次の日（といっても月曜日）の午後改めて調べ直し。
エラーで調べるのをやめて、PHP8.0にXdebugインストールと言うところで調べると
やっとわかった。

Xdebugは２．０系と３．０系とでは書き方が異なるらしい。
http://www.y2sunlight.com/ground/doku.php?id=eclipse:xdebug3

というわけで、
[xdebug]
xdebug.mode=debug
xdebug.client_host="localhost"
xdebug.client_port=9000
xdebug.start_with_request=default
zend_extension=C:\usr\xampp7.3.25\php\ext\php_xdebug-3.0.1-7.3-vc15-x86_64.dll
のように書き直せばよかったらしい。

なお、portの部分は自分の環境のポート、extensionの部分は、Xdebagのdllを格納した場所に書き直すことに注意。
私の場合は、最初DLしたXamppの中にあったphp/ext/のところにdllがあったのでこれを格納場所にしています。
EclipseだけDLしたなら、その中にXamppがあるのでそこの格納場所を書けばいいと思います。

そして重要なこと。
上記のdllファイルを格納したら、格納場所にある、ｐｈｐ_xdebug.dllは削除しておくこと（バックアップとして、デスクトップとかにコピーしといたらいいです）
こうして再びデバッグしたら、、、成功しました！

ということで環境構築終了！

#今回ハマったのは

・環境変数（と、Xamppを最初にインストールしたことが間違い）
・Xdebug2.0系と３．０系とでは書き方が違う
・dllは１つだけにする

でした

今回は仕事用のWindowsだったけど、プライベートのmacも8.0にしてみよっと。

# 追記（2021.05.25）

・結局、xamppはEclipseの外で使うと、やりたいことについて色々弊害が出てきてしまうので、結局外のxamppとEclipseすべてを削除、DL、インストールし直した。
その時は３０分程度で完了した。
このときは、どこでハマるかというのがわかっていて、上記の３．０のを直せばすぐできた。
やはり環境構築の場数を踏むというのはすごく大事。
ちなみにここで、環境変数を変えたりとかはしていない。やはり余計なことをすると、余計な作業も増えてしまうってわけか。。。
まあ、スキルアップしたと考えればそれもまたよし。

# さらに追記（2021.05.26）

チュートリアルサイトの場合、大抵は新規作成から入るので、
ほぼxamppの中のhtdocsというフォルダにphpファイルが作られてその中だとデバッグなり、実行だったりもできる。

しかし、たとえば、GitHubなど他からクローンで持ってきたフォルダはC:¥直下においたりなどして、htdocsの中に入れていなかったりして、その中で実行しようとしても絶対に実行できない。
したがって、htdocsのフォルダの中に開発したいやつをクローンで持ってきたらいいことになる。
ここに気づかず、調べたりして右往左往してた。ガッデム。

でもここで疑問。
たとえばhtdocsじゃない他のフォルダに置きたい場合、設定はどうすればいいのだろうか？
今は時間がないので、ひとまず疑問を書いておく。
【TS】Typescriptで役に立つかもしれない物たち

初書：2021/05/24
mac : 11.2.3
vscode : 1.56.2

# 前書き

typescriptを触っている時に色々と小物を見つけたのでメモ。
随時追加する可能性あり。

# import exportの関係を可視化する

ファイル数が大きくなると複雑になってくるimportとexportの連携を図で見れるようにする。

今回は「Madge」というライブラリを使用する。

[madge - npm](https://www.npmjs.com/package/madge)

## インストール

madge本体と、図示化するためにgraphvizをインストールする

```zsh
% npm -g install madge
% brew install graphviz
```

madgeのページには`brew install graphviz || port install graphviz`と書いているのだが、portコマンドらしきものはないので一旦無しでやる。

`Error: Permission denied @ apply2files - /usr/local/lib/node_modules/npm/node_modules/.bin/is-ci`
なぜかパーミッションエラー。でもインストールは完了しているらしい。よく分からん。（詳しい人教えてください）

## 画像生成

インストールが完了したら、基準となるtsファイル（例としてmain.ts）の相対座標をメモし、以下を実行

```zsh
% madge --image dependencies.svg main.ts
```
`dependencies.svg`のファイル名は任意。出力先。`main.ts`が基準となるファイル。
`dependencies.svg`ができたら、ブラウザ等で開くと表示される。

非常に簡単でみやすい。ありがたい。

## 参考サイト：

[JSの依存関係を視覚化できる「Madge」が便利すぎる - GOOTA TECH](https://tech.gootablog.com/article/js-madge/)

# tsファイルをとりあえず実行する

デバッグとか。テストとか。わざわざコンパイルして動かしたくないけど動作確認したい時に使う用。

## インストール

```zsh
% npm install --save--dev ts-node
```

`--save--dev`はnodejsで使ってるので。

## 実行

```zsh
% npx ts-node main.ts
```

main.tsは実行したいファイル。

## 参考サイト：

[tscコマンドを使わずに.tsファイルを実行する - Qiita](https://qiita.com/Yorinton/items/28c46333e9d4f714e09c)
ThreeTenABPのLocalDateTimeからミリ秒を除外する

```build.gradle
dependencies {
    ...
    def threeTenAbpVersion = '1.3.0'
    implementation "com.jakewharton.threetenabp:threetenabp:$threeTenAbpVersion"
}
```

```MainActivity.kt
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.jakewharton.threetenabp.AndroidThreeTen
import org.threeten.bp.LocalDateTime
import org.threeten.bp.OffsetDateTime
import org.threeten.bp.format.DateTimeFormatter
import org.threeten.bp.temporal.ChronoUnit

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

	// ThreeTenABPを初期化
        AndroidThreeTen.init(this)

	// truncatedTo(ChronoUnit.SECONDS)で秒以下を切り捨て
        val localDateTime = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_DATE_TIME)

        Log.d("ThreeTen", localDateTime)

        val offsetDateTime = OffsetDateTime.now().truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_DATE_TIME)

        Log.d("ThreeTen", offsetDateTime)
    }
}
```

> 出力結果

- D/ThreeTen: 2021-05-24T16:31:28
- D/ThreeTen: 2021-05-24T16:31:28+09:00