OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】Linux上でSharedMemoryが解放されない？

## 概要
Python3.8から導入された**multiprocessing**モジュールの**SharedMemory**によって共有メモリが使えるようになった。
しかし、Windows上では問題なかったが、Linux上でメモリが解放されていないような...。
SharedMemoryの公式HPは[こちら](https://docs.python.org/ja/3/library/multiprocessing.shared_memory.html)。

## エラー内容の例
プロセス１（proc1.py）で共有メモリ作成、及びデータを格納し、プロセス２（proc2.py）でプロセス１が格納したデータを取得。
まずはソースコードから。

```python:proc1.py
import pickle
import sys
from multiprocessing import shared_memory

# SharedMemory新規作成
try:
    shm = shared_memory.SharedMemory(create=True, size=30, name="test")
except:
    print("メモリ作成エラー")
    sys.exit(1)

# データ格納
while True:
    brother = {
        "1": "taro",
        "2": "jiro",
        "3": "saburo"
    }
    data = pickle.dumps(brother)
    shm.buf[:len(data)] = data
```

```python:proc2.py
"""
プロセス２での処理
"""

import pickle
import time
import sys
from multiprocessing import shared_memory
  
start = time.time()

while True:
  
    try:
        shm = shared_memory.SharedMemory(name="test")
    except:
        print("取得エラー")
        break
    else:
  
        try:
            data = pickle.loads(shm.buf)
        except pickle.UnpickingError:
            continue
        except:
            print("読み込みエラー")
            sys.exit(1)
        else:

            if time.time() - start > 5:

                shm.close()
                #shm.unlink()
                print("close")

                break
```

この例では、プロセス２が起動５秒後に処理終了。
その際、**shm.close()**でメモリを解放してよかったね！となるはずだが、
こんなUserWarningが出現。

```bash
UserWarning: resource_tracker: There appear to be 1 leaked shared_memory objects to clean up at shutdown
warnings.warn(‘resource_tracker: There appear to be %d ‘
```

**shm.close**でメモリ解放がされてないらしく、プロセス２をもう一度動かしてみると、メモリを取得不可（取得エラーと出力される）。

ついでに[公式](https://docs.python.org/ja/3/library/multiprocessing.shared_memory.html)にあったもう１つの**shm.unlink**も実行。
当然unlinkと言う名前の通りリンクを切るため、再度プロセス２を実行しても取得できるわけもなく。

また、これも当然の話ですがプロセス１を再起動したら、再び取得可能。

## まとめ
SharedMemoryの**close**がLinux上でうまく動いてなさそう。
共有メモリはまだPython＆Linuxではやらない方が良いかも。

## その他

GitHubに載せています。

https://github.com/khfkd/shared_memory
リファクタについて

# まえがき
最近、リファクタリングの重要性を再認識したので、自分用のメモとして残しておく。

# なぜリファクタが重要なのか
そもそも、最初の設計段階で完璧な設計ができていれば、リファクタは必要ない。
が、完璧な設計なんてそもそも不可能。
そのアプリケーションが将来メンテすることがないと保証されているなら、最初から完璧な設計ができるかもしれないが、
今の時代に一度作られたアプリケーションが進化しないなんてことは普通ない。
かつ、その分野の業務知識について完璧に知っている状態で実装を始められるなんてことはほぼありえないので、
ある程度理解した状態で設計を始める以上、完璧なものを求めること自体現実的じゃない。
まとめると、
- アプリケーションは進化していくもの
- 業務知識は徐々に理解できていくもの
なので、設計は絶えず改善していく必要がある。
そしてそのためには、リファクタリングが絶対に必要。

# リファクタリングをいつするか
よほどのレガシーコードでみんなが悪戦苦闘している場合を除いて、リファクタのために特別な工数を割けるなんてことはないと思われる。
（レガシーコードでもまとまった工数がもらえるとは限らないし
なので、改修の際にリファクタできる工数も確保するのが正しいと思う。
「立つ鳥跡を濁さず」で、改修する前よりもした後の方が綺麗なコードになることを目指す。
順番としては、先に必要なリファクタをしてしまって、後から改修するのがいい。
（もちろん、改修中も絶えずリファクタを繰り返していく。）
リファクタをせずに、立て付けの悪いところに更に改修を加えて、手に負えなくなったコードを見たことはある。

# リファクタリングとテストコード
テストコードがなくても平気な人とは上手くやっていく自信がない。
「レガシーコードとは、テストコードがないコードのことである」みたいな文言を、「[リファクタリング](https://www.amazon.co.jp/dp/B01IGW5MG0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)」で目にした記憶がある。（違ってたらごめんなさい）
テストコードの意義は、
- 素早く、かつ安全に、リファクタリングを行うことができる
- (クラス単位の)仕様書の代わり
だと思っていて、リファクタとテストコードは切っても切り離せない関係だと思う。
もし（十分にケースをカバーした）テストコードがなければ、自前でテストデータを用意して実際にテストしなければならない。
しかも、毎回、修正のたびにテストしないといけない。かつ、修正の影響範囲を調べ、
影響のある全てのテストケースについてテストしないといけない。
結果として、リファクタを気軽にできなくなってしまう。
もちろん、リファクタによってテストが壊れることもある。
これについてはだいぶ長い間頭を悩ませていて、以前はテストが壊れない実装ができてからテストコードを書いたほうがいいのかと
思っていたが、最近は、もっといい設計があると最初からわかっている場合でも、既存のコードに対してテストコードを実装するのを
優先したほうがいいという考えに変わってきた。
2番目の意義も重要だと思うが、本題から外れるので別の機会に回したい。

# リファクタリングの方向性
闇雲にコードをいじるだけでは、かえって悪い実装になる、というのは自分の失敗談。
当たり前だが、リファクタによってコードは改善されなければならない。
その時に、「良い実装とはなにか」についての知識（と、それを実現するためのリファクタのテクニック）が必要。
良い実装とは：
- 各クラスが必要最小限のインターフェースしか持っていないこと
- 各クラスのサイズが小さいこと
- 各クラスのインスタンス変数の数が少ないこと
- 各クラスのメソッドが細かく分割されていること
- 各クラスにsetterが存在しないこと
- 各クラスが必要最小限のgetterしか持っていないこと
結局、単一責任かつ粗結合なクラスということになるが、上記を意識すれば自然にそのようなクラスを実装できるのではと思う。
（単一責任とか、一つって言ってもどの粒度で区切るかによってどでかい業務単位でも一つと言えば一つだし）
あとは、ドメイン駆動的な知識、特にみんな軽視しがちな値オブジェクトを積極的に実装していくことが大事な気がする。

# リファクタリングの流れ
「リファクタリング」にあるように、細かいステップで修正・テスト・コミットを繰り返していく。
インターフェースが変わらないのであれば、内部の構造をどんなふうに変えようが外部には全く影響がない。
また、そのようにテストコードも実装しておくべき。
インターフェースが変わる場合、既存のインターフェースを残したまま、少しずつ新しいインターフェースに切り替えていく、というのも重要。
例えば、B#hogeの代わりに新しいメソッド(new_hoge)をインターフェースにしたい場合、
1. B#new_hogeを定義し、B#hoge内の処理をコピー。引数や内部のロジックを変更し、動作が変わらないようにB#hogeからB#new_hogeを呼ぶ形にする。
2. テストが全て（B#hogeのテスト、及びB#hogeを呼んでいる箇所に対するテスト）通ることを確認。
3. B#new_hogeのテストを実装。
4. B#hogeを呼んでいる箇所を一つずつB#new_hogeを呼ぶ形に切り替え、そのたびにテストが通ることを確認。
5. B#hogeを呼んでいる箇所がなくなった時点で削除。
同じような流れで、クラスの位置づけを安全に切り替えることも可能。

# 参考文献
- [リファクタリング 既存のコードを安全に改善する](https://www.amazon.co.jp/dp/B01IGW5MG0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
- [現場で役立つシステム設計の原則](https://www.amazon.co.jp/exec/obidos/ASIN/B073GSDBGT/hatena-blog-22/)
【Azure】VMコストについて突然聞かれて困ったときに使うやつ

# はじめに

いつも大変お世話になっております。

__急にVMのコストのことを聞かれて困ることありますよね？__
いきなりなんだ？って感じですけど、私はよくあります。

そりゃAzureのことは一般人よりわかっているほうですが、~~基本とはいえVMとか普段ほとんど使わないので~~記憶がおぼつかなくなっていることが多く、「ええっと…」ってなります。
そこで今回は、VMでよく聞かれるコストのことをここにまとめておくことにしました。

## コストはどれぐらいかかるの？

なんといっても一番聞かれるのはこれですよね。
ではまず料金計算ツールを開きましょう。

 https://azure.microsoft.com/ja-jp/pricing/calculator/

「製品」から「仮想マシン」を選択します。「保存されている見積もり」タブに移動すると、仮想マシンの見積もりが表示されます。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/837b54f9-9395-06db-36fe-9e85f6a272a5.png)|
|:--|

まぁここまでは聞いてきた人も来れているはずです。

## VMの価格を左右する勘どころ

### A.インスタンスシリーズ

当たり前ですが__インスタンスの種類は、パフォーマンスと価格に直結します！__

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/5635ab29-be59-00ea-11c8-5a295862a5ac.png)|
|:--|

カテゴリを開いてみましょう。開くとそれぞれのインスタンスの利用用途として推奨されているカテゴリが表示されます。
ここで、適切なものを選択するのが第一歩です。カテゴリに合致する用途のインスタンスのみ、インスタンス一覧に表示されるようになります。

しっかり要件が決まっているものであれば適切なインスタンスを選択すればよいですし、要件が全然固まっていないのであれば…ある程度想定より高いパフォーマンスを持てるインスタンスを選択することをお勧めします。

インスタンスについて、細かい情報は以下をご参照。

https://azure.microsoft.com/ja-jp/pricing/details/virtual-machines/series/

ここで言えるのは、__正確で安い見積もりを出したいならまず要件をしっかりまとめてください、ってことですね！！！(重要)__

### B.Reserved Virtual Machine Instances を検討する

1年、3年運用することが前提なのであれば、__Reserved Virtual Machine Instances__を必ず検討しましょう。
最大で72%程度の節約が可能です。
Reserved Virtual Machine Instances は解約費用を支払えば途中解約することもでき、絶対にインスタンスタイプが変更できないわけではありません。

__これも要件がしっかり決まっている場合に取り得る選択肢ですね!(重要)__
要件が決まっていない場合でも、要件が固まって運用開始すればこの程度のコスト削減が見込めますよ、と最初にアナウンスしておくだけでも、お客様は好意的な感情を持ってくれるかもしれません。

### C. Managed Disks

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/a350fcb5-44ed-0ee2-88e9-252c1bd99bc2.png)|
|:--|

VMにはManaged Diskという形でディスクボリュームを設定します。
レベルとして、「Standard HDD」「Standard SSD」「Premium SSD」の3つから選択することになります。

これもIOPSの要件がしっかり決まっているのであれば適切なディスクを選択してもらうだけなのです。
__しっかり決まっていない場合は…Standard SSD以上にしておくのが無難です!__
Standard HDDは、思ったよりパフォーマンスが出ません。ほんとに。検証や開発環境以外で利用するのは控えるのが無難です。

冗長性は、今のところ東日本リージョンではLRSのみ選択可能です。他のリージョンを利用する場合は、ZRSを選択することができます。
LRSとZRSについてはこちらをご参照。

https://qiita.com/hikaru_motomiya/items/18055deb63b5515b6a9b

ディスクサイズは、要件が決まっていれば利用したいディスクサイズを選択しましょう。
決まっていなければ…やはり大きめを指定するのが無難です。
スナップショットは必要に応じて設定します。

### D.その他

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/311af02a-63ed-d7fd-e1c3-a6c141af8d62.png)|
|:--|

#### ストレージトランザクション
ストレージトランザクションは、どれだけストレージに対してトランザクションが発生するか、を入れるのですが…これ実際に運用開始してみないと何とも言えないことが多いはず。
そんなにコストに影響する項目でもないので、__適当にオーバーに入れておくぐらいの認識でよいと思います。__

#### 帯域幅
Azureの場合、基本的にAzure⇒インターネットの送信量に応じて課金が発生します。
ここにこれを入れるのですが…これも運用開始してみないと何とも言えないことが多いと思います。
ストレージトランザクションと同じくそんなにコストに影響する項目でもないので、__適当にオーバーに入れておくぐらいの認識でよいと思います。__

## おわりに

見積もる際は、オーバーなスペックで見積もっておくのがクラウドの基本かと思います。
運用後に無駄があるようであれば、インスタンスタイプを調整したりして柔軟にパフォーマンスを調整できるのがクラウドの強みですね。
Databricksにおけるセキュアクラスター接続

[Secure cluster connectivity \| Databricks on AWS](https://docs.databricks.com/security/secure-cluster-connectivity.html) [2021/10/14時点]の翻訳です。

> **重要！**
この機能は、[E2バージョンのDatabricksプラットフォーム](https://qiita.com/taka_yayoi/items/7d209bc8d32bc5f2dba4#e2%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3)でのみ有効です。2020/9/1以降、E2プラットフォームはでは、セキュアクラスター接続はデフォルトで有効となっています。

セキュアクラスター接続を有効にすることで、顧客管理VPCにオープンなポートがなくなり、DatabricksランタイムクラスターノードはパブリックIPアドレスを持たなくなります。

> **重要！**
この記事では、Databricksの計算機レイヤーである*データプレーン*という単語を使います。この記事の文脈においては、データプレーンはお使いのAWSアカウントにおけるクラシックなデータプレーンのことを指します。一方で、[Serverless SQL endpoints \(パブリックプレビュー\)](https://docs.databricks.com/sql/admin/sql-endpoints.html#serverless)をサポートするサーバレスデータプレーンは、DatabricksのAWSアカウントで稼働します。詳細は[Serverless compute](https://docs.databricks.com/serverless-compute/index.html)をご覧ください。

- ネットワークレベルでは、それぞれのクラスターはクラスター作成時に、コントロールプレーンのセキュアクラスター接続リレーに対する接続を確立します。クラスターは、ポート443(HTTPS)を用いて接続を確立し、Webアプリケーション、REST APIとは異なるIPアドレスを使用します。
- コントロールプレーンが、新たなDatabricksランタイムジョブや他のクラスター管理タスクを論理的に起動した際に、これらのリクエストはこのリバーストンネルを通じてクラスターに送信されます。
- データプレーン(VPC)にはオープンなポートはなく、DatabricksランタイムクラスターノードにパプリックIPアドレスはありません。

メリット：

- セキュリティグループに対するポートの設定や、ネットワークピアリングの設定が不要となり、ネットワーク管理が容易になります。
- 強化されたセキュリティとシンプルなネットワーク管理によって、情報セキュリティチームはPaaSプロバイダーとしてのDatabricksの認可を促進することができます。
![](https://docs.databricks.com/_images/secure-cluster-connectivity-aws.png)

# セキュアクラスター接続を使う

ワークスペースでセキュアクラスター接続を使うには、[Account API](https://docs.databricks.com/administration-guide/account-api/new-workspace.html)を用いて新規ワークスペースを作成します。既存のワークスペースにセキュアクラスター接続を追加することはできません。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
BANDAI NAMCOさんの感情分析用アダプターを使ってみた

# 感情分析用アダプターとは？
BANDAI NAMCO研究所が作成した、BERTと組み合わせることによって感情分析ができるものです。
ここで行われる感情分析は、与えられた文がポジティブなのかネガティブなのかの二値分類となっています。

ダウンロードや詳細説明、Google Colabでのデモは以下のサイトに書かれています。

https://github.com/BandaiNamcoResearchInc/sentiment-analysis-adapter/blob/main/README_ja.md

この記事ではローカル環境でこれを使った感情分析の方法を紹介します。
コードとしてはGitHubで紹介されている方法とほぼ同じなのですが、エラーが出てしまうことが考えられるのでその解決方法も含めて説明します。

# 実行環境
|項目|バージョン等|
|---|---|
|OS|mac Mojave|
|python|3.8.2|
|pyenv|1.2.26|
|transformers|4.12.2|
|torch|1.10.0|
|adapter-transformers|2.2.0|

# 実行コード
```
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification, AdapterType

#モデルのロード
def load_model():
    adapter_path = "ADAPTER_PATH"  # 事前学習済みのアダプターが保存されたディレクトリのパス
    model = AutoModelForSequenceClassification.from_pretrained(
        "cl-tohoku/bert-base-japanese-whole-word-masking")
    tokenizer = AutoTokenizer.from_pretrained(
        "cl-tohoku/bert-base-japanese-whole-word-masking")
    model.load_adapter(adapter_path)
    
    return model, tokenizer

#ロードされたモデルを使った感情分析
def predict(sentence, model, tokenizer):
    token_ids = tokenizer.convert_tokens_to_ids(tokenizer.tokenize(sentence))
    input_tensor = torch.tensor([token_ids])
    outputs = model(input_tensor, adapter_names=['sst-2'])
    result = torch.argmax(outputs[0]).item()

    return 'positive' if result == 1 else 'negative'

if __name__ == "__main__":
    model, tokenizer = load_model()
    print(predict("ちゃんと出力されてめっちゃ嬉しい！", model, tokenizer))
```

predict関数の第一引数に分析したい文字列を入れればOKです。

この場合、出力は、

```
positive
```
となります。

以下、多くの人が遭遇するだろうエラーを挙げます。

# ImportError: cannot import name 'AdapterType' from 'transformers'
最初、私がこのコードを実行した時、このようなエラーが出ました。
実はこれ実行するためには、transformersだけでなく**adapter-transformers**というモジュールもインストールする必要があるんです。
pythonファイルではtransformersと同様に `import transformers` で使えるので気づくのが遅れました...
下のコードをターミナルで実行すれば大丈夫です。

```
$ pip install adapter-transformers
```

# その他エラー
ここで使っている、東北大が公開している日本語BERTに関連するエラーが発生する可能性があるので、そのエラーについても書いておきます。

### fugashiのモジュールが存在しない

```
ModuleNotFoundError: No module named 'fugashi'
```

### ipadicのモジュールが存在しない

```
ModuleNotFoundError: The ipadic dictionary is not installed. See https://github.com/polm/ipadic-py for installation.
```

これらについても、対応するモジュールをインストールするだけで大丈夫です。

```
$ pip install fugashi
$ pip install ipadic
```

# 使ってみた感想
### メリット
* 学習の必要がないので手軽に感情分析を試すことができる
* APIではないので一ヶ月のリクエスト上限みたいなのがない

### デメリット
* ポジネガの二値分類なので、感情を伴わない文が入力された場合上手く対応できない。（大体ポジティブになる） 

### まとめ
感情分析のとっかかりとして、試してみるのはアリだと思いました。ただ、感情がのっていない文がポジティブ扱いになってしまうというデメリットがかなり大きいです。特定のユーザーのツイートに対してポジネガの割合を出す、みたいなタスクを行うとポジティブの割合がかなり大きくなってしまうので...
この感情分析アダプターは映画のレビューをもとに学習されているようですが、このような場合には必ず文に感情がのっていると仮定できるため、うまい具合に使えるかもしれませんね。
IntelliJでLateX環境を作る(Mac)

# 環境

- Mac OS Catalina 10.15.7
- Homebrew 3.3.2

# MacTeXのインストール
## MacTeXとは

MacTeX は [TeX Live](https://texwiki.texjp.org/?TeX%20Live) をベースにした macOS 専用の TeX ディストリビューションです。 TeX Live をフルインストールし，オプションでいくつかの追加アプリケーションもインストールします。

[MacTeX - TeX Users Group](http://tug.org/mactex/)

## インストール

homebrewを利用してインストールできます。インストールには時間がかかります。

```bash
/*GUIアプリケーションも込みでインストール、今回はこちら*/
$ brew install --cask mactex 

/*GUIアプリケーションを除いたものをインストール*/
$ brew install --cask mactex-no-gui 
```

以下のコマンドウを実行して最新版にアップデート、デフォルトの用紙サイズをA4に変更します。

```bash
$ sudo tlmgr update --self --all
$ sudo tlmgr paper a4
```

`/Library/Tex/texbin`に諸コマンドが格納されています。

サイトからのダウンロードだと完全なアンインストールが難しくなるようなのでbrewを用いたインストールがおすすめです。

[MacTeX をおすすめできる場合とそうでない場合（私見）](https://blog.wtsnjp.com/2020/07/07/about-mactex/)

# IntelliJ IDEAの諸設定

## Pluginの導入

#### TeXiFy IDEA
Preferences → Plugins → texで検索
[TeXiFy IDEA - IntelliJ IDEs Plugin | Marketplace](https://plugins.jetbrains.com/plugin/9473-texify-idea)

#### PDF Viewr
Preferences → Plugins → PDFで検索
[PDF Viewer - IntelliJ IDEs Plugin | Marketplace]
(https://plugins.jetbrains.com/plugin/14494-pdf-viewer)



## PDF出力に伴うRun/Debug Configrationsの設定

### Run/Debug Configrationsの設定

1. '+' → Shell Script を選択
2. Script Path  : スクリプトが存在するパスを指定
    
    Working Directory : PDF出力したいtexファイルが存在するパスを指定
    
    Execute in Terminal : チェック
    

### Shell Scriptの例

```bash
for file in *.tex #ディレクトリ直下のtexファイルに対して処理
do
  filename=${file%.*} #拡張子を除いたファイル名を取得
  platex "$filename" 
  dvipdfmx "$filename"
done
```

# 画面
画像のようにtexファイルを編集、実行するとすぐにPDFに反映するような形で作業が進められます。
![スクリーンショット 2021-11-04 21.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1153569/fbb6ae6b-f5f5-5b11-7199-d980a30d6e01.png)

# おわりに
ご拝読ありがとうございました。
TensorFlow(2系)で実際に使用しているGPUのメモリ量を確認する

# はじめに
TensorFlowはGPUを利用する際、特に`tf.config.experimental.set_memory_growth`を設定しなければ、メモリ効率化のために全てのメモリを割り当てようとしてしまう。
そのため`nvidida-smi`等ではその割り当てられた割り当てられた量しか確認できず、内部では実際にどれだけのGPUメモリを使用しているのか確認する方法はないか知りたかった。
# 実行環境
Ubuntu: 20.04
TensorFlow: 2.4.0
# 方法
結論としては`tf.config.experimental.get_memory_usage`を使えばよい。
GPUのみにしか使えない。

```
gpu_devices = tf.config.list_physical_devices('GPU')
if gpu_devices:
  tf.config.experimental.get_memory_usage('GPU:0')
```

上記のように、`GPU：ID`みたいに指定すると、実際に使用したbyteが返ってくる。

もし、間違っている点やより良い方法があれば教えてください。
# 参考
https://www.tensorflow.org/versions/r2.4/api_docs/python/tf/config/experimental/get_memory_usage
今回はversion2.4で試したが、TensorFlow2.6では`get_memory_usage`の方が推奨らしい
https://www.tensorflow.org/api_docs/python/tf/config/experimental/get_memory_info
https://www.tensorflow.org/api_docs/python/tf/config/experimental/get_memory_usage
事前に採番したそのID使われてないかも！？（CakePHP）

# はじめに

データ新規作成時、あらかじめ ID を採番しておいて、オブジェクトを持ちまわしていました  
しかし、そのオブジェクトの保存処理後、採番していた ID とは違う ID で保存されていたのです

# 結論

:::note info
patchEntity() の返り値のエンティティの id に値を設定すれば OK
:::

```php:CakePHPUserRepository.php
// ユーザーを保存する
public function save(User $user): UserId
{
    $model = TableRegistry::getTableLocator()->get('Users');
    $saveData = [
        'Users' => [
            // ここで ID を設定しても保存処理に採用されない
            // 'id' => $user->getId()->getValue(),
            'username' => $user->getUsername()->getValue(),
            'password' => $user->getPassword()->getValue(),
            'role' => $user->getRole()->getValue(),
        ],
    ];

    $entity = $model->newEmptyEntity();
    $entity = $model->patchEntity($entity, $saveData);
    // patchEntity() 時に ID が消え去るため、明示的に設定
    $entity->id = $user->getId()->getValue();
    $saved = $model->saveOrFail($entity);

    return new UserId($saved->id);
}
```

# バージョン

- PHP
    - 8.0.10
- CakePHP
    - 4.3.0

# 状況

## プロダクトコード

ユーザー新規追加APIで、以下のような雰囲気のコードを書いていました

```php:CakePHPUserRepository.php
// 独自クラス
// ユーザーID を UUID で採番する
public function assignId(): UserId
{
    return new UserId(\Cake\Utility\Text::uuid());
}

// ユーザーを保存する
public function save(User $user): UserId
{
    // （略）↑の結論と同様
}
```

```php:UsersController.php
// ユーザー新規追加アクション
public function add(): void
{
    $jsonData = $this->request->getData();
    $userRepository = new CakePHPUserRepository();
    $userId = $userRepository->save(
        new User(
            $userRepository->assignId(),
            new Username($jsonData['username']),
            new Password($jsonData['password']),
            new Role($jsonData['role']),
        )
    );

    $data = ['userId' => $userId->getValue()];
    $this->set($data);
    $this->viewBuilder()->setClassName('Json')->setOption('serialize', ['userId']);
}
```

以下の独自クラスにゲッターメソッド（`getXxx()`、`getValue()`）定義

- User.php
- UserId.php
- Username.php
- Password.php
- Role.php

## テストコード

しかし、テストを実行すると、ID が一致しないのです

```php:CakePHPUserRepositoryTest.php
public function test_ユーザー情報を保存すること(): void
{
    $expect = new UserId('01509588-3882-42dd-9ab2-485e8e579a8e');
    $user = new User(
        $expect,
        new LoginId('test'),
        new Password('p@ssw0rd1'),
        new RoleName('admin'),
    );

    $actual = (new CakePHPUserRepository())->save($user);
    $this->assertEquals($expect, $actual);
}
```

ということで、上記の結論となります

# おわりに

テストコードを作成して実行するまで、全然気づきませんでした  
この記事が他のエンジニアの助けになれば幸いです
vue3+typescriptでアプリを作成してデプロイするまで【Vue個人開発Part2】

## はじめに
vueアプリを個人で作成してデプロイまでしたのでその備忘録として。
以下の記事に従って、HelloWorldは済ませている。

https://qiita.com/ninoko1995/items/55282783af3529ebe262

作成するアプリは、The Movie Database Apiにアクセスして映画を探せるアプリ。

https://developers.themoviedb.org/3/getting-started/introduction

ちなみに作成した全コードは以下。

https://github.com/ninoko1995/vue-app

## 導入
### axiosの導入
APIを叩くためにaxiosを入れないといけない。
色々調べたが、結局以下のコマンドで導入後、特に何かのファイルとかをいじらなくても利用できた。

```
npm install axios --save
```

これできちんと`package.json`にも追加されたし、ファイルからも読み込めるようになった！


### vuexの導入
気に入った映画をお気に入り登録して、お気に入り一覧を表示したいので、vuexを導入してstoreに保存できるようにする。
今回はページ遷移がないのでなくても大丈夫ではあるが、拡張性を考えると絶対にあった方がいいので入れておく。

https://stackoverflow.com/questions/64412243/vue-js-3-and-typescript-property-store-does-not-exist-on-type-componentpub

うまく動かなかったので調べた記事。

https://qiita.com/after666/items/59d40a6687aeeafaaa7e

https://zenn.dev/okakyo/articles/87faf411c4766e5ccb4a

どうするのがベストプラクティスかはわからないが、vue3では以下の方法で動くことがわかった。
コード全部はgithubに載ってるので、大事なとこだけメモする。

```main.ts:
import { createApp } from 'vue'
import App from './App.vue'
import { store } from "./store"; // <- 自分で作ったstoreファイル

const app = createApp(App).use(store) // <- ここでstoreをuseする

app.mount('#app')
```
```store/index.ts:
import Vuex from "vuex";
import { movie, MovieState } from "./modules/movie"; // 自分の定義したmodule

// interfaceを定義する
export interface RootState {
  movie: MovieState;
}

// このstoreが、上の`main.ts`で読み込まれるやつ。
export const store = new Vuex.Store<RootState>({
  modules: { movie }, 
}); 
```
で、使う時はこんな感じ。

```vue:
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
import { useStore } from "vuex"

// ...

@Options({
})
export default class Home extends Vue {
  store = useStore() // this.storeでstoreにアクセスできるようになる。
  
  // ...
}

```

ほんとはvue2みたいに`this.$store`で読み込めるようにしたかったけどうまいことできなかった。
時間があるときにそこら辺周りをきちんと調べたい。


### font-awesomeの導入

https://qiita.com/k-itachida/items/e95ffd50dd4c1db9a85f

solidからもregularからも同じ名前のものをimportしたいときにちょっと困った。
やってみれば簡単だった。

```main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { library } from '@fortawesome/fontawesome-svg-core'

// それぞれ別の名前でimportして
import { faHeart as solidHeart } from '@fortawesome/free-solid-svg-icons' 
import { faHeart as regularHeart } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

// それぞれaddする
library.add(solidHeart);
library.add(regularHeart);

const app = createApp(App)
app.component('fa', FontAwesomeIcon )

app.mount('#app')
```
使うときに同じ名前で混乱しないかと思ったけど、regularとsolidで使うクラス名が異なるので大丈夫だった。

```ts
<fa icon="heart" /> // <- solid icon
<fa :icon="['far', 'heart']" /> // <- regular icon
```

ただ、使うアイコンを一つ一つimportしないといけないの面倒くさい。
もうちょっと楽な方法もありそうな気もする。

## 開発

ここまでくれば、あとは自分の好きなようにコードを書くだけ。
特に困ったことはないので飛ばす。


## デプロイ
### Netlifyへのホスティング
以下の記事を参考に、ホスティング先を決めた。

https://www.serversus.work/topics/b2p2s9r2k29qjpxeuzqj/

netlifyのページを、指示に従って進めていくと、githubのレポジトリから簡単にデプロイしてくれる。
ちょー便利。

というわけで、デプロイできたものが以下。

https://angry-carson-84bdcd.netlify.app/

## 感想
始め方は簡単だし、セットアップも簡単な一方で、組み合わせがたくさんあって「何を使えばいいのか」という点とそもそもバージョンの観点でどれが使えてどれが使えないのかみたいなことを、記述方法を調べるときにまず大前提に置いておかないと、色々調べながら混乱するなぁと思った。
javaでダウンロードzipファイルを一時保存せず処理

javaでネットワーク上のzipファイルを取得する場合はローカルの適当なディレクトリに一時保存してから解凍して処理が多いと思われる。内部実装はともかく、java上でzipファイルのダウンロードから処理までを完結する方法について。

# 環境
* java 17

# ソースコード
例として郵便番号（いわゆるken_all.csv）のzipファイルを読み込む。

```java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipDownload {
  public static void main(String[] args) throws IOException {
    URL url = new URL("https://www.post.japanpost.jp/zipcode/dl/oogaki/zip/10gumma.zip");

    try (InputStream is = url.openStream();
        ZipInputStream zip = new ZipInputStream(is);
        InputStreamReader isr = new InputStreamReader(zip, "Shift_JIS");
        BufferedReader br = new BufferedReader(isr);) {

      ZipEntry entry;
      while ((entry = zip.getNextEntry()) != null) {
        System.out.println("####" + entry.getName());
        br.lines().forEach(System.out::println);
      }
    }
  }
}

```

zipファイルの中身の処理（ディレクトリの有無とか）や脆弱性対応（https://www.jpcert.or.jp/java-rules/ids04-j.html あたり参照）については省略している。
webpack 5からurl-loader/file-loader/raw-loaderが要らなくなった

doc: [Asset Modules | webpack](https://webpack.js.org/guides/asset-modules/)

## Asset Modulesの概要

webpack 5から **Asset Modules** が追加されました。モジュールのタイプを指定するもので、webpack4以前ではloaderを使用していたファイルの読み込を置き換えるものになります。
次のような対応になります。

|webpack 4 (loader)|webpack 5 (Asset Module)|
|-|-|
|url-loader|asset/inline|
|file-loader|asset/resource|
|raw-loader|asset/source|
|url-loader + limitオプション|asset|

## 使用方法

`webpack.config.js` でloaderを使用していた部分をAssetModuleの指定に書き換えます。

```js:wepback.with-loader.config.js
module.exports = {
  module: {
   rules: [
      {
        test: /\.svg$/,
        use: 'url-loader',
      },
   ]
  },
}
```

```js:wepback.with-asset-module.config.js
module.exports = {
  module: {
   rules: [
      {
        test: /\.svg$/,
        type: 'asset/inline',
      },
   ]
  },
}
```

`asset/resource` (ファイル出力)で出力ファイル名の指定は各 `rule` での `generator.filename` の指定、または `output.assetModuleFileName` で可能です。

```js:webpack.export-name.config.js
module.exports = {
  module: {
   rules: [
      {
        test: /\.svg$/,
        type: 'asset/inline',
        generator: {
          filename: 'images/[hash][ext][query]'
        }
      },
   ]
  },
}
```

```js:webpack.export-name.config.js
module.exports = {
  output: {
    assetModuleFilename: 'images/[hash][ext][query]'
  }
}
```

その他詳細は[公式ドキュメント](https://webpack.js.org/guides/asset-modules/)を参照してください。
初心忘れるべからずということです。

試したことを記録。

**以下記事にて実装**
投稿日：2021/11/04
・[「何食べたい？」に対して「なんでもいい」以外の言葉、探してみませんか？](https://qiita.com/yui-kouy/items/5dc0db657e29e677bed6)
カラーコード
・[WEB色見本 原色大辞典 - HTMLカラーコード](https://www.colordic.org/) 

#Web上の画面再読み込み
Web上で再読み込みボタンを作る
HTMLとCSSの記述のみで実装可能


**参考**
・[See-SS](https://see-ss.com/) 

<details><summary>HTML</summary><div>
``a href=""``の``""``は「再読み込み」を行う指示
``a href=""``を``"#"``にすると「ページ上部へ戻る」の指示になる
やりたいことによって記述が変わるので注意。

```HTML
    <a href="" class="button-19">他の料理も見たい場合は押してください</a>
```

</div></details>

<details><summary>CSS</summary><div>

```CSS
.button-19 {
  position: relative;
  padding: 0.5em 1.6em;
  font-size: 0.8em;
  color: #8b4513;
  text-decoration: none;
  user-select: none;
  border-top: 1px #8b4513 solid;
  border-bottom: 1px #8b4513 solid;
  transition: 0.3s;
}

.button-19:hover {
  opacity: 0.5;
}

.button-19::after,
.button-19::before {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  content: '';
  background: #8b4513;
}

.button-19::after {
  top: 2px;
}

.button-19::before {
  bottom: 2px;
}
```

</div></details>

#背景グラデーション
CSSの記述のみで実装可能
ごめんなさい。参考元がわからなくなってしまいました・・・

<details><summary>CSS</summary><div>

```CSS
/*背景グラデーション*/
body {
  overflow: visible !important;
  background: -webkit-linear-gradient(45deg, #fffacd 10%, #ffa500 90%);
  background: -moz-linear-gradient(45deg, #fffacd 10%, #ffa500 90%);
  background: -ms-linear-gradient(45deg, #fffacd 10%, #ffc0cb 90%);
  background: -o-linear-gradient(45deg, #fffacd 10%, #ffc0cb 90%);
  background: linear-gradient(45deg, #fffacd 10%, #ffc0cb 90%);
 }
```

</div></details>


#気になるサイト
・[コピペ実装！CSSだけで作れるお洒落で使いやすいボタン◉サンプルコード12選](https://grow-group.jp/archives/2674/)
・[CSSで表現する背景パターン51種＋【コピペで簡単！/アニメーション有】](https://webdesignfacts.net/entry/css-background-patterns/#gsc.tab=0)
・[コピペでできるCSSボタンプロデザインをコピペで実装！ 【 グラデーション・カラフル系 】](https://deshinon.com/2019/03/02/colorful-css-button/)
・[【CSS】使える背景パターン、実装サンプル25選（コピペで簡単です）](https://125naroom.com/web/3737)
・[CSSで見出しをデザイン！コピペできるおしゃれな見出しデザインまとめ](https://ferret-plus.com/6821)
・[かわいい系デザインに使えるCSSいろいろ](https://www.webcreatorbox.com/tech/cute-css-tips)
私個人がアドベントカレンダーに参加したきっかけ


[アドベントカレンダー初参加する人に向けた、アドベントカレンダーに参加したきっかけアドベントカレンダー](https://qiita.com/advent-calendar/2021/sanka-kikkake)
1日目です

私個人がアドベントカレンダーに参加したきっかけを記載します。

## きっかけ

以下のカレンダーが盛り上がっているのを見たことがきっかけです。
内容というよりは、失敗や反省を公開して将来同じ失敗を繰り返さないようにようにする志に共感しました。

> [本番環境でやらかしちゃった人 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yarakashi-production)

## 過去に参加したアドベントカレンダー

以下に参加しました。
[ソフトウェアテストの小ネタ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/software-testing-koneta)
[Pythonその2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/python2)
[Jetson Advent Calendar 2020](https://qiita.com/advent-calendar/2020/jetson)

ちなみに過去に参加したカレンダーは以下のように過去カレンダーページの「参加中のカレンダー」から確認できます。
https://qiita.com/advent-calendar/2020
![スクリーンショット 2021-11-04 20.25.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/717d89e9-c700-5534-c68e-ac214f3ca8e8.png)

## 過去にアドベントカレンダーに投稿した記事

アドベントカレンダーに参加してみたい！という一心で記事をひねりだしました。
目的と手段が逆な気もしますが、、アドベントカレンダーに参加するという意味ではモチベーションがボトルネックになる事もあると思うので、そういう点ではよかったと思います。


[プログラミング学習を目的とした、ブロックを操作してスコアを競うゲームをpythonで作成する試み](https://qiita.com/seigot/items/a1a7b80ef6f4142ae602)
[シェルスクリプトで自動インストールスクリプトを作成する際の注意点メモ](https://qiita.com/seigot/items/f481445b9bd917e21f4a)
[Jetson Nano/PC間でROS接続する](https://qiita.com/seigot/items/a6eaebccfd427bb315b4)
[ps4コントローラーをJetsonNano+ros melodicで使用する](https://qiita.com/seigot/items/80bb409ff2de351ee9fa)

今見返すとすごくn番煎じな記事も投げてしまった感がありますが、、
アドベントカレンダーに投稿したい欲は満たす事ができました。
今後は、[本番環境でやらかしちゃった人](https://qiita.com/advent-calendar/2021/yarakashi-production)のような本質に迫る記事を書いていきたい。

## 感想
おそらくきっかけをシェアする事の共通点を分解すると、色々な活動のプロジェクトマネジメントに通ずる話になるのではと考えています。
情報をオープンにする事が、将来の悩み解決に繋がる文化がこれからも継続されていくことを望みます。

アドベントカレンダー界隈では情報をオープンにする事がもはや当たり前な空気感ですが、
そうでない界隈もあると思うので、何かの参考になりますと幸いです。
【Vue.js】v-ifとv-showの違い

#はじめに
こんにちは！
今回は【Vue.js】v-ifとv-showの違いについてアウトプットしていきます！

#v-ifとv-showの違い

##v-if
・要素をDOMから削除・追加することで表示/非表示を切り替える。
⏩切り替えコストが高い。
・v-else、v-else-ifが使える。

##v-show
・CSSのdisplayプロパティを使って表示/非表示を切り替える。
⏩初期描画コストが高い。
・v-else、v-else-ifが使えない。

#まとめ
・v-ifは実行時に条件を変更することはほとんどない場合に使用するのが推奨されます。
・v-showは表示/非表示を頻繁に繰り返す場合に使用するのが推奨されます。

#最後に
今回はv-ifとv-showの違いについてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
【SwiftUI】NavigationLinkでの遷移先でTextFieldをタップしたら画面が閉じる件

#遷移先でTextFieldをタップしたら画面が閉じる
SwiftUIでNavigationViewで画面遷移を実装中にだいぶ詰まったので、備忘録として残しておきます。
NavigationLinkまわりの画面遷移は色々詰まっている人がいるようで、自分が経験したケース以外にも色々あるみたいなので、参考にしたスレッドを書きに記しておきます。
https://developer.apple.com/forums/thread/677333


#解決策
navigationViewStyleにStackNavigationViewStyleを指定するだけで解決しました。
思いのほか簡単な解決策でしたが、結構ハマちゃってました笑
以下のコードでNavigationLinkでの遷移先で、TextFieldをタップしても画面が落ちずにすみます。

```swift
NavigationView {
}
.navigationViewStyle(StackNavigationViewStyle())
```

#参考
https://developer.apple.com/forums/thread/691242
seleniumチートシート（Windows＆Python編）


分類：Python3,Windows10,クロム
日付：2021/11/04

seleniumの使い方を毎回忘れるのでチートシートにしました



#環境構築

###①クロムのバージョンチェック

メニュー右上の︙アイコンをクリック、→　ヘルプ　→　googleクロムについて　を選ぶ


<img width="300" alt="c1.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/ce579288-bf90-5d6b-8a33-6e5ff4b83b09.jpeg">


<img width="300" alt="c2.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/574c2070-02b9-60d0-5dfa-d1c04dda3713.jpeg">


###②ダウンロードのページ
　　https://chromedriver.chromium.org/downloads



![c3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/72de9b64-2004-300d-30dc-a35272e79f7a.jpeg)

確認したバージョンに合わせてリンク先を選択

###③Windows10はchromedriver_win32.zipをダウンロード



![c4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/5eb8ef3c-052c-b070-282d-74b2aec239b9.jpeg)

###④zipを解凍してできた　chromedriver.exe　をc:\にコピー
 このあとPythonのコードで

```py:test.py
driver = webdriver.Chrome("c:\chromedriver")
```

　として使うので　c:\　に解凍していますが、ほかのフォルダで使うときは、コードとフォルダ名を合わせればOKです

###⑤Python側でseleniumライブラリをインストール

　pip install selenium


###⑥動作テストはこんな感じ

```py:test.py
	from selenium import webdriver
	driver = webdriver.Chrome("c:\chromedriver")
	driver.get("https://yahoo.com")
	driver.close()
	driver.quit()
```
yahooが開いて閉じればインストール成功！
sympyのPoint2D.rotateを調べてみた。

オリジナル
rotate(angle, pt=None)

https://docs.sympy.org/latest/modules/geometry/points.html#sympy.geometry.point.Point2D.rotate

```python
from sympy import *
var('sx sy')
var('tx ty')
var('t')
def myPoint2DRotate(myDai,mySyo,t):
    tx=myDai.x
    ty=myDai.y
    sx=mySyo.x
    sy=mySyo.y
    return Point2D(tx+sx,ty+sy).rotate(t, (tx,ty))
print("#",Point2D(tx+sx,ty+sy).rotate(t, (tx,ty)))
print("#",Matrix([[cos(t),-sin(t),tx],[sin(t),cos(t),ty],[0,0,1]])*Matrix([[sx],[sy],[1]]))

print("#",Point2D(2-1,0-0).rotate(pi/2, (2,0)))
print("#",myPoint2DRotate(Point2D(2,0),Point2D(-1,0), pi/2))
# Point2D(sx*cos(t) - sy*sin(t) + tx, sx*sin(t) + sy*cos(t) + ty)
# Matrix([[sx*cos(t) - sy*sin(t) + tx], [sx*sin(t) + sy*cos(t) + ty], [1]])
# Point2D(2, -1)
# Point2D(2, -1)
```
【AWS】EC2のログをOpsworksを用いてCloudWatchへ転送する。

# はじめに
アプリケーションのログをCloudWatchへ転送することが出来ると、
**Logs insightsで統計的な分析が出来たり、
CloudWatch Alermと連携させて特定のlogを検出すれば通知させたり**することが出来ます。

今回は**Opsworks**でEC2を管理している場合での、CloudWatchへのログの転送方法を紹介します。


# 転送方法
Opsworksでは`Stack`という概念があり、Stackの中に`Layers`と呼ばれる管理単位があり、この中でEC2インスタンスを管理します。
（Stack > Layers > EC2インスタンス という関係）

CloudWatchへの転送の設定は`Layers`の設定変更のページで行います。
※ インスタンス単位で設定するワケではないので、対象となるLayers内で管理されているEC2全てでCloudWatchへの転送設定が反映されます。


対象となるLayersを選択、`CloudWatch Logs` タブを開き、Editボタンを押します。
![スクリーンショット 2021-10-19 15.31.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/08d77240-4a8d-4791-4da0-2bfc3e554f01.png)

**CloudWatch Logs integration**を`On`にし、**Stream command logs**を`Yes`にすれば、
**Stream custom logs** に記述したパスのlogを転送させることが出来ます。

ただし、上の画像の注意文にあるように、今のままではIAMのポリシーが無いので、
CloudWatch Logsへの転送を可能にするには、`Default IAM instance profile`のIAMロールに**AWSOpsWorksCloudWatchLogs**ポリシーをアタッチする必要があります。


# IAMロールにポリシーのアタッチ
`Default IAM instance profile`はStackページの**stack settings**で確認できます。

![スクリーンショット 2021-11-04 19.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/2b501f88-00ff-e044-e2dd-dc730be9bf95.png)

`Advanced options` の項目に`Default IAM instance profile` は載っています。
ここからIAMロールのページへ飛べます。

![スクリーンショット 2021-10-19 15.39.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/1085dd27-7bb9-81d8-789d-6a4d5079856c.png)


該当のIAMロールのページへジャンプしたら、「ポリシーをアタッチします」ボタンをクリックします。
![スクリーンショット 2021-10-19 15.46.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/09fbf3ce-3c2c-540b-fbe1-d8095abd0df9.png)



**AWSOpsWorksCloudWatchLogs** で検索し、チェックボックスにチェックを入れたら「ポリシーのアタッチ」をクリックします。

![スクリーンショット 2021-10-19 15.48.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/a7cfc3a5-513a-5616-aee6-85621c41321e.png)

これでCloudWatch Logsに転送する許可設定が出来ました。
あとは、先ほどのEdit画面の**Stream Custom Logs**の欄に転送したいlogのパスを記入します。
例） `/var/www/rails_app/log/production.log`　
「Save」ボタンを押して暫くすると設定が反映されます。


# 反映
「Save」して暫くすると、対象レイアーのインスタンス内で`/var/awslogs` が自動生成されます。
細かい設定は `/var/awslogs/etc/awslogs.conf`で変更できますが、名前の変更くらいなので使うことは無いと思います。


暫くするとCloudWatchの**ロググループ**に反映されます。
ロググループの命名規則は
`Stack名`/`Layers名`/`指定したパス名`
となります。

これでCloudWatchへのログ転送完了となります。
Scalaトレイト：挙動 (Scala Trait Behavior)

##ミックスイン合成 (Mixin Composition)
###extendsを使用した場合
```Scala
// Define trait
trait Cat {
    def bark(): Unit = {
        println("meow meow")
    }
}

// Mixin trait using "extends"
class Savannah extends Cat {
    override def toString = "wild"
    override def bark(): Unit = {
        println("Roar! Roar!!!")
    }
}
```
###withを使用した場合
```Scala
class Hunting {
    def hunt(): Unit = {
        println("Find food")
    }
}

// Define trait
trait Cat {
    def bark(): Unit = {
        println("Meow of a cat : meow meow")
    }
}
trait Zebra {
    def escape(): Unit = {
        println("Zebras run")
    }
}

// Mixin trait using "with"
class Savannah extends Hunting with Cat with Zebra{
    override def toString = "wild"
    override def hunt(): Unit = {
        println("Lion aims at zebras")
    }
    override def bark(): Unit = {
        println("Lion barks : Roar! Roar!!!")
    }
    override def escape(): Unit = {
        println("Zebras run at full power")
    }
}
```

##Ordered トレイト (Ordered Trait)
クラスのメソッドを使用して、メソッドを自動的に増やすことが出来る。
それにより、インターフェースをリッチにすることが出来る。
Use the methods of the class to automatically increase the methods.
By doing so, the interface can be enriched.

```Scala
// Mixin Ordered trait
class Comparison(val num: Int) extends Ordered[Comparison] {
    def compare(that: Comparison) = {
        val res = this.num - that.num

        if (res == 0) {
            0
        }else if (res < 0) {
            -1
        }else {
            1
        }
    }
}
```

##積み重ね可能な変更 (Stackable Modifications)
クラスのメソッドを変更するときは、積み重ね可能な変更を行うことが出来る。
それにより、サブクラス、スーパークラス、およびトレイトを線形化することが出来る。
When changing a method of a class, you can Stackable Modifications.
By doing so, subclass, superclass, and trait can be linearized.

```Scala
abstract class Calculation {
    def calc(x: Int): Unit 
}

class Addition extends Calculation {
    def calc(x: Int): Unit = {
        println(x + x)
    }
}

// Define traits for Stackable Modifications
trait Squared extends Calculation {
    abstract override def calc(x: Int): Unit = {
        super.calc(x * x)
    }
}
trait Cube extends Calculation {
    abstract override def calc(x: Int): Unit = {
        super.calc(x * x * x)
    }
}

// Mixin Stackable modifications traits
class AddSquCalc extends Addition with Squared
class AddCubeCalc extends Addition with Cube

```

## GitHub
https://github.com/GL-Kageyama/Scala_Trait
conda 環境で PyQt5 "xcb" error は環境再構築で対応

## 背景

conda で Python 環境を作っている.

opencv を conda でいれたりしたら

```
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.
```

というエラーが出てしまった. 検索するとよくあるエラーでした.

`QT_DEBUG_PLUGINS=1` だと,

```
... libQt5XcbQpa.so.5: undefined symbol: _ZTI23QPlatformVulkanInstance, version Qt_5_PRIVATE_API)
```

となる. Vulkan は特に関係なくて, 各種パッケージ間などでなんらかの Qt バージョンのミスマッチがあるのが原因の模様.

## 対処

検索すると xcb を apt で入れる, apt で pyqt5 入れるなどありますが, 私の環境では特に解決しませんでした.

原因究明も面倒で時間を無駄にするだけなので, conda 環境作り直しで対応しましょう.

環境の削除は

```
$ conda remove -n <env> --all
```
認可　gate　メソッドの違いについて

#gate

（名前の通り門のイメージ）
→roleに応じてアクセス制御を行う

#使われるメソッド
authorize　

403のAuthorizationExceptionがthrow


allows⇄denies

allows

→AuthorizationExceptionがthrowされないので、if分により分岐処理を行うことができる

forUser
アクセス制限を行うために他のユーザのアクセス権を利用する
forUserメソッドに他のユーザを指定して、指定したユーザの情報で削除のアクセス制限を行う（？）
端末のHMSバージョンの取得方法

端末のHMSバージョンは次のコードで取得できます。

```java
public String getHmsVersion(Context context) {
    String version = null;

    try {
        PackageManager packageManager = context.getPackageManager();
        if (null != packageManager) {
            PackageInfo packageInfo = packageManager.getPackageInfo("com.huawei.hwid", 0);
            if (null != packageInfo) {
                version = packageInfo.versionName;
            }
        }
    } catch (PackageManager.NameNotFoundException exception) {
        exception.printStackTrace();
    }

    return version;
}
```
私的WSH/JScript総括②～（今更）これからWSH/JScriptを学ぶには。

WSH/JScriptを学ぶには

(1) JavaScriptのこと
(2) WSH/Jscript固有のこと
(3) いろいろなオブジェクトのこと

が必要になると思います。トータルでカバーできるお手軽なものとしては

基礎解説 演習方式で身につけるチェック式WSH超入門 - ＠IT
https://atmarkit.itmedia.co.jp/ait/series/2744/
【牟田口大介（Microsoft MVP - Visual Developer - Scripting） , 著】(2006年6月2日)

Windows管理者のためのWindows Script Host入門 - ＠IT
https://atmarkit.itmedia.co.jp/ait/series/2728/
【デジタルアドバンテージ , 著】(2003年12月18日)

などがあります。いずれも古いですがWSH自体がオワコンなんだから仕方がない。
残念ながらVBScriptの比重が高いため、WSHを学ぶ資料としては手頃ですがJScript派には物足りない感じ。

書籍もこれといったものが思い浮かびません。すくなくとも新品で買えるものはないと思う。
古本屋の100円コーナーで「WSH」の３文字がある本を見つけたら買ってみるのもいいかも。程度。

ちなみにこんな本もありました。

O'Reilly Japan - Wsh クイックリファレンス
https://www.oreilly.co.jp/books/4873110068/

O'Reilly Japan - WSHクイックリファレンス 第2版
https://www.oreilly.co.jp/books/4873113091/

逆にJavaScriptについてはそりゃもうガンジス河の砂の数ほど書籍があります（大袈裟）。
しかしネックになるのは「WSH/JScriptはES3(ECMAScript 3rd Edition)準拠である」ということ。
本で読んで試してみようとしても、どれもこれも未サポート。これはすでにJavaScriptが書ける人も当然ハマります。
「ES3は何が未サポートなのか。使えないのか」を把握する必要があります（これについては別途まとめたい。）。

WSH/JScript志望のJavaScript初学者の場合（いるのかそんなひと？）、むしろ古本屋で古い入門書をお安く買うのもよいかもしれない。
WSH/JScriptにも役立つと思われるおすすめ本はまた別途紹介したい。

WSH/JScriptをやるうえで一番お役立ち＆重要なのはWSH5.6のヘルプファイル script56.chm です。
私は今でもこれを一番参照します。なんといっても公式リファレンスですし、必要なことはほとんど網羅しています。
しかし、現在ではこれを新たに入手するのが難しいんですね。普通には入手不可。
ググってでてくる情報もほぼすべて賞味期限切れです。こまったものです。

あとWEBサイトで大変参考になるのがこちら。

Windows Script Host Laboratory
http://www.roy.hi-ho.ne.jp/mutaguchi/wsh/

ここにもすごくすごくお世話になりました。
上に出てきた牟田口大介さんのサイトです。

あとはこのシリーズが現時点の有用なリソースになれればと願っています。


【参考】
私的WSH/JScript総括①～なぜ今更しつこくWSH/JScriptなのか？ - Qiita
https://qiita.com/itasnasal/items/12dc23533487cca5dbe1#comment-a1b93ae66dd0c62fc283

平成最後のWSHのヘルプファイル(script56.chm)の入手方法 - Qiita
https://qiita.com/itasnasal/items/c34119dd1f25f51c93d3
Firebase Cloud Messagingで特定のデバイストークンを対象にテスト通知を送る

# やりたいこと

Firebase Cloud Messaginでテストのために特定のデバイス（ある既知のデバイストークン）に通知を送りたい.

# 困った

Firebaseコンソール https://console.firebase.google.com >
Cloud Messaging >
新しい通知 >
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217079/21df84df-de6f-3ce7-d143-1652e67280e4.png)
どこで対象を指定するの？ :thinking: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217079/79ccdefa-50b1-91fe-18a5-7ad3f0b9275d.png)

# 方法

こっちでした.（ `テストメッセージを送信` ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217079/e4bc31d3-0d0b-8574-e74b-1bed2b0da6c8.png)
ここが入力欄になっている.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217079/f2697e38-5352-30a7-0b6f-50241f2b16e0.png)
Swiftで文字列削除（firstとlastが欲しかった）

# やりたいこと

`123abc456abc789` 
こんな文字列があった時、最初の`abc`か最後の`abc`のどちらかを**分けて**削除したかった。


#　使い方

最初の文字列を消す

```Swift:
print("123abc456abc789".removeFirstStr(of: "abc"))
# -> 123456abc789
```

最後の文字列を消す

```Swift:
print("123abc456abc789".removeLastStr(of: "abc"))
# -> 123abc456789
```

# 実装したもの

```Swift:
extension String {
    func removeFirstStr(of: String) -> String {
        guard let idx = self.range(of: of) else { return self }
        return String(self[..<idx.lowerBound] + self[idx.upperBound...])
    }
    
    func removeLastStr(of: String) -> String {
        let reversedSelf = String(self.reversed())
        guard let idx = reversedSelf.range(of: String(of.reversed())) else { return self }
        return String(String(reversedSelf[..<idx.lowerBound] + reversedSelf[idx.upperBound...]).reversed())
    }
}
```
【Git】既にあるリモートブランチに、再度pushするときのエラー

## 前提

ローカルのfeature/Aでの開発を、一度リモートのfeature/Aにpush済。

## 状況

再度ローカルのfeature/Aで修正をした。

その間にリモートのdevelopに更新があったので、ローカルのdevelopにpullし、ローカルのfeature/Aをリベースした。

ここで再度ローカルのfeature/Aからリモートのfeature/Aにpushしたところ、エラーになる。

## エラー内容

```bash
$ git push origin feature/A

// 結果
info: detecting host provider for 'https://fandmnet2.backlog.jp/'...
info: detecting host provider for 'https://fandmnet2.backlog.jp/'...
To https://fandmnet2.backlog.jp/git/HOJOSAPO/src.git
! [rejected]        feature/nagao/update_service_classes -> feature/nagao/update_service_classes (non-fast-forward)
error: failed to push some refs to 'https://fandmnet2.backlog.jp/git/HOJOSAPO/src.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

## 解決法

```bash
$ git push -f origin feature/A
```

リベースの運用ではよく起こるエラー。

一つのプルリクエストにおいて、コミット履歴は自分のものだけを残したいので、-fオプションを付けて強制的にpushする。
【Mac版】Android studioでWifi経由でワイヤレスデバックをする

Androidバージョン11以降の内容です。

##やること

1.開発者向けオプションの表示
2.USBデバックの有効化、ワイヤレスデバックの有効化
3.同じWifiに接続する
4.接続リクエスト

##1.開発者向けオプションの表示

Android端末で、設定→デバイス情報→ビルド番号と進んでください。
<img width="200"alt = "![Screenshot_20211104-173204_Original.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/89123cfc-ce27-2479-bd59-d0d3231f2fcc.png> <img width="200"alt = "![Screenshot_20211104-173255_Original.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/81226dac-7818-ef9b-5d14-cecbe7294827.png> <img width="200"alt = "![Screenshot_20211104-173412_Original.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/96544207-9bf4-bf53-c295-ea28f7feb978.png>



そしてビルド番号を7回タップすると設定→システム→詳細設定の中に開発者向けオプションが表示されてます。※数えるのもめんどくさかったらビルド番号をひたすらタップすればOKです。
<img width="200"alt = "![Screenshot_20211104-173255_Original 2.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/31034023-fad3-c0a7-2d6c-cb572ab30924.png> <img width="200"alt = "![Screenshot_20211104-173444_Original 2.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/a490434a-deb3-8d8f-8161-60275c063009.png>



##2.USBデバックの有効化、ワイヤレスデバックの有効化

開発者向けオプションの中にUSBデバックとワイヤレスデバックの欄があるので、下記を参照しながらオンにしてください。

<img width="200"alt = "![Screenshot_20211104-173444_Original 2.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/a490434a-deb3-8d8f-8161-60275c063009.png> <img width="200"alt = "![Screenshot_20211104-173542_Original 2.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/185f1eee-14cd-0938-0d5e-dd7bfa0defed.png>


##3.同じWifiに接続する

当たり前ですが、同じWifiに接続していなければデバックも実行もできません。

端末とMacが同じWifiを使用していることを確認してください。

##4.接続リクエスト


接続リクエストの際にIPアドレスとポート番号が必要になります。
ワイヤレスデバックをタップするとIPアドレスとポート番号が表示されてるので、そちらを見てください。

<img width="200"alt = "![Screenshot_20211104-173542_Original.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/2df41c5a-009a-ebed-c20f-ebe7e4be97ea.png> <img width="200"alt = "![Screenshot_20211104-173849_Original.PNG]"src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/fea8925b-3ce1-b897-0964-6de69cd06e32.png>

IPアドレスとポート番号がわかったらターミナルを開いてコマンドを打っていきます。

最初にこちら。

    $ adb pair IPアドレス:port番号

次にこちら。

    $ adb connect IPアドレス:port番号

するとUSBを使っていないのにAndroid Studioで端末が表示されUSBコードなしでデバックができるようになります。

接続できているかどうかはこちらのコマンドで確認できますので、接続できているか確認したい方はこちらのコマンドをどうぞ。

    $ adb devices

##問題点

IPアドレスは変わらないのでいいんですが、ポート番号が変わってしまうことがありその度に再度接続し直さないといけないのが少し面倒だなと感じました。

とはいえ、コードだらけの中作業をするといったことを若干回避できるので、充電がない場合を除いてWifi経由でデバックしようと思います。
【自分用メモ】作業メモ

#自分用の独り言メモです
作業中にわからなかったことや学んだことの備忘録的に使う。


・すんごい便利だったもの
CodePen
https://codepen.io/
HTML、CSS、Javascriptが並行して書けてそのまま挙動まで確認できる。
他の人のサンプルもたくさんあるので、fork機能を使って丸パクリもできちゃう。


BootStrapというCSSのフレームワーク
↓リファレンスガイド
https://getbootstrap.jp/docs/4.2/getting-started/introduction/

これをCDNで宣言すれば大体のものがおしゃれになる。
自分のセンスより他人のセンスを信じろ。
もとはTwitter社が作ったものらしい。確かにボタンとかTwitter仕様っぽい気はした。

jQueryとかPopper.jsを入れておかないとうまく挙動？描画？できないものもあるっぽい。
結構読むだけでセンスいいページは作れそう。



・勉強：連想配列
複数要素でひとまとまりの配列を、複数列追加したい場合。（何言ってるかわからん）
教えてもらったこと。

↓配列の追加
this.OshiList.unshift({name:this.name,
                             contents:this.contents,
                             period:this.period,
                             point:this.point,
                             other:this.other});

↓こんな感じでv-for回すと表示できると思います
<tr v-for="item in OshiList">
     <td> {{ item.name }}</td>
     <td> {{ item.contents }}</td>
     <td> {{ item.period }}</td>
     <td>{{ item.point }}</td>
     <td>{{ item.other }}</td>
</tr>

OshiListの中のitemにあるnameをそれぞれとってくる、という感じになるのかな。

OshiList ・・・　item【[name][contents][period][point][other]】 これがひとまとまり
1個目のOshiListと2個目のOshiListはどうやって分けているのか？
よくわからん。Consoleから動きを確認してみよう。


#
パクって
勉強してみたいサンプル
これとかめっちゃおしゃれ。色んなエフェクト。
https://codepen.io/yuhomyan/pen/OJMejWJ

チェス。ロジックを勉強しなければ。
https://codepen.io/jakealbaugh/pen/JjRGQPY
【jQuery】form内でEnterキーを押すと次の要素にフォーカスさせる

ささっと作ってみた。

```javascript:.js
$('form input, form select').on("keypress", function (e) {
    if (e.key === "Enter") {
        let submit = false;
        let reverse = false;
        let nowinput = this;
        let inputs = $(this).closest('form').find('input:visible:not(input[readonly]), select:visible:not(input[readonly])');
        if (e.shiftKey) {
            reverse = true;
            inputs = $($(inputs).get().reverse());
        }
        inputs.each(function (index, input) {
            if (nowinput == input) {
                if (index < inputs.length - 1) {
                    $(inputs[index + 1]).focus();
                    return false;
                } else {
                    submit = true;
                    return false;
                }
            }
        });
        if (submit && !reverse) {
            return true;
        } else {
            return false;
        }
    }
});
```

動作としては以下の通り。

- フォーム内でEnterキーを押すと次の要素（input,select）にフォーカス
 - 次の要素がなかった場合はそのまま送信
- 非表示またはreadonlyになっているinputはフォーカス対象にならない
- Shiftキーを押しながらEnterキーを押すと逆順にフォーカス

## 留意点とか

- textareaに対応させてない
 - 気が向いたら対応させます
- Ctrl+Enterで一発送信させたいかも
 - こちらも気が向けば対応
cloudwatch logs の サブスクリプションフィルタ とは

## 勉強前イメージ

なんかのフィルタ？サブスクリプション？

## 調査

### cloudwatch logs の サブスクリプションフィルタ とは

cloudwatch logsのサブスクリプションフィルタとは
cloudwatch logsに出力されたログデータを特定の文字列を含むデータなどをリアルタイムに検知し、
kinesis や lambda などにログを転送できる機能になります。
サブスクリプションフィルタを使用すると、あるログを出力されていて「Error」が含まれると
lambdaからチャットなどに流すことができるようになります。

### どういう構成で使われる？

例えば以下のような構成で使われます。

1. あるログをずっと取得しています。
2. cloudwatch logs のサブスクリプションフィルタで error という文字列があれば
3. lambdaにログを送ります。
4. そのログからチャットに通知を行います。

![12021-11-04 # cloudwatch logs の サブスクリプションフィルタ とは - diagrams.net - Google Chrome 2021-11-04 17.31.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/b768fa49-3c32-6e77-5c27-e70a3949fd3c.png)

こちらでできることは、errorをslackを通知させることが出来ます。

## 勉強後イメージ

通知とかある特定のログの割り振りとかに使われるかんじかな？
一回やってみるのもありよね。

## 参考

- [CloudWatchLogsサブスクリプションフィルタの役割と設定方法について](https://bbh.bz/2019/09/16/how-to-subscription-filter/)
- [CloudWatch Logs を定期的にS3 へ転送する](https://oji-cloud.net/2021/08/04/post-6462/)
- [[アップデート] CloudWatch Logs のロググループに2つのサブスクリプションフィルタを設定できるようになりました！](https://dev.classmethod.jp/articles/cloudwatch-logs-supports-two-subscription-filters/)
自分用のリンクメモ

https://prtimes.jp/main/html/rd/p/000000003.000047683.html

https://boxil.jp/mag/a3028/?utm_source=google&utm_medium=cpc&utm_campaign=dsa-all&gclid=CjwKCAjwiY6MBhBqEiwARFSCPqoATdXdA4ilEzHAb1L6NKSxL4DVKgYURcXMFSfEClpcI_UdS1pXqxoCxfIQAvD_BwE
kintone REST API を 開発者ツールでちょこっと試す方法

kintone上で、kintone REST API をちょっとお手軽に試してみる小ネタです。

kintone REST API
https://developer.cybozu.io/hc/ja/articles/360028177472

# 開発者ツールを開く

こちらを参考にConsoleを表示しましょう。
※筆者PCは2021/11/4からWindows11です。
[Google Chrome 開発者ツールのTips集 -デバッグ効率化編-](https://developer.cybozu.io/hc/ja/articles/900000974626)

# kintone REST API を叩いてみる

たとえば [レコードの取得(GET)](https://developer.cybozu.io/hc/ja/articles/202331474) だと下のような感じに入力すると、

```js
kintone.api(kintone.api.url('/k/v1/record.json', true), 'GET', {app:【アプリID】, id:【レコード番号】},(resp)=>{console.log(resp)})
```

とってきたレコードの内容が表示されます。▶をクリックして開いて確認しましょう👀

```
▼{record: {…}}
 ▶record: {・・・省略・・・}
```

実際にやってみるとこんな感じになります↓👀

![2021-11-04_16h38_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/cac6b9eb-b2bc-4e8f-27d5-7c5c20ad8a7b.png)

## 他にも試してみる

こんな感じで試すことができます

```js
// レコード一括取得
kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', {app:【アプリID】},(resp)=>{console.log(resp)})

// コメント一括取得
kintone.api(kintone.api.url('/k/v1/record/comments.json', true), 'GET', {app:【アプリID】, record:【レコード番号】},(resp)=>{console.log(resp)})

// フォームの設定の取得
kintone.api(kintone.api.url('/k/v1/app/form/fields.json', true), 'GET', {app:【アプリID】},(resp)=>{console.log(resp)})

// アプリ情報の取得
kintone.api(kintone.api.url('/k/v1/app.json', true), 'GET', {id:【アプリID】},(resp)=>{console.log(resp)})

// アプリ情報の一括取得
kintone.api(kintone.api.url('/k/v1/apps.json', true), 'GET', {},(resp)=>{console.log(resp)})

```

1つ実行するごとにAPI使用回数が増えていきますが、
jsファイルに書き込む前にConsoleで一度試してみるのはオススメです。

ですが、PUTやPOST、DELETEは安易に試さないほうがいいかも💦💦