OmniAICreator/Qiita-1.07M huggingface dataset:
macOS Catalina で Oniguruma v5.9.6 をコンパイル

需要なさそうだけど、成り行きでやったのでメモ。

## configureファイルとMakefile生成に必要なツールをインストール
```
❯ brew install autoconf
❯ brew install automake
❯ brew install libtool
❯ brew install intltool
❯ brew install pkgconfig
❯ brew install cmake
```

## ソースコード取得
```
❯ git clone https://github.com/kkos/oniguruma.git
❯ cd oniguruma 
❯ git checkout v5.9.6
```

## ソースコードの前処理
よくわからないけど、automakeやlibtoolのバージョン違いなどに起因しているように思われるエラーが出るので、それを解消するために、ファイル作ったりすこし内容を置換したり。

```
❯ touch NEWS
❯ touch ChangeLog
❯ sed -i '' -e 's/INCLUDES/AM_CPPFLAGS/g' Makefile.am 
❯ sed -i '' -e 's/INCLUDES/AM_CPPFLAGS/g' sample/Makefile.am 
❯ glibtoolize --ltdl --force --copy
❯ automake --add-missing
```

## configureファイル・Makefile.in生成
```
❯ autoreconf
```

いろいろwarningは出ますが、これでconfigureとMakefile.inの両ファイルが生成されればOK。

## Makefile生成・コンパイル・インストール
インストール先はお好きに。

```
❯ ./configure
❯ make
❯ make DESTDIR=/Users/xxx/Library/oniguruma5.9.6 install 
```

## エラーと参考サイト
上記手順で進めればエラーは出ないと思いますが、エラーメッセージから解決を求めて来た方の参考になればということで。

### test-driverがないエラー
```
parallel-tests: error: required file './test-driver' not found
parallel-tests:   'automake --add-missing' can install 'test-driver'
```

エラーメッセージのとおり `automake --add-missing` すれば解消します。

### Makefile.in生成でエラー
古いバージョンのautomakeが期待されていることから起きるエラー？のようですが。これはもうMakefile.amのほうを編集して解決してしまいます。

```
sample/Makefile.am:5: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
```

### configureでエラー
```
sed: ./ltmain.sh: No such file or directory
mv: rename libtoolT to libtool: No such file or directory
cp: libtoolT: No such file or directory
chmod: libtool: No such file or directory
config.status: executing default commands
```

https://stackoverflow.com/questions/11826167/libming-0-4-2-installation-giving-error-on-osx-10-7-4-x64-when-building-from-sou

↑を参考にしました。configureファイル生成前に、必要なライブラリをインストールして `glibtoolize` 実施。
【PHP8.0】例外をcatchしたいけど何もしたくない


例外をcatchしたいけど何もしたくない。

```php
try{
	foo();
}catch(Throwable $e){
	// 何もしない
}
```

何もしないのにわざわざ変数に受け取るのって無駄じゃありませんか？

