OmniAICreator/Qiita-1.07M huggingface dataset:
マイクロサービスに移行した際の分散トランザクションの危険性

# 概要

* マイクロサービスに移行する際にシステム移行に伴うDBの分解が発生した場合に、参照整合性の維持の為、分散トランザクションが選択肢に上がると思う。(上がらなければこの記事は読み飛ばしてください。)
* そんな分散トランザクションの危険性について、今回は記事にしていこうと思います。

## データベーストランザクション

* 通常、データベーストランザクションについて考える時、このトランザクションが指すものとして**ACIDトランザクション**という概念があります。

### ACIDトランザクション

* ACIDトランザクションとは、関連する複数の処理を一つとして管理するトランザクション処理に求められるジム・グレイが定義した**4つの特性**の概念です。

#### Atomicity(原子性/不可分性)

* トランザクションに含まれる個々の手順が「全て実行される」か、「全て失敗する」のどちらかの状態になることを保証します。
* その為、何かの理由で失敗した場合、操作全体が中断され、変更は行われなかったようになります。

#### Consistency(一貫性/整合性)

* データベースに変更が走った場合、トランザクションの前後でデータの整合性が保たれ、矛盾の無い状態が継続することで、データベースが有効で一貫性のある状態であることを保証します。

#### Isolation(分離性/独立性)

* トランザクション実行中の処理過程が外部から隠され、他の処理などに影響を与えないこと保証します。
* その為、複数のトランザクションが干渉することなく同時に動作できます。

#### Durability(永続性/耐久性)

* トランザクションが完了した場合、その結果は記録されシステム障害が発生してもデータが失われることがないことを保証します。
* また、データ記録中に障害などで中断した場合は、記録を元に更新を反映させるといった処理が行われます。


## DB分割とトランザクジョン

* 下記に新しい顧客を登録するシステムの例にモノリスからサービスの移行とDBの分割したものを記載します。
* このシステムでは、顧客の登録が保留中から確認済みになった場合に、**顧客テーブル**の該当idのレコードのcolumnであるStatusを更新し、**登録保留テーブル**から該当idのレコードを削除します。

### モノリス

* モノリスのシステムの場合は、下記のようにモノリスなシステムの場合、2つのトランザクションを１つのモノリスなシステムがそのトランザクションをコントロールできます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/671a14e0-356e-d087-7d0b-134f1f4a4e1f.png" width="400px">

### マイクロサービス

* 下記にマイクロサービスに移行し、DBを分割し別のデータベースとした場合の図を示しました。
* この場合、それぞれの変更を別のデータベースで行われている為、2つのトランザクションを順序立て実行しなければならなくなります。

**=> つまり、原子性が保証されなくなっていることを指します。**

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/a5d6b965-a65b-4acc-83d6-6d8fd5421091.png" width="500px">

## 2フェーズコミット

* 上記のような複数のサービスに同時に行われる変更を可能にする方法として、**2フェーズコミット**という分散トランザクションの一般的なアルゴリズムがあります。

### 2フェーズコミットの仕組み

* 2フェーズコミットは、コミットを2段階に分けて行います。

#### 第1フェーズ
* **第1フェーズ**では、トランザクション処理を行うソフトウェア(コーディネータ)が、トランザクションに参加する全ワーカに問い合わせを行い、レコードの更新(コミット可能)かを確認します。
* なおこの時、レコードはローカルでロックされている状態にあります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/95eabbfb-b98d-35ed-46e0-6c62513eeb39.png" width="400px">

#### 第2フェーズ
* **第2フェーズ**では、全てコミット可能となれば、コーディネータは全ワーカに対してコミット処理を指示して、データの更新が行われます。
* ロックも解除されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/56d5e0a6-57a4-a165-350b-856866596d81.png" width="400px">

### 欠点

**2フェーズコミットには、下記のような欠点があります。**

* 全てのコミットが正確に同じ時間に行われる保証はない。
* ロックを行うため、その調整が難しい。
* ワーカと関連するDBが増えた場合、システムの待ち時間も長くなり、システム全体のレイテンシーを低下させる恐れがある。

## まとめ

* 以上のことより、マイクロサービスに移行した際に分散トランザクションを使用する選択肢が出た場合は、一度DBの設計を検討し直す(例えば、DBの分割を行わない等)、もしくは別の解決策を検討した方がいいです。


# 参考文献

