OmniAICreator/Qiita-1.07M huggingface dataset:
device　ユーザーcreateと同時に別のモデルもcreate

railsで新規ユーザー登録をする時、同時に、サーチモデルも作成されるようにしましたので、説明します。

やり方）
deviceのcontrollerをカスタマイズする。

詳細）
まず、ルーティングを設定。
以下を追加。

```ruby:routes.rb
  devise_for :users,controllers: { registrations: "users/registrations",}
```

次はcontrollarをカスタマイズ

```ruby:registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  def new
    @user = User.new
    @search_height = SearchHeight.new
  end

  def create
    @user = User.new(configure_sign_up_params)
    if @user.save
      SearchHeight.create(min_height: 0, max_height: 200, user_id: @user.id)
      sign_in(@user)
      redirect_to new_profile_user_path(@user)
    end
  end

  protected

  def configure_sign_up_params
    params.permit(:email, :password, :password_confirmation, :sex)
  end

  def after_sign_up_path_for(resource)
    new_profile_user_path(current_user)
  end

  def after_inactive_sign_up_path_for(resource)
    new_profile_user_path(current_user)
  end
end

```
ユーザーがcreateされたら、SearchHeightもcreateされる。

ここで、ポイント！
sign_in(@user)が大事。これがないとsessionが付かないので、ログインしたことにならない。

そして、viewの設定

```ruby:new.html.slim
  = form_tag @user, url: user_registration_path do
    = devise_error_messages!
    .devise-registration__textarea
      = select_tag :sex, options_for_select({ "男性": "男", "女性": "女"}), { prompt: "性別", class: "devise_registration_select"}
      = email_field_tag :email,"", placeholder: " メールアドレス"
      = password_field_tag :password,"", autocomplete: "off", placeholder: " パスワード(英数字4文字以上)"
      %p.devise-i (確認)
      = password_field_tag :password_confirmation,"", autocomplete: "off", placeholder: " もう一度パスワードを入力して下さい", class: "devise_registration_area_confirmation"
      = submit_tag "登録", class: 'registration__create'
```

今回は、form_tagでやった。
特に意味はない。

これで同時に作成できるはず。

以上
AWSでCloudfrontでDistributionが作れない

# Cloudfrontでdistributionが作れなかった件

最初ServerlessでWebDistributionを作ろうとして、以下のエラーが出ていた。

> Your account must be verified before you can add new CloudFront resources. 
> To verify your account, please contact AWS Support (https://console.aws.amazon.com/support/home#/) and 
> include this error message. (Service: AmazonCloudFront; Status Code: 403; 
> Error Code: AccessDenied; Request ID: 83e4013e-ac5e-4e71-b137-e01cfc46a575)

まあ403だし、よくあるIAMロールさんかなあと思い、ルートユーザーで実行しても全く変わらず、、、 :thinking: 

よく見るとAWS Supportに連絡しろって書いてあるので、連絡したら１日くらい経ってこんな返信が来た。
アカウントに制限がかかっていてCloudfrontのDistribution作成ができなくなっていた模様。

> お知らせいただいたCloudFront resourcesに関するエラーは、アカウントの制限により発生しているものと思われるため、
> 該当の制限を解除するよう担当部署へ依頼をいたしました。

でなぜアカウントの制限が起こっていたのか聞いたところ、こんな回答。

> アカウントの制限についてご心配をおかけし、申し訳ございません。
> AWSではアカウントのご利用実績などに基づいて、機能や上限値などを制限させていただくことがございます。
> 詳細な内容についてはお伝えすることができないのですが、何卒ご理解をいただけますと幸いでございます。

はあ、とりあえず１日ハマってたよね。 
ググってもそんなに情報なかったのでレアなケースな気もする :thinking:
wgetコマンドでsegmentation fault (core dumped)が出たときの対処法（続きからダウンロード再開）

#wgetコマンドでsegmentation fault (core dumped)
BAMファイル（今回は12GBほど）をダウンロードしようとしたらエラー。
進捗は99%止まり。

```
wget https://www.encodeproject.org/files/ENCFF898DZV/@@download/ENCFF898DZV.bam

HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 13039955683 (12G) [binary/octet-stream]
`ENCFF898DZV.bam' に保存中

ENCFF898DZV.bam     99%[============> ]  12.14G  13.6MB/s    残り1s 
[1]    27853 segmentation fault (core dumped)  wget 
```

##解決法
--continue　オプションで続きからダウンロード再開。
wget 強制終了したときなどにも使える便利オプション


```
wget --continue https://www.encodeproject.org/files/ENCFF898DZV/@@download/ENCFF898DZV.bam

HTTP による接続要求を送信しました、応答を待っています... 416 Requested Range Not Satisfiable

    このファイルは既に全部取得しおわっています。何もすることはありません。
```

なんやねん。
416 Requested Range Not Satisfiableはリソースのサイズを超えるデータを要求したときのエラー。
参照：https://liginc.co.jp/web/programming/164003
原因は不明。

以上。
【Vagrant+VirtualBox】CentOS8のLAMP開発環境を構築

#概要
VagrantとVirtualBoxがインストールされていること前提で構築方法を記述する。なおローカルで使用するためセキュリティは考慮しない。

#環境
MACOS Mojave 10.14.5（18F132）
Vagrant 2.2.7
VirtualBox 6.0.16 r135674 (Qt5.6.3)

#Vagrantfileの作成
ターミナルより作成ディレクトリに移動した後、下記を実行するとVagrantfileが作成される。
基本的には、必要な設定を追記していく。

```command:command
vagrant init bento/centos-8
```
###記述方法
```command:Vagrantfile
Vagrant.configure("2") do |config|

　# Vagrant設定この中に記述していく

  config.vm.provision "shell", inline: <<-SHELL
　  # SHELL設定この中に記述していく
  SHELL

end
```

#Vagrantfileの編集
ここで行うことは下記の通り。

- ネットワークの設定
- 仮想端末のスペック設定
- モジュール設定（SHELL）
 - apache、php、mysql
- サービス起動（SHELL）

###ネットワークの設定
```command:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.network "private_network", ip: "10.10.10.74"
end
```

###仮想端末のスペック設定
```command:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.provider :VirtualBox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "3072"]
    vb.customize ["modifyvm", :id, "--cpus", "3"]
  end
end
```
###モジュール設定（SHELL）
####基本設定
```command:Vagrantfile
config.vm.provision "shell", inline: <<-SHELL
    # リポジトリ登録
    dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
    dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

    # OSアップデート
    dnf -y update kernel
    dnf -y install kernel-devel kernel-headers dkms gcc gcc-c++
    dnf -y update
SHELL
```

####apache2.4
```command:Vagrantfile
config.vm.provision "shell", inline: <<-SHELL
  dnf -y install httpd
  cat >> /etc/httpd/conf/httpd.conf << "EOF"
<Directory "/var/www/html">
  AllowOverride All
  Require all granted
</Directory>
EOF
SHELL
```

####PHP7.4
```command:Vagrantfile
config.vm.provision "shell", inline: <<-SHELL
  dnf module install -y php:remi-7.4
  dnf install -y php-mbstring
  dnf install -y php-mcrypt
  dnf install -y php-mysqlnd
  dnf install -y php-xmlrpc
  dnf install -y php-pear
  dnf install -y php-gd
  dnf install -y php-pdo
  dnf install -y php-intl
  dnf install -y php-mysql

  cat >> /etc/php.ini << "EOF"
date.timezone = Asia/Tokyo
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = pass
mbstring.encoding_translation = On
mbstring.detect_order = UTF-8,EUC-JP,SJIS,JIS,ASCII
mbstring.substitute_character = none
sendmail_path = /usr/local/sbin/ssmtp -t -i
upload_max_filesize = 128M
post_max_size = 128M
EOF
SHELL
```

####MySQL8
```command:Vagrantfile
config.vm.provision "shell", inline: <<-SHELL
  dnf -y module install mysql

  cat >> /etc/my.cnf << "EOF"
[client]
default-character-set = utf8
[mysql]
default-character-set = utf8
[mysqldump]
default-character-set = utf8
EOF
SHELL
```

###サービス起動
```command:Vagrantfile
config.vm.provision "shell", inline: <<-SHELL
  systemctl start php-fpm
  systemctl start mysqld.service
  systemctl start httpd.service
     
  systemctl enable php-fpm
  systemctl enable mysqld.service
  systemctl enable httpd.service
