OmniAICreator/Qiita-1.07M huggingface dataset:
ATOMCamのシェルに入る

この記事はあくあたん工房 GWアドベントカレンダー 2020、6日目の記事です。
https://gw-advent.9wick.com/calendars/2020/86

# ATOMCamとは
今年1月中頃から[Readyfor](https://readyfor.jp/projects/atomcam)でクラウドファンディングを行っていた、一台2000円台の小型監視カメラ。
クラウド連携などに対応している。

## ATOMCamの中身について
ATOMCamはHuaLai Tech iSmartCam, Xiaomi Dafang, WyzeCam(V2)などで知られた製品のCPUなどが変更されたもの(≒OEM)である。(参考: [WYZE LABS製の監視カメラはOEM提供を受けた製品だった](https://yasurok2.wordpress.com/2019/05/21/wyze-cams-were-oem-products/))
[分解記事](https://qiita.com/Dmitrievich/items/72fc7d200375d0526d4a)によると、他の製品ではIngenic T20(21?)であったCPU(SoC)がIngenic T31となり、H.265ハードウエアエンコーダーなどが追加されている。

# 本題
上記の分解記事にある通り、従来のrootパスワードを使う方法ではシェルにアクセスできない。
ファームウェアを書き換えるのも、SoCが変化している以上brickする危険がある。
そこで今回は、公式のアップデート機能をMITMして違うアップデートファイルをダウンロードさせることでrootログインを可能にすることを試みた。

### 利用するツール
* [Fiddler](https://www.telerik.com/fiddler)　MITMするために利用する。
* squashfs-tools(Linux) ファームウェア更新ファイルを書き換えるために使う（無くてもいいかもしれない・要検証）

### 手順
まずは端末にFiddlerのプロキシを設定、証明書をインストールします。(解説省略)
その後、ATOMアプリからアップデートを確認すれば以下のようなリクエストが飛ぶはずです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183667/0768611c-a2b7-18e1-d143-1ee0932af513.png)
これがATOMのファームウェア更新一覧です。ここにあるファームウェアを書き換えてログインを可能にします。
ちなみに、ここでリクエストを捕捉できているということは、リクエストの書き換えが可能ということです。

さて、さっそく記載されているURLからファームウェアをダウンロード・展開してきます。(以下の作業はLinux環境で行うほうがいいでしょう)

```shell
$ wget https://atom-upgrade-package.s3-ap-northeast-1.amazonaws.com/UpgradeKit/1585636528/Upgrade_4.33.1.40.tar
$ tar xvf Upgrade_4.33.1.40.tar
Upgrade/
Upgrade/PARA
Upgrade/upgraderun.sh
Upgrade/rootfs
```

なんとなくアップデートの仕組みが見えてきました。ここでupdaterun.shの中身を確認してみます。(以下抜粋)

```shell
#!/bin/sh
flash_eraseall /dev/mtd5
sync
echo "write backa !!!!!!!!!!!"
flashcp -v /tmp/Upgrade/rootfs /dev/mtd5
sync
echo "erase para !!!!!!!!!!!"
flash_eraseall /dev/mtd7
sync
echo "write para !!!!!!!!!!!"
flashcp -v /tmp/Upgrade/PARA /dev/mtd7
sync

reboot
```

どうやら、内部にイメージファイルを持っていて、それをmtdに書き込んだあとにrebootするようです。ここで、mtd5は`aback`という領域になっています。そして、PARA(=parameter?)というファイルには `FWGRADEUP=rootfs` という文字列が書き込まれていました。
再起動後の挙動を見る限り、U-Bootがこの文字列を読み取り`aback`から`rootfs`(mtd2)に複製することでアップデートが完了するようです(内容の検証をしているかまでは不明)。
ではここでrootfsの中身を見ていきましょう。

```shell
$ file rootfs
rootfs: Squashfs filesystem, little endian, version 4.0,・・・・
$ unsquashfs rootfs
・・・・
```

fileコマンドよりrootfsはSquashFSであることがわかりました。なので`squashfs-tools`の`unsquashfs`コマンドで展開します。
するとLinuxの標準的なrootfsが出現してきます。なので、そこの`/etc/shadow`を書き換えてしまいましょう。
ほかにも、/etc/init.d/rcSを書き換えるといろいろと起動させることもできます。
書き換えた後はmksquashfsでrootfsを再構築します。xzで圧縮です（もとがそうだったので）
その後またtarに固めます

```shell
$ tar cvf Upgrade_new.tar ./temp
....
```

さてさて、ここまで来たらFiddlerのAutoResponderでアップデート情報のJSONを書き換えるだけですが、`fileinfo`というところは良く分からないままですね。
長さ的に推測できますが、ここは単純にtarのmd5です。HMACとかではないです。
また書き換える際の注意として、アップデートのダウンロードは実際にはATOMCam側で行うので、tarは実際のHTTPSが使えるサーバ上に置いておかないといけません（ホスト名とかはなんでもいいです。Let's Encryptでいけます）

さっきのHTTPリクエストを選択して、AutoResponderのルール一覧のところにD&Dします。「Enable rules」のチェックもお忘れなく。
そして、D&Dで作成されたRuleを選択しF2でレスポンスを編集、SyntaxViewあたりで書き換えてしまいましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183667/9060a821-77bd-3fb4-b7d8-032a06d5538d.png)


ここまでくれば公式アプリでファームウェア更新をすればいけます。
sayコマンドでLINE Clovaを使い倒す

# やりたいこと

- 声で操作すべきデバイス（LINE Clova）を自分の肉声を出さずに操作する
- 機械どうしが意思をもって語り合っているかのような雰囲気を醸し出す

# 方法

- macOSデフォルトの`say`コマンドを使う
- 声は日本女性の`Kyoko`さんにする
- LINE Clova側の設定で、声認証をONにしていると自分の声でないmacOSの音声には反応しないので、予めOFFにしておく。スマホアプリの`声認証`項目参照

```shell
$ say -v Kyoko クローバ
```

（Clova 「ポンっ（緑に光る）」）

```shell
$ say -v Kyoko 明日の天気は
```

（Clova「明日は曇りのち雨でしょう。降水確率は…」）

# 工夫

- macOSの`crontab`で`say`コマンドの発動を設定しておけば、LINE Clovaを実質的なアラームとして使うことができる（特にMac miniユーザーとかよさそう）
- 毎回`say -v Kyoko XXX`を打つのは面倒なので、シェルのエイリアスで`alias say=say -v Kyoko`などの設定をしておくといいかも
- LINE Clovaの[マイコマンド](http://clova-blog.line.me/ja/archives/17164378.html)機能との合わせ技。先述の`crontab`と組み合わせれば「毎朝7時に勝手にその日の天気と予定を伝え、好きなプレイリストの音楽を流し始めるLINE Clova」とかがつくれる

おわり
AWS未経験SIエンジニアがAWSクラウドプラクティショナーに合格するまで

今月、AWSクラウドプラクティショナーを受験し合格したので勉強法を解説します。
#AWSクラウドプラクティショナーとは
- AWSの全体的な理解を計る試験です。下図の通りベーシックレベルの試験なので簡単かな？と思いますが、広く浅くAWSのことを聞かれるので、インプットすべきことは多いです。
（画像は４つに分かれているように見えますが１つの試験です。）
- 試験時間は９０分で合格ラインは７００点以上です。（１００点〜１０００点の範囲）
![AWS_Certification_Roadmap_2018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281220/461f4643-8af5-5225-b626-f08e4d73d68b.png)

#勉強前の私のスキル
- 前提として私のスキルは、新卒でSIerに入社し、仮想サーバ・ストレージ・ネットワーク（セキュリティ含む）の開発・運用・保守を４年しており、インフラの基本的な知識がありました。なので、AWSを触っているときにオンプレでいうと○○のことか！と自分が持っている知識と紐付けながら勉強しました。

#勉強したこと
- 「[AWSをはじめよう](https://booth.pm/ja/items/1032590)」のハンズオンで主なサービスを理解する。（1500円）
    - AWSを触ったこともなかったので、とりあえず、初心者向けの本をチョイスしました。この本ではAWSのサービスを組み合わせてWordpressを使ったblogを作ります。

    - ハンズオンの手順が丁寧で主要なサービスを理解するにはとても良かったです。具体的に以下の手順でblogを作りました。

    1. EC2でWebサーバ構築
    2. Route53でblogのドメインを設定
    3. RDSでDB作成
    4. Wordpressインストール
    5. 記事の画像をS3に保存
    6. ELBで負荷分散
    7. AutoScalingでサーバ自動復旧

- 参考書を読み、ハンズオンで触っていないサービスの概要を理解する。
[AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー(kindle版)](https://www.amazon.co.jp/dp/B07QX45RXM)（2356円）
    - 「AWSをはじめよう」でAWSの主要サービスを理解しましたが、試験は他のサービスについても聞かれるので、参考書を買いました。初めて出てきたサービスはノートにメモし理解しました。

- Udemy問題集を正答率70%以上になるまで繰り返す
[この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問)](https://www.udemy.com/course/aws-4260/)（3600円）
    - 試験に向けた総仕上げに問題集を解きました。この問題集は演習テストが６つありますが、難易度高の６つ目以外の５つを正答率７０％以上になるまでやりました。結局2周して70％以上になり、試験の予約をしました。


#試験の結果
スコアは755／1000で合格でした！
おそらく数問ミスしていたら不合格だったので、問題集で80%以上正解していると安全だと思います。

#さいごに
- 最初にハンズオンでblogを作ったことで主要なサービスを理解でき効率的に勉強できました。「AWSをはじめよう」は初心者向けに書かれているので、これからAWSを始める方に非常におすすめです。

- 次は、以下の書籍で各サービスの理解を深めて、「ソリューションアーキテクト　アソシエイト」の合格を目指します！

    - [Amazon Web Services 基礎からのネットワーク＆サーバー構築　改訂3版 大澤 文孝](https://www.amazon.co.jp/dp/B084QQ7TCF/ref=cm_sw_r_tw_dp_U_x_2t7REb7QFVV1M)

    - [Amazon Web Services パターン別構築・運用ガイド 改訂第2版 NRIネットコム株式会社](https://www.amazon.co.jp/dp/B07BMQL59H/ref=cm_sw_r_tw_dp_U_x_ou7REbBK496RM)
ショートカット集

デュアルディスプレイ(Windows)
- アクティブウィンドウを別ディスプレイに移動　　
　`Windows + Shft + ⇄`
- アクティブウィンドウを同一ディスプレイ内で移動
  `Windows + ⇄`
　　

VSCode（Mac）
- ターミナルのOpen/Closef
  `ctr+shift+' `
-１行コピー
   ` ctr+shift+^ `
JUCEを使うためにDebian Buster環境をParallelsを使ってセットアップ

Parallelsのガイドではなく、手動でDebianをインストールしたときのメモ。RaspbianがBusterだったけど、ガイドからインストールできるDebianがStretchだったので手動で行う必要があった。なぜこんなことしたいのかというと、RaspberryPi上でビルドするのは遅いし動作確認もめんどくさいのです。なので、可能な限りのことはMac上で行いたい。JUCEはMac/Windows/Linuxのマルチプラットフォームで動くアプリが書けるので、通常はMacで動作確認するんだけど、ごく一部OS依存の挙動とか、フォルダ・ディレクトリ構成の違いとか、フォントの違いによる差異などを確認しなければならないのでその時にDebianを使いたいのです。ちなみに僕にはLinuxの知識はほとんどありません。

## Debianのインストール
Debianの公式サイトからネットインストール用のディスクイメージをダウンロードして、Parallelsでインストールする。

## 一般ユーザーにsudoの権限を与える
インストール後にできているユーザーはsudoの権限を持っておらず色々めんどくさいのでに、ターミナルを起動して、下記を行う。

```
su
(パスワード)
apt-get install -y sudo
gpasswd -a <username> sudo
```
一旦ログアウト。

## Parallels Toolsのインストール
[ここ](https://kb.parallels.com/en/124805)の通りに行う。

## Clangをインストール
```
sudo apt-get install clang
```

## Gitをインストール
```
sudo apt-get install git
```

## JUCEを設定
JUCE本体をクローン。

```
git clone https://github.com/WeAreROLI/JUCE.git
```
ビルドに必要なライブラリをインストール。

```
sudo apt-get install freeglut3-dev g++ libasound2-dev libcurl4-openssl-dev libfreetype6-dev libjack-jackd2-dev libx11-dev libxcomposite-dev libxcursor-dev libxinerama-dev libxrandr-dev mesa-common-dev webkit2gtk-4.0-dev
```
Projucerをビルド、起動してみる。

```
cd JUCE/extras/Projucer/Builds/LinuxMakefile
make CXX=clang++ -j4
./build/Projucer
```

以上、かな。
音声、タッチ、視線入力を備えたスマートスイッチ自作して見えてきたIoTの最適インターフェースについて

#とりあえず機能もりもりのIoTデバイスを作ってみて最適なインターフェースを探る

IoTデバイスの入力は、ホームスピーカーを活用して音声によって扱うのが良いのか、[exUI](https://www.ntticc.or.jp/ja/archive/works/exui/)で代表されるようにスマホのタッチですべて完結するのがいいのか、あるいはAR時代に最適とされる空間Computingの考えを借りるなら、その一例として空間を見るという動作(視線)によって入力を行うのが良いのか。

これはそれぞれのIoTデバイスが実現したい機能によって異なってくるはずである。


このインターフェースの問題は、生活の中で実際に試し、それとともに生活してみて初めて最適解が見えてくるはず。ということで、主に上3つの入力を備えたIoTの代表格スマートスイッチを実装してみた。最近は筋電センサによって腕の動きを取るなどもあるが、家庭に普及しているスマホとホームスピーカーとカメラを用いて活用できる３つのインターフェースの搭載を考えてみる。

![IMG_2183.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222551/eb7d3268-9f4c-673c-25ce-1637c3761ff5.jpeg)

写真のスイッチは、

・スマホアプリ内で操作する(触覚的)
・Alexaに呼びかける(音声的)
・スイッチの方を見る(視覚的)

動作による入力に対応する。
細かいコードまでは記さないが、使用したものなどを簡単に記し、最後に見えてきたことをまとめる。




#BlynkとESP23を用いたタッチ入力

![e8b00fab597d540410e8ae9165a3e78ec865b749.12.2.9.2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222551/813ffbca-25f0-f45c-be2f-c88cc62ca049.jpeg)

BlynkはESP32といった無線モジュールをスマホから操作できるスマホアプリである。

IoT開発で地味に使えるプロトタイピングツールたち - ソフトウェア
https://qiita.com/d-yamamoto/items/ec6ba1b54766e89b514a

に詳細はあるので省くが、連携することでサーボモータに取り付けたピンの入力を下の写真のスマホから操作する(On/Offボタンを押す)ことで、スイッチを45度+方向と-方向へ動かす簡単な仕組み。
<img width="375" alt="IMG_2952.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222551/cc3871a3-79b4-f9f5-a7b0-27f1cadca1a5.png">

#Blynkとifttt(Alexa + Webhook)を用いた音声入力

これは先程のBlynkのアプリが、Httpリクエストを用いてスイッチのOn/Offを管理できることから、iftttを用いて、alexaに〇〇と呼びかけたときに、webhookというアプリがhttpリクエストを送ってくれるという連携を構築することで、alexa入力から、webhookを通じて、blynkのボタンが操作され、それがesp32のサーボ入力に繋がるという流れ。

<img width="412" alt="スクリーンショット 2020-05-03 15.29.41.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222551/af786b70-452a-bf1d-9092-cc05e44ea344.jpeg">


詳しくは、https://wak-tech.com/archives/1546 なんかを参照するといいかも。

#OpenFaceを用いた視線入力

このパートはほとんど、見るだけで押せる「視線スイッチ」
https://qiita.com/takjg/items/afc6348ceed67868d41f
を参照してほしい。変えたのは、視線を検知したら、音声入力同様Blynkのhttpリクエストを送信するようコードを変更しただけである。

#まとめ - スマートスイッチにおける最適なインターフェース

これを簡単に自作してみて3日ほど立つ。見えてきたこととして

視線入力　…　より直感的に操作できる。つまり、使っていて生活の行動リズムに融けるような印象。音声入力のようになれる時間がほとんど必要がない。初心者でも簡単に慣れられるはず。実際に、日常でAlexaを利用しているときに、見る必要のないのにalexaの方を見て喋ってしまうのは、やはり見て何か操作するというのが私達の行動の基底に流れているからなのか。この点から、この方法は認知負担が少ないといえる。ただし、問題点は、暗闇や間の障害物があると使えないことや、見るという入力上複雑な入力を行えないため自由度が低いことがある。

音声入力 …　独り言がインターフェースになるということには、初めて使う人は戸惑うのだが、慣れると一番肉体的負担が少ない、わざわざ視線やタッチのように身体の主要な部分(首とか手)を動かすことなく、喉だけを動かせばいいから。ただし、喋るという行為そのものが脳に対する認知負荷が高いのと、加えてalexaが受け取るべきフレーズみたいなのを一度考えないといけなかったりするので、その分認知負荷は高いと言える。ただし、暗闇の中では間違いなくこれが最適な選択。あとは、スイッチの方を見るのが難しいときなど環境的要因にも強い。特にスイッチは電気と連携させることが多いことを考えると、暗闇での入力にも耐えないといけないことから音声入力が適しているとも言える。

スマホ入力 …　ほとんど使わない。たまたまtwitterを見ていて、電気消すかと思ってスマホ内でBlynkアプリを開いて使う程度。ただし、スイッチ以外に電気の明るさといった0か1でなく、アナログ信号のような複雑度の動作を行う場合には、スマホがより直感的なインターフェースになる。

それぞれ強みがあり。スマートスイッチの場合には電気を扱うことの多さという観点を重視するなら音声がインターフェースとして適切な可能性が見えてきた。一方で、視線入力も行為性への融けといった観点では捨てきれない。２つが別々に存在しても十分機能しそうでもある。スマホは機能上簡単に実装できるのであってもいいが、スイッチというデバイスではあまり使うことはなさそう。

まだ3日程度なので、まだまだ一人称的に最適なインターフェースを探っていきたい。
Railsアプリ立ち上げ（メモ）

随時更新
####1.アプリケーション立ち上げ

```
$ rails new アプリケーション名 -オプション名
#DBをMySQLにしたい場合は
$ rails new アプリケーション名 -d mysql
```

####2.DB作成

```
#立ち上げたアプリのディレクリ内にて
$ rails db:create
>> Created database 'アプリ名_development'
>> Created database 'アプリ名_test'
```
開発環境用とテスト環境用のデータベースが作成される。
database.ymlの内容に基づいてデータベースを新規作成する機能を持っている。
**database.ymlの役割**
・rake db:createのコマンドを実行した時に作成されるデータベースの名称を指定する。
・RailsアプリケーションがSQLサーバーにアクセスするときのソケットファイルの位置を指定する。


####3.サーバー立ち上げ & 停止

```
#立ち上げたアプリのディレクリ内にて
$ rails s #立ち上げ
=> Booting Puma
=> Rails 5.2.4.2 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.4 (ruby 2.5.1-p57), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop

$ rails c #停止
```
ASEのMDモジュールで遊ぶ

ASE (Atomic Simulation Environment) の`ase.md`モジュールを用いて，Ni結晶のMDシミュレーションをしてみます．

## モデル

Ni (fcc) のバルクモデルを作成します．

```python
import numpy as np
from ase.build import bulk
from ase.build.supercells import make_supercell
from ase.calculators.emt import EMT

# Niバルク
Ni_bulk= bulk('Ni', 'fcc', a=3.5, cubic=True) 

# 超格子
Ni_bulk = make_supercell(Ni_bulk, np.diag([3., 3., 3.]))

# EMTを用いる
Ni_bulk.set_calculator(EMT())
```

![Ni_bulk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629650/32c10ce4-5f9f-1941-4a84-aa75980b3fd6.png)

## MDシミュレーションの設定

NVTシミュレーション (体積・温度一定) を行います．
はじめに系の温度を10Kに保ち，その後500Kに上げます．
また20ステップごとに温度の出力も行います．

```python
from ase import units
from ase.md.nvtberendsen import NVTBerendsen
from ase.md.velocitydistribution import MaxwellBoltzmannDistribution

dt = 2 * units.fs
temp0, nsteps0 = 10, 200
temp1, nsteps1 = 500, 400
taut = 20*units.fs
    
MaxwellBoltzmannDistribution(Ni_bulk, temp0*units.kB)
dyn = NVTBerendsen(Ni_bulk, dt, temp0, taut=taut, trajectory='md.traj')
def myprint():
    print(f'time={dyn.get_time() / units.fs: 5.0f} fs ' + \
          f'T={Ni_bulk.get_temperature(): 3.0f} K')
dyn.attach(myprint, interval=20)
```


## MDシミュレーションを実行

```python
dyn.run(nsteps0)

# 温度を上げる
dyn.set_temperature(temp1)
dyn.run(nsteps1)
```

## 結果を可視化する

温度・構造・動径分布関数 (RDF) の変化をmatplotlibを用いて可視化します．

```python
%matplotlib widget 

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from ase.visualize.plot import plot_atoms
from ase.io.trajectory import Trajectory
from ase.geometry.analysis import Analysis

traj =  Trajectory('md.traj')

fig, ax = plt.subplots(1, 3, figsize=(9,3), tight_layout=True)

t = np.arange(nsteps0+nsteps1+1) * dt
temp = [atoms.get_temperature() for atoms in traj]

nframes = 20

def update(iframe):
    idx = int((nsteps0+nsteps1)*iframe/nframes)
    
    ax[0].clear()
    ax[0].set_title('Temperature')
    ax[0].set_xlabel('time (fs)')
    ax[0].set_ylabel('T (K)')
    ax[0].plot(t, temp)
    ax[0].plot(t[idx], temp[idx], marker='X', markersize=10)
    
    ax[1].clear()
    ax[1].set_title('Structure')
    ax[1].axis('off')
    plot_atoms(traj[idx], ax=ax[1], rotation='45x,45y')
    
    distribution, distance = Analysis(traj[idx]).get_rdf(rmax=5., nbins=100, return_dists=True)[0]
    ax[2].clear()
    ax[2].set_title('RDF')
    ax[2].set_ylim((0,10))
    ax[2].set_xlabel('distance (A))')
    ax[2].set_ylabel('distribution')
    ax[2].plot(distance, distribution, color='darkblue')

ani = FuncAnimation(fig, update, np.arange(nframes), blit=True, interval=250.)
ani.save('ani.gif', writer="imagemagick")
```

![anim_Ni.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629650/faf80c4c-6d7e-6103-2a58-ea80dbbe7ad6.gif)

## 参考
- ASE
    - Molecular Dynamicsのチュートリアル <https://wiki.fysik.dtu.dk/ase/tutorials/md/md.html>
    - `md`モジュール <https://wiki.fysik.dtu.dk/ase/ase/md.html#module-ase.md>
- GitHub matplotlib/ipympl <https://github.com/matplotlib/ipympl>
- Qiita
    - とりあえずやってみる分子動力学シミュレーション
 <https://qiita.com/tamaki_osamu/items/4bacfcc7dc78a5bfd94e>
    - matplotlib でアニメーションを作る <https://qiita.com/yubais/items/c95ba9ff1b23dd33fde2>
定刻にMacからチャイムを鳴らす

# やりたいこと

- タイトル通り
- 想定するユースケース：定期的に発生、かつ開始時間やインターバルが決まっているイベント
- オンライン授業とか、週次会議とか、休憩とか

# 方針

- crontab：コマンドを定時に実行させるコマンド
- 手元の環境はmacOS Catalina v10.15.4

# 方法

- crontabコマンドの使い方チュートリアル：[crontabの書き方](https://www.server-memo.net/tips/crontab.html)がおすすめ
- afplay（ターミナルからオーディオファイルを再生するコマンド）を併用
- 予め任意のmp3ファイルを好きなパス（ここでは`~/Music/chime.mp3`）に置いておく
  - Webで探すなら[soundsnap](https://www.soundsnap.com/)がオススメ



- crontabの編集

```sh
$ crontab -e
```

- デフォルトのエディタで`crontab.XXXXXXXXXX`みたいなファイルが開かれる
- 好みの設定を記述して、ファイルを保存・エディタquit

```sh
25 8 * * mon-fri afplay ~/Music/chime.mp3
20 10 * * mon-fri afplay ~/Music/chime.mp3
55 12 * * mon-fri afplay ~/Music/chime.mp3
50 14 * * mon-fri afplay ~/Music/chime.mp3
# Comment for the newline of crontab termination character. See man 5 crontab
```

- 月曜〜金曜の8:25・10:20・12:55・14:50に`chime.mp3`が再生される
- 最終行にコメントがないとなぜか実行がうまくいかなかったので付してある
  - [cronの最終行が実行されない原因と対処法](https://qiita.com/airtanker/items/72359c234f898e3255d2)

- 確認：`$ crontab -e`

# 参考

- [Macに現在時刻を喋らせる - 橋本商会](https://scrapbox.io/shokai/Mac%E3%81%AB%E7%8F%BE%E5%9C%A8%E6%99%82%E5%88%BB%E3%82%92%E5%96%8B%E3%82%89%E3%81%9B%E3%82%8B)

おわり
IBM i (旧AS400）の自己学習メモ　RPG Ⅳプログラミング編０３　コンパイル時配列（DS/INZ/OVERLAY）

# 自己学習メモインデックス

[IBM i (旧AS400）の自己学習メモ　インデックス](https://qiita.com/You_name_is_YU/items/3964849e7803c8eaf767)

# 概要

[IBM i (旧AS400）の自己学習メモ　RPG Ⅳプログラミング編０２　コンパイル時配列（CTDATAを使う）](https://qiita.com/You_name_is_YU/items/41d9845dbe4360694d32)でCTDATAを使ったコンパイル時配列の初期化の記事を書きましたが、これはRPGの古い使い方？のようです。

CTDATAの調査をしている中で、やり方が分からないので別の方法に逃げようかなぁと思って探していたのが、この記事の方法です。

# DS/INZ/OVERLAYを使ったコンパイル時配列の実現

以下サンプルコードです。

```shell
 FMT *  ..... *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
        *************** Beginning of data **********************************************
0001.00       * コンパイル時配列用の変数定義                                          
0001.02      D @@DSMODES       DS                                                       
0001.03      D                                6    INZ('登録')                        
0001.04      D                                6    INZ('更新')                        
0001.05      D                                6    INZ('削除')                        
0001.06      D @@MODES                        6    DIM(3) OVERLAY(@@DSMODES)            
0002.01       * インデックス変数                                                      
0002.02      D i               S              1P 0 INZ(1)                               
0003.00       * コンパイル時配列の値を表示                                            
0003.01      C                   FOR       i = 1 to 3 by 1                              
0003.02      C     @@MODES(i)    DSPLY                                                  
0003.03      C                   ENDFOR                                                 
0006.00       * RPGの終了                                                             
0007.00      C                   EVAL      *INLR = *ON                                  
        ****************** End of data *************************************************
```

重要なのは以下の部分です。

- `D @@DSMODES       DS`
    - DS：Data Structure（データ構造）という技術を使った構造体を定義
    - 構造体には３つの要素（サブフィールド）を名前を付けずに定義し、初期値（INZ）として文字列を定義。
- `D @@MODES                        6    DIM(3) OVERLAY(@@DSMODES)`
    - OVERLAYで構造体で定義した登録，更新，削除の各サブフィールドの値を、@@MODESの配列にオーバーレイ（重ねる）して配列を初期化しています。
    - OVERLAYキーワードは、1 つのサブフィールドの記憶域に別のサブフィールド の記憶域、またはデータ構造自体の記憶域をオーバーレイ させます。という役割があるようです。

参考：https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_71/rzasd/sc092508551.htm

```shell
0001.00       * コンパイル時配列用の変数定義                                          
0001.02      D @@DSMODES       DS                                                       
0001.03      D                                6    INZ('登録')                        
0001.04      D                                6    INZ('更新')                        
0001.05      D                                6    INZ('削除')                        
0001.06      D @@MODES                        6    DIM(3) OVERLAY(@@DSMODES)  
```

CTDATAを使うより、こっちの方が初心者には読みやすい気がします。
ただ、配列を初期化するのに、わざわざ別の変数を定義して、それをオーバーレイしなければ初期化できないとは、なんて不便な、、、

こんな風に１つにまとめられればいいのにと思いました。

```javascript
var modes = ["登録", "更新", "削除"];
```
Kaggleとは何かをざっくり理解する


Kaggleで何ができるのか、どう始めればいいかをまとめました。
**Kaggle：[https://www.kaggle.com/](https://www.kaggle.com/)**


#はじめに
世間でAIや機械学習、ディープラーニングが流行っていて、何か勉強してみようかなと思いつつサボっていました。最近は家で暇しているので、噂のKaggleに登録してみました。調べたことを主観でざっくりまとめます。

#Kaggleとは　
Kaggleは、データサイエンス・機械学習のコミュニティーサイトで、世界の40万人企業や公共団体がデータ分析の課題をコンペとして賞金付きで登録しており、ユーザーが分析手法を競い合う場になっています。Googleが親会社。

###特徴
- 機械学習について手軽に情報交換できる。ソースコードも見れる。
- Jupyter Notebookが用意されている。
- 解説サイトや参考になる書籍が豊富。
- 腕試しができるのでモチベーションにつながる。
- 全部英語。苦手な人は自動翻訳や日本語の解説サイトを活用しましょう。

#こんな人におすすめ？
- 機械学習に興味があるけど何から始めればいいか分からない人
- 簡単なプログラムは書けるけど作りたいものがない人
- 暇で何か自己学習しようとしているSEや学生

#進め方
1. サイトに登録。Googleアカウントで簡単に登録できます。
2. チュートリアルに取り組む。（下記参照）
3. 好きなコンペを探して挑戦

#チュートリアル
「Titanic」という練習問題がチュートリアルとして用意されています。
[https://www.kaggle.com/c/titanic/overview](https://www.kaggle.com/c/titanic/overview)

#もっと知りたい方
以下の記事が分かりやすいです。
**[Kaggle事始め](https://qiita.com/taka4sato/items/802c494fdebeaa7f43b7)**
コンペの進め方が簡潔にまとめられています。
**[データサイエンティストを目指して勉強するなら、Kaggleからはじめよう](https://qiita.com/KIKUYA-Takumi/items/13ac849582318f559271)**
データサイエンスの学び方を中心に説明されています。
**[Kaggleに登録したら次にやること ～ これだけやれば十分闘える！Titanicの先へ行く入門 10 Kernel ～](https://qiita.com/upura/items/3c10ff6fed4e7c3d70f0)**
コンペの進め方から実際のソースの書き方、機械学習の基本まで細かく書かれています。
ウェーブレット変換を用いたノイズ除去法

kaggleのkernel(今はnotebook)で「こんな方法があるんだー」と納得したノイズ除去法があったので、あれこれ調べてみたことを以下にメモがてらまとめます。

##方法の概要 

ある信号や波形に対しての解析手法として**ウェーブレット変換**と呼ばれるものがある。
解析手法としてフーリエ変換をイメージすることが多いと思うが、フーリエ変換が波形を三角関数（さいん、こさいん）の和に展開するのに対して、ウェーブレット変換では好きな形の波形で分解することが出来る。（しかも逆変換ある）

よって、与えられた波形に一部特徴的な波（**マザーウェーブレット**）が確認できたら、その波を基底として分解してあげることにより、どの時間帯や規則でその特徴が現れるかを確認することが出来る。（分解したときに現れる係数を**ウェーブレット係数**という）

したがって、ノイズの形が把握出来たらそれをマザーウェーブレットとしてウェーブレット変換をし、ノイズ部分を0に置き換えてから逆変換を行えば、ノイズが無い波形が得られる。

##手順

さて、以上の仕組みを与えた関数が以下である

```python
import numpy as np
import pywt 

def maddest(d, axis=None):
    return np.mean(np.absolute(d - np.mean(d, axis)), axis)

def denoise(x, wavelet='db', level=1):
    coeff = pywt.wavedec(x, wavelet, mode="per")
    sigma = (1/0.6745) * maddest(coeff[-level])

    uthresh = sigma * np.sqrt(2*np.log(len(x)))
    coeff[1:] = (pywt.threshold(i, value=uthresh, mode='hard') for i in coeff[1:])

    return pywt.waverec(coeff, wavelet, mode='per')
```

一番目のdefでは平均絶対偏差の計算を与えている
偏差とは各データと平均との差であり、絶対偏差とは偏差の絶対値、そして平均絶対偏差とは絶対偏差を母数で割ったもの、つまり平均である。

例：50点、70点、90点、70点の４つのデータ(平均70点)
　　偏差は-20、0、20、0 であり、
　　絶対偏差は20、0、20、0 であり 、
　　平均絶対偏差は(0+20+20+0)/4=10である。

二番目のdefでは波形のノイズ除去を与えている。まず

```python
coeff = pywt.wavedec(x, wavelet, mode='per')
```
では与えられた波形をウェーブレット変換している。
パラメータxは配列データ、waveletはウェーブレットの名前（今回はdb）、modeは境界条件のこと（perで波形の右端と左端が繋ぐことを意味する）
coeffはウェーブレット係数のリストとして与えられる。（但し、初めから一番目はウェーブレット係数ではない。最小の解像度の余りが格納されている。）

次に

```python
sigma = (1/0.6745) * maddest(coeff[-level])
```

ではノイズの大きさを与えている。maddest(coeff[-level])でウェーブレット係数のリストの後ろから一番目の値の平均絶対偏差を表している（リストの後ろであればあるほど解像度が高い。その設定をlevelとしている）。0.6745はおまじない、、といいたいところではあるが、標準偏差と平均絶対偏差との比率を表す定数である。

次に

```python
uthresh = sigma * np.sqrt(2*np.log(len(x)))
coeff[1:] = (pywt.threshold(i, value=uthresh, mode='hard') for i in coeff[1:])
```
では、まず閾値(uthresh）の計算をして、ウェーブレット係数がその閾値を下回ったらノイズとみなして０を与える処理を行っている。

最後に

```python
return pywt.waverec(coeff, wavelet, mode='per')
```
で、ウェーブレット変換の逆変換で元の形に戻す。先ほどの閾値とのギャップを調べる処理を経ているから、ノイズがなくなった波形が得られるのである。

##感想

もうちょっと理論おっかけてみたいと感じた。

##参考
[Discrete Wavelet Transform (DWT)](https://pywavelets.readthedocs.io/en/latest/ref/dwt-discrete-wavelet-transform.html)
[ウェーブレット変換の基本](https://www.hellocybernetics.tech/entry/2017/06/17/040736)
[ウェーブレットによるノイズ除去](https://medium.com/@junkoda/%E3%82%A6%E3%82%A7%E3%83%BC%E3%83%96%E3%83%AC%E3%83%83%E3%83%88%E3%81%AB%E3%82%88%E3%82%8B%E3%83%8E%E3%82%A4%E3%82%BA%E9%99%A4%E5%8E%BB-fc20d82bcb80)
pyOCRを用いて、カード中の説明文をテキスト化する

# 目的
pyOCRを用いて、カード中の説明文をテキスト化する際の備忘録です

# 準備
- pyOCR、Tesseract、jpn.traineddataをインストール

> [Mac環境でpyOCRで画像データをテキスト化する](https://qiita.com/seigot/items/7d424000c8d35e5146e4)
> PyOCR インストール
>
>```
$ sudo pip install pyocr
```
>
>OCRエンジン部である Tesseract をインストール
>
>```
$ brew install tesseract
$ ls /usr/local/Cellar/tesseract/4.1.0/share/tessdata/
```
>
>jpn.traineddataを取得
>
>```
$ wget https://github.com/tesseract-ocr/tessdata/raw/4.00/jpn.traineddata
$ mv jpn.traineddata /usr/local/Cellar/tesseract/4.1.0/share/tessdata/
```

- カード

（例）カードは以下を使用させて頂きます。
引用：[遊戯王デュエルリンクス攻略](https://www.google.com/url?sa=i&url=https%3A%2F%2Fkamigame.jp%2F%25E9%2581%258A%25E6%2588%25AF%25E7%258E%258B%25E3%2583%2587%25E3%2583%25A5%25E3%2582%25A8%25E3%2583%25AB%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25AF%25E3%2582%25B9%2F%25E3%2582%25AB%25E3%2583%25BC%25E3%2583%2589%2F%25E9%259D%2592%25E7%259C%25BC%25E3%2581%25AE%25E7%2599%25BD%25E9%25BE%258D.html&psig=AOvVaw3wIPO8FpnvpxrtFSCtCIN2&ust=1587370256244000&source=images&cd=vfe&ved=0CA0QjhxqFwoTCPiXxpiF9OgCFQAAAAAdAAAAABAD)
![card1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/8f50d346-efbd-5f03-0021-4e59f56d5df1.png)


# コード

```py:sample.py
from PIL import Image
import sys
sys.path.append('/path/to/dir')

import pyocr
import pyocr.builders

tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("No OCR tool found")
    sys.exit(1)
tool = tools[0]
print("Will use tool '%s'" % (tool.get_name()))

langs = tool.get_available_languages()
print("Available languages: %s" % ", ".join(langs))

txt = tool.image_to_string(
    Image.open('card.png'),
    lang='jpn',
    builder=pyocr.builders.TextBuilder()
)
print(txt)
```

# テスト

```
$ python sample.py
Will use tool 'Tesseract (sh)'
Available languages: eng, jpn, jpn_vert, osd, snum
士 い 攻 繁 カ を 誇 る 侵 設 の E ラ ゴ ン 。 ど ん な 祖 子 で
も 物 碑 す る 、 そ の 碇 壊 カ は 計 知 れ な い 。
```

# 備考
どうすればより高い精度で検出できるのだろう。

# CodingError対策
問題：
　OCRの結果が出力されない
対策：
　画像中の文字が小さくて解析できていない可能性があります。
　画像サイズを大きくすると解析できました。
　（もしくは、他に必要な前処理があれば実行すると良い。例：背景ノイズ除去）

# 参考
[遊戯王デュエルリンクス攻略](https://www.google.com/url?sa=i&url=https%3A%2F%2Fkamigame.jp%2F%25E9%2581%258A%25E6%2588%25AF%25E7%258E%258B%25E3%2583%2587%25E3%2583%25A5%25E3%2582%25A8%25E3%2583%25AB%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25AF%25E3%2582%25B9%2F%25E3%2582%25AB%25E3%2583%25BC%25E3%2583%2589%2F%25E9%259D%2592%25E7%259C%25BC%25E3%2581%25AE%25E7%2599%25BD%25E9%25BE%258D.html&psig=AOvVaw3wIPO8FpnvpxrtFSCtCIN2&ust=1587370256244000&source=images&cd=vfe&ved=0CA0QjhxqFwoTCPiXxpiF9OgCFQAAAAAdAAAAABAD)
[Mac環境でpyOCRで画像データをテキスト化する](https://qiita.com/seigot/items/7d424000c8d35e5146e4)
[PythonでOCRを実行する方法](https://gammasoft.jp/blog/ocr-by-python/#sample-image)
SageMakerでOptunaをinstallできない

# はじめに
SageMakerでOptunaをinstallしようとしたらつまづいた話。
1時間くらいかけて解消できたので備忘メモとして残しておきます。

# 環境
- AWS SageMaker
- env: tensorflow_p36

# やりたかったこと
- optunaをpip installだか、conda installして、SageMakerでパラメータチューニングしたい。

# エラー内容
Notebook上で `!pip install optuna` を実行すると、以下のようなメッセージが表示される。
> AttributeError: module 'enum' has no attribute 'IntFlag'

# 解決方法
enum34をインストールしたら解消されました。
- Terminalで `pip uninstall enum34`
- Notebookで `!pip install optuna`


# 参考記事
以下の記事が参考になりました。ありがとうございます。
https://blog.goo.ne.jp/field_light/e/1d6e42b4e9322b5f5546ca89a4e7a7a6-
Windowsでポートが開いているか確認する

サーバを構築しているときに、ポート開放の確認をする方法を調べたので、その方法を書きます。

Windows10では、Powershellを使えば通信相手のポートが開いているか確認することが出来ます。
Powershellを起動して、下記のコマンドを入力し、Enterを押します。


`Test-NetConnection -ComputerName [相手のIPアドレス] -Port [確認するポート番号]`

例：Test-NetConnection -ComputerName 192.168.1.6 -Port 10306



コマンドを実行した結果、`TcpTestSucceeded`が`True`となっていれば、ポートは開いています（＝接続可能）。
![コメント 2020-05-04 180343.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520421/9e472d74-97d5-85a6-fe97-9c462a166041.jpeg)


`TcpTestSucceeded`が`False`で、`PingSucceeded`が`True`の場合は、
PINGは通るがポートは空いていない（＝通信相手は存在するがポートは解放されていない）ということです。
![コメント 2020-05-04 180556.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520421/78c7d53f-2179-003e-f6e1-5fc4ebbd7f61.jpeg)

`PingSucceeded`が`False`の場合は、
通信相手が存在しない（IPアドレスが間違っているか、そもそも存在しない）ということです。
![コメント 2020-05-04 180724.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520421/220c36ea-7cab-bb0b-c6e3-bfbbf98226ec.jpeg)


以上です。
お役に立てれば幸いです。
CSSの書き方

### idとclass
 - id：同一のid名が、同じページ内に存在できない
    - idの場合はCSS内のセレクタは「＃」から始める
 - class:同一のclass名を、同じページ内に存在させることができる
    - classの場合はCSS内のセレクタは「.」から始める

### margin 
要素の外側の余白。

```
margin: 上下左右;
margin: 上下　左右;
margin: 上　左右　下;
margin: 上　右　下　左; 
```

### padding
要素の内側の余白。
CSVデータをPostgreSQLに一括挿入する方法

# CSVデータをPostgreSQLに一括挿入する方法

## はじめに

`Mac環境の記事ですが、Windows環境も同じ手順になります。環境依存の部分は読み替えてお試しください。`

### 目的

この記事を最後まで読むと、次のことができるようになります。

| No.  | 概要       | キーワード |
| :--- | :--------- | :--------- |
| 1    | PostgreSQL | COPY       |

### 実行環境

| 環境           | Ver.    |
| :------------- | :------ |
| macOS Catalina | 10.15.3 |
| Python         | 3.7.3   |
| PostgreSQL     | 11.5    |

### 関連する記事

- [PostgreSQL/COPY](https://www.postgresql.org/docs/current/sql-copy.html)

## CSVデータの一括挿入

### テーブル定義

```t_feedback.sh
~# \d t_feedback;
                                        Table "public.t_feedback"
   Column   |            Type             | Collation | Nullable |                Default
------------+-----------------------------+-----------+----------+----------------------------------------
 id         | integer                     |           | not null | nextval('t_feedback_id_seq'::regclass)
 service    | character varying(255)      |           | not null |
 title      | character varying(255)      |           | not null |
 detail     | character varying(255)      |           | not null |
 created_at | timestamp without time zone |           |          |
 updated_at | timestamp without time zone |           |          |
Indexes:
    "t_feedback_pkey" PRIMARY KEY, btree (id)
```

### CSVデータ

```path/data.csv
id,service,title,detail,created_at,updated_at
1,service1,title1,detail1,2020-05-04 00:00:00,2020-05-04 00:00:00
2,service2,title2,detail2,2020-05-04 00:00:00,2020-05-04 00:00:00
3,service3,title3,detail3,2020-05-04 00:00:00,2020-05-04 00:00:00
4,service4,title4,detail4,2020-05-04 00:00:00,2020-05-04 00:00:00
5,service5,title5,detail5,2020-05-04 00:00:00,2020-05-04 00:00:00
```

### COPYコマンド

```copy.sh
~# \COPY {table name} FROM {csv file} WITH CSV HEADER
```

### 一括挿入

1. postgresにログインする

2. COPYコマンドで一括挿入する

```insert.sh
~# SELECT * FROM t_feedback;
 id | service | title | detail | created_at | updated_at
----+---------+-------+--------+------------+------------
(0 rows)

~# \COPY t_feedback FROM path/data.csv WITH CSV HEADER
COPY 5

~# SELECT * FROM t_feedback;
 id | service  | title  | detail  |     created_at      |     updated_at
----+----------+--------+---------+---------------------+---------------------
  1 | service1 | title1 | detail1 | 2020-05-04 00:00:00 | 2020-05-04 00:00:00
  2 | service2 | title2 | detail2 | 2020-05-04 00:00:00 | 2020-05-04 00:00:00
  3 | service3 | title3 | detail3 | 2020-05-04 00:00:00 | 2020-05-04 00:00:00
  4 | service4 | title4 | detail4 | 2020-05-04 00:00:00 | 2020-05-04 00:00:00
  5 | service5 | title5 | detail5 | 2020-05-04 00:00:00 | 2020-05-04 00:00:00
(5 rows)
```
Google Chromeのスクロールバーを非表示にする

# やりたいこと

- Google Chromeでサイト閲覧中、右側にでてくるスクロールバーをなくしたい

[![Image from Gyazo](https://i.gyazo.com/94fb1e6d179869848e43b0e96e3de8f7.gif)](https://gyazo.com/94fb1e6d179869848e43b0e96e3de8f7)

- ここ1〜2週間くらい（2020/5/4現在）どのサイトでも表示されるようになったような気がする。前からそうだったっけ…？（そうだったのかもしれない）
- 以前は`chrome://flags`から非表示にする方法もあったみたい（[Chromeでスクロールバーを拡張機能なしで自動非表示にする方法](https://xn--qck4bi9b5gsd.com/2122)）だが、現在ではこのオプションがみつからない

# 方針

- 別の記事では専用のChrome拡張機能をインストールしている方もいるよう
- 誰か（もちろん自分でも可能）がつくったUserCssをどのサイトにも適用できるChrome拡張機能[Stylus](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne)を普段から使っているので、今回はこれを使って解決する
- Stylusの使い方は[ブラウザー拡張機能 Stylus で GitHub Markdown を見やすくする](https://qiita.com/peaceiris/items/31dd73d24b486799e7a4)など参照

# 方法

- Stylusの管理ページ（拡張機能インストール後、アイコン右クリック→`Open Stylus Manager`）で`Write new style`からスタイルの新規作成

[![Image from Gyazo](https://i.gyazo.com/e3bd04d2851ab8f03adad5c6ba550b0a.png)](https://gyazo.com/e3bd04d2851ab8f03adad5c6ba550b0a)

- 今回は特定のドメイン配下でなく全てに適用させたいので、デフォルトで書き込まれている`@-moz-document domain("example.com") {`以下を削除し、以下を記入

```css
::-webkit-scrollbar {
    display: none;
}
```

[![Image from Gyazo](https://i.gyazo.com/c7e13fef172fa9e391279b3ecd493bd0.png)](https://gyazo.com/c7e13fef172fa9e391279b3ecd493bd0)

- これで任意のサイトを開けばスクロールバーが消えるはず！

[![Image from Gyazo](https://i.gyazo.com/0260ffd488ef43c1fda154c576a7e35b.png)](https://gyazo.com/0260ffd488ef43c1fda154c576a7e35b)

おわり
How to install pgbadger on windows

# Dwonload strawberry perl
http://strawberryperl.com/
# Download pgbadger
https://github.com/darold/pgbadger
# How to install pgbadger on windows
https://github.com/darold/pgbadger/issues/480
# How to analyze from postgresql.log
You can get out.html from following command
$ pgbadger.bat postgresql.log
UITextFieldのReturnKey一覧

UITextFieldの右下の部分の文字を変える時の一覧です。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255216/bfd2d842-47c4-991b-1dbd-ef16a0ab817e.png)

UITextField下の画像の部分を変えると変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255216/04719566-3a2a-801c-ecfb-45475d9093cf.png)

| Default | 改行 |
| ---- | ---- |
|  Go  | 開く |
| Google | 検索  |
| Join | 接続 |
| Next | 次へ |
| Route | 経路 |
| Search | 検索 |
| Send | 送信 |
| Yahoo | 検索 |
| Done | 完了 |
| Emergency Call | 緊急電話 |
| Continue | 続ける |
社会人エンジニアがプログラミングコンテストに参加してみたい#1

#始める理由
今の社会情勢により、自宅にいてとても暇です。
その中でゲーム感覚でできる勉強はないかとプログラムコンテストを始めることにしました。

#どんなサイトがあるか
[AtCoder株式会社](https://atcoder.jp/company?lang=ja)が運営しているプログラムコンテストがおすすめです。
全て日本語で説明されています。

#一体何を学ぶのか
基本情報技術者や応用情報技術者などの資格勉強がより有益ではないかと思われます。
しかし、基本情報は今回中止になりました。半年後は必ず開催されるなど保証はありません。
基本情報だけの勉強で人生を終わらせるわけにはいきません。
必要なのはアルゴリズムと数学です。

#それ業務で役にたつの？
データベースの検索など最適化が求められる部分。
グラフィック、データ解析、機械学習など数学とプログラムの両方を求められる現場では役に立ちます。
つまり高給な仕事です。

#高給な仕事に求められる物
学位。
数学、プログラム技術を証明できる物。

#つまり何が必要か
高卒、専門卒、短大卒は学位が必要になります。
通信大学でもいいので大学を卒業し応用数学の知識と情報系の知識を証明する必要があります。
そしてアルゴリズムとプログラムを勉強したと証明する物がプログラムコンテストの参加履歴と結果です。

#始める理由にはタイミングしか記載されてないけど動機は？
私は情報系の専門卒です。
主に組み込み系のエンジニアとして働いてきました。
難しいシステム部分は高学歴の方が実装されるので、私はユーザーに近いロジック部分の制作です。
変な言い方をすると誰でもできます。
いつか若い子に切替られ、リストラされるのではないかという危機感です。

#私がこれからやること
放送大学の学費が安いので勉強の為に入学してみようと思います。
あと数学の勉強をしてみようと思います。

#欲しい物
安定と金

#次回
コードを書く環境とかプログラムを書きます。
LaravelでRefreshDatabaseを使えない場合はどうするべきか

`RefreshDatabase` はマイグレーションを使う場合にしか使えません。そういうときは `DatabaseTransactions` を使うといいよというお話です。

なお、古くからの Laravel 遣いには、目新しさが微塵も無い記事だと思うので、スルーしていただければと思います。

# 前提
- Laravel 6.8.10

# RefreshDatabaseもいいけど...

Laravel で DB に関するテストをする際は `RefreshDatabase` を使うのがテッパンだと思います（ [ドキュメント](https://readouble.com/laravel/6.x/ja/database-testing.html#resetting-the-database-after-each-test) ）。

しかし、 `RefreshDatabase` はテストが終わったらマイグレーションを再度実行するというものなので、 **マイグレーションを使わない場合** （例えば、既存 DB を使う場合）には適していません。[^1]

[^1]: そりゃ、私だって、あんな **メチャクチャな** テーブル定義の DB を使いたくはないですよ。どうせ、Laravel で作るなら、心機一転、全部作り直したい。でも、 **大人の事情** という例のアレのせいで、そうできないんですよ！（溜息）

# そこでDatabaseTransactionsを使おう

`Illuminate\Foundation\Testing\DatabaseTransactions` は、 **テストを実行しているあいだだけ有効なトランザクション** を作ってくれるトレイトです。具体的には、 `setUp()` したタイミングでトランザクションを作成し、 `tearDown()` したタイミングでロールバックします。[^2]

[^2]: `Illuminate\Foundation\Testing\TestCase` の `setUpTraits()` で `DatabaseTransactions` クラスを使っている場合は、その `beginDatabaseTransaction()` をコールしています。 `beginDatabaseTransaction()` では、プロパティ `$beforeApplicationDestroyedCallbacks` にロールバックと DB 接続を切断する関数を追加しています。ここで追加された関数が `tearDown()` でコールされます。

実は、Laravel **5.4** の [ドキュメント](https://readouble.com/laravel/5.4/ja/database-testing.html#using-transactions) には記載があるのですが、 **5.5** で `RefreshDatabase` が追加されたからか、ドキュメントからは削除されてしまったようです。

1つ注意しないといけないのは、 `DatabaseTransactions` は、何も設定しなければ、デフォルトの DB 接続 [^3] に対してトランザクションを作るということです。

[^3]: `config/database.php` の `default` の設定値を参照します。 `.env` で `DB_CONNECTION` が設定されていれば、それが優先されます。設定されていなければ、 `'mysql'` が使われます。

もし、デフォルト以外の DB 接続に対してトランザクションを作りたい場合は、テストクラスにプロパティ `$connectionsToTransact` を作り、 `config/database.php` に設定した DB 接続名を指定することができます。

```php:Tests\Unit\SampleServiceTest
namespace Tests\Unit;

use Tests\TestCase;
use App\Http\Services\SampleService;
use Illuminate\Support\Facades\DB;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class SampleServiceTest extends TestCase
{
    // テスト実行中のみ有効なトランザクションを設定する。
    use DatabaseTransactions;

    // トランザクションを設定する DB 接続名を指定する。
    private $connectionsToTransact = [ 'mysql_slave' ];

    public function setUp(): void
    {
        parent::setUp();

        // トランザクションを設定した DB に対して、テストデータを INSERT する。
        DB::connection('mysql_slave')->table('d_products')
            ->insert([
                [
                    'name' => 'りんご',
                ],
                [
                    'name' => 'オレンジ',
                ],
        ]);
    }

    /**
     * @test
     */
    public function 製品一覧を取得できること()
    {
        $service = new SampleService();
        $result = $service->fetchProducts();

        $expected = [
            (object)['name' => 'りんご'],
            (object)['name' => 'オレンジ'],
        ];

        $this->assertEquals($expected, $result);
    }
}
```

# 注意点

[Laravel 5.4 で手軽にテストを書こう！](https://www.infiniteloop.co.jp/blog/2017/05/laravel-5-testing/) や [laravelでDBテストコードを書く前の設定すべきこと](https://qiita.com/kuriya/items/4c9dbefc19514f415374) で指摘されているように、 `AUTO_INCREMENT` の設定値は変わってしまいます。

# 終わりに

`RefreshDatabase` しか無いのか... と軽く絶望していたときに、 `DatabaseTransactions` を見つけたときは、本当に嬉しかったです。はい。
PyODE 使ってみる



バネダンパ系の計算をする必要があり PyODE を試します。
似たようなものとしてPybulletというのもあるそうですね。
(他にかわりになる選択肢があれば教えてほしい)


筆者は5年ほど前（2015年頃）にC/C++版のODEを動かしたことがあります。が
......ほとんどなにも思い出せない。
今は Python 普段使いしてるので PyODE を使ってみます。
大元の公式サイト
ODE　http://www.ode.org/
マニュアル　http://ode.org/wiki/index.php/Manual
参考になるdemura.net様Webページ　https://demura.net/ode_faq#b8
PyODE　https://pyode.sourceforge.net/
PyODE API　https://pyode.sourceforge.net/api-1.2.0/index.html

## 1 PyODE インストール
### 1.1 環境など
作業時期：2020年4月
・Windows10
・Python3.8.0　64bit版

↓ ここを参考に進めた。
https://algorithm.joho.info/programming/python/pyode-install/

######備考
sourceforge にWindowsインストーラがあるんだけど、Python2（2.5か2.6）でなきゃならんのと2010年版ということで　選択肢から除外。（一応リンク→　http://pyode.sourceforge.net/#download　）
「インストーラ使う必要なし」が結論です。



### 1.2 ダウンロード
[前述の参考サイト](https://algorithm.joho.info/programming/python/pyode-install/)に従って whl ファイルを入手
ファイル名：ode-0.15.2-cp38-cp38-win_amd64.whl

### 1.3 インストール
whlの保存先にてPowerShellを開く。（「『Shift』＋右クリック」とかで）
pip コマンドでインストール：

```:pipによるインストール
C:\Python380\python.exe -m pip install .\ode-0.15.2-cp38-cp38-win_amd64.whl
```

（「-m」オプションでpipを呼ぶことにしている）


結果：　「Successfully installed ode-0.15.2」
特に苦労しませんでした。

## 2 可視化ツールについて
PyODEには可視化機能はついてない。
（C++のODEはどうだったっけ？　たしか、OpenGLっぽい描画が標準で使えたような気がする）

PyODEと組み合わされる可視化パッケージには
・VPython
・Pygame
・PyOpenGL
・PyOgre
の4つの候補がある。（有名どころではね）
過去の定番だったのは「VPython」のようです。
筆者は当初この「VPython」を試しましたが問題があって
結局「Pygame」に移行しました

#### 2.1 About VPython
最新の「バージョン7」をインストールして動かしてみたところ
・バージョン「5」から「6」に変わるときに大きな変更があったうえ、さらに「6」→「7」でも結構変わったらしく、
現行バージョンで使えるサンプルや記事が少ない。
・現行バージョンは「WebGL」らしくWebブラウザ上に出力される

ということが判明。
どうにも扱いづらかったので
筆者は「VPython」を使うのはいったん諦めて「Pygame」に移りました。

### 2.2 pygame
当面これを使うつもりです。
PyOpenGLやPyOgreにくらべて、記述量は少なく済むと見ています。
pipで最新版がインストールできました。

### 2.3 PyOpenGL
インストールはひと手間かかりました。（pipから取得は駄目でした→[チュートリアル3](https://qiita.com/emuai/items/840c776f146ac12ac416)参照）
VPythonやPygameより記述量は多い。

### 2.4 PyOgre
まだ試してない。
PyOgreの中にODEが組み込まれているような話もちらほら。

##3 チュートリアル

本家PyODEサイトに3つのチュートリアルがあります。
手前で実施しました記事もご覧ください。

・[PyODE チュートリアル 1](https://qiita.com/emuai/items/75df831c16dbe660df68)
概要：「物体の落下」（地面なし）
※本家チュートにグラフ描画を追加しました。

・[PyODE チュートリアル 2](https://qiita.com/emuai/items/63be99c31db4aa9dfbb2)
概要：「ジョイント　と　pygame による2D描画」
※本家チュートにGIF出力など追加

・[PyODEチュートリアル3](https://qiita.com/emuai/items/840c776f146ac12ac416)
概要：「落下して積み重なる多数のオブジェクトとPyOpenGLによる3D描画」地面あり、接触あり
※画像/GIF動画出力を追加しました。
こんなご時世なのでdebian(openmediavault)でFolding@homeに参加してみた

# Folding@home
Folding@home（FAH、フォールディング・アット・ホーム[4]）は、分子動力学シミュレーションによりタンパク質のフォールディングを解析するための、ボランティア・分散コンピューティングプロジェクト。
(wikipediaより)


いわゆる分散コンピューティングですね。
NASとして使っているOpenmediavault(富士通機)のリソースが割と余ってるので、これを使ってみる。
（他のOSはインストーラがあるのでそれを使えばOK）

## インストール
公式からdebパッケージをwgetとかで持ってくる。
https://foldingathome.org/alternative-downloads/

`sudo dpkg -i fahclient_7.6.9_amd64.deb`
webviewerも入れとこうと思ったので
`sudo dpkg -i fahviewer_7.6.9_amd64.deb`

でインストール。
依存関係のエラーがでるかもしれないので、上記`dpkg`実行後に
`sudo apt install -f` (fは--fix-brokenオプション)
で依存関係をインストールしてくれる。（確か別の方法で一発で入れれた気がする）

`fahclient`のインストールでいくつか質問されるのでそれは自分の環境に応じて適当な回答を。


## webview
GUIがない環境だとWebから見るくらいしかないので、Webから見れるように設定を変更
設定ファイルは`/etc/fahclient/config.xml`にある。

```xml
<config>
  <!-- Client Control -->
  <fold-anon v='true'/>

  <!-- Folding Slot Configuration -->
  <gpu v='false'/>

  <!-- HTTP Server -->
  <allow v='192.168.1.0/24'/> <!-- ←追加　CIDR表記でもOK -->

  <!-- Web Server -->
  <web-allow v='192.168.1.0/24'/> <!-- ←追加　CIDR表記でもOK -->

  <!-- Folding Slots -->
  <slot id='0' type='CPU'/>
</config>
```

これで同じネットワーク内から`[ip or host]:7396`をブラウザで叩けば見れる。
（他のディストリとかだとFirewallのこともあるので注意）

*早く収束してほしい…*
【Python】集合型（セット）について図でわかりやすくまとめてみた

#この記事を書いた理由

AI人材目指して`Python`を勉強しているのですが、集合型の内容がもろ数Aの集合の内容だったので今後使うことが多いのかなと思ったので、まとめます。

Pythonの勉強はこちらを活用して進めてます。
[Python入門者のための学習ロードマップ【ブログでも独学可能】](https://obgynai.com/python-roadmap/)

[現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/)

[Python, set型で集合演算（和集合、積集合や部分集合の判定など）](https://note.nkmk.me/python-set/)



#集合型（セット）とは

- 中にある要素が重複せず、順番がなく番号が定義されていない要素の塊
- シーケンス型（文字列、タプル、リスト）の親戚みたいな感じ
- { }の中にコンマで区切って定義
- set( )関数でデータタイプを集合型（setタイプ）に変えて定義

#図示してみた
２つの集合型aとbがあったとする。

- aとbで共通している集合（積集合）：`a & b`
- aから「aとbで共通している要素（積集合）」を除いた集合（差集合）：`a - b`
- bから「aとbで共通している要素（積集合）」を除いた集合（差集合）：`b - a`

は以下の図のイメージ。
![IMG_1621.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/e6a7acca-b221-27c0-291c-c919fe8d9e9b.jpeg)

- aとbの要素を全て合わせた集合（和集合）：`a | b`

は以下の図のイメージ
![IMG_1622.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/264609f1-33f8-5da0-84ad-12347246d7dc.jpeg)

-「aに属してbに属さないもの」と「bに属してaに属さないもの」を合わせた集合（対象差集合）:`a ^ b`

は以下の図のイメージ
![IMG_1623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/a9871013-c2d1-099e-3d88-bf8dcbb087d2.jpeg)

#集合体の演算方法

先ほど図示したものを実際にコードで表現してみる。

```python:set.py
# 集合型aとbを定義
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
b = {2, 4, 6, 8, 10, 12} 

# 積集合
print(a & b)  #実行結果：{2, 4, 6, 8, 10}

# 差集合
print(a - b)  #実行結果：{1, 3, 5, 7, 9}
print(b - a)  #実行結果：{12}

# 和集合
print(a | b)  #実行結果：{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12}

# 対象差集合
print(a ^ b) #実行結果：{1, 3, 5, 7, 9, 12}
```

ちなみに集合型の演算にはメソッドも使える。

```python:set.py
# 集合型aとbを定義
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
b = {2, 4, 6, 8, 10, 12} 

# 積集合
print(a & b)  #実行結果：{2, 4, 6, 8, 10}
print(a.intersection(b))  #実行結果：{2, 4, 6, 8, 10}

# 差集合
print(a - b)  #実行結果：{1, 3, 5, 7, 9}
print(a.difference(b))  #実行結果：{1, 3, 5, 7, 9}

print(b - a)  #実行結果：{12}
print(b.difference(a))  #実行結果：{12}

# 和集合
print(a | b)  #実行結果：{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12}
print(a.union(b)) #実行結果：{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12}

# 対象差集合
print(a ^ b) #実行結果：{1, 3, 5, 7, 9, 12}
print(a.symmetric_difference(b)) #実行結果：{1, 3, 5, 7, 9, 12} 
```

#おわりに

部分集合に関してはまた別の記事にでもまとめてみようかなと。
やはり何かしらアウトプットした方が頭の中が整理できるのでオススメ。

Python、楽しい！
[Python]知ったばかりのzipfileで解凍ツールを作ろうとしたら、知ったかぶりのsys.exit()でハマった

# はじめに
Pythonに、zipfileモジュールがあることを知って、
（zip解凍のフリーソフトやWindows標準のzip解凍機能を知りつつ、あえて）
以下の仕様で、簡易の解凍ツールを作ってみることにしました。

- zipファイルを、DOSバッチにドロップしたら、解凍を実行
  - WindowsのPythonは、スクリプト（*.py）に直接ドロップできない
- 出力先フォルダパスは、zipファイルのフルパスから拡張子を取ったもの
  - 入力：`[任意フォルダ]\[任意名称].zip`
  - 出力：`[任意フォルダ]\[任意名称]`
- 解凍処理が正常終了したら、DOS窓はすぐ閉じる
- 解凍処理が異常終了したら、DOS窓は終了コードを表示して入力待ち

そうしたら、C#の`Application.exit()`のつもりでコールした
`sys.exit()`で数分間ハマったので、メモします。

# 完成形
とりあえず、先に完成形を示しておきます。
Pythonはインストール済、かつ、Pathが通っている前提です。
各スクリプトのファイル名は決め打ちにしてますが、DOSバッチ内の記述と整合していれば、何でもよいです。

``` bat:extract.bat
@echo off
cd /d "%~dp0"

:: 本バッチと同じ階層に「extract.py」がある前提
python extract.py -i "%~1"

if errorlevel 1 (
	echo.解凍に失敗しました。
	echo.ExitCode:%errorlevel%
	pause
)
```
``` py:extract.py
from argparse import ArgumentParser
import os
import sys
import zipfile

def main():
	parser = ArgumentParser()
	parser.add_argument("-i", "--input", default=False, help="Input Zip")
	args = parser.parse_args()
	filePath = args.input
	
	if (not filePath):
		sys.exit(1)
	if (not os.path.isfile(filePath)):
		sys.exit(2)
	
	folderName = os.path.splitext(os.path.basename(filePath))[0]
	outputPath = os.path.join(os.path.dirname(filePath), folderName)
	
	try:
		with zipfile.ZipFile(filePath) as zip:
			zip.extractall(outputPath)
	except:
		sys.exit(3)
	else:
		sys.exit(0)

if (__name__ == "__main__"):
	main()
```

# ハマったこと
先に言ってしまうと、以下を知らないまま、ハマり続けました。
- [【Python】sys.exit()は例外を投げているだけ](https://hira98.hatenablog.com/entry/2019/07/02/210000)

どうハマったかは、コードを見たほうが早いですね。

## ハマったこと：その１
正常終了時でも、終了コードが３になりました。。。

``` py
		try:
			with zipfile.ZipFile(filePath) as zip:
				zip.extractall(outputPath)
			sys.exit(0)
		except:
			sys.exit(3)
```

## ハマったこと：その２
異常終了時でも、終了コードが０になりました。。。

``` py
		try:
			with zipfile.ZipFile(filePath) as zip:
				zip.extractall(outputPath)
		except:
			sys.exit(3)
		finally:
			sys.exit(0)
```

# 終わりに
ハマったおかげで、Pythonのtry-except-else-finallyの動きは、よく分かりました。
Rails  data-confirmを使ってlink_toやform_tagでアラート表示させる方法

####結論

link_toやform_tag と data: { confirm: "表示させたい文言" } で
簡単にアラート表示を作ることができます。

---
例1

```
= link_to "アカウント削除", user_registration_path, method: :delete, data: { confirm: "【確認】アカウントを削除してもよろしいですか？" }
```


アカウント削除ボタンをクリックすると、下図のように画面上部にアラート表示されます。
<img width="1098" alt="aade35cc41ead1b8b58adf58a20f3725.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600614/7689cd45-564f-7ad3-4587-6dee760cdbc3.png">

---
例2

```
= form_tag(delete_credit_cards_path, method: :post, data: { confirm: "【確認】クレジットカード情報を削除してよろしいですか？\n（削除後も再登録可能です）" }, id: 'charge-form',  name: "inputForm") do
```

削除するボタンをクリックすると、下図のように画面上部にアラート表示されます。

"【確認】クレジットカード情報を削除してよろしいですか？\n（削除後も再登録可能です）"
というように、\nを挿入することで改行させることもできます。
※改行を有効にするためにはダブルクオーテーションにした方が良いようです。

<img width="1065" alt="3c0d25f3c6818f14057d11018a5df21b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600614/07583968-0d4a-b482-666d-98218a6d833b.png">

####補足
Bootstrapとgem 'data-confirm-modal'を利用して、アラートをお洒落にするやり方もあるみたいです。

####参考にさせていただいた記事
https://satoh-d.hatenablog.com/entry/2017/01/21/110000
https://fuchiaz.com/rails-gem-data-confirm-modal/
WindowsのServer CoreにVMware Horizon 7のView Composerをインストールする

#概要
・WindowsのServer CoreにVMware Horizon 7のVIew Composerをインストールする。
・最低限の設定のみ実施。
・サービスが起動したところのみ確認

#環境

|種別 |ソフトウェア|
|---- |-----------|
|ハイパーバイザ |Hyper-V(Windows 10 1903)|
|OS|Window Server 2016|
|Database|MS SQL Server 2017 Express<br>※データベースエンジンのみ|
|アプリケーション|View Composer 7.12|

#事前準備

・MS SQL Server 2017 Expressのダウンロード
https://www.microsoft.com/ja-jp/download/details.aspx?id=55994

・ODBCはVMwareがサポートしている「SQL Server Native Client 11.0」を使用
　※その他ODBC Driverだとインストール出来ない。

・VMware HorizonのView Composerは評価版をダウンロード

#手順

## MS SQL Server 2017 Expressの構築


・MS SQL Server 2017 Expressのインストール

~~~
cd <インストールバイナリの配置先>
※インストールバイナリの展開は割愛します。

SETUP.EXE /QS /IACCEPTSQLSERVERLICENSETERMS /ACTION="install" /FEATURES=SQLEngine,Tools /INSTANCENAME=SQLEXPRESS /SECURITYMODE=SQL /SAPWD=<パスワード>

shutdown -r -t 0
※インストール後に再起動しないとsqlcmdコマンドが使用できない。

~~~

・データベースの作成

~~~

sqlcmd -S localhost\SQLEXPRESS

1>create database composer;
2>go

1>exit
~~~
・ODBCの設定

~~~
C:\Windows\System32\C:\Windows\System32\odbcad32.exe

ODBCデータソースアドミニストレータ(64ビット)画面が出力されるので、必要な設定をする。

　(1)[システムDNS]タブをクリックする。
　(2)[追加]ボタンをクリックする。
　(3)SQL Server Native Client 11.0を選択して[完了]ボタンをクリックする。
　(4)[名前]にcomposerを入力する。
  (5)[サーバー]にlocalhost\SQLEXPRESSを入力して[次へ]ボタンをクリックする。
　(6)[統合Windows認証を使う]にチェックが入っていることを確認して[次へ]ボタンをクリックする。
　(7)[規定のデータベースを以下に変更する]にチェックをクリックする。
　(8)プルダウンから[composer]を選択して[次へ]ボタンをクリックする。
　(9)[完了]ボタンをクリックする。
　(10)[データーソースのテスト]ボタンをクリックする。
　(11)[テストは無事に完了しました。]が表示されていることを確認し、[OK]ボタンをクリックする。
  (12)[OK]ボタンをクリックする。
  (13)画面を閉じる。
~~~

## View Composerの構築

~~~
cd <インストールバイナリの配置先>
※インストールバイナリの展開は割愛します。

VMware-viewcomposer-7.12.0-15747753.exe /s /v”/qn DB_DSN=composer DB_USERNAME=<SQLのユーザ> DB_PASSWORD="<パスワード>""

~~~

#その他

ODBCデータソースを設定する際に「odbcconf」コマンドはデスクトップエクスペリエンスに使用できましたが、Server Coreではエラーが出力されたので、使用することを諦めました。

odbcconfコマンド使用例：
odbcconf /A {CONFIGSYSDSN "SQL Server Native Client 11.0" "DSN=composer|DATABASE=composer|SERVER=localhost\MSSQLEXPRESS|Trusted_Connection=yes"}
【Swift5】TableViewのCustomCellの高さを可変にする

# カスタムセルで高さを可変にする時につまづいた

## いろいろ解決方法を試した
・AutoLayoutの設定もした。
・`tableView.estimatedRowHeight`と`tableView.rowHeight = UITableView.automaticDimension`の設定もした。
・以下の記述も試した。

```ViewController.swift
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        tableView.estimatedRowHeight
        return UITableView.automaticDimension
}
```

でもうまくいかない・・。

## 原因

カスタムセルの可変にしたい文字をTextViewを使っていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/109f9956-c995-3877-5aed-f51a01ebd688.png)

TextView → Labelに変更and LabelのLinesを0に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/f661e2a2-989a-a53b-17ca-84a4f2d0bfb2.png)

TextViewだと自動計算が走らないため、うまくいかなかった様子。
Labelに変えてLinesを0(複数行表示するため)すれば無事表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/aeec9152-a4f1-b079-659c-27dc3f3e1625.png)


## 反省

基本的に文字を複数行表示する時はLabelではなく、日常的にTextViewを使うようにしてしまっていので、必要な用途に合わせて使い分ける必要がありますね・・。