OmniAICreator/Qiita-1.07M huggingface dataset:
DontDestroyOnLoadのGameObjectを列挙する

## シーンに配置されているもの一覧

開発中のデバッグにおいて、今のシーンに配置されている`GameObject`の一覧を取得したいことがあります。
`UnityEditor`上でならば`Hierarchy`上にあるものを見れば済むわけですが、やっぱり実機上で何が起こっているのかを知りたいわけです。
このとき、普通のシーン上に配置されているものなら以下のコードで取得できます。

```c#:getCurrent
// 現在のHierarchyのRootにあるGameObjectの一覧
var currentSceneGameObjects = SceneManager.GetActiveScene().GetRootGameObjects();
```
## DontDestroyOnLoadの一覧

普通のやつはそれでいいのですが、`DontDestroyOnLoad`に登録された`GameObject`を取得するAPIはありません。
実機でしか動作しないSDKが動的に~~テキトーに~~作成する`GameObject`や、タイミングによって実機でしか起きない事象などを解析する場合など、どうしても実機上で`DontDestroyOnLoad`の一覧が取りたい場合があります。
というわけで、以下のような回避策で取得することができました。

```C#:workaround
// まずDontDestroyOnLoadされたGameObjectを作る
var go = new GameObject(string.Empty);
Object.DontDestroyOnLoad(go);
// DontDestroyOnLoadはSceneの一種なので,GameObject.sceneから取得することができる
var dontDestroyOnLoadGameObjects = go.scene.GetRootGameObjects();
```

## 解析用コード

これを利用してこんな解析用のコードを作ってみました。
このファイルをプロジェクトに入れておくだけで、シーン遷移のたびに、シーン名と合わせて`DontDestroyOnLoad`の一覧をログに出力してくれます。
`CollectDontDestroyOnLoad()`を`public`にしておいたので、好きなときに`GameObject`の配列を取得することもできます。