EOF
SHELL
```

#確認
ブラウザで10.10.10.74にアクセスする。
[macOS][Cocoa]モーダルシートの表示

# MacOSでモーダルシートの表示方法

## 画面

![panel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37947/f543017b-d3d4-961b-3c29-5139811fa33b.gif)

## ソース

ViewController

```swift
import Cocoa

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func openClick(_ sender: Any) {
        let sheetViewController = self.storyboard!.instantiateController(withIdentifier: "SheetViewController") as! SheetViewController
        self.presentAsSheet(sheetViewController)
    }
    
}
```

SheetViewController

```swift
import Cocoa

class SheetViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // 表示されたシートのサイズを固定にする場合
        // self.preferredContentSize = NSSize(width: 300, height: 400)
    }
    
    deinit {
        print("deinit")
    }
    
    @IBAction func closeClick(_ sender: Any) {
        self.presentingViewController?.dismiss(self)

        // こっちだと何故か deinit されず。。。
        // 呼び出し元のViewControllerでdismissしないと駄目ってことかな。。。
        // self.dismiss(self)

        // これはOK。理由は後で調べようかな。。。
        // self.dismiss(nil)
    }
    
}
```

## deinit について補足

モーダルウィンドウを非表示にするには、self（表示側のビューコントローラー）でdismissViewController（_ :)メソッドを呼び出さないといけないようです。
nilにするとOKなのは不明だけど、その場合は恐らくiOSと同じで、VCを指定していないから表示側の親ビューコントローラに処理を移譲していると思われるかな。

https://developer.apple.com/documentation/appkit/nsviewcontroller/1434489-presentassheet
> To dismiss the sheet, call the dismiss(_:) method on self (the presenting view controller).

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss

> The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.


iOSの方の説明なのでmacOSの場合はそうなのかは不明ですが、
公式ドキュメントには原則として呼び出した ViewControlelr が消すべきと書いてあるので
デリゲートかクロージャを使ってdismissを呼び出し元で実行するほうがいいかも。
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/PresentingaViewController.html
テストにおいて特定のリンクをクリックする方法

#テストにおいて特定のリンクをクリックする


![スクリーンショット 2020-01-16 16.14.02.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550443/30d7a16d-e00a-0d66-9184-6cf740fd8072.jpeg)


##前提条件
taskアプリを作成してある。(scaffoldでもOK)
gem 'capybara', '>= 2.15'
gem 'rspec-rails'
インストール済

###上記画像の黒丸に囲まれた(詳細を確認する)をクリックする

```task_spec.rb
#省略
visit tasks_path
tds = page.all('td')
tds[24].click
#省略

```
2019-09EclipseのClean起動

# 2019-09Eclipseのclean起動(Mac）
最新版の前のeclipseとパスが違ったのでメモとして残しときます。
`/Applications/Eclipse_2019-09.app/Contents/MacOS/eclipse -clean`

大体**Eclipse_2019-09.app**この部分の名前が変わるのでこの部分を自分がダウンロードしているeclipseのバージョンにすればclean起動できると思います。

デフォルトとは違う場所に保存してる人はeclipseを右クリックしてoptionキー押せばパスをコピーが出てくるのでそれをターミナルに貼り付けて探せば楽にたどり着けると思います。
🔧 refractor を使ったシンタックスハイライトで css in js がおかしい

## 環境

- `rehype-prism@0.4.0`
  - `refractor@2.10.1`

## 問題

```jsx
css`
  color: ${color}
`;
```

のような場所が、

```jsx
css`
  color: ___CSS_0___;
`
```

のようになる。

## css in js では崩れないようにする

以下を`package.json`へ追加して`refractor@2.9.x`台を使うようにする。

```json
{
  "resolutions": {
    "refractor": "2.9.x"
  }
}
```

`yarn`して反映する。
react-qr-readerを(Windowsで)使うときにはまったこと(2020年1月時点)

# Node.jsの環境を作っておく
 QRコードリーダーの作り方の記事にはnpxとかいきなり出てくるので、Node.jsの環境はあらかじめ構築しておく必要はあります。
　最近はyarnを使うと速いのでそれを使ったりする。yarn自体にもインストーラーがありますが、Chocolateyからyarnをインストールするというのもあります。

[Chocolateyを使った環境構築の時のメモ](https://qiita.com/konta220/items/95b40b4647a737cb51aa)

[Yarn を導入しよう（Windows）](https://qiita.com/kurararara/items/21c70c4adfd3bb323412)

# QRコードリーダーを作る
 作り方は↓を参照。基本的にはこれで作れます。PCからはlocalhost:3000でアクセスできます(Webカメラがついていれば)が、iPhoneと同様Androidのスマホでもhttpsでなければカメラにはアクセスできません(権限の確認もない)。

[react-qr-reader を利用したQRコードリーダーの作成](https://qiita.com/KenNagami/items/1493b498ff197f8f7689)

WindowsのReactをHTTPSで使うには

```
SET HTTPS=true&&yarn start
```

などとします。実行するディレクトリ/フォルダは上の記事で作ったqrcode-reader直下です。Windowsのファイヤーウォールの設定もいじったかも。

# はまったこと
 HTTPSで動かすと、見事に下の不具合にぶち当たりました。

[create-react-appで作ったアプリがhttpsだと動かない](https://qiita.com/uemuram/items/a8f727b780bfd115bbaf)

　現時点ではまだreact-scriptの3.3.1は出ていないので、記事に書いてある更新後のpackage.jsonに書き換えて、

```
npm install
```

で無事動作するようになりました。あとは、自分の目的に応じてApp.jsを書き換えましょう。
UbuntuでSSLを利用したWebサービスを構築する

# はじめに
Webサイトを制作しているとローカル環境にWebサービスを立ち上げて動作確認することがあると思います。今回は、MacBookにUbuntuの仮想環境を作り、SSL通信のWebサービスを構築しました。
<a href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0387">こちら</a>のサイトを参考にさせていただきました。
詳しくは分かりませんが、オレオレSSL証明書なので、Chromeではつながらなかったです。Safariで動作確認を行いました。

# 構築環境
- MacBookPro MacOS:10
- VirtualeBox 6.0
- Ubuntu 18.04
- Apache 2.4
- Chrome 79.0
- Safari 13.0

#UbuntuにApacheをインストールする
まず、Apacheがインストールされているかを確認します。httpdもしくはapache2コマンドでApacheインストール有無の確認します。

```
$ httpd -v
Server version: Apache/2.4.29 (Ubuntu)
Server built: 2019-09-16T12:58:48
```

or

```
$ apache2 -v
Server version: Apache/2.4.29 (Ubuntu)
Server built: 2019-09-16T12:58:48
```

Apacheがインストールされていない場合は、Apacheをインストールしましょう。

```
$ sudo apt-get install apache2
```

次にApacheのSSLモジュールとデフォルトのSSLのサイトを有効化し、Apacheを再起動します。

```
$ sudo a2enmod ssl
$ sudo a2ensite default-ssl
$ sudo service apache2 restart
```

Apacheが443番ポートの待ち受け状態かどうかを確認します。

```
$ ss -lnt
State      Recv-Q    Send-Q        Local Address:Port          Peer Address:Port
LISTEN     0         128                       :::80                      :::*
LISTEN     0         128                      :::443                      :::*
```
SSLで通信を行うには、SSL証明書をサーバーにインストールしなければなりません。Ubuntuの場合、Apache2をインストールした時にSSL証明書が自動的に作成されて利用可能にな利ます。なんて便利で簡単なんだ！

# 動作確認
Webブラウザーからhttps://（サーバーのIPアドレス）にアクセスします。
最新のChromeではOCSPが無効のようで接続できませんでした。
<img width="825" alt="Screen Shot 2020-01-30 at 11.43.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565739/7cf3123d-4a7c-38bd-aafa-5666dc8d5324.png">

SafariでWarningを許可してあげると繋がりました。
<img width="928" alt="Screen Shot 2020-01-30 at 11.52.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565739/086fca28-04d6-5285-5851-b4550cfb022e.png">

今回はここまで。これでhttpsでしか動作しない機能（メディアデバイスなど）をローカル環境で検証できそうです。
JaveScriptでタップイベントを拾う

意外と情報がなかったので。
## ES6版
```js:tap_es6.js
element.addEventListener("touchstart", function(...args) {
    const [element, event] = args;
    let isTouchMove = false;
    element.addEventListener("touchend", (e) => {
        if (!isTouchMove) {
            /* logic */
        }
    }, {once: true})
    element.addEventListener("touchmove", (e) => {
        isTouchMove = true;
    }, {once: true})
}.bind(null, element))
```

## normal版
```js:tap.js
element.addEventListener("touchstart", function(...args) {
    const [element, event] = args;
    let isTouchMove = false;
    element.addEventListener("touchend", (e) => {
        if (!isTouchMove) {
            /* logic */
        }
    }, {once: true})
    element.addEventListener("touchmove", (e) => {
        isTouchMove = true;
    }, {once: true})
}.bind(null, element))
```

## 解説
touchendの中にタップしたときのロジックを載せてしまうと、要素を触りながら要素外へ移動して離したときもタップしたことになってしまう。
つまりユーザが一度要素を触ってしまったらキャンセル不可能になってしまう。
それを防ぐためにtouchstartを拾ったらその中でtouchendとtouchmoveを拾うようにした。
もしtouchendよりまえにtouchmoveを検知したらタップをキャンセルしたとみなして、タップされたときのロジックを実行しない。
bokeh: dictが含まれるDataFrameは、`ColumnDataSource`でプロットできなかった


# 環境
* Python 3.6.9
    * bokeh 1.4.0
    * pandas 0.25.3
* Xubuntu 18.04
* Firefox 71.0

# やりたいこと
bokehで折れ線グラフを作成したいです。

```python
import bokeh
import bokeh.plotting
import pandas

