OmniAICreator/Qiita-1.07M huggingface dataset:
Canvas API の基本的な使い方

## はじめに

技術系同人誌を書くつもりでエディタを開いたのですが、何となくエタりそうな気がしたので、とりあえずこちらにまとまっている部分だけでもアップしようと思った次第です。[note](https://note.com/v416/n/n96cb85d72e1b) にも同じ内容をアップしています。

JavaScript で図を描き時の Canvas API の基本的な扱い方、注意点について述べています。なお、登場するメソッドの引数等の説明は行いません。メソッドについて詳しく知りたい方は [MDN](https://developer.mozilla.org/ja/docs/Web/API/Canvas_API) などで調べて下さい。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="v416" data-slug-hash="zYvbaWX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Canvas APIの基本">
  <span>See the Pen <a href="https://codepen.io/v416/pen/zYvbaWX">
  Canvas APIの基本</a> by よいち　ろくろう (<a href="https://codepen.io/v416">@v416</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

それでは、雛形となる html を用意しましょう。

```html:index.html
    <!DOCTYPE html>
    <html lang="ja">
     <head>
       <meta charset="utf-8"/>
     </head>
     <body>
       <canvas id="cvs">
       </canvas>
       <script>
       </script>
     </body>
    </html>
```

script タグを body の中に書いています。これから記述する JavaScript は、すべて script タグの中に書いて下さい。

## 直線を描く

canvas 要素は 2D レンダリングコンテキストというインスタンスを持ち、このオブジェクトが持つメソッドを使って図形、文字、画像といったものを描画します。手始めに 2D レンダリングコンテキストを取得し、直線を描いてみましょう。

    const canvas = document.getElementById('cvs');
    const ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.moveTo(10, 10);
    ctx.lineTo(50, 10);
    ctx.stroke();

canvas ではまずパスを設定し stroke メソッドを使って線を描画します。まず beginPath でパスの開始を宣言します。それから moveTo で始点を指定し lineTo で中間点を指定します。そして stroke を実行すれば直線が描かれます。

## 四角形を描く

点を結べば四角形を描くことができます。

    ctx.beginPath();
    ctx.moveTo(60, 10);
    ctx.lineTo(100, 10);
    ctx.lineTo(100, 50);
    ctx.lineTo(60, 50);
    ctx.closePath();
    ctx.stroke();

closePath は最後に指定した中間点と moveTo で指定した始点とを結ぶメソッドです。lineTo で始点を指定しても挙動は同じになります。

四角形は始点と縦横の幅が分かればいいので moveTo から closePath までをまとめた rect というメソッドがあります。そして塗りつぶしを行う時は fill メソッドを使います。

    ctx.beginPath();
    ctx.rect(110, 10, 40, 40);
    ctx.fill();

注意してもらいたいのは beginPath から fill/stroke まではひとまとまりのコマンドだということです。例えば以下のようなコードを組んだ場合、最初の四角形は枠線のみで次の四角形は塗りつぶしの描画を期待すると思います。

    ctx.beginPath();
    ctx.rect(10, 60, 40, 40);
    ctx.stroke();
    ctx.rect(60, 60, 40, 40);
    ctx.fill();

しかし、実行してみてもらえば分かる通り、両方とも塗りつぶしの四角形になります。ポイントは beginPath で、このメソッドがパスから描画までの一連の流れをリセットする命令になっています。なので stroke の後に beginPath を入れると想定通りの描画になります。

なお、四角形には beginPath から fill/stroke までをひとまとめにしためドッドも存在します。

    ctx.fillRect(160, 10, 40, 40);
    ctx.strokeRect(160, 60, 40, 40);

## 円を描く

今度は円を描いてみましょう。

    ctx.beginPath();
    ctx.arc(230, 30, 20, 0, 2 * Math.PI);
    ctx.stroke();

arc は円弧のパスを設定するメソッドです。このメソッドで気をつけたいのは、弧の始点座標です。

    ctx.beginPath();
    ctx.arc(230, 80, 20, 0, Math.PI / 2);
    ctx.stroke();

中心座標から右に半径分ずらした座標が始点になります。そして時計回りにパスが設定されます。角度の単位もラジアンになりますので、そこも注意が必要です。

早足でしたが、以上が Canvas API の基本的な使い方、注意点になります。次回はこれらを念頭に置いた、トランプ画像の描き方について述べるつもりです。

それでは。
C4346 "依存名は型ではありません"

# エラー
C++でコンパイルエラーが出力された。[Point Cloud Library (PCL)](https://pointcloudlibrary.github.io/) という外部ライブラリを利用しており、関数テンプレートの宣言の仮引数に問題があるようだ。

ソースの該当箇所

```c++
#include <pcl/point_cloud.h>

template<typename PointT>
void hoge(pcl::PointCloud<PointT>::Ptr);
```

コンパイラーのお言葉。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440643/1424e439-d334-16cd-136b-25daa4ebab9e.png" width="500">

# 問題の原因
"dependent name is not a type（依存名は型ではありません）"とは？  
[依存名 cppreference.com](https://ja.cppreference.com/w/cpp/language/dependent_name) より引用
> **依存名**
> テンプレート (クラステンプレートと関数テンプレートの両方) の定義内では、一部の要素の意味がある実体化と別の実体化で異なることがあります。 特に、型や式が型テンプレート引数の型や非型テンプレート引数の値に依存することがあります。

**確認１**　関数テンプレート`hoge`は`PointT`という型テンプレート引数をとる。
**確認２**　`pcl::PointCloud<PointT>::Ptr` は依存名である。  

> **名前探索のルール**
> テンプレートで使用される依存名の名前探索はテンプレートの実引数が判明するまで遅延されます。

**確認３**　宣言の段階で`PointT`の型は不明であり、依存名`pcl::PointCloud<PointT>::Ptr`も"不明"である。  
ここで言う "不明" とは、実体化されていないという意味ではなく、名前探索が未完で "型か変数であるかも知らない" という意味。

> **依存名に対する `typename` 曖昧性解消子**
> テンプレートの宣言または定義において、テンプレート仮引数に依存する現在の実体化のメンバでない名前は、キーワード `typename` を使用するか、すでに型名として確立されていない限り、型であるとみなされません。

**確認４**　上記の宣言の仕方では依存名`pcl::PointCloud<PointT>::Ptr`はコンパイラに型として認識されていない！

"依存名は型ではありません" の言葉とおりでした。関数の宣言における仮引数の記述なのだから型以外は普通来ないだろう、と思いたくなるがコンパイラ的にはNGだそう。

# 解決方法
どのようにしてコンパイラに依存名を型であると伝えるか？答えは既に出ていた。

以下[依存名 cppreference.com](https://ja.cppreference.com/w/cpp/language/dependent_name) より再掲。
> **依存名に対する `typename` 曖昧性解消子**
> テンプレートの宣言または定義において、テンプレート仮引数に依存する現在の実体化のメンバでない名前は、キーワード `typename` を使用するか、すでに型名として確立されている (例えば `typedef` 宣言や、基底クラスを表すために使用されているなどによって) のでない限り、型であるとみなされません。

### 1. `typename` で修飾する  
  問題となる依存名に`typename`をつければよい。

```c++
template<typename PointT>
void hoge(typename pcl::PointCloud<PointT>::Ptr);
```

### 2. あらかじめ型名として確定させる
`typename` `typedef` などで依存名を型として確定させておく方法。

```c++
// case 1
using PointCloudPtr = typename pcl::PointCloud<PointT>::Ptr;
// case 2
typedef pcl::PointCloud<PointT>::Ptr PointCloudPtr;
```

`PointCloudPtr` は型として認識されるので問題の依存名の代わりに使えばよい。  
  
PCL は様々なデータを保持する点の型に対応するためライブラリ全体がテンプレートで書かれており、2.の記述が多くみられる理由がようやく分かった。

## 補足
C++のテンプレートをよく理解していなかったのが大きな原因のひとつだった。  
[[Stack Overflow] Where and why do I have to put the “template” and “typename” keywords?
](https://stackoverflow.com/a/613132)で同様の問題を議論しており、かみ砕いて説明した分かりやすい回答があり、読んでおくと幸せになれる。
RevitをPythonで操作する備忘録　#0

# はじめに
Pytonを使ってRevitの自作アドインを作ってみよう！という話になり色々試しているなかで、
為になったこと、やったことを書き溜める場所を作ろうというのが最初の動機です。

元々別のテキストファイルに書きためていましたが、
他の人にも共有できたほうが、都合が良くなるかもしれないと思いQiitaに書いていく方針にしました。
文章を書くことが苦手なのでその練習も兼ねています。




# 環境設定
Qiitaに投稿されている先駆者の知恵[^1] をお借りしながら環境設定をしました。
ソフトバージョンは Revit2020、コーディングは Visual Studio code で進めていて、それにあたり、

 - pyRevit
 - pyRevit MEP
 - Revit Python Shell
 - Revit Lookup
 - Revit Python Wrapper

といったものをインストール済みです。


# 実現したいこと
### 自動で作図する
書きたいものはRevitの標準機能にないため、現状ではファミリをひとつひとつ作り、ひとつひとつ置いて作図する必要があります。
人力ではとても苦労する作業のため、これを自動化したいです。
### 自動でプロパティの設定をする
ひとつひとつファミリを触ってプロパティを変更していくなんて気の遠くなることをしたくないため、これも自動化したいです。
### 独自のUIを作る
自動化を試みるにあたり、設定画面など避けては通れない道だと思っています。




# 苦労したこと
### 環境設定に手間取る
一番最初に Revit Lookup と RevitPythonShell を入れようとして躓きました。
これは今後、別の記事にまとめようと思います。

### Pythonのバージョンの違いで戸惑う
Revitを操作しよう！となる前からPython自体の勉強は進めていて、自PCにはPython3.7とPython3.8を入れていました。
構文やライブラリもPython3系で勉強していたため、いざRevitでIronPythonを触り始めたときには細かいところでひっかかったことが多かったです。
たとえばList型を削除するときのやりかたでは、

```Python
# Python3系
list.clear()

# Python2.7
del list[:]
```

小さなことではありますが「3系で動いていたコードが動かない！」というのはストレスの種だったと思います。
また、Web上にあるサンプルプログラムはもれなく`print`に`()`がついていないのでとても違和感がありました。

### 先駆者が少ない
日本語で読めるPythonでのRevitAPI資料が少なく、調べ方が難しいです。
英語で書かれているドキュメントはけっこうありますが、英語が壊滅的に読めない私にとってはGoogle Translateさんの助けがあっても地獄です。

RevitAPIそのものについては公式ドキュメント等があるので基本的なところは学べますが、Pythonでとなると一気に情報が減ります…。
前途した記事[^1] には大変お世話になりました。

### 社内で同じ言語を学んでいる人がいない
弊社システム部門のみなさんはC言語で書くひとが多く、Pythonの疑問については自力で調べるほかありませんでした。
この自作アドイン計画も、私と、同チームの先輩の2人だけで手をかけ始めたのでかなり手探りです。

### Revitの操作が難しい
Revitの操作やオブジェクトの構造やどんなプロパティがあるかとか基本的な知識が乏しいです。
ただ先輩がかなりRevitに詳しいので都度助けてもらいました。

### 初心者がコードを書くことの恐ろしさ
 - そもそもIT系出身でない
 - 元は図面屋だったためコードを書く仕事をしてこなかった

→ 基礎が無さ過ぎるため恐ろしいほど汚いコードが生まれています。恐ろしい。
VBAやPythonRPAなどで細々と作ったことはあるものの、個人ベースで作られているためコードは見づらく、
プログラムを組む仕事をしてこなかったためにエラー処理がとても緩い状態です。
この辺のコーディング知識みたいなものもちゃんと身に付けていきたいと思っています。



# おわりに
具体的な内容などは別記事にまとめていく予定です。
ペースも不定期ですが、自分があとで見返すことができるような備忘録として、
また、誰かの小さな助けになるように書いていこうと思います。






[^1]: [pyRevitをはじめよう！Pythonで始める気軽なRevit開発](https://qiita.com/yishizu/items/6e812db233b7fa970555)
[メモ] AWS SAMのsam local start-apiでcode 400, message Bad ~と出る時は

## 事象

`sam local start-api` で `code 400, message Bad request version` とか `code 400, message Bad HTTP/0.9 request type` と表示されて文字化けしたメッセージが出てエラーになる。

## 対応

HTTPSでリクエストしていないか確認すること。
`sam local start-api` した場合 `http` でリクエストの受付が開始されるが、そこに `https` でリクエストするとこうなる。

なおDevツール等でよく見ると `net::ERR_SSL_PROTOCOL_ERROR` と出ている。
強く推奨されるChromeプラグイン 5選

Chromeブラウザは、シンプルなインターフェースと強力な機能でエンジニアに愛されています。Chromeは内部ブラウザーアプリケーションをサポートするだけでなく、さまざまな強力なプラグインも備えています。今回は、非常に使いやすいChromeプラグインをいくつかお勧めします。これらのプラグインを上手に使用すると、作業と学習の効率を大幅に向上させるでしょう！

####1.Sourcegraph
GoogleとFacebookは1億ドルを投資してSourcegraphを構築しました。Sourcegraphは、コード検索、コードレビュー、アラートと自動化のための標準で開発されたプラットフォームであり、各エリート開発チームがより優れたソフトウェアをより早くリリースできるようにしています。ourcegraphは現在、GitHubやGitLabなどの高品質のコミュニティをサポートしています。
![alt](https://jp.scrapestorm.com/wp-content/uploads/2020/04/1-1.png)

####2.Postman
Postmanは、強力なHTTPデバッグおよびシミュレーションプラグインです。CSS、HTML、スクリプトなどの単純なWebページの基本情報をデバッグできるだけでなく、ほぼすべてのタイプのHTTPリクエストを送信できます。 Postmanは、ネットワークHTTPリクエストを送信するChromeプラグイン製品の代表的な製品の1つと言えます。
![alt](https://jp.scrapestorm.com/wp-content/uploads/2020/04/2-1.png)

####3.Talend API Tester
Talend API Tester は、どんなに複雑であっても、すべてのHTTPリクエストを処理します。 変数を挿入することにより、リクエストを動的にすることができます。セキュリティと認証、およびハイパーメディアとHTMLフォームが完全にサポートされています。 HTTP応答を視覚化、事前設定、および検査できます。
![alt](https://jp.scrapestorm.com/wp-content/uploads/2020/04/3-1.png)

####4.SimilarSites
任意のWebサイトにアクセスするときは、検索バーの横にあるSimilarSitesアイコンをクリックして、アクセスしているWebサイトに関連する類似のWebサイト結果を10件取得します。 推奨される各Webサイトのホームページの画像、簡単な説明、Webサイトのタイトルを取得できます。
![alt](https://jp.scrapestorm.com/wp-content/uploads/2020/04/4-1.png)

####5.Octotree
Octotreeは、主に膨大な数のプログラマを対象とした、Githubプロジェクトのディレクトリ構造を表示するためのChromeプラグインです。Github上の何千ものオープンソースプロジェクトがプログラマに多くの助けをもたらします。ただし、特に1つのディレクトリから別のディレクトリにジャンプする場合、Githubでソースコードを表示するエクスペリエンスは非常に悪いです。 octotreeプラグインは上記の問題をうまく解決できます。
![alt](https://jp.scrapestorm.com/wp-content/uploads/2020/04/5-1.png)
【Swift】Realm Listのシャッフル


他は知らないがSwiftのRealmはshuffleがサポートされていない。

自分でシャッフルする。
それだけの記事。

```swift
func shuffle() {
    for _ in array {
        let swap1 = Int.random(in: 0..<array.count)
        let swap2 = Int.random(in: 0..<array.count)
        try! realm.write {
            list.swapAt(swap1, swap2)
        }
    }
}

```

まぁswapする回数はお好み。

どうやってシャッフルすればいいか結局小一時間悩んだ。
クソ時間な無駄ですね！！！
Dartで末尾一文字だけを削除する

## やりたいこと

`hoge/foo/bar/` という文字列から末尾`/`を取り除き、`hoge/foo/bar`としたい。

## やり方
```dart
final str = 'hoge/foo/bar/';
// 末尾'/'の場所を返す
final pos = str.length - 1;
// 最初からposまでの部分文字列を取得
final result = str.substring(0, pos);
print(result);
// hoge/foo/bar
```

## 参考
[dart - Flutter - Remove String after certain character? - Stack Overflow](https://stackoverflow.com/questions/59763793/flutter-remove-string-after-certain-character)
Swift the realm is already in a write transaction

the realm is already in a write transaction と言われたとき。

realmの処理が落ちきっていないんですかね。処理自体は完遂されていると思うんですが。
僕にはわからん。

```swift
try! realm.write {
    /* ... */
    realm.cancelWrite() // 処理を止めて
    realm.beginWrite() // また始める
    /* ... */
}
```

これでエラーが出なくなった。
エラーが起こる原因もこれで通る理由もよくわかっていないのは釈然しないがどうしてもというときは。
リリースまでの流れ

# ビルド
様々なソースコードを機械語に翻訳し一つにまとめ、実行ファイルにすること
これをすることでデプロイに必要な実行ファイルを作れる

# デプロイ
開発したシステムを使える環境に移行し、実際に使用可能な状態にすること

>SESであればお客さんが使える状態
>自社開発であれば、社内で使える状態

#リリース
リリースとは開発したものを公開すること
本番環境に移行することで、ユーザーが使用可能になる

- リリースの中にはプレリリースや本番リリースがある
 - プレリリース：完全な状態ではないが使える状態
 - 本番リリース：完璧な状態


# リリースまでの流れ
リリースまでの流れを簡単に表すと　

1.ビルド
2.デプロイ
3.リリース

このような流れになる

# まとめ
全て似たようなものだが一つ一つみていくと違うものなので、今後詳しく勉強していきたい。
Visual Studio CodeでライブラリをインストールしたのにUnable to import 

# ライブラリをインストールしたのにUnable to import 

Djangoでバージョンを合わせたのにvscodeにずっと指摘されたのでその原因と解消方法を書いておきます。

#原因
**実行環境とVSCodeの仮想環境が異なる**からです。

例えば、A,BというPythonの仮想環境があったとしましょう。

Aの方にライブラリをインストールしたとしてもBの方をつかってVSCodeで動いていたらそりゃ指摘されますよねってことです.

# 解決策

1. 左下の**PythonのVersion**が書いてある部分を押します。
![Sept19-Linting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593429/0fc98d8c-e1ad-fc99-014b-a991c644d4a0.png)


2. 複数環境が出てくるので実行してる環境に合わせてあげることで指摘は消えるはずです。お疲れ様でした。


## 参考
https://stackoverflow.com/questions/48270385/vs-code-error-when-importing-django-module
PyQt5がWindowsでうまく開けなかった話

常識なのかもしれませんが、ちょこっとだけ詰まったので書きます。

# 問題のコード
```py:Raspbian
# このコードだと、Windows10で起動できなかった
qtCreatorFile = "ir_post_v2.ui"  # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
```
上記のコードの状態で実行するとエラーが発生する。
>例外が発生しました: FileNotFoundError
[Errno 2] No such file or directory: 'ir_post_v2.ui'

# 解決したコード
```py:Windows10
# このコードだと、Raspbianでも起動できた
from os.path import (join, dirname)

qtCreatorFile = join(dirname(__file__), "foobar.ui")  # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
```

<a href="https://www.amazon.co.jp/Qt-Quick%E3%82%B9%E3%82%BF%E3%83%BC%E3%82%BF%E3%83%BC%E3%83%96%E3%83%83%E3%82%AF-%E6%8A%98%E6%88%B8-%E5%AD%9D%E8%A1%8C-ebook/dp/B07B4D87WS/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=pyqt5&qid=1589792407&sr=8-4&linkCode=li2&tag=gokuseijo-22&linkId=7d9fbf2a30fc7b57d546659b324beb59&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B07B4D87WS&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=gokuseijo-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=gokuseijo-22&language=ja_JP&l=li2&o=9&a=B07B4D87WS" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
ATmega328PBでArduinoのWire(I2C)ライブラリを使う際の留意事項

ATmega328PBはArduinoUNO等に用いられているATmega328Pの後継です。
後方互換性があるので大体のコードはそのまま動くのですが、Wire(I2C)ライブラリについては修正が必要となります。

## 修正箇所

ATmega328PBはATmega328Pと比較してI2Cインターフェイスが1系統から2系統へ増えています。そのため、レジスタと割り込みベクタの呼称が少し変更されています。Wireライブラリ内の`twi.h`に以下の定義を追加することで対応することができます。

``` twi.h
#define TWBR TWBR0
#define TWSR TWSR0
#define TWAR TWAR0
#define TWDR TWDR0
#define TWCR TWCR0
#define TWAMR TWAMR0
#define TWI_vect TWI0_vect
#define TWI_vect_num TWI0_vect_num
```

要するに連番が追加されただけです。連番を弄れば別のI2Cインターフェイスを割り当てることができると思います。特に割り込みベクタの定義(`TWI_vect`)は修正を忘れていてもコンパイルが通ってしまうので要注意です。

## 補足

- ArduinoIDEの代わりにAtmelStudioを用いています。プロジェクト毎にArduinoIDEからライブラリをコピーしてくるので、元のライブラリを破壊せずに済みます。また、debugWIREが非常に便利です。Atmel-ICEは少々お高いですが(秋月で1万円)。。。
- AtmelStudioでのプロジェクト作成時は、"Arduino Pro or Pro Mini"を選択しました。プロジェクトを作成したら、Project->Properties->DeviceをATmega328PBに変更してあげます。プロジェクトは2つ("ArduinoCore"と自分が名付けたプロジェクト)生成されるので、両方について変更します。
- SPIも増えているので同様の問題が発生するかもです（未確認）。UART(Serial)も増えていますが、こちらは問題なく動作するようです。
【Python】Excelと同じ切片0の近似式の算出方法【scikit-learn】メモ

# 概要
* Excelには、切片固定で近似式を算出する方法がある
* numpy.polyfitでは、切片固定ができない。
* scikit-learnのLinerRegression,make_pipeline,PolyFeaturesで実現する

# Excelの場合
* 赤線部分の設定を行えば切片を固定できる（青プロットの近似式）
* 今回は固定値を0とした。
![qiita_20200518.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148213/c3d971ae-d91b-0b54-d762-b6bfa473cf7e.jpeg)

# Pythonの場合
```python:pandas+scikit-learn
from sklearn.linear_model import Ridge,LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

# Excelと同じデータを作成
x=np.array([0,3,12.5,18.7,25,20,16,12.8,10.24,8.192])
y=np.array([0,15,46.6,60.3,74.3,59.44,47.552,46,36.8,29.44])

# DEGREE（次数）
degree = 3

# LinearRegression
# make_pipelineでPolynomialFeaturesとLineaRegressionをがっちゃんこ
model = make_pipeline(PolynomialFeatures(degree,include_bias=False),LinearRegression(fit_intercept=False))
model.fit(x.reshape(-1,1),y)
y_model=model.predict(x.reshape(-1,1))

#データフレームの確認
df = pd.DataFrame({'y_model.predict':y_model,},index=x)
df.sort_index().plot(kind ='line',figsize=(10.,5.))

# 係数
model.steps[1][1].coef_
```

* よく似たグラフになりました。
![qiita_20200518-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148213/6f22bb45-7378-1c09-83bf-15420c3c728d.png)

* 係数一致（ほぼ）

```text
array([ 5.06817229e+00, -1.71343566e-01,  3.49200227e-03])
```

# まとめ
* numpyのpolyfitではできなかったけど、scikit-learnでできてよかった。
* Excelの代替手段としてPython使ってるときに困ったのでメモ
CircleCIのContextがCLIから触れるようになったのでメモ


CircleCIはAPIが公開されていますが、ContextはAPIがずっと公開されていませんでした。
1年半ほど待ちましたがようやくCLI（だけ？）が公開されましたので、Contextの入れ替えが少しだけ楽になりました。

https://github.com/CircleCI-Public/circleci-cli/pull/362

コマンドの説明がほぼ見当たらなかったので忘れないようにメモしておきます。

# help

```
$ circleci context --help
Contexts provide a mechanism for securing and sharing environment variables across projects. The environment variables are defined as name/value pairs and are injected at runtime.


Usage:
  circleci context [command]

Available Commands:
  create        Create a new context
  delete        Delete the named context
  list          List all contexts
  remove-secret Remove an environment variable from the named context
  show          Show a context
  store-secret  Store a new environment variable in the named context. The value is read from stdin.

Flags:
  -h, --help   help for context

Global Flags:
      --host string    URL to your CircleCI host, also CIRCLECI_CLI_HOST (default "https://circleci.com")
      --token string   your token for using CircleCI, also CIRCLECI_CLI_TOKEN
Use "circleci context [command] --help" for more information about a command.
```

# Context 一覧
vcs-typeは github や bitbucket などらしいです。oraganizationはCicleCIのOrgを入れましょう。

```
$ circleci context list <vcs-type> <organization>
+----------+--------------+--------------------+--------------------------+
| PROVIDER | ORGANIZATION |        NAME        |        CREATED AT        |
+----------+--------------+--------------------+--------------------------+
| github   | oreno-org    | context-a          | 2019-12-18T01:51:06.584Z |
| github   | oreno-org    | context-b          | 2019-09-24T02:03:04.904Z |
| github   | oreno-org    | context-c          | 2019-09-24T11:29:52.765Z |
| github   | oreno-org    | context-d          | 2019-09-25T06:15:32.103Z |
| github   | oreno-org    | context-e          | 2018-09-04T09:51:11.838Z |
| github   | oreno-org    | context-f          | 2019-12-18T01:50:58.478Z |
| github   | oreno-org    | context-g          | 2017-10-11T12:56:04.010Z |
| github   | oreno-org    | context-h          | 2019-11-21T01:11:04.974Z |
+----------+--------------+--------------------+--------------------------+
```

# Context自体の作成、削除
```
$ circleci context create <vcs-type> <organization> <context-name>
$ circleci context delete <vcs-type> <organization> <context-name>
```

# Contextの中身の確認、作成、削除
```
$ circleci context show <vcs-type> <organization> <context-name>
Context: context-a
+-----------------------------------------+--------------+
|          ENVIRONMENT VARIABLE           |    VALUE     |
+-----------------------------------------+--------------+
| AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA          | ••••4Q6      |
| BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB          | ••••QEQQ     |
| CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC          | ••••O01A     |
+-----------------------------------------+--------------+

$ circleci context remove-secret <vcs-type> <organization> <context-name> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

$ circleci context store-secret <vcs-type> <organization> <context-name>
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
Enter secret value and press enter: <ここにvalueを入れる>
```
Ruby rails コマンドや　repecコマンドが使えなくなった時の話

## 概要
こんにちは

先日、Laravelの環境構築でhomebrewなどいろいろいじっていたら
Railsのプロジェクトで

```
rails s
rails c
rspec
```
みたいなコマンドが一通り使えなくなった。

## rails sできない

rails s　すると

```
You've tried to invoke Spring when it's already loaded (i.e. the Spring constant is defined).

This is probably because you generated binstubs with Spring 1.0, and you now have a Spring version > 1.0 on your system. To solve this, upgrade your bundle to the latest Spring version and then run `bundle exec spring binstub --all` to regenerate your binstubs. This is a one-time step necessary to upgrade from 1.0 to 1.1.

Here's the backtrace:

/Users/username/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.0.7.2/lib/active_support/dependencies.rb:287:in `load'
/Users/username/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.0.7.2/lib/active_support/dependencies.rb:287:in `block in load'
/Users/username/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.0.7.2/lib/active_support/dependencies.rb:259:in `load_dependency'
/Users/username/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.0.7.2/lib/active_support/dependencies.rb:287:in `load'
/Users/username/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `<top (required)>'
/Users/username/.rbenv/versions/2.5.1/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/Users/username/.rbenv/versions/2.5.1/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/Users/username/projects/bookcafe-review-app/bin/spring:16:in `<top (required)>'
bin/rails:5:in `load'
bin/rails:5:in `<main>'
```

いろいろ調べた結果
[この記事](https://stackoverflow.com/questions/59006602/dyld-library-not-loaded-usr-local-opt-openssl-lib-libssl-1-0-0-dylib)の

```
brew switch openssl 1.0.2s
```

このコマンドをすると

rails s 
rails c
できるようになった。

一安心と思いきや
次は

## rspec できない

rspecコマンドを実行すると
db exist みたいなエラーが出たので、
test用のdbをリセットしてみたり試みたが
permission errorになる(errno: 13)

次は
[この記事](https://masahiro.me/2017/01/homebrew%E3%82%92%E3%81%84%E3%81%98%E3%81%A3%E3%81%9F%E3%82%89-mysql2error-cant-read-dir-of-errno-13-permission-denied-show-tables-like-schema_migrations-%E3%81%8C%E5%87%BA%E3%81%A6/)より

```
sudo chown -R _mysql /usr/local/var/mysql
```

で権限を与える

phpをインストールすると権限が変わったみたいです。

ようやく正常に動きました。
Verilogで書いたコードで基盤のランプを点滅させる！

最近研究室でVerilogを触り始めたので、メモがてらこちらの記事を書こうと思います。

## 環境
Windows 10
Quartus Prime Lite 17.0
EPM1270T144C3N
USB Blaster

Quartusは2020年現在19が最新だと思いますが、私は諸事情で17を使っています。

## Pin Assignment

AssignmentsからPin Plannerを開きます。

![屏幕截图(15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/0ee2397c-478c-5205-badd-9d2941bca8d0.png)

下のほうに`Node Name`と`Location`があるのでこちらを設定していきます。今回は試してみるだけということでノードの名前はすべて`example`で始めることにしました。`PIN_143`などのピン番号はあらかじめ設計図などを見たもので、143は基板の左端のランプにつながっていることから選択しました。

![屏幕截图(16)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/bef46ba0-b419-054b-94e7-3bf5014f92f4.jpeg)


## Verilogのコード

```verilog:area_project.v
module area_project(
    output example_144, output example_143, output example_142
);

assign example_144 = 1;
assign example_143 = 1;
assign example_142 = 1;

endmodule
```

上記のファイルではとりあえず`1`をアウトプットさせて、ランプをオンにするようにしています。ここで`0`とした場合はランプはオフのままとなります。

ファイル名とモジュール名は同じにしておかなければいけません（今回だと`area_project`）。そうしないとコンパイルの際に以下のようなエラーが出ます。

```
error top level design entity is undefined
```

## コンパイル、そしてダウンロード

コンパイルを行うには以下のスクショの赤い丸で囲んだ青いボタンを押します。

![屏幕截图(7)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/06d7e2b6-32e9-6d41-6640-b26fd05528d8.jpeg)

ここでコンパイルが成功すれば、プログラマを押して、コード命令をダウンロードすることになります。

![屏幕截图(8)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/41bf8eae-aa9d-3c72-c030-5ef8048f22b5.jpeg)

このときにデバイスが検出されていない場合は`auto detect`ボタンを押してデバイスを検出します。（検出できない場合もありますが面倒なのでまた別の記事で書きます。）

ここで以下のようにProgram congifuration, verify, blank-checkの３つにチェックをチェックボックスに入れると、`start`ボタンが押せるようになると思います。

![屏幕截图(9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/c8c0cff7-0717-85b4-d5b0-dfe9a76af8ae.png)

start ボタンを押すとダウンロードが始まります。ダウンロードの進捗は右上のバーからチェックできます。

![屏幕截图(12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/9455b6b6-a0ce-eb6f-ebb3-1ad9d6adc6f3.png)

ダウンロードしている間はUSB blasterも青色に点滅するので、そこからもダウンロードしていることが確認できます。

## 結果

以下のように二つランプを点灯させることができました！
あれ、なぜ3つじゃないのか、と思ったのですが（自分の誤解で） `PIN_143`はランプにつながっていないからでした。
撮るのが意外と大変だった、、、

![IMG_4410.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/f4ad7afc-7c24-7bf9-92e0-2144a6030d1c.jpeg)
deviseを使ったユーザー登録

今回はdeviseを使ったユーザー登録の流れを！
忘れないように自分用です。

# deviseとは
　ユーザー管理機能を簡単い実相するためのgem。

# Gemfileに追記する
```gem 'devise ```を最終行に追記。
その後、プロジェクトディレクトリで
```bundle install```

# deviseの設定ファイルを作成。
ターミナル
```$ rails g devise:install```
・config/initializers/devise.rb
・config/locales/devise.en.yml
上記のファイルが作成される。

# deviseの機能を持ったUserモデルを作成。
deviseを利用する際にはアカウントを作成するためのUserモデルを新しく作成します。通常のモデルの作成方法ではなく、devisdeのモデル作成用コマンドで作成。
①userモデルの作sでい
ターミナル
```$ rails g devise user```
・app/models/user.rb
・db/migrate/20XXXXXXXXXXXX_devise_create_users.rb
・test/fixtures/users.yml
・test/models/user_test.rb
上記ファイルが自動で作成され、config/routes.rbに以下の記述がされる。
```Rails.application.routes.draw do
  devise_for :users```
この記述により、ログイン・新規登録に必要なルーティングが生成されます。

②userテーブルの作成
ターミナル
```$ rails db:migrate```
userテーブルが作成されているのを確認できればOK！

# 新規登録/ログインの実装
手順は以下の通り、
1.未ログイン時のボタン設定
2.未ログイン時・ログイン時でボタン表示の変更
3.devise用のビューを作成する

1.未ログイン時のボタン設定については、ビューの装飾を変更するだけなので割愛。

# 2.未ログイン時・ログイン時でボタン表示の変更
こちらを変更できようにするのが、user_signed_in?メソッド
# user_signed_in?メソッドとは
deviseでログイン機能を実相する際に使用できるメソッドで、ユーザーがサインインしているかどうかを検証するためのメソッドです。
サインインしている場合はtrueで返し、サインインしていない場合は、falseで返します。
```<% if user_signed_in? %>
          <%= link_to "新規投稿", [prefix], class: "" %>
          <%= link_to "ログアウト", [prefix], method: :delete, class: "" %>
<% end %>```
user_signed_in?が返す値は最終的に、trueかfalseになるおで、上記の例のようにif文またはunless文とともに使用します。

# devise用のビューを作成
deviseのコマンドを利用してビィーファイルを生成すると、簡単い新規登録画面とログイン画面が作成できます。
ターミナル
```$ rails g devise:views```
新規登録画面：app/views/devise/registrations/new.html.erb
ログイン画面：app/views/devise/sessions/new.html.erb
というビューファイルが対応。

# ユーザー名も登録できるようにする。
deviseの初期状態では、nicknameカラムは作成されないため、もし必要であれば以下のコマンドでuserテーブルにnicknameカラムを作成する。
```# usersテーブルにnicknameカラムをstring型で追加するマイグレーションファイルを作成
$ rails g migration AddNicknameToUsers nickname:string```

```# マイグレーションファイルの実行
$ rails db:migrate```

# configure_permitted_parametersメソッド
deviseの初期状態でサインアップ時にメールアドレスとパスワードのみ受け取るようにストロングパラメーターが設定してあるので、上記で追加したキー(nickname)のパラメーターは許可されていない。
追加のパラメーターを許可したい場合は、application.controller.rbにおいて以下の記述をする。
```class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?```
```protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
end```

# current_userメソッド
current_userメソッドは、deviseのヘルパーメソッドで、ログイン中のユーザー情報を取得できる。
idを取得したい場合、```current_user.id```記述
Cygwin X サーバー (XWin) で英語キーボードにされてしまう現象を回避

CygwinのXサーバーを -rootless で起動すると、勝手に英語キーボードにされてしまう（良く知られた？）現象に遭遇。以下の手順で解消した。
#### 日本語配列キーボードの設定
ホームディレクトリに、設定ファイル .XWinrc を作成し、以下を記述。

```
XKBModel jp106
XKBLayout jp
```
これで、Xクライアントでキーボードを日本語配列で使用できるようになるが、タスクトレイの言語バーに不要な「ENG 英語(米国) / US キーボード」という項目が追加されキーボード設定からも削除できなくなる、という症状が残る。
キーボード設定で「いったん英語キーボードを追加してから改めて削除」することで一応項目を削除できるが、Xを起動するたびに「ENG...」の項目が復活するので、これは無意味。
#### 解決策
[「Cygwin/Xがキーボード配列を英語(ENG)に設定する現象」](https://mjt.hatenadiary.com/entry/20170903/p1)によると、日本語キーボードの場合のみ強制的に英語キーボードを読み込むという処理がされていることが原因のよう。
コードを眺めると、日本語キーボードかどうかは GetKeyboardType() で判別している。そこで、さらにコレをキーワードに検索したところ、別の問題への対処ではあるが、[バイナリファイルのシンボルを強制的に書き換えてチェックを無効にするという荒技](https://groups.google.com/forum/#!msg/fj.os.ms-windows.win95/BrOZ20sCQMY/Yxh3KSMxLZcJ)を発見。これに倣って、XWin.exe の該当シンボルを書き換える。
バイナリエディタは面倒なのでsedでちゃちゃっと。

```
# cd /usr/bin
# cp XWin.exe XWin.exe.bak
# sed 's/GetKeyboardType/IsWindowEnabled/' < XWin.exe.bak > XWin.exe
```
かなり強引な方法だが、これにて一見落着！
【Unity】webgl向けにビルドしたときのvectorのずれを直す方法

#現状
以下のソースを用いてprefabをインスタンス化しているのですが、Unity上で動かしたときとWeb上にアップロードした後でオブジェクトが作られる位置がずれてしまいます。
Unity上ではWebGLのデフォルトのサイズである960x600で作っており、index.htmlのstyleも960×600なのですがなぜずれてしまうのでしょうか？
また、直す方法はないでしょうか？

**ソース**
// prefabのkomaをインスタンス化する。
GameObject koma = (GameObject)Instantiate(obj,new Vector3(332,291.5,0),Quaternion.identity,komaParent);

▼Unity上で動かしたとき
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635236/c98397ba-56c7-4f18-7f9e-7cd7461d9e4e.png)

▼Webサーバー上で動かしたとき
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635236/53aef132-e002-bf0b-fcdc-fe57300eb6b9.png)
ローカルでのスクレイピング作業をGCPに持っていく作戦(その２)

#前回のお話


~~やめて！ラーの翼神竜の特殊能力で、ギルフォード・ザ・ライトニングを焼き払われたら、闇のゲームでモンスターと繋がってる城之内の精神まで燃え尽きちゃう！~~
~~お願い、死なないで城之内！あんたが今ここで倒れたら、舞さんや遊戯との約束はどうなっちゃうの？ ライフはまだ残ってる。ここを耐えれば、マリクに勝てるんだから！~~
~~次回、城之内しs~~


[ローカルでのスクレイピング作業をGCPに持っていく作戦(その1)](https://qiita.com/kazumatsukazu/items/5b7141c85fd85c7d1c0d)


#今回のお話
定時実行させるためにGoogle Cloud Schedulerを設定します。

#献立

##Google Cloud Schedulerページへアクセス
一番最初はリージョンの選択を迫られるので[こちら](https://cloud.google.com/about/locations?hl=ja)を参考に選択するよろし
##ジョブの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/b1ef9d85-30ba-b36b-5800-bce36e0ca4e6.png)
###名前
お好きなのどーぞ

###頻度
お好きなのどーぞ
頻度の書き方がわからん人は[ここを参照する](https://qiita.com/katsukii/items/d5f90a6e4592d1414f99#%E6%99%82%E9%96%93%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E4%BE%8B)よろし

###タイムゾーン
検索するときはJSTだと出てこない謎。
日本と打てば出てきます。
その他お住まいの地域に合わせるのが良いかと。
###ターゲット
今回はHTTPで。いずれPubSub版も試す。

###URL
GCFをデプロイして作られたURLをコピペ

#作成
もしきちんと実行されるか心配、と言う人は作成後の画面の一番みぎに「今すぐ実行」ボタンがあるのでポチッとしてログ確認してください。

#おしまい
クソ簡単ですな。
次はログ蓄積です。
どうやらログビューアではログを30日間しか持てないみたいなので、それをどうにかGoogleDriveに持っていきます。
java の抽象クラスについて

java のabstract の理解が進んでいなかったので学習した。

特徴
---
・直接のインスタンス生成が出来ない
・サブクラスにオーバーライドを強制する
・サブクラスでコンストラクタを記述する必要がある

```java:sample.java
abstract class Abst_sample {
    abstract void abstractMethod(int num, String str);
    void nonAbstractMethod() {
        System.out.println("非抽象メソッドより出力");
    }
}
public class sample extends Abst_sample {
    public static void main(String[] args) {
        sample aaa = new sample();   
// 継承したあとで、自身のインスタンスを生成してabstractMethod を呼び出している。
        aaa.abstractMethod(3, "Test");
    }
    @Override
    public void abstractMethod(int num, String str) {
        System.out.println("引数int num = " + num + " / 引数String str = "+ str);
    }
}

```

「こういうメソッドを使いなさい」を指示を出すイメージかな。

多人数で開発をするとなると、こういう機能も必要になってくるんだろう。

覚えておいて損はないな。


参考
---
https://www.sejuku.net/blog/22689
意外と知らない「name属性」について

# name属性
要素の名前を指定する属性で、フォーム，フレーム，コントロール，オブジェクトなどの多数の要素で，「要素の名前」を指定する。
ユーザーがリクエストをする際に、viewの方で入力されたparameterにnameのキーをつけることができる。name属性をつけるときは、保存したいデータベースのカラム名にすること。

## 使用例
####1.JavaScript
要素にアクセスする際， この name 属性 の値を用いて，対象要素を特定することができる。

####2.input 要素
フォームのデータが送信されるときに，name 属性の値が付加されており，対象とする要素のデータに簡単にアクセスできます。
また，input 要素 では， name=”_charset_” と name=”isindex” という指定は特別な意味を持ちます。

#####2-1. name=”_charset_”
フォームデータのエンコードの種類 を送信します。

#####2-2. name=”isindex”
フォームデータの送信の際特別な扱いがなされ， HTML5 では廃止になっ た isindex 要素の動作がエミュレートされます。

####3.iframe 要素 と object 要素
name 属性の値は， a要素のtarget属性から参照してHTML文書の表示先を指定する際に使用できます。


##まとめ
簡単に言うと、上記の使用例にあるフォーム等に名前をつけることが出来て、その値を取得するために活用できると言うことです！
name属性を適当なものになっていると、JavaScriptで値がおかしかったりするので注意してください！！
EC2インスタンスをコピーする方法

コピー元インスタンスのAMIをつくってそこからインスタンスを作成することで、インスタンスのコピーを作れる
> Amazon マシンイメージ (AMI) は、ソフトウェア構成 (オペレーティングシステム、アプリケーションサーバー、アプリケーションなど) を記録したテンプレートです。
> [インスタンスと AMI - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instances-and-amis.html)





# EC2インスタンスの画面を表示する
1. AWSのコンソールにログイン > [EC2]

# イメージを作成する
1. サイドメニューの[インスタンス] > コピー元のインスタンスを選択
1. [アクション] > [イメージ] > [イメージの作成]でダイアログを表示する
1. [イメージ名]に何のイメージかわかるような値を設定する
    - [再起動しない]チェックボックス : コピー元インスタンスを再起動しないでイメージを作成したい場合はチェックを入れる
    - [終了時に削除]チェックボックス : コピーしたインスタンスを終了した時にボリュームを削除する場合はチェックを入れる
1. [イメージの作成]ボタンでイメージを作成 > [閉じる]ボタンでダイアログを閉じる
1. サイドメニューの[AMI] > 一覧に作成したイメージが表示される
1. [ステータス]カラムが「pending」から「available」に変わったら出来上がり

# コピー元のインスタンス情報を表示する
インスタンス作成時に参照できるように以降のインスタンス作成とは別画面でコピー元のインスタンス情報を表示しておく。

1. 別画面でインスタンスの一覧を表示する
1. コピー元のインスタンスを選択して、画面下部に詳細情報を表示しておく

# インスタンスを作成する
1. サイドメニューの[AMI] > 作成したAMIを選択
1. [起動]ボタンでインスタンス作成画面を表示する
1. コピー元の情報を参照しながら設定をする
    1. コピー元のインスタンスは作成画面で設定してくれないので別画面で表示しておいたコピー元のインスタンス情報を見ながら設定していく
    1. [ステップ 2: インスタンスタイプの選択]
        - 参考 : [インスタンスタイプ - Amazon EC2 | AWS](https://aws.amazon.com/jp/ec2/instance-types/?nc1=h_ls)
    1. [ステップ 3: インスタンスの詳細の設定]
        - プライベートIPアドレスを指定したい場合
            - 下のほうにある[ネットワークインターフェイス] > [プライマリIP]で指定できる
        - 参考 : [[小ネタ] プライベートIPアドレスを指定して EC2 インスタンスを起動する方法 | Developers.IO](https://dev.classmethod.jp/articles/201903_ec2-with-custom-private-ip-address/)
    1. [ステップ 4: ストレージの追加]
        - ボリュームの情報 : コピー元インスタンス情報 > [設定]タブ > [ルートデバイス]リンク > ポップアップの[EBS ID]リンクからみられる
1. [起動]ボタンでSSH鍵情報のダイアログを表示する
1. 接続用の鍵をどうするか選択する
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/45bb7374-4dd5-409c-34cd-08d0a868e749.png)
1. [インスタンスの作成]ボタンでインスタンスを作成 > [インスタンスの表示]ボタンでインスタンスの一覧に戻る
機械学習で素数を理解してみる

#挨拶
初投稿です。なんならマークダウン方式も初めてです。Pythonも機械学習も経験値はあまりありません。（なので指摘やアドバイスをいただけると幸いです）

今回は素数大好き人間の自分が素数関連のプログラムを作って、その道の途中でたどり着いた機械学習を用いてもっと効率のいい判定法を導こうという話です。

効率はともかく、学習は成功したのではないではないかと思ってます（多分）
#事前考察・研究

なんか重いサブタイですが、要はコーディングする前の考え事です。（次の見出しにまとめがあるのでスキップしても構いません）

まずは一番下にあるだろう、参考文献・引用元を総合した結果

「素数は二値分類（YesかNo）で判別することはできない」

という結論に至りました。（その経緯は省略させていただきます）

そこで新たな方法を模索するため、素数の性質を考えます。

・１と自身以外の自然数では割り切れない
・約数は二つ
・合成数ではない

最初に二つ目の特徴に注目しました。すなわち約数の個数です。

機械学習で任意の値の約数の個数を覚えさせ、回帰問題に行き着かせるのはのはどうか、ていう話です。

####結果
https://twitter.com/NeoNuc2001/status/1260601923738013696?s=20
惨敗
どうやら訓練データの約数の個数を平均した値と近いものを出すだけのものなってしまったようです。

そこでさらに三つ目の特徴、合成数に注目しました。

合成数の判別方法、例えば3や4,5,6,8,9,11で割り切れるかどうかを調べるにはどうすればいいか。

それはその値のそれぞれの桁に注目すればいいのです。

機械学習は言ってしまえば関数の近似、それも微分可能な連続した関数です。対して上記の値で割り切れるかどうかは10^nで割り切り捨てした値を調べるという非連続的な関数を使わなければいけないのです。なので今回は数値をそのまま入れるのではなく、入力値を桁ごとに分離してみました。

#いじったところ
- 約数の個数で判定する
- 入力値を桁ごとに分離する
- ついでに訓練データを素数、非素数半々ずつにする

#環境
OS:Windows 7 (64bit)
メモリ:4gb
CPU:Intel(R) Core(TM) i5 M480 
GPU:なし
言語:Python 3.8.2
ライブラリ
- Chainer 7.4.0
- NumPy 1.18.2
- sklearn 0.0
- sympy 1.5.1
- その他　略（要望があれば追記します）

#コード
コメントアウトや不要な処理、間違った記述があると思いますが、お許しください
GitLab:https://gitlab.com/Neonuc2001/primenumber_chainer
(Wikiなどはまだ未設定です、ごめんなさい)

#結果
2-999998までの全範囲で行いました。
####約数の個数分布（予想）
![Figure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/ddfadf82-abf4-0de7-b545-10179f39f90c.png)

####モデルの的中率
![Per_all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/7645b233-3464-6833-75a1-4a6b9c5bc280.png)

####素数のみに絞った場合のモデルの的中率
![Per_prime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/34755750-c649-54ba-afb3-079b03c1f10e.png)

過学習とも、未学習とも言えないいい線を行ってるのではないでしょうか。

#考察と反省
なんか成功したぽいですね（実際はまだ疑心暗鬼）。
ですが問題点があります。入力層において桁数をあらかじめ指定している以上、特定の範囲でのみしか判別ができないということです。桁数が一つ増えるたびに計算量がどれほど増大するかはよくわかりませんが、素数の最大値を求めさせるにはいささか不安が残りそうな結果です。

また上記に記した環境を見れば一目瞭然ですが、明らかなスペック不足です。なのでこれ以上の桁数については検証できないのがなんとも残念です。

また先述の通り疑心暗鬼なのは機械学習に慣れていない事、素数の割には的中率が高いこと、コードにありうる潜在的バグが気になるなど様々理由があるためです。（みなさんにもやってほしい）

以上で終わります。

#追記
モデルの優秀さを計るために別の視点でデータを見たいと思います。
素数のみのデータを集め、その値が「素数である」と判断する確率を調べます。

| 素数の個数     |       モデル       |   乱数（約数の個数1-100）   |二値分類（YesかNo） |
|:-----------------|------------------:| ------------------:|------------------:|
|1-10000           |              0.83 |       0.01       |0.5|
|10001-20000          |            0.82 |       0.01     |0.5|
| 20001-30000           |              0,83 |       0.01       |0.5|
| 30001-40000               |               0.81 |       0.01        |0.5|
| 40001-50000              |             0.80 |      0.01       |0.5|
| 50001-60000           |           0. 78|      0.01      |0.5|
| 60001-70000           |           0. 67|      0.01      |0.5|

上記の通り、ただの乱数より優秀な確率がでてます。
#参考文献、引用
https://qiita.com/tanuk1647/items/d868c4eab76a9f79c1d3
https://qiita.com/wataoka/items/5201a1ac8696160828fd
Google Spreadsheetでアクティブなシートが変更されたときにスクリプトを実行したい

# 概要
この投稿では、Google Spreadsheetでアクティブなシートが変更されたときにスクリプトを実行するための方法について記載させていただきます。[2020年4月22日に`onSelectionChange`のシンプルトリガーが追加されました。](https://developers.google.com/apps-script/releases/#april_22_2020) 残念ながら、私の環境ではこれはすぐには使用できず、セルを選択してもトリガーが発火しない状態が続いていました。今日、これを確認したところ、動作することを確認しましたので、ここではタイトルのゴールを実現するためのサンプルスクリプトを紹介させていただきます。

# デモ

![20200518b-fig1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133383/8d617db2-f601-dfc0-9454-c8bc925b78e8.gif)


# 使用方法
次のような流れで使用してください。

1. Google Spreadsheetのコンテナ―バウンドスクリプトへ下記のスクリプトをコピーペーストしてください。

	```javascript
	function onOpen(e) {
	  const prop = PropertiesService.getScriptProperties();
	  const sheetName = e.range.getSheet().getSheetName();
	  prop.setProperty("previousSheet", sheetName);
	}

	function onSelectionChange(e) {
	  const prop = PropertiesService.getScriptProperties();
	  const previousSheet = prop.getProperty("previousSheet");
	  const range = e.range;
	  const a1Notation = range.getA1Notation();
	  const sheetName = range.getSheet().getSheetName();
	  if (sheetName != previousSheet) {
	    range.setValue(`Changed tab from ${previousSheet} to ${sheetName}. ${a1Notation}`);

	    // When the tab is changed, this script is run.

	  } else {
	    range.setValue(a1Notation);
	  }
	  prop.setProperty("previousSheet", sheetName);
	}
	```

2. Google Spreadsheetを一度閉じて、再度開いてください。
	- これにより、`onOpen`が実行され、現在のシート名がPropertiesServiceへ保存されます。
	- 現状では`onSelectionChange`のイベントオブジェクトには、シートの移動前後、選択されるセルの前後の情報は含まれていないようでした。これについては、今後のアップデートに期待したいと思います。このような情報を取得するために、このサンプルではPropertiesServiceを使用しています。

3. ここで、スプレッドシート上のセルをクリックすると、`onSelectionChange`が実行されて選択したセルにa1Notationが入力されます。また、アクティブシートを移動すると、これに基づいてシートがどこからどこへ移動したのかの情報がセルに入力されます。

`onSelectionChange`のイベントトリガーは、いろいろなところで活躍しそうです。

# 参考

- [onSelectionChange(e)](https://developers.google.com/apps-script/guides/triggers#onselectionchangee)
- [Properties Service](https://developers.google.com/apps-script/reference/properties)
ABC 36 D 塗り絵

##問題
https://atcoder.jp/contests/abc036/tasks/abc036_d
##見た感じ
ノードの個数がn個で橋の個数がn-1、かつ任意の二つのノードを行き来できるので、このグラフは木になっていることがわかる。
だからある頂点からスタートして、それが黒の時$color=1$、白の時$color=0$として、以下の漸化式について計算すればよさげ。

```math
dp[i][color]=i番目のノードを根とする部分木でiに来る前のノードpastを含まないものの\\塗分け方をmodで割ったやつ\\
dp[i][color=1]=\prod_{iからいけるv}　dp[v][0]\\ 
dp[i][color=0]=\prod_{iからいけるv} dp[v][0]+dp[v][1]

```
##解法
上の漸化式どおりにメモ化再帰で書いた
##ソースコード
```c++
//mintはmodとってくれるやつ
//edge はedge.to を持つための橋struct
const int N_MAX=100001;
vector<edge> v[N_MAX];
mint dp[N_MAX][2];
int n; 
//color=1::黒
mint rec(int now,int color,int past){
    if(dp[now][color].x>0)return dp[now][color];
    if(v[now].size()==1){
        return dp[now][color]=1;
    }
    mint res=1;
    rep(i,v[now].size()){
        int w=v[now][i].to;
        if(w==past)continue;
        if(color){
            res*=rec(w,0,now);
        }else{
            res*=rec(w,0,now)+rec(w,1,now);
        }
    }
    return dp[now][color]=res;
}

int main(){
    int i=0,x,y;
    //入力
    cin>>n;
    rep(i,n-1){
        cin>>x>>y;
        v[x-1].push_back(edge(y-1));
        v[y-1].push_back(edge(x-1));
    }
    //処理
    while(v[i].size()<=1)i++;
    mint ans=rec(i,1,-1)+rec(i,0,-1);
    //出力
    cout<<ans<<endl;
    return 0;
}
```
チャネルファーストデータをチャネルラストにする

# はじめに
Pytorchを前提に記述されたプログラムをKerasに書き換えている時に、画像データ配列の軸を入れ替える必要があったため、その方法について共有します。

# Image Channel Order

Channels First : **(N, C, H, W)** ← PyTorch
Channels Last  : **(N, H, W, C)** ← Keras

**N** : 画像の枚数
**C** : チャネル数（色など）
**H** : 画像のHeight
**W** : 画像のWidth

### チャネルファースト（Channels First）
PyTorchなどにおいて、画像データ配列でモデルを学習する際は、**Channels First** 形式が一般的です。画像の次元の並び方が **(Channel, Height, Width)**となっています。Channel（Color）の次元が配列の先頭にあることが名前からわかります。

### チャネルラスト（Channels Last）
Keras,PIL,OpenCVなどにおいて、画像データ配列を扱う場合は、**Channels Last** 形式が一般的です。画像の次元の並び方が **(Height, Width, Channel)**となっています。Channelの次元が配列の最後にあることが名前からわかります。


# Channels First → Channels Last

仮の **Channels First** の画像配列データを作成します。

```python:仮の画像配列データ
img = np.arange(100*64*64*3).reshape(-1,3,64,64)
img.shape 
(100, 3, 64, 64)
```

## 方法1 : np.transpose()
```python:np.transpose()
%%timeit
img.transpose(0,2,3,1).shape
(100, 64, 64, 3)
791 ns ± 92.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
```

## 方法2 : np.swapaxes()
```python:np.swapaxes()
%%timeit
np.swapaxes(img, 1, 3).shape
(100, 64, 64, 3)
1.54 µs ± 410 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
```

## 方法3 : np.moveaxes()
```python:np.moveaxes()
%%timeit
np.moveaxes(img, 1, 3).shape
(100, 64, 64, 3)
9.29 µs ± 956 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

```

## 方法4 : np.rollaxes()
```python:np.rollaxes()
%%timeit
np.rollaxes(img, 1, 4).shape
(100, 64, 64, 3)
2.89 µs ± 358 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
```

## 方法5 : np.einsum()
```python:np.einsum()
%%timeit
np.einsum('ijkl->ilkj', img).shape
(100, 64, 64, 3)
1.77 µs ± 210 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
```

# 最後に

np.transpose()　が最速でした。お好きなのを使用してください。

[what-is-the-correct-way-to-change-image-channel-ordering-between-channels-first](https://stackoverflow.com/questions/43829711/what-is-the-correct-way-to-change-image-channel-ordering-between-channels-first) を参考にしました。
ファイルをダウンロードさせる方法

リンククリックでファイルをダウンロードさせる方法についてまとめました。

右クリック→リンク先を保存ではなく、リンクボタンをクリックしただけでダウンロードさせるという方法です。

# 画像などの単体ファイルをダウンロードさせる

```index.html
<a href="ファイル名" download>ファイルをダウンロード</a>
```

リンクしたファイルがダウンロードされます。

## ダウンロードされるファイルに名前をつけたい場合

```index.html
<a href="ファイル名" download="ダウンロードした後のファイル名">ファイルをダウンロード</a>
```

リンクするファイルのファイル名と、ダウンロードされるファイルのファイル名を変えたい場合は、`download=""`にファイル名を指定するとできます。

#フォルダ内をまとめてダウンロードする

サーバーに上がっているファルダの中身をフォルダごとzipにまとめてダウンロードする場合、zip化するphpを叩いてダウンロードする、がシンプルかなと思います。

phpの`ZipArchive`クラスを使います。

```zip.php
<?php

$zipName = $_GET['dl']; // 圧縮するフォルダ名

$dist = $zipName.'.zip'; // 生成する圧縮ファイル名
$path = 'フォルダまでのパス'.$zipName; // 圧縮するフォルダのパス

//DLするファイルのフォルダ構成を維持するか否か　0:しない／1:する
//維持する場合、ダウンロードしたファイルは $path の構成になります
$filePath = 0;
//DLファイルが１つの場合、フォルダに入れるか否か　0:いれない／1:いれる
$folderIn = 1;

$zip = new ZipArchive();
$zip->open($dist, ZipArchive::CREATE | ZipArchive::OVERWRITE);

if (is_dir($path)) {
	$files = array_diff(scandir($path), ['.', '..']);
	$filesNum = count($files);
	foreach ($files as $file){
		if($filePath >= 1){ //フォルダ構成を維持する
			$zip->addFile($path.'/'.$file);
		}else{ //維持しない
			if(($folderIn >= 1) && ($filesNum <= 1)){ //ファイルが１つの時、フォルダに収める場合の処理
				$localFile = $zipName.'/';
			}else{
				$localFile = '';
			}
			$zip->addFile($path.'/'.$file, $localFile.$file);
		}
	}
}
$zip->close();

// ストリームに出力
header('Content-Type: application/zip; name="' . $dist . '"');
header('Content-Disposition: attachment; filename="' . $dist . '"');
header('Content-Length: '.filesize($dist));
//echo file_get_contents($dist);
readfile($dist);

// 一時ファイルを削除しておく
unlink($dist);

exit;

?>
```
```index.html
<a href="zip.php?dl=フォルダ名">ファイルをダウンロード</a>
```
圧縮するファイルにフォルダを指定していても、フォルダ内のファイルが１つしかない場合、解凍するとファイルだけ、ということが起きるので、`$zip->addFile`の第２引数でフォルダ内に収めるようにしています。

ダウンロードされたファイルに特定の名前などを指定したい場合も、`$zip->addFile`の第２引数で指定してあげると可能です。

※コメントで`file_get_contents()`は、maxlenパラメータを指定しない場合対象ファイル全体をメモリに抱え込んでしまうと教えていただきましたので、出力部分を`readfile()`に変更しました。
【Swift】Error, failed to read Core Data data model from...でつまづいた話

[技術は熱いうちに打て | 【Swift】Error, failed to read Core Data data model from…でつまづいた話](http://blog.dalt.me/?p=1609)

# 概要
掲題の通りですが、一度追加したCoreDataの定義ファイルの名前を変更したかったので削除し、
ファイル名を変えたものをもう一度追加した時に発生しました。

# 直し方

https://stackoverflow.com/questions/25589138/compilation-failed-for-data-model-at-path

こちらが非常に参考になりました。

`xcdatamodeld`のあるフォルダを直接Finderで表示して、
元ファイルを削除したら解決しました。

誰かのお役に立てば。
Atcoder　アルゴリズムテンプレ自分用メモ

#素因数分解とN以下の素数の数

```C++
map<ll,int> m;

//素因数分解
//因数の個数を数えれば、n以下の素数の個数を求めることができる
ll countPrimes(ll n)
{
  for (ll i=2;i*i<=n;i++)
  {
    while (n%i==0)
    {
      m[i]++;
      n /= i;
    }
  }
  if (n!=1) m[n]++;
  return (m.size());
}

int main()
{
  ll n;cin>>n;
  countPrimes(n);
  cout<<n<<" = ";
  for (auto i=m.begin();i != m.end();i++)
  {
    cout<< i->first <<"^"<<i->second;
    if (i != m.end())
      cout<<" * ";
  }
  cout<<endl;
}
```

#nCr
何回も同じ階乗を計算しなくて済むように、前処理しておく。
top,botをそれぞれ計算しておいて、top/botを計算したい。
二分累乗法とフェルマーの小定理で、逆元の計算をする。

```C++
vector<ll> fac(MAX);

void COMinit()
{
  fac[0]=1;
  for (ll i=1;i<=MAX;i++)
  {
    fac[i]=(fac[i-1]*i) % MOD; 
  }
}

ll fast(ll a, ll n)
{
  ll ret=1;
  while (n>0)
  {
    if (n & 1)
    {
      ret = (ret * a) % MOD;
    }
    n = (n>>1);
    a = a * a % MOD;
  }
  return (ret);
}
 
ll comb(ll n, ll r)
{
  ll top=1;
  ll bot=1;
  ll ans;
  
  if (n<r || n<0 || r<0) return (0);
  
  top = fac[n];
  bot = fac[r]*fac[n-r] % MOD;
  ans = top * fast(bot,MOD-2) % MOD;
  return (ans);
}
```

#二分累乗法

高速にa^nを求める「二分累乗法」
log(n)でできる
2^32を計算するのにwhile 2回しか回らないすごい 33 = 2^5+2^0なので2,0の2回

```C++
ll time(int a, ll n)
{
  ll ret=1;
  while (n>0)
  {
    if (n & 1)
    {
      ret = ret * a % MOD;
    }
    a = a*a % MOD;
    n = (n>>1); //n /= 2
  }
  return (ret);
}
```

#Union Find

グループ分けを管理したい・・・！！！
初めは別々のグループでそれをまとめる作業をしていく。
グループが一緒かどうかは「根が一緒かどうか」で判定する。
まとめていく作業をする時に、縦長になってしまうと効率が悪いので、
・ `経路圧縮`
・ `ランクが短い方を繋げる`
という方法で効率化する、片方やるだけでO(logN)になり、
両方行うとO(logN)より大分早くなる。

```C++

int par[MAX_N];//親の番号
int siz[MAX_N];//木のサイズ
//int rnk[MAX_N];
 
void init(int n)
{
  //根の定義・・・par[i]=iの時iを根という
  //最初全てが根
  for (int i=0;i<=n;i++){
    par[i]=i;
    siz[i]=1;
  }
}
 
//木の根を求める
int root(int x){
  if (par[x]==x){  //xが根の時
    return (x); 
  }else{
    par[x]=root(par[x]);//xを、xの親の根につなぎ直す
    return par[x]; //経路圧縮
  }
}
 
//x,yが同じ集合に属しているか、つまり同じ根に繋がっているか
bool same(int x,int y){
  return ( root(x)==root(y) );
}
 
//x,yの属する集合を合併する
bool merge(int x, int y) {
   x = root(x); y = root(y);
   if (x == y) return false;
   if (siz[x] < siz[y]) swap(x, y);
   siz[x]+=siz[y];
   par[y] = x; //ランクが大きい方に小さい方を繋げる
   return true;
}
 
int treesize(int x)
{
  return (siz[root(x)]); 
}
```

#拡張版GCD
まだ使ったことないけど、フェルマーの小定理を使わずに逆元の計算をする時に使える。
>ax+py=1
⇔ ax ≡ 1  mod p
⇔ x ≡ a^(-1) mod p

より、ax+py=1なるxがaの逆元。

```C++

ll extGCD(ll a,ll b, ll &x, ll &y)
{
   if (b==0) 
   {
     x=1;
     y=0;
     return (a);
   }
   else
   {
     ll s,t;
     ll g = extGCD(b,a%b,s,t);
     x = t;
     y = s-((a-a%b)/b)*t;
     return (g);
   }
}

int main()
{
  ll a,b;cin>>a>>b;
  ll x, y;
  cout<<"最大公約数は:"<<extGCD(a,b,x,y)<<endl;
  cout<<"ax+by="<<a<<"×("<<x<<")+"<<b<<"×("<<y<<")="<<extGCD(a,b,x,y)<<endl;  
}
```
Laradockを使った開発環境の構築方法

nginx mysqlを使用して進めます。

#ローカルにファイルを作成
最終的に以下の構造になります。

```
app
├── app
└── laradock
```


#laradockのインストール
```
git clone https://github.com/Laradock/laradock.git
cd laradock
cp env-example .env
mkdir ../app
```
laradockをgithubからインストールし、設定ファイルをコピーします。
また、ローカルのフォルダも作成しておきます。

#.envを編集
```
APP_CODE_PATH_HOST=../app
```
ローカルで編集できるようにするためAPP_CODE_PATH_HOSTの設定を変えます。


#Laradockのコンテナ起動

```
$ docker-compose up -d nginx mysql

Recreating laradock_docker-in-docker_1 ... done
Recreating laradock_mysql_1            ... done
Recreating laradock_workspace_1        ... done
Recreating laradock_php-fpm_1          ... done
Recreating laradock_nginx_1            ... done
```


#workspaceコンテナのパッケージのアップデート
```
docker exec -it laradock_workspace_1 bash
```
でコンテナの中に入ります。
-itオプションは以下の意味です。
  -i アタッチしていなくても STDIN をオープンにし続ける(標準入力を使えるようにする)
  -t 疑似ターミナル (pseudo-TTY) の割り当て(ターミナルの形で表示させる)

```
apt-get update
```
仮想OSをupdateします。




#laravelのプロジェクトの作成
```
composer create-project laravel/laravel .
```
仮想OSのプロジェクト直下にlaravelのプロジェクトを作成します。
APP_CODE_PATH_HOSTの設定を変えたため、実際は、../appに作成されます。


#MySQLの設定
ローカルに作成されたlaravelプロジェクト内の`.env`を編集します。

```
DB_CONNECTION=mysql
DB_HOST=laradock_mysql_1
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
```


#[localhost](http://localhost/)にアクセスしてみる
[localhost](http://localhost/)にアクセスしてみましょう。

<img width="1071" alt="Screen Shot 2020-05-18 at 16.43.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169789/f070a17b-8729-5da3-9995-1bccb963b4ea.png">

この画面が表示されれば、うまく行っています。
AWS Single Sign-On とは

#AWS Single Sign-On とは

> AWS Single Sign-On は、AWS アカウントおよびクラウドアプリケーションへの SSO アクセスの一元管理を容易にするクラウドベースのシングルサインオン (SSO) サービスです。特に、AWS Organizations 内のすべての AWS アカウントを対象に SSO アクセスとユーザーアクセス許可を管理するうえで役立ちます。AWS SSO はまた、一般的に使用されているサードパーティー SaaS (Software-as-a-Service) や Security Assertion Markup Language (SAML) 2.0 をサポートするカスタムアプリケーションに対するアクセスとアクセス許可を管理するのにも便利です。AWS SSO には、エンドユーザーが自分に割り当てられている AWS アカウント、クラウドアプリケーション、カスタムアプリケーションを一元的に検索したり確認したりできるユーザーポータルが含まれます。

らしいです。SAMLを使ったSSOには必須でしょう。

##AWS Single Sign-On（SSO）でAWSアカウントへシングルサインオン
http://blog.serverworks.co.jp/tech/2020/03/06/sso/

AWS Orgnizationにて全ての機能の有効化が必須

#参考文献

* AWS Single Sign-On とは
    * https://docs.aws.amazon.com/ja_jp/singlesignon/latest/userguide/understanding-key-concepts.html
Firestore のセキュリティルールのデバッグには debug() を使おう

Firestore のセキュリティルールは、テストを書きながら emurator で実行して問題ないかをチェックする、というのが一般的な方法。

ただ、いろいろなチュートリアルや書籍を見ていてもプリントデバッグができる `debug()` 関数が載っていなかった(エミュレータのみだからなのか、当たり前すぎるのか、みんな知らずに書いているのか…)ので書いておく。

- https://firebase.google.com/docs/reference/rules/rules.debug
  - (というか、この debug も含めた、セキュリティルールの関数や型全般の仕様が理解できる「[セキュティルールのAPIリファレンス](https://firebase.google.com/docs/reference/rules/index-all)」にたどり着くのが困難…)

の通り、使い方は単純で `debug()` は引数の値を firestore-debug.log に出力し、引数自体を返す関数。

例えば、

```
match /users/{userId} {
  allow read, update, delete: if
     request.auth.uid == userId;
```

は、`debug()` を使うと

```
match /users/{userId} {
  allow read, update, delete: if
    debug(
      debug(request.auth.uid) == debug(userId)
    );
```

と書くことができ、firestore-debug.log には

```
string_value: "taro" // これが request.auth.uid
string_value: "jiro" // これが userId
bool_value: false // これが == の評価の結果
```

みたいなログが出力される。いわゆるプリントデバッグが可能になるのだけど、あるだけで十分挙動理解がしやすくなる。なお手元にログが吐かれるので、emurator限定だ。

## request すべてを print する

```
allow list: if cond();
```

みたいの条件のときに debug() で request 全部を表示して確認したい。そんなときは

```
allow list: if debug(request) && false;
allow list: if cond();
```

と書くと、最初の行は必ず偽になるので debug(request) が実行され、かつ何もおこらず。セキュリティルールを並列で書いた時は OR マッチになるので、次の `allow list: if cond();` の行は普通に評価される。

```
// allow list: if debug(request) && false;
allow list: if cond();
```

debug(request) を表示たくない場合は、こんな風にコメントアウトするだけなので楽。

## もっと詳しい使い方

- https://qiita.com/sgr-ksmt/items/594496b17e0998aefed0
Windows10でSQL Serverの接続方法

#環境
SQL Server Express
SQL Server Tool

#手順

1. Win+R services.mscを入力
2. SQL Server Expressを選択-> Log on-> "Local System account"　を選択, General->Startup type-> Manual
3.  "Start"をクリク
4. SQL Server Configuration Managerを開く->SQL Server Network Configurationを選択
5. "Protocols for SQL"->Enable TCP/IP->properties->IP Address->IPALL ->TCP Port:1433