[gist](https://gist.github.com/nekomimi-daimao/bd22bb881d3fa4a25df803aa3bcc8b6e)

```C#:DontDestroyOnLoadCollector
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Nekomimi.Daimao
{
    public class DontDestroyOnLoadCollector
    {
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
        private static void Register()
        {
            SceneManager.sceneLoaded += (scene, mode) =>
            {
                var ddol = CollectDontDestroyOnLoad();
                var separator = ", ";
                var s = string.Join(separator, ddol.Where(go => go != null).Select(go => go.name));
                Debug.Log($"DDOL_{scene.name} : {s}");
            };
        }

        public static GameObject[] CollectDontDestroyOnLoad()
        {
            var go = new GameObject(string.Empty);
            Object.DontDestroyOnLoad(go);
            var ddol = go.scene.GetRootGameObjects();
            Object.Destroy(go);
            return ddol.Where(o => o != null && !string.Equals(o.name, string.Empty)).ToArray();
        }
    }
}

```

## 実機での動作について
[How can I get all DontDestroyOnLoad GameObjects?](https://gamedev.stackexchange.com/questions/140014/how-can-i-get-all-dontdestroyonload-gameobjects)
ここの解答をもとに作ったのですが、Editorでしか動かないことが強調されています。
> works only in the Editor

また、その根拠として示されている[公式ドキュメント](https://docs.unity3d.com/Manual/MultiSceneEditing.html)でも以下のような記載があります。
> You do not have access to the DontDestroyOnLoad scene and it is not available at runtime.

でも私が試したところでは`Android`でも`iOS`でも実機にブッこんだら**動きました**！
`UnityEditor`のバージョンは2018と2019です。下のバージョンは覚えてない。
`Android`と`iOS`でしか試してませんが、この分だと他のプラットフォームでも動きそうな気がします。
公式ができねえ！　と言ってることをやってるので、使用範囲はあくまでもデバッグにとどめたほうがよいとは思いますが。

## まとめ
先人の解答を参考にしつつも、とりあえず**自分で数発殴ってみる**ことは重要だなって思いました。
あと普通に考えて公式がそういうAPI用意してくれてもよくない……？　って！　思いました！
`DontDestroyOnLoad`って状態の権化みたいなものなのでできるだけ使わないのがベストプラクティスな気もしますが。でも使っちゃうね。しょうがないね。

おしまい。
存在しない正規表現 ~正規表現と秘密の部屋~

この記事は  **[闇の魔術に対する防衛術 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yaminomajutu)** の2日目の記事です。

3日目は **@Ringa_hyj** さんの記事です。

参加しているカレンダーとして完走させたいので、是非参加してください！
枠はまだまだ空いています！

---

闇の魔術っぽいタイトルにするため、タイトルを一部省略しました。

本記事では **(常に検索結果が)存在しない正規表現** を考えてみる記事です。

正規表現は **「文字列内で文字の組み合わせを照合するため」に用いられるもの** です。

では、正規表現では無意味なパターン、 **「常に照合結果が0件となるパターン」** は作れるでしょうか？
そのようなパターンが作れるのであれば、「実務で使われることがない（意味がない）≒知られていない」ことから、 **正規表現の秘密の部屋** といえるでしょう。~~無理やり~~


また、関連した内容として、 **「常に照合結果が存在するパターン」** と、 **「(予想外に)シンタックスエラーとなってしまうパターン」** も存在したので紹介します。

なお、本記事は、`ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]` にて動作検証をしています。

# 常に照合結果が0件となる正規表現

## 先頭を示すアンカー前に文字クラスがある正規表現

例）/a\A/

```
irb(main):001:0> "Am I Dead?".match(/a\A/)
=> nil
```

## 末尾を示すアンカー後に文字クラスがある正規表現

例）/\zz/

```
irb(main):002:0> "Am I Dead?".match(/\zz/)
=> nil
```

## 単語境界かつ非単語境界の正規表現


例）/\b\B/

```
irb(main):003:0> "Am I Dead?".match(/\b\B/)
=> nil
```

## &&で作成した存在しない文字クラス

例）/[a&&Z]/

```
irb(main):004:0> "Am I Dead?".match(/[A&&z]/)
=> nil
```

## 矛盾した(否定)先読み

例）/(?!A)A/

```
irb(main):005:0> "Am I Dead?".match(/(?!A)A/)
=> nil
```

## 矛盾した(否定)後読み

例）/A(?<!A)/

```
irb(main):006:0> "Am I Dead?".match(/A(?<!A)/)
=> nil
```

## 任意文字列のアトミックグループ後の任意文字のパターン

例）/(?>.*)./

```
irb(main):007:0> "Am I Dead?".match(/(?>.*)./)
=> nil
```


# 常に照合結果が存在するパターン

## ちょうど0回の量指定

例）/.{0}/

```
irb(main):001:0> "Am I Dead?".match(/.{0}/)
=> #<MatchData "">
irb(main):002:0> "".match(/.{0}/)
=> #<MatchData "">
```


# (予想外に)シンタックスエラーとなってしまうパターン

## 量指定子の最小が最大より大きい

例）/.{2,1}/

```
irb(main):001:0> "".match(/.{2,1}/)
Traceback (most recent call last):
        3: from /usr/local/bin/irb:23:in `<main>'
        2: from /usr/local/bin/irb:23:in `load'
        1: from /usr/local/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
SyntaxError ((irb):1: upper is smaller than lower in repeat range: /.{2,1}/)
```

---

以上です。他のパターンもあれば、コメント欄などで教えてください！
JavaScriptでクエリパラメータを取得

# 方法

```js
new URL(decodeURIComponent(document.location.href)).searchParams.get(<keyName>)
```

で取得できます。


# 解説

```
http://example.com/?param1=hoge&param2=fuga
```

例えばこのようなクエリパラメーターつきのURLがあるとします。
それぞれ`param1`と`param2`の値である`"hoge"`と`"fuga"`を取得したいと思います。

## URLを取得

```js
document.location.href
// "http://example.com/?param1=hoge&param2=fuga"
```

パーセントエンコーディングに対応させる場合

```js
decodeURIComponent(document.location.href)
```

このようにしてデコードできます。

## パラメータを取得

```js
new URL(decodeURIComponent(document.location.href))
// URL {...}
```

先ほどのURLから[URLオブジェクト](https://developer.mozilla.org/ja/docs/Web/API/URL)を作ります。


```js
new URL(decodeURIComponent(document.location.href)).searchParams
// URLSearchParams {...}
new URL(decodeURIComponent(document.location.href)).searchParam.get("param1")
// "hoge"
new URL(decodeURIComponent(document.location.href)).searchParam.get("param2")
// "fuga"
```


そして[URLSearchParamsオブジェクト](https://developer.mozilla.org/ja/docs/Web/API/URLSearchParams)に対して、getメソッドでキーを指定することでパラメータを得ることができます。
強震モニタの画像から震度と地点を特定するまで

この記事は [地震界隈 Advent Calendar 2020](https://adventar.org/calendars/5903) 3日目の記事です。

# 自己紹介
ingen084です！
リアルでは5月頃から某サイトの主にプレミアム会員を扱うグループで働かせていただいています。[^1]
(隠してたけど最近特に隠さなくてもいいかなというお気持ちになってきた、というかGitHub見たらバレる)

[KyoshinEewViewer for ingen](https://github.com/ingen084/KyoshinEewViewerIngen)
というソフトを作っていますが、最近更新できていません…。使ってくださっている方ごめんなさい。

# この記事について
僕の頭の中のノウハウ(というか考え方？)の共有ということで。
画像の取得はすっ飛ばしています。今回の記事はあの点が並んでいる画像から場所ととの震度を求めます。

# 強震モニタの情報を解析するアプリを作る前に考えてほしいこと
私達サードパーティソフトウェアの開発者は**不正な方法で強震モニタを閲覧している、させている**事を忘れないでください。
**複数のアプリケーションを起動することや、複数の情報がほしいがために通常のWebページで閲覧している以上のHTTPリクエストを送信することは、意図的に負荷をかけていることに違いありません**。
強震モニタはみなさんの税金で運用されています(はず)。アプリケーションを利用･開発した結果迷惑をかける可能性が高いことを念頭に置き、負荷や帯域の面から見ると常に他の利用者に迷惑をかけていることを考慮しましょう。[^2]

# 画像から観測点を特定する
まずは観測点です。
結論としては現状強震モニタが使用している地図の図法がわからない(僕がにわかなだけかも)かつ、見やすいように観測点がずらされている可能性なども考慮しほぼ手動でマッチングを行うしかありません。
まあ大体の人はこの時点で察してしまうと思いますが、この投稿ではその観測点のデータを作成するにあたってのテクニックを紹介します。

## 観測点を絞り込む
観測点はNIEDで公開されていますが、無効のものも含め1700件ですが、実際の強震モニタの画像には1000件ちょっとしか表示されておらず、700件ほどが表示されていない観測点になります。
まずその不要な観測点を取り除く作業を行うのですが、それに使用するのがかつて試験公開されていたスマホアプリ版強震モニタのAPIです。

APIの詳細はこれもまた需要があれば書きますが(コメントください)、このAPIでは詳細な観測点はわかりませんが観測点の震度と座標がわかります。
同じ強震モニタですから、このAPIで使用されている座標は強震モニタの画像でも使用されているということです。

APIについての詳細を見てみたい方は僕のライブラリのコードも参考にしてみてください。
https://github.com/ingen084/KyoshinMonitorLib

それAPIにも欠点があり、

1. 観測点が少ない
2. 異常な震度の観測点が混ざることがある
3. そもそも正規のページで使用されるAPIではない

といった問題があります。
それを無理やり使用しているのが僕のソフトですが、使用は推奨しません。

ですがこれを活用することで観測点を絞り込むことが可能になりました。
ただし多少の差異はあるので適時見極めていきましょう。

## 観測点を割り当てる
実際の地図も参考に割り当てていきましょう！
地獄のように感じますが、結構絞り込めているので数時間で終わらせることが可能です。
アドバイスと言うかヒントですが、観測点がかぶっていると思われる箇所はたいていKiK-netが優先されています。
地中震度とかあるので。いままで手動でやろうとしてた人はアハ体験できるかもしれません。

## 拙作のツールとデータでぱぱっとやる方法(宣伝)
ここまでめんどくさそうな解説をしてきましたが、これらはすべて僕が作業してきたものでありMITライセンスでツールと成果物を配布しています。
好き勝手使ってください。

https://github.com/ingen084/KyoshinEewViewerIngen
これをCloneして `src\Tools\ObservationPointEditor` をビルドしてください。

ビルド先のディレクトリの `ObservationPointEditor.exe` を起動して、左下の `ファイル(F)` → `読み込み(L)` でさっきcloneしてきたフォルダの
`src/KyoshinEewViewer/Resources/ShindoObsPoints.mpk.lz4` を開いてください。僕が数時間かけて調整した観測点データがあります。[^3]

主に左側のパネルで操作するのですが、細かい解説は需要があったらやります(コメントください)。

上記のソフトを介することでCSVやJsonで出力することも可能です。
C#での使用例: https://github.com/ingen084/KyoshinMonitorLib/blob/master/src/Tests/Program.cs

# 画像の色から震度を求める
観測点の座標がわかったらあとは色から震度を求めるだけですね。

震度の場合、-3.0～6.9の100段階？で色が変化します。
まだ不確定ですが震度7.0の色も含めた101色の割当表を公開しています。
https://github.com/ingen084/KyoshinShindoColorMap
活用してね！

加速度の場合はちょっと難しく、500段階ほどありそうでした。(未特定)
近似値になる計算式を求めてもいいんですがやはりテーブルを作ったほうが確実だと思うので、そのあたりは見極めていきたい。(やる気力はない)


[^1]: 過去に投稿してるAPIとかの記事は入社前なので、あくまで一個人としての投稿です。更新予定はありませんが、削除するかもしれません。
[^2]: ちなみに気象庁のサイトは合法的にスクレイピングできるらしいです。あんまりやりたくないけど。
[^3]: 今となってはオマケ機能ですが、ほかのフォーマットのファイルも読み込めるようになってます。
【小ネタ】ユーザー名を変えたら「dyld: Library not loaded」

# ユーザー名を変えた
[こ↑こ↓](https://support.apple.com/ja-jp/HT201548)の通りに変えてみた
【変更前】`soluna`=>【変更後】`SolunaEureka`
ちゃんと再起動もした

# 結果

```bash
$ ruby -v
dyld: Library not loaded: /Users/soluna/.rbenv/versions/2.7.2/lib/libruby.2.7.dylib
  Referenced from: /Users/soluna/.rbenv/versions/2.7.2/bin/ruby
  Reason: image not found
Abort trap: 6
```
ユーザー名が古い方で動作していた


### 影響を受けた奴ら
`ruby`（`rbenv`），`python3`（`pyenv`），`node`（`nodenv`）
載せているのは1個目のケース
というか確認してないだけで相当数が影響を受けてるんじゃ…

# 解決

## `source ~/.bashrc`をやり直す

```bash
$ ruby -v
dyld: Library not loaded: /Users/soluna/.rbenv/versions/2.7.2/lib/libruby.2.7.dylib
  Referenced from: /Users/SolunaEureka/.rbenv/versions/2.7.2/bin/ruby
  Reason: image not found
Abort trap: 6
```

シンボリックが参照してくるディレクトリの文字列が変わってねぇ

## そもそも入れ直す
```bash
rbenv uninstall 2.7.2
rbenv install 2.7.2
```

## 解決した
```bash
$ ruby -v
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
```

### 他のも全て同じ方法で解決した
もっとややこしい問題だと思ったけどコレで済んでよかった

### 気づいたこと

```bash
...
Downloading openssl-1.1.1h.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/5c9ca8774bd7b03e5784f26ae9e9e6d749c9da2438545077e6b3d755a06595d9
Installing openssl-1.1.1h...
Installed openssl-1.1.1h to /Users/SolunaEureka/.rbenv/versions/2.7.2
...
ruby-build: using readline from homebrew
...
```

なぜか`openssl`が入れ直された
あと`ruby-build`も`node-build`も`python-build`もみんな`openssl`と`readline`を使っとる
そして`python-build`だけ`/usr/local/Cellar/`にない，なにゆえお前だけ`/usr/local/bin/`にある…
（昔の記憶がもう残っていないから不明）（brewは取り扱っていないらしい）
Elixir 1.11 でついに新しくなった Logger

この記事は、[Elixir Advent Calendar 2020](https://qiita.com/advent-calendar/2020/elixir) の1日目です。

アルケミストのみなさんこんにちは。こんにちは。今年もアドベントカレンダーがはじまりました。[去年は派手なネタに力を入れて書いた](https://qiita.com/kikuyuta/items/9690e0905bf4fded937b)のですが、今年は地味〜に軽く行きますね。

# Elixir の Logger の問題
今回のネタは前から気になっていた [Elixir の Logger](https://hexdocs.pm/logger/Logger.html) の話です。ずっとブチブチ文句を言ってたのですがついに [version 1.11](https://elixir-lang.org/blog/2020/10/06/elixir-v1-11-0-released/) で改善されました。何が気に食わなかったかと言うと、これまでの[Elixir ではレベルが4つに限定されている](https://qiita.com/kikuyuta/items/a06a36582701d7ef3725#elixir-ではレベルが4つに限定されている)からなのでした。

- :debug - デバッグ関連メッセージ
- :info - いろんな情報提供
- :warn - 警告
- :error - エラー

これはただでも種類が少ない上に MacOS での開発でもっと困る事態を引き起こしてました。Logger の出力を syslog に向けることができるのですが、Macの「コンソール」アプリには error と warn しか出てこないので（手元のはMacOS10.15.7）、事実上ログレベルを2種類に制限されてしまうという状況を招いていました。このため debug や info レベルのログメッセージを warn や error として Logger に出すというあまり良くない振る舞いを強制されることになってました。

# Logger レベルの改善
ちょっとまえに [Erlang の logger](https://erlang.org/doc/man/logger.html) が先に改善されて Elixir も追いかけるように改善されました。今は以下の[8つのレベル](https://hexdocs.pm/logger/Logger.html#module-levels)になっています。これによると重篤なレベルから以下のように定義されています。

- :emergency - システムが利用不能・パニック状態になった場合
- :alert - 警報、直ちに措置が必要な場合、例えばデータベースの障害など
- :critical - 致命的な状況
- :error - エラーの発生
- :warning - 警告
- :notice - 通常のただし重要なメッセージ
- :info - いろんな情報
- :debug - デバッグ関係のメッセージ

これでレベルの少なさに悩む必要はなくなりました。MacOS のコンソールアプリでも6レベルが出せますので、info や debug レベルのメッセージを notice レベルとしてログ出力しないとならないとしても、まあ許せる範囲でしょう。

なお、「致命的な状況」「エラーの発生」「警告」ってなんだよ〜、説明になってないぞ、と憤慨される向きもあろうかと思いますが、これは Elixir が悪いのではなく元々このレベルを規定している IETF の syslog の標準ドキュメント [RFC5424: The Syslog Protocol](https://tools.ietf.org/html/rfc5424#page-11) にそう書いてあるのです。

# そのほかの改善
今回の Logger ではメッセージとして出力できるのが（引数として許す型が）文字列以外にもリストやマップを受け取れるようになりました。例えばこれまでは、
`err_info = [something: :reported, this: :error]`
を Logger に出力させたければ
`Logger.error(inspect(afo))`
と書いていたのが
`Logger.alert(afo)`
とか直接書けるようになりました。これは便利です。

ただしこれ、もう一声感があって、もうすこし複雑な構造は使えません。たとえば Logger に出したくなるのはプロセス作ったときの pid だったり何かオープンした結果の ref だったりするのですが、それは直接書くことができず、あいかわらず `inspect/1` 関数に食わせて文字列にしないとなりません。

# まとめ
Logger の機能が良くなって使いやすくなりました。さらによく使う型にも対応してくれると嬉しいですね。自分で改良して本家にプルリク出したいところです（夢）。

さて、明日の[Elixir Advent Calendar 2020](https://qiita.com/advent-calendar/2020/elixir) 2日目の記事は [@Papillon6814](https://qiita.com/Papillon6814) さんの[Timexで時を操る](https://qiita.com/Papillon6814/items/d71a7f3fed26ea0b0d96)です。お楽しみに！

# 参考文献
- [Elixir Logger](https://hexdocs.pm/logger/Logger.html)
- [Erlang logger](https://erlang.org/doc/man/logger.html)
- [RFC5424: The Syslog Protocol](https://tools.ietf.org/html/rfc5424#page-11)
- [はじめてな Elixir(23) ログを出力する](https://qiita.com/kikuyuta/items/b4d6a4e0ea591281f920)
- [はじめてな Elixir(24) ログを出力しない](https://qiita.com/kikuyuta/items/9f15e92046845dcba4b0)
- [はじめてな Elixir(28) Logger ライブラリを改造する](https://qiita.com/kikuyuta/items/a06a36582701d7ef3725)
- [言語バトル時には秘匿しておきたい Elixir の急所](https://qiita.com/kikuyuta/items/9690e0905bf4fded937b)
モバイルゲームのサブスクリプション型サービスをQAしてみよう

#はじめに
先日私の担当するモバイルゲームで、サブスクリプション機能（以下サブスク）がリリースされました。
プラットフォーム（以下PF）の機能を使用した定期購入のリリースは弊社で初めてであったため、色々と苦労することが多かったので、ナレッジとしてまとめてみたいと思います。
#本記事のターゲット
本記事では、AppleのAppStore、GoogleのPlayStoreでそれぞれ提供している定期購入システムを利用して、
モバイルゲームでサブスク型のサービスを提供するケースをターゲットとしています。
具体的には、**「月○○円を定期的に支払う代わりに、期間内はゲーム内で何らかの特典が発生する」**
といったような機能のことを指しています。
今回は↓のようなサービスを想定して、記事を書いていきたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320947/c72bb406-13e3-6513-9e82-72dd6fa7d6ed.png)


#サブスク型サービスのテストの流れとフェーズごとのTips
サブスクのテストをフェーズに分けて、各フェーズのタスクやTipsを記載するという形で流れを説明していきたいと思います。
今回はザックリと以下の4つに分けています。

- 環境準備
- テストケース作成
- テスト実施
- リリース後

**※サブスク以外でも確実に実施するようなタスクは省略しています。**

##環境準備
サブスクの検証を行うために必要な環境の準備です。


| タスク | 説明 | Tips |
|:---|:----------|:---|
| 課金検証環境の準備  |サブスクリプションの検証時は、疑似課金が出来るsandbox環境が必須です。<br>下の記事等を参考にして、プロダクトチームに環境を準備してもらってください。<br>https://qiita.com/Masataka-n/items/6f98a5a9fee7b28ccd1f<br>https://qiita.com/soratyan/items/91423b9d0d474cb044c7| sandbox環境ではサブスク継続期間は5分で固定されます。<br>5分間でコンテンツが確認しきれない場合は別途デバッグ機能の用意等が必要になります。|
|  課金用アカウントの準備 |iOS/Androidそれぞれで課金検証用のアカウントが必要です。<br>| **-iOSのテスト課金アカウント準備**<br>AppStoreConnectでdeveloper以上の権限を持っていれば、sandboxアカウントが作成できます。<br>https://developer.apple.com/jp/apple-pay/sandbox-testing/<BR>**-Androidのテスト課金アカウント準備**<br>Playコンソールから課金テスターを追加できます。<br>https://support.google.com/googleplay/android-developer/answer/6062777?hl=ja<br>実在のメールアドレスが必要かつ、権限付与したアカウントは、組織内のすべてのアプリに課金の権限を持ちます。  |
|検証端末の準備|検証に使用する実機端末の準備です。|iOSの場合、14以降では無料や割安でサービスを提供する、トライアル期間のリセットが行えます。<BR>AndroidやiOS14未満の端末ではトライアル期間のリセットは出来ないので、複数回検証する場合はその数だけアカウントが必要になります。|
|デバッグ機能の準備|サブスク検証に必要なデバッグ機能の準備です|以下のようなデバッグ機能があると便利でした。<br>どんな時に使ったかは、テスト実施の項目で記載します。<br>・サブスク課金状態にする機能<br>・サブスク加入状態のユーザの時刻を変更する機能<br><br>|

##テストケース作成
テストケース作成時にベースとなる観点や、検証項目ごとの注意事項を記載します。
あくまでこれは一例で、実際の実装ごとに追加で必要な観点は色々あると思うので、テストケースを作成する際には企画やエンジニアと調整のうえで進めてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320947/643bc043-ec4e-bd42-8086-ab6ec6e21e13.png)


##テスト実施
テスト実施では往々にしてトラブルが発生し、検証が期間内に行えない場合等もあります。
トラブルの対処などQAの手腕が問われるフェーズとなります。
ここでは事前準備したデバッグ機能の活用法や、検証が行えなかった時の対処方法等、サブスクに特化したテスト実施時のタスクを記載します。

| タスク | 説明 | Tips |
|:---|:----------|:---|
|デバッグ機能の使用|PFのsandbox課金だけではカバーできない部分は、デバッグ機能を実装してもらって検証します。|＜使用例＞<br>・特典コンテンツ挙動確認<br>sandboxは5分で期限が切れるので、サブスク加入状態でコンテンツを広く確認することには向いていません。特典コンテンツのボリュームが多い場合、サブスク加入状態を作る機能が必要になると思います。<br>・月跨ぎの挙動確認<br>月を跨ぐ際に特典コンテンツが更新される、月跨ぎで継続するとボーナスがつく、といった実装の際には、サブスク加入状態で時間を操作できる機能や、サブスク継続回数を操作できる機能が必要になります。|
|検証不能箇所の洗い出し|sandbox課金が5分で更新されるという制約上、ユーザ環境と全く同じ検証は不可能です。<br>TestFlightでもSandBoxと同じ挙動になるので、ユーザと同環境での挙動の担保方法はリリース前に決めておきましょう。|テスト準備・テスト設計・テスト実施の各フェーズでリスクとなる箇所が判明していくと思います。メンテナンス状態でリリースして、実課金を行ってからリリース等のリスク回避・軽減手段を事前に検討しておくとよいでしょう。|

##リリース後
サブスク以外の施策でも実施するとは思いますが、リリース後の状況確認は必ず行いましょう！
注意するタイミングとしては、次のようなものがあげられます。

- 契約の更新タイミング
- 特典コンテンツの更新タイミング(月初等）
- 継続ボーナスの発生タイミング

特に、テスト実施フェーズで例示したような残存タスクがある場合には、リリース後の確認はとても重要になってきます。

#最後に
簡単ではありますが、サブスクのテストを行った際に感じたことを書き連ねてみました。
今回記載しなかったことでもナレッジとなる可能性があるので、何か気になることがあればお気軽に質問ください！
【UE4】【TIPS】uprojectを開けない時の対処法一覧【随時更新】

# 最初に

この記事はuprojectが開けない場合の対処法を自分用にまとめたものとなります。

こちらは対応が発生次第随時更新していきます。

# 対処法


### Binariesフォルダの削除

「ロードができなかった」などのエラーメッセージが表示され、プロジェクトが開かれなかった場合に、プロジェクトフォルダ下にあるBinariesフォルダを削除してバイナリを再構築してみる。

### Intermediateフォルダの削除

作業の途中でクラッシュして、その後開けなくなった場合に有効。

https://answers.unrealengine.com/questions/440407/view.html

### Saved/Configフォルダの削除

上記フォルダを削除しても解決しない場合はSavedフォルダの削除も行う。それでも解決しない場合はConfigフォルダの削除も試す。
https://answers.unrealengine.com/questions/190708/cant-open-project-2.html

### ファイルパス文字の確認

外付けHDD等にプロジェクトを保存している場合にたまにあるかもしれない。

https://answers.unrealengine.com/questions/857471/view.html

### 新しいプロジェクトを作成しContentsフォルダを移す

力技にはなるけど急いでいる場合には有効かも。

https://answers.unrealengine.com/questions/234498/view.html

### Saved/Logsの確認

こちらに何故Crashしたか、などの問題解決につながるログが眠っている可能性がある。
指定した緯度経度から最も距離の短い線分上の緯度経度を返す

文字で説明するとよくわからないので、インタラクティブに表すと次の図のようなものです。

![cap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/7070b3b0-6b04-5d1e-8880-527c93592b56.gif)

マウスカーソルの位置に最も近い、線分(LineString)上の点を赤で描画しています。

これは turf.js の [``nearestPointOnLine``](http://turfjs.org/docs/#nearestPointOnLine) を使用します。

- [Mapbox with OpenStreetMaps - JSFiddle - Code Playground](https://jsfiddle.net/amay077/qn8m3pbj/)

```javascript
// <script src='https://unpkg.com/@turf/turf/turf.min.js'></script>

const routeSource = {
  'type': 'geojson',
  'data': {
    'type': 'Feature',
    'properties': {},
    'geometry': {
      'type': 'LineString',
      'coordinates': [
        [-122.48369693756104, 37.83381888486939],
        [-122.48356819152832, 37.82954808664175],
        [-122.48751640319824, 37.83168351665737],
        [-122.49223709106445, 37.83337825839438],
        [-122.49378204345702, 37.83368330777276]
      ]
    }
  }
};

const pointFeature = {
  type: 'FeatureCollection',
  features: [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type":"Point",
        "coordinates": []
      }
    }
  ]
};

const map = new mapboxgl.Map({
  container: 'map',
  center: [-122.486052, 37.830348],
  zoom: 15,
  style: {
    version: 8,
    sources: {
      OSM: {
        type: "raster",
        tiles: [
          "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
        ],
        tileSize: 256,
        attribution:
        "OpenStreetMap",
      },
    },
    layers: [{
      id: "BASEMAP",
      type: "raster",
      source: "OSM",
      minzoom: 0,
      maxzoom: 18,
    }],
  },      
});

map.once('load', () => {

  map.addSource('route', routeSource);
  
  map.addLayer({
    'id': 'route',
    'type': 'line',
    'source': 'route',
    'layout': {
      'line-join': 'round',
      'line-cap': 'round'
    },
    'paint': {
      'line-color': '#888',
      'line-width': 8
    }
  });


  map.addSource('pointOnLine', {
    'type': 'geojson',
    'data': pointFeature
  });
  pointSource = map.getSource('pointOnLine');
  
  map.addLayer({
    'id': 'pointOnLine',
    'source': 'pointOnLine',
    'type': 'circle',
    'paint': {
      'circle-radius': 10,
      'circle-color': "red",
      'circle-opacity': 0.7,
    }
  });
  
  map.on('mousemove', e => {
  
    const start = routeSource.data.geometry.coordinates[0];
    const nearest = turf.nearestPointOnLine(routeSource.data, 
    	[e.lngLat.lng, e.lngLat.lat], { units: 'kilometers' });
  //  console.log(nearest);
  
    pointSource.setData(nearest);
  });

});
```

動くサンプルということでだらだらと長いコードになってしまったけれど、重要なのは ``map.on('mousemove', e => {`` のマウスカーソルが移動した時のハンドラです。

``nearestPointOnLine(lineStringFeature, [lng, lat], { units: 'kilometers' })`` という感じで呼び出します。
返値が 『``lineStringFeature`` 上にある ``[lng, lat]`` から最も近い点』です。

あとはこれを MapBox GL JS を使って描画しています。

## 参考

- [Turf.js | Advanced geospatial analysis](http://turfjs.org/docs/#nearestPointOnLine)
Raspberry Pi 4 で Google Domains に DDNS する

# はじめに

なんとなく取得していたドメインがあった（ [お名前.com](https://www.onamae.com) で持っていたが、ほぼ未使用）
この度これまたなんとなく [Google Domains](https://domains.google.com) にドメイン移管した

移管してから気付いたんだけど、Google Domains は自分のドメインで DDNS が使えるようなので試してみる
あと `ddclient` というのが Google Domains DDNS の自動更新に対応しているっぽい

やることは以下の 2つ 

1. Google Domains の保有ドメインに DDNS 設定の追加
2. 対応させたいサーバ側でIPアドレスが自動更新されるように設定

今回のサーバは Raspberry Pi 4 で、環境は以下

```
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:        10
Codename:       buster
```

# Google Domains で DDNS 設定の追加

左ペインで `DNS` を選択し、`合成レコード` で `ダイナミックDNS` を選択し、サブドメイン名を入力して`追加`を押す
（`@` を指定するとルートドメイン）

|![google_domains_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87322/c0894b2a-1ad7-f1c1-aff3-0549464af56d.png)|
|:--|

自動更新したいDDNS名をクリックすると、詳細が表示されるので `認証情報を表示する` をクリックして`ユーザー名` と `パスワード` を控える
（今回は2個設定したので2個分を控えておいた）

|![google_domains_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87322/4de5ad33-61cc-5c9e-4ee1-cc0dbb9b6cb6.png)|
|:--|

# IPアドレスが自動更新されるように設定

## ddclient をインストール

インストールすると初期設定ウィザードが始まるが、設定は手動で行うので全部適当に空打ちEnterで進める

```
# apt install ddclient
```

## Google Domains 用の設定に変更

複数設定するときは、そのまま続けて書く

```
# vim /etc/ddclient.conf
```

```:/etc/ddclient.conf
# Configuration file for ddclient generated by debconf
#
# /etc/ddclient.conf

ssl=yes
protocol=googledomains
use=web
login=[ユーザー名1]
password='[パスワード1]'
[DDNS名1]

ssl=yes
protocol=googledomains
use=web
login=[ユーザー名2]
password='[パスワード2]'
[DDNS名2]
```

## 単発で実行して動作確認

単発で実行する

```
# ddclient -daemon=0 -verbose
```

分かりづらいけど、更新できた場合は

```
INFO:     setting IP address to 14.3.62.29 for mtkhs.com
```

既に更新されていた場合は

```
SUCCESS:  mtkhs.com: skipped: IP address was already set to 14.3.62.29.
```

いずれにしても最後に

```
RECEIVE:  good 14.3.62.29
```

と出たら成功していると思われる

## デーモン化の設定変更

```
# vim /etc/default/ddclient
```

`run_ipup` を `false`
`run_daemon` を `true`
に変更する

```:/etc/default/ddclient
# Configuration for ddclient scripts-
# generated from debconf on Sun 29 Nov 2020 10:50:23 PM JST
#
# /etc/default/ddclient

# Set to "true" if ddclient should be run every time DHCP client ('dhclient'
# from package isc-dhcp-client) updates the systems IP address.
run_dhclient="false"

# Set to "true" if ddclient should be run every time a new ppp connection is-
# established. This might be useful, if you are using dial-on-demand.
run_ipup="false"

# Set to "true" if ddclient should run in daemon mode
# If this is changed to true, run_ipup and run_dhclient must be set to false.
run_daemon="true"

# Set the time interval between the updates of the dynamic DNS name in seconds.
# This option only takes effect if the ddclient runs in daemon mode.
daemon_interval="300"
```

サービス再起動

```
# systemctl restart ddclient.service
```

# おわりに

たぶん10年以上、自宅とかVPSで使うDDNS名は [ieServer.Net](https://www.ieserver.net) を利用して、curl とか wget で自動更新して使用していた。

んだけど、最近のLinuxディストリビューションの openssl ライブラリでは ieserver.net に繋げられない。
（2020年11月29日 時点）
原因は ieserver.net 側が SSLv3 を利用しているから。
最近の openssl ではセキュリティ上の問題で SSLv3 は切り捨てられているので対話不可。
一応 Docker とかで古いバージョンのDebian（ jessie くらい ）なんかを走らせれば SSLv3 が利用できる。
ランレベルのことを今更調べてみた

## 勉強前イメージ

シングルユーザモードでの起動とか、GUIの起動とか表すやつ
よく見るけど、正直あんま理解してない

## 調査

### ランレベルとは？

linuxの動作モードのこと。
0から6までモードがあって、ランレベル毎にどのサービスが起動する・しないを決定しています
`/etc/rc.d/rc*.d` にあるファイルによって、各ランレベルで起動するプログラムを指定しています。

- Redhat,CentOS等

systemd target に記載した内容が結構わかりやすいのではないかなと思います。

| ランレベル | systemd target | 内容 |
|:-:|:-:|:-:|
| 0  | runlevel0.target, poweroff.target | 停止  |
| 1  | runlevel1.target, rescue.target | シングルユーザーモード、ネットワーク無し。rootでのログインが出来ないときに使用します |
| 2  | runlevel2.target, multi-user.target | マルチユーザーモード（NFSマウントなし）  |
| 3  | runlevel3.target, multi-user.target | マルチユーザーモード（コンソール）、ネットワーク有り。通常の操作で使用されます。  |
| 4  | runlevel4.target, multi-user.target | 未使用  |
| 5  | runlevel5.target, graphical.target | マルチユーザーモード（X Windows）、ネットワーク有り。GUIでのログインの際に使用されます。  |
| 6  | runlevel6.target, reboot.target | システム再起動  |

### 実際にランレベルを見てみよう

- runlevelコマンド

現在のランレベルがわかります。
`1つ前のランレベル 現在のランレベル` という順で表示されます。
1つ前のランレベルが `N` : システム起動後に一度も変更されてないときに使われる
現在のランレベルが `3` : 上記の表でいうと、ネットワークが接続されておりコンソールでのログインの際に表示されるランレベル ということがわかります。

```
[root@localhost ~]# runlevel
N 3
```

- systemctlコマンド

こちらでも、同じように現在のランレベルが見れます。
multi-user.target なので、ランレベル3で確認出来ました

```
[root@localhost ~]# systemctl get-default
multi-user.target
```

- chkconfigコマンド

httpdとか起動してるのに見えないな...
実はsystemdの配下にしたみたいです。

```
[root@localhost ~]# chkconfig --list

注記: この出力に含まれるのは SysV サービスのみです。ネイティブな 
      systemd サービスは含まれません。SysV の設定データはネイティブな
        systemd 設定で上書きされる場合があります。
      systemd サービスを一覧表示する場合は 'systemctl list-unit-files' を使用します。
      特定のターゲットで有効になっているサービスを確認する場合は
      'systemctl list-dependencies [target]'を使用します。

netconsole      0:off   1:off   2:off   3:off   4:off   5:off   6:off
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off
```

- systemctl list-unit-files コマンド

ここには `httpd` とか含まれてた。
めっちゃ出てくる

```
[root@localhost ~]# systemctl list-unit-files
UNIT FILE                                     STATE   
proc-sys-fs-binfmt_misc.automount             static  
dev-hugepages.mount                           static  
dev-mqueue.mount                              static  
proc-sys-fs-binfmt_misc.mount                 static  
sys-fs-fuse-connections.mount                 stati
....

[root@localhost ~]# systemctl list-unit-files | grep httpd
httpd.service                                 disabled
```

## 勉強後イメージ

実際にちゃんと気にしたことはなかったかも。。。
シングルユーザーモードで入ったりはしたことあったけど。。
3と5ってコマンドかGUIって感じだけど、2と3って難しいよね。


## 参考

- [ランレベルとは（chkconfig）](https://webkaru.net/linux/run-level/)
- [CentOS 7.0 では systemctl を使う。](https://tacohachi.hatenadiary.org/entry/20150904/p2)
- [Linux - run level / shutdown](https://www.infraeye.com/study/linuxz3.html)
- [SYSTEMDによるサーバ管理](https://mizuti69.github.io/book_configure_centos8/2.configure/2.configure_systemctl.html)
- [CentOS 7 ランレベルの変更方法](https://www.server-memo.net/centos-settings/centos7/change-runlevel.html)
- [CentOS 7で起動ランレベルを変更する方法](http://www.lesstep.jp/step_on_board/centos-7/1184/)
progateやってみました

# 再開する
- ほったらかしていたQiitaに改めて記事を書く
- ITのお勉強内容を記録するならやっぱりQiitaだと思う
- 同じように困ってる人、迷ってる人の助けになればいいと思う

# 再開のきっかけ
- 転職活動でもっとも希望していたところの最終面接で落ちた事
- そのせいで家族をはじめ、周囲に迷惑をかけてしまった事
- 今のスキルではジリ貧なので新しい何かを加えたいと思った事
- [健太さん](https://qiita.com/poly_soft)の本を買って、サーバーサイドエンジニアに興味をもった事

# progateやってみて
- HTML/CSSコースをやってみた
- さすがは初歩っと言うこと、まだチャプター7程度なので自分にとっては簡単
- HTML/CSSの内容が簡単な構文で実装出来るって、やはりWIKIは凄い！
標準型攻撃メール

#1、目的
あくまで個人的見解ですが、テレワーク含めセキュリティ対策で二段階認証を使ったSMSでのパスワード確認はプライベートでも業務上でも利用する機会が増えてきたきがします。
SMSのスパムメールでよく聞くのが宅配便の不在連絡を装ったものをたまに見かけますが、これに近い形でSMSを利用した二段階認証時などのカスタマーサポートを装った標準型攻撃メールは今後出てくるかもしれないなとなんとなく思ったので標準型攻撃メールの対策について改めて調べて記事にまとめようと思いました。

#2、標準型攻撃メールとは
特定のターゲットに絞ってメールなどでサイバー攻撃を仕掛ける「標的型攻撃」。その多くがメールを利用して行われるため「標的型メール攻撃」と呼ばれたりしてます。
取引先を偽装したメールなどが主な例で挙げられています。

#3、対策
・OS、ソフトウェアを最新のバージョンにしておく
・セキュリティ対策ソフトを導入する
・標準型攻撃を疑似体験する
その他
・メールの見分け方を社内共有する
・万一に感染した場合のマニュアルを周知する
などがあると思います。

#4、まとめ
結局はヒューマンエラーで起きてしまう事故だと思うので日ごろから普段と違う、違和感があるメールはないか注意して慎重に扱う必要があるということになります。
もし、スマートフォンなどを活用した業務体制が発展してくるのであればスマートフォン用のセキュリティマニュアル。対策なども用意する必要が出てくるのかもしれません。
webサイトが見えるまでの仕組みを初心者がざっくり解説してみた



webサイトで何か見るときにはサーバーと通信していますこちら側何か要求することをHTTPリクエストそしてサーバー側から帰ってくる応答をHTTPレスポンスといいます。
![グループ 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660417/cd01f27e-1040-72dc-ce87-0d9882ceb97f.png)
しかしこのままではどこにリクエストを送ればいいのかわかりませんまた何か送るには住所のようなものが必要ですコンピュータの住所に当たるのがIPアドレスというものですIPアドレスは0~255までの数字が4つ区切りで合わさった形をしています(111.217.161.35)各サーバーにはipアドレスが割り当てられていて重複することはありません試しにgoogle.comのIPアドレスである172.217.25.206をアドレスバーに入れるとgoogleのサイトに行くことができます。
しかしながら、ipアドレスは数字の羅列でありコンピュータには理解しやすいですが、私たちにはあまり理解しやすいとは言えませんそこでドメインというものがありますドメインというのはyahoo.co.jpやgoogle.comやpornhub.jpなどipアドレスに比べると人間の理解しやすい形となっています。ipアドレスとドメインは一対一で対応しています。このドメインとipアドレスを対応させる(名前解決する)のがDNSサーバーです。また、yahoo.co.jpなどのドメインでは直接リクエストを送ることができません。サーバーにリクエストを送る前にDNSサーバーに対応するIPアドレスを聞き出してからサーバーにリクエストを送るのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660417/05c6249a-7ab5-6a1c-64ee-f8a45365c2fc.png)
![グループ 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660417/9b853d63-aa08-6bb6-667e-e23d518bfd61.png)
##まとめ
リンクを押してからページが見えるまでの過程をおさらいしてみましょう
yahoo.co.jpとアドレスバーに入力したとき
①yahoo.co.jpに対応するIPアドレスをDNSサーバーから聞き出す
②IPアドレスが分かったら、それをもとにWEBサーバーにリクエストを送る
③それを受け取ったサーバーはレスポンスとしてHTMLファイルやCSSファイルjavascript ファイルなどをレスポンスとして返す
④ファイルたちを受け取ったPCのブラウザが人間の解釈できるようにレンダリングする
データ管理の提案 -削除は必要なのか？ -

# 削除は必要なのか？

私はプログラムを組む時、Gitを使う。
家では[TimeMachine](https://ja.wikipedia.org/wiki/Time_Machine_(ソフトウェア))で1時間ごとにバックアップされている。
iCloudを介して、Mac, iPhone, Apple Watchで色々な物を共有している。

どの機器が何時壊れても、データが消える恐れが無い。
とても安心だし、要らない物は心置きなく捨てられて、スッキリする。

ユーザから見えなくする事は必要だが、システムとして「削除」する事は要らないのではないだろうか？

# 追記型ストレージの紹介

[Plan9](https://ja.wikipedia.org/wiki/Plan_9_from_Bell_Labs)のファイルサーバは WORM(Write Only Read Many)で、追記型光ディスクが主体だ。
HDDもメモリも単なるキャッシュとして動作する。
「追記型」と言う事は消えない。新しいファイルを古いファイルの手前に置いて、見えなくする方法を取っている。
新しいファイルを退ければ、古いファイルが見える、Docker Imageの様なレイヤ構造になっている。
Plan9は、計算サーバなど現在のクラウドの基本概念を作った分散OSだが、追記型ストレージはまだ一般的になっていない。
余談だが、Unicodeもこのプロジェクトから生まれている。

# システムには履歴データが必要ではないだろうか？

フォルダやファイル単位でのバックアップや、追記による履歴データの保存を見てきた。
さて、私たちが開発しているシステムではどうだろう？
相変わらずデータは上書きされている。
過去の経緯は消え去り、今現在が刻々と変更されているのではないだろうか？
一度起こった現象は二度と再現できず、ユーザーが「そんな事やっていない」と言うのをなんとかログから探してはいないだろうか？
ユーザのフルデータバックアップではなく、差分データバックアップが欲しいのではないだろうか？

# 追記型差分ストレージを作って見ないか？

現在の安価な大容量ストレージと、分散環境のノウハウを使えば、追記型で差分(履歴)を使ったストレージのサービスやフレームワークを作れる環境が整っていると思う。
もちろん、排他や整合性は考えなくてはならないので、簡単ではないと思う。
しかし可能性を追うのは楽しいし、壁にぶち当たらなくては限界もわからない。
一緒に壁にぶち合ったって見てもらえないだろうか？

# 自己組織化ストレージも欲しくないか？

発展型として、自己組織化ストレージも作ってみたい。
システムが自分で判断して、効率の良いデータの置き場所やサービスの構成を採ってくれる仕組みも可能ではないだろうか？
ここまで来て、やっとコンピュータの本来の力が発揮できるのではないか、と思っている。
【Spring Boot】CORSをアプリケーション全体で設定する時にEnvironmentインタフェースを使いたい

## 概要
[Spring MVC で CORS 設定](https://qiita.com/m_kikuchi/items/df8c070b228df44a5462)の記事で解説されている通り、Spring BootでCORSの設定をする際にはアノテーションを個別に設定する方法と、アプリケーション全体で設定する方法があります。個別のパスでCORSの設定をするケースは、個人的にはあまり多くないかなと思っていてまずは、アプリケーション全体で設定を選択すると思います。今回は、アプリケーション全体で設定する時の課題に関して書いてみます。

## 課題
上記の記事で紹介されている`WebMvcConfig`のclassを定義する方法では、Environmentインタフェースを使用できません。理由として考えられるのは`@Configuration`のアノテーションが付与されているclassは、`applicantion.properties`と同列の扱いとなり、このclass内ではEnvironmentインタフェースの設定が読み込めないと考えられます。[Spring Bootがプロパティファイルを読み込む方法に一同驚愕！！](http://blog.tagbangers.co.jp/2019/07/12/how-spring-deals-with-properties)の記事が参考になります。

## どうすれば良いのか
とはいえ、やはり環境毎にCORSの許可URLを変えたいので、どうすれば良いのかというのが[Spring Boot enabling CORS by application.properties](https://stackoverflow.com/questions/42874351/spring-boot-enabling-cors-by-application-properties)で紹介されています。いくつか方法はあるのですが、`SpringBootApplication`に直接`WebMvcConfig`の定義を書いてしまう方法が、シンプルで分かりやすいかなと感じました。ので、以下にサンプルの実装をのせておきます。

## サンプル実装

```SampleApplication.java

@SpringBootApplication
public class SampleApplication {

    @Autowired
    private Environment env;

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                String url = env.getProperty("allowed.url");
                registry.addMapping("/**")
                        .allowedOrigins(url)
                        .allowCredentials(true);
            }
        };
    }

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

}

```
【Python】Web上の画像やPDFをストレージにダウンロードせずに関数に渡す方法

# はじめに
Web上に公開された画像やPDFを利用したいシーンは多いですが、いちいちダウンロードして保存先のパスを参照してませんか？
ここではわざわざ保存せずにURLから直接データを取得して利用する方法を紹介します。

# 方法
結論から言います。

**BytesIOを使いましょう。**

`io`は標準ライブラリなのでインストールせずとも使えるはずです。

```python
from io import BytesIO
```

#使用例

使用例ですが、厚生労働省から新型コロナウイルスの陽性者数のPDFでも取得して`tabula`で表を抽出してみましょう。
（ちなみに`tabula`はPDFから表を抽出してくれる関数などを含むライブラリの名前です。インストールは`pip install tabula-py`でできます。）
まずは、データの取得から、
`requests`でも標準ライブラリの`urllib`でも構いませんが`requests`のほうが扱いが楽なのでそちらでいきます。

```python
from requests import get

url = 'https://www.mhlw.go.jp/content/10906000/000699602.pdf'
content = get(url).content
```

これで`content`にはPDFのデータがバイト列で格納されます。
バイト列をそのまま使用できる関数の場合は`BytesIO`を使うまでも有りませんが、大抵のファイルを扱う関数はPC上のパスを引数に取りますよね。
`BytesIO`を使うことで
そのような関数にバイト列を渡すことができます。

```python
from tabula import read_pdf

pdf_data = BytesIO(content)
df = read_pdf(pdf_data, pages='1', multiple_tables=False)[0]
df
```
<details><summary>結果</summary><div>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501281/cda38d82-f75b-565d-0393-b05b805850b2.png)
</div></details>

抽出の精度はまずまずですがそれはさておき、正常にデータを渡せていますね。

画像でもやってみますか。

```python
import matplotlib.pyplot as plt

url = 'https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F501281%2F428a2cd3-9005-a88d-85fa-648fe37c9618.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=21e8bcf27cad307545ed42fe9dfeaf31'
img = plt.imread(BytesIO(get(url).content))
plt.imshow(img)
plt.show()
```

<details><summary>結果</summary><div>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501281/04afc995-6244-93c6-79a3-2ffa1203def1.png)
</div></details>

OK

# さいごに
受ける側の関数との相性によっては必ずしも万能ではないかもしれませんが、使用機会は多いと思いますので覚えておくと捗るかも。
社内向けクイズアプリを作ってみる Vol.1  #PowerApps #decode夏まつり

# 初めに・・・

以前、de:code 夏まつりにて、クイズアプリを作って多くの反響をいただきました。

詳しくは、 @chomado さんのこちらの記事をご確認ください。
 [Microsoft Tech クイズ大会の問題と解説 + オンライン クイズアプリ開発アーキテクチャ #decode夏まつり #Azure #PowerPlatform](https://qiita.com/chomado/items/7755a57aa70937f9eb6d)

この中では、クイズの配信用アプリとデータベースを担当させてもらい、回答者側には [@dz_](https://twitter.com/dz_)さんにWebクライアントを作ってもらいました。
→ソースコード [Github:dzeyelid/decode20-azure-quiz-client](https://github.com/dzeyelid/decode20-azure-quiz-client/)

ただ、社内限定であれば、Power Apps 単体で構築可能であることに気づきましたので、2020年の締めくくりとして、
Advent Calendar かねてまとめようと思い立ったのです。

# このアプリを使用するにあたり必要となるライセンス

このアプリを作成及び利用するユーザー全員に、以下のいずれかのライセンスが必要となります
* Power Apps per apps user license 
* Power Apps per user license

# 構成図の変更

## de:code 夏まつり版システム構成図

de:code 夏まつりでのシステム構成はこのような形となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/cbf9ceef-8850-4a1c-9f50-121190386fe0.png)

## 社内向けクイズアプリ版システム構成図

それに対し、社内向けクイズアプリでのシステム構成はこのような形となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/1dcf4521-22a5-13e1-3b7d-c4dca118852f.png)
※エンティティ表記になっていますが、Microsoft Dataverse よりテーブルに名称変更されています。

このように、テーブル構造はそのまま利用できますが、これまで Logic Apps や Power Automate で処理していた部分を、参加者用アプリのPower Apps に代替処理させる必要があります。

# 次回から・・・

今回はとっかかりと概略について簡単に説明する記事となりましたが、次回はデータを格納するテーブルを作っていきます。
shellの引数で処理を分ける方法

業務で覚えた知識を備忘録として記載していきます。

#対象者
- shellに興味のある人
- 実行時の引数で処理を分けたい場合

先日業務でshellを書くことがあったのですが、調べてみると中々自分がやりたい内容が見つからなかったので、そんな人の一助になればと思ったのと単純に覚えた内容を忘れないために記事にしたいと思いました。

#やりたいこと
+ shell実行時の引数で処理を分ける
+ 外部ファイルを読み込み情報を取得する
+ 取得した情報を変数として持ち活用する

#使用コマンド if / while read LINE / AWK
```ts
if [ 条件 ] then [ 実行処理 ] fi
```
```ts
while read LINE (変数名)
do
  実行されるコマンド
done < [ ファイル名 ]
```
```ts
awk [ オプション ]  [ コマンド ]
```


#環境
Linux

#ディレクトリ構成
シンプルに実行するshellと読み取るファイルが同じ階層のケース。
shellを実行するとlist.csvを読み取り、引数に対応した値を取得する。
階層が複雑な場合はフルパス指定したり、プロパティファイルを作ったり変数にしたりして可読性とメンテナンス性を上げる。
下記はサンプルなので.confファイルも中身2行で用意。

```
home/
  ├ country.sh
  └ list.conf
```

# ファイルの中身
```list.conf
JPN,日本,東京,3
USA,アメリカ合衆国,ワシントンDC,1
CHN,中華人民共和国,北京,2
DEU,ドイツ連邦共和国,ベルリン,4
IND,インド,ニューデリー,5
・・・
```

# shellの中身
```country.sh
#!/bin/bush
#シェル名:country.sh
#処理概要:引数に与えた国の和名と首都、GDP何位かを表示します。
#引数:$1 国コード(アルファベット3桁)

#設定ファイル
CONF_FILE="/home/list.conf"

#1.開始メッセージ
echo "処理を開始します。"

#2.パラメータチェック
if [ $# -ne 1 ]
then
 #パラメータ数不正
 $echo "引数の国コードは1つ(3文字)にしてください。"
exit
fi
PARAM_IF_ID=$1

#3.定義ファイル取得
while read LINE
do
TOP_STR=`echo ${LINE:0:1}`
if [ ${TOP_STR} == "#" ]
  then
  # コメント行
  countinue
fi

#引数取得
IF_ID=`echo ${LINE} | awk -F, '{print $1}'`
  #引数判定
  if [ "${IF_ID}" = "${PARAM_IF_ID}" ]
    then
    #国名(和名)
    NAME=`echo ${LINE} | awk -F, '{print $2}'`
    #首都
    CAP=`echo ${LINE} | awk -F, '{print $3}'`
    #国内総生産ランキング
    GDP=`echo ${LINE} | awk -F, '{print $4}'`
    break
fi
done < ${CONF_FILE}

echo "選択した"${NAME}"の首都は"${CAP}"です。近年のGDPは世界"${GDP}"位でした。"
exit

```
shell実行引数をキーにlist.confファイルから情報を抽出する。
処理を実行するとメッセージが表示され、引数が1つ以外の場合はエラーを発して終了します。
決められた引数を受け取ると、list.confの2カラム目、3カラム目の値を$2/$3...に受け取っていく。
あとは内部の処理で受け取った引数を使うだけ。



# 引数が"JPN"の実行結果
```ts
$ bash country.sh JPN
処理を開始します。
選択した日本の首都は東京です。近年のGDPは世界3位でした。
```
# 引数が"USA"の実行結果
```ts
$ bash country.sh USA
処理を開始します。
選択したアメリカの首都はワシントンDCです。近年のGDPは世界1位でした。
```

# 引数なしの場合
```ts
$ bash country.sh
処理を開始します。
引数の国コードは1つ(3文字)にしてください
```

#解説という名の復習
引数をキーに.confファイルの中身を抽出する方法でした。
ポイントはwhile read LINEと awk を｜を使って繋げた所です。
.confファイルの中身を一行ずつ取り出して変数に格納していて,(カンマ)区切りで記入されたファイルの中身を読み取っています。
この処理があるので.confファイル内に複数のパターンの定義が存在していても、引数をキーに使い分けることが出来ます。
今はA/Bパターンだけでも、今後C/D/E...と増えた際に.confファイルのみメンテすればshellの処理を変えずに対応が可能となりメンテナンス性が向上します。
typescript拡張関数


## 概要
typescriptは良い言語ですがゴリゴリコードを書いていると、なんか物足りなくなってしまいます。
配列が空の場合に`Array.lenght === 0`や配列の重複要素を削除するのに`Array.from(new Set([1,1,2,3]))`など...

その際によく使いそうな処理をlibやutilityに切り出して使うのも良いのですが、typescriptには拡張関数という機能があるのでそれを使ってそれらを表現してみました。

## 設定方法
以下のような定義をして、使用したい場所でimportするだけ

```test.extensions.ts
export {};

declare global {
  interface Array<T> {
    isEmpty(): boolean;
  }
}

Array.prototype.isEmpty = function () {
  return this.length === 0;
};
```

```index.ts
import 'extensions/test.extensions.ts';

[].isEmpty()
```
## 使用例

- 配列が空の場合

```*.extensions.ts
Array.prototype.empty = function () {
  return this.length === 0;
};
```

```*.ts
// before
[].lenght === 0
// after
[].isEmpty()
```

- 配列の要素の重複を禁止

```*.extensions.ts
Array.prototype.distinct = function () {
  return Array.from(new Set(this));
};
```

```*.ts
// before
Array.from(new Set([1,1,2,3])) // [1,2,3]
// after
[1,1,2,3].distinct() // [1,2,3]
```

- 配列の初めの要素を取得

```*.extensions.ts
Array.prototype.front = function () {
  return this.length === 0 ? undefined : this[0];
};
```

```*.ts
// before
[1,1,2,3][0]// 1
// after
[1,1,2,3].front() // 1
```

## 最後に

よく使う汎用的な処理を拡張関数として定義しておけば、vscodeなどで候補として表示されるので、割と便利でした。


続きまして、アルサーガパートナーズ Advent Calendar 2020 2日目の記事は @miumi さんの「エンジニア転職に必要な資金を調べてみた」です :tada:
そもそもwebアプリケーションって何？           

**webアプリケーション**
---
web上で利用できる、ある目的を持った**サービス**のことです。

ある目的とは、例えば「音楽を聞く」「商品を買う」などの行為を指します。

SpotifyやAmazon、
webアプリケーションがないと私たちはもう生きていけないんじゃないでしょうか？
　　　

**web**
---

インターネット上でさまざまな情報を公開・閲覧できる**仕組み**のことです。

さまざまな情報とは、「文字」「画像」「動画」などの要素のことを言います。






**アプリケーション**
---
コンピューター上で動く**プログラム**のことです。
[PHP]標準入力で与えられる値を取得する

#PHPで標準入力で与えられる値を取得する
```java:PHP
<?php
$input = fgets(STDIN);
echo $input;
?>
```
#Rubyの場合
```java:Ruby
input = gets
print input
```
###PHPはRubyと違いコード量が多くなる。 <?php  ?>タグで囲む事でPHPのコードとして認識される
#以上！
なんでGo？

書くことが思い浮かばず、「Qiitaだしポエムでもいいか」と開き直ったらこんな内容になってました。

# 「なぜGoを使うのか？」
3年ほど前、私は「新しい言語に触れてみたい」という単純な理由からGoを書き始めました。私の周りには優秀な人が多く、そういった人々がRustやHaskellといった言語にのめり込んでいく中で私は一人Goの沼へと足を踏み入れました。実際に書き始めてみると周囲から「なんでGo？」と聞かれる機会がそれなりにありました。そして私はその質問に満足な回答を持ち合わせていませんでした。

# Goは面白い言語ではない
Goについて話をする上で避けて通れない話題が仕様の小ささです。Goが採用している言語機能の数は非常に少ないです。このことはGoの[言語仕様](https://golang.org/ref/spec)がペライチのWebページに収まっていることからも明らかです。印刷してもA4 110ページに収まります。比較対象として[C++17のWorking Draft](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf)は1440ページにも渡ります。プログラミング言語の中でも特に複雑な部類に当てはまるC++と比較するのはフェアではないかもしれませんが、スケール感の違いはおわかりいただけるかと思います。

仕様が小さいが故にそれが「不十分である」例としてよく槍玉に挙げられるのは「比較的新しい静的型付き言語なのにジェネリクスがない」ことでしょうか。ジェネリクスがないので他の言語には当たり前に実装されているような `map` や `filter` のような機能は標準的に用意されていません。Goではそういった処理は全て `for` 文で行うことになります。重複する機能がほとんどないので仕様の適切な取捨選択による創意工夫をすることができず、学べることも少ないです。正直に言ってしまえばGoは「味のない、面白みのない言語」です。

人によってはそれだけでGoは学ぶに値しない言語として映るかもしれません。しかし、私はこの味気なさはむしろいいことだと捉えています。その理由は私がなぜGoを書くのかという問いに対する答えに直結しています。

# Simplicity is Complicated
「単純さは複雑だ」

これはGoの開発者の一人であるRob Pike氏の言葉で、dotGo 2015での同氏の発表のタイトルでもあります。私がGoを書き続ける理由を一言で表すとすればこの言葉を選ぶでしょう。Goに興味がある人やGoを書いている人でこの発表を見たことがないという方はぜひ一度見てみることを強くおすすめします。

> dotGo 2015 - Rob Pike - Simplicity is Complicated https://youtu.be/rFejpH_tAHM @YouTubeより 

Goの小さな仕様はしばしば「シンプル」と評されますが、それは他の現代的な言語と比較して「シンプル」なのであり必ずしもGoがシンプルさに特化しているわけではありません。仕様を究極的にシンプルにしたければそれこそ[Brainf*ck](https://ja.wikipedia.org/wiki/Brainfuck)のような言語になってしまいます。発表中にRob Pikeが言っているように、Goは「シンプル」なのではなく、「シンプルに感じる」だけなのです。

なぜ「シンプルに感じる」のか。それは「書きやすさ」と「読みやすさ」のバランスを絶妙に取っているからです。直交する必要十分な仕様のみを採用しているので書くときにどの言語機能を使うかで迷うことはなく、見慣れない仕様を採用していないので読み方がわからないこともありません。Goを扱う時、書き手としても読み手としても脳にかかる認知的負荷が小さいと感じることが多いです。

Goはメモリ管理モデルもガベージコレクションという、ユーザにとっては非常にシンプルな（認知的負荷の小さい）手法を採用しています。その一方で、実用に耐えるレベルのガベージコレクションを実現するためにその実装は非常に複雑になっています。これもタイトルである「単純さは複雑である」ことの例として発表の中で取り上げられています。

こういった「シンプルに見える」言語デザインを追求した結果、Goは「書く」あるいは「読む」時に知らなくてはならないことが少なく、また考えることも少ないと言えます。それは一方で「書く面白さ」や「学ぶ面白さ」を削いでしまうという側面もありますが、逆に「書くことよりも、作ることに集中させてくれる」とも言えます。Goに「書く楽しさ」ではなく「作る楽しさ」を見出した時、私はGoという言語の真価を自分の内に発見しました。

# 書くことと作ること
そうは言っても「書くことが楽しく」かつ「作ることが楽しい」と思える言語が一番であることは間違いありません。ですが、「書くことが楽しい言語」を駆使して「作ることが楽しい」という領域に至るのはとても大変です。私は今からC++の規格書に目を通して「正しい」C++を書けるようになる労力を割きたいとは思えません。それなら勉強に必要な時間を使ってGoでなにかを作っていたほうが楽しい、というのが私の考えです。そういう意味でもGoの「一度ある機能を覚えたらそれさえ使えればいい」という割り切り方に非常にシンパシーを感じています。

私は昔から制限のある環境下で創作する時に最も創造力が働く傾向があり、そういった側面からもGo言語ととても性格的にマッチしているというのもあるのだとは思います。少ない言語機能セットの中でいかに創造的にソフトウェアを作り上げるか。明瞭でわかりやすく読みやすく使いやすいソフトウェアを作るためにどうしたらいいか。複雑な言語に関する細かな仕様をちまちまと勉強するよりも、単純な言語でどんどんモノを作っている方が性に合っていました。

# 最後に
こういった「モノづくり」的なプログラミングへのアプローチを持っている方にはぜひGo言語をおすすめしたいです。これからGoに触れてみようと思っている方や、なんとなくGoを敬遠していたけど興味がないわけではないという方にこの記事を通じて「そういう捉え方もあるのか」と思っていただけたのなら幸いです。
古の技術TOCを使って業務改善をしよう

[ちゅらデータアドベントカレンダー](https://qiita.com/advent-calendar/2020/churadata)の3日目はたまーに社内で話をするTOCの話を少ししようかなと。

# TOC知ってますか？

TOC知ってますか？
最近の人は知らない人が多いかもな。
すこし年いってる人は「あー、TheGoalっすよね？」って言ったり、一部の大きな会社だとほぼ必修みたいな感じになってるから、知ってたりするだろうか？

今日はそんな古の技術TOCを使って開発チームの業務改善をする話。

# 開発チームの目的はなんですか？

開発チームの目的は、**新しい開発成果物を顧客に届けること**。

違う？

…

違うわけ無いですよ！

…

そうですよね？

そう、**リリース**ですよ。

たぶん動くからリリースしようぜ！のあれです。

単位時間あたりどれだけのリリースができるか。
それが開発チームのKPIですよね？

# リリースを妨げるもの

それはレビューです。

…

おい、そこ、物を投げてくるな！

だって、レビュー待ちとかありません？レビューがあと1時間早ければ、リリースも1時間早くできません？

え、そうですよね？

…

そうですよ。

めっちゃくちゃ端折って言うとTOCというのはこういう全体のスループットを下げる部分を**ボトルネック**って呼んで、そこを改善して全体のスループットをあげようという話です。

TheGoalという本だとボトルネックを**制約**と呼んで、それを制約理論(Theory of Constraints=TOC)と言うわけです。

# よくあるリリースを妨げるやつら

（ここから啓発本のノリ） 
業務改善するなら、最初にボトルネックを探そう。
たぶんたくさんWIPやPBIが溜まってるところが怪しい。
とはいえチームによって違うから、後で上げる例にばかり気を取られてはダメだ。
ボトルネックは予期しないところにあることも多い。

**リリースを1秒でも早くできる何かを見つけたらそれはボトルネックかもしれない。**
まぁ、だいたいボトルネックだ。
**逆に「でも、これ早くしても、リリース早くならないよな？」っていうのはボトルネックじゃない。**
頑張って見分けよう。

たとえば下記のようなところでボトルネックをよく見かける。

- 自動化されてないテスト … 毎回リリースするために人手でテストしてる。新機能のリリースは手動テスト待ち。
- 安全じゃないデプロイ … デプロイ怖いからいくつかの新機能をためてデプロイしよう。
- レビューする人がぜんぜんレビューしてくれない … リーダーは忙しい。レビュー対象のPRがどんどん溜まる。
- この機能はあの人しか作れない … キーマンはいつも忙しい。作りたい機能のPBIはどんどん溜まる。

対策は簡単だけど、難しい。
開発チームは業務改善をするために覚悟を決めて進まないといけない。
かっこいいな。

## 自動化されていないテスト

テストコード書け、今すぐ。
自動テスト組め、今すぐ。

## 安全じゃないデプロイ

誰でも気軽にデプロイしたり、戻したりできるようにしろ、今すぐ。

## レビューする人がぜんぜんレビューしてくれない

これは色々やり方がある。
たとえばペアプロして、レビュー不要にしよう。
というかほんとにリーダーがレビューする必要あるのか？
レビューのために時間をさくんだ。レビューアーはレビューが本業だ。

いっそ、ビズサイドも巻き込んでモブワークしてWIP1のチームにしたら、ボトルネックはなくなるんじゃないか？

## この機能はあの人しか作れない

トラックNo.1だこれ。ほっとくと別の意味でも不健全。
ナレッジトランスファーしよう。

# そうして、開発チームは

ボトルネックを解消したり、逆にボトルネックを中心に業務を回すようになると、とてもリリースサイクルが上がる。
ハッピーだ。

とはいえ当たり前過ぎて、TOCを知らなくても、上記のような業務改善はできるかもしれない。

# 別のチームでは

さて、ではTOCを知らないチームの業務改善を見てみよう。

- テストは手でやるから大変なので、いくつかの機能をまとめてテストしよう！（よし！効率がいい！）
- ついでにデプロイもまとめてやったほうが効率が良いからそうしよう！（よし！効率がいい！）
- リーダーの承認がもらえるまでPRのマージは禁止だ！（よし！品質担保だ！）
- これ関係の機能は、あの人しか作れないから、月に3個までしかPBIを受け付けない！（なんだこれは？でもたまに見る）

うん、いまいちだな。
でも現実にはたまに見かける意思決定だ。
きっといろいろ事情があるのだろう。

# ボトルネック以外の改善について

さて、ここで、悲しいお知らせ。

…

**「ボトルネック以外の改善は無意味」**

…

なぜなら改善してもリリース数が増えないからです。
さっき、業務改善をするなら、「最初にボトルネックを探そう」と言ったのはこれが理由。

たとえば部長の承認を待たなきゃいけないチームがいくらたくさんの機能を短時間に作れるようになったって、一日に部長が承認できる機能が1つまでだったら、それ以上多くの機能をリリースすることはできないだろ？
現実は無情だ。


だから、**ボトルネックを探す。その後ボトルネックをどうにかする。**
こういうムーブが正解で、改善対象がボトルネックじゃなかったら、意味があんまりない。

え？ボトルネックをどうにもできない？

…

よかったじゃないか、君のチームはこれ以上パフォーマンスを上げる必要がないところまで、改善しきっているんだ！
はりきって前向きな気持で次の職場を探そう！


さて、業務改善をバシバシやっていくと作業工程感の同期タイミングがシビアになって、チームにプレッシャーが漂うかもしれない。（はやくレビューしろよ！PR出したらすぐ連絡くれよ！などなど）
開発チームは工場の機械じゃないから、グルーミングは大事だとは私も思う。（プログラマはみんな猫みたいなものだから）

最近の研究ではこういう業務改善よりは、本質的な心理的安全性の高い率直な意見の飛び交う開発チームにしたほうが生産性が高いことがわかってきてるから、あくまでTOCベースの業務改善はツールの一つでしか無いのだろう。


# さてCCPMを知っているか？

ちょっと上で書いた業務改善とは別なのだけど、TOCをベースにしたプロジェクトマネジメントの手法にCCPMというのがある。
これも工程間の同期についての知見や、プロジェクトバッファや合流バッファの採用、そしてボトルネックになるリソースに人を含めるアイデアなど、学ぶべきことが多い。
もしTOCに興味を持ったのなら、CCPMあたりから入門して、見るといいかもしれない。


# おわりに

今日の小話は。
もう終わりです。
TOCいいですよ。

ちゅらデータでは相変わらずクレイジーな仲間を募集しています。
こういうTOCの知識を持ってお客様の業務を分析して改善に取り組んだりしたいなって人いたらぜひお声がけください。
Railsでテーブルの値を、別テーブルの項目で並び替える方法

こんばんは
アロハな男、やすのりです！

今日は、Railsでモデルやテーブルを扱っていく上で1度は必ず通るであろう`sort_byメソッド`について書いていこうと思います。
ただ普通に配列を並び替えわけではなく、今回は`アソシエーションを組んでいる別テーブルの値`で並び替えをする方法になります！！

#結論
並び替える方法が2種類あります。

* `全く該当しない物は扱わない`

```ruby
モデル名.joins(:並び替えたい項目があるテーブル名).group(:まとめたい項目).order('count(並び替えたい項目)')
```

* `該当しないものも扱いたい`

```ruby
テーブル情報を入れた変数.sort_by { |x| x.並び替えたい項目があるテーブル名 }
```

となります。

#テーブル構造
例えば以下の様なテーブルがあった場合で考えます。

* experiencesテーブル(色んなお店やレジャー施設情報保存用)
* usersテーブル（登録していただいているユーザー様の情報保存用)
* favoritesテーブル(ユーザー様がお店等をお気に入りしたことを保存)

favoritesテーブルでは、他2つのidを外部キーとして持っています。
ユーザー様がお店やレジャー施設をお気に入り登録すると、

| id  | user_id | experience_id | 
| --- | ------- | ------------- | 
| 1   | 1       | 1             |
| 2   | 1       | 3             | 
| 3   | 2       | 1             | 
| 4   | 3       | 2             | 
| 5   | 2       | 2             |

こんな具合にテーブルに値が保存されていきます。

#なぜ2種類？
それでは、なぜ方法が2種類あるのかを見ていきたいと思います。

まず`全く該当しない物は扱わない`場合ですが、
こちらの重要部分は`joinsメソッド`です。

詳しいことは↓こちらを見ていただく方がよりわかりやすいかと思います。
<a href='https://pikawaka.com/rails/joins'>【Rails】joinsメソッドのテーブル結合からネストまでの解説書</a>

簡単に説明すると、例えば

```ruby
Experience.joins(:favorites)
```
とすると、`experiencesテーブルとfavoritesテーブルの両方共に存在しているレコード情報`しか検索できなくなってしまいます。

つまり、**お気に入り登録をまだされていないお店・レジャー施設は検索対象から外す。**ということになります。
検索対象から外さない場合の物は後述します。

続いて、

```ruby
Experience.joins(:favorites).group(:experience_id).order('count(user_id) DESC')
```
と、記述することによりお気に入りされている数が多い順でお店等を取得することができます。

`groupメソッド`でexperience_idを指定することにより、**複数お気に入り登録されているお店等を1つのレコードにまとめる**ことができます。

そして`orderメソッド`で並び替えをするんですが、メソッド内で`count(user_id)`とすることによって**お店等がお気に入り登録されている数**で並び替えることができます。

ただこの方法ですと、お気に入り登録されている場所だけをピックアップして、そこから人気店を探す！！とかなら使用できるメソッドですが、**お店等を全て一覧で表示したいから除外されてしまうのは...**という場合もあると思います。

**『それなら`joinsメソッド`を抜いてコードを書けばいいじゃん！！』**

となりそうなんですが、その後の`groupメソッド`ではexperience_idを、`countメソッド`ではuser_idを使用しています。
この2つのidは`favoritesテーブル`が持っているテーブルですので、Experienceモデルだけでは使用できません...

その場合には、もう1種類の方法です。

#全て取得する方法
`該当しないものも扱いたい`場合ですが、こちらは先ほどまで説明していた方法とは少し違います。
具体的には`モデルではなくテーブルに対して並び替えをする`ということです。

1度変数等にレコード情報を格納してしまいます(今回は`@experiences`とします。)

そして変数に対して`sort_byメソッド`を使用します。

```ruby
@experiences.sort_by! { |exp| exp.favorites.length }.reverse!
```

と記述することで、**全件のお店等を対象にお気に入り数が多い順**で並び替えることができます。

`sort_byメソッド`を使用することで変数(配列)の並び替えをでき、`{}`内でその値を1つずつ取り出して評価していきます。

`experiencesテーブル`と`favoritesテーブル`はアソシエーションを組んでますので、

```ruby
exp.favorites.length
```
と記述することで、**1つずつ取り出してきたお店のお気に入り数**を評価して並び替えをしてくれます。
ただこのままだと昇順での並び替えになってしまいますので、最後に`reverseメソッド`で結果を反転させています。

#最後に
最初は全部モデルに対してだけで並び替えができると思い込んでいたので、すごく時間がかかってしまいました...

いや、もしかしたらこれ以外にもっといい方法があるかも...？

ご指摘・アドバイスはどんどんいただきたいと思っていますので、コメントお待ちしています！！
初学者向け Go言語(Golang)の変数宣言＊数値型

# はじめに
メモ書きです。
初歩中の初歩ですのでGoを始めたての方の助力になればと思います。

## 変数宣言1

#### 整数型
整数型のnumを宣言します。
変数は以下のように宣言します。

```
var [変数名][データ型]
```

整数型は"int"を型に用います。

```Go
package main

import (
	"fmt"
)

func main() {
	var num int
	num = 1

	fmt.Println(num)
}
```
実行結果

```
PS C:\pg\Go\study> go run sample.go
1
```

int型でデータのサイズを決めることができます。
サイズを指定しなかった場合はOSやCPUに依存した数値となります。

```
int8　　//8bit  min~max -128～127
int16  //16bit  min~max -32768～32767
int32  //32bit  min~max -2147483648～2147483647
int64  //64bit  min~max -9223372036854775808～9223372036854775807
```

#### 小数型
小数型のnumを宣言します。
小数型は"float32 or float64"を型に用います。

```Go
package main

import (
	"fmt"
)

func main() {
	var num float32
	num = 1.234567

	fmt.Println(num)
}

```

実行結果

```
PS C:\pg\Go\study> go run sample.go
1.234567
```
float型のデータのサイズは以下のようになっています。

```
float32    //IEEE-754 32-bit 
float64    //IEEE-754 64-bit
```

## 変数宣言2
変数の宣言と初期化を同時に行う方法です。
よく使う（個人的な主観）ので覚えておきましょう。

```
[変数名] := 初期値
```
実際に書くとこんな感じです。

```Go
package main

import (
	"fmt"
)

func main() {
	num := 4

	fmt.Println(num)
}
```
お分かりだと思いますが出力は"4"です。

小数点型も同じです。

```Go
package main

import (
	"fmt"
)

func main() {
	num := 1.234

	fmt.Println(num)
}
```

出力は"1.234"です。

# 参考文献
golang.jp-Go言語の仕様-
http://golang.jp/go_spec