def plot_line(df: pandas.DataFrame, html_file:str):
    source = bokeh.plotting.ColumnDataSource(data=df)
    fig = bokeh.plotting.figure()
    fig.line(x="u", y="v", source=source)
    
    bokeh.plotting.reset_output()
    bokeh.plotting.output_file(html_file)
    bokeh.plotting.save(fig)


df_base= pandas.DataFrame({"u":[1,2], "v":[2,4]})
plot_line(df_base, "test_base.html")
```

上記のコードを実行すると、HTMLファイルが出力されます。HTMLファイルには以下のグラフが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37903/601e187d-e7fc-a8a8-23b3-365544c5f064.png)

# 問題
DataFrameに`dict`要素が格納された列を追加した場合、グラフは表示されませんでした。
また、ブラウザのコンソールには「TypeError: u is undefined」というエラーが出ていました。

```python
d1 = {"a":1}
df_fail1 = df_base
df_fail1["w"] = [d1, d1]
plot_line(df_fail1, "test_fail1.html")
# => fail

print(type(df_fail1["w"].iloc[0]))
# => dict
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37903/b30cf35f-a355-af82-1170-1f427721ee92.png)

```
TypeError: u is undefined bokeh-1.4.0.min.js:346:2235
    l https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:346
    decode_column_data https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:346
    initialize https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:320
    finalize https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:265
    _initialize_references_json https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:242
    o https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:242
    f https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:242
    _initialize_references_json https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:242
    from_json https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:242
    v https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:240
    embed_items https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js:240
```


# 問題が起きるパターンを調査

セルの要素の型を変更して検証したところ、以下の結果になりました。

* `List[Dict[str,int]]`  => fail
* `List[str]`  => success

要素にdictが含まれると、失敗するようです。

```python
df_fail2 = df_base
df_fail2["w"] = [[d1,d1], [d1,d1]]
print(type(df_fail1["w"].iloc[0]))
# => list
plot_line(df_fail2, "test_fail2.html")
# => fail

df_success = df_base
df_success["w"] = [["a","b"], ["a","b"]]
print(type(df_fail1["w"].iloc[0]))
# => list
plot_line(df_success, "test_success.html")
# => success
```

# 原因
よく分かりません。GitHubのIssueに挙げておきます。
https://github.com/bokeh/bokeh/issues/9620
for inとfor ofの違いを軽くまとめてみた。

## はじめに
私がJavaScriptで`foreach`を使った時に疑問に思ったことをまとめたメモです。わかりにくいところ少々ありますが、ご了承ください。

## for in
配列番号(key)でループするタイプ
`for(let key in object)`でオブジェクトの`key`または`配列番号`が`key`の中に入る。オブジェクトの中身を表示するためには`object[key]`と指定してあげる必要がある。

サンプル
https://repl.it/@mei1161/for-in

## for of
オブジェクトをそのまま入れるタイプ
`for(let val of object)`で`val`に配列の中のオブジェクトが入る。オブジェクトの中身を表示したい場合は`val`を指定してあげれば、表示できる。

サンプル
https://repl.it/@mei1161/for-of

## 最後に
変数を定義する場合は`var`より`let`を利用したほうが、予期せぬバグなどを防ぐことができるので、使ってみてください。



## 参考サイト
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...in

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...of
Azure SQL Databaseでの照合順序について

#はじめに
断片化したインデックスを自動的に再構築／再構成するためにAzure Functionsで関数を作成、アプリ側で再構築／再構成してほしくないインデックスを除外リストCSVに入れてもらい、BULK INSERTでワークテーブルに取り込み、sys.DM_DB_INDEX_PHYSICAL_STATS、sys.OBJECTS、sys.INDEXES、sys.SCHEMASとJOINすると以下のエラーが出るのを調べた結果を覚え書き

```SQL:SQLError
Cannot resolve the collation conflict between "Japanese_CS_AS_KS_WS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
```

#照合順序とは

データの文字の大小関係を比較する場合の基準となるもの
ソートや検索に関わってくる
e.g.)
「海」と「空」と「陸」はどれが一番大きい？ってのを決めるルール

#なんでエラー？
何も考えずにツルっと作成したテーブルには照合順序は設定されていない
片やsys.INDEXESやsys.OBJECTS、sys.SCHEMASには照合順序"SQL_Latin1_General_CP1_CI_AS"が設定されている
照合順序が設定されているものとされていないものをJOINの結合条件で使用すると、照合順序を指定してないものはデフォルトの照合順序に設定される
偶々一致すればエラーにならないが、件の場合は照合順序が異なるためにエラーになる

#エラー時の対応方法
* テーブル作成時に照合順序を指定する

```SQL:CreateTable
CREATE TABLE excludeList
  (SCHEMA_NAME sysname collate SQL_Latin1_General_CP1_CI_AS, 
   TABLE_NAME sysname collate SQL_Latin1_General_CP1_CI_AS, 
   INDEX_NAME sysname collate SQL_Latin1_General_CP1_CI_AS);
```
* JOIN時に照合順序を指定する

```SQL:Join
    SELECT *
    FROM SYS.DM_DB_INDEX_PHYSICAL_STATS (DB_ID(),NULL,NULL,NULL,NULL) AS A 
    LEFT OUTER JOIN  SYS.OBJECTS AS B 
      ON A.OBJECT_ID = B.OBJECT_ID 
    LEFT OUTER JOIN  SYS.INDEXES AS C 
      ON A.OBJECT_ID = C.OBJECT_ID
     AND A.INDEX_ID = C.INDEX_ID 
    LEFT OUTER JOIN  SYS.SCHEMAS AS D 
      ON B.SCHEMA_ID = D.SCHEMA_ID 
    LEFT OUTER JOIN dbo.excludeList AS E
      ON D.NAME = E.SCHEMANAME collate SQL_Latin1_General_CP1_CI_AS
     AND B.NAME = E.TABLENAME collate SQL_Latin1_General_CP1_CI_AS
     AND C.NAME = E.INDEXNAME collate SQL_Latin1_General_CP1_CI_AS
```

#最後に
あまり照合順序を意識したことがなかったが、いろいろな並び順に影響してくる部分なので今後気を付けて見ようと思う
AWS WorkSpacesでRPA環境を構築した時の落とし穴

##この記事について
大手メーカー系SIerからITベンチャーに転職したての情弱が最初にRPAでの効率化業務に挑戦し
見事に落とし穴にハマった時の話です。
半分備忘録のようなもの。

##内容
・AWS WorkSpacesでRPAぶん回し環境構築
・良さげなRPAソフトの選定
・インストール実行、しかし...
・落とし穴はここにあった
・まとめ
・おまけ

##AWS WorkSpacesでRPAぶん回し環境構築
会社から支給されたPCがMacbookだったので、これではRPAは使えない。
（現状、大抵のRPAソフトはWindows OSでしか動作しない仕様のものが多い。気がする）
なのでVDI環境を準備しようという結論になった。