* [2フェーズコミットとは何？](https://www.weblio.jp/content/2%E3%83%95%E3%82%A7%E3%83%BC%E3%82%BA%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88#:~:text=2%E3%83%95%E3%82%A7%E3%83%BC%E3%82%BA%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%A8%E3%81%AF%E3%80%81%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E5%86%85%E3%81%AB%E3%81%82%E3%82%8B%E8%A4%87%E6%95%B0,%E3%81%95%E3%82%8C%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B%E3%80%82)
* [モノリスからマイクロサービスへ
――モノリスを進化させる実践移行ガイド](https://www.oreilly.co.jp/books/9784873119311/)
Node.jsのExpressが久しぶりで忘れたときに見るやつ

# 「Express久しぶりに使うな〜、あれ?」
**「どう書くのか忘れたー!」**というときに見るものです

# 環境を作る
ディレクトリを作って、ターミナルでそこに移動して
npmを初期化します

```sh
npm init -y
```

次にExpressをインストールします

```sh
npm install --save express
```

これで起動できます

```sh
node .
```

お好みで開発に便利な[nodemon](https://www.npmjs.com/package/nodemon)も

`index.js`を用意します

```js:index.js
const express = require("express")
const app = express()

/* 書いてあるコードはここに書いてね */

app.listen(3000, () => {
  console.log("listening at http://localhost:3000")
})
```

準備完了

# GET - get()
これでブラウザで http://localhost:3000 にアクセスすれば`Hello World!`と返ってきます

```js
app.get("/", (req, res) => {
  res.send("Hello World!")
})
```

# POST - post()
Postmanやcurlなどを使って試しましょう
これで http://localhost:3000 にPOSTすると`Hello World!`と返ってきます

```js
app.post("/", (req, res) => {
  res.send("Hello World!")
})
```

# 場所を変える - xxx(path, ...)
`/5000trillion`とかにアクセスしたときのリクエストを捌こう

```js
app.get("/5000trillion", (req, res) => {
  res.send("5000兆円\n    欲しい!")
})
```

# 簡単なデータをもらう - query
これで http://localhost:3000/5000trillion?mode=deflation にアクセスすると
~~デフレが起きて物価が下がり、50万円で満足します~~
`50万円欲しい!`と返ってきます

ちなみに`mode=deflation`は [クエリ文字列](https://www.google.com/search?q=%E3%82%AF%E3%82%A8%E3%83%AA%E6%96%87%E5%AD%97%E5%88%97)といいます
URLにちょっとしたデータを含めることができます

```js
app.get("/5000trillion", (req, res) => {
  if (req.query.mode === "deflation") {
    res.send("50万円\n    欲しい!")
  } else {
    res.send("5000兆円\n    欲しい!")
  }
})
```

# 静的な場所 - use(..., static(...))
publicフォルダーの下を`/assets`にアクセスしたときに返したいとき
こんな感じになります
http://localhost:3000/assets/logo.png <-> ./public/logo.png

```js
app.use("/assets", express.static("./public"))
```

# ファイル分割 - Router()
ディレクトリ別に`.js`ファイルを分けることもできます
`route.get()`のパスを`"/5000trillion"`にすると、`/5000trillion/5000trillion`になるので注意

```js:5000t.js
const express = require("express")
const route = express.Router()

route.get("/", (req, res) => {
  if (req.query.mode === "deflation") {
    res.send("50万円\n    欲しい!")
  } else {
    res.send("5000兆円\n    欲しい!")
  }
})

module.exports = route
```

```js:index.js
const route = require("./5000t")

app.use("/5000trillion", route)
```

# ミドルウェア - use(...)
`get(...)`などの前に認証などの処理をすることができます
ここでは、ログを出してみます
最後に**必ず**`next()`を呼びましょう
そうしないと続きが実行されません

```js
app.use((req, res, next) => {
  console.log(`[${Date.now()}] ${req.ip} ${req.url}`)
  next()
})

// `/5000trillion`の下だけ
app.use("/5000trillion", (req, res, next) => {
  res.setHeader("powered-by", "5000 trillion yen!") // ヘッダーを追加 CORSなんかもここでする ライブラリ使ったほうがいい
  console.log(`[${Date.now()}] ${req.ip} ${req.url}`)
  next()
})
```

# おわり
「せや! Expressこんな感じやったな」というふうになったらいいな
もっと詳しいことは http://expressjs.com/en/4x/api.html で
Q1.[Misc] Test Problem

問題文のとおりフラグは
**cpaw{this_is_Cpaw_CTF}**

<br>
ーーーーーーーーーーーーーー
↓全問Writeup執筆(予定)
[CpawCTF Writeup](https://qiita.com/parsley_irodori/items/bebde41ce1305d1edcd4)
WordPressのタグ一覧画面に表示されないタグがあった場合への対応

# 背景
WordPressサイトで固定ページを使ってタグ一覧画面を作成した時、
管理画面側から追加したタグが一覧に表示されない現象が発生しました。

# 仕様
- [AdvancedCustomField（ACF）](https://www.advancedcustomfields.com/)で追加したカスタムフィールド（下記の例では`tag_index`がキー）を取得する記事の並びの基準にする 
- `tag_index`は数値フィールドで昇順に取得する

# 修正前のコード

```page-tags.php
<?php
$args = [
  'taxonomy' => 'tags',
  'order' => 'ASC',
  'orderby' => 'meta_value',
  'meta_key' => 'tag_index', //ACFのフィールド名
  'hide_empty' => true,// 紐づけられている記事があるタグのみ取得
];
$tags_array = get_terms($args);
?>

// タグのループ
<?php if($tags_array): foreach($tags_array as $tag):
  $term_link = get_term_link($tag, 'tags');
?>
  <div class="tag"><a href="<?php echo esc_url($term_link); ?>"><?php echo $tag->name ;?></a></div>
<?php endforeach; endif; ?>
```

# 原因
投稿エディタ画面のサイドバーの「タグを追加」から登録を行なったタグはカスタムフィールドの値が存在しない（slugもタグ名と同じになる）
↓
順序を決定するための値が存在しないので取得するタグの対象に入らない
↓
タグ一覧画面にタグが表示されない

# 対応
- 投稿エディタ画面の「タグを追加」リンクを無効化（非表示）にする
- `get_terms`で並び替えをせず、自前の処理で行う

# 修正後のコード
```page-tags.php
$args = [
  'taxonomy' => 'tags',
  'hide_empty' => true,// 紐づけられている記事があるタグのみ取得
];
$tags_array = get_terms($args);
usort( $tags_array, 'tags_order_by_index' );
```

```function.php
/**
 * tag_indexの値によって並び替えを行う
 * @param $a
 * @param $b
 *
 * @return int
 */
function tags_order_by_index($a, $b) {
  // nullのときは0にキャストされる（tag_indexの初期値は0）
  $a_index = (int) get_field('tag_index', "tags_{$a->term_id}");
  $b_index = (int) get_field('tag_index', "tags_{$b->term_id}");
  if ($a_index == $b_index) {
    return 0;
  }
  return ($a_index < $b_index) ? -1 : 1;
}

/**
  * エディタ画面から直接タグを追加できないようにする
*/
function hide_tags_adder(){
  echo <<<JSCODE
<script type="text/javascript">
  window.onload = function(){
    var element = document.getElementById('tags-adder');
    if(element) {
      element.style.display = 'none';
    }
  }
</script>
JSCODE;
}
add_action('admin_head', 'hide_tags_adder');
```
`document.getElementById('tags-adder')`の部分はタグ名によって変わります。
え！？Amazonプライム会員なのに「プライムリーディング」を知らないの！！？？？



「お急ぎ便や日時指定便が無料になるし、プライムビデオでこんな色々な動画見れるの！？お得じゃ～ん！(๑˃̵ᴗ˂̵)و」

みたいな気持ちでAmazonプライム会員になって数年…

…僕は今まで知らなかった。

「**プライムリーディング**」の存在を。

# Prime Reading(プライムリーディング)とは？

「**プライムリーディング**」は、書籍が無料で読めるサービスです。

https://www.amazon.co.jp/kindle-dbs/fd/nonprime-pr

Amazonには「**Kindle unlimited**」という一部の本が読み放題のサービスがあり、こちらの方が読める本の数は多いです。
ただ、「**Kindle unlimited**」はプライム会員とは別の月額料金がかかります。

一方、「**プライムリーディング**」はラインナップは少ないものの（といっても数百冊はある）既にAmazonプライムの会員なら追加料金なしで使えます。

…え？普通に神な特典では…！？

## 試してみた

早速、オススメされていた本をいくつか流し読みしてみました。

### 面白かった本

#### 『一生使える見やすい資料のデザイン入門』

https://www.amazon.co.jp/dp/B01AT266XS/ref=s9_acsd_hps_bw_c2_x_8_t?pf_rd_m=A3P5ROKL5A1OLE&pf_rd_s=merchandised-search-3&pf_rd_r=W5NNGNDA5TV3W1P7R1PN&pf_rd_t=101&pf_rd_p=73a10a3e-7fc0-4944-bb78-e13052492079&pf_rd_i=5298794051

#### 『線一本からはじめる伝わる絵の描き方　ロジカルデッサンの技法』

https://www.amazon.co.jp/dp/B07BKT9ZNS/ref=redir_mobile_desktop?_encoding=UTF8&bsppEnabled=false


月額料金に直したら、**これだけでプライム会員の元取れるくらい**です…！

※ラインナップは定期的に更新されるようです。

他にも結構話題作も多く配信されていている印象です。

「買って読むほどではないかな…」くらい本にざっと目を通すのにはもってこいです。


## とりあえず、プライム会員なら使って損は無いはず！

「**プライムリーディング**」が日本でサービスを開始した2017年10月には既にプレミアム会員だったこともあり、僕は今日まで気付きませんでした。

https://japanese.engadget.com/jp-2017-10-05-amazon-prime-reading-900.html#:~:text=%E3%81%93%E3%82%8C%E3%81%AFKindle%E9%9B%BB%E5%AD%90%E6%9B%B8%E7%B1%8D,%E6%8F%90%E4%BE%9B%E3%81%97%E3%81%A6%E3%81%84%E3%81%9F%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%80%82

Amazonプライム会員で「**プライムリーディング**」の存在を知らなかった方は、是非一度ラインナップを眺めてみてはいかがでしょうか！
GCP 使った開発してて権限追加が必要な時にroleがわからない

GCP 使った開発ばかりしてるわけでもないし、毎回忘れててググるので備忘録です。

### ロール
[ここ](https://cloud.google.com/iam/docs/understanding-roles?hl=ja)にロールと権限の一覧がある。

### アカウントに権限を付与
だいたいこんな感じで怒られるので、

```
rpc error: code = PermissionDenied desc = The principal(user or service account) lacks IAM permission "<権限>" for the resource "<リソース名>" (or the resource may not exist)
```
上記サイトで<権限>で検索するとその権限を持ってるロールがわかる。
可能な限り必要最低限の権限だけを持つロールを選んだら、 Cloud Console の 「IAM と管理」-「IAM」からその権限を付与したいアカウントの「編集」からロールを追加する。

### 追加したいロールが出てこなかったら
ときどき、ベータ版のロールは Cloud Console 上で選択肢に出てこないことがある。
そういうときは [`gcloud` コマンドで追加する](https://cloud.google.com/iam/docs/granting-roles-to-service-accounts?hl=ja#gcloud)しかない（のか？）

```
$ gcloud projects add-iam-policy-binding <project 名> \
  --member serviceAccount:<service account> \
  --role <role>
```
sklearnで交差検証をする時に使うKFoldの備忘録

sklearnで交差検証をする時に使うKFoldについての備忘録

```
import numpy as np
from sklearn.model_selection import KFold

# ###################
# サンプルデータの生成
# ###################

# 乱数の初期値設定
rand = np.random.RandomState(seed=71)
data = np.linspace(0, 1, 10000) # 0～1まで等間隔に10000個の実数を取得
```

分割器を作る。ここでは、シャッフルした上で4つに分割する分割器を作成

```
kf = KFold(n_splits=4, random_state=71, shuffle=True)
```

実際に分割するには、

```
kf.split(data)
```
とするが、返却されるのが、イテレータブルオブジェクトの為、for文と組み合わせて取得する。


```
for i in kf.split(data):
    print(i)

# > (array([   0,    1,    2, ..., 9996, 9998, 9999]), array([   6,   10,   11, ..., 9994, 9995, 9997]))
# > (array([   0,    1,    2, ..., 9997, 9998, 9999]), array([   3,    5,   15, ..., 9981, 9985, 9987]))
# > (array([   2,    3,    4, ..., 9995, 9996, 9997]), array([   0,    1,    7, ..., 9992, 9998, 9999]))
# > (array([   0,    1,    3, ..., 9997, 9998, 9999]), array([   2,    4,    8, ..., 9990, 9993, 9996]))

```

全部で、10000件あるので、2500件ずつデータを4つに分割し、3(7500件)：1(2500件) の組み合わせを作っている。（4パターン）


### 注意
splitで返却されるのは、データのインデックであって、データ自体ではないことに注意が必要です！！
なので、こんな感じにする必要があります。

```
for i, (train_index, test_index) in enumerate(kf.split(data)):
    train_data, test_data = data[train_index], data[test_index]
    print(train_data)

# output
# > Trainデータ： [0.00000000e+00 1.00010001e-04 2.00020002e-04 ... 9.99699970e-01
# >  9.99899990e-01 1.00000000e+00]
# > Testデータ： [6.00060006e-04 1.00010001e-03 1.10011001e-03 ... 9.99499950e-01
# >  9.99599960e-01 9.99799980e-01]
# > ========================================================
# > Trainデータ： [0.00000000e+00 1.00010001e-04 2.00020002e-04 ... 9.99799980e-01
# >  9.99899990e-01 1.00000000e+00]
# > Testデータ： [3.00030003e-04 5.00050005e-04 1.50015002e-03 ... 9.98199820e-01
# >  9.98599860e-01 9.98799880e-01]
# > ========================================================
# > Trainデータ： [2.00020002e-04 3.00030003e-04 4.00040004e-04 ... 9.99599960e-01
# >  9.99699970e-01 9.99799980e-01]
# > Testデータ： [0.00000000e+00 1.00010001e-04 7.00070007e-04 ... 9.99299930e-01
# >  9.99899990e-01 1.00000000e+00]
# > ========================================================
# > Trainデータ： [0.00000000e+00 1.00010001e-04 3.00030003e-04 ... 9.99799980e-01
# >  9.99899990e-01 1.00000000e+00]
# > Testデータ： [2.00020002e-04 4.00040004e-04 8.00080008e-04 ... 9.99099910e-01
# >  9.99399940e-01 9.99699970e-01]
# > ========================================================
```

KFoldの備忘録でした。

おしまい
総務省　電気通信番号指定状況の携帯電話・PHSの電話番号の一覧からCSVを作成する

総務省　電気通信番号指定状況の携帯電話・PHSの電話番号
Excelから事業者一覧を取り出しCSVに変換

https://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/number_shitei.html

```python
import pandas as pd

df_070 = (
    pd.read_excel(
        "https://www.soumu.go.jp/main_content/000697563.xlsx", skiprows=5, dtype=str
    )
    .set_index("番号")
    .stack()
)
df_080 = (
    pd.read_excel(
        "https://www.soumu.go.jp/main_content/000697565.xlsx", skiprows=5, dtype=str
    )
    .set_index("番号")
    .stack()
)
df_090 = (
    pd.read_excel(
        "https://www.soumu.go.jp/main_content/000697567.xlsx", skiprows=4, dtype=str
    )
    .set_index("番号")
    .stack()
)

# 結合
df = pd.concat([df_070, df_080, df_090]).reset_index()

# 列名変更
df.rename(columns={"番号": "CD", "level_1": "E", 0: "事業者"}, inplace=True)

# 半角
df["E"] = df["E"].str.normalize("NFKC")

# 結合
se = df["CD"] + df["E"] + "XXXXX"

# 電話番号表記
df["番号"] = se.str[:3] + "-" + se.str[3:7] + "-" + se.str[7:]

df

df.to_csv("number.csv", encoding="utf_8_sig")
```
Jiraで課題をCSVエクスポートする

Jiraを使っていて課題数が増えてきたり、分析にかけたい場合、課題一覧をエクスポートしたくなります。
その際にJiraのエクスポート機能は少し癖がありますので解説していきます。

## エクスポートしたい課題をフィルタリング
【課題】→【課題の検索】からJQLを入力し、今回は「SAKATEST」というプロジェクトからすべての課題を取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/a73b9309-0762-ac71-514d-6181566f4d73.png)

## エクスポートメニューから課題をCSVエクスポート
CSV（現在のフィールド）を選択してエクスポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/2bf45c72-dd2c-4587-c5d8-d38844c176d6.png)
※ここでCSV（すべてのフィールド）を選択すると使用していないカスタムフィールドなども項目としてエクスポートされてしまうので非常に使い勝手が悪くなるので注意

CSV形式でダウンロードできました。

```CSV
課題タイプ,課題キー,課題 ID,要約,担当者,報告者,優先度,ステータス,作成日,更新日
タスク,SAKATEST-20,23291,タスク3,Yosuke-Sakaue,Yosuke-Sakaue,Low,Active,2019/11/01 4:27 午後,2021/03/30 4:01 午後
タスク,SAKATEST-22,23293,タスク2,Yosuke-Sakaue,Yosuke-Sakaue,Low,Active,2019/11/01 4:27 午後,2021/03/30 4:00 午後
タスク,SAKATEST-19,23290,タスク5,Yosuke-Sakaue,Yosuke-Sakaue,Low,進行中,2019/11/01 4:27 午後,2021/03/30 4:00 午後
タスク,SAKATEST-24,23306,タスク1,Yosuke-Sakaue,Yosuke-Sakaue,Low,Active,2019/11/21 10:52 午前,2021/02/25 4:12 午後
タスク,SAKATEST-23,23305,タスク4,Yosuke-Sakaue,Yosuke-Sakaue,Low,進行中,2019/11/21 10:51 午前,2021/02/25 4:11 午後
タスク,SAKATEST-21,23292,親タスク２,Yosuke-Sakaue,Yosuke-Sakaue,Low,進行中,2019/11/01 4:27 午後,2021/02/25 4:11 午後
```

## 別のフィールドもCSVに含めたい場合は？
上記のCSV（現在のフィールド）は現在のUIに表示されているフィールドのみのエクスポートなので、基本的な項目しか表示されていません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/1e179111-4d77-4506-4a89-02dd65c89e11.png)

例えば、「期限」というフィールドを含めたい場合は【コラム】のメニューから「期限」を検索してチェックを付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/fc1f18f8-7be6-c354-b617-a95c6944edec.png)

すると、「期限」の列が追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/81f0344a-158b-0112-c761-ed8dcbec53ec.png)

この状態で現在のフィールドをエクスポートすると、CSVの列にも「期限」が追加されています。
Defold特有の要素を説明する！

# はじめに
Defoldの記事たくさん書いてるのに、まだプログラミングに突入していないという状況です()
この記事では、Defoldを使うときに知らなきゃいけない要素を紹介します。
要素の追加方法は、[この記事](https://qiita.com/nonzu/items/4c3a01c389c7e8a17f5b#%E8%A6%81%E7%B4%A0%E3%81%AE%E8%BF%BD%E5%8A%A0)で紹介してあるのでこっちを見てください。
とりあえず一覧はこんな感じです。
![2021-03-29_08h37_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620977/8a66510d-1d15-8e9d-6336-fdc96bcc9e1d.png)
たくさんありますが使うものは
![2021-03-29_08h33_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620977/79fc5fac-d213-4ab6-b640-dbfe59736251.png)
この9個です。画像の順番はアルファベット順なのですが、説明するときには分かりやすいように順番を変えて行います。

# Game Object (.go)
1つ目はゲームオブジェクトですね。.goは「ドット・ゴー」じゃなくて**「ドット・ジーオー」**だと思います。**G**ame **O**bjectの略なので。まぁここではゲームオブジェクトと呼びます。
ゲームオブジェクトは様々ものを表現する単位です。例えば、自分だったり、敵だったり、アイテムだったり、銃弾だったり、壁だったり、床だったりします。
ゲームオブジェクト同士の衝突や個々のプログラムによって様々な物体を表現できます。もちろんゲームオブジェクトにイラストなどを貼り付けることもできます。
ゲームオブジェクトという基礎にいろいろな要素を追加していくイメージで、敵などを作っていきます。
![go.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620977/f363b924-3430-ef28-7d09-1483e3d2d181.png)
# Script (.script)
2つ目はスクリプトです。ゲームオブジェクトで紹介したプログラムはスクリプトに記入します。プログラムの2台巨塔の1つです。
実際のプログラムの話はまだしていないので、とりあえず中身の紹介はしません。
# Gui (.gui)
3つ目はGUIです。GUIで分かる人はわかると思います。簡単にいうと、画面の情報表示のことです。例えば、自分の体力とか、ゲームが始まってからの経過時間とか、現在のレベル数とか、メニューの画面とかです。基本的に画面の一番手前に表示されていて、ボタンとかも簡単に作ることができます。
# Gui Script (.gui_script)
4つ目は、GUIスクリプトです。その名の通りGUI用のスクリプト(プログラム)です。GUIを作るときはこっちを使います。ほとんど使い方は同じなのですが、ゲームオブジェクトはスクリプト、GUIはGUIスクリプトという風に分けられています。ただ、GUIはゲームオブジェクトが無いと動きません。つまり、GUIも1つのゲームオブジェクトに追加される物だと言うことです。まぁ実際作ってみればわかります。
# Atlas (.atlas)
5つ目は、アトラスです。アトラスはいろんな画像を一旦溜めておくところです。アトラスに溜めた画像を、ゲームオブジェクトやGUIから呼び出すイメージです。いちいち全部の画像をそれぞれのゲームオブジェクトから読み込む必要がなく、Atlasだけを読み込めばことが足ります。
![atlas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620977/315de7d9-ae13-7533-332b-0539314090ea.png)
# Collection (.collection)
6つ目は、コレクションです。例えるなら、コレクションは「世界」です。世界の中にいろんな物体が存在するように、コレクションの中に様々なゲームオブジェクトが存在します。
# Tile Source (.tilesource)
7つ目は、タイルソースです。コレクションの背景的なものを作るときの画像を読み込む要素です。具体的な画像は、著作権的に貼り付けて良いのかわからないので[Google先生](https://www.google.com/search?q=%E3%82%BF%E3%82%A4%E3%83%AB%E3%83%9E%E3%83%83%E3%83%97+%E7%B4%A0%E6%9D%90&rlz=1C1CHBD_jaJP811JP811&sxsrf=ALeKk002colB1J1NchbfLwWMrH5IRQAP0A:1616978695914&source=lnms&tbm=isch&sa=X&ved=2ahUKEwihx52Go9TvAhXKad4KHVlaDvQQ_AUoAXoECAEQAw&biw=1920&bih=969)に聞いてみましょう。要するに、32x32くらい(16x16などもある)の大きさの画像がたくさん並んでいる1枚の画像のことです。これを分割して、使えるようにする感じです。分かりやすい画像は[Defold公式](https://defold.com/manuals/tilesource/)にあるので、見てみてください。
# Tile Map (.tilemap)
8つ目は、タイルマップです。タイルマップはタイルソースを読み込んで実際に背景を作る要素です。タイルソースの形の応じた当たり判定を付けることもできます。また、タイルマップの要素をスクリプトから読み込むことができるので、このタイルを置いたところにこのオブジェクトを生成する、みたいな使い方もできます。例えば、赤い□のタイルを置いたところに自機を生成するなどの使い方ができます。
# Font (.font)
9つ目は、フォントです。日本語のフォントも使えますが、めちゃくちゃ重たいです。
フォントがわからない人もいると思うので説明すると、パソコンで使う字体のことです。手書きフォントとか、ポップ体のフォントとかいろいろあります。画面に文字を表示させたいときはフォントを使用します。
# さいごに
こんな感じで要素の説明でした。コイツらを知っていれば、まぁ当分困ることは無いと思います。
次回は、Luaのプログラミングをしようかなと思っています。
気になる人は[目次](https://qiita.com/nonzu/items/73a39368855f3e1e0f28)をチェックしてみてください。
scipy.optimize.minimizeを使った最適化サンプル

# 閾値の最適化
分類タスク（正例(1) or 負例(0)を予測するタスク）で、ロジスティック回帰モデルなど予測確率を出力するモデルを作成した際、ある閾値以上なら正例(1)を、以下ならば負例(0)として出力を行うことになるが、最適な閾値って？？

ということで、scipy.optimize.minimizeを使ったサンプルを纏めておくことにする。
※個人備忘録の為、煩雑でスミマセン（涙）


```
import pandas as pd
import numpy as np
from sklearn.metrics import f1_score
from scipy.optimize import minimize

# ###################
# サンプルデータの生成
# ###################

# 乱数の初期値を設定　こうしておかないと実行のたびに異なる乱数を出力してしまう。
rand = np.random.RandomState(seed=71)
train_y_prob = np.linspace(0, 1, 10000) # 0～1まで等間隔に10000個の実数を取得

## 真の値(0 or 1)のサンプルデータ生成
#  一様分布から0～1の範囲で値を取得し、上で取得したtrain_y_probとの比較を行い 0 or 1 のデータを生成
train_y = pd.Series(rand.uniform(0, 1, train_y_prob.size) < train_y_prob)

## 予測確率とするサンプルデータの生成
train_pred_prob = np.clip(train_y_prob * np.exp(rand.standard_normal(train_y_prob.size)*0.3), 0, 1)
```

ちなみに、train_yはこんな感じです。

```
train_y

0       False
1       False
2       False
3       False
4       False
        ...  
9995     True
9996     True
9997     True
9998     True
9999     True
Length: 10000, dtype: bool
```

予測確率とみなすサンプルはこんな感じです。

```
train_pred_prob
array([0.00000000e+00, 1.10648939e-04, 2.29275798e-04, ...,
       9.05431241e-01, 5.25621437e-01, 8.81456054e-01])
```

まず、閾値を0.5とした場合のf1-scoreは・・・

```
# 閾値を0.5とすると・・・
init_threshold = 0.5
init_score = f1_score(train_y, train_pred_prob >= init_threshold)
print("閾値0.5の時のf1-score：{}".format(init_score.round(3)))

# >> 閾値0.5の時のf1-score：0.722
```

**「0.722」** になります。


## 最適化関数
ここでは、f1-scoreが最も大きくなるような threshold（閾値）を探すということで、
 **「閾値、正解データ（フラグデータ）、予測確率データ」** の３つを引数として受け取り、
f1-scoreを算出し、符号を反転させたデータを返却する関数を作成します。
※最適化にminimize関数を使うので、return 時の符号を反転させています。

```
# 閾値の最適化関数
# 　f1-scoreを元に最適化を行う
# 　引数の順番は、最初に最適化される変数がくるようにする？
def f1_optimizer(threshold, train_y, train_pred_prob ):
    return -f1_score(train_y, train_pred_prob >= threshold)
```

## 最適化
スタートを0.5に設定　x0で指定
そのほか、train_yとtrain_pred_probは、argsでタプル指定
最適化アルゴリズムはmethodeで指定　ここでは、ネルダーミード法を指定

```
result = minimize(f1_optimizer, x0 = 0.5, args = (train_y, train_pred_prob), method = "Nelder-Mead")
print(result)

# >>  final_simplex: (array([[0.32324219],
# >>       [0.32319336]]), array([-0.75573177, -0.75573177]))
# >>           fun: -0.7557317703844165
# >>       message: 'Optimization terminated successfully.'
# >>          nfev: 31
# >>           nit: 14
# >>        status: 0
# >>      success: True
# >>             x: array([0.32324219])
```


```
print("最適な閾値：{}".format(result["x"].round(3)))
print("最適な閾値でのf1_score：{}".format(f1_score(train_y, train_pred_prob >= result["x"]).round(3)))

# >> 最適な閾値：[0.323]
# >> 最適な閾値でのf1_score：0.756
```

自分向けの備忘録のため、煩雑でスミマセン（涙）

おしまい
助けて！Postman！

# はじめに
業務でAPIの作成をしたのですが、テストの際にとても役立ったPostmanについて皆さんにも知って欲しいと思い、記事を書きました！

## Postmanとは？
URLやRequestの内容、TOKENを設定してAPIにRequestを送り、Responseを確認することができるツールで、Web APIの開発者「提供する側・活用する側」の双方にとってより良い開発エクスペリエンスを提供するクライアントアプリケーションです。

### 主な機能の特徴
- API Client
    - 公開されているもしくは開発中の各種APIを簡単にテストできる機能です。
- Automated Testing
    - API開発者向けに各エンドポイントに対する自動テスト機能を提供します。
- Design & Mock
    - APIを開発するにあたって、API SchemaをDesignするための専用EditorとそれをテスティングするためのMock Server機能を提供します。
- Documentation
    - PostmanのAPI定義から自動的にAPIドキュメントを生成し、外部ユーザーに提供することができる機能です。
- Monitors
    - 提供されているAPIを定期的にチェックし、APIのアップデートや変更に伴う破損や従来のエクスペリエンスに変化が無いかモニタリングすることができます。
- Workspaces
    - チームでAPIを共同開発するためのコラボレーション機能を提供します。

## インストール方法
[こちら](https://www.getpostman.com/downloads/)のURLからダウンロードして、インストールします。

### Web APIを使うために抑えたい重要な要素

- Base URI
    - 一番最初に知らなければいけないことは、Web APIを提供しているサービサーのURIエンドポイントを特定すること。

<例>

```ruby

https://qiita.com/api/v2/items
```

- Resource
    - Web APIではどんなデータを操作するのかを決める必要があります。それをBase URIと合わせて指定するのがWeb API（REST）では一般的です。

<例>

```ruby

# itemsがResourceにあたり、このitemsに対してなんらかの操作を行う
https://qiita.com/api/v2/items
```

- Method
    - GETやPOST・PUT・DELETEといったリソースに対する操作方法を指定する。

- Authentication
    - Web APIを操作するための認証部分。

- Header
    - 対象のAPIに対して、追加情報を渡すために使用されるプロパティセットのこと。
    - 主に後述する認証情報やどんなフォーマットでデータの受け渡しを行うか？を指定する。
- Query
    - Queryは主にデータを取得する際の各種諸条件を適用するために使われるパラメータセットのこと。
    - URIとリソースを指定した後に続く文字列として「？」以降に指定するものがQueryです。

- Body
    -  Web APIに渡すためのメインとなるデータを指定するための要素。
    -  主にPOSTやPUTでリソースにデータを登録したり、更新したりする時に指定する。

## 使い方
1.Postman を立ち上げて、まずは対象となる Web APIのBase URIを指定する。

2.対象のリソースを指定します。

3.プルダウンで各Methodを選択することができるので、該当のリクエストを選択する。

4.次にQueryを指定します。Paramsタブで指定を行います。Paramsタブを選択し、KeyとValueを指定します。このParamsタブにデータを入力すると、自動的にURIへQueryが補完されます。

5.APIを実際にリクエストするにはPostman右上にある「Send」ボタンをクリック。

### グローバルで Web APIを展開しているサービスのテンプレートを使う
1.[Postman API Network](explore.postman.com) にアクセスする。

2.任意のAPIを検索して、「Run in Postman」をクリックする。


### Postman API Network以外のAPIを使う
1.任意のサイト等でAPIをダウンロードしてくる。(例:[freee](https://developer.freee.co.jp/))

2.取得したOpenAPISpecは、PostmanのImport機能から取り込む。画面右上の「Import」をクリック

3.「Import File」タブから、ダウンロードしたOpenAPI（Swagger）Specを指定する。

4.API情報が取り込まれる。

### プログラムからWeb APIを操作する
1.Code Snippetのプルダウンから任意の言語を選択する。

2.出てきたコードをペースト。

# 終わりに
どうでしたでしょうか？
APIの作成には、必要不可欠くらい便利なツールですよね笑
どんどん活用して行こう！

## 参考
[はじめてでも怖くない！　Postman を使って、Web API を触ってみよう！]
(https://kageura.hatenadiary.jp/entry/hazimetepostman#Postman-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6-OReilly-BookList-%E3%81%AE-Web-API%E3%82%92%E5%8F%A9%E3%81%84%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)

[API開発・テスト便利ツール Postmanの使い方メモ]
(https://qiita.com/zaburo/items/16ac4189d0d1c35e26d1)

[APIの開発がむちゃくちゃ捗る「Postman」の使い方]
(https://www.webprofessional.jp/master-api-workflow-postman/)

[Railsで超簡単API]
(https://qiita.com/k-penguin-sato/items/adba7a1a1ecc3582a9c9)

[Ruby on Rails で Web API のパラメータをバリデーションする]
(https://blog.mmmcorp.co.jp/blog/2015/07/11/rails_web_api_validation/)
ROSの勉強　第33弾：ロボットアームの作成（1）

# #プログラミング ROS< ロボットアームの作成（1） >

##はじめに
1つの参考書に沿って，ROS(Robot Operating System)を難なく扱えるようになることが目的である．その第33弾として，「ロボットアームの作成（1）」を扱う．

##環境
#####仮想環境
|||
|:-:|:--|
|ソフト|VMware Workstation 15|
|実装RAM|2 GB|
|OS|Ubuntu 64 ビット|
|isoファイル|ubuntu-mate-20.04.1-desktop-amd64.iso|

#####コンピュータ
|||
|:-:|:--|
|デバイス|MSI|
|プロセッサ|Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz|
|実装RAM|8.00 GB (7.89 GB 使用可能)|
|OS|Windows (Windows 10 Home, バージョン：20H2)|

#####ROS
|||
|:-:|:--|
|Distribution|noetic|

##ロボットアームの作成
ROSを使って，ほとんどの新しいロボットを制御する手順は次のようである．

**1. ROSのメッセージインタフェースを決める．
2. ロボットのモータ用ドライバを書く．
3. ロボットの物理構造を書く．
4. Gazeboのシミュレーションで使用できるようにモデルに物理的特性を追加する．
5. tfを介して座標変換データを配信し，rvizでそれを可視化する．
6. センサを追加する．ドライバとシミュレーションのサポートも必要．
7. ナビゲーション等の標準的なアルゴリズムを適用する．**

これらについては，移動ロボットのときと同じである．その中身は異なってくる．

ロボットアームを例にその流れを確認していく．
今回はその1つ目ということで，1と2をまとめてロボットアームの作成（1）として扱うこととする．

##手順1:ROSメッセージインタフェース
ROSメッセージインタフェース

移動ロボットの標準的なROSインタフェースはcmd_vel/odomというトピックの組だったが，ロボットアームでの類似のインタフェースは次のようになる．

* **control_msgs/FollowJointTrajectory（follow_joint_trajectoryアクション）**
	* アームの軌道を指示し，その経過を観察する．
* **sensor_msgs/JointState（joint_statesトピック）**
	* アームの各関節の現在の状態を配信する．

follow_joint_trajectory/joint_statesというROSのインタフェースを使って簡単にロボットアームの関節を観測したり，コマンドを送ることができる．

どのようなゴールメッセージを送ることができるのか？
![ゴールメッセージ](https://user-images.githubusercontent.com/61382602/112954664-92821100-9179-11eb-8429-de75edc1ba4f.PNG)
-かなり多くのパラメータがある．
**軌道は，経過時間とその経路に従って動作する際の許容範囲を，位置，速度，加速度，作用の目標点との組み合わせで定義することができる**ようだ．幸いにも，すべてのフィールドを埋めなくても簡単な軌道を作成することはできる．

joint_statesは...
![joint_states](https://user-images.githubusercontent.com/61382602/112954668-93b33e00-9179-11eb-9409-777d8dc5c05f.PNG)
-**各関節の現在の位置，速度，回転力（トルク）を報告している**だけ．


##手順2:ハードウェアドライバ

* ドライバを書くステップは，ロボットのハードウェアがどのように設計され，
　そのハードウェアとどうやって通信を行うことができるのかに強く依存する．

* 通信の内容がどんなものであっても，ドライバノードで何らかの計算をして，
　ロボットが提供するコマンドとデータの表現形式と，私たちが**ROSのインタフェース
　としてサポートすfollow_joint_trajectory/joint_states間での変換を行う必要がある**．

* ロボットアームを制御するための汎用的なドライバのコードはないが，ROSエコシステム内
　には，参考になるサンプルがたくさんある．

##感想
前回までは，移動ロボットの作成について扱っていたが，今回からはロボットアームについて扱う．しかしながら，ほとんどのロボット作成の方針・手順は同じようで，実際に中身は違ってくるけれども，流れは同じだと感じることができた．その流れに沿って，移動ロボットを学んだようにロボットアームについての理解も深めていきたい．


##参考文献
プログラミングROS Pythonによるロボットアプリケーション開発
　　　　　　　　Morgan Quigley, Brian Gerkey, William D.Smart 著
　　　　　　　　　　　　　　　　　　　　　　　河田　卓志　監訳
　　　　　　　　　　  　松田　晃一，福地　正樹，由谷　哲夫　訳
　　　　　　　　　　　　　　　　　　オイラリー・ジャパン　発行
VSCodeのリモートSSHが急に接続できなくなったら。

ターミナルからは`ssh {ユーザー名}@{IPアドレス}`で接続できるが、VSCodeのRemoteSSHでのみ接続できなかった時の対処覚書。

原因はおそらく、リモートマシンの`.vscode-server`内のファイルと、ホストマシンのRemoteSSHの何かがミスマッチしている。

- VSCode以外のターミナルからリモートマシンへssh接続
- リモートマシンのホームディレクトリに存在する`.vscode-server`を探す。
- 中身を全部削除
- VSCodeから再度接続する。
変更履歴をSOQLで取得する（salesforce）

SELECT Name, CustomItem__c, (SELECT OldValue, NewValue FROM Histories) FROM CustomObject__c where id = 'xxxxxxxxxxxxxx'

参考：履歴オブジェクトでの関係クエリの使用
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_relationships_query_hist.htm
WordPressのqueryやrewriteを検証するときのコピペ用PHPコード

# 概要
WordPressで新しい投稿タイプを足す時、queryやrewriteルールの書き換えのために
毎回出力用のPHPをググったり過去のメモを漁っているので
よく使うものを記事でまとめようと思いました。（覚えられない）
PHPテンプレートにコピペしてフロント側で出力を確認できます。

# コード
## WP_Queryを出力
### 現在のページのリクエストに関係する情報

```php
<pre><?php var_dump($wp_query); ?></pre>
```
### 参考
https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/WP_Query

## WP_Rewriteを出力
### リライトルール一覧

```php
<pre>
<?php
global $wp_rewrite;
      var_dump($wp_rewrite->rules);
?>
</pre>
```

### rewritecode、rewritereplace、queryreplaceの出力
#### $rewritecode
>パーマリンク構造が利用できるすべてのタグからなる配列。

#### $rewritereplace
>リライトルールの正規表現によってタグがどのように置換されるかを示す。

#### $queryreplace
>リライトルールの対応する位置によってタグがどのように変換されるかを示す。

```php
<?php
echo '<p><strong>$wp_rewrite->rewritecode</strong><br />';
foreach ( $wp_rewrite->rewritecode as $key => $val ) {
  echo $key . ' => ' . $val . '<br />';
}
echo '</p><p><strong>$wp_rewrite->rewritereplace</strong><br />';
foreach ( $wp_rewrite->rewritereplace as $key => $val ) {
  echo $key . ' => ' . $val . '<br />';
}
echo '</p><p><strong>$wp_rewrite->queryreplace</strong><br />';
foreach ( $wp_rewrite->queryreplace as $key => $val ) {
  echo $key . ' => ' . $val . '<br />';
}
echo '</p>';
?>

```
### 引用元・参考
https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/WP_Rewrite
mean Intersection over Union (mIoU) の理解と実装

segmentationの評価手法の一つであるmIoUが計算していることがよくわからなかったので絵にしてみました。

## 式[^1]
$$
mIoU = \frac{1}{k} \sum_{i=1}^k \frac{N_{ii}}{\sum_{i=1}^k N_{ij} + \sum_{j=1}^k N_{ji} - N_{ii}}
$$

* $N_{ij}$: 正解クラスが$i$であるピクセルをモデルがクラスjに分類した数
* $k$: クラス数

## まとめ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167909/563482a3-a731-e98b-22da-afb12bde85e2.png)

## Accuracyに対するメリット

* クラスの偏りがあっても不当な評価値になりにくい
  * 例) Accuracyではほとんどのピクセルが１になるようなサンプルでは、全ピクセルで１を出力するモデルでも評価が高くなってしまう。
  * mIoUではざっくりクラスごとに評価してから平均するので、２のラベルの予測が全くできていないとほとんどのピクセルがが１であっても大きく評価値に影響する。

## 実装
```python
import numpy as np
from sklearn.metrics import confusion_matrix

def mIoU(true: np.ndarray, pred: np.ndarray) -> float:
    """Calculate mIoU between 2 class label arrays
    
    Parameters
    ----------
    true : np.ndarray
        A 2d class label array
    pred : np.ndarray
        A 2d class label array of the same shape of true
    
    Return
    ------
    float
        mIoU
    """
    c_matrix = confusion_matrix(true.ravel(), pred.ravel())
    intersection = np.diag(c_matrix)
    union = np.sum(c_matrix, axis=0) + np.sum(c_matrix, axis=1) - intersection
    iou = intersection / union
    miou = np.mean(iou)
    return miou

# Test
true = np.zeros((5, 5))
true[1:3, 1:3] = 1
pred = np.zeros((5, 5))
pred[2:4, 2:4] = 1
assert mIoU(true, pred) == np.mean([1 / 7, (5 * 5 - 7) / (5 * 5 - 1)])
print("true")
print(true)
print("pred")
print(pred)
print("mIoU = %.2f" % mIoU(true, pred))
```

理解や実装に誤りありましたらご指摘いただけると助かります。

## 参考
* [Intersection over Union \(IoU\) for object detection \- PyImageSearch](https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/)
* [5\. 実践編: MRI画像のセグメンテーション — メディカルAI専門コース オンライン講義資料 documentation](https://japan-medical-ai.github.io/medical-ai-course-materials/notebooks/05_Image_Segmentation.html#%E8%A9%95%E4%BE%A1) 

[^1]: [5\. 実践編: MRI画像のセグメンテーション — メディカルAI専門コース オンライン講義資料 documentation](https://japan-medical-ai.github.io/medical-ai-course-materials/notebooks/05_Image_Segmentation.html#%E8%A9%95%E4%BE%A1) より引用
​ 環境構築不要の開発環境 Google Colaboratory 

	
Kudo Yoshihisa (工藤 廉久)
★

少し前に改めてPythonの学習を始めたのですが、自宅PCを買い替えた直後でまた環境構築するのがちょっとめんどくさいなあと思っていました。

そんな時に見つけたのがGoogle Colaboratoryです。（提供自体は2018年あたりからされているようでした。知らなかった…）
このプラットフォームは、Googleのアカウントさえあれば、何かソフトをインストールする等々もなく本当に一切の準備いらずでPythonの実行環境が整うGoogleアプリです。
手順としては
1.Googleアカウントを作成する
2.ドライブからアプリを追加する（「Colaboratory」で検索）
…だけです。

ひと手間必要でしたが、GoogleDrive内のファイル参照もできるので、データを食べさせたりと「よくあるやりたいこと」はできるのではないでしょうか。
グーグルドライブ内ファイル参照のひと手間：https://www.codexa.net/how-to-use-google-colaboratory/
​ファイル参照と結果表示のサンプル：http://column.hajimari.co.jp/archives/356

Pythonはよく機械学習や統計データの処理等にも使われており、結果を可視化させたいというケースも多いです。
Google ColaboratoryはGPUも準備いらず実行できるので、まさに手間いらずといった感じです。

調べるとGoogle Colaboratoryで実施できる機械学習のサンプルが色々ありました。
（僕自身まだできていないですが、GitHubなどからソースの共有ができるようです。）
こんなことができるんだ、くらいの認識を得るだけでも楽しいかなと思います。
サンプル集：https://tkrel.com/10041

使うとわかりますが、始めるまではすぐですし、ちょっと触ってみたいな、という人には余計におすすめできると思います。
他に似たようなものがあれば、Pythonに限らずぜひ教えてください。
気になった方は使ってみてください。
Azure Developer試験(AZ-204)受験記

# はじめに
今日（3/30）に「AZ-204: Developing Solutions for Microsoft Azure」資格（以降AZ-204）に受かったので、勉強に使った教材や試験の所感を書いていきます。
AZ-204は、AWSで言うところのDevelper Associate(DVA)ぐらいの資格だと思いますが、具体的なコード(C#)の問題が出るなど、インフラ畑の人間には多少辛い試験ではありました。
（同じようなことをDVA受けた時にも書いた覚えがありますが）
AWSと違ってAzureの資格試験に興味のある人がどれぐらいいるかはわかりませんが、誰かの役に立てば幸いです。
※試験情報はこちら
https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-204

# 獲得スコア
|受験日|スコア/合格点/満点|結果|
|:--|:--|:--|:--|
|2021/3/30|753/700/1000|合格|

# Azure経歴
Azureの経験はおよそ1年程度です。
案件としては簡単なインフラ構築案件をやったり、ドキュメント作成をする中でインフラにありがちなサービスはチョットデキル、というレベルです。
資格としてはAZ-900(AWSで言うところのCLP)、AZ-103(同SAA)は所持済みです。

# 勉強に使った教材

## Microsoft Learn
Microsoftが提供している自習用サイト。
各サービスの解説やハンズオンコンテンツが数多く提供されており、それらを無料で試せるSandbox環境も利用可能となっています。
自分は基本的に試験にあたっては問題を解きまくるスタイルですが、AzureのPortal画面はAWSに比べて癖が強く、試験ではCLIの穴埋め問題も出るので、よく知らないサービスはここでまず手を動かしておくと実務でも役に立ちます。
（※1日に10回までの利用回数制限はありますが、1つ1つをまともにやるとそこそこ時間がかかるので、普通の使い方をしている限りは実質あって無いようなものかと思います）
https://docs.microsoft.com/ja-jp/learn/

## Whizlabs
AWSで散々お世話になったWeb問題集。AzureやGoogleCloudの他にも色々な試験をカバーしているのでとても重宝しています。
過去にも書きましたが、自分は年間のサブスクリプションを購入して使い倒しています。
https://www.whizlabs.com/

## Microsoft公式ドキュメント
サービスについて調べる時はやっぱり公式ドキュメント、と言いたいところですが、Microsoftのドキュメントははっきり言ってわかりにくい(欲しい情報が書いていない・やたら日本語がわかりにくい)ので、慣れるまでに多少苦労するかもしれません。
何か調べ物をする際はざっくり解説されている個人ブログも横に並べるとイメージが掴みやすくなると思います。
https://docs.microsoft.com/ja-jp/

# 試験の所感
- 問題の形式は大きく分けて「①ケース問題」、「②多項選択式問題」、「③セット問題」の三種類
    - ①ケース問題は、特定の要件（データやセキュリティなど）を与えられて、それに応じた問題が出される形式
        - AZ-204では6問×2セット
        - 解き終わった後は見直し不可(全部の問題を解いた後に戻ってくることはできない)なので注意(※ケース問題を「完了」するまでは見直し可)
    - ②多項選択式問題は、要するにいつもの問題
        - 選択肢を正しい順番に並べ替える、コードの該当箇所のプルダウンから正しいものを選ぶ、という問題も出る
        - Microsoftの試験では部分点がある(2つ選ぶ内、片方でも合っていれば1点、など)
    - ③セット問題は、特定のケースで「このソリューションは要件を満たしますか？」みたいな問題が2つか3つぐらい連続で聞かれる形式
        - たとえばｍ「数百万件のデータを保存する」という要件があり、「AzureBlobStorageに保存します(正しいですか？)」→「ServiceBUSに保存します」→「EventHUBに保存します」といった感じで連続で聞かれるイメージ
        - こちらも解き終わった後は見直し不可(全部並べて見たらどれが正解・不正解かは何となくわかってしまうので当然と言えば当然)
- 問題はAzureサービスの設定手順を問う基本的な問題から、与えられた要件を満たすための設定値を問うやや高度な問題まで
- Azureは価格レベル（SKU）に応じてできることとできないことが細かく分かれている
    - AppServiceの場合、カスタムドメインはBasicでも利用可能だが、オートスケーリングはStandard以上じゃないと使えない、などの制約がある(他にも色々ある)
- 各サービスの構築手順は理解しておく
    - 例えば、AppServiceはAppServiceプラン作成→AppService(WebApps)作成→その他設定(カスタムドメインなど)の順番になる
    - Azure Portalなど裏でよろしくやっていて外から見えない部分もあるため、Microsoft Learnなどで一度CLIで作ってみるのが推奨
    - ちなみにAzureのCLIはbashとPowershellがあり、試験にはどちらも出る
- 主な出題範囲(サービス)は下記の通り(※括弧内はAWSで言うところのサービス)
    - AppSerivce(※後述)
    - AzureFunction(Lambda)
    - ApplicationInsights(cloudwatch)
    - APIManagement(APIGateway)
    - CosmosDB(※後述)
    - AzureAD(DirectoryService)
    - ServiceBus(SQS+SNS)
    - EventHUB(Kinesis Data Stream)
    - その他諸々
- AppServiceはAWSで言うところのBeanstalkが一番近い
    - 実際はもう少しアプリに寄った機能なのでややLambda寄りでもある
- CosmosDBはDynamoDBとDocumentDBとNeptuneを全部ひとまとめにした欲張りセットなサービス
    - AWSは機能単位でサービスを分けるが、Azureでは一つのサービスに機能をマシマシにする傾向がある
- .Net(C#)のコードについての問題もいくつか(直接・間接含めると10問程度)
- Azureを語る上でADは外せない
Google Cloud APIのAccess TokenをPythonで取得する(gcloud auth application-default print-access-tokenのやつ)

# 背景
- REST APIでGoogle Cloud APIsを実行したいので、Access Token が欲しい
- [例](https://cloud.google.com/speech-to-text/docs/async-recognize#uploading_your_transcription_results_to_a_gcs_bucket)

```sh
curl -X POST \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     -H "Content-Type: application/json; charset=utf-8" \
     --data "{
       'config': {...}
     }" "https://speech.googleapis.com/v1p1beta1/speech:longrunningrecognize"
```

- 例えば、CloudFunction上で、python経由でshell実行  `gcloud auth application-default print-access-token` してもaccess tokenは取得できなくて困る(空文字が返る)
- Pythonだけで上でAccess Tokenを取得したい

# 実装

```py:getting_access_token_with_python
import google.auth
import google.auth.transport.requests
credentials, your_project_id = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])
auth_req = google.auth.transport.requests.Request()
credentials.refresh(auth_req) #refresh token
print(credentials.token) # prints token
```

これだと、CloudFunctionからでもAccessTokenが取得できた。

# 参考
[How to get a GCP Bearer token programmatically with python
](https://stackoverflow.com/questions/53472429/how-to-get-a-gcp-bearer-token-programmatically-with-python)
Auroraのパラメータグループ確認方法

・max_connection
パラメータグループに設定値が書いてあるが、計算式で書かれていたりするので実際の値は下記クエリで確認する

```
MySQL [(none)]> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 2000  |
+-----------------+-------+

```

気になったものはどんどん追記していく
processingでfloat型をファイル読み書き（保存展開）する

# はじめに
　processingにおけるファイルの読み書きは、バイト配列やテキストなら単純にできますが、float型の読み書きがちょっと戸惑ったので、メモします。
　HDRI画像のように32bit深度の画像データを読み書きしたいのですが、最低限の機能を自前で実現するための準備です。

# 説明
　float型は4バイトあるため、そのままでは、読み書きができません。シフト演算などを駆使して、byte[4]に変換して書き込んだり、intに変換してから、byte[4]に変換して書き込んだり、といった記事が多いのですが（floatToIntBits）、もうちょっとシンプルに書けないか、試行錯誤した結果です。byte[4]に変換すると、リトルエンディアン、ビックエンディアン問題も気にしなくてはいけなくなると思います。

　javaのFileOutputStreamやFileInputStreamを使ってみたものの、ファイルの生成ができなかったので、processingのcreateOutputでファイル作成します。javaのDataOutputStreamとDataInputStreamには、float型を直接読み書きする命令があり、これが便利そうなので使いました。とてもシンプルに書けたと思います。

# ソースコード
float型の変数をout.datに保存して、
out.datを開き、floatを読み込んで、表示します。

```java:floatWR.pde
import java.io.*;

// write
float f = 3.1415926535f;
try{
  OutputStream os = createOutput("out.dat");
  DataOutputStream dos = new DataOutputStream(os);
  dos.writeFloat(f);
  dos.flush();
  dos.close();
}catch(IOException e){
  e.printStackTrace();
}

// load
float f2 = 0f;
try{
  InputStream is = createInput("out.dat");
  DataInputStream dis = new DataInputStream(is);
  f2 = dis.readFloat();
  dis.close();
}catch(IOException e){
  e.printStackTrace();
}

println(f2);

exit();
```

画像のような２次元配列の場合、以下のようになります。

```java:floatArrayWR.pde
import java.io.*;

// write
float[][] f = new float[256][256];
for (int y=0; y<256; y++) {
  for (int x=0; x<256; x++) {
    f[x][y] = sin(x)*sin(y);
  }
}

try {
  OutputStream os = createOutput("out.dat");
  DataOutputStream dos = new DataOutputStream(os);
  for (int y=0; y<256; y++) {
    for (int x=0; x<256; x++) {
      dos.writeFloat(f[x][y]);
    }
  }
  dos.flush();
  dos.close();
}
catch(IOException e) {
  e.printStackTrace();
}

// load
float[][] f2 = new float[256][256];
try {
  InputStream is = createInput("out.dat");
  DataInputStream dis = new DataInputStream(is);
  for (int y=0; y<256; y++) {
    for (int x=0; x<256; x++) {
      f2[x][y] = dis.readFloat();
    }
  }
  dis.close();
}
catch(IOException e) {
  e.printStackTrace();
}

exit();
```
ABC170 D Not Divisible

#はじめに
　本記事は競技プログラミングにおいて解くのに困った問題について、なぜその解法に思い至るのか、どのような所でハマったか等のポイントをメモした、筆者の筆者による筆者のための備忘録となっております。読まれることを意識していないので文章がとっ散らかってます。

#問題
問題は[こちら](https://atcoder.jp/contests/abc170/tasks/abc170_d)。

**問題文**
長さ$N$の数列$A$が与えられます。
次の性質を満たす整数$i(1\leq i \leq n)$を答えてください。

- $i \neq j$である任意の整数$j(1 \leq j \leq N)$について$A_i$は$A_j$で割り切れない

**制約**

- 入力はすべて整数
- $1 \leq N \leq 2 \times 10^5$
- $1 \leq A_i \leq 10^6 $

#提出解答
解答は[こちら](https://atcoder.jp/contests/abc170/submissions/21399778)。

```ABC170D.py
n = int(input())
a = list(map(int, input().split()))
a.sort()
a_max = max(a)
dp = [True]*(a_max+1)
for i in range(n):
    for j in range(2*a[i], a_max+1, a[i]):
        dp[j] = False

ret = 0
for i in range(n):
    if (i < n-1 and a[i+1]==a[i]) or (i > 0 and a[i-1]==a[i]):
        continue
    if dp[a[i]]:
        ret += 1

print(ret)
        
```

#エラトステネスの篩(ふるい)
　これはある自然数$N$以下の素数を求めるアルゴリズムです。詳しくは[こちら](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9)や[こちら](https://manabitimes.jp/math/992)。
　ざっくりと手順を書くと、

1. $2,...,N$の自然数列$A$と、空の数列$P$を用意する。
1. $A$に含まれる最小の要素$p$を数列$P$に追加し、$A$から$p$の倍数をすべて取り除く。
1. $p$が$\sqrt　N$を超えたところで終了。$P \cup A$が$N$以下の素数。

となります。考え方の根底には、「自然数から倍数を除いて残ったものを求めよう」というものが見られます。ちなみに2021 年度の一橋大学入学試験の数学において、これを背景とした問題が出題され、話題になりましたね。

#なんでこの解法に至る？
　元の問題に戻りましょう。まず、愚直な計算でやると計算量は如何ほどになるかを考えてみます。
　各$i(1 \leq i \leq N)$に対して$i \neq j$ なる$j$は$N-1$個ありますから、各$i, j$の組について判定していくと、計算量は$N(N-1)$で$O(N^2)$となり、今回の制約下ではTLEしてしまいます。困っちゃいました。
　そこで「$A_i$は$A_j$で割り切れる」という文章を「$A_i$は$A_j$の倍数である」と読み替えてみます。すると、

- $A$をソートしておいて、各$i$について$2A_i, 3A_i, ...$を$A$から除いていき、残ったものの個数が答え

というような考えに至ります(これは**厳密には正しくない**ことが後ほどわかりますが、大体の方針は上記の通り)。これはまさに先ほど述べたエラトステネスの篩の考え方と合致します。ここで$A_i$自身は除く必要がないことに気を付けましょう。
　ただ、「$x$を$A$から除く」という操作はちょっとやりにくいので、別の方法をとりましょう。すなわち、長さ$A_{max}$のbool値を持つ列$B$を用意し、すべてTrueで初期化しておきます。この下で、

- $A$をソートしておいて、各$i$について$B_{2A_i}, B_{3A_i}, ...$をFalseにしていく。
- $x \in A$のうち、$B_x$ = Trueなるものの個数が答え。

と言えるでしょう。
　一つ目の手順は計算量$O(A_{max}\log A_{max})$、二つ目の手順は計算量$O(N)$で完了でき(計算量は適当なので間違っているかも)、本問の制約下で解くことができます。

#本当にこれでいいのか？
　これで万事解決......としたいところでしたが、何やらテストケースに不穏な一文が。

**「同じ数が存在する場合に注意してください。」**

......怖いです。実際上の解法をこのテストケースである$A=[5, 5, 5, 5]$について適用してみましょう。

- $A_1 = 5$なので5以外の5の倍数をAから除きたいが、それは存在しないのでスキップ。
- $A_2, A_3, A_4$についても同様。
- $A=[5, 5, 5, 5]$が生き残り、答え$4$。

おかしくなっちゃいました。それもそのはずで、エラトステネスの篩の考え方は元々対象が自然数の列でしたから、**対象となる数列が同一の要素を持たない**時にうまくいくもので、**要素の重複があるときのことは考慮されていない**わけです。
　しかし途方に暮れる必要はありません。重複した要素は、互いに割り割られることができるわけですから、**条件を満たしようがない**わけです。ゆえに前項の手順に以下の文言を付け加えたものが、最終的な計算プロセスになります。

- $x \in A$のうち、$A$に複数個存在する要素は無視する。

これで無事解くことができました。わいわい。

#反省
　以下は個人的な反省です。

- 「割り切れる→倍数である」の読み替えは思いついたが、そこから具体的な解法に至らなかった。「約数が存在しない→エラトステネスの応用」に思い至れるとよかった。
- $A$に要素が複数個存在するか否かの判定について、ソートしていたため前後に同一要素があるか否かで判定したが、Counterを使えるとよかった。便利なライブラリは覚えていきたい。
エラー対処法が分からない駆け出しエンジニアさんへ

こんにちはHIROです。

##自分の簡単な自己紹介（興味なければ飛ばしてください）
現在新大学2年生でサイバー大学という通信制大学に通っている。
もともとフロントエンドを勉強していて3/25よりC++を勉強し始めた
C++を勉強し始めた理由としては競技プログラミングに興味を持ったからIoTに興味があるからです。
質問があれば自分のtwitterのDMへhttps://twitter.com/HIRO52636022

##はじめに

今回はプログラミング始めたての初心者あるあるなのですが、エラーが出てしまったら頭が混乱してしまう対処法について話してこうと思います。

自分の体験談なのですが1つのエラーに1日中費やしてしまってプログラミングをするモチベーションがなくなってしまうという事が多々あったんですよね。

そして結局QiitaやTeratailや知恵袋で回答が来るのを待つというオチですよね。

しかし、それでは何の力にもならないし回答を待っている時間が無駄です。

##プログラミングにおいて一番重要な事は

プログラミングにおいてエラー解決は一番重要な事なんですよ！

実際に自分自身メルカリの模倣的なアプリケーションを作っていた時も8割くらいの時間はエラーなどの解決をしていたと思います。

凄く地味な作業なのですがエラー解決方法を学ぶことによって作業がさらに効率よくなるんですよね。


Qiitaなどで質問を待っていたら半日以上何もできなくなってしまうし力もつかないのでぜひエラー解決能力を身につけましょう。

##実際にエラー解決を実践してみよう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234338/5d94f40c-6e9b-370a-b825-74af322c4315.png)

上の画像に1，2，3の番号を付けたので順を追って説明していきます。

ちなみに自分はAtomというテキストエディタを使用していますが他のでもあんまり変わりないです。

1は見たらすぐにわかるようにErrorとかWarm（警告）などが書かれているだけなので特に話しません

2は1で書かれていた内容ですね。ここではどんなところがエラーしているのかを表していますが英語で全然分からないですよね。

なのでとりあえず検索エンジンにエラー文をそのまま張り付けてみましょう。↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234338/f3f0d714-6250-7903-b12a-79a867f43735.png)

Object-Cというわけのわからない言語が出てきたのですが自分も分からないので安心してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234338/6c6cd2c0-a1bd-70d6-7140-9d1135031b6b.png)

はい、こんな感じで詳細が簡単に出てきましたね。

全角の空白があるときに出るエラーらしいです。

プログラミングのコードでは全角は使えないんですね！

上記の3に戻るのですが、どこでエラーが起こっているのか詳細に書かれているんでよね。
エラー解決の記事を見なくてもエラーが起こっている個所を見れば解決できることもありますね。

##どうしても分からないときは聞いてよし

調べても英語の記事しか出てこない事が多々あるんですよね。

こういう時筆者は、Google翻訳を使用するのですが、それでも分からなかった場合は、時間の無駄だと思うので聞くことにしています。

はい、お疲れさまでした。
slee-Pi3（ラズパイ用電源管理/死活監視モジュール）の使用 GPIO 変更

[slee-Pi3](https://mechatrax.com/products/slee-pi/) は、ラズベリーパイの電源管理や死活監視を GPIO 経由で行います。
今回は **RI 信号・IRQ 信号・HEARTBEAT 信号の GPIO 割り当て** の変更方法をご紹介します。
slee-Pi3 と他デバイスの併用で GPIO が被ってしまう際に利用できる便利な機能です。

# RI 信号・IRQ 信号・HEARTBEAT 信号の GPIO 割り当て変更
各信号のピン割り当ては出荷時状態だと下記のように設定されています。
・RI 信号 → 設定なし
・IRQ 信号 → GPIO 26
・HEARTBEAT 信号 → GPIO 5
詳細は、[こちら](https://github.com/mechatrax/slee-pi3/wiki/%E3%83%8F%E3%83%BC%E3%83%89%E3%82%A6%E3%82%A7%E3%82%A2#rpi1) を参照ください。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/e7536921-ab73-95d6-b57d-a0d802d8e7cb.png)

今回は HEARTBEAT 信号のみのピン変更を例に紹介します。
## [手順1]/boot/config.txt に追記
slee-Pi3 のパッケージが正しくインストールされているとファイル下部に下記のような記述があります。
```/boot/config.txt
dtoverlay=sleepi3
```
下記のように"，"区切りで設定したいピン番号を追記します。
```/boot/config.txt
dtoverlay=sleepi3,heartbeat_pin=24
```
保存後シャットダウンします。

## [手順2]JP3 のジャンパピン付け替え
slee-Pi3 基板上の JP3 のジャンパピンを右側に付け替えます。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/a1b1f8d4-3362-4961-bd7c-8c0ccbfb31b5.png)
以上で作業終了です。
起動後に slee-Pi3 基板上の LED1 が点滅していれば切り替え成功です。
※点滅を確認できない場合は、config.txt 追記部分の見直しや JP3 のジャンパピンが奥まで差し込まれているか確認して下さい。

### 各信号に対するパラメータは下記の設定も可能です。
これらは手順1と同じく config.txt に追記してください。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/fa41b221-a4fd-200a-d1fb-d86ecfc037bc.png)
以上が変更方法の紹介でした。
ご覧いただきありがとうございました。
【Rails】Railsサーバ起動時にすでに起動しているといわれた時の対処法 A server is already running. Check /home/ubuntu/environment/プロジェクト名/tmp/pids/server.pid.

<h2></h2>

rails sでサーバーを起動しようとすると、ターミナルに下記エラーが表示されてしまいました。
ざっくりエラーを確認すると、「すでにサーバーが立ち上がってるよ」と言っているようです。

```terminal:ターミナル
rails s
=> Booting Puma
=> Rails 6.0.3 application starting in development 
=> Run `rails server --help` for more startup options
A server is already running. Check /home/ubuntu/environment/プロジェクト名/tmp/pids/server.pid.
Exiting
```

<h2>解決法</h2>
rails s発行時の5行目のCheckより後ろのアドレスをopenすると、数字(対象サーバーのプロセスID)の記載がありました。

```server.pid
18445
```

上記IDに対して、killコマンドを発行したのちに、再度railsサーバーを起動したら、正常に起動できました。
ちなみに、killコマンドはプロセスを終了させるコマンドです。

```
kill 18445
```

<h2>参考</h2>
"`rails s`でサーバー起動時の"「`A server is already running.`」エラーへの対処
https://zenn.dev/masa20210102/articles/2fa07434282044

プロセスを終了するkillコマンドの使い方まとめ！【Linuxコマンド集】
https://eng-entrance.com/linux-command-kill
たまに使うページスクロール時にページトップからどれだけ移動したかを取得する方法

ページスクロール時にページトップからどれだけ移動したかを取得する方法。

```javascript
    window.addEventListener('scroll', () => {
      console.log(window.pageYOffset)
    })
```

地味に使うのでメモ
Hello Worldを作りました

# HelloWorldを作りました
## 概要
HelloWorldを作りました

## ご挨拶
みなさん初めまして。
そろそろ4月ということで、新入生や新入社員の方がプログラミングを始めることもあるかと思います。
最初に書くプログラムの定番といえばそう、"HelloWorld"ですね。
HelloWorldのプログラムを作成したので、本記事でも紹介していこうと思います。

※以下、出てくるコードはpaiza.ioで動作確認したので、トップレベルステートメントは使いません。

## HelloWorld
```CSharp
class Program
{
    static void Main()
    {
        System.Console.WriteLine("Hello World!");
    }
}
```

オーソドックスですね。

## マジックナンバー
このHelloWorld、シンプルでいいと思うのですがマジックナンバーが使用されていますね。
マジックナンバーを使用せずに定数を使用する癖をつけておいたほうがいいかもしれません。

```CSharp
class Program
{
    private static readonly string DisplayText = "Hello World!";

    static void Main()
    {
        System.Console.WriteLine(DisplayText);
    }
}
```

## 文字列リテラル
文字列リテラルもある意味マジックナンバーみたいなものなのでは？(暴論)
そんなわけで文字列リテラルを排除してHelloWorldを作成してみました。

```CSharp
class Program
{
    static void Main()
    {
        var O=sizeof(byte);
        var T=sizeof(char);
        var t=O+T;
        var F=T*T;
        var E=T*F;
        var s=E*F;
        var _=s+O;
        var d=_*t+O;
        var e=d+O;
        var l=d+E;
        var h=l-s-F;
        var o=l+t;
        var r=o+t;
        var w=o-s+E;
        foreach (char c in new[] { h, e, l, l, o, s, w, o, r, l, d, _ })
        {
            System.Console.Write(c);
        }
    }
}
```

## 終わりに
マジックナンバー(もとい、文字列リテラル)を排除したHelloWorldを作成してみました。
コードゴルフ的に遊んだら面白いかもしれません。
【Swift】シミュレータでもデバイスの種類を取得する

## 環境
- Xcode Version 12.4 (12D4e)


## 実現したいこと
- デバイスの種類毎にUIを微調整したい
    - ex) iPhone SE(1st) より小さいデバイスでは CollectionView のレイアウトを2列に変更する


## 問題点
- 実機での種類は `hw.machine` で取得可能

```swift
            var size = 0
            sysctlbyname("hw.machine", nil, &size, nil, 0)
            
            var machine = [CChar](repeating: 0, count: Int(size))
            sysctlbyname("hw.machine", &machine, &size, nil, 0)
        
            let modelIdentifier = String(cString:machine)
```

- シミュレータでこのコードを動かすと一律で `modelIdentifier` が  `"x86_64"` になってしまう


## 解決方法
- シミュレータの場合には `ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]` を利用することでシミュレート中のデバイスのモデルを取得できる

```swift
// MARK: - UIDevice

public extension UIDevice {


    // MARK: - DeviceType

    enum DeviceType {

        // サンプルコードの簡略化のため5種類にわける.
        case simulator
        case iPod
        case iPhone
        case iPad
        case unknown

        init(by value: String) {

            if value.range(of: "i386") != nil { self = .simulator }
            else if value.range(of: "x86_64") != nil { self = .simulator }
            else if value.range(of: "iPod") != nil { self = .iPod }
            else if value.range(of: "iPad") != nil { self = .iPad }
            else if value.range(of: "iPhone") != nil { self = .iPhone }
            else { self = .unknown }
        }
    }

    func deviceType() -> DeviceType {

            var size = 0
            sysctlbyname("hw.machine", nil, &size, nil, 0)
            
            var machine = [CChar](repeating: 0, count: Int(size))
            sysctlbyname("hw.machine", &machine, &size, nil, 0)
        
            let modelIdentifier = String(cString:machine)
            let deviceType = DeviceType(by: modelIdentifier)

            // シミュレータの場合には ProcessInfo からシミュレート中のデバイスのモデルを取得する
            if case .simulator = deviceType {
                    
                    if let simulatorModelIdentifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {

                        return DeviceType(by: simulatorModelIdentifier)
                    }
                    
                    return .unknown
            }

            return deviceType
    }
}
```


## 参考
- https://qiita.com/tomohisaota/items/f8857d01f328e34fb551
- https://stackoverflow.com/questions/33493800/how-to-get-the-iphone-type-from-simulator-ios