というわけで[non-capturing catches](https://wiki.php.net/rfc/non-capturing_catches)というRFCが提出されました。


# PHP RFC: non-capturing catches

## Introduction

今のところ、PHPは例外を明示的に変数でキャプチャする必要があります。

```php
try {
    foo();
} catch (SomeException $ex) {
    die($ex->getMessage());
}
```

しかしながら、ときにはその変数を使わない場合もあります。

```php
try {
    changeImportantData();
} catch (PermissionException $ex) {
    echo "You don't have permission to do this";
}
```

これを見た人は、プログラマが意図してこの変数を使わなかったのか、あるいはバグなのかがわかりません。

## Proposal

例外を変数に受け取らずcatchできるようにします。

```php
try {
    changeImportantData();
} catch (PermissionException) { // catchした変数を使わないという意図が明白
    echo "You don't have permission to do this";
}
```


## Prior art

7年前にあった[似たようなRFC](https://wiki.php.net/rfc/anonymous_catch)は、以下のように例外名も省略可能にするという理由で否定意見が多数でした。

```php
try {
    foo();
} catch {
    bar();
}
```

いっぽう、このRFCは肯定的な反応が多く、再検討の余地があります。


## Backward Incompatible Changes

後方互換性を壊す変更はありません。

## Proposed PHP Version(s)

PHP8.0

## RFC Impact

特になし。

## Vote

投票は2020/05/24まで、投票者の2/3の賛成で受理されます。
このRFCは賛成48反対1の圧倒的多数で受理されました。

## Patches and Tests

・[https://github.com/php/php-src/pull/5345](https://github.com/php/php-src/pull/5345)

## References

・[メーリングリスト](https://externals.io/message/109550)


# 感想

このRFCが意図しているところは決して例外の握り潰しなどではなく、例外処理のロジックに例外の中身を使わないときに省略できるというものです。
変数に受け取る処理がなくなるので速度も速まることでしょう。

しかしですな、こんな機能があったら絶対にこんなコードを書く奴が出てくるわけですよ。

```php:PHP8
try{
	foo();
}catch(Exception){}
```

いやまあ、こんなの書いてしまう人は今でもやってると思いますけどね。

```php:PHP7
try{
	foo();
}catch(Exception $e){}
```

なら別にあってもいいか。

劇的に便利になるというわけではないですが、ちょっと気が利く書き方ができるようになりますね。

最後にもう一度言いますが、冒頭のコードは悪い例なので決して真似してはいけません。
直線の方程式を正規化する(sympyで)

(オリジナルポスト)直線の方程式を正規化する
https://qiita.com/tydesign/items/c942fd6b25cd5f07ed7a
(参考)sympyのcoeffの使い方を教えて下さい
https://ja.stackoverflow.com/questions/33677/sympyのcoeffの使い方を教えて下さい?r=SearchResults

# 【例】直線 3x-2y-4=0 を正規化する。
```python
from sympy import *
var('x y a b')
def MyCoeffxy(myf,xy,i):
    if i==0:
       p = Poly(myf, xy)
       return p.coeff_monomial(0+1)
    else:
       return myf.coeff(xy ** i)

f=3*x- 2*y -4
print(f)
a= MyCoeffxy(f, x, 1)
b= MyCoeffxy(f, y, 1)
c= MyCoeffxy(MyCoeffxy(f, x, 0), y, 0)
q=sqrt(a*a+b*b)
# g=str(a/q) + "x+" + str(b/q) + "y+" + str(c/q) + "=0"
# print(g.replace('+-', '-'))
g=str(N(a/q,6)) + "x+" + str(N(b/q,6)) + "y+" + str(N(c/q,6)) + "=0"
print(g.replace('+-', '-'))
# 3*x - 2*y - 4
# 0.832050x-0.554700y-1.10940=0
```
RTX1210の初期化（工場出荷状態）に戻す方法

RTX1210の初期化方法は2つあります。
お使いの環境でやりやすい方で行ってください。

1. RTX1210のコンソールに入り初期化する
2. RTX1210本体の外部ボタンから初期化する

### 環境
* OS:MacOS
* terminal:iTerm2

※私の環境で動作確認を行ってはいますが、お使いの環境ですべての動作を保証するものではありませんのでご注意ください。

## RTX1210のコンソールに入り初期化する

RTX1210のコンソールから初期化（工場出荷状態）する流れは以下となります。

1. RTX1210に管理者モードで入る
2. 初期化コマンドを入力

コンソールから管理者モードで、初期化コマンドの「cold start」を叩きます。
※RTX1210のコンソールへの接続がわからない方は[__こちらから__](https://qiita.com/2480230/items/4b5a650ef19907ad30aa)

```japanese:RTX1210
# cold start
Password: //設定しているパスワードを入力
RTFS formatting... Done.
Restarting ...
```

RTX1210が再起動すると設定の初期化が完了します。

## RTX1210本体の外部ボタンから初期化する

RTX1210本体から初期化する方法はとても簡単です。
本体前面にある「microSD+USB+DOWNLOAD」の外部ボタンを同時に押しながら、背面の電源ボタンを入れ直します。
RTX1210が起動すると設定の初期化が完了します。

※ログインパスワードがわからない場合にはこちらの方法で初期化することができますが、既存の設定は全て初期化されるのでご注意ください。

## RTX1210設定Howto記事まとめ

できるだけ、初期設定から順にして掲載していく予定です。
[こちら](https://qiita.com/2480230/items/aecd2c86133f18e24332)にRTX1210のHowto記事まとめページがあります。

* [RTX1210設定Howto記事まとめ](https://qiita.com/2480230/items/aecd2c86133f18e24332)

RTX1210を中心に書いてはいますが、YAMAHAのRTXシリーズのコマンドはRTX5000、RTX3500、RTX1200、RTX830、RTX810でも同じコマンドで設定できることが多いので、ご参考になれば幸いです。
Linux client(Ubuntu + remmia)から Windows へ RDP したときに alt-tab, IME 切り替えする

## 背景

* Linux RDP client(gnome desktop + remmia) から Windows へ RDP 接続している
 * remmia は Linux での標準的(?)な RDP ソフト 
 * 関連: Windows で OpenGL/Vulkan アプリを動かして画面をイントラネットで VNC などで転送したいメモ https://qiita.com/syoyo/items/909f5915252ba5f197a0
* RDP Windows 内で Alt + tab でアプリ切り替え, Alt + ` で IME 切り替えしたいが, gnome のキーバインドとかぶってしまう.


## 方法

キーボート右側の Ctrl(フルサイズキーボード想定)か, remmia の GUI で Grab all keyboard events ボタンで切り替える(キーボード入力を RDP 側がキャプチャ)ことができます.

Using Alt+Tab in Remmina RDP connection
https://askubuntu.com/questions/155769/using-alttab-in-remmina-rdp-connection

ありがとうございます!

## TODO, 問題点

* [ ] gnome-desktop 側での task 切り替えのキーバインドをいい感じにしたい
(Super(Win) + Tab に設定すると, RDP 側で Win キーがキャプチャされてしまう)
Google Apps Script で公開したWebアプリケーション内で Web Woker や ES Modules を使う

「CORSか SOP違反か」何とかしたいですよね。
※本記事は「xxx.gs」ではなく「xxx.html」に書く方のJavaScriptの話です。

#外部スクリプトが使えない
GASで作ったWebアプリで下記のようなコードを書いてもエラーになります。

```xxx.html
<script type="module">
import { module } from "https://xxx/module.js";
cosnt worker = new Worker("https://xxx/worker.js");
</script>
```

開発コンソールで確認してみると「CORS」だの「SOP」だのといった文言のエラーメッセージが出ていると思います。
CORSはオリジン間リソース共有、SOPは同一生成元ポリシーのことで、ざっくり言うと「他のWebサイトから持ってきてはいけない」というエラーです。

つまり、他所から持って来ていないように見せれば解決します。

#失敗例 ContentServiceを使ってみる
GASにはHTMLを表示するHtmlServiceに対してプレーンテキストなどを表示するContentServiceというクラスがあります。

Class ContentService
https://developers.google.com/apps-script/reference/content/content-service

これを使ってdoGetメソッドをURLパラメーターを渡したときだけWorker用のJSファイルを返すようにカスタマイズします。

```JavaScript:main.gs
function doGet(e) {
  const js = e.parameter.js;
  if (js != null) {
    const content = HtmlService.createHtmlOutputFromFile(js).getContent();
    return ContentService.createTextOutput(content).setMimeType(ContentService.MimeType.JAVASCRIPT);
  }
  return HtmlService.createTemplateFromFile("index").evaluate();
}
```

```HTML:index.html
<!-- 前略 -->
<script>
const url = "<?=ScriptApp.getService().getUrl();?>?js=worker.js";
const worker = new Worker(url);
worker.onmessage = console.log;
worker.onerror = console.error;
worker.postMessage("Test Message.");
</script>
<!-- 後略 -->
```

```JavaScript:worker.js.html
self.addEventListener("message", event => {
  self.postMessage(event.data);
});
```

しかし、これでも上手くいきません。
何故ならHTMLがインラインフレーム(iframe)で入れ子にされるからです。

![Screenshot 2020-05-25 at 18.10.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519665/0a8980e8-0924-67d9-65c7-d533199c6cec.png)

こちらで作ったHTMLは一番内側のiframe内に表示され、これが外側(アプリにアクセスするときに使うURL)と異なるドメインになっているため、結局また同一生成元ポリシーに違反します。

#成功例 文字列からBlobを起こしてObjectURLを生成する

所謂インラインワーカーを使います。

ウェブ ワーカーの基本
https://www.html5rocks.com/ja/tutorials/workers/basics/#toc-inlineworkers


GAS側にWorkerのソースコード文字列を返すメソッド(getCode)を定義します。
このメソッドをindex.html側でgoogle.script.runを使って呼びます。

```JavaScript:main.gs
function doGet(e) {
  return HtmlService.createTemplateFromFile("index").evaluate();
}

function getCode() {
  return HtmlService.createHtmlOutputFromFile("worker.js").getContent();
}
```

```HTML:index.html
<!-- 前略 -->
<script>
google.script.run
.withSuccessHandler( code => {
  const url = URL.createObjectURL( new Blob([code], {type:"text/javascript"}) );
  const worker = new Worker(url);
  worker.onmessage = console.log;
  worker.onerror = console.error;
  worker.postMessage("Test Message.");
})
.withFailureHandler(console.error)
.getCode();
</script>
<!-- 後略 -->
```

```JavaScript:worker.js.html
self.addEventListener("message", event => {
  self.postMessage(event.data);
});
```

以上。
コードはWeb Workerで説明しましたが、ES Modulesの場合はObjectURLを生成するところまでは一緒で、Dynamic Importを使えば同様に実現できます。

import - MDN - Mozilla
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Import

#余談
本当はgoogle.script.runはPromiseで処理するようにしたいところですが、本題から外れるのでこの記事では触れません。
~~気が向いたら書きます。~~ [書きました。][next]

[next]:https://qiita.com/37cohina/items/b3bb08d4c52c5e7e3022
ログイン、サインアップ画面のビュー変更

１．devise用のビューファイルを作成
　deviseでログイン機能を実装すると、ログイン・サインアップ画面は自動的に生成されるがビューファイルとしては生成されない。これは、deviseのGem内に存在するビューファイルを読み込んでいるため。

ビューファイルに変更を加えるためには、deviseのコマンドを利用してビューファイルを生成する必要がある。

ターミナルで
　rails g devise:views
　新規作成されるファイル
　app/views/devise以下のディレクトリにあるビューファイル各種

２．ログイン・サインアップ画面のビューファイルを編集する
　サインアップ画面
　app/views/devise/registrations/new.html.erb
　ログイン画面
　app/views/devise/sessions/new.html.erb
AWS SAA資格取得~EBSとEFS編~

##はじめに
SAA対策のWEB問題集で「EBS」と「EFS」の違いについて理解できていなかったため、
少しまとめたいと思います。

##EBSとは
永続可能なブロックストレージサービス。EC2インスタンスにアタッチすることで利用できる。
簡単にいうと**「EC2の仮想的に外付けされるHDD」**的なもの
※ブロックストレージとはデータを「ブロック」と呼ばれる細かい単位で分割して保管する方式。
EBSの拡張・タイプ変更は可能。縮小はできない。
拡張時に関してはEC2を停止せずに拡張！
⇨「大きめのEBSをアタッチしておき、あとで縮小を行う」ということはは実現できない。

##EBS特徴的機能
####複数のストレージタイプ
- **汎用SSD(General Purpose SSD:gp2)**
デフォルトで提供されているストレージタイプ。SSDを安価に利用することができる。
確保した容量に応じてIOPSが設定されており、OSのルート領域や、高性能なI/Oを
要求されないデータ領域で利用される。

- **プロビジョンドIOPS SSD(PIOPS:io1)**
高パフォーマンスを実現できるストレージタイプ。
SSDをベースにユーザが自由にIOPSを設定して利用することができる。
汎用SSDより高いパフォーマンスが求められる場合にも利用され、ストレージ容量に加えて、
指定したIOPSに対しても課金される。

- **スループット最適化HDD(st1)**
HDDタイプのストレージタイプで大容量のストレージを安価に利用することができる。
SSDのストレージタイプと比べて契約できる最低の容量が多くなっている。


####高可用性
EBSはS3のAZ間での複製とは異なり、AZ内で自動的に複製される仕組みを備えている。
単一のディスク障害を回避することができる。

####スナップショットによるバックアップ
EBSではスナップショットを用いてバックアップを取得することができる。
スナップショットは自動的にS3に保管される。⇨高い耐久性が備えられている。
オンプレミス環境のストレージではバックアップを取得完了するまで待たなくてはならない。
しかしEBSの場合取得を実行した時点で保管される。
初回はフルバックアップで取得し、以後は増分で取得する特徴がある。


##EFS(Amazon Elastic File System)とは
**「複数のEC２インスタンスから同時アクセス可能、容量無制限」**
スケーラブルな共有ストレージサービスで、複数のEC2インスタンスから
共有ファイルストレージとして利用することができる。
標準的なファイルシステムかでアクセスすることが可能。
そのためEC２だけでなくオンプレミスサーバーからも
利用することが可能。ストレージ容量や、パフォーマンスを自動的にスケーリングする機能も備えている。

価格は高いが、可用性や拡張性に優れている。
またEBSでは不可能であった複数EC2インスタンスとの共有ディスクとして利用でき、
データベースサーバーやファイルサーバのストレージとして利用用途が多い。

スナップショットのようなバックアップ機能を提供していないため、
別途バックアップを行う仕組みを組む必要がある。

##EBSとEFSの違いについて
簡単に
・接続台数
EBS：１台のEC2インスタンスと接続可能
EFS：複数のEC2インスタンスと接続可能
・耐久性
EBS：単一のAZ内で冗長化
EFS：複数のAZで冗長化
・拡張性
EBS：手動でボリューム拡張可能
EFS：自動でボリューム拡張可能
・料金体系
EBS:Gバイトあたりの従量課金（安）
EFS：Gバイトあたりの従量課金（高）

共通項としては
・接続：EC2インスタンスとネットワーク接続
・データ永続性：永続化可能
・パフォーマンス：高速

コストを許容できるならEFSがおすすめ（高パフォーマンス・高可用性で自動で拡張される。楽）
コストが積めない。パフォーマンス重視なら⇨EBS

##最後に
それぞれの特徴と、ユースケースを踏まえ理解を深めます。
あぁ〜〜〜〜先は長いなぁ〜
YAMAHA RTX1100でGCPとVPN接続

# 概要

YAMAHA RTX1210(RTX1200)の設定例は巷にいくつかあるものの、RTX1100 (IKEv1)での設定例が無かったので、備忘録として残しておく。

### 目的
Google Cloud Platformととある拠点をVPN接続すること。

VPN接続後、とある拠点からプライベートIPアドレスでGCPのCompute Engineにアクセスしたい。

### 環境
とある拠点はYAMAHA RTX1100を利用中。

インターネットは固定IP1の契約。

### 構成図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527863/573aee30-fbd9-8805-4edc-5e11e3af6961.png)


# GCPでのVPN設定

GCP管理コンソールから、「ハイブリッド接続」→「VPN」と辿る。

「VPN設定ウィザード」か「VPN接続を作成」をクリック。

### VPN接続の作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527863/15bb9884-59e0-69bc-1773-63b59ec77a69.png)

ルータが1台しかなく、トンネル2つ張るメリットもそこまでないため、今回は「Classic VPN」を選択して「続行」を押下。

### Google Compute Engine VPN ゲートウェイ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527863/7f8e09ea-4a61-2629-c9e0-9409cc8cec31.png)

- 名前：適当にわかりやすいもの
- ネットワーク：Compute Engineと同じネットワーク
- リージョン：Compute Engineと同じリージョン
- IPアドレス：**ここはGCPのVPNのゲートウェイとなるため、新たに静的IPアドレスを取得**　(構成図の2.2.2.2)

### トンネル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527863/7cd19467-20db-693e-d1ea-81ad39d44a85.png)

- 名前：適当にわかりやすいもの
- リモートピアIPアドレス：RTX1100のグローバルIPアドレス (構成図の1.1.1.1)
- IKEバージョン：RTX1100はバージョン1しか対応していないので、**IKEv1**を選ぼう
- IKE事前共有鍵：生成してコピー
- ルーティングオプション：ポリシーベース
- リモートネットワーク：RTX1100側のプライベートIPアドレスのNW (構成図の192.168.1.0/24)
- ローカルサブネットワークのIP範囲：GCPのVPCネットワークを選択 (構成図の192.168.2.0/24のNW)

「完了」および「作成」を押下する。

以上でGCPのVPN部分は終了です。

# YAMAHA RTX 1100設定

VPN接続部分のみ抜粋。

ルーティング設定

```
ip route 192.168.2.0/24 gateway tunnel 1
```

トンネル設定

```
tunnel select 1
 description tunnel To-GCP
 ipsec tunnel 10
  ipsec sa policy 10 1 esp aes-cbc sha-hmac
  ipsec ike always-on 1 on
  ipsec ike encryption 1 aes-cbc
  ipsec ike group 1 modp1024
  ipsec ike hash 1 sha
  ipsec ike keepalive log 1 on
  ipsec ike keepalive use 1 on icmp-echo 192.168.20.2
  ipsec ike local address 1 1.1.1.1
  ipsec ike nat-traversal 1 on
  ipsec ike pfs 1 on
  ipsec ike pre-shared-key 1 text 生成してコピーした事前共有鍵
  ipsec ike remote address 1 2.2.2.2
  ipsec auto refresh 1 on
 ip tunnel tcp mss limit auto
 tunnel enable 1
```

local addressの箇所はRTXのプライベートIPアドレスではなく、**グローバルIPアドレス**を指定します。


NAT設定

```
nat descriptor masquerade static 1 1 192.168.1.1 udp 500
nat descriptor masquerade static 1 2 192.168.1.1 esp
```



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

https://qiita.com/tkhroy/items/a90590d27745bd267ad9

# 追記

安定しない…

オンプレ側ルータの再起動等のタイミングでVPN切断→再接続の際に異様に時間がかかる現象に見舞われた。

接続しっぱなしであれば、切れたりしないみたいなんだが、う～ん。

以下の情報によるとGCPとYAMAHAのデフォルトのIKEのライフタイムに違いがあるようだ。

https://cloud.google.com/network-connectivity/docs/vpn/concepts/supported-ike-ciphers?hl=ja

おまじないとして以下の設定を追加してみた。

```
ipsec ike duration ipsec-sa 1 10800
ipsec ike duration isakmp-sa 1 36000
```

が効果の程は不明。

また、以下の情報によるとYAMAHAルータは相互運用ガイドになく利用推奨してないみたいだ。

https://cloud.google.com/network-connectivity/docs/vpn/how-to/interop-guides?hl=ja
GatsbyJS入門【GraphQL】

# GatsbyJSの入門書籍

下記の書籍でGatsbyJSの入門を行いました。

[GatsbyJS Guidebook - mottox2（つのぶえ出版） - BOOTH](https://booth.pm/ja/items/1312387)

書籍に沿って進めると、下記の流れで進めることができReact初心者でも特に躓くことなく進められます。

1. React + JSX
2. GatsbyJS
3. GatsbyJS + Headless CMS

しかし、GraphQLの箇所は難易度が高いと感じました。
もし、同じように困難を感じた方が「GatsbyJSやっぱり面倒くさい。。。」とならないように、
公式チュートリアルのGraphQL箇所を一読されることをオススメします。

# GatsbyとGraphQL

[公式チュートリアル「Data in Gatsby」](https://www.gatsbyjs.org/tutorial/part-four/)

上記チュートリアルパートは、GatsbyでGraphQLのごくシンプルなクエリを書くパートです。
下記引用にもあるように、GraphQLを使うことでGatsbyではデータ取得の作法を統一できるのですね。

> There are many options for loading data into React components. 
> (Reactコンポーネントにデータをロードするための多くのオプションがあります。)

## 補足

上記公式チュートリアルにもある通り、GraphQLは必須ではないようです。
`createPages`APIを使用すると、GraphQLをコンポーネントに書くことなくデータを渡せます。

[Gatsby without GraphQL](https://www.gatsbyjs.org/docs/using-gatsby-without-graphql/)

# GraphQLとGraphiQL

[公式チュートリアル「Source Plugins」](https://www.gatsbyjs.org/tutorial/part-five/)

上記チュートリアルでは、`gatsby-source-filesystem`プラグインを使用して
GatsbyJSプロジェクト内のファイルからファイル情報の一覧をGraphQL使って取得、出力します。

また、GraphQLのクエリを取得するためにGraphiQLを使用します。
GraphiQLの基本の使い方、ショートカットを覚えるとこができます。

紹介書籍を読んだ時は、内容について行けてなかったこともあり、GraphiQLの便利さがイマイチ理解できていなかったのですが、上記チュートリアルをこなすと、GraphiQLの便利さが分かります。

## 補足

もしかしたら、GatsbyJSでサイトを作る際は下記の流れで作成した方がデータの流れが分かりやすいかもしれません。

1. コンテンツ作成（ファイルでも、Headless CMSでも）
1. ソースプラグイン導入
1. GraphiQLでクエリ作成
1. GraphiQL「Code Exporter」でGraphQLクエリのコードをコピー
1. 上記のコードからコンポーネント作成
SpringBoot中Property和Message的加载顺序问题

### Spring boot中属性文件加载顺序

- spring.profiles.include=test1,test2 按照test1,test2的顺序进行加载
- 无论key定义在哪个文件中，最终生效的总是最后一次加载的key的值

### Spring boot 中message文件加载顺序
- spring.messages.basename=messages1,messages2按照messages1，messages2的顺序进行文件加载
- 定义在同一个文件中的相同messageId，总是后加载的有效（覆盖）
- 定义在不同文件中的相同messageId，总是先加载的有效（之前property文件已存在则后续相同key不加载）
Cognito認証でAWS ESのKibana 接続時のエラー[Something went wrong during authentication between Kibana and Amazon Cognito. ]



## tl;dr

自動作成された`Cognito_<name>Auth_Role`のRoleに対して権限が足りてないので、`es:ESHttp*` を追加する。

自動作成された`CognitoAccessForAmazonES `ではありませんので、注意です。（自分は、こっちに権限を割り当ててハマった）

## エラー内容

- `Something went wrong during authentication between Kibana and Amazon Cognito.`

- `User: x:x:x::xx:x is not authorized to perform: es:ESHttpGet`



## Ref

- [Kibana の Amazon Cognito 認証を使用した問題のトラブルシューティング](https://aws.amazon.com/jp/premiumsupport/knowledge-center/elasticsearch-authentication-kibana/)
PythonファイルをWindows10のコマンドプロンプトで実行する方法

## はじめに
Pythonのインストールがまだの人は、[こちらの記事](https://qiita.com/Futo_Horio/items/2bed334b07eab5e130e8)が分かりやすく手短に書かれていてオススメです。
ちなみに、筆者のPythonのバージョンは3.8.0ですが、Python3系であれば問題ないです。

## Pythonファイルの作成
まず、以下のスクリプトをテキストエディタなどにコピペして拡張子を.pyにして保存してください。ここでは、ファイル名をsample.py、保存先をDesktopフォルダの中とします。

```python:sample.py
print("Hello World!!")
```

Python3系では、print()と書くと、かっこの中のものを出力してくれます。文字列を出力したい場合はダブルクォーテーション""で囲みます。

## コマンドプロンプトの起動
Windows10では、画面左下にあるこの虫眼鏡を押してcmと検索すると、かんたんにコマンドプロンプトが見つかります。cmはコマンドの頭文字ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643696/7efde014-8e30-a313-fafd-6f5ffaf24faa.png)
虫眼鏡が画面左下にない場合は、タスクバーの上で右クリックして、検索アイコンを表示させてください。

## Pythonファイルの実行
コマンドプロンプトを起動できましたか？起動したら次のような画面が表示されていると思います。青色で隠してあるのは、筆者の名前です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643696/e5303099-60c7-46f7-d51c-85b274927bc2.png)
起動できていたら、ここで`cd desktop`というコマンドを打って、Pythonファイルがあるフォルダへ移動します。
Pythonファイルがあるフォルダへ移動できたら、`python sample.py`というコマンドを打ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643696/a5f8c4ec-59b0-9809-ddff-6e86e43f9774.png)
このようにHello World!!と表示されていたら、成功です！

## 終わりに
実は、Pythonファイルは直接ダブルクリックすることでも実行することが可能です。

しかし、この方法だとプログラムの処理が最後の行まで実行された後、ウィンドウが閉じられます。出力内容を確認するには、プログラムの最後の行に`input()`と書く必要があります。

また、`input()`と書いた場合でもプログラムに誤りがあった場合、その時点で強制的にウィンドウが閉じられるため、エラー内容が分かりません(コマンドプロンプトでは、エラーの内容と場所を教えてくれます)。

したがって、デバッグを楽にするためにも、Pythonファイルはコマンドプロンプトで実行するようにしましょう。
Best Digital Marketing Company in Lucknow Web and Pro Infomedia

Digital marketing is one of the fastest changing industries in the world and today’s digital marketing technology is more advanced than ever before. Automation and technology lets marketers do so much more in a fraction of the time. Technology helps us track, analyze and reach target customers.
According to a recent Forbes Insights survey, nearly 62% of brand and agency representatives around the world are satisfied with how well their current marketing technology is meeting their expectation and 57% plan to make new technology investments.
We have technology to help us understand customer behavior and characteristic trends. Growth in smartphone adaption and the popularity of mobile and messaging has exploded since 2005 with 50% of searches done on mobile. Artificial intelligence such as Facebook’s Bot Engine for Messenger, that offer consumer assistance, is one of the biggest trends of 2016. Marketing cloud solutions like Adobe, Salesforce, and HubSpot help us help us automate data across customer lifecycles.
VSCodeでDenoをコーディングする際の準備


巷で話題の[Deno](https://deno.land)はじめました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/95e5cff4-a587-4729-32ac-51d8337ed173.png)
↑かわいい

-----
うちのエンジニアの若い子たちも気軽に始められるように、少しずつDenoなコンテンツも書いていけたらなと思っています。まずはプログラムを書くための環境からということで[VSCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)でDenoを書くための準備をしましょう。

サンプルとしてGoogleにアクセスするコードを書いてみました。

```sample1.ts
import {Status} from 'https://deno.land/std/http/http_status.ts';

const result = await fetch("https://google.com");
if ( result.status === Status.OK ){
  console.log("OKですよ");
}else{
  console.log(`なんかエラーですよ:${result.status}`);
}

```
VSCodeを立ち上げておもむろにTypeScriptを書いていくと、エラーとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/6a64f5ae-3be0-c6ea-40fd-7d60adbe0958.png)

DenoのランタイムにはTypeScriptのトランスパイラが含まれるため、TypeScriptで記述することはできますが、VSCodeはDenoを知らないためエディタの支援機能を得ることができません。

試しに

```Shell
deno run --allow-net sample1.ts
```

とコマンドラインから起動すれば普通に動きます。

```Shell
$ deno run --allow-net sample1.ts
Compile sample1.ts
OKですよ
```

## VSCodeにjustjavac.vscode-denoプラグインを追加

VSCodeの左側Extensionsボタンを押して*Search Extensions in Marketplace*テキストボックスに**deno**と入力して検索すると該当のプラグインが見つかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/06c4c118-a1ce-e46c-c43d-380a4973b74a.png)

該当のプラグインを無効にする場合はコマンドパレットに

```
Disable Deno
```

逆に有効にする場合は

```
Enable Deno
```
と入力します。
既存のプロジェクトにも影響を及ぼしますので、Denoのプロジェクトは*Enable Deno*しておいて他のプロジェクトは*Disable Deno*しておいてくださいね。

では、一緒にDeno楽しみましょう。広がると良いですね!
WSLからWindowsのexeを拡張子なしで実行する

Windows Subsystem for LinuxからはWindowsのアプリケーションを直接実行する事ができます。PATHが通っていれば単純に
`$ explorer.exe`
とすればエクスプローラーが立ち上がります。しかし、必ず拡張子まで含める必要があります。
コマンドプロンプトから実行するときのように、拡張子を省略して実行する方法です。

## コマンドプロンプトで拡張子を省略できる理由

そもそも、なぜWindowsのコマンドプロンプトやPowerShellでは.exeや.cmdなどの拡張子を省略できるのかというと、コマンドが見つからない場合、PATHEXTという環境変数から拡張子のリストを読み込んで検索しているからです。この値はコマンドプロンプトから確認でき、筆者の環境では
`.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC`
となっていました。
これと同じことをすればできそうです。

## 実装

### Windows側の設定
WSLと環境変数を共有するにはWSLENVという環境変数を用います。
コントロールパネル等でPATHEXTをWSLENVに追加するだけです。
![pathext.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290493/114c636b-e86f-f6ac-61ea-4093a6231c79.png)

### WSL側の設定
コマンドが見つからなかった場合、PATHEXTから拡張子を取得して再検索するため、command_not_found_handleを利用します。すでに定義済みの場合は処理を挿入して再定義します。

```bash:.bashrc
if declare -f command_not_found_handle >/dev/null 2>&1; then
  eval 'command_not_found_handle() {
    local ext
    for ext in ${PATHEXT//;/ }; do
      if which "$1$ext" >/dev/null 2>&1; then
        "$1$ext" "${@:2}"
        return $?
      fi
    done
    '"$(declare -f command_not_found_handle|tail -n +2)"'
  }'
else
  command_not_found_handle() {
    local ext
    for ext in ${PATHEXT//;/ }; do
      if which "$1$ext" >/dev/null 2>&1; then
        "$1$ext" "${@:2}"
        return $?
      fi
    done
    printf "%s: command not found\n" "$1" 1>&2
    return 127
  }
fi
```

## 実行
余談ですが、NTFSはファイル名の大文字小文字を区別しないため、コマンド名の大文字小文字が違っていても実行できます。
![ubuntu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290493/caf37d48-141d-a325-519c-76c63c225038.png)

## おわりに
PATHが通っていれば補完が効くし、あまり意味はない気もする。

## 追記(2020/05/25 19:53)
いろいろといじっていたら短くなったのでそれも載せておきます

```bash:.bashrc
eval 'command_not_found_handle() {
  local ext
  for ext in ${PATHEXT//;/ }; do
    if which "$1$ext" >/dev/null 2>&1; then
      "$1$ext" "${@:2}"
      return $?
    fi
  done
  '"$(declare -f command_not_found_handle|tail -n +2)"'
  printf "%s: command not found\n" "$1" 1>&2
  return 127
}'
```

## 参考文献
[Linux との Windows の相互運用性](https://docs.microsoft.com/ja-jp/windows/wsl/interop#share-environment-variables-between-windows-and-wsl)
Android Studio activity_main.xmlでXMLではなくDesign Editorを使う方法

#はじめに
`activity_main.xml`を開くと、デフォルトでは視覚的に操作するDesign Editorが開くかと。ただし、たまに`XML`の表示になっていることがある。
**Android Studioを使い慣れていない方は、ここで戸惑うことがたまにある。。**

そんな時のための記事

#Design Editorに変更する方法
`activity_main.xml`を開く
<img width="1156" alt="スクリーンショット 2020-05-25 14.55.28.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/74945b7a-09a7-d67f-cff6-cada6b4d58c1.jpeg">

<img width="1118" alt="スクリーンショット 2020-05-25 14.55.41.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/2e8dafc8-fa89-7324-1a95-71f51af52d72.jpeg">

これでOK！

#参考
https://developer.android.com/studio/write/layout-editor?hl=ja
Db2 Warehouse on Cloud を利用するときのTips

#Db2 Warehouse on Cloud
クラウドで使えるDWHとしてIBM Db2 Warehouse on Cloudがある。
フルマネージドなので難しいことは考えずすぐに利用可能なのが利点であるが、オンプレのDb2ユーザーの観点からするとsshでの接続ができないなどの制約があり、オンプレで実施していた様々な方法をそのままでは利用できないことがある。
未来の誰かのためにTipsというか覚書として残しておく。

## バージョン情報の取得方法
通常のDb2であれば、db2cmdからdb2levelで情報を取得できる。
Db2WoCでは以下のSQLを発行して情報を取得する。

>SELECT T.SERVICE_LEVEL, T.RELEASE_NUM, T.BLD_LEVEL  FROM TABLE(ENV_GET_INST_INFO()) AS T
| DB2 v11.5.2.0 | 0603010F | special_39774 |

## Db2 Warehoue on Cloudの接続方法とバージョン
Db2WoCに対しては主に以下の方法で操作が可能：
- Webコンソール
- クライアントソフトウェアからのJDBC/ODBC接続
- Db2クライアント
- Db2Wh Client Container

クライアントソフトウェアであるが、Db2は共通エンジンなのでDb2 11.1に対応しているクライアントであればすべて問題なく接続できる。ただし、機能拡張の関係上、Db2のドライバは11.1 fp4以上が推奨されている。もちろん最新のドライバのほうが良い。

## アクセスプランのとり方
2年くらい前はアクセスプランを取ることができなかったが、現在ではオンプレと同様にアクセスプランを取ることができる。
1. ツールを使う方法
    GUIでDB操作が可能なDBeaverを利用する。ツールの画面から簡易的なアクセスプランを取得可能。
2. Db2をインストールしているマシンがローカルに存在する場合
    Db2クライアントであれば、db2explainを利用可能。ただし取得できる情報が少ないことに注意。
3. db2exfmt
    サーバーとしてインストールされていればdb2exfmtを利用することができる。詳細な情報を取れるので、可能であればこちらを利用する。

##外部表を利用した高速なデータロード
Db2 Warehouse on Cloudを利用するお客様の場合、多くはS3やiCOSといったオブジェクトストレージにデータをCSVで保管して、必要に応じてデータを読み込む、といった使い方をすることが多い。
この場合は外部表を使ってロードすると高速にロードできる。

>db2 "INSERT INTO <I>ターゲットテーブル</I> SELECT * FROM EXTERNAL 'loaddata/hoge.csv' USING (s3('endpoint url', 'authkey1','authkey2', 'endpoint') DELIMITER ',' )"

更に速度を出すためには、パーティションロードや並列実行といった手段を用いる。

##LIFTを使ったデータのロード
LIFTは既存のオンプレミスデータベースから、Db2 Warehouse on CloudにデータをロードすることができるCLI。
ダウンロードはhttps://www.lift-cli.cloud.ibm.com/。
データ型の対応もLIFTが自動で行うため非常に簡単にデータの移行をすることができるが、仕組み上遅い。
具体的には以下の手順となる。
1. ソースとなるデータベースからCSVでクライアントにアンロード
2. Db2WoCのランディングゾーンにCSVをアップロード
3. ランディングゾーンのCSVをロード (Db2ロードコマンド)

各手順には対応するLIFTのコマンドを利用するため、操作自体は非常に簡単ではあるので、最初に一度だけデータ移動をする場合や、データ移動に関わる時間の余裕がある時に利用すると良い。

## パイプを使ったデータロード

オンプレデータベースからデータを高速にデータの転送をしたいという要求がある。LIFTのように、通常はCSV経由でのデータ連携を行うが、CSV経由だとディスクI/Oがネックとなり時間がかかるのは避けられない。
これを解消するためパイプを使うことで高速にデータをロードできる。
以下はDb2のデータベースをソースの例として、2行目でソースとなるCSVを作成するために外部表での出力をしているが、異なるDBでも同様に出力先をパイプにすることで同様のことが可能。

>mkfifo <B>pdata</B>

>db2 "create external table '<B>pdata</B>' using (delimiter ',' ) as select * from <I>ソーステーブル</I>" &

>dbload -host <I>ホスト名</I> -u <I>ユーザー</I> -pw <I>パスワード</I> -df <B>pdata</B> -db <I>DB</I> -t <I>ターゲットテーブル</I>

DB間でのデータ転送を行う場合はデータ量がネックになることが多いので、パイプにGZやLZ4といった圧縮を利用してネットワーク使用量を減らすことも併用する。


## Db2ロードコマンドをする際にヘッダーを取り除く方法（パイプ）
Db2のロードコマンドを利用したロードは、統計情報の取得や文字数のカット、エンコード変換などができるので個人的には非常に好きなのだが、なぜかヘッダを含むCSVのロードに対応するオプションが無い(オプションを見逃していたらごめんDB2)。
ヘッダ行を無視すればよいだけなので、ロード実行後に1行エラーが出ていたら無視すればよいだけではあるのだが、ちょっと汚い。
そんなときに以下の方法でヘッダ行だけ無視する。
具体的には、1行目を抜いた結果をパイプに流し込むだけ。
>mkfifo <B>pdata</B>

>tail -n +2 $file > <B>pdata</B> &

>db2 "LOAD FROM <B>pdata</B> OF DEL INSERT INTO <I>ターゲットテーブル</I> NONRECOVERABLE"
AtCoderで使えるPython知識のメモ

#まえがき
AtCoderでよく使うなと思いながらも書き方を忘れたりする知識をメモとして残す意味合いもあって書いていこうと思います。説明が浅いので詳しく知りたい場合は他の記事なども見てください。　

#listの中にある要素が何番目にあるか検索
`if a in data`　などで変数aはdataのlistに含まれているかどうかの確認をすることがよくあります。ですが何番目に入っているか、というものを簡単に書いて返せるものがあればなと思っていたらあって感動したので紹介します。

```python:qiita1.py
box = [4, 2, 1, 0, 3]
print(box.index(3))
#4
```

このように`index()`を用いることで3という値は4番目にあるよという答えを返してくれます。


#多次元リストにてkeyを複数指定してsortする
見出しの言い方はとても難しいですが簡単に言えば多次元listをsortするときの優先順位を決めれるよって感じです。これでも難しいとは思いますが...

```
box = [[1,1,8], [8,6,4], [5,9,8]]
```
このような多次元リストがあった場合にふと、こう思うときがあると思います。
「昇順に並べたいけど**3番目の数字、1番目の数字、2番目の数字の順番で昇順**にしてほしいんだよなー」
こうなったときにlambda式が活躍します。


```python:qiita2.py
box = [[1,1,8], [8,6,4], [5,9,8]]

box_sort = sorted(box)
print(box_sort)
#[[1, 1, 8], [5, 9, 8], [8, 6, 4]]

box_sort = sorted(box, key=lambda box_i:(box_i[2], box_i[0], box_i[1]))
print(box_sort)
#[[8, 6, 4], [1, 1, 8], [5, 9, 8]]
```
こうするとできます。sortするときの優先順位が書く順番でsortするので結果も変わってきます
下の見出しにて類題がありますのでそちらもご覧ください。
lambda式についての説明は省きます。
参考文献([[Python] 多次元リストを複数キーでソートする](https://qiita.com/t_kanno/items/13dd226e70d080159d97))


#多次元リストにてkeyを複数指定して昇順、降順どっちもしたいとき

```
box=[[1,1,8], [8,6,4], [5,9,8]]
```
このような多次元リストがあった場合にふと、こう思うときがあると思います。
「3番目の数字、1番目の数字、2番目の数字の順番で**昇順、降順、昇順**にしてほしいんだよなー」
こうなったときは上の見出しではできないんじゃないの？？と思いますが

```python:qiita3.py
box = [[1,1,8], [8,6,4], [5,9,8]]

box_sort = sorted(box, key=lambda box_i:(box_i[2], box_i[0], box_i[1]))
print(box_sort)
#[[8, 6, 4], [1, 1, 8], [5, 9, 8]]

box_sort = sorted(box, key=lambda box_i:(box_i[2], -box_i[0], box_i[1]))
print(box_sort) 
#[[8, 6, 4], [5, 9, 8], [1, 1, 8]]
```
このように `-` をつけることで値に`-1`をかけるので大きい値ほど小さくなります。これを利用して降順昇順を合わせて使用することができます。[ABC128_B](https://atcoder.jp/contests/abc128/tasks/abc128_b)の問題ではこのlambda式を使って解くと勉強になる良い例題になるかと思います。

#辞書型を操りたい
Counterなどを使って辞書型を作った後その辞書型の処理の仕方にしばらく苦戦した覚えがあるので簡単に書こうと思います。
`keys()`：要素ごとのkeyだけ取り出せる。
`values()`：要素ごとの値だけ取り出せる。
`items()` ：要素ごとのkey、値の両方を取り出せる。
この三つを使って取り出したりforで回す場合に用いられたりします。

参考文献( [Pythonの辞書(dict)のforループ処理(keys, values, items)](https://note.nkmk.me/python-dict-keys-values-items/
) )


#最後に
最初なので丁寧な言葉遣いをしましたが次からは雑だと思います。
初めて投稿するので間違った情報やらマナーの悪いところがありましたらご連絡ください。
メモの意味もあるので雑な説明はご了承ください。

#追記　
strip()の内容に対する間違いがありました、前の記述ではエラーが出ると書かれているところには実際にはエラーが出ずわざわざstrip()を使う必要性もないことが判明しました
よってそこの記述は削除いたしました
不確かな情報の発信誠に申し訳ありません
Azure Machine Learning Studioで顧客離反予測をしてみよう~①概要編~

#本シリーズURL
①概要編：https://qiita.com/mottie/private/977a66ffb719453f62ee
②小売離反予測編:https://qiita.com/mottie/private/868798fb98e89fa43a08
③キャリア携帯離反予測編:https://qiita.com/mottie/private/0af8fe916a3ef04b0f2a
#はじめに
ここ数年、『機械学習』や『AI』という言葉を聞く機会が増えてきました。
多くの企業でこれらの技術を導入しようという動きが活発になり、事業の収益性を拡大しようとしています。
しかしいざ導入するにしても、どうすればいいか分かりにくいですよね。
本記事ではスムーズに導入ができるように、

- 機械学習を始めるにあたり最低限押さえるべき基礎(①概要編)
- 機械学習ツールとしてのAzure Machine Learning Studioの紹介(①概要編)
- Azure AI Galleryを使用した小売の離反予測(②小売離反予測編)
- キャリア携帯契約者の顧客離反予測(③キャリア携帯離反予測編)

の順に学んでいこうと思います。

#ターゲットとゴール
**ターゲット**

- 初めて機械学習に触れる人

**ゴール**

- 必要な知識を得てAzure Machine Learning Studioで実験をする

#機械学習をやる前に押さえるべきところ
###1.可能なアウトプット
機械学習でデータ分析をして可能なことは以下の5つです。

- **二者択一の判定**（AかBか、YesかNoか）
- **異常発見**(集団から仲間外れを見つける)
- **計量化、計数化**（どれだけあるのか、いくつあるのか）
- **分類化**（データからグループ分けする）
- **行動決定**（次に何をすべきか）

###2.必要なインプットデータ
データ分析には適したデータとそうでないものがあります。データの必要要件は4つです。

- **関連性がある**([例]東京のラーメンの平均価格とアフリカの出生率のデータを組み合わせても、何も分からない)
- **欠損が少ない**（ある程度のデータ欠損は何とかなるが、多すぎると分析できない）
- **正確である**（外れ値が多すぎると回帰分析できない。[例]急激なインフレ情勢では10年後の不動産価格の変動は予測しづらい）
- **データ量が十分である**（[例]画像分析をするのに写真が数枚しかないと分析できない）

###3.目標設定
データ分析にするにあたり、ゴールを決めなければなりません。
分析の目標を
**具体的に設定する**ことは絶対に忘れてはいけません。

[悪い目標と良い目標の例]

- 保有する株の価格がどうなるか分析したい（悪い目標、抽象的）
- **保有する株の価格が来週の金曜日にどれくらい変動しているか分析したい**（良い目標、具体的）

###4.どうやって予測するのか？
単回帰分析、重回帰分析、ロジスティック回帰分析、ランダムフォレスト、k-means、ブースティングなどなど。
非常に多様なものがあります。

今回の離反予測は最終的に「解約する」か「解約しない」という予想結果で表されます。
両者は0と1という数字で表現することができます。
こういった分析問題を**二値判別問題と言います。**
今回はその分析を実行するにあたって、ロジスティック回帰モデルとブーストデシジョンツリーモデルを利用します。
この二つの分析手法は続編の②小売離反予測編にて解説します。

###5.注意点
社会状況が変動すると、正確に予測することが難しくなることがあります。
例えば出生率の予測は非常に変動を受けやすいです。
出生率は、文化、経済、政策、食糧事情、女性の社会進出など様々な要素によって変動します。
しかし逆に社会的変動の影響を受けづらいものは長期的に信頼できる分析が可能でしょう。
天気予報などは比較的に影響を受けづらい部類だと言えるでしょう。

#Azure Machine Learning Studioとは何か？
Micro Soft製のプログラミング不要な機械学習ツールです。
データセットと学習モデルモジュールをドラッグアンドドロップで結ぶことでデータ分析をすることができます。
他のMicro Soft製品（Excel）などと相性がよく、それらのアプリで結果を表示できるのも特徴の1つです。

#Azure AI Gallery
Azure AI Galleryでは、Azure Machine Learning Studioで開発された機械学習分析システムが多数公開されています。
ユーザーはそのシステムをコピーし、独自のデータと交換するだけでデータ分析を実行することができます。

#終わりに
次回はAzure AI Galleryに掲載されている小売の離反予測の実装方法を解説します。
②小売離反予測編:https://qiita.com/mottie/private/868798fb98e89fa43a08

#参考URL集
**機械学習を初めてする人向けの公式動画**
https://docs.microsoft.com/ja-jp/azure/machine-learning/studio/data-science-for-beginners-the-5-questions-data-science-answers

**Azure Machine Learningについて**
https://docs.microsoft.com/ja-jp/azure/machine-learning/overview-what-is-azure-ml

**Azure Machine Learning　Studioについて**
https://docs.microsoft.com/ja-jp/azure/machine-learning/studio/

**Azure AI Galleryについて**
https://docs.microsoft.com/ja-jp/azure/machine-learning/studio/gallery-how-to-use-contribute-publish
Maxで数値と文字列の型変換

Max内部での取り回しでは必要になる事が特になかったが、外部とやり取りする時に型変換でハマったので備忘。

toSymbol / fromSymbol オブジェクトで可能。

![Untitled1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26386/134af293-a7e9-156c-1ce1-cac3a6047b58.png)
Content-Type: multipart/form-dataでファイルをUploadするときの注意点

めちゃめちゃハマったので自分用メモに書く

### `Content-Type: multipart/form-data` でファイルをUploadするときは、HeaderにContent-Typeを書かない

もしも書くなら、`Content-Type: multipart/form-data;boundary=~~`とboundaryまで書かないと死ぬ。
※Headerを省略しておくと、勝手に補完してくれる。

下手にform-dataまで書いて試してた結果全然動かない・・・・・・ってなったので
Ruby で解く AtCoder 第一回アルゴリズム実技検定 A 例外処理

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

# 今回のお題
*[AtCoder 第一回アルゴリズム実技検定 A - 2 倍チェック](https://atcoder.jp/contests/past201912-open/tasks/past201912_a)*
<font color="gray">Difficulty: ???</font>

今回のテーマ、例外処理

基本に忠実であれば`正規表現`で解答しますが、***Ruby*** をより深く理解するために`例外処理`で解答したいと思います。
# Ruby 正規表現
3文字とも数字だったらのパターン

```ruby1.rb
s = gets.chomp
puts (/[0-9]{3}/ === s ? s.to_i * 2 : 'error')

s = gets.chomp
puts (s.match(/[0-9]{3}/) ? s.to_i * 2 : 'error')
```
1文字でも英小文字だったらのパターン

```ruby2.rb
s = gets.chomp
puts (/[a-z]/ === s ? 'error' : s.to_i * 2)

s = gets.chomp
puts (s.match(/[a-z]/) ? 'error' : s.to_i * 2)
```
1文字でも数字以外だったらのパターン

```ruby3.rb
s = gets.chomp
puts (/[^0-9]/ === s ? 'error' : s.to_i * 2)

s = gets.chomp
puts (s.match(/[^0-9]/) ? 'error' : s.to_i * 2)
```
# Ruby to_i (WA)
`to_i`を直接適用したパターン

```ruby4.rb
s = 'abc'
puts s.to_i # => 0
s = '42A'
puts s.to_i # => 42
```
*[リファレンス](https://docs.ruby-lang.org/ja/latest/method/String/i/to_i.html)* に`整数とみなせない文字があればそこまでを変換対象とします。`とありますので、ここまでです。

# Ruby Rational (AC)
`Rational`を適用したパターン

```ruby5.rb
s = gets.chomp
begin
  Rational(s)
rescue
  puts 'error'
else
  puts s.to_i * 2
end
```
例外処理の制御構造は次の通りです。

```rescue.rb
begin
  # 例外が発生する可能性のある処理
[rescue [error_type,..] [=> evar] [then]
  # 例外が発生した時の処理
[else
  # 例外が発生しなかった時の処理]
[ensure
  # 例外に関係なく実行される処理]
end
```
`begin` `else` `ensure` は省略可能です。

普段はあまり使用しない`Rational`ですが、「1/3」のような有理数を扱うクラスです。
`to_r`ですと先頭の数字を解釈しますが、`Rational`ですと上手く例外が発生するようです。

```ruby6.rb
puts '0x8'.to_r     # => 0/1
puts Integer('0x8') # => 8
puts Float('0x8')   # => 8.0
puts Complex('0x8') # => ArgumentError
puts Complex('08i') # => 0+8i
```
`Complex`は複素数を扱うクラスで、`0x8`では例外が発生するのですが`i`を含む文字列はすり抜ける可能性があります。

標準出力する際に`to_i`を使用するのが心苦しいと申しますか、やはり普通に正規表現を使用するのがいいと思います。
# まとめ
+ 第一回アルゴリズム実技検定 A を解いた
+ Ruby に詳しくなった
+ 素直に正規表現を使用しましょう

参照したサイト
*[AtCoderでRuby学習8【第一回アルゴリズム実技検定 2倍チェック 】正規表現](https://qiita.com/jag_507/items/2eda3b3bf441c1b16baa)*
*[instance method String#to_i](https://docs.ruby-lang.org/ja/latest/method/String/i/to_i.html)*
*[class Rational](https://docs.ruby-lang.org/ja/latest/class/Rational.html)*
*[制御構造](https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#begin)*
[swift5] ボタンにセットした画像の色をコントロールする.

# 結論

以下のように, 「画像の読み込み時」にRenderingModeにalwaysTemplateを指定します. 

```swift

let img = UIImage(named: "test.png")?.withRenderingMode(.alwaysTemplate)

self.imgButton.setImage(img, for: .normal)
self.imgButton.tintColor = UIColor.green   //ボタンにセットした画像の色を緑にする.
```

# 注意事項
以下のように画像を取得してから, 違う行でRenderingModeを変更しても, 画像の色を変更することはできません. エラーは出ませんが, 画像取得時にRenderingModeを変更しなければならないようです.

```swift
////////////////////////////////////上手く行かない例///////////////////////////////
let img = UIImage(named: "test.png")

//ここ.
img?.withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
self.imgButton.setImage(img, for: .normal)
self.imgButton.tintColor = UIColor.green   
```


# 補足
UIImage.RenderingMode : 画像生成時(レンダリング)のモードを特定する.
alwaysTemplate : 入力画像のカラー情報を無視して, 画像を描画するようにする.
[参考]https://developer.apple.com/documentation/uikit/uiimage/renderingmode
CUIからJavaを実行する

# 記事作成の経緯

当方、Robert Simmons, Jr.の著作「Java™️魂」を学習しようと思ったのですが、
サンプルコードの実行がAntによるものでした。

Antの勉強をするにしてもコマンドオプションの設定など、
Javaのコマンドについての知識がないと最低限の学習も厳しいなと。
そんな感じでこの記事を書くことにしました。

# 第１章 Javaアプリケーションの作成に必要な作業

Javaアプリケーションを作成していると、主に以下の作業が発生します。
※今回はあくまで「Javaコマンド」について学習したいので自動テストなどは除外します

1. コードを書く
2. コンパイルしてクラスファイルを生成する
3. 実行する
4. JARファイルなどにアーカイブする
5. javadocを生成する

以降の章では、上Javaコマンドを使用して上記の作業を実際に行い、
各コマンドについて解説していきたいと思います。

実際に手を動かすという方は、
[こちら](https://commons.apache.org/proper/commons-lang/)からApache Commonsの```commons-lang3-x.xx.jar```
をダウンロードしておいてください。

# 第2章 Javaのコードを書く

当記事では、以下のサンプルを使ってJavaアプリケーションの実行を学びます。
なお、コマンドの説明用に以下の構成にしているだけなので、
ソースコードとして綺麗とは言い難いです。

サンプルコードでは、/java-sample直下に以下のようなフォルダ構成があるとします。
**※ルート直下で作業すると危険なので、任意のディレクトリを切って作業した方が安全です**

<img width="280" alt="スクリーンショット 2020-05-25 17.00.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/b8c7f8c1-275c-129b-1f98-57f9f0290231.png">

```java:UseCommons.java
package com.example.app;

import org.apache.commons.lang3.StringUtils;

public class UseCommons {
	// javaコマンドにUseCommonsを指定して実行した際に実行される処理
	public static void main(String[] args) {
		System.out.println(CommonsHelper.returnNgStrIfHasProbrem(null));
		System.out.println(CommonsHelper.returnNgStrIfHasProbrem(""));
		StrFactory strFactory = new StrFactory();
		System.out.println(CommonsHelper.returnNgStrIfHasProbrem(strFactory.sayHelloWorld()));
	}
	// インナークラスを定義した場合のコンパイル結果を見るためのヘルパークラス
	static class CommonsHelper {
		//CommonsのAPIを利用して、文字列が空、もしくはNullの場合に”NG"を返却する
		static String returnNgStrIfHasProbrem (String target) {
			if (StringUtils.isEmpty(target)) {
				return "NG";
			} else if (StringUtils.isBlank(target)) {
				return "NG";
			}
			return target;
		}
	}
}
```

```java:StrFactory.java
package com.example.app;

public class StrFactory {
	public String sayHelloWorld() {
		return "Hello World!";
	}
}
```

記事がいささかボリューミーになってきたので、以降は記事をリンクにして分割しました。

# [第３章 ソースコードをコンパイルする : javac](https://qiita.com/maple_syrup/items/f5e17eaf5483d0f4a9a8)

# [第４章 コードを実行する : java](https://qiita.com/maple_syrup/items/ce0d839624b56edcaaa5)

# [第５章 成果物をアーカイブする : jar](https://qiita.com/maple_syrup/items/a2f21fe356fa5f06bf44)

# [第６章：Javadocを生成する : javadoc](https://qiita.com/maple_syrup/items/96f7142222cd4eb5c9de)

# おわりに
以上、長々とJavaのコアツールについて書いてきましたが、これらの記事を読めば
最低限、Javaのコーディングから成果物の作成に関してはターミナルなどのCUIから
実行できるようになるのではないかと思います。

最後までお読みいただき、ありがとうございました。
既存の管理パッケージのソース形式への変換

開発者ドキュメントだけで手を動かそうとして地味に↓のエラーでハマったので備忘メモ
> ERROR running force:mdapi:convert:  This command is required to run from within an SFDX project.


### コマンドの流れ
1. プロジェクトDir作成
```sfdx force:project:create -n <SFDXプロジェクト名>```

2. ソース取得
```mkdir temp
sfdx force:mdapi:retrieve -s -r ./temp -u <ログインID> -p <パッケージ名>```

3. ソース展開
tempディレクトリ内に取得されたzipファイルを展開

4. 変換
```cd <手順1.で作成したSFDXプロジェクト名>
sfdx force:mdapi:convert -r ../temp```

### 参考
* [開発者ドキュメント](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_retrieve_man_pack.htm)
* [フォーラム記事](https://developer.salesforce.com/forums/?id=9060G000000MQqgQAG)
windows周りの備忘録

## 概要
いつもはlinux, macを主に使っていますが、windowsを使う機会があり、
その時の備忘録についてまとめていきます。


##記録たち

### 選択範囲のスクリーンショット
```
［Win］+［Shift］+［S］
```

また、このときスクショ画像はファイルとして保存されているわけではなく、クリップボードにあるので、ペイントなどを開いてコピーし、それを保存する必要あり。


### WSLを使いたいとき

Microsoft Store　で、ubuntuと検索し、好きなバージョンをダウンロードする。
ダウンロード後、launchをする。

### WSLをlaunchするときのエラー

```bash
WslRegisterDistribution failed with error: 0x8007019e The Windows Subsystem for Linux optional component is not enabled. Please enable it and try again.
```
powershell で、

```bash
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
```
を行う。この時、パーミッションで怒られる時がある、

そのときは、powershellを以下のように開きなおせばよい。

windowsマークより、タスクマネージャーへと飛ぶ。

ここでfileを選択し、
<img width="576" alt="test.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/87ab0759-faa4-911e-271d-7a3a39a6019b.png">

Run new task を選択し、powershellと入力し、
その際に下のアドミンでこのプログラムを開く、にチェックを入れること。

起動するとusername 及びpasswordを入れることができ、
だいたいubuntuのターミナルのような感覚で操作できる。


### WSL上でopenCV
```bash
sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev -y
```

```bash
$ sudo apt install python-dev python-numpy python3-dev python3-numpy -y
```

```bash
sudo apt install libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev libvtk5-qt4-dev libqt4-dev libqt4-opengl-dev libgtkglext1 libgtkglext1-dev libgtk-3-dev libatlas-base-dev gfortran -y

```

```bash
cd ~ &&\
git clone https://github.com/opencv/opencv.git &&\
git clone https://github.com/opencv/opencv_contrib.git &&\
cd ~/opencv && mkdir build && cd build &&\
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D WITH_OPENGL=ON -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules -D OPENCV_GENERATE_PKGCONFIG=ON ..
```

```bash
make -j7 && sudo make install
```

これで結果的にopencvが/usr/local/lib などに入ってくれるのでいいのだが、
もしこれをpythonから呼びたいだけの時は、

```bash

pip install opencv-python
```

が結局一番手っ取り早い。。


### WSL 状のファイルをvscode で編集し開発する
remote wsl の拡張機能をインストールする。
[Python] DFS（深さ優先探索）　ABC157D

#[ABC157D](https://atcoder.jp/contests/abc157/tasks/abc157_d)

UnionFind Treeが定石だが、初学者はまずDFSを習熟するべきと考える。単純な操作なら再帰関数を使わない。

参考
[ABC 157 D 問題の優しい解説](http://osora01.com/?p=226)

```python:サンプルコード
N, M, K = map(int, input().split())
F = [[] for _ in range(N)]
B = [[] for _ in range(N)]

# フレンドの隣接リスト
for _ in range(M):
    a, b = map(int, input().split())
    a, b = a - 1, b - 1
    F[a].append(b)
    F[b].append(a)

# ブロックの隣接リスト
for _ in range(K):
    c, d = map(int, input().split())
    c, d = c - 1, d - 1
    B[c].append(d)
    B[d].append(c)


# 交友関係グループ（辞書型）
D = {}
# グループの親
parent = [-1] * N
# 訪問管理
visited = [False] * N

for root in range(N):
    if visited[root]:
        continue

    D[root] = set([root])
    # 訪問先のスタック
    stack = [root]
    # 訪問先が無くなるまで
    while stack:
        # 訪問者をポップアップ
        n = stack.pop()
        # 訪問者を訪問済み
        visited[n] = True
        # 訪問者のグループの親を設定
        parent[n] = root

        # root のフレンドをグループと訪問先に追加
        for to in F[n]:
            if visited[to]:
                continue
            D[root].add(to)
            stack.append(to)

ans = [0] * N
for iam in range(N):
    # 自分の交友関係グループを設定
    group = D[parent[iam]]
    # グループからフレンドと自分を除く
    tmp_ans = len(group) - len(F[iam]) - 1
    # グループからブロックを除く
    for block in B[iam]:
        if block in group:
            tmp_ans -= 1
    ans[iam] = tmp_ans

print(*ans, sep=' ')
```
Wordpressで投稿タイプ、タクソノミー、カスタムフィールドを追加する

functions.phpにそれぞれの追加関数を書けば良さそう。
しかし、
カスタムフィールドは見た目がよろしくない。。。タイトルとかエディターみたいに出来ないの？

[関数リファレンス](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9)

この手のカスタマイズはプラグインが良いのかな？
どうなんだろうか。。。

ビジュアルエディターの場合は`'show_in_rest' => true`が必要！

# 投稿タイプを追加

register_post_type関数を使う。

```php:functions.php
function create_my_news_post_type() {
  register_post_type('my_news',
    array(
      'labels' => array(
          'name' => 'ニュース'
        , 'singular_name' => 'ニュース'
        , 'all_items' => 'ニュース一覧'
      )
      , 'description' => 'ニュースの投稿'
      , 'public' => true
      , 'show_in_rest' => true
      , 'menu_position' => 5
      , 'supports' => array(
          'title'
        , 'editor'
        // , 'page-attribute'
        , 'revisions'
      )
      // , 'hierarchical' => true
      , 'has_archive' => true
    )
  );
}
add_action('init', 'create_my_news_post_type');
```

# タクソノミーを追加

register_taxonomy関数を使う。

```php:functions.php
function create_my_brand_taxonomy() {
  register_taxonomy(
    'my_location'
    , array('my_news')
    , array(
      'labels' => array(
          'name' => '地域'
        , 'singular_name' => '地域'
        , 'add_new_item' => '新規地域を追加'
        , 'edit_item' => '地域の編集'
        , 'update_item' => '地域を更新'
        , 'parent_item' => '親地域'
        , 'search_items' => '地域を検索'
        , 'not_found' => '地域が見つかりませんでした。'
      )
      , 'description' => '地域の分類'
      , 'public' => true
      , 'show_in_rest' => true
      , 'show_admin_column' => true
      // , 'hierarchical' => true
    )
  );
}
add_action('init', 'create_my_brand_taxonomy', 0);
```

# カスタムフィールドを追加

add_meta_box関数を使う。

編集をするのに以下の関数も使う。
get_post_meta
update_post_meta
delete_post_meta

```php:functions.php
// カスタム項目
function create_my_news_fields() {
  add_meta_box(
      'my_copy_field'
    , 'キャッチコピー'
    , 'insert_my_copy_fields'
    , 'my_news'
    , 'normal'
  );
}
function insert_my_copy_fields() {
  global $post;

  echo '<textarea class="" name="my_copy_field" placeholder="キャッチコピーを追加" rows="1">';
  echo get_post_meta($post->ID, 'my_copy_field', true);
  echo '</textarea>';
}
add_action('admin_menu', 'create_my_news_fields');

function save_my_news_fields($post_id) {
  if (!empty($_POST['my_copy_field'])) {
    update_post_meta($post_id, 'my_copy_field', $_POST['my_copy_field']);
  } else {
    delete_post_meta($post_id, 'my_copy_field');
  }
}
add_action('save_post', 'save_my_news_fields');
```
FlutterのWidgetでOS判定を行う場合に dart:io.Platform を使うべきではない

FlutterでOS判定をする際、多くの記事で `Platform.isIOS` `Platform.isAndroid` を用いて解説されていますが、これは誤りを含んでいるように思います。
[ThemeData#platform](https://api.flutter.dev/flutter/material/ThemeData/platform.html) のドキュメントにはこう書かれています。

> Widgets from the material library should use this getter (via Theme.of) to determine the current platform for the purpose of emulating the platform behavior (e.g. scrolling or haptic effects). (中略) The dart.io.Platform object should only be used directly when it's critical to actually know the current platform, without any overrides possible (for example, when a system API is about to be called).
> 
> (訳) マテリアルライブラリのウィジェットは、プラットフォームの挙動（スクロールや触覚効果など）をエミュレートする目的で現在のプラットフォームを決定するのにTheme.ofを介してこのゲッター（訳注： `platform` のこと）を使用すべきです。(中略) dart:io.Platformオブジェクトは現在のプラットフォームを実際に知ることが重要で、上書きができない場合（例えばシステムAPIを呼び出そうとしている場合）にのみ直接使用すべきです。

つまり、Widgetの見た目を出し分ける目的では `Platform.is*` は使用するのは好ましくないということです。

このように書かれているのは、Flutterには[見た目を上書きできる機能](https://api.flutter.dev/flutter/material/ThemeData/platform.html)がありますが、OSの挙動にまつわる処理まで変更されてしまうことがないように `dart:io.Platform` の値は変わることがないからです。

代わりにWidgetでは、 `Theme.of(context).platform` で比較をすべきです。

```dart
Theme.of(context).platform == TargetPlatform.android
Theme.of(context).platform == TargetPlatform.iOS
```

こうすることにより、例えばAndroidの実機やエミュレータでデバッグしている状況でiOSのウィジェットの挙動も見たいときに、themeに1行追加するだけで確認できます。

```dart
MaterialApp(
  theme: ThemeData(
    platform: TargetPlatform.iOS,
    ...
  ),
  ...
)
```

（ちなみにDart DevToolsにPlatformをオーバーライドする機能もありますが、私の環境では動きませんでした）

もちろんシステムAPIを呼び出す部分はAndroidのままのため、実際に動くかiOS端末で確認する必要はありますが、iOSのビルドは比較的遅いため、ウィジェットの見た目のチェックでは役に立つかと思います。
vscodeにエラーがでた時の対処法

#初め：急にエラーがでた
ある日急に実行できなくなりエラー画面が出てきました
![2020-05-22 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638196/f31d3248-63c5-5a33-2021-110261d8088e.png)
どういうことかわからなかったので、アンインストールしました
#インストールできない
アンインストールしたはいいが次に
インストールの画面に行くとまたもやエラーが…
![2020-05-25 (7)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638196/10228950-f3e0-72fb-35df-3450e198cbb1.jpeg)
![2020-05-25 (8)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638196/33664e30-6bc7-94ac-d334-d59036542baf.jpeg)
何度もやり直しをしたが何度もこの画面が出てくる
むかついたのでパソコンのエクスプローラー内のvscodeに
かかわるものをすべて消していきました
#Microsoft Edgeで立ち上げる
今までなんとなくGooglechromeで立ち上げていたけれど
Miccrosoft Edgeで立ち上げようと思った
<img width="359" alt="2020-05-25 (9).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638196/e1b9dc59-183a-8ad3-f427-7981aaeb5a35.png">
↑Googlechromeで入れた場合こうなりました
<img width="960" alt="2020-05-25 (10).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638196/14c94a7d-70a0-9f7f-d74d-dc8ea9d52c67.png">
↑Miccrosoft Edgeでいれようとしました
[https://code.visualstudio.com/docs/?dv=win]
#２～３回入れ直し無事入れました
Miccrosoft Edgeで入れたほうが
都合がよいのかもしれないですね
皆様も急にエラーが出てきてもあせらず、ネットなどで調べ、
アンインストールして再インストールしてみてはいかがでしょう？
自動因数分解装置を作成してみよう／中学数学編　vol.1

# プログラミングを利用して因数分解できないか

**※改善あればWelcomeですので、宜しくお願い致します。**

勉強がてら自動因数分解装置を作ってみようと思い始めてみたが、ソースコードが美しくない。。。
ところどころ無理やり感満載ではあるが、中学基本数学レベルであれば因数分解できるソースは完成した。

因数定理から因数分解したほうが良いかもしれないが。おいおい分数が出ると困るので、地道にやるしかないのだろうか。

以下のソースコードを利用すれば、中学数学レベルであればコンピュータがやってくれるので、宿題がはかどるかも！？

おいおいは以下のような因数分解できるようになればなと思う。
STEP1はそんなに時間かからなそうではあるが、今日は疲れたので中学数学まで。

STEP1 : (a+c)x**2 + (ad+bc)x + bd = (ax+b)(cx+d)
STEP2 : 因数定理を活用した3次式の因数分解
STEP3：その他大学入試で出題されるレベルのものを網羅的に


以下のコードに入力値を渡せば因数分解の式が出力される。

【inputのルール】
①符号と式の間はスペースをあける
②1*x　の場合は、通常は1を省略するが、1x　と記載する

(例)
input
`x**2 - 20x + 96`
output
`(x - 12)(x - 8)`

input
`x**2 - 9`
output
`(x + 3)(x - 3)`

input
`x**2 - 4x + 4`
output
`(x - 2)**2`

```python

import math

a = 0
b = 0
jud1 = "+"
jud2 = "+"

nums = input().split()

if len(nums) <= 3:
    a = int(math.sqrt(int(nums[2])))
    print("(x + " + str(a) + ")(x - " + str(a) + ")")
else:
    if nums[3] == "-":
        nums[4] = int(nums[4])*(-1)
    
    li = list(nums[2].split("x"))
    
    if nums[1] == "-":
        li[0] = int(li[0])*(-1)

    for i in range(-100,100):
        if (i * (int(li[0]) - i)) == int(nums[4]):
            a = i
            b = int(li[0]) - i
    
    if a < 0:
        jud1 = "-"
        
    if b < 0:
        jud2 = "-"
    
    if a == b:
        print("(x " + jud1 , str(abs(a)) + ")**2")
    else:
        print("(X " + jud1 , str(abs(a)) + ")(x " + jud2 , str(abs(b)) + ")")
```

## 改善したいポイント
初学者が故に実は簡単な求め方があるかもしれないが、**各項の係数を簡単に取り出したい(できれば符号含め)**というのができればよりスマートに書けそうだなと思う。
また、`x**2 - 9`のように項が2つしかないパターンを無理やり

```python
if len(nums) <= 3:
    a = int(math.sqrt(int(nums[2])))
    print("(x + " + str(a) + ")(x - " + str(a) + ")")
```
としているところが一番気持ち悪い。
今のところは通過できているが、例えばおいおいx**3 - 8　みたいのが出たときに困るのでどうしたものかと考え中。