お手軽なのはやはりAWS。EC2を使わなくても手軽にWindows OSを構築できるWorkSpacesというサービスがあるのです。流石です。
構築手順についてはネット上の記事を参考にすれば何も問題は無い。自分が参考にしたのはここ。
https://dev.classmethod.jp/etc/getting-started-amazon-workspaces-workdocs-settings/

標準的なWindows Server OSを構築すればそれだけでOK。
（2020年1月現時点ではWindows Server 2019）

##良さげなRPAソフトの選定
一応業務として利用するのでライセンスには気をつけないといけない。
よくある話が、組織で利用する訳じゃなく業務担当者が勝手に探して独自で使うから「個人利用」と解釈してしまうこと。
現実的にはその程度で規約違反だ何だと騒がれることは無いだろうけど、ライセンスに関しては常に正規利用を意識していないといつか痛い目を見ることになる。

んで、辿り着いたのがWorkFusion Studio。旧称はRPA Expressというらしい。
なんと此奴、RPAとしての基本的な機能だけを使用する場合は個人だろうが企業だろうが一切合切無料で使えるとのこと（フリービールのように、という表現も素敵。ビール飲みたい）
https://www.workfusion.com/products/

導入に至ってはここを参考にすれば **普通は** 大丈夫と思う。
https://sarudeki.com/robot/rpa/workfusion-rpa-express1.html

##インストール実行、しかし...
おかしい。何回インストーラを叩いてもFaral Errorを吐いてロールバックされる...
<img width="509" alt="スクリーンショット 2020-01-30 11.23.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575892/e409809d-c0f7-77d5-587a-a892989ac25d.png">
エラーログを確認すると、どうやらインストーラが引っ張ってきたmsiパッケージが入らない様子。

[17DC:14C4][2020-01-06T18:38:49]e000: Error 0x80070643: Failed to install MSI package.
[17DC:14C4][2020-01-06T18:38:49]e000: Error 0x80070643: Failed to execute MSI package.
[1524:13A8][2020-01-06T18:38:49]e000: Error 0x80070643: Failed to configure per-machine MSI package.

0x80070643エラーに関する対処法はWorkFusionのTSページにも載ってはいたが、
「セキュリティソフトに弾かれてるのかもぉ〜〜〜！」とのこと。
https://kb.workfusion.com/display/RPAe/Troubleshooting#expand-Errorcode0x80070643
WorkSpacesも構築したばかりだし、セキュリティソフトなんて入れてない。
念の為Windows Defenderを無効にしてみたが結果は変わらず。
※なおFireWallは有効でないとインストールできない仕様なので、そこは注意。

う〜む、わからん...

##落とし穴はここにあった
TSページを読み進めていくと、気になる部分を発見。
前提条件の７番目に「8200番ポートが開いている必要がある」と記載されている。
https://kb.workfusion.com/pages/viewpage.action?pageId=81396263#IntelligentAutomationCloudExpress/BusinessInstallation-Preconditions
うん...？なんかこの辺が怪しいな、と思って調べてみると、案の定だった。
どうやらWorkspacesの管理サービスがこの8200を使っているとのこと。
https://docs.aws.amazon.com/ja_jp/workspaces/latest/adminguide/workspaces-port-requirements.html
ここだ！ここでコンフリクトが起きているに違いない！！！
ということで早速調べてみると、SkyLightWorkspaceConfigServiceという奴が8200を占拠しているサービスということがわかった。
<img width="876" alt="スクリーンショット 2020-01-30 11.38.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575892/d5a147fd-fb64-204f-28cc-3dea6b2196e0.png">
と、いうワケでこいつを一時的に無効にしてやってインストーラ再起動。
ばっちりインストールできました。わっしょい！

念の為OS再起動後にサービス確認してみるが、SkyLightWorkspaceConfigService以外に8200を使っているサービスは無さそう。再起動でしっかりサービスも起動したので問題なし。

##まとめ
VDI環境でRPAを動かしたいという需要は結構ありそうだし、WorkFusion Studio以外に無料であれこれできるRPAもなかなか見つからなかったのでこの手のナレッジは出回っていそうなものだったけれども、意外なことに情報はほとんどなかった。転職したての情弱エンジニアの初業務にはちょっとハードル高かった感じでした。

##おまけ
WorkFusion Studioの基本的な使い方はここを見ると分かりやすい。
https://nextrpa.com/
ほとんど英語だけど公式フォーラムもあるので、コアな内容はこっちで検索かけるといいかも
https://forum.workfusion.com/
Windows10：「OneDriveの同期が終了しない / ディレクトリを削除できない」場合の対処

# 現象１：OneDriveの同期が終わらない

　OneDriveの同期がいつまで経っても終わらないので、同期中のディレクトリを確認した。
　すると、あるディレクトリがずっと同期中のまま。
　とりあえずいらないので削除しようとすると次のエラーがでて削除できなかった。　

# 現象２：エラーメッセージ「再解析ポイント バッファにあるタグは無効です」

　同期が終わらないディレクトリを削除しようとすると「再解析ポイント バッファにあるタグは無効です」のエラーメッセージ。
　管理者権限で、PowerShell、cmdでやっても同じメッセージ。

　とりあえず、日本語の解決記事を探したけど、参考になりそうなのがすぐは見つからなかった。

# 対処：ファイル修復コマンド「chkdsk」を実行

 ファイルのメタ情報に関連するエラーということなので、以下のコマンドを**管理者権限**にて、任意のディレクトリで実行。

```run.cmd
chkdsk /r /f
```

　この後、再起動をして、長い修復処理（20分ぐらい）が終わると、問題となったディレクトリは削除できました。


 この解決方法は日本語ではなく、英語で調べて見つけました。日本語の情報はマニアックなほど、情報が少なくこういうときは英語で調べるのが一番です。

　この動画に感謝です。

