OmniAICreator/Qiita-1.07M huggingface dataset:
【Swift】UILabel 幅 設定 できない

# 状況

- 対象のUILabelのtextを処理によって変えたい
  - textによって幅の長さを変えたい
- 対象のUILabelになんらかの制約がかかっている

## なにがあったのか

UILabelの幅をtextの長さではなく自由に設定したいが、制約がかかっている場合だとどうも `label.frame` や、textを基準にしたPadding的なことをコードを書いて設定することができない（できなかった）。
単純にStoryboardで設定すればうまくいくが、例えばなんらかの処理でtextの文字列が変わるとその都度変えることができなくなる。

## なんとかする

コードで制約を書いて変更したらなんとかなった。

```swift
label.text = "なんとかしてください"
label.widthAnchor.constraint(equalToConstant: 100).isActive = true
```

これを `if` とかで分岐した処理によって数値を変えたらいいと思う。
NuttX for Raspberry Pi PicoでmicroSDカードを読み書き (SPI接続)

[NuttX for Raspberry Pi PicoでSSD1306 OLEDに画像表示 (I2C接続)](https://qiita.com/yunkya2/items/fdc5d53b05e3cf5be290) に続いて、同様にSPRESENSEの実装を元にしてSPIドライバを追加しました。

SPIの先には、以下のようなカードスロットを接続してmicroSDカードを読み書きしてみます。

https://akizukidenshi.com/catalog/g/gK-05488/

# 接続

Raspberry Pi PicoのSPI0と電源に、microSDカードスロットの各端子を以下のようにつなぎます。

|microSDカードスロット|Pico端子|Pico ピン番号|
|:----------:|:-----------:|:-----------------------:|
|DAT2|(接続しない)|-|
|CD/DAT3|GP17 (SPI0 CSn)|22|
|CMD|GP19 (SPI0 TX)|25|
|VDD|3V3|36|
|CLK|GP18 (SPI0 SCK)|24|
|VSS|GND|3, 38 などのGNDピンのどれか|
|DAT0|GP16 (SPI0 RX)|21|
|DAT1|(接続しない)|-|
|カード検出スイッチB|(接続しない)|-|
|カード検出スイッチA|(接続しない)|-|

# NuttXのビルド

SPI接続のmicroSDカードスロットをサポートするコンフィグレーションとして用意した、`raspberrypi-pico:spisd`を指定してビルドします。

```
$ git clone https://github.com/apache/incubator-nuttx.git nuttx
$ git clone https://github.com/apache/incubator-nuttx-apps.git apps
$ cd nuttx
$ ./tools/configure.sh raspberrypi-pico:spisd
$ make
```

microSDカードスロットの接続先となるSPI0のGPIOピン番号は、コンフィグレーションファイル`nuttx/boards/arm/rp2040/raspberrypi-pico/configs/ssd1306/spisd`の以下の箇所で指定されています。
指定した番号のGPIOがSPIのRXに、それ以降のGPIOは番号順にCSn, SCK, TXに使われます。[Raspberry Pi Picoのピンレイアウト図](https://datasheets.raspberrypi.org/pico/Pico-R3-A4-Pinout.pdf)でSPI0が出せるGPIOピンであれば、他の番号[^1]に変更することも可能です。

[^1]: 指定できるのは 0, 4, 16, 20のいずれかになります。

```
CONFIG_RP2040_SPI0_GPIO=16
```

# 起動

起動すると、カードスロットにmicroSDカードが刺さっていてそれがFATでフォーマットされていれば、`/mnt/sd0`にマウントされてアクセス可能になっています。
(現時点では、カードの活線挿抜はサポートしていないため、カードの抜き差しの際は再起動する必要があります)

```

NuttShell (NSH) NuttX-10.0.1
nsh> mount
  /mnt/sd0 type vfat
  /proc type procfs
nsh> ls -l /mnt
/mnt:
 drw-rw-rw-       0 sd0/
nsh> ls -l /mnt/sd0
/mnt/sd0:
 drw-rw-rw-       0 System Volume Information/
 -rw-rw-rw-      71 README
```

以下は、NuttXを起動してmicroSDカードを読み書きしている動画です。カードのアクセス速度も測ってみました。

![nuttx-spisd-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642667/6fc064b1-3c96-5729-e611-0a8f53d0a915.gif)

1MBのファイル読み書きで、

- ~~write: 7.32秒 (1.1Mbps)~~
- ~~read: 1.60秒 (5.1Mbps)~~

~~SPIモードでの接続なのでカード本来の速度を出せていないのは確かですが、こんなものですかねえ?~~

【追記】単に読み書きの単位が小さすぎですね。バッファを32KBに、ファイルサイズを10MBにして測り直すと、

```
nsh> time "dd if=/dev/zero of=test bs=32768 count=320"

6.5600 sec
nsh> time "dd if=test of=/dev/null bs=32768"

5.2700 sec
```
- write: 6.56秒 (12.8Mbps)
- read: 5.27秒 (15.9Mbps)

microSDアクセス時のSPIのクロック周波数は20MHzに設定しているので、そこそこの値は出ている様子です。
OpenAPI(swagger): 定義したスキーマの使用時に一部を上書きしたい時の小技

`UserName`というスキーマ定義があったとする。

```yaml
UserName:
  type: string
  description: ユーザー氏名
  example: 山田太郎
```

この`UserName`という定義の使用時に、一部を変更したいと思っても↓の書き方では上書きされない。

```yaml
properties:
  adminName:
    $ref: "#/components/schemas/UserName"
    description: 管理者氏名
    example: 管理者
```

この書き方では、decriptionは「ユーザー名」だし、exampleは「山田太郎」のままである。


### allOfを使って上書きする
しかし、`allOf` を使って↓のように書くことで上書きすることができる。

```yaml
properties:
  adminName:
    allOf:
      - $ref: "#/components/schemas/UserName"
    description: 管理者氏名
    example: 管理者
```

ちょっと Swagger UI の表記を調整したいな、という時に便利。

同じ書き方でオブジェクトのプロパティを上書きすることもできるが、構造に手を入れるぐらいなら新しく定義を作るべき。
エクセルVBAにて最終行の次の行にコピーする方法（備忘録）

エクセルVBAやpythonなどのプログラミング初心者の備忘録として以下の内容をまとめていきます。

業務で処理が必要になった「VBAで最終行をコピー＆最終行の次の行に貼り付ける操作」。

ほぼほぼ参考サイト様の中身のままですが・・

```vba

Sub VBAのタイトルをここに記入()

最終行 = Cells(Rows.Count, “A”).End(xlUp).Row
最終行の次の行 = Cells(Rows.Count, “A”).End(xlUp).Row + 1

Range(“A” & 最終行).Copy
Range(“A” & 最終行の次の行).PasteSpecial

End Sub
```


最初の2行で最終行と最終行の次のセル番号を取得。

続いてそのセル番号の中身をコピーし、
最終行の次の行へ貼り付け。

1文ずつ丁寧に見ていくのがプログラミング初心者には
重要のようですね。


https://toushitsu-off8.com/excel-vba-ssaishuugyou/



別シートを挟んで最終行→最終行の次の行にコピペは以下のよう。

```vba

Sub 別シートの最終行コピー後に最終行の次の行に貼り付け()

Sheets(“Sheet2”).Select
last = Cells(Rows.Count, “A”).End(xlUp).Row
Range(“A” & last).Copy
Sheets(“Sheet1”).Select
tugi = Cells(Rows.Count, “A”).End(xlUp).Row + 1
Range(“A” & tugi).PasteSpecial

End Sub

```

何度も書いてみて覚えなきゃですね・・
GmailをURLで共有する

# はじまり
Google Chat上で昔のGmailをリマインド目的で共有する必要があったのですが、
該当メールを開いているブラウザのURLを貼っても相手からは開けませんでした。
(Gmailの画面に「リクエストされたスレッドを読み込めませんでした」と表示される)

# GmailのURLの構造
受信トレイを開いたとき
'https://mail.google.com/mail/u/0/#inbox'

hogeラベルのメール一覧を開いたとき
'https://mail.google.com/mail/u/0/#label/hoge'

hogeラベルのメール一覧から特定のメールを開いたとき
'https://mail.google.com/mail/u/0/#label/hoge/xxxxxxxx(メールのID)' 

ラベルがURLにくっついています。
ラベル名は自由に設定できるのだから、そりゃ共有できないですよね。

さらに、同じメールであっても受信者それぞれでメールのIDは異なってくるので、
'https://mail.google.com/mail/u/0/#inbox/xxxxxxxx(メールのID)'
みたいなURLでも共有はできません。

# 暫定対応：Gmailの検索演算子を使う
メールIDとは別で、GmailにはメッセージIDと呼ばれる一意の識別子が存在しています。
rfc822msgidという検索演算子があるので、
これを組み込んだURLを相手に読んでもらうことで、相手のメールBOXを検索してもらいます。
※もちろん、そのメールを受信していることが前提です

メッセージIDの確認方法
検索対象のメールを開いていて、画面右上のその他をクリック
![スクリーンショット 2021-03-08 18.05.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104729/6dc87cba-b4b8-ff60-37ca-7764428d3dbe.png)

コードがつらつら表示されている中の以下部分を見つける
Message-ID: <<xxxxxxxxxxx@example.com>>
※この<>内の文字列を控える

メールの検索窓に以下を打って検索
rfc822msgid:xxxxxxxxxxx@example.com

下記画像のように1通だけHITするので、
その画面のURLを相手にも読み込ませれば、同じ画面が表示されます。
(他にもGoogle Chat上で共有できる方法があれば教えてください・・・)
![スクリーンショット 2021-03-08 18.17.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104729/4ff1671e-5bc6-f987-39e7-cdde121b0ea2.png)
URI編　

# URIの重要性
URIはUniform Resource Identiferの略で、直訳すると「統一リソース識別子」だ。

URIは、**「リソースを統一的に識別するID」**

URIを使うと、Web上にあるすべてのリソースに簡単にアクセスできる。

# URIの構文

`https://qiita.com/drafts/08a5fa533e72f83f6937/edit`
このURIを構成するパーツは次のようになります。

- URIスキーム: https
- ホスト名:　qiita.com
- パス: /drafts/08a5fa533e72f83f6937/edit


URIスキームはそのURIが利用するプロトコルを示すのが一般的。
URIスキームとその後ろに続く部分には「://」で区切られます。

ホスト名はDNSで名前が解決できるドメイン名か、IPアドレスで、インターネット上で必ず一意になります。

パスは、そのホストの中でリソースを階層的に示します。

このような仕組みであるリソースのURIが世界中の他のリソースのURIと絶対に重複しないようになっています。

# 複雑なURIの例

`http://yohei:pass@blog.example.jp:8000/search?q=test&debug=true#n10`

URIスキームの後ろには、ユーザ情報がある。
ユーザ情報は、このリソースにアクセスする際に利用するユーザ名とパスワードから成り立っています。
「:」で区切られています。

その次にはホスト情報がくる。
ホスト情報は、ホスト名とポート番号から成る。

ポート番号とは、このホストにアクセスするときのプロトコルで用いるTCPのポート番号を示します。
ポート番号を省略した場合は各プロトコルのデフォルト値が使われます。HTTPのデフォルト値は80番です。

パスの後ろには、?が続き名前=値形式のクエリが続きます。
この例では、q=testとdebug=trueがそれぞれクエリです。
クエリが複数あるときは、&でつなぎます
クエリはサーバにアクセスし情報を検索する時に使う検索キー。

この一つ以上のクエリの集合を「クエリパラメータ」という。

クエリパラメータは、検索サービスに検索キーワードを渡す時など、クライアントから動的にURIを生成するときに使用します。

最後に、#で始まる文字列は、「URIフラグメント」といい、その前までの文字列で表現するURIを指し示すリソース内部のさらに細かい部分を特定するときに利用します。

このリソースがHTML文書だった場合、id属性の値が「n10」である要素を示すことになります。

# URLとURN
URIはURLとURNを総称する言葉です。
Uniform Resource Locater(URL)とUniform Resource Name(URN)

URLにはドメインを更新しなかったり、サーバが何らかの障害で変更になった場合などに、アクセスできなくなる問題がある。
その問題を解決するべく、URNが生まれました。URNはリソースにドメイン名とは独立した名前が付けられます。URNはドメイン名に依存しません。
この、URLとURNの要素を組み合わせた総称がURIなのです。

URLがLocater、つまり、リソースの場所を示すもの
URNがName、つまり、リソースの名前を示す者
URIがIdentifer、つまり、リソースを識別するもの

# URIの設計

- URIにプログラミング言語依存の拡張子を利用しない
- URIに実装依存のパス名を利用しない（cgi-bin, servleyなど）
- URIにプログラミング言語のメソッド名を利用しない
- URIにセッションIDを利用しない
- URIはそのリソースを表現する名詞である。

# マトリクスURI
階層式にリソースを表せない場合、マトリクスURIを使います。

階層構造を表現するスラッシュの代わりに、複数の軸のパラメータをそれぞれセミコロン(;)またはカンマ(,)で区切ってリソースを表現します。

例えば、Google Mapの場合、緯度と経度を使うと
`https://www.google.co.jp/maps/place/lat=35.202902902;lng=183.1010011`

とこんな感じで表せる。
何にも知らなかった頃の自分へ 「Oracleとは」

#書くこと
Oracleって聞いたことあるけど、何のこっちゃ...
と思っていたので、今回「とってもざっくり」、何にも知らなかった頃の自分でも理解できるように書いてみました。

## この記事でわかること
- Oracleって何？
- Oracleはなぜ生まれた？
- 似たサービスはあるか？

##Oracleとは？
結論からいくと

> オラクル社が開発・販売しているリレーショナル・データベース管理システム（Relational Database Management System（RDBMS））

なるほど、PostgreSQLやMySQLのように、二次元でデータを管理するDB管理システムだったのですね。
なので、Oracle Databaseと呼ばれることもあります。

DBとは、データベースのことです。データを入れる箱です。
その中でもリレーショナル・データベースとは、二次元でデータを保管する箱になります。

身近な例だと、エクセルも二次元ですよね。
あの形で、**「どこに存在するあれに関するデータ」**という形でデータを保管します。


また、

>データの操作にはSQL言語を使用する

とあります。SQL(Select Query Languages)文とは、ざっくりいうとDBから条件を指定してデータを抜き出すための文法のことです。

使い方について詳しく知りたい場合は、以下の記事を参考にすると良いかもしれません。
[【これだけ覚えてたらOK！】SQL構文まとめ](https://qiita.com/tatsuya4150/items/69c2c9d318e5b93e6ccd)

正し、`オラクル社が販売している`、とあるのでこれは有償です。
対して、MysqlやPostgreSQLは無償で利用することができます。

でも、Mysqlは現在Oracle社が開発を行うオープン・ソースSQLデータベース管理システムです。つまり、Oracleは有償の**Oracle Database**と、無償の**MySQL**を提供している企業ということになります。

オープン・ソースとは、無料で提供・公開されているという意味です。

では、なぜ同じ会社が有償と無料のものを提供しているのでしょうか？
Oracleが持つ特徴と共に見ていきましょう。

## Oracle Databaseの特徴
まず、大きく分けて、二つの特徴が存在します。

- 行レベルロック
- 読みとり一貫性

**行レベルロック**とは、エクセルでいう横の行を単位として、各処理間の影響を排除しながら処理する仕組みのことです。これがないと、大量の処理が発生する時には、データベースへの更新処理などを遮ってしまうロック機能が発動し、正しくDB更新がなされなくなるみたいです。

**読み取り一貫性**とは、検索した時点での情報を読み取る機能です。これがないと、検索している間に更新されてしまった場合、検索時のデータではなく更新後のデータを取得してしまいます。

他にも、堅牢性や移植性といった特徴もあるようです。詳しくは、以下の記事を参照してみてください。
- [知ってるようで知らない！Oracle（オラクル）とは？](https://itpropartners.com/blog/8599/#Oracle_Database)

まぁざっくりまとめると、`「無償のものよりも、大きな処理に対応したり、セキュリティしっかりしているRDBMSだ」`くらいに思っても差し支えないと思います。

##似たサービス
Amazonが提供する、AWS（Amazon Web Service）は、**Amazon Aurora PostgreSQL（アマゾン・オーロラ・ポスグレSQL）**を提供しています。

僕は現時点で仮想サーバのEC2と、画像保存のためにS3を利用した経験しかありませんが、確かに、AWSの仕組みの中で色々完結していました。

[こちら](https://www.orangeitems.com/entry/2019/03/07/000500)の記事でも、AWSとOracleがバトってるということを解説しておられました。AWSがOracle DataBaseを刈り取り始めているみたいですね...

## まとめ
それでも、[PostgreSQLとMongoDB増加 - 5月データベース人気ランキング](https://news.mynavi.jp/article/20200503-1029382/)を見るように、Oracleは依然としてシェア率トップにいます。

駆け出しエンジニアとして、プログラミング言語だけでなく、インフラの面でも少しずつトレンドが変わることを意識したいですね。

##最後に
最後まで読んでいただき、ありがとうございます。
ソースコード、記事の書き方について「もっとこうしたほうがいいよ！」というご意見、「そこどうなっているの？」というご質問など、お待ちしております。

##参考文献
- [【これだけ覚えてたらOK！】SQL構文まとめ](https://qiita.com/tatsuya4150/items/69c2c9d318e5b93e6ccd)
- [今さら聞けない!? Oracle入門 ～概要編～](https://www.oracle.com/jp/a/tech/docs/technical-resources/0413-1330-oracle-beginner-overview.pdf)
- [知ってるようで知らない！Oracle（オラクル）とは？](https://itpropartners.com/blog/8599/#Oracle_Database)
- [orangeitems’s diary 「ついに刈り取られ始めたOracle Database」](https://www.orangeitems.com/entry/2019/03/07/000500)
- [PostgreSQLとMongoDB増加 - 5月データベース人気ランキング](https://news.mynavi.jp/article/20200503-1029382/)
XCUITestからIAPのシートを操作する

Xcode12から[StoreKit Configuration](https://developer.apple.com/documentation/storekit/in-app_purchase/testing_in-app_purchases_in_xcode)が追加され、今まで自前でモックを作成していたようなStoreKit周りの処理を簡単に記述できるようになりました。

XCTestはこれで難なく進めていけるのですが、XCUITestで処理を進めようと思うとAppleの標準シートが表示され、購入への確認操作を要求されます。しかし、インスタンス化したテスト対象の`XCUIApplication`からは操作ができません。

この操作は以下のように`SpringBoard`を操作することで実行可能です。

```swift
let springboardApp = XCUIApplication(bundleIdentifier: "com.apple.springboard")
springboardApp.buttons["Confirm"].tap()
```

他にも、iCloud連携をしているアプリケーションではアカウントへのログインを要求するダイアログが表示されるのですが、同じように`springBoardApp`の要素にアクセスすることでアクセス可能です。

```swift
let signInAlert = springboardApp.alerts.element
signInAlert.buttons["Cancel"].tap()
```

# 推測
おそらくですが、XCUITestの実行中に表示されるAppleの標準ダイアログなどは全て上記のSpringBoard経由で操作できるのではと考えています。異なるケースあれば、教えていただけると助かります。

ちなみに、このSpringBoardを操作すれば、アプリ削除の自動テストも実行できるようです。

[https://qiita.com/bbq-all-stars/items/be63ecddea15ec7453cc](UITestで任意のタイミングでアプリを削除する)

# 注意
シミュレーター実行時のみ使えるテクニックなので、実機では動きません。

# 参照
[iPhoneのホーム画面をデバッグしてみよう](https://qiita.com/hongmhoon/items/739fa1ab6a63311c1eaf)

一次情報を探したのですが見つからずでした。
【Javascript】Leafletでポップアップを全て開く or 全て閉じる

#概要
LeafletでMap上に表示する複数のポップアップを全て表示したり、任意のタイミングで全て閉じる方法で詰まったのでメモ。

#全て開く
方法は簡単でbindPopupする時に、openPopup()と付け加えるだけ。
注意点としてはポップアップは<b>デフォルトでは一つずつしかマップで開けない</b>ようになっているため
autoCloseというオプションをfalseに設定しておく必要がある。

```javascript
// マーカーの見た目を定義
var divIcon = L.divIcon({
  html: '<div>マーカー</div>',
  className: 'marker', 
  iconSize: [100, 20]
});
// マップに追加する
marker = L.marker([35.6896, 139.6918], {icon:divIcon }).addTo(map);
// バインド時にautoCloseをfalseに設定
marker.bindPopup(popuphtml,{autoClose:false}).openPopup();
```
上記をMapに追加する時に設定してやれば、例えばページを開いた時に全てのポップアップを表示するという動作も可能。

#全て閉じる
開いたpopupを閉じる手段の一つとしてはclosePopup()がある。

```javascript
// マーカーを閉じる
marker.closePopup();
```

ただ、この方法ではautoClose:falseに設定した複数のpopupを一斉に閉じる事ができず、<b>「最後に開いたpopupを一つだけ閉じる」</b>という動作が行われる。

この問題を解決するなら、Layerに閉じたいマーカーを入れて、eachLayerを使って回すという方法が手っ取り早い。

```javascript
// マップに追加するマーカーをまとめるレイヤーを作成
markertGroup = new L.layerGroup();

// マーカーの定義を省略(=marker)
// マップ追加時にレイヤーに登録する
markertGroup.addLayer(marker).addTo(map);
// 表示済みのレイヤーを削除する
markertGroup.eachLayer(function (layer) {
    markertGroup.removeLayer(layer);
});
```

上記のようにeachLayerでremoveLayerを回してやれば、簡単にmap上の複数の要素を削除する事ができる。
内部にif文を加えて捕捉の条件を付け加えれば<b>「特定の値を持つ要素のみの削除」</b>なども可能

```javascript

marker.id= 1;
const number = 1;
markertGroup.eachLayer(function (layer) {
    // marker.idの値が1のものを削除する
    if (layer.id == number) {
       markertGroup.removeLayer(layer);
    }
});
```

##参考
[レイヤーがポリゴンであるLeaflet LayerGroupで特定のレイヤーを見つける]
(https://www.it-swarm.jp.net/ja/javascript/%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%81%8C%E3%83%9D%E3%83%AA%E3%82%B4%E3%83%B3%E3%81%A7%E3%81%82%E3%82%8Bleaflet-layergroup%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E3%82%8B/823093436/)
[
Documentation - Leaflet](https://leafletjs.com/reference-1.0.3.html)
JAVA Convert short[] to byte[]

Method 1：

```
byte [] ShortToByte_ByteBuffer_Method(short [] input)
{
  int index;
  int iterations = input.length;

  ByteBuffer bb = ByteBuffer.allocate(input.length * 2);

  for(index = 0; index != iterations; ++index)
  {
    bb.putShort(input[index]);    
  }

  return bb.array();       
}

```

Method 2:

```
byte [] ShortToByte_Twiddle_Method(short [] input)
{
  int short_index, byte_index;
  int iterations = input.length;

  byte [] buffer = new byte[input.length * 2];

  short_index = byte_index = 0;

  for(/*NOP*/; short_index != iterations; /*NOP*/)
  {
    buffer[byte_index]     = (byte) (input[short_index] & 0x00FF); 
    buffer[byte_index + 1] = (byte) ((input[short_index] & 0xFF00) >> 8);

    ++short_index; byte_index += 2;
  }

  return buffer;
}
```
Windows 10(WSL2) vs Ubuntu パフォーマンス計測

300万レコードくらいの機械学習（LightGBM）の前処理、トレーニングにどれくらいの時間がかかるか計測してみました。
比較対象はWindows10 Pro vs Ubuntu 18 です。

実行環境はDockerでWindowsもUbuntuも同じDockerfile、docker-composeから構成されています。
（WindowsのDockerはWSL2を使用）

マシン構成は以下となっています。

* CPU：Corei7-9700K
* メモリ：64GB
* ハードディスク：SSD
* （今回はGPUは使用していません）

同じタイプのSSDのハードディスクを切り替える構成で、WindowsとUbuntuでハードウェアの優劣はない構成です。


### Windows 10 Pro 結果

* 特微量前処理
    * 1,003秒
    * 16分
* 学習（LightGBM）
    * 1,116秒
    * 18分

（Windowsで実行時に特にエラーになる事はありませんでした。）


### Ubuntu 18.04.5 LTS 結果

* 特微量前処理
    * 908秒
    * 15分
* 学習（LightGBM）
    * 1,049秒
    * 17分


### 結論

Windowsで10%くらいのパフォーマンス減衰がおきている模様。
このくらいの速度感であれば十分使い物になるかなという印象。
一般的なweb系などの開発では体感ではおそらく分からないレベルかと。

### 追記

#### DockerfileのCMDが正常に動かない

WSL2のデフォルトbackendではDockerfileのCMDのpathが見つからないというエラーが発生しました。backendをUbuntuに変えることでエラーは解消しました。

#### windows insider preview で無限再起動

GPUを試してみようとwindows insider previewを入れてみましたが起動してしばらく経ってからWindowsのエラーが発生して再起動を繰り返すようになってしまいました。バックアップを取っていなかった為、泣く泣くOSをクリーンインストールをする羽目になりました。要注意です。

#### Web開発は依然として遅い

Web開発しているものもWindowsのDockerで動かしてみましたがUbuntu(WindowsのWSL2ではなくピュアUbuntu)のDockerと比べる体感ではっきりわかるくらい遅いです。おそらくWebの方がファイルアクセスが頻繁にされているからではないかと思います。

個人的にCPU OnlyであればWindowsも機械学習系は許容範囲内かなと思いましたがWeb開発についてはUbuntuから乗り換える気にはなれません。
【NW001】仮想ネットワーク（VNETのみ）を設計する

# Azure仮想ネットワーク（VNET）のパラメータがわからない
わりとわかりやすいパラメータではあったんですが、ちょっと調べました。

## 基本
[サブスクリプション]
VNET作成先のサブスクリプション

[リソースグループ]
VNET作成先のリソースグループ

[名前]
VNETの名前。システムカットでCIDR上げることにして場所気にする必要があるから
VNET_10_0_0_0x24_JapanWest
とかにしたわ。

[地域]
仮想サーバと同じ地域を指定する必要がある。VNETの地域。これと同じ場所に仮想サーバ作成されます。つまり、仮想サーバを複数リージョンに作成させたい場合はVNETも複数作成必要です。

## IPアドレス
このあたりはCIDRの設計になるのであまり触れません
[IPv4 アドレス空間]
仮に以下とします。
192.168.0.0/25

[IPv6 アドレス空間の追加]
IPv6を使いたい場合設定

[サブネットの追加]
192.168.0.0/25に追加するサブネットということで、
192.168.0.0/27などを指定することになります。
ここではわけ合って192.168.0.32/27を指定。

サブネットの名前は
snet_192.168.0x27
とかがいいのかなと思います。

## セキュリティ
[BastionHost]
WEB経由でアクセス可能な踏み台サーバ。
つまり踏み台サーバにRDP/SSHなどで接続してAzure内部の仮想サーバにアクセスするのではなく、Azure portalからWEBでアクセスできる踏み台サーバ。仮想サーバを選択してBastionという選択項目があるのでそこから接続できるようになる。

++-----------------------------------------
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111921/91ac04b7-612e-4d3e-ae79-945a1133b8e6.png)
で
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111921/f25618a4-af7b-c822-7e9b-afa811cc7f4b.png)
という感じ
++-----------------------------------------

[AzureBastionSubnet のアドレス空間]
IPアドレスの設定画面で指定したIPv4アドレス空間に存在し、なおかつサブネットの追加でサブネットをまだ割り当ててない部分の割り当てが必要。
なので192.168.0.0/27などを指定。

[DDos Protection Standard]
DDos攻撃をいい感じに処理するための機能を盛り込むかどうかの指定
事前にDDoS保護プランを作成していないと設定できないみたい。

[ファイアウォール]
このNWにファイアウォール機能を設定するかどうかの指定

## タグ
ご自由にどうぞ
【CSS】white-spaceの使い方

#プログラミング勉強日記
2021年3月8日

#white-spaceとは
　テキスト内の改行・スペース・タブをどのように扱うか指定できる。

#white-spaceの使い方

```css
white-space: 値;
```

　この値には、`normal`, `nowrap`, `pre`,  `pre-wrap`, `pre-line`のどれかを指定する。
　
　normalは初期状態と同じで、HTMLを使用するときのいつも通り表示される。連続した半角スペース/tab/改行を全て1つの半角スペースとして表示し、改行は通常通り横幅いっぱいになったときに行う。
　nowrapは、normal同様連続した半角スペース/tab/改行を全て1つの半角スペースとして表示する。テキスト内で改行を行われた場合に改行する。
　preは、半角スペース/tab/改行をそのまま表示し、改行は横幅いっぱいになっても改行を行わない。テキスト内で改行を行われた場合に改行する。
　pre-wrapは、normal同様連続した半角スペース/tab/改行を全て1つの半角スペースとして表示する。改行は横幅いっぱいになってもテキスト内で改行を行われた場合でもどちらの場合も改行する。
　pre-lineは、preと同様に半角スペース/tab/改行をそのまま表示する。改行はpre-wrap同様に横幅いっぱいになってもテキスト内で改行を行われた場合でもどちらの場合も改行する。
　pre-lineは、normal同様連続した半角スペース/tab/改行を全て1つの半角スペースとして表示する。改行はpre-wrap同様に横幅いっぱいになってもテキスト内で改行を行われた場合でもどちらの場合も改行する。

これらを表にまとめると以下のようになる。

| 値 | 表示の説明 | 改行の説明
|:--:|:--:|:--:|
| normal（初期値）| 連続した半角スペース/tab/改行を全て1つの半角スペースとして表示 | 横幅いっぱいになったときに改行 |
| nowrap | 連続した半角スペース/tab/改行を全て1つの半角スペースとして表示 | テキスト内で改行を行われた場合に改行 |
| pre | 半角スペース/tab/改行をそのまま表示 | 改行は横幅いっぱいになっても改行を行わない。テキスト内で改行を行われた場合に改行 |
| pre-wrap | 半角スペース/tab/改行を全て1つの半角スペースとして表示 | 横幅いっぱいになってもテキスト内で改行を行われた場合でもどちらの場合も改行 |
| pre-line | 連続した半角スペース/tab/改行を全て1つの半角スペースとして表示 | 横幅いっぱいになってもテキスト内で改行を行われた場合でもどちらの場合も改行 |


#参考文献
[CSSで改行ルールを簡単設定！改行をコントロールする方法](https://www.sejuku.net/blog/75317)
[white-space](https://html-coding.co.jp/annex/dictionary/css/white-space/)
tiktokでogp相当の情報をAPIで取得する（ruby）

tiktokのスクレイピングをしてogp情報をとってくる処理を書いていたのだがいつのまにか下記のようにstatus code1000で弾かれるようになってしまっていた。

```
[25] pry(main)> html = open(movie_url) do |f| f.read; end
=> "{\"statusCode\":10000,\"verifyConfig\":{\"code\":10000,\"type\":\"verify\",\"subtype\":\"slide\",\"fp\":\"verify_5f101e29a0ad54278347a24437cfcb93\",\"region\":\"sg\",\"detail\":\"2SdJGObfW85-lX4dEGohkmh8YbPmZYiXwIh1pqrEUuohsJqr4t3XjgXHtkBHWheNJbj4MB*CVwF1ayKFmhUFcJY2yAgBxyatF0XXzv0*xk*DmEz7Og6oE0nS1mFuZXdkJE*Z05uOnCgTkh4d4yy7xfv6EiiQJGBxdHDxp21vXCZjphcNMaY6YoCrq-5wRulWVle0lP3RJyqJQUFbtIP8pH0LICH8SRGn9a6mItvTEiEwiHCfJHBxhTUf1kFCYkGm1gBpVE1s45qbaNPeVELCCU0732nlU1VLR7Jm16yTIne64NABwJSaXFAl19NrjsfHrV-Cxq*d4kuVUBERzDIIncNGgQ3m6MLdwGLw*H4xfl94O1LId2V5zlOltVL1gYtral9VUYNMskUBWclUpWt2zrUfpbVzuUg.\"}}"
```
どうしようかなと思ったが、調べてみたらTikTokのAPIでogp相当の情報をとってこれるようだったので、apiを通して取得してくるように修正した。ドキュメントもあるので別に何も大変なことはない。

https://developers.tiktok.com/doc/Embed

```
https://www.tiktok.com/oembed?url=https://www.tiktok.com/@scout2015/video/6718335390845095173
```
このような形で情報を取得したいtiktokのURLをurlパラメータに渡してhttps://www.tiktok.com/oembed を叩くだけでいい。そうすると下記のようなレスポンスが返ってくる。

```
{
  "version": "1.0",
  "type": "video",
  "title": "Scramble up ur name & I’ll try to guess it😍❤️ #foryoupage #petsoftiktok #aesthetic",
  "author_url": "https://www.tiktok.com/@scout2015",
  "author_name": "Scout & Suki",
  "width": "100%",
  "height": "100%",
  "html": "<blockquote class=\"tiktok-embed\" cite=\"https://www.tiktok.com/@scout2015/video/6718335390845095173\" data-video-id=\"6718335390845095173\" style=\"max-width: 605px;min-width: 325px;\" > <section> <a target=\"_blank\" title=\"@scout2015\" href=\"https://www.tiktok.com/@scout2015\">@scout2015</a> <p>Scramble up ur name & I’ll try to guess it😍❤️ <a title=\"foryoupage\" target=\"_blank\" href=\"https://www.tiktok.com/tag/foryoupage\">#foryoupage</a> <a title=\"petsoftiktok\" target=\"_blank\" href=\"https://www.tiktok.com/tag/petsoftiktok\">#petsoftiktok</a> <a title=\"aesthetic\" target=\"_blank\" href=\"https://www.tiktok.com/tag/aesthetic\">#aesthetic</a></p> <a target=\"_blank\" title=\"♬ original sound - 𝐇𝐚𝐰𝐚𝐢𝐢𓆉\" href=\"https://www.tiktok.com/music/original-sound-6689804660171082501\">♬ original sound - 𝐇𝐚𝐰𝐚𝐢𝐢𓆉</a> </section> </blockquote> <script async src=\"https://www.tiktok.com/embed.js\"></script>",
  "thumbnail_width": 720,
  "thumbnail_height": 1280,
  "thumbnail_url": "https://p16.muscdn.com/obj/tos-maliva-p-0068/06kv6rfcesljdjr45ukb0000d844090v0200010605",
  "provider_url": "https://www.tiktok.com",
  "provider_name": "TikTok"
}

```


コード（ruby）

```
uri = URI.parse("https://www.tiktok.com/oembed?url=#{params[:tiktok_url]}")
response = Net::HTTP.get_response(uri)
res_json = JSON.parse(response.body)
html_doc = res_json["html"]
title = res_json["title"]
ogp_image = res_json["thumbnail_url"]
```
【Ruby】クラスの中のアットマークの意味。@と@@の違いは？（インスタンス変数とクラス変数の実例）

【Ruby】クラスの中のアットマークの意味。@と@@の違いについて。

##@と@@の違い
どちらも変数を表す。インスタンスで使う変数か、クラスで使う（すべてのインスタンスで共通）の変数かの違い。

| 項目 | 意味 | 使い方 |
|:--|:--|:--| 
| @  | インスタンス変数  | @<変数名> |
| @@  | クラス変数  | @@<変数名> |



##インスタンス変数とクラス変数の使い方

###インスタンス変数
インスタンス変数は、生成したインスタンスごとに値がセットされるため、それぞれで固有となる。

```rb:
class Aaa
  #インスタンス変数を定義
  def setName(lastname, firstname)
    @name = lastname + " " + firstname
  end

  #メソッドを定義
  def hello
    p "#{@name}さん"
  end
end

#インスタンスの生成
p1 = Aaa.new
p2 = Aaa.new

#インスタンス変数に名前をセット
p1.setName("山田", "克巳")
p2.setName("田中", "次郎")

#インスタンスメソッドの呼び出し
p1.hello  # => "山田 克巳さん"
p2.hello  # => "田中 次郎さん"
```


###クラス変数
クラス変数は、**すべてのインスタンスで共通**となる。**上書きされる**ため、後からセットした値が入る。

```rb:
class Aaa
  #クラス変数を定義
  def setName(lastname, firstname)
    @@name = lastname + " " + firstname
  end

  #メソッドを定義
  def hello
    p "#{@@name}さん"
  end
end

#インスタンスの生成
p1 = Aaa.new
p2 = Aaa.new

#インスタンス変数に名前をセット
p1.setName("山田", "克巳")
p2.setName("田中", "次郎")

#インスタンスメソッドの呼び出し
p1.hello  # => "田中 次郎さん"
p2.hello  # => "田中 次郎さん"
```

各インスタンス毎で名前をセットしたが、後からセットした名前で上書きされるため、出力はどちらも後からセットした値になる。
Unityのテクスチャ


# [Unity】Texture を Texture2D に変換する拡張メソッド](https://baba-s.hatenablog.com/entry/2018/02/26/210100)

```
using UnityEngine;

public static class TextureExt
{
    public static Texture2D ToTexture2D( this Texture self )
    {
        var sw = self.width;
        var sh = self.height;
        var format = TextureFormat.RGBA32;
        var result = new Texture2D( sw, sh, format, false );
        var currentRT = RenderTexture.active;
        var rt = new RenderTexture( sw, sh, 32 );
        Graphics.Blit( self, rt );
        RenderTexture.active = rt;
        var source = new Rect( 0, 0, rt.width, rt.height );
        result.ReadPixels( source, 0, 0 );
        result.Apply();
        RenderTexture.active = currentRT;
        return result;
    }
}

```

# Unityのテスクチャコピー(deep)

```
	{
		//参照だとダメ
		//		m_materials[name_list_curr].mainTexture = m_updatetex2d;

		//ConvertTextureはダメ: 何も表示されない
		//Graphics.ConvertTexture(m_updatetex2d, m_materials[name_list_curr].mainTexture);

		// CopyTextureはdeepcopy:何も表示されない
		//Graphics.CopyTexture(m_updatetex2d, m_materials[name_list_curr].mainTexture);

		//SetPixelsによるdeepcopy
		if (true)
		{
			var originalTexture = m_updatetex2d;
			Texture2D copyTexture = new Texture2D(originalTexture.width, originalTexture.height, TextureFormat.ARGB32, false);
			copyTexture.SetPixels32(originalTexture.GetPixels32());
			copyTexture.Apply();
			m_materials[name_list_curr].mainTexture = copyTexture;
		}

		// 外部テクスチャはコピーできない？
		if (false)
		{
			int texid = getTextureID4Unity();
			if (texid != -1)
			{
				IntPtr texidptr = new IntPtr(texid);
				Texture2D nativeTexture = Texture2D.CreateExternalTexture(
					tex_sizeX, tex_sizeY,
					TextureFormat.ARGB32,
					false, false,
					texidptr
				);

				IntPtr nativeData = nativeTexture.GetNativeTexturePtr();
				m_tex2d_2.UpdateExternalTexture(nativeData);

				{
					var originalTexture = m_tex2d_2;
					Texture2D copyTexture = new Texture2D(originalTexture.width, originalTexture.height, TextureFormat.ARGB32, false);
					copyTexture.SetPixels32(originalTexture.GetPixels32());
					copyTexture.Apply();
					m_materials[name_list_curr].mainTexture = copyTexture;
				}

				//m_materials[name_list_curr].mainTexture = m_tex2d_2;
			}
		}
	}
```
2021年データ分析に関するビジネストレンド--レアルタイムデータ

**元記事：[https://jp.scrapestorm.com/tutorial/2021-data-analysis-business-trends-real-time-data/](https://jp.scrapestorm.com/tutorial/2021-data-analysis-business-trends-real-time-data/)**

ビッグデータは情報通信技術の発展によって蓄積されてきたもので、自身の技術発展ロジックに従い、生産効率を向上させることからより高度な知能段階に成長して行きます。ありふれた収集端末は大量のデータを収集して、計算技術は絶えず進歩するにつれて、人々に強力なデータ分析能力を提供してくれました。本文では、今回はデータ分析におけるレアルタイムデータのビジネストレンドに対する影響を予測します。

リアルタイムのデータに対する需要は2020年に大きく変化した、今年も引き続き発展します。ビッグデータの発展につれて、リアルタイムで正確的にデータを更新することは、バースト・イベントに対処するために適切な戦略を立てる上でとても重要です。一部の国はすでにデータを使って最善の方策を決めました。会社もデータ爆発の時代に淘汰されないように行動しなければなりません。
![大屏.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/af495623-c028-609b-12b6-cae8ea5ced10.gif)

リアルタイムのデータには、未来の変化を把握し、ビッグデータ時代によりよく適応します。ビジネスにおいても、予測と警報は、将来の戦略を策定し、より多くの変数対応できるに役たちます。また、リアルタイムダッシュボードを実施すると、すぐにその業務に関する情報を訪問し、潜在的な問題が発生した時に反応します。最新のデータはいつまでも重要です。これはいくつかの会社が生存できて、他の会社が生存できない原因の一つです。

また、リアルタイムのデータは日常生活の中の規範になりました。一番直観的なのは記者会でリアルタイムのデータを分析して生成されたデータテーブルです。

疑いなく、業界の動向を分析し、リアルタイムデータを2021年の主要な駆動力の一つになります。
VSCodeのホバーの枠線の色と背景色を変更する方法

Visual Studio Codeでダーク系のテーマを使用しているとホバー(マウスカーソルを属性などに載せたときに表示されるもの)の境界が見づらいことがあります。
そこでその枠線の色と背景色を変更します。

`Shift+Command+P` から `Preferences: Open Settings (JSON)` を選択して、`settings.json` に以下を追加します。

```settings.json
   "workbench.colorCustomizations": {
        "editorHoverWidget.background":"#2c2c2c",
        "editorHoverWidget.border": "#727272"
    },
```

#### 変更前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155587/ba21b6b3-f838-3e9a-5b39-a8e100d561ca.png)

#### 変更後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155587/7f17b9bb-185a-6342-1930-1df471390397.png)
foo, bar, bazとは一体なんなのか？

今更ながら、foo, bar, bazって何！？と思ったので調べてみた。

##どこで出てくるか？
チュートリアルなど説明のメソッド名やクラス名などで使われることが多い。

```rb:foo,barの例
module Foo
  extend ActiveSupport::Concern
  included do
    def self.method_injected_by_foo
      ...
    end
  end
end

module Bar
  extend ActiveSupport::Concern
  include Foo

  included do
    self.method_injected_by_foo
  end
end
```


##意味
**意味はない**。

プログラミングの世界で、**仮の名前を設定**するときに使われる。日本語の、hoge, fuga, piyo, hogehogeなどと同じ。

意味のない単語を[`メタ構文`](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BF%E6%A7%8B%E6%96%87%E5%A4%89%E6%95%B0)と呼ぶ


##順番
使う順番に決まりはないが、次の順で使われることが多い。

foo
bar
baz
qux
quux
corge
,,,


<br>
これらが出てきたら、名前つけるのめんどくさいから、適当に仮の名前を設定してあると認識すればOK。
Linuxコマンドのメモ

##ディレクトリ操作　現在のディレクトリの場所を表示　[pwd]##
   ・ディレクトリの中身ではなく、ディレクトリの現在の場所を指す。

```
pwd
```



##画面をクリアする　[clear]##
・ctrl + Lでも可能。

```
clear
```


##ディレクトリの操作　ディレクトリの作成　[mkdir]
```
mkdir 'ディレクトリ名'
```

##ディレクトリの操作　中身をリスト表示　[ls]
```
ls
```
・lsの後に-lとつけると所有者と権限なども表示される

```
ls -l
```

##ディレクトリの操作　ディレクトリ間を移動　[cd]

```
cd 'パス指定'
```

##サブディレクトリを含んだディレクトリの作成　[mkdir -p]

```
mkdir -p 'ディレクトリ名/サブディレクトリ名'
```

##ディレクトリの移動　[mv]

```
mv 'ディレクトリ名' '移動先のディレクトリ名'
```

##ディレクトリの削除　[rmdir, rm]

・rmdirは空のディレクトリしか削除できないため、実務ではあまり使用されない。

```
rmdir 'ディレクトリ名'
```
・実務では主にrmが使用される。
・オプションの-rはリカーシブでディレクトリの中身全ても含むということ。

```
rm -r 'ディレクトリ名'
```

##ディレクトリのコピー　[cp]
・オプションの-rは先述したように、リカーシブでディレクトリの中身も全て含むことです。

```
cp -r 'コピー元のディレクトリ名' 'コピー先のディレクトリの名前'
```
##ファイルの操作　作成　[touch]

```
touch 'ファイル名'
```

##ファイル操作　移動・リネーム　[mv]
・移動はディレクトリと同様です。

```
mv 'ファイル名' '移動先のディレクトリ名'
```

・ファイルのリネームも可能

```
mv '変更したいファイル名' '変更後のファイル名'
```

##ファイルの内容を確認する　[cat]

```
cat '確認したいファイル名'
```

##ファイルの内容を確認する　[less]
・catとの相違点はスクロールが出来る。

```
less '確認したいファイル名'
```
GithubのIssue・pull requestを用いた疑似チーム開発

### はじめに
- Git HubのIssueとpull requestを用いて疑似チーム開発をしました。その備忘録です。

### Issueとは
- 「[Git hub,Issueについて](https://docs.github.com/ja/github/managing-your-work-on-github/about-issues)」によると、Issueはソフトウェア開発のやることリスト機能的なものらしい。

>リポジトリ中の Issue で、ユーザフィードバックの収集、ソフトウェアバグの報告、完了したいタスクの編成ができます。 Issueは、単なるソフトウェアのバグを報告する場所以上の働きをします。

### pull requestとは
- 一方で、pull requestは、「[さる先生のGit入門 プルリクエストを使ってみよう](https://backlog.com/ja/git-tutorial/pull-request/06/)」によると、プルリクエストは,個人での開発の変更分を,他の人にレビューしてもらう機能と言われています。


>プルリクエストとは簡単に言うと、開発者のローカルリポジトリでの変更を他の開発者に通知する機能です。
>プルリクエストは次のような機能を提供します

>・機能追加や改修など、作業内容をレビュー・マージ担当者やその他関係者に通知します。
>・ソースコードの変更箇所をわかりやすく表示します。
>・ソースコードに関するコミュニケーションの場を提供します。


### pull requestの手順
1. 変更を`git add -A`, `git commmit -m "変更内容"`する
2. リモートブランチにプッシュする。`git push origin ブランチ名`
3. 対処のリポジトリのpull requestタブを選択し、new pull requestをクリック
4. ターゲットブランチ(プルリクエストをマージする対象のブランチ)とプルリクエストブランチ(マージしてもらうブランチ)を入力する
5. `create pull request`をクリックする
6. レビュー担当者が,Files changedタブを選択し、修正してほしい箇所がある場合は,ソースコードにコメントをする
7. 開発者は,レビュー内容を元に修正を行い,再度コミット,プッシュを行う。 `git push origin 作業ブランチ名`
8. 開発者は,修正した旨を伝えるために,プルリクエストにコメントをする
9. レビュー担当者は,問題がない場合は、マージする。「conversation」タブの,「Merge pull request」ボタンをクリックする

### 参考資料
- [Git hub,Issueについて](https://docs.github.com/ja/github/managing-your-work-on-github/about-issues)
- [さる先生のGit入門 プルリクエストを使ってみよう](https://backlog.com/ja/git-tutorial/pull-request/06/)
【Ruby】includeとextendの違い。クラスメソッドとインスタンスメソッドの違いと実例。

【Ruby】includeとextendの違い。クラスメソッドとインスタンスメソッドの違いと実例。

##目次

1. [includeとextendとは?](#includeとextendとは)
2. [includeとextendの違い](#includeとextendの違い)
3. [クラスメソッドとインスタンスメソッドの違い](#クラスメソッドとインスタンスメソッドの違い)
4. [クラスメソッドとインスタンスメソッドの使い分け](#クラスメソッドとインスタンスメソッドの使い分け)
7. [includeとextendの実例](#includeとextendの実例)



<br>
##includeとextendとは？
どちらも、クラスの中でモジュールを呼び出すときに使う（mixin ミクシン）。

[モジュールとmixinとは？](https://qiita.com/yuta-38/items/da7e564b821629864f60)


##includeとextendの違い
読み込んだモジュールのメソッドを、インスタンスメソッドかクラスメソッドのどちらで読み込むかの違い。

| メソッド | 意味 |
|:-:|:--|
| include  | インスタンスメソッドとして読み込む  |
| extend  | クラスメソッドとして読み込む  |


<br>
##クラスメソッドとインスタンスメソッドの違い

その名の通り、クラスから呼び出せるメソッドか、インスタンスから呼び出せるメソッドかの違い。


| メソッド | 呼び出し |
|:--|:--|
| クラスメソッド  | <クラス名>.<メソッド名>  |
| インスタンスメソッド  | <クラス名>.new.<メソッド名> |

クラスメソッドは、クラスから**直接メソッドを呼び出せる**。

インスタンスの場合は、クラスから**`new`を使って、インスタンスを生成して、メソッドを呼び出す**。



<br>
###クラスメソッドとインスタンスメソッドの使い分け

| メソッド | 用途 |
|:--|:--|
| クラスメソッド  | 全体で共通  |
| インスタンスメソッド  | インスタンス毎に固有 |


####インスタンスメソッド
**メソッドの結果が生成したインスタンス毎に固有**となるメソッドを定義していく。（例えば、苗字や名前を登録するなど。）

```rb:インスタンスメソッド
class <クラス名>
  def <メソッド名>
    処理
  end
end
```

```rb:呼び出し
<クラス名>.new.<メソッド名>
```



<br>
####クラスメソッド
DBから指定したデータを抽出する場合など、**どのインスタンスでも同じ答えが返るメソッドに使う**。

- メソッド名の前に`self`がつく
- メソッドはクラス名の後で直接呼び出せる（インスタンスを生成する必要がない）


```rb:インスタンスメソッド
class <クラス名>
  def self.<メソッド名>
    処理
  end
end
```

```rb:呼び出し
<クラス名>.<メソッド名>
```



<br>
##includeとextendの実例

###include
インスタンスメソッドとして読み込む

```rb:include
module Aaa
  def hello(name)
    p "こんにちは、#{name}さん"
  end
end


#モジュールの読み込み（mixin）
class Xxx
  include Aaa
end 

#メソッドの実行
Xxx.new.hello("山田")

 => "こんにちは、山田さん"
```

**▼クラスはNG**

```rb:NG
Xxx.new.hello
NoMethodError (undefined method `hello' for Xxx:Class)
```


<br>
###extend
クラスメソッドとして読み込む

```rb:extend
module Bbb
  def hello
    p "皆さん、こんにちは"
  end
end


#モジュールの読み込み（mixin）
class Yyy
  extend Bbb
end 

#メソッドの実行
Yyy.hello

 => "皆さん、こんにちは"
```


**▼インスタンスはNG**

```rb:NG
Yyy.new.hello
NoMethodError (undefined method `hello' for #<Yyy:0x00007f81b2083410>)
```


<br>
以上。
Rails newまでまとめてみた

アウトプット兼ねてまとめてみました。
＊アドバイス訂正などありましたらご指摘お願いいたします。

# ステップ１

```
mkdir xxx
```
でフォルダー作ってそこに移動

#ステップ２

```
gem install rails 
↓
rbenv exec gem install bundler
```
`rbenv exec`はrbenvでインストールしたrubyを使ってbindlerを入れるらしい。

#ステップ３

```
rails new プロジェクト名　-d mysql
```
 作成したプロジェクトに移動
↓
`bundle install --path vendor/bundle`が非推奨になった↓を代わりにやる

```

bundle config set --local path 'vendor/bundle'
```
`$bundle config`コマンドで確認できます。
https://qiita.com/devzooiiooz/items/8babd82f780f01812f9d

二回目以降は`bundle install`のみでOK

#bundle configのglobalとlocalの違い
--global は設定を ~/.bundle/config に保存する。
--local は設定を application_name/.bundle/config に保存する。



#ステップ4

```
bundle exec rails s
```
[Django][RestFramework]Object of type "AA" is not JSON serializable エラー

生のSQL文を実行したいと考え模索していたが、今回のエラーが解決できたので備忘録として残す。

##エラー内容
Object of type "AA" is not JSON serializable
とエラーが出た　
AAはJson形式ではないという内容

##解決

```views.py
from .models import BaseAPI
from .serializer import BaseAPISerializer
from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response


class BaseAPIViewSet_GET(APIView):
    def get(self, request, pk, format=None):
        sql = "SQL文"
        queryset = BaseAPI.objects.raw(sql,pk)
        return Response(queryset.query) #ここが解決ポイント
```

```urls.py
path('user/<int:pk>/test', BaseAPIViewSet_GET.as_view(), name='GET'),
```

ちなみにSQL文について
変数を使用した複数行に渡ってSQL文を書きたいと考えていた時があったが、

```sql
SELECT * FROM api WHERE name1=(SELECT name2 FROM api WHERE id=%s)
```

```views.py
queryset = BaseAPI.objects.raw(sql,[pk]) #ここで実行
```
SELECTの中にSELECTを書くことが可能なため、一行のSQL文で自在に操作が可能
Blazor + Electron.NETでファイル操作を行いたいときの注意点

# はじめに
以前[Blazor + Electron.NETを試してみた](https://qiita.com/minoura_a/items/6361a213fdb86343c441)という記事でBlazorで作成したWebアプリを簡単にデスクトップアプリとして扱えるようになることを紹介しました。その記事の最後にElectronのファイルダイアログを操作することができるということと、[参考リンク](https://narazaka.hatenablog.jp/entry/2019/12/24/Blazor%2BElectron_NET%E3%81%A7%E3%82%AF%E3%83%AD%E3%82%B9%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0GUI%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%9F%E6%99%82%E3%81%AE%E3%83%A1#:~:text=Web%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AA%E3%81%AE%E3%81%A7%E3%81%93%E3%82%8C%E3%81%AF,%E3%81%AA%E6%8A%80%E8%A1%93%E3%81%A8%E3%81%AE%E3%81%93%E3%81%A8%E3%80%82)の紹介をしました。参考リンクには書かれていない注意点があったため、今回はそのことについてまとめます。実際のファイル操作の実装は参考リンクが分かりやすいので、そちらを参照ください。

# Electronのファイルダイアログ操作について
Electronでローカルファイルの選択ダイアログを実装するときには、dialogモジュールのshowOpenDialog関数を用います。詳しくは[こちら](https://qiita.com/unhurried/items/b622726851d22e36dccb)。
Electronのdialogモジュールなどの[リモートモジュール](https://imfly.gitbooks.io/electron-docs-gitbook/content/jp/api/remote.html)を使う際にWebPrefarenceのenableRemoteModuleというプロパティをtrueに設定しないと利用できないそうです。詳しくは[こちら](https://github.com/electron/electron/blob/master/docs/breaking-changes.md#default-changed-enableremotemodule-defaults-to-false)。

# Elecrron.NETを使用する場合のenableRemoteModuleプロパティの設定
Electron.NETを使用する際、この設定ができるAPIが公開されているのは最新のElectronNET.APIのみでした(2021/2/26に確認した時点でV11.5.1)。startup.csファイルでElectronのウィンドウを開く処理を行う際に、WebPreferencesの設定を行うことができます。

```cs
var browserWindow = await Electron.WindowManager.CreateWindowAsync(new BrowserWindowOptions
{
	WebPreferences = new WebPreferences() { EnableRemoteModule = true },
});
```

# ElectronNET.APIの最新バージョンと対応するBlazorプロジェクトのフレームワークのバージョンについて
ElectronNET.APIの最新バージョンは.NET5に対応しています。Blazorのサーバーアプリのプロジェクトを作成した段階では、プロジェクトの対象のフレームワークが.NETCore 3.1で作成されるのではないかと思います。その状態でElectron.NETの最新バージョンをインストールしようとすると、.NETCore3.1と互換性が無いという旨のエラーが出てインストールできないためご注意ください。

また、Blazorのサーバーアプリではなく、Blazor WASMを使用することができないかも試しました。ElectronNET.APIをインストールしようとすると、上記と同様にBlazor WASMの対象フレームワークである.NETStandard2.1と互換性が無いという旨のエラーがでてインストールできないです。（ElectronNET.APIの以前のバージョンであっても.NETCoreにしか対応していないため、現状Blazor WASMとの組み合わせができないみたいです。）

したがって、現状Blazor + Electron.NETを使用してファイル操作も行うアプリの開発したい場合は
Blazorのサーバーアプリで対象フレームワークを.NET5にして、ElectronNET.APIの最新バージョンを使用するのがよさそうです。

# さいごに
少々細かい話ではありましたが、私が詰まった点でしたのでまとめした。
最後までお読みいただきありがとうございました。
Couchbase Server アーキテクチャー解説: クライアント・クラスター間コミュニケーションにおける独自性

# はじめに

本記事では、Couchbase Serverのアーキテクチャー解説記事の一つとして、主にクライアントとクラスター間のコミュニケーションについて解説します。その解説に進む前に、（クライアント・クラスター間接続を含む）Couchbase Serverにおけるネットワーク間通信の種類について簡単に整理します。

# 承前： コミュニケーション概要

Couchbase Serverは、クライアントからクラスター、ノードからノード、およびクラスターからクラスターへの通信を処理します。また、サードパーティ製品への接続も提供します。

### クライアントとクラスター間
クライアントアプリケーションは、サーバー定義の（複数の）アクセスポイントを介してCouchbase Serverクラスターと通信します。各アクセスポイントは、非暗号化の通信と暗号化通信の両方にポートを提供します。

### ノード間
クラスターノードは、データの複製、インデックスの維持、ノードの状態の確認、クラスター構成への変更の伝達などのために相互通信します。

### クラスター間
Couchbase Server-クラスターは、クロスデータセンターレプリケーションを使用して相互に通信します。

### コネクター
CouchbaseServer-クラスターはサードパーティ製品と通信します。コネクタ。Elasticsearch、Hadoop、Kafka、Spark、およびTalend用のコネクタが提供されています。ODBCおよびJDBC用のドライバーが提供されています。

# クライアント接続における3つのフェーズ
クライアント接続は、認証と承認、検出(Discovery)、およびサービス接続の3つのフェーズで確立されます。

### 認証と承認
クライアントはユーザー名とパスワードで認証します。ユーザーは、Couchbase Serverで定義されたロールに関連付けられており、認証を介してロールを取得します。

### 検出(Discovery)
クラスターマップがクライアントに返されます。これは、現在のクラスタートポロジを示しています。クラスターマップは、クラスターを構成するノードのリスト、ノー​​ド間のサービス配置、およびノード間のデータ配置に関する情報を含みます。

クライアントは、これらの情報を持っているため、適切なノードへアクセスすることができます。これは、単に適切なサービスを提供するノードへアクセスできることを意味しているだけなく、データの作成や（検索クエリではなく、キー/IDによる）取得の際に、そのデータの管理を担当するノードへ直接アクセスができることを意味しています。

ここまでの処理は、ブートストラップと呼ばれます。

### サービスへの接続
クラスターマップを取得すると、クライアントはサービスレベルの操作を実行するために必要な接続を確立します。

この時実行しようとする操作の種類・内容によって、承認が必要になる場合があります。ユーザーのロールが、要求しているリソースへのアクセスに対する適切な特権に関連付けられている場合、アクセスが許可されます。

クラスタートポロジが変更された場合、サービスへの接続要求の際に例外が発生する可能性があります。この場合、検出を再実行し、新しい接続で操作を再試行する必要があります。

# 最後に

本稿の解説の中では、特に「検出」のプロセスの部分は、他の分散アーキテクチャーを持つデータプラットフォームと比べて、Couchbase Serverに独自な部分だといえます。本記事で解説したCouchbaseにおけるプロセスとは異なり、多くの分散アーキテクチャーを持つデータベースでは、クライアントとのコミュニケーションを担当する特別なノードが存在しています。
この違いは、（メモリファーストアーキテクチャに加えて）Couchbase Serverが、低遅延・ハイスループットを実現する要素となっています。
pybind11 + CUDA 利用のメモ

## 背景

pycuda などで Python side から CUDA 呼んでもいいですが, C++ side から CUDA kernel を呼びたいときもあります.


https://www.torsteinmyhre.name/snippets/cuda_python_integration.html

https://github.com/PWhiddy/pybind11-cuda

このあたりのコードを参考にすれば特に問題なく行けました.

numpy 配列(`py::array_t<T>`)の CUDA 変換が主に参考となるでしょう.

## TODO

* [ ] CUDA driver API 版も用意する.
Mockery\Exception\NoMatchingExpectationException を とりあえず解決する方法


Mockery をテストしているとやっているときに配列やオブジェクトを使っていると`NoMatchingExpectationException`が出てきたときにどこが問題だかわからなくなる場合があります。



```php
$this->guzzleClient = Mockery::mock(ClientInterface::class);
$requestResponse = $this->client->request('POST', $apiUrl, ['form_params' => $params]);
$this->guzzleClient
    ->shouldReceive('request')
    ->once()
    ->with('POST',
        'http://test.example.com/article/xxxx/comments',
        ['form_params' => $params])
    ->andReturn($response);
```

```text
Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_0_GuzzleHttp_ClientInterface::request('POST', 'http://test.example.com/article/xxxx/comments', ['form_params' => [...]]). Either the method was unexpected or its arguments matched no expected argument list for this method
```

こういうとき、どの引数が一致せずにエラーが出るのかよくわからなくなります。
なので anyな引数を許可して実行してみることが大事です。


### 解決法： こんなときは Mockery::on を使ってすべての引数を許可する形にしてしまう。

どの引数が原因だかわからないときは、とりあえずエラーが出ずに動くようにすることを優先すると特定が早まった.


```php
$this->guzzleClient = Mockery::mock(ClientInterface::class);
$requestResponse = $this->client->request(
    Mockery::on(function($actual) {
        return true;
    }),
    Mockery::on(function($actual) {
        return true;
    }), 
    Mockery::on(function($actual) {
        return true;
    })
);
```


例えば、弄っているうちに原因が第三引数にあることがわかったので下記のように修正すると↓

### 最終形はこんなの

```php
$form_params = ['form_params' => $params];
$this->guzzleClient = Mockery::mock(ClientInterface::class);
$requestResponse = $this->client->request(
    'POST',
    $apiUrl,
    Mockery::on(function($actual) {
        return is_array($actual) && arrayHasKey($actual,'form_params') && is_array($actual['form_params']);
    })
);
```




### 参考文献：

- 検索時に一番上に出てくるやつ： object.equals を受けてる
    - https://qiita.com/ttn_tt/items/a35638ab12d4dc2ea488
- 謎の判定の厳密比較されているarrayのやつ（どこでついたかわからないPHP_EOLが必要）：
    - https://laracasts.com/discuss/channels/testing/mockerywithargs-wont-match-with-array
- そもそもMockery::onを使って判定をスルーする方法。
    - https://stackoverflow.com/questions/22946306/mockery-no-matching-handler-for-closure/22948810 
- 引数の数を確かめるのも大事
    - https://www.nyamucoro.com/entry/2018/09/05/211448


### その他
上記はチームメンバーの問題解決に口出ししただけなので、自分の手元で動かして動作確認してないことに注意
nicehash REST API 利用のメモ 

## 背景

* nicehash で得られたマイニング収益計算などをスクリプトで処理とかやりたい.

## API key 取得

https://www.nicehash.com/docs/

とりあえずは test 環境でアカウント作ってためすのがよいです.

API 自体は引き出し(withdrawal)や交換などの操作も(許可すれば)可能なので必要に応じて permission を設定しましょう.


private(non-public) API の場合は, 署名が必要なので curl でぺろっとやるのはめんどいです.

https://www.nicehash.com/software-developers

https://github.com/nicehash/rest-clients-demo

の REST client サンプルを参考にするとよいでしょうか.

Organization ID は `Create API Key` のパネルにあります.

サンプルはちょと古いためそのままでは動かないのがあります. nicehash REST API ドキュメントで最新を見てみましょう.

## 注意点

production 環境(実アカウント環境)では, 機種変更などで 2FA を変えた場合, 7 日間ロックされて API key 作れないので注意です!
(moratorium lock によるエラーが出る)
環境構築　OSがMojave以前の場合

#1. Command Line Toolsの導入
##1-1. Command Line Toolsをインストール
ターミナルに入力

```
$ xcode-select --install
```

「インストール」をクリック。
「同意する」をクリック。
#2. Homebrewの導入
##2-1.　Homebrewをインストール
コマンドを順番に1つずつ実行。

```
$ cd  #ホームディレクトリに移動
$ pwd #ホームディレクトリにいるかどうか確認
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # コマンドを実行
```

PCのパスワードを入力する。
「Press RETURN to continue or other key to abort」
が表示されたら、エンターキーをおす。

##2-2. Homebrewがインストールされているか確認
上のコマンドだけ実行する。
バージョン情報が表示されれば無事にインストールされている。

```
$ brew -v
Homebrew 2.5.1 # 数値は異なる場合があります
```

##2-3. Homebrewをアップデート

```
$ brew update
```

##2-4. Homebrewの権限を変更

```
$ sudo chown -R `whoami`:admin /usr/local/bin
```

再度パスワードを求められた場合は、先ほどと同じように入力。

#3. Rubyをインストール
Webアプリケーションの開発においては専用のRubyをインストールする必要があります。

##3-1. rbenv と ruby-buildをインストール
```
$ brew install rbenv ruby-build
```

##3-2. rbenvをどこからも使用できるようにする
```
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
```

##3-3. bash_profileの変更を反映
```
$ source ~/.bash_profile
```

##3-4. readlineをinstall
ターミナルのirb上で日本語入力を可能にする設定

```
$ brew install readline
```

##3-5. readlineをどこからも使用できるようにする
```
$ brew link readline --force
```

##3-6. rbenvを利用してRubyをインストール

```
$ RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"
$ rbenv install 2.6.
```

2.6.5と書いてあるのは今回インストールするRubyのバージョンです。

##3-7. 利用するRubyのバージョンを指定

```
$ rbenv global 2.6.5
```

デフォルトでPCに入っていたRubyから、先ほどインストールしたRubyを使用するように切り替えることができました。

##3-8. rbenvを読み込んで変更を反映

```
$ rbenv rehash
```

##3-9. Rubyのバージョンを確認
以下のコマンドで最終確認。

```
$ ruby -v
```

#4. MySQLを用意
##4-1. MySQLのインストール

```
$ brew install mysql@5.6
```

##4-2. MySQLの自動起動設定
MySQLは本来であればPC再起動のたびに起動し直す必要がありますが、それは面倒であるため、自動で起動するようにしておく。

```
$ mkdir ~/Library/LaunchAgents
$ ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents
$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist
```

##4-3.mysqlコマンドをどこからでも実行できるようにする 

```
# mysqlのコマンドを実行できるようにする
$ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile
# mysqlのコマンドが打てるか確認する
$ which mysql
# 以下のように表示されれば成功
/usr/local/opt/mysql@5.6/bin/mysql
```

##4-4. mysqlを起動を確認

```
# mysqlの状態を確認するコマンドです
$ mysql.server status

# 以下のように表示されれば成功
 SUCCESS! MySQL running
```


#5. Railsの導入
##5-1. bundlerをインストール
Rubyの拡張機能（gem）を管理するためのbundler（バンドラー）をインストールする。

```
$ gem install bundler --version='2.1.4'
```

##5-2. Railsをインストール 

```
$ gem install rails --version='6.0.0'
```

##5-3. rbenvを再読み込み 

```
$ rbenv rehash
```

##5-4. Railsが導入できたか確認 

```
% rails -v
Rails 6.0.0   #「Rails」のあとに続く数字は変わる可能性があります
```


#6. Node.jsの導入
##6-1.Node.jsのインストール

```
$ brew install node@14
```

Node.jsへのパスを設定

```
$ echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile
```


##6-2. Node.jsが導入できたか確認 

```
$ node -v
v14.15.3 # 数値は異なる場合があります
```


#7. yarnの導入
##7-1. yarnをインストール

```
$ brew install yarn
```

##7-2. yarnが導入できたか確認

```
$ yarn -v
```
Java の SimpleDateFormat は「Jun」でも「June」でも Parse してくれる



SimpleDateFormatで「MMM」を指定すると、月の書き方が短縮系でもそうでなくてもParseしてくれる。

# コード

```java

public static void main(String[] args) throws Exception {

	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);
		System.err.println(sdf.parse("01-June-2020"));// OK
	}
	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);
		System.err.println(sdf.parse("01-Jun-2020"));// OK
	}
	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);
		System.err.println(sdf.parse("01-September-2020"));// OK
	}
	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);
		System.err.println(sdf.parse("01-Sep-2020")); // OK
	}
	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);
		System.err.println(sdf.parse("01-Sept-2020")); // NG
	}

}


```

# 結果

```
Mon Jun 01 00:00:00 JST 2020
Mon Jun 01 00:00:00 JST 2020
Tue Sep 01 00:00:00 JST 2020
Tue Sep 01 00:00:00 JST 2020
Exception in thread "main" java.text.ParseException: Unparseable date: "01-Sept-2020"
	at java.text.DateFormat.parse(DateFormat.java:366)
	at hello.date.HelloSimpleDateFormat2.main(HelloSimpleDateFormat2.java:28)

```
【Ruby】モジュールとは？クラスの違いについて。モジュールの中のメソッドの呼び出し方

Rubyのモジュールとクラスの違いについて。モジュールの中のメソッドの呼び出し方実例と注意点。

##目次

1. [モジュールとは？](#モジュールとは)
2. [モジュールのメリット](#モジュールのメリット)
    3. [メリット１ 複数継承可能](#メリット１-複数継承可能)
    4. [メリット２ 同じメソッド名を定義できる](#メリット２-同じメソッド名を定義できる)
5. [モジュールの呼び出し方法](#モジュールの呼び出し方法)
    6. [classの中で読み込む](#1-classの中で読み込む)
    7. [moduleの中でmodule_functonを定義する](#2-moduleの中でmodule_functonを定義する)
    8. [Objectとextendを使う](#3-objectとextendを使う)
    9. [NG事例](#ng事例)
10. [mixinとは？](#mixinとは)



##モジュールとは？

- メソッドを記述しておく場所
- moduleの中にdefでメソッドを書いていく
- メソッドを複数定義できる


```rb:
module <モジュール名>
  def <メソッド名1>
    処理1
  end

  def <メソッド名2>
    処理2
  end
  ,
  ,
  ,
end
```


<br>
##モジュールのメリット

1. 複数読み込み可能
2. 同じメソッド名を定義できる


###メリット１ 複数継承可能
複数のクラスを継承したい（メソッドの書かれた複数のファイルを読み込みたい）場合の代替手段。


**▼どういうこと？**
Rubyのデメリットとして、クラスを一つしか継承できない（単一継承）がある。

このため、他のクラスを読み込んで、更に既に定義したメソッドを読み込みたい場合に、他のクラスを読み込むことができない。

この解決手段としてモジュールがある。**モジュールを使えば、継承するクラスの他にもメソッドを読み込むことができるようになる**。


<br>
###メリット２ 同じメソッド名を定義できる
module自体の名前が異なれば、同じメソッドでも違う名前になる。（オブジェクトのKVと同じ。）

```rb:オブジェクトの場合
obj1 = {name: yamada, age: 24}
obj2 = {name: tanaka, age: 24}

#呼び出し
obj1.name  #yamada
obj2.name  #tanaka
```

nameという同じプロパティ名が存在するが、大元がobj1とobg2で異なるため、違う扱いになる。


**▼モジュールの場合**

```rb:module
module Aaa
  def hello
    p "こんにちは"
  end
end

module Bbb
  def hello
    p "ニーハオ"
  end
end
```

メソッド名はどちらもhelloだが、入れ物が異なるので問題ない。


<br>
##モジュールの呼び出し方法
モジュールの呼び出し方法は２つ。

1. classの中で読み込む
2. moduleの中でmodule_functonを定義する
3. Objectとextendを使う


###1. classの中で読み込む

・`include <モジュール名>`で読み込む
・`<クラス名>.new.<メソッド名>`で実行する

メソッドの実行方法は、通常のクラスと同じくインスタンスを作成して、メソッドを呼び出す。

```rb:OK
#モジュールの定義
module Aaa
  def hello
    p "こんにちは"
  end
end

#クラスで読み込み
class Xxx
  include Aaa
end

#メソッドの実行
Xxx.new.hello

 => "こんにちは"
```

####モジュールが複数ある場合
カンマで繋ぐ。

・`include <モジュール名1>, <モジュール名1>,,,` 

**▼注意点**
メソッド名が同じ場合は、上のモジュールのメソッドが読み込まれる。（下側は無視される）

```rb:OK（メソッド名が同じ場合）
#モジュールの定義
module Aaa
  def hello
    p "こんにちは"
  end
end

module Bbb
  def hello
    p "ニーハオ"
  end
end

#クラスで読み込み
class Xxx
  include Bbb, Aaa
end

#メソッドの実行
Xxx.new.hello

=> "こんにちは"
```


###mixinとは？
**クラスの中でmoduleを呼び出すこと**をmixin（ミクシン）と呼ぶ。

mixinというメソッドがあるわけではなく、classの中でincludeを使ってmoduleを呼び出すこと　＝　mixinとなる。

`<`を継承と呼ぶのと同じく、ただの名称。



<br>

###2. moduleの中でmodule_functonを定義する

・`module_function :<メソッド名>`

**▼注意点**
- `:`の後にスペースを空けない（エラーになる）
- 記述するメソッドは一つずつ。（メソッドが複数ある場合は複数記述する。カンマでつなげない）


```rb:OK
#モジュールの定義
module Aaa
  def hello
    p "こんにちは"
  end

  module_function:hello
end

#メソッドの実行
Aaa.hello

 => "こんにちは"
```


<br>
###3. Objectとextendを使う
`Object.new`で空のオブジェクトを生成し、`.extend <モジュール名>`で拡張すれば、メソッドが使用できる。


```rb:OK
#モジュールの定義
module Aaa
  def hello
    p "こんにちは"
  end
end

#オブジェクトの生成
obj = Object.new

#モジュールの拡張
obj.extend Aaa

#メソッドの呼び出し
obj.hello
 => "こんにちは"
```






<br>
###NG事例
モジュールはクラスの中で定義した関数のように、`<モジュール名>.new.<メソッド名>`では呼び出せない。

```rb:NG
#モジュールの定義
module Aaa
  def hello
    p "こんにちは"
  end
end

#メソッドの実行
Aaa.new.hello

#エラー内容
NoMethodError (undefined method `hello' for Aaa:Module)
```