　[How to Fix "tag present in the reparse point buffer is invalid" OneDrive Error](https://www.youtube.com/watch?v=SMd2s1Em42Q)

 Thanks!

　QiitaはWindows系の記事は少ないけど、同じエラーで困っている人の解決策になれば幸いです。

# 注意事項

　コメントにありますように、復旧しない可能性もあるため、**コマンド実行前にはデータの保存**をすることをお勧めします。
AndroidアプリでRealmマイグレーションするときの勘所

# 概要
[Realm](https://realm.io/)は、オープンソースのモバイル向けオブジェクトデータベース管理システムである。
弊社のモバイルアプリ[drill](https://drill.5thfloor.co.jp/)のAndroid版でも、設問の回答やアイデアメモ等のデータをデバイスに保存するために使っている。
Realmで保存しているデータのModelを書き換えるとマイグレーションが必要になる。実施した際に覚えておきたいと思ったところをまとめておく。

# 手順
## マイグレーション用のコードを記述する
マイグレーションするために、[`RealmMigration`](https://realm.io/docs/java/latest/api/io/realm/RealmMigration.html)を実装して、`migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long)`をオーバーライドする。

```MyMigration.kt
class MyMigration : RealmMigration {
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        // Migration code here
    }
}
```

`migrate`の内容には、Modelの変更箇所を記述する。
下記に一例を示す。
### `.create(<新しいモデル名>)`
新たに追加したModelがあるときにRealmにModelを作る
### `.get(<該当モデル名>)`
既存のModelに変更があるときにRealmからModelを取得する
### `.addField(<プロパティ名>, <プロパティの型>, <アノテーション（ある場合）>)`
Modelにプロパティを追加する（新規Modelの場合全部記述する）

```kotlin:MyMigration.kt
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        val realmSchema = realm.schema // Realmのスキーマ
        var oldVersion = oldVersion

        if (oldVersion == 0L) { // スキーマのバージョンが以前のものであるとき
            realmSchema.create("NewModel") // NewModelを新規作成した
                .addField("id", Long::class.java, FieldAttribute.PRIMARY_KEY) // @PrimaryKeyアノテーション付きのプロパティ
                .addField("text", String::class.java, FieldAttribute.REQUIRED) // nullを許容しない場合、REQUIREDが必要らしい（ソースがない……）
                .addField("bool", Boolean::class.java)
            realmSchema.get("ExistModel")!! //  ExistModelにプロパティを追加した
                .addField("id", Long::class.javaObjectType) // class.javaObjectTypeはnullを許容する
                .addField("text", String::class.javaObjectType)
            oldVersion++ // マイグレーションしたためスキーマバージョンを上げる
        }
    }
```

## マイグレーションするコードを記述する
マイグレーション用のコードが記述できたら、マイグレーションを実行するコードを記述してマイグレーションする。
`MainActivity`や起動時に実行するコード等に以下を記述する。

```kotlin:MainActivity.kt
        Realm.init(this)
        val realmConfig = RealmConfiguration.Builder() // Realmの設定を定義
            .schemaVersion(1L) // 新しいスキーマのバージョンを設定
            .migration(MyMigration()) // マイグレーション用のコードを設定
            .build()
        Realm.setDefaultConfiguration(realmConfig) // 上記の設定をRealmにセット
```

これで、（スキーマのバージョンが0のとき）マイグレーションが実行される。

さらにModelに変更があった場合、`MyMigration`に追記し、`schemaVersion`を上げることで適宜マイグレーションできる。

# その他
## `deleteRealmIfMigrationNeeded()`を使う
開発時にModelが頻繁に変わる場合などに、その都度マイグレーションを追記するのは大変であるため、`deleteRealmIfMigrationNeeded()`を使うことで、マイグレーションせずに開発を続行できる。
`realmConfig`の定義時にマイグレーション設定の代わりに`.deleteRealmIfMigrationNeeded()`を設定する。

```kotlin:MainActivity.kt
        val realmConfig = RealmConfiguration.Builder()
            .deleteRealmIfMigrationNeeded()
            .build()
```

## マイグレーションせずにビルドした場合
以下のようなRealmの例外が発生した。

```
io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:
   - Class 'NewModel' has been added.
   - Property 'ExistModel.id' has been added.
   - Property 'ExistModel.text' has been added.
```

# 参考
https://realm.io/docs/java/latest
https://realm.io/docs/java/latest/api/io/realm/RealmMigration.html
https://qiita.com/kumas/items/c98f1006776ad141d5f7
Django, DRF(Django REST Framework)での論理削除

論理削除が良い悪いの話はおいておいて、金融系のシステム等では過去のいかなるデータも物理歴に（一定期間）削除してはならず、論理削除を使うことがある。DRFでの論理削除の実装方法についていくつかの記事を見てきたが、僕らはこんな形で実装したので、思い切って公開する。

## 論理削除対応のモデル

```python
class XQuerySet(models.QuerySet):
    def get_or_none(self, *args, **kwargs):
        try:
            return super(XQuerySet, self).get(*args, **kwargs)
        except ObjectDoesNotExist:
            return None

    def delete(self):
        """
        論理削除
        Model.objects.all().delete()
        :return:
        削除した件数
        """
        return super(XQuerySet, self).update(is_active=False, deleted=now_tz())

    def delete_hard(self):
        """
        物理削除
        Model.objects.all().delete_hard()
        :return:
        削除した件数
        """
        return super(XQuerySet, self).delete()


class XModelManager(models.Manager):
    def get_or_none(self, **kwargs):
        try:
            return self.get(**kwargs)
        except ObjectDoesNotExist:
            return None

    def get_queryset(self):
        return XQuerySet(self.model)


class XModelManagerActive(XModelManager):
    def get_queryset(self):
        return XQuerySet(self.model).filter(is_active=True)


class XModel(TimeStampedModel):
    is_active = models.BooleanField(
        default=True,
        editable=False,
        help_text="論理削除用のフラグ"
    )

    deleted = models.DateTimeField(
        null=True,
        default=None,
        editable=False,
        help_text="論理削除された時刻"
    )

    """
    通常検索で利用する Manager
    論理削除されたものが表示されない
    """
    objects = XModelManagerActive()
    """
    全体検索で利用する Manager
    論理削除されたものも含めて表示する
    """
    entire = XModelManager()

    def delete(self, using=None, keep_parents=False, is_hard=False):
        if is_hard:
            return super().delete(using, keep_parents)
        else:
            self.deleted = now_tz()
            self.is_active = False
            self.save(using)
            return 1, {}

    def delete_hard(self, using=None, keep_parents=False):
        self.delete(using, keep_parents, is_hard=True)

    class Meta:
        abstract = True
```

ModelManagerを2つ作って使い分けていますが、基本（普段使い）は `objects` なのでプログラマが特に意識せずとも論理削除になる仕組みです。

## 実際のモデル
```python
class Category(XModel):
    name = models.CharField(
        max_length=32,
        null=False,
        blank=False,
        default="",
        help_text="カテゴリ名"
    )

    key = models.CharField(
        max_length=32,
        null=False,
        blank=False,
        default="",
        help_text="カテゴリ名英語"
    )
```
XModelを継承するだけです。ついでに `get_or_none` とかもついてきます。

たとえばAdminなどで論理削除されたデータにもアクセスしたい場合はこうすれば良い

```python
@admin.register(Category)
class AdminUserAdmin(admin.ModelAdmin):
    list_display = ('key', 'name')

    def get_queryset(self, request):
        return self.model.entire.all()
```

XTechではAPIの開発に `Django REST framework` を使っています。DRFのかゆい所に手が届く拡張をたくさん持ってますので、出来る限り公開していきたいと思いますので、乞うご期待で。
Google Chrome の Software Reporter Toolを無効化！

#はじめに
ある日、Chromeでネットサーフィンしているとき、CPUファンがフルスピードで回転していてうるさいなあと思い、タスクマネージャーを開いたら、CPU使用率が100%になっていました。Chrome以外、アプリを立ち上げているわけではないので、何がこんなにCPU食ってんだ？と思い詳細にタスクマネージャーを確認するとChrome内のソフト**「Software Reporter Tool」**がめちゃんこCPU使用率を食っていました。

##Software Reporter Toolとは
簡潔に書くと
「**Google Chromeの実行時に妨げになっているアプリケーションを発見したらにGoogleにレポートを送る**」
というものです。名前そのまんまの意味でしたね。

##Software Reporter Toolを止めていいの？
はい、特に問題ありません。
内容を見て分かる通り、Googleにレポートを送っているだけなので、Chromeの実行環境には
関係していないからです。

**2021/11/25追記**
読者様からこのソフトは悪意のあるソフトウェアを検知した際にGoogleに詳細なレポートを送信
しているので、停止したらその分脆弱になることを留意した方が良いとのご指摘をいただきました。
全く問題ないというのは誤りでした。お詫びいたします。

##Software Reporter Toolの一時停止方法
①設定を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/f943c990-67be-106d-e8bc-0fb4442dedbd.png)

②詳細設定をクリック（一番下にあります）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/04575f18-2699-718a-2ae0-32930dbe2613.png)

③パソコンのクリーンアップをクリック（一番下にあります）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/8d817fcc-77be-c905-c39b-6646a2795c26.png)

④「このクリーンアップ中にパソコン上で見つかった有害なソフトウェア、システム設定、プロセスについて詳細なレポートをGoogleに送信する」項目のチェックをはずす
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/f44736a2-25b1-e621-1b4f-add571db2699.png)

上記の手順でSoftware Reporter Toolを一時停止させることができますが、Chromeを閉じてまた開くと
④ではずしたはずのチェックがまた復活してしまいます。
Chromeの標準設定でそのようになっているようです。
完全に無効化したい場合は以下の手順を行ってください。

##Software Reporter Toolを無効化させる方法
①`「C:\Users\＜ユーザー名＞\AppData\Local\Google\Chrome\User Data\SwReporter\＜Chromeのバージョン＞」`
のパスをエクスプローラーで開き、software_reporter_tool.exeを右クリックし、プロパティを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/e96d6479-9db5-13ac-edea-84d22ecc8382.png)

②セキュリティタブから詳細設定をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/4a45f88b-9702-5678-620f-78ff89521718.png)

③継承の無効化をクリック（下の画像は私が既に継承を無効化しているため、「継承の有効化」となっています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/9da9d026-0ec6-4306-50e3-7de25bb3d02a.png)

④「このオブジェクトから継承されたアクセス許可を全て削除します」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500511/2684b19c-ba7b-7f78-8de7-d263b4bd9900.png)

これでSoftware Reporter Toolの無効化が完了しました。
#終わりに
Software Reporter Toolを無効化することで、急にCPUファンが回りだしてCPU使用率をめっちゃ食っているということはなくなりました。いまのところSoftware Reporter Toolを無効化したことでChromeがおかしくなったとかはなく問題なく使えています。Software Reporter ToolはGoogleにレポートを送るだけなので大丈夫だと思いますが、もしChromeの動作がおかしくなったとかあればまた記事にします。
PlatformIOでSTM32 blue pillクローンをビルドする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/ad7335ec-0a56-beb7-9f5b-b88d2787ea5c.png)


[bluepillクローン](https://www.amazon.co.jp/VKLSVAN-STM32F103C8T6-Minimum-%E9%96%8B%E7%99%BA%E3%83%9C%E3%83%BC%E3%83%89%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB-Arduino%E3%81%A8%E4%BA%92%E6%8F%9B/dp/B0811D7DR2/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=stm32&qid=1580349589&s=electronics&sr=1-2)は安価で便利なのですが、そのままではPlatformIOのビルドが通らないことがあるようです。

型番のバリエーションがたくさんあるので、まずはチップ表面の型番を[このページ](https://ht-deko.com/arduino/stm32f103c8t6.html)の情報に照らし合わせ、[PlatformIOのチップ情報のページ](https://docs.platformio.org/en/latest/boards/ststm32/bluepill_f103c6.html)を参照し```platformio.ini```を書き換えます。
[秋葉原ラジオデパート3F Shigezone](https://twitter.com/ShigezoneAkiba/status/1167799288925061121)で売っていたのはこんな感じ

```
env:bluepill_f103c8]
platform = ststm32
board = bluepill_f103c8
framework = arduino

; change microcontroller
board_build.mcu = stm32f103c8t6

upload_protocol = stlink
```

その際、ビルドすると下記のようなエラーが出ることがあります。

```
Warn : UNEXPECTED idcode: 0x2ba01477
Error: expected 1 of 1: 0x1ba01477
in procedure 'program'
** OpenOCD init failed **
shutdown command invoked

*** [upload] Error 1
```

その場合は[このサイト](https://community.platformio.org/t/cannot-upload-to-stm32-bluepill-board-over-stlink-v2/3492/7)にあるように

```~/.platformio/packages/tool-openocd/scripts/target/stm32f1x.cfg ```

の_CPUTAPIDを

```Error: expected 1 of 1: 0x1ba01477```
のものから
```Warn : UNEXPECTED idcode: 0x2ba01477```
へ書き換えます。

```
      set _CPUTAPID 0x1ba01477
```
↓

```
      set _CPUTAPID 0x2ba01477
```

これでビルドが通るようになるかと思います。
typeormで Duplicate column name と出てしまうときの解決法

#解決法
[Issue with snake_case naming strategy](https://github.com/typeorm/typeorm/issues/2200#issuecomment-511037158)

```ts
const SnakeNamingStrategy = require('typeorm-naming-strategies').SnakeNamingStrategy;

module.exports = {
   type: "mysql",
   host: "localhost",
   port: 3306,
   ...
   namingStrategy: new SnakeNamingStrategy(),
}
```

# 説明
以下のようなentityがあったとする。

```ts
import {Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn} from "typeorm";
import {User} from "./User";

@Entity()
export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @ManyToOne(type => User, user => user.photos, { eager: true })
    @JoinColumn({ name: 'user_id' })
    user: User;

}

--- 

import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm";
import {Photo} from "./Photo";

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @OneToMany(type => Photo, photo => photo.user)
    photos: Photo[];

}
```

このとき、`photoRepository.findOne()`を実行すると、以下のようなクエリが実行されて`Duplicate column name`のエラーが出てしまう。

```sql
SELECT DISTINCT ~略
FROM (SELECT `Photo`.`user_id`  AS `Photo_user_id`,
             `Photo_user`.`id`  AS `Photo_user_id`,
~略

```

そこで、上記解決法にある`namingStrategy`を導入することにより、以下のようなクエリが実行されるようになりエラーがでなくなる。めでたしめでたし。[^1]

```sql
SELECT DISTINCT ~略
FROM (SELECT `Photo`.`user_id`  AS `Photo_user_id`,
             `Photo__user`.`id`  AS `Photo__user_id`,
~略

```


参考
[Duplicate alias names for different fields - Stack Overflow](https://stackoverflow.com/questions/49182535/duplicate-alias-names-for-different-fields)
[Issue with snake_case naming strategy](https://github.com/typeorm/typeorm/issues/2200)

[^1]: 0.3.0でデフォルトで対応する予定らしいが、該当issueが立てられたのは2018年5月。いつになることやら…
pythonからGCEを起動・停止する

python 3.7

requiremets.txt

```
google-api-python-client==1.7.9 
oauth2client==4.1.3
```

main.py

```python
import time

from googleapiclient.discovery import build, Resource
from oauth2client.client import GoogleCredentials


def start(project, zone, instance_name):
    credentials: GoogleCredentials = GoogleCredentials.get_application_default()
    compute: Resource = build('compute', 'v1', credentials=credentials)
    instance: dict = compute.instances().get(project=project, zone=zone, instance=instance_name).execute()
    result: dict = compute.instances().start(project=project, zone=zone, instance=instance['name']).execute()
    # Wait Running
    while True:
        instance: dict = compute.instances().get(project=project, zone=zone, instance=instance_name).execute()
        print(instance["status"])
        # TERMINATED -> STAGING -> RUNNING
        if instance["status"] == "RUNNING":
            break
        time.sleep(5)


def stop(project, zone, instance_name):
    credentials: GoogleCredentials = GoogleCredentials.get_application_default()
    compute: Resource = build('compute', 'v1', credentials=credentials)
    instance: dict = compute.instances().get(project=project, zone=zone, instance=instance_name).execute()
    result: dict = compute.instances().stop(project=project, zone=zone, instance=instance['name']).execute()
    # Wait Terminated
    while True:
        instance: dict = compute.instances().get(project=project, zone=zone, instance=instance_name).execute()
        print(instance["status"])
        #  RUNNING -> STOPPING -> TERMINATED
        if instance["status"] == "TERMINATED":
            break
        time.sleep(5)


if __name__ == "__main__":
    project = 'xxx'
    zone = 'yyy'
    instance_name = "zzz"
    start(project, zone, instance_name)
    stop(project, zone, instance_name)

```
blender2.81に公式mmd_toolsを導入できない

Q)一応インストールはできるが「2.8xへのアップグレードが必要」って出て有効化できない
A)ブランチ版で解決。

【ブランチ版の場所】
https://github.com/powroupi/blender_mmd_tools
downloadするファイル:
 blender_mmd_tools-dev_test.zip

【ダウンロードファイルの調整】
1)ダウンロードファイルを解凍
2)解凍されたフォルダのmmd_toolsフォルダのみを再圧縮 -> mmd_tools.zipを作る

【blender側での作業】
blender->編集->プリファレンス->アドオン->インストール
で、先程圧縮したmmd_tools.zipを指定
mmdでアドオン検索
有効にチェック

サイドバーのタブにMMDができればOK
![mmdtools.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356086/93504a40-4dbc-32f3-f0aa-a8e739977adb.png)
WinPython に Julia を導入する

WinPython使うとWindowsでポータブルなPython環境が簡単に作れるので重宝します。
今回はPythonだけでなくJuliaでも使えるようにしたので備忘録ついでに共有します。

## WinPythonのダウンロード

お好きなダウンロードをどうぞ。

https://winpython.github.io/

私は `Winpython64-3.8.1.0.exe` をダウンロード。`D:\Apps` フォルダに展開しました。

## Juliaのダウンロード

Juliaをダウンロードします。

https://julialang.org/downloads/

Windows 64bit版 v1.3.1のexeファイルをダウンロードしました。

### Juliaのインストール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328319/77a2b7b6-92b5-fa96-bde4-e700540d0b4f.png)

インストール（といっても展開するだけ？）先はWinPythonを展開したフォルダ配下の `t\Julia-1.3.1` フォルダにしました。

## WinPythonの設定ファイルを書き換える

`[WinPythonの展開フォルダ]\settings\winpython.ini` ファイルを編集します。

```
[environment]
JULIADIRBASE=%WINPYDIR%\..\t\Julia-1.3.1
JULIADIR=%JULIADIRBASE%\bin
JULIA_DEPOT_PATH=%JULIADIRBASE%\share\julia
JULIA_HISTORY=%JULIADIRBASE%\logs\repl_history.jl
JUPYTER=%WINPYDIR%\Scripts\jupyter.exe
PATH=%PATH%;%JULIADIR%
BINARYPROVIDER_DOWNLOAD_ENGINE=curl
```

`Julia-1.3.1` のバージョンの部分は適宜修正してください。

`BINARYPROVIDER_DOWNLOAD_ENGINE=curl` の行については、Juliaのバージョンによっては必須で、
無くても動くバージョンもありそうです（要調査）。

## Julia設定

Juliaを起動するには WinPythonのインストールディレクトリにある `WinPython Command Prompt.exe` で開くコマンドプロンプトから実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328319/40a630f8-f4a2-057e-9bac-ba66a1e49b99.png)

では、必要なパッケージをインストールしていきます。

Juliaが開いたら `]` キーを打つと、 `(v1.3) pkg>` みたいな表示に切り替わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328319/87a201e0-7a73-8bc0-4b57-c314df532505.png)

このモードだとパッケージの追加／削除ができるようになるので、下記コマンドを実行します。

```julia
add IJulia
```

実行するとJupyterにカーネルが追加されます。
確認方法はWinPython Command Promptで以下のコマンド。

```cmd
jupyter kernelspec list
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328319/52a24fb9-68a3-28f5-f575-efa79fe5dc86.png)

…他とは違うディレクトリにカーネル設定が書かれてしまった…！！！！
（が、とりあえず動くので放置…解決方法があれば教えてほしいです）

## Jupyterの使用

いつもどおりWinPythonの展開ディレクトリから`Jupyter Lab.exe` を実行します。

`New Launcher` で開く画面に Juliaが追加されていればオッケー！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328319/ab4b283c-8c1a-9f98-b195-ca573bc8d0aa.png)

## Juliaを使う

あとはお好きなように！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328319/f26faf79-fd99-ed2d-c73b-6367da5a57af.png)
IT系専門学校1年生が考える社会での資格の必要性

#はじめに
平成31年、少しパソコンが好きレベルでIT系の専門学校に入学しました。
専門学校で学び、考えてきたことをまとめていきたいと思います。
これからIT関連の道に進みたい方の参考になれば幸いです。

#学習環境 - 大学との差
正直な話、偏差値などの話をするとこの学校は底辺に当たると思います。
だって、名前を書けば入れたんですから。(入学経緯は後々お話できればと思います。)
しかし、先生たちは皆、仕事経験のある方たちが多く、かなり先生環境は充実しています。
馬鹿な奴らの上位にいるというのもモチベ的には良いものです。あくまでもモチベ的にはですよ。

###専門学校の目標
専門学校は、「資格試験に重点を置き、最終目標は就職をさせる。」という考えのもと運営されています。
社会の即戦力を育てているので、研究室とかの概念はありませんから、自己学習がかなり大切になってきます。
学校とは別に何か自主的にしていないと、大学で研究している人との知識の差が付くのは事実です。
技術には常に貪欲に生きましょう。

###学びの場所を選ぶ際には

`自分が何をしたいのか明確なのか。`
`研究室に入ってバリバリ研究をしたいのか。`
`時間に余裕のある専門学校で自分でスキルを磨くべきなのか。`

を考えてから選びましょう。
惰性で入るとついていけなくなって最悪退学が待っています。

#資格は必要か。
ネットで検索をかけるとよく、「～試験(資格)　必要性」などと疑問形で出てきます。
多くの人が、資格は本当に必要なのかと考えているようです。

私は、***『新卒は必要。(有名大学を除く)』***と考えています。

新卒はなぜ必要なのか？
その答えは、基本情報技術者のポスターの謳い文句にもある、
***『技術があると口で言うだけじゃ分からない。』***にあると思います。


###採用企業の立場になって考えてみましょう。

>1. イチから教え込まないといけない未経験。
2. 面接では技術的な事を言っているけど名の知られてない大学で技量は不明な人。
3. 国やベンダー認めている技量の証明書を持っている人。

教育コストや即戦力が求められる世の中で、採用されるであろう人は果たしてどれでしょうか。
もちろんですが、起業したいといった考えをお持ちの方はまた別の話になるでしょう。

###資格なんか取らなくてもいいじゃないか

資格なんかとんないで、コンテストで賞取ったり、Qiitaで超有名になったり...etc, 
なんて方法もありますが、それはトップYouTuberになるようなもんです。並外れた努力と才能と運が必要。
ある程度休息しながら頑張りたい私には向いてません。

###資格勉強だけで技術向上はしない
ただ、勘違いをしていけない事として、資格勉強をしているだけで実践的な役立つスキルが身に付くという訳ではありません。
資格勉強の傍らに、サーバー構築してみたり、OSSの開発してみたり...などは確実に必要です。

資格というのは、***「就職の保険 and 技術の証明書」***であると言うことを忘れてはいけません。

#おわりに
資格試験は、目に見えて自分が進歩していると気付けるものでもあり、合格したときの嬉しさは大きいです。
ある意味、趣味の一環になっているのかもしれませんね。

技術系の資格取得に関しては賛否両論ありますが、以上は私の考えになります。
最後までお読みいただきありがとうございました。

2年生も技術を突き詰める人物を目指し、がんばります。
IT歴1年目のひよっこにアドバイスなど、何でもコメントいただけるとありがたいです。
OpenCVで線とか矩形とかループとか入力する

## 背景

OpenCVを使って画像フィルタを試す時など、画像全体ではなく一部をクロップしたり、ループ部分だけへの操作などが欲しい時があります。

そんな時いちいち座標を自分で定義してやるのはヒジョーに面倒なので、画面で各種の図形入力ができるようにしたライブラリを作りました。[github](https://github.com/moicci/cv2operator)にあげてあるので、良かったら使ってみてください。

OpenCV の python バインディング専用です。

![](https://raw.githubusercontent.com/moicci/cv2operator/master/docs/polygon-op.png)

## 機能

- **LineOperator**: ドラッグで線を入力する
- **PolylineOperator**: 点をクリックして行き折れ線を入力する
- **PolygonOperator**: 点をクリックして行きポリゴンを入力する
- **RectOperator**: ドラッグで矩形を入力する
- **BrushOperator**: ドラッグでマスク領域を塗りつぶす
- **KeyOperator**: ウィンドウでのキー管理

## 使い方

LineOperator の使い方はこんな感じです。

```
import cv2
from cv2operator import KeyOperator, OperatorWindow, LineOperator

def line_cb(p1, p2):
    print(f"line: p1={p1}, p2={p2}")

image = cv2.imread("goru.jpg")
window = OperatorWindow("example", image)

line_op = LineOperator(window, callback=line_cb)

key_op = KeyOperator()
print(key_op.help())
key_op.main_loop()
```

## その他の入力

その他については [examples](https://github.com/moicci/cv2operator/tree/master/examples) の [demo.py](https://github.com/moicci/cv2operator/tree/master/examples/demo.py) を参照してください。

こんな入力が可能です。

### RectOperator

![image](https://raw.githubusercontent.com/moicci/cv2operator/master/docs/rect-op.png)

### LineOperator

![image](https://raw.githubusercontent.com/moicci/cv2operator/master/docs/line-op.png)

### PolylineOperator

![image](https://raw.githubusercontent.com/moicci/cv2operator/master/docs/polyline-op.png)

### PolygonOperator

![image](https://raw.githubusercontent.com/moicci/cv2operator/master/docs/polygon-op.png)

### BrushOperator

![image](https://raw.githubusercontent.com/moicci/cv2operator/master/docs/brush-op.png)
Wordpress開発で役立った記事

##WPでボタンクリックでPHP実行しページ遷移無しでpost送信してJavascriptで結果を表示する方法

https://rdk.me/php-js-post/


##WordPressのパーマリンクにスラッシュ「/」を含める方法
https://businessdepartment.jp/wordpress/perma-link-slash/

##【wordpress】データベースへの値の挿入(wpdb->insertの使い方について)
https://teratail.com/questions/185177

##プラグイン用の管理画面を作るときにコピペするテンプレート
https://nskw-style.com/2011/wordpress/customize/plugin-admin-template.html


##wpdb道場 (2) 〜データの作成・更新・削除〜
https://takahashifumiki.com/web/programing/3309/


##WordPress（ワードプレス）のデータベースを操作する「wpdb クラス」で、WP上級者はこんなことをしています
https://www.wpcloud.jp/wordpress-tips/database-wpdb-class/

##HTMLのAタグでPOSTする方法
https://qiita.com/next1ka2u/items/9736ce2f9c7f3aa69d61

##PHP、1つのフォーム内に複数のsubmitボタンを配置して、submitボタン毎に動作を変える
http://piyopiyocs.blog115.fc2.com/blog-entry-1023.html

##WordPressでデータベースを使う
https://accelboon.com/tn/%E3%80%90wpdb%E3%80%91%E3%80%80wordpress%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92%E4%BD%BF%E3%81%86/

##可変変数を使って動的に変数を操作してみる
https://qiita.com/h-ueno2/items/892b34ae744be3563c51

##可変変数
https://www.php.net/manual/ja/language.variables.variable.php

##isset, empty, is_null早見表
https://qiita.com/shinichi-takii/items/00aed26f96cf6bb3fe62

##クォートされた文字列のクォート部分を取り除く
http://phpspot.net/php/man/php/function.stripslashes.html
Capistranoでdbロールが複数設定されていてもdb:migrateは1回しか実行されない

# 検証したい事
複数 `server` に `db` ロールが設定されている場合、`db:migrate` が複数回実行されるのでは？？
気になり調査、検証してみました。

# 結果

`db:migrate` は1回だけ実行されるように配慮された実装になっていました。
[capistrano/tasks/migrations.rake#L38](https://github.com/capistrano/rails/blob/dec480554144bd1904f607dd665cf42c962f1e4b/lib/capistrano/tasks/migrations.rake#L38)

また、定義順序を変更して検証をしてみると、最初に定義されている `server` で実行されました。

# server定義順序を変更した検証
## パターン1
capistrano


```shell
# app01.com、app02.comの順に記述
server 'app01.com', user: 'ssh-user', roles: %w{app db}
server 'app02.com', user: 'ssh-user', roles: %w{app db}
```

deploy実行ログ
app01.comでdb:migrateが実行された

```shell

** Invoke deploy:migrating (first_time)
** Invoke deploy:set_rails_env
** Execute deploy:migrating
  INFO [79c7f9ef] Running /usr/local/rbenv/bin/rbenv exec bundle exec rake db:migrate as ssh-user@app01.com
  INFO [1661fd3f] Finished in 3.259 seconds with exit status 0 (successful).
```

## パターン2
capistrano


```shell
# app02.com、app01.comの順に記述
server 'app02.com', user: 'ssh-user', roles: %w{app db}
server 'app01.com', user: 'ssh-user', roles: %w{app db}
```
deploy実行ログ
app02.comでdb:migrateが実行された

```shell
** Invoke deploy:migrating (first_time)
** Invoke deploy:set_rails_env
** Execute deploy:migrating
  INFO [79c7f9ef] Running /usr/local/rbenv/bin/rbenv exec bundle exec rake db:migrate as ssh-user@app02.com
  INFO [1661fd3f] Finished in 3.259 seconds with exit status 0 (successful).
```

# まとめ
dbロールが複数定義されていても、`db:migrate` は1回しか実行されません。
とはいえ、誤解が生じないよう特定の `server` 1つだけにdbロールは定義したほうが良いですね。

```shell
server 'app01.com', user: 'ssh-user', roles: %w{app db}
server 'app02.com', user: 'ssh-user', roles: %w{app}
```
Podコマンドが見つからない！？

swiftの勉強をしようと思いUdemyにそって始めたのですが、環境ですぐにつまづきました。。。
`pod command not found`

**とのことでしたのでQiitaで調べた結果、以下のサイトに助けていただきました！**
https://qiita.com/sachiko-kame/items/e832c6de3b8c2d803eb3

・本来は

``sudo gem install cocoapods``

らしいのですが、これで解決しなかったのでもう一方を試しました！

・解決策
``sudo gem install -n /usr/local/bin cocoapods``

・セットアップ
``pod setup``

・Podfile作成
``pod init``

これで無事にPodfileを作成できました！
出だしでつまづくとモチベーション削がれますよね、ご参考程度に。
覚えておくべきEXCELショートカット40選 ALT＋〇＋〇、Ctrl＆〇編


## はじめに
自分の備忘録として残します。EXCELショートカットのALT+複数key、Ctrl&keyの絞り厳選。EXCEL操作を劇的に早くしてくれる＆すべてポチポチとマウス操作するよりもカッコよく操作できます(自己満)。　ここに載ってあることは、マウス操作しないように気を付けています。

## ALT＋X＋X＋X（20選）

|No|キー1|キー2|説明|
|---|------------|---|-------------------------------|
|1 |ALT＋W＋F＋F|WFF|ウィンドウ枠を固定する/解除する|
|2 |ALT＋D＋F＋F|DFF|フィルターの設定|
|3 |ALT＋D＋F＋S|DFS|フィルターのクリア|
|4 |ALT＋E＋S＋(x)|ES(x)|コピーした状態で形式を選択して貼り付け V(値)/T(書式)|
|5 |ALT＋D＋G＋G|DGG|グルーピング化(DGU：解除)/(DGE：設定画面)|
|6 |ALT＋D＋P＋P|DPP|ピボットテーブルを作成する|
|7 |ALT＋H＋K   |HK|表示形式を桁区切りスタイルにする|
|8 |ALT＋I＋R   |IR|行を挿入する|
|9 |ALT＋I＋C   |IC|列を挿入する|
|10 |ALT＋H＋H   |HH|背景色を塗る|
|11|ALT＋H＋H＋N|HHN|背景色を取る|
|12|ALT＋W＋V＋G|WVG|ワークシートの枠線を表示/非表示にする|
|13|ALT＋H＋B＋A|HBA|格子線（罫線）を引く|
|14|ALT＋I＋W   |IW|新しいシートの追加をする|
|15|ALT＋H＋O＋R|HOR|シート名を編集する|
|16|ALT＋E＋L   |EL|シートを削除する|
|17|ALT＋W＋Q   |WQ|ズームを表示する|
|18|ALT＋H＋A＋C|HAC|セルの内容を中央揃えで示する|
|19|ALT＋H＋W   |HW|文字を折り返して全体を表示する|
|20|ALT＋H＋Q＋I|HQI|列の幅の自動調整を行う|

## Ctrl＆X （20選）

|No|キー1|キー2|説明|
|---|-------|---|-----------------------|
|1 |Ctrl & S| S |ファイルを上書き保存|
|2 |Ctrl & A| A |すべてのセルを選択|
|3 |Ctrl & Z| Z | 元に戻す|
|4 |Ctrl & C| C |コピー|
|5 |Ctrl & V| V |貼り付け|
|6 |Ctrl & X| X |切り取り|
|7 |Ctrl & F| F |文字列を検索|
|8 |Ctrl & H| H |文字列を置換|
|9 |Ctrl & W| W |選択したウィンドウを閉じる|
|10|Ctrl & ;| ; |本日の日付を入力|
|11|Ctrl & 1| 1 |セルの書式設定を開く|
|12|Ctrl & 5| 5 |取消線をつける|
|13|Ctrl & D| D |上のセルの内容を下のセルにコピー|
|14|Ctrl & R| R | 左のセルの内容を右のセルにコピー|
|15|Ctrl & PgUp|PgUp|左のシートに移動する|
|16|Ctrl & PgDn|PgDn|右のシートに移動する|
|17|Ctrl & 矢印|矢印|データが終わるまで or 次のデータまでセルを移動|
|18|Ctrl & N| N |空白のbookが立ち上げる|
|19|Ctrl & Tab|Tab|次のbookに移動|
|20|Ctrl & B| B |太字にする|


## おまけ：ショートカット　リボン編

 - `「Ctrl＆F1」`でリボンを表示・非表示を切り替えることが可能。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/e158dd99-7922-ac7a-197e-fc0ebd050f93.png)
↑切り替え可能↓
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/d0b01c07-9474-8095-e8bd-b2e4073f2c3d.png)


 - `「Alt」`キーを押下すると、ショートカットのヘルプが表示される
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/4800efa0-45e1-d3f9-2d0d-7eabd78493f2.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/2c9dde1b-7288-8e09-26f4-15496c086d75.png)


 - `クイックアクセスツールバー`にも、キーが表示されるので、それでショートカットしてもOK。
下図の例（アクセスツールバーはリボン下に表示）：中央揃え　ALT＋H＋A＋C　ではなく、ALT＋07
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/289a28e2-50e8-d3b9-5f08-25ef8233e608.png)