OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】ActionCable~役割について~

## はじめに
実装の流れは長くなるので省略させていただきます。
自分が疑問に思ってノートに記録した物を記事にしていきます。

## 前提条件
Ruby 2.6.3
Rails 6.1.5

## 記事の対象者
実装を終えたが、それぞれの役割について理解を深めたい人

## 実装の流れ
リアルタイム機能を持ったDM機能を実装するまでの主な流れです。
用語については、[Railsガイド](https://railsguides.jp/action_cable_overview.html)を参考にしてください。

**①サーバーサイド側のチャネルの処理を実装する
②クライアント側のチャネルの処理を実装する
③コネクションの設定ファイルに変更を加える
④データ保存後の処理をモデルに実装する
⑤ブロードキャストの処理を実装する
⑥表示するviewを実装する**

上記流れの中で、記述方法に注意が必要なものだけ説明します。


## ①サーバーサイド側のチャネルの処理を実装する

コンシューマーがこのチャネルのサブスクライバになると下記コードが呼び出される。
（コンシューマーとはクライアントのこと。）

```php:chat_room_channel.rb
 def subscribed
    stream_from "chat_room_channel"
 end
```

サーバー側のspeakアクションでは、クライアント側のspeakアクションから送られてきたデータを保存する。
下記の例（どの場所から、誰が、チャットメッセージを送ってきたか）

```php:chat_room_channel.rb
 def speak(data)
    ChatMessage.create!(
      content:,
      user_id:,
      chat_room_id:
    )
  end
```


## ②クライアント側のチャネルの処理を実装する
指定のチャネルでサブスクリプションを作成すると、コンシューマーがサブスクライバになる。
この処理の中に、サーバーからのデータの受け取り処理や、送る処理を実装する。
```php:chat_room_channel.js
appChatRoom = consumer.subscriptions.create("ChatRoomChannel",{});
```

他にも、チャットルームページだけで発火するように条件を加える。
例えば、下記の条件を加えることで、条件下のみspeakアクションが発火するようになる。
```php:chat_room_channel.js
(/chat_rooms/.test(location.pathname)) {
  $(document).on("keydown", ".chat-room__message-form_textarea", function(e) {
    if (e.key === "Enter") {
      appChatRoom.speak(e.target.value);
~~以下略~~
```

## ③コネクションの設定ファイルに変更を加える
chat_room_channel.rb ではcurrent_userを使うことができないため、current_userを使うためのコードを書く必要がある。
```php:connection.rb
private

      def find_verified_user
        self.current_user = env['warden'].user
      end
```


## ④データ保存後の処理をモデルに実装する
データ保存後にブロードキャストの処理を書いたファイルを呼び出す。
```php:chat_message.rb
 after_create_commit { ChatMessageBroadcastJob.perform_later self }
```

## まとめ
実装については記事を参考にすることで、行うことが可能です。
ただし、概念の理解はまだまだ必要だなと感じています。
特に難易度を上げている要因として、３つありました。

**・クライアント側の処理がJavaScriptであること
　　→JSの知識について学習が少なかったため、苦労した。
・通信方法の設定変更などが必要だったこと
　　→MVCの概念ではなく、Action cableとwebsocketの独自の通信ルールのため理解が難しい
・知らないメソッドが多くあったこと
　　→処理の流れだけでなく、メソッドも独自のものがあり、混乱する**

今回の実装を通して、まず、改めてJSの学習の強化していきたいと思いました。
Web処理ロジック

ウェブ処理ロジックはServlet→JSP→MVC→restAPIの順に発展した。

Servlet：htmlの処理においてurl mappingをクラス単位でするため、
　　　　数多くのクラスの作成が必要になる。
JSP：htmlの処理が簡単になったものの、
　　ビジネスロジックとViewが混ざっているなど、関心の分離にならない
MVC：関心ごとにコードの分離によって各自の役割も明確になり、メンテナンスが容易になった。
Blender 3.2 or later で Maya モードで Skinning(Armature)設定するメモ

## 背景

Blender で skinning つきデータの import/export したいので仕組みと基礎を知りたい.
Maya での経験はある!

## 情報

https://blender3d.biz/simpleanimation3dcg_deformed_armatures.html

ありがとうございます.
また, 探せば Youtube とかでいい解説動画あるかもしれません.

Blender 3.0 前か後かとか, Maya キーバインドかどうかで挙動変わりますので注意です!

## 基礎

Armature = ボーンです.
以下基本は用語として`ボーン`を使うことにします.

Maya キーバインドにしているものとします.

手順としては

* ボーンを作る
* メッシュにバインド
* ウェイト調整
* Pose mode で実際に skinning

となります.

### ボーンの作成

Layout view で Object mode(キー `4`)で Add -> Armature

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/48fddfab-e3ee-4881-b1ba-09e115c8809e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/9fe69da2-64ce-eec6-9c72-3ba775811140.png)

Maya と異なり, `+Z` 方向に生成されますので注意です(Maya は `+X` 方向).
また, 連続して Armature(ボーン) 生成というのはできません.

### ボーンを付け足す.

Edit mode(キー `1` )にして, ボーンの先端(tip)を選択して, `Ctrl + E`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/03e86f8e-d5b5-7047-fe39-1aab4409e6b0.png)

### ボーン tip は skinning では考慮されない?

Maya と異なり, tip (先のほう)を skinning 時に移動させるなどができませんので注意です! 手先などにボーンを仕込むときは, Maya の時に加えてボーンを追加で一つ足す感じがいいでしょうか.
(root 基準となる)

## メッシュへのバインド

Object mode(`4` キー)で メッシュを選択 + Shift でボーンを選択し, `p` キーで parenting.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/995b9e5a-3da6-0a32-f952-39f7b7b551b1.png)

With Automatic weights を選ぶのがよいでしょうか(たぶん Maya でのバインドと同じふるまい)

## Skinning の確認

Skinning(ボーンに応じてメッシュが変形する)は通常モードでは反映されず, Pose mode(`3` キー)にする必要があります!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/ab7fcf0a-65e4-95c3-d237-570b7939bddc.png)

また, Pose mode での移動は実際には回転のみです(Bone の移動はできない).
`Edit mode` でボーンの移動はできますが, このときは skinning は追随しないのでわかりにくいです(これが Blender では想定される動作なのかもしれませんが)

## ウェイトの設定

メッシュを選択して, `Weight Paint`(キー `7`)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/be1a96c9-cee8-d092-ab9b-35f14e887f7c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/84efe848-a5d3-462b-7bc5-324f9683c0f5.png)

対応するボーンを選択するには, 逆三角形のアイコンからボーンを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/765588cd-34c5-9b77-2b35-f202b8049abe.png)

もしくは Shift + left mouse でもいけます.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/57e3b002-e642-6b6c-d05f-aa14c728ca28.png)

## アニメーションの設定

`Pose mode` で設定して, `s` キーでキーフレームを打つ

skinning の反映は, `Object mode` と `Pose mode` で確認できます!
(`Edit mode` では反映されないっぽい)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ありがとう Blender skinning🤟 <a href="https://t.co/BTcuElaH8y">pic.twitter.com/BTcuElaH8y</a></p>&mdash; Syoyo Fujita 🌸 レイトラ ® 🐯 4 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1535300539734687745?ref_src=twsrc%5Etfw">June 10, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Voila!

## TODO

* [ ] Python で skinning データにアクセスする方法を探す(Skinning の import/export 用)
Your Ruby version is 2.6.3, but your Gemfile specified 2.7.1

## 概要

bundle installしたら「Your Ruby version is 2.6.3, but your Gemfile specified 2.7.1」エラーが出たので解決方法を書きました。
１人でも多くの人の役にたてればと思います。

## はじめに

### 使用する環境
- MacOS(Intel)
- Rails 6.0.3
- Ruby 2.6.3
- yarn 1.22.17
- Homebrew 3.5.0

## 状況
bundle installしたら上記エラーが出た。
エラー文はローカルの環境のrubyは2.6.3だけど、gemfileに記述されてるrubyは2.7.1になってるから合わせてねってこと

Rbenvでインストール可能なRubyのバージョンを確認
```
$ rbenv install -list
```
バージョンを指定してインストール
```
$ rbenv install 2.7.1
```
上記のrbenvでインストール可能欄に入ってなくても直接指定することでインストールすることが可能です。
 反映する
```
$ rbenv rehash
```
使用可能なRubyのバージョンを確認
```
$ rbenv versions
```
カレントディレクトリに反映
```
$ rbenv local 2.7.1
```

Rubyのバージョン変更されてるかを確認
```
$ rbenv versions

  system
  2.5.5
* 2.7.1 (set by /Users/user/cool/path/lockers/gitrepos/forms/.ruby-version)
```
再度bundle install
```
$ bundle install
```
タイトルと同じエラーが出る
gemfileの確認
```
$ gem environment
 2.6.3になっている

  - RUBYGEMS VERSION: 3.0.3
  - RUBY VERSION: 2.6.3 (2019-04-16 patchlevel 62) [universal.x86_64-darwin20]
  - INSTALLATION DIRECTORY: /Library/Ruby/Gems/2.6.0
  - USER INSTALLATION DIRECTORY: /Users/user/.gem/ruby/2.6.0
  - RUBY EXECUTABLE: /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby
  - GIT EXECUTABLE: /usr/local/bin/git
  - EXECUTABLE DIRECTORY: /usr/local/bin
  - SPEC CACHE DIRECTORY: /Users/user/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Library/Ruby/Site
  - RUBYGEMS PLATFORMS:
略
```

## 解決方法

なんでだろと思ってパスを確認すると
```
$ which gem
/usr/bin/gem
```
Rubyのパスを確認
```
$which ruby
/usr/bin/ruby
```

元々のMacに入ってるシステムで管理してるのでrbenvで管理するようにする

.zshrcファイルにパスを通す
```
$ echo '# rbenv' >> ~/.zshrc
$ echo 'export PATH=~/.rbenv/bin:$PATH' >> ~/.zshrc
$ echo 'eval "$(rbenv init -)"' >> ~/.zshrc
```
設定ファイルに反映
```
$ source ~/.zshrc  
```
再度確認
```
$ which ruby
/Users/user/.rbenv/shims/ruby
```
```
$ which gem
/Users/user/.rbenv/shims/gem
```
Rbenvで管理されるようになった
再度bundle install
動いた


# 最後に
rbenvで管理しないといけないことに気づかなくて時間が経ってしまった
改めてrubyの理解が深まった。
AWS Transcribeを使ってMP4ファイルに字幕を付けてみる

# はじめに
動画ファイルに半自動的に字幕をつける方法についてまとめる。

今回、文字起こしには「AWS Transcribe」を使った。12ヶ月限定の無料枠もあり、そうでなくてもそこまでの料金は設定されておらず、手軽に使える。
特に、SRTファイルを出力できるため、字幕作成にはとても有用なサービスとなっている。

https://aws.amazon.com/jp/transcribe/

また、動画に字幕を追加する作業は、ffmpegを使い、ローカル環境で実行する。

https://ffmpeg.org/

# 検証環境 (字幕追加作業用)
- MacBook Air (M1, 2020) macOS Monterey 12.4

# 手順
以下の流れで動画に字幕を追加する。

1. Speech-To-Textと字幕ファイルの生成
2. 字幕の修正
3. 動画に字幕を追加

## 1. Speech-To-Textと字幕ファイルの生成
動画 (MP4ファイル) に音声認識をかけて字幕ファイル (SRTファイル) を生成する。今回この文字起こしには前述の通り「AWS Transcribe」を使う。

まず、対象の動画ファイル (ここでは `input.mp4`) を適当なS3へ格納する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/577ddbd9-64d9-9dad-84c3-841fa3347ddd.png)

次に、AWS Transcribe から文字起こしを行う。

「Transcription job」を作成する。日本語音声のため、「Language」は「Japanese」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/2b0b8448-97b7-585c-b2a2-600085a280cf.png)

「Input data」で、先ほどS3へ格納したMP4ファイルを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/d4ddab44-ad60-2728-ea1f-777481ef9389.png)

「Output data」の「Subtitle file format」で、今回必要なSRTファイルが出力されるよう「SRT」にチェックを入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/5a2d664e-4798-783f-a921-1d5e7f2aeda4.png)

次ページのConfigure jobも含めその他は既定値のままで「Create job」をし、Jobをスタートさせる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/ef35ed04-3fba-181e-d208-e2fa356cec92.png)

完了すると、jobの画面で実行結果を確認できる。
また、「Transcription preview」で認識結果のテキストやSRTファイルのプレビューも可能。右上の「Download」からSRTファイルをダウンロードする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/555868ae-602f-d488-4c3f-88ea07437b06.png)

## 2. 字幕の修正
自動音声認識による字幕生成であるため、一部誤認識となった部分も含まれていることがある。
任意でSRTファイルを修正する。

## 3. 動画に字幕を追加
「ffmpeg」を使い、動画に字幕を追加する。

- 元とする動画ファイル `input.mp4`
- 字幕ファイル `srtSubtitles.srt`
- 字幕をつけた動画ファイル `output.mp4`

```bash
ffmpeg -i input.mp4 -i srtSubtitles.srt \
    -c copy -c:s mov_text \
    -metadata:s:s:0 language=jpn \
    output.mp4
```

# 再生
QuickTime Player等、字幕再生に対応している動画プレイヤーで再生すると、このように字幕を表示させることができる。

![字幕動画](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/1fe79de7-460b-ab99-9a82-1f9471d9022e.png)

# まとめ
AWS Transcribeとffmpegを使って字幕を追加する方法についてまとめた。音声認識の精度もそれなりに高く、このようにSRTファイルも出力できるため、字幕追加の作業がスムーズになった。
良いプログラミングをするには、適切な分離作業が必要（関心の分離）

日々発展する変化に対応可能な設計を考慮しなければならない。よくできているProgramだとしても必ず変更が起きる。開発の効率性を高め、メンテナンスにかかる時間を減らすため分離作業は必要になる。こういう分離のことを関心の分離という。

関心の分離：関心毎に処理を分けていくこと。Separation of Concerns、SoC。
　　　　　　関心を役割や機能別に適切に分けて、理解しやすくなるし、修正や変更もしやすくなる。
　　　　　　例えば、Codeを2種類（common code、uncommon code）にを分離することで
　　　　　　commonは再使用可能になり、uncommonの変更に対する影響も最小化できる。
　　　　　　MVCモデルが代表的な例だ。
PhoenixアプリをGitHub ActionsでGigalixirにデプロイする

本記事は下記スライドの追加記事です。
（スライド内のコードをテキストでコピペできるようにしたかった）

https://speakerdeck.com/nako_sleep_9h/piyopiyo-dot-ex-number-8-github-actionsdegigalixirnidepuroisuru

メインの内容はスライドを参照ください（´(ｪ)｀）

## GitHub Actionsのワークフロー記述

GIGALIXIR_EMAIL、GIGALIXIR_PASSWORD、GIGALIXIR_APP_NAMEはGitHubリポジトリのsecretsに登録する。

Gigalixirのデプロイについては [公式ドキュメント（Deployment & CI/CD）](https://gigalixir.readthedocs.io/en/latest/deploy.html)で例としてリンクされている、
https://gist.github.com/jesseshieh/7b231370874445592a40bf5ed6961460
を参考にしています。

```.github/workflows/deploy_to_gigalixir.yml
name: Deploy to Gigalixir
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - run: sudo pip install gigalixir --ignore-installed six
      - run: gigalixir login -e "${{ secrets.GIGALIXIR_EMAIL }}" -y -p "${{ secrets.GIGALIXIR_PASSWORD }}"
      - run: gigalixir git:remote ${{ secrets.GIGALIXIR_APP_NAME }}
      - run: git push -f gigalixir HEAD:refs/heads/main
      - run: gigalixir run mix ecto.migrate

```

git commitを忘れない。

```zsh
$ git add .github/workflows/deploy_to_gigalixir.yml
$ git commit -m "Set GitHub Action workflow"
```

## Gigalixirデプロイに必要な設定ファイル

elixir_buildpack.configにElixir、Erlangのバージョンに記載する。
バージョンは `elixir -v`で確認。

```zsh
echo "elixir_version=1.13.4" >> elixir_buildpack.config
echo "erlang_version=25.0" >> elixir_buildpack.config
```

phoenix_static_buildpack.configにnodeのバージョンを記載する。
バージョンは`node -v`で確認できる。

```zsh
echo "node_version=16.15.0" >> phoenix_static_buildpack.config
```

assets/package.jsonに下記を記載する。

```assets/package.json
{
  "scripts": {
    "deploy": "cd .. && mix assets.deploy && rm -f _build/esbuild*"
  }
}
```

git commitを忘れない。

```zsh
git add elixir_buildpack.config phoenix_static_buildpack.config assets/package.json
git commit -m "Set Elixir, Erlang, and Node version"

```

## いざGigalixirにデプロイ

git pushするとGigalixirへのデプロイが実行される。
GitHubリポジトリのActionsメニューから実行ステータス、ログが確認できる。

```zsh
git push
```

## 最後に

メインの内容はスライドにあるので、コピペしたい部分だけこちらに:bear:
【Xcode Cloud】FirebaseのプロジェクトをXcode Cloudで動かす時のGoogleService-Info.plistの立ち回り

# GoogleService-Info.plist ←曲者すぎん？
みなさんGoogleService-Info.plistってGitHubにアップロードしないと思うんですけど（安全性の観点から）、これだとXcode CloudでFirebaseのプロジェクトを実行できないわけですよ。
困ったな〜〜🤔
👮‍♀️「解決します」

# 環境変数を設定する
AppStoreConnectの「Xcode Cloud」のタブを開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/09feaa64-48a8-85d4-f4fa-62a02907f10f.png)

「ワークフローの管理」から、使用しているワークフローを選択します（今回は「Default」）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/0f135827-1aba-e37b-9e13-cdebc1a8d79e.png)
「環境」タブの「環境変数」の、「編集」ボタンを押します


「名前」をわかりやすい名前に設定します（例：GOOGLE_SERVICE_INFO）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/9a540927-88c0-3163-e469-8d87e1db5e74.png)

「値」の方にはGoogleService-Info.plistの中身をそのまま丸ごとコピペします

コピペの方法：GoogleService-Info.plistをお好きなエディタで開いてもらって、中身をそのままコピー・ペーストします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/29b890c6-4bd4-2513-93d7-e428dc2121f8.png)

シークレットにチェックを入れて、完了を押します

その後、画面右上の保存ボタンを押して（←←忘れがち）、環境変数の設定は完了です
![20220611-012133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/5bf258c4-7f13-50dc-7162-94bf5cf16f1e.png)

# Xcode Cloud上で実行するためのShellScriptを用意する
環境変数からGoogleService-Info.plistを生成するShellScriptを用意します
ファイルやディレクトリの位置や名前が重要なので、気をつけてください

.xcodeproj直下に「ci_scripts」という名前のフォルダを作成します
.xcodeprojを右クリック、「New Group」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/11dcbdc2-2f97-dcaf-5762-f4c4397f0439.png)

作成したフォルダを右クリック、「New File...」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/d29725ff-3237-80f8-c91d-c6d32ef3a320.png)

Shell Scriptを選択して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/ed414f15-1e8a-ff6e-2999-50d4216eba7c.png)

「ci_pre_xcodebuild.sh」という名前でファイルを作成します
この時、Targetsに何も選択しないように注意してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/c7c724df-ab66-8cc6-b23e-755c8ea15daf.png)

環境変数をもとにGoogleService-Info.plistを生成するコードを書きます
`#!/bin/sh` も忘れずに記入しましょう
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3534303137382f37373532333561302d383333652d643165362d666430612d6631303864623963326634632e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/46c352d8-5097-305f-6020-c05e521c54f9.png)

```shell:ci_pre_xcodebuild.sh
#!/bin/sh
echo $GOOGLE_SERVICE_INFO > ../ここにプロジェクトの名前/GoogleService-Info.plist
```

次に、このファイルの権限を変更します
ターミナルでプロジェクトファイルのディレクトリまで移動し、次のコマンドを実行します
```shell
chmod +x ci_pre_xcodebuild.sh
```


あとはこの変更をGitHubにpushして、Xcode Cloudを動かしましょう！うまくいけばうまくいくはず🤔


参考：https://developer.apple.com/documentation/xcode/xcode-cloud-workflow-reference#Custom-environment-variables
参考：https://developer.apple.com/documentation/xcode/writing-custom-build-scripts
MVCモデルとその流れ

MVCモデル：M、V、C で構成されているプログラミングモデル
 　　　　　　Model：データの制御を担当
  　　　　　　Controller：ロジックの処理を担当
  　　　　　　View：視覚的な要素を担当
   
ビジネスロジック（情報処理の流れ）
1.ClientがControllerにDataを要求する（入力）
2. ControllerはModelからデータを受け取る（処理）
3. 受け取ったDataに基づいてViewを更新（処理）
4. 更新されたViewをClientに見せる（出力）
Samsung Galaxyの機器においてアプリの不具合を解消する方法

# Samsungの独自UIの問題について

https://dontkillmyapp.com/

に書いてある通りですが、Samsungを筆頭としたAndroidのベンダーは独自のユーザーインターフェースを用いてバッテリーの消費を最適化しています。

それ自体に問題は(あまり)ないのです。
Androidがオープンソースである以上、Androidの開発者達は、AndroidというベースOSが意図しない動作を上書きする場合はそれについての透明性をできるだけ確保するように各自ベンダーに求めています。まぁ透明性についてはいろいろありますが、その一つには、「Androidがネイティブでサポートしていない根幹にかかわる機能は、設定から容易に切る事ができる事」が入っている事は(OSSの理念上)当然だと考えられます。

つまりここでの問題は、Sansungは他者の用にバッテリーの消費を最適化しているが、そのルーティンの中にバックグラウンドのアプリの強制停止、データ通信の強制停止、最近では(バグの可能性もありますが)フォアグラウンドアプリの強制停止など、本来カーネルが行うべき挙動を対象とした実装がなされていて、Samsungはそれ止めるための設定項目をはっきりとは用意していないという事です。

私がこの問題に気付いたのは、Spotifyのアプリで「再生中」のバーが何分かアプリを触っていないだけで突然消えるという不具合を経験してからでした。
それ以前から通知がこない、何日か触ってないアラームが週を跨いで機能しないなど「あれ」と思う事が色々ありましたが、Spotifyは良く使うのでさすがに我慢できなくなりかなり時間を費して調べました。

※これが発端です (身バレしそう...)

https://community.spotify.com/t5/Ongoing-Issues/Now-Playing-bar-missing-on-Android/idc-p/5391512/highlight/true#M126939

# ではどうすれば無効化できるのか

これは上に貼ったリンクの和訳となります。
当方海外にいるて、デバイスの基本設定が英語なので、設定項目の和訳が間違えているかもしれません。その時はコメントでおしえて下さい。また質問なども受付ています。

## レベル1
大抵の挙動はこれで解決します。

Android 12. UI ver. 4.1 で動作確認

 1. 設定アプリを開く
 2. アプリ→対象のアプリ→アプリが未使用の場合に権限を削除をオフにする
 3. (2.)の設定で、バッテリーをタップして制限無しを設定する
 
 4. 設定アプリのバッテリーとデバイスケアを選択
 5. バッテリーから省電力モードをオフに
 6. (5.)と同じメニューで、バックグラウンドでの仕様を制限をタップして、仕様していないアプリをスリープをオフに。
 7. (6.)と同じメニューでスリープ状態にしないアプリをタップして上の"+"を押して全てのアプリを追加する
 8. (5.)と同じメニューに戻り、その他のバッテリー設定を選択、バッテリーを最適化をオフに。バッテリー保護もオフに。
 
 9. (4.)と同じメニューに戻り上の"︙"を押して自動化を選択。その全てをオフに (毎日自動最適化、設定時刻に自動最起動、省電力を最適化)。
 10. (4.)と同じメニューで ︙の横の統計のアイコンを押す (.i|こんなやつ)。 一番下の自動最適化をオフにする。

 11. (4.) と同じメニューで、メモリーを選択、「除外するアプリ」で上の"+"をおして、全てのアプリをリストに追加

 12. (4.)と同じメニューでデバイスを保護をオフに。
 
 13. 設定アプリで、「便利な機能」を選択して、他のデバイスでアプリを続行をオンに(ここはしなくてもいいかも)
  
  14. 再起動 (https://www.galaxymobile.jp/support/mobile-devices/how-do-i-force-a-reboot-in-galaxy/)

## レベル2
レベル1では、短い楽曲などではおかしな挙動をしなくなりますが、
でもやっぱり長いPodCastなどを再生中に一時停止して他のアプリに移ってごちゃごちゃやると、戻った時にやはりアプリの挙動がおかしくなります。また、通信状態の悪い所で長時間バックグラウンドに放置をしたりするとやはり挙動が辺になります。

その場合は開発者向けオプションをさらにいじくらなければなりません。

 1. 開発者向けオプションを有効にする (詳しくはここなどを参考にして下さい https://atmarkit.itmedia.co.jp/ait/articles/1602/19/news044.html#:~:text=%EF%BC%BB%E9%96%8B%E7%99%BA%E8%80%85%E5%90%91%E3%81%91%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%BD%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC,%E3%81%9F%E3%82%89%E3%80%81%E8%A8%AD%E5%AE%9A%E3%81%AF%E5%AE%8C%E4%BA%86%E3%81%A0%E3%80%82)
 2. 開発者向けオプションで、「バックグラウンドの上限」をバックグラウンドプロセスを使用しないに設定する。
 3. ~~再起動 (https://www.galaxymobile.jp/support/mobile-devices/how-do-i-force-a-reboot-in-galaxy/)~~ 再起動をすると(2.)の設定が上書きされて元に戻ってしまいます!

これで多分解決します。私の場合は解決しました。

# おわりに
最後にこんな事を書くのはあれですが、上記の設定をすると、セキュリティに問題がでる可能性があります。なぜなら、プロセスの制限とセキュリティというのは表裏一体だからです。上の設定がSamsungによる設定のみを上書きする事をそれこそ神に祈るしかありません。

これのなにが卑怯かって、(意図的かはおいておいて、結果として)Samsungはデバイスのセキュリティーを盾にこれらの設定を容易に変更でいないようにしているように思えてならない所です。でもこればっかりは本当の所はどうかはわかりませんが、他のデバイスでは普通に機能するアプリが機能しなくなるのにはすごくイライラしますね。
wireitの利用例


## wireit

wireitは設定だけでscriptsの並列処理ができる事が魅力です。

### 例

```
  "scripts": {
    "vercel": "echo 1",
    "wrangler": "echo 2",
    "firebase_host": "echo 3"
  },
```
通常、↑の実行は次のように行っています↓
```
npm run vercel 
npm run wrangler
npm run firebase_host
```






wireitを利用したnpm script例にするとscript自体は冗長化しますが、
並行実行ができます。

```
  "scripts": {
    "build": "wireit",
    "vercel": "wireit",
    "wrangler": "wireit",
    "netlify": "wireit",
    "firebase_host": "wireit"
  },
  "wireit": {
    "build": {"command": "ls ", "dependencies":["vercel", "wrangler", "netlify", "firebase_host"]},
    "vercel": {"command": "echo 1"},
    "firebase_host" : {"echo 2"},
    "wrangler": {"command": "echo 3"},
    "netlify": {"command": "ls"}
  }
```


↑の実行は次↓のように行います。（４並列で動かしてみます）
```
export WIREIT_PARALLEL=4 
npm run build
```

パラレル実行ができることは魅力ですね
https://github.com/google/wireit#parallelism




#### 所感
npm scriptsへのwireit適応による嬉しさは、はGulpによりparallel実行がもたらされた時のちょっと嬉しい感覚に似ています。ただ、適応後のコードは少し冗長になるかもしれません。
Ktor+FlywayでherokuのDBをmigrationする

## 背景

Springを使っている場合、適切にファイルを配置すればFlywayのmigration scriptが自動で実行されるようです。
https://devcenter.heroku.com/articles/running-database-migrations-for-java-apps#running-flyway-automatically-with-spring

そうでない場合は、自動では実行されず、自前で設定する必要があるようです。
migrationを実行するスクリプトを用意して、Procfileに実行コマンドを追加すればOKです。


## 環境

- heroku20
    - JVMは16 (`system.properties`で設定)
- flyway 8.5.11
- kotlin 1.6.21

## サンプルの構成

```text
src/
　├ main/
　│　├ kotlin/
　│　│  └ migration/
　│　│    └ script.kt
　│　└ resources/
　│　   └ db/
　│　     └ migration/
　│　       └ V1__Initial.sql
　└ test/
```

## 手順

### migrationを実行するスクリプトを作る

`JDBC_DATABASE_URL` などは、DBが作成してあれば、herokuが自動で挿入してくれます。

```kotlin:script.kt
package migration

import org.flywaydb.core.Flyway

fun main() {
  val flyway =
      Flyway.configure()
          .dataSource(
              System.getenv("JDBC_DATABASE_URL"),
              System.getenv("JDBC_DATABASE_USERNAME"),
              System.getenv("JDBC_DATABASE_PASSWORD"))
          .load()
  flyway.migrate()
}
```

### Procfileにmigrationコマンドを追加

- `${プロジェクト名}`は適宜入れ替えてください
- 最後の引数は、`mainからのパス.クラス名` 

```:Procfile
release: java -cp .:build/classes/kotlin/main:build/install/${プロジェクト名}/lib/*:build/resources/main migration.ScriptKt
```

### デプロイして確認

デプロイ

```shell
git add .
git commit -m "add migration script"
git push heroku
```

psqlを実行して確認。

```shell
heroku pg:psql <database name> --app <app name>
```
大学院を中退するゴミが Twitter スペースを検索できるサービス作ったよ

# はじめに

どうも yoshii です。
普段はお酒を飲みながら趣味でアプリやサイトを作っています。

今回の記事は作ったものの宣伝でしかないです。

# 作ったもの

これです。
Twitterスペースを検索できるサイトです。
PCでログインしたらサジェスト表示もできます。

https://space-dig.vercel.app/

デザインは気に入ってますが、機能面は正直微妙です。
Twitter APIのスペースAPIの仕様がそこまで成熟してないからって感じだと思いますね。
キーワード検索とかなしで、全体から参加者上位のスペースを取得とかできたらよかったんですが。
結果的にとりあえず遊びの域を出なかった感じですね…

# 作成期間

2週間…

# 大変だったところ

ログインですね。
Twitter APIのOAuth 2.0のログインとログイン情報の保持の参考情報が少なすぎて大変でした。
トークンの有効期限が2時間で切れるので、リフレッシュする必要があったり、
モバイルだとリダイレクトURLにアクセスした時にTwitterアプリ開いてしまってうまくいかなかったりと、微妙な感じでした。

# 技術構成

- TypeScript
- Next.js
- Vercel

# 何がいけなかったか

Twitter APIの仕様かな、、

# まとめ

大したことないもの作るのに2週間もかけてしまって疲れました…
ちょっとでも見てくれたら嬉しいです。
「ここどうやって実装してるの？」とか言ってもらえれば、掘り下げて記事にしてみようかなとも思います。

あと、友達がいないのでTwitterで仲良くしてくれたら嬉しいです。
スペースもたまにやっています。

https://twitter.com/ganja_tuber

ではまた…
キャッシュサーバーとは

静的コンテンツのハードディスクからの読み出し、DBMSのデータ検索処理はリクエストの数が多くなるとサーバーの負荷が大きくなり、処理が遅くなってしまう。
そこで
更新の少ないコンテンツやデータであればリクエストに対するレスポンスを覚えていればサーバーやDBMSに負荷がかからないように```キャッシュサーバー```というプログラムを使う。

リクエストに対するレスポンスの記憶

レスポンスの種類によってキャッシュサーバーの種類が違う。
### コンテンツキャッシュ
文書、画像、動画のコンテンツのキャッシュ

### クエリキャッシュ
DBMSのデータ検索要求（クエリ）の結果のキャッシュ

# キャッシュの有効期限
データベースが更新されていく中でいつまでもキャッシュにある記憶ではずれが生じてしまう。そのためにキャッシュに対して```有効期限```を設定する。

# CDN（Contents Delivery Network)
```世界各地に分散```して配置されたキャッシュサーバーの集合体。
リクエストに対してアクセス元から```ネットワーク的に最も近い```サーバーに対応してもらうことで早くレスポンスを返せるようになっている。
データベース管理システム

３層アーキテクチャの中のデータ層にある。
Webアプケーションに蓄積されるデータはデータベースに書くのされる。
そのデータベースの管理をするのが```データベース管理システム(DBMS: Database Management System)```だ。
アプリケーションサーバーから命令をうける。
DBMSを搭載したサーバーを```一般```に```データベースサーバー(DBサーバー)```と呼ぶ。
データの量は多くなるとデータ検索の負荷が増えるため```メモリやCPUtといったサーバー機器の性能```、```ハードティスクの読み取り速度```が重要。
データを扱うために```データ消失```への対策も重要。

# 冗長化とデータの同期
データベースにとって保持するデータの保全に重要。
そのために冗長化構成になっている。
冗長化している機器同士のデータベースの内容をいかに最新の状態に同期させるかが重要。
## 冗長化の種類
### ミラーリング
更新命令を受けたプリンシパルDBMSが同時にミラーのデータベースの更新をする
正副の関係性はある。
### レプリケーション
```任意のタイミング```でマスタDBMSが更新履歴をスレーブDBMSに対して送る。
正副の関係性はある。
### シェアードディスク
共用の機器（データストレージ)をもち複数のDBMSから更新する。
```耐障害性の強い```機器を採用している。
正副の関係性はない。
UE5 AI作成メモ



# AI関連のAssetの関係性
ACharacter>AIController>BehaiviorTree>Blackboard

# 敵を見つける
PawnSencing,AIPerception

# 情報、データ
Blackboard

# Action（攻撃するなど、〇〇する、させる
GameplayAbility

# BehaviorTree
## 向き
Rotate to face BB entry

https://pafuhana1213.hatenablog.com/entry/2015/10/28/232832

## BTTask Blueprint Base
何かやらせたいときにAssetを追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/8d9bb873-b328-92f5-aa46-6965784a3f8f.png)
AssetとしてBTTaskBlueprintBaseを継承して作成
BT上で右クリックから追加ができる

## Selector
行動を選択する

## Sequence
順番に実行する

## 移動
Move To

## targetの選択

# Task,Decorator,Service?

# 何かやらせたいとき

* BTService Blueprint Baseを継承したBTSを作成
    * Blueprint Class → BTService Blueprint Baseを選択
* Selectorノードを作成してBTSをつける
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/fbebbbed-1343-8e93-e6b0-bd52525eae0a.png)
* EventNodeを追加
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/763d6d30-9b0a-8131-662d-c646c590725f.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/fd5cc963-04b2-4af9-b10a-e01ac37dc6bc.png)

    * このあたりからそれっぽいのを選択
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/9648e253-7f19-c884-66f9-d773d6210a03.png)
    * このあたりも使いやすそう
経済空間の組成理論　中央大学出版部　石川利治先生

```r

#p.144
#3.利潤最大化を目指す工場の立地と価格


#工場m1の位置(製品m1)
x1=10
y1=-2
p1=200 #工場渡し価格

#工場m2の位置(製品m2)
x2=-1
y2=-5
p2=100

#工場m3の位置(潤滑油)
x3=0
y3=-10
p3=50　#工場渡し価格

#工場m4の位置(製品の市場)
x4=0
y4=5　#工場渡し価格

#原料m1,m2の運賃率tm
tm=0.2


#潤滑油の運賃率te
te=0.1

#市場への運賃率
tg=0.01

#最大需要価格
a=2000

#生産関数のパラメータ
alpha=0.4
beta=0.4
A=1

#工場の固定費
f=0

YM=function(X,Y,P){
d1=sqrt((X-x1)^2+(Y-y1)^2)
d2=sqrt((X-x2)^2+(Y-y2)^2)
d3=sqrt((X-x3)^2+(Y-y3)^2)
d4=sqrt((X-x4)^2+(Y-y4)^2)
m1=(A^(-1.25))*((a-P)^(1.25))*sqrt((p2+tm*d2)/(p1+tm*d1))
m2=(A^(-1.25))*((a-P)^(1.25))*sqrt(1/((p2+tm*d2)/(p1+tm*d1)))
m3=a-P
ym=(a-P)*((P-tg*d4)-(p3+te*d3))-2*((a-P)^(1.25))*(A^(-1.25))*sqrt(p1+tm*d1)*sqrt(p2+tm*d2)-f
return(c(ym,m1,m2,m3))
}


#工場の位置
x=10
y=10
#製品の価格
p=20


h=0.001
eta=10^(-3)

while((x-x_pre)^2+(y-y_pre)^2+(p-p_pre)^2>0.1)({
x_pre=x
y_pre=y
p_pre=p
x=x+eta*(YM(x+h,y,p)[1]-YM(x,y,p)[1])/h
y=y+eta*(YM(x,y+h,p)[1]-YM(x,y,p)[1])/h
p=p+eta*(YM(x,y,p+h)[1]-YM(x,y,p)[1])/h
#print((x-x_pre)^2+(y-y_pre)^2+(p-p_pre)^2)
})

YM(x,y,p)

M1=YM(x,y,p)[2]
M2=YM(x,y,p)[3]
M3=YM(x,y,p)[4]

QS=A*(M1^alpha)*(M2^beta)

```

```r

#12.商品購入における多様性志向に関する分析

p=c(1,3,2,4,5)
C=30000
n=length(p)
sigma=0.2

#Broyden Quasi-Newton Algorithm p.213

f=function(XX){
lam=XX[1]
q=XX[-1]
dLq=(q^sigma/sum(q^sigma))^(1-1/sigma)-lam*p 
vec=c(C-sum(p*q),dLq)
return(vec)
}

X=c(2,rep(10,n))

ite=3*10^3
H=diag(f(X))
eta=10^(-2)

for(l in 1:ite){
X_pre=X  
X=abs(X-eta*H%*%f(X))
s=X-X_pre
y=f(X)-f(X_pre)
H=H+((s-H%*%y)/as.numeric(t(s)%*%H%*%y))%*%t(s)%*%H
print(sum(abs(f(X))))
}

#X[1]と一致
sum(Q*(Q^sigma/sum(Q^sigma))^(1-1/sigma))/C


```
solrにネットワーク経由でアクセス出来るようにする

過去バージョンのsolrを経験している場合、バージョン9.0で特にこれまで通りの手順でsolrを起動して
ネットワーク経由で管理画面にアクセスしようとするとアクセス出来ないことにまず驚かされ、焦りました。
（アップグレードノートにこの件については記載されており、予めきちんと読んでいればどういうことはないです…）

以下、ネットワーク経由でアクセスするための設定

# 対象バージョン
9.0～

# 設定方法
初期設定ではlocalhostからの接続のみ許可されています。
必要に応じて狭い値を設定するようにとコメントが記載されています。
```bash
# Sets the network interface the Solr binds to. To prevent administrators from
# accidentally exposing Solr more widely than intended, this defaults to 127.0.0.1.
# Administrators should think carefully about their deployment environment and
# set this value as narrowly as required before going to production. In
# environments where security is not a concern, 0.0.0.0 can be used to allow
# Solr to accept connections on all network interfaces.
#SOLR_JETTY_HOST="127.0.0.1"
```

サーバ側の設定などでセキュリティが担保されている場合は、「0.0.0.0」と設定することで
ネットワーク経由でアクセスを受け付けるようになります。
```bash
SOLR_JETTY_HOST="0.0.0.0"
```

## 参考
[Security Considerations](https://solr.apache.org/guide/solr/latest/deployment-guide/taking-solr-to-production.html#security-considerations)
[Major Changes in Solr 9](https://solr.apache.org/guide/solr/latest/upgrade-notes/major-changes-in-solr-9.html#security)
研修の全体像と進捗が確認できるアプリをGlideで作成！


![227647142.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670703/612e6be0-610f-b1f7-634c-5c6f52c2af08.jpeg)
こんにちは:blush:
スーパーマーケット事業で働く会社員です。
普段は教育の仕事をしています。

## 新入社員は大変なんです。

社会人になると社内研修ってたくさんありますよね。
特に新入社員向けの研修はどこの企業もけっこうな回数をやるのではないでしょうか？
とはいえ新入社員は業務を覚えるのに一生懸命です。
**「自身が参加する研修って何？」「次の研修って何回目だっけ？」
「今月受ける研修は連絡があったからわかるけど今後はどのくらいあるの？」**

こんな時に**いつでもどこでも研修の全体像がわかる**と嬉しいですよね。
会社のパソコン以外でも**自分のスマホで確認**できたら事前準備や気持ちの整理も
できるのでは・・・。
そんなアプリがあったらいいなぁ。
というわけで今回はアプリ作成ツール『**Glide**』に挑戦してみたいと思います。

## 使用ツール
**[Glide](https://www.glideapps.com/)**
　　⇒アプリ開発用のノーコードツールです。
スマホ
　　⇒作成後の確認用で使用します。
これだけです。


## まずは完成品です。

https://twitter.com/Maepon517/status/1535179172670472193

## 使用方法
『**Glide**』はアプリ作成にあたり一から作成もできますが、いくつかのテンプレートから作成もできます。
今回はテンプレートから『**Onboarding & Company Handbook**』を選び、中身を編集する形で作成しました。

最初に**Glide**を立ち上げます。下にスクロールして
`Start from a classic template` から右の`View all`をクリックします。

![スクリーンショット (107).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670703/b970eb87-99fa-024f-1dc9-aa64b43dcb57.png)

『**Onboarding & Company Handbook**』を選択

![スクリーンショット (108).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670703/bb39c916-decf-b540-360e-91f55ff4f835.png)

`Copy Template `を選択し、編集を始めます。
![スクリーンショット (109).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670703/7e67364f-0a58-c436-07d2-6d15aafcf6da.png)

左にある　`TABLES`　からシートを選択して中身の編集をしていきます。
今回は年間の研修を各セッションに分けます。

![スクリーンショット (103).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670703/4693a978-0fe3-482c-9344-c555576cf47e.png)

次に各セッションのカリキュラムをタスクに分け細分化します。
![スクリーンショット (104).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670703/faa4d80b-9534-5605-1b4e-da87eaf75da6.png)

他のシートも編集して、今回入れ込んだ機能は4つです。
**①研修の全体像を実施する順番で作成し見える化**
**②研修カリキュラムをタスクで細分化し、進捗確認ができる。**
**③同期の情報（店舗、部門、連絡先』もお互い共有できる。**
※個人情報のため記事には載せていません。
**④タイムスタンプ機能で進捗履歴が残せる。**

## 実際にさわってもらいました。
今回は試作品として同じ部署のメンバーにさわってもらいフィードバックをいただきました。

**同僚Kさん**
良い点:ok_woman:
* 全体像がわかるので研修前に予習もできそう。
* 手軽にスマホで確認できるのがいい。
* オンライン研修でも活用できそう。

改善点:no_good:
* 実施日・会場などの詳細もわかると良い。
* 同期の情報などの更新がタイムリーにできるとよい。

**同僚Hさん**
良い点:ok_woman:
* 研修の中身も確認できるのがいい。
* 手書きのサインとか【おもしろ要素】もいい感じ。

改善点:no_good:
* 業務において私用のスマホは良いのか？
* 提出物など会社のシステムとリンクできたら使いやすい。

他の方からのフィードバックも:blush:
* 英語が多くわかりづらい。
* 研修資料や動画も見れるとさらに良いかも。
* 質問なども共有できるといいですね。

フィードバックしていただいた皆さまありがとうございます。
一人で考えるより、実際に触れていただくと皆さまから様々なアイデア
が出てきて、ワクワクが止まらないですね:satisfied:
なんか使いやすいアプリになりそうな予感です。

## あとがき
今回社内PCにて作成しましたがセキュリティの問題で
スプレッドシートとの連携ができず、ブラウザ上で編集しているのが
難点でした。
連携できれば情報の更新やアプリ作成自体も楽にできそうです。
実装にあたり、まずは少人数で実施回数の少ない研修から
お試し運用してみたいと思います。
Azure Databricks でストレージをマウントする

## はじめに
Azure Databricks でストレージをマウントするには以下 2 つの方法が存在します。

* ストレージ アカウントのアクセス キーを使用する方法
* Azure Active Directory 資格情報パススルーを使用する方法

今回は両方の実装方法を説明します。

## ストレージ アカウントのアクセス キーを使用したマウント

### 1. ストレージ アカウントの用意
Azure Data Lake Storage Gen2 (ADLS Gen2) を作成し、確認用のファイルを格納しておきます。
![スクリーンショット 2022-06-10 23.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/d68ee3c6-d334-b959-9a11-f87049dfc715.png)

アクセス キーを確認しておきます。
![スクリーンショット 2022-06-10 23.12.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/f92e9a99-5d45-e983-201b-c53902c80068.png)


### 2. マウント処理
Databricks コンソールにて、以下のコードを実行します。
```python
storage_account = "<ストレージ アカウント>"
container = "<コンテナ>"
access_key = "<アクセス キー>"

dbutils.fs.mount(
  source = "wasbs://"+container+"@"+storage_account+".blob.core.windows.net",
  mount_point = "/mnt/data",
  extra_configs = {"fs.azure.account.key."+storage_account+".blob.core.windows.net": access_key}
)

display(dbutils.fs.ls("/mnt/data"))
```

ディレクトリ内容が表示されることを確認します。
![スクリーンショット 2022-06-10 23.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/d1debe34-f4a0-9c8e-9c0c-31be387b318e.png)


## Azure Active Directory 資格情報パススルーを使用したマウント

### 1. ストレージ アカウントの用意
先程と同様、Azure Data Lake Storage Gen2 (ADLS Gen2) を作成し、確認用のファイルを格納しておきます。
![スクリーンショット 2022-06-10 23.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/d68ee3c6-d334-b959-9a11-f87049dfc715.png)

Databricks で処理を行いたいユーザに [ストレージ BLOB データ所有者] の権限を与えておきます。
![スクリーンショット 2022-06-11 0.29.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/b2c1f4e1-1b83-3bb3-dfb6-a8b35f10c3b9.png)


### 2. Databricks クラスターの設定
Databricks コンソールのクラスター作成画面にて、[Enable credential passthrough for user-level data access] を有効化します。
[Cluster mode] が [Standard] のため、使用できるのは 1 人のユーザに限られます。
必要に応じて [Hight Concurrency] を選択しましょう。
![スクリーンショット 2022-06-10 23.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/17a99bbc-4e1e-8d40-5a12-cb57b78057ee.png)

### 3. マウント処理

Databricks コンソールにて、以下のコードを実行します。

```python
storage_account = "<ストレージ　アカウント>"
container = "<コンテナ>"
configs = {
  "fs.azure.account.auth.type": "CustomAccessToken",
  "fs.azure.account.custom.token.provider.class": spark.conf.get("spark.databricks.passthrough.adls.gen2.tokenProviderClassName")
}

dbutils.fs.mount(
  source = "abfss://"+container+"@"+storage_account+".dfs.core.windows.net/",
  mount_point = "/mnt/data",
  extra_configs = configs
)

display(dbutils.fs.ls("/mnt/data"))
```

ディレクトリ内容が表示されることを確認します。
![スクリーンショット 2022-06-11 0.24.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307853/c03f0176-e3d3-c805-0e95-0a2383e98e40.png)


## おわりに

Azure Databricks からストレージをマウントする方法について 2 種類説明しました。
ストレージ アカウントのアクセス キーは、シークレットのスコープにシークレットから取得すると安全性が増します。

## 参考

https://docs.microsoft.com/ja-jp/azure/databricks/data/data-sources/azure/azure-storage

https://docs.microsoft.com/ja-jp/azure/databricks/security/credential-passthrough/adls-passthrough
AWS CLI を利用してコスト配分タグをアクティブ化してみた

## 概要

「AWS コスト配分タグの API を発表」が公開されました.

> これまでは、コスト配分タグのアクティブ化と非アクティブ化は、[AWS 請求コンソール](https://aws.amazon.com/jp/aws-cost-management/aws-billing-console/)のコスト配分タグのページから行う必要がありました。今回のサポートにより、ListCostAllocationTags の API を使用して全てのタグを一覧表示し、UpdateCostAllocationTagsStatus の API を使用してコスト配分タグのアクティブ化と非アクティブ化できるようになりました。

コンソールを介さずに使用できるそうです

https://aws.amazon.com/jp/about-aws/whats-new/2022/06/aws-cost-allocation-tag-api/



## 環境

aws-cli/2.7.7 Python/3.9.11 Windows/10 exe/AMD64 prompt/off

※ 新しく追加されたAPIのため, 更新が必要そう

## 手順

1. 現状の設定を取得する

   ```shell
   aws ce list-cost-allocation-tags > before.json
   ```

2. 設定を更新する

   ```shell
   aws ce update-cost-allocation-tags-status --cost-allocation-tags-status TagKey={TAG_KEY},Status={Active|Inactive}
   ```

3. 設定が反映されたか確認する

   ```shell
   aws ce list-cost-allocation-tags > after.json
   ```

4. before.json と after.json を比較し, 意図した設定が反映されていることを確認する
FlutterアプリをAndroid端末にインストールする時にハマった内容メモ

## はじめに
久しぶりにFlutterアプリを開発してAndroidで実機確認しようとした際に、上手くビルドできずに時間がかかってしまった。時間が経つと細かいところ忘れてしまうので、メモとしてハマったポイントを残しておく。

## 環境
【PC】
　　MacBook Air (M1, 2020)

【各SWバージョン】
　・macOS Big Sur 11.6.1
　・Flutter 2.5.3　（dart 2.14.4）
　・Xcode 13.1

## メモ内容

Android実機にインストールするため`flutter build apk`を実行するがエラー

```terminal:
* What went wrong:
Execution failed for task ':app:checkReleaseAarMetadata'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
   > The minCompileSdk (31) specified in a]
・・・
```

SDKのバージョンが悪いとのことなので、以下を修正。

```gradle:android/app/build.gradle
android {
    compileSdkVersion 30  ←ここを適切なバージョンに変更！

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "**************"
        minSdkVersion 16  ←ここを適切なバージョンに変更！
        targetSdkVersion 30  ←ここを適切なバージョンに変更！
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}
```

再度`flutter build apk`を実行するが、またしてもエラー。今度のエラーメッセージは Kotlinのバージョンに問題があるらしい。

```terminal:
* What went wrong:
Execution failed for task ':app:compileReleaseKotlin'.
```

```gradle:android/build.gradle
buildscript {
    // ext.kotlin_version = '1.3.50'　コメントアウトして
    ext.kotlin_version = '1.4.32'  ←ここを適切なバージョンを追記！
    repositories {
        google()
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
```

上記を修正をしたら、一旦`flutter build apk`のコマンドよりビルドができたため、`flutter install -d [端末シリアル]` でインストールできた。
RDS(MySQL)からS3へのデータエクスポート


# 最終的な目標
AWS RDS(MySQL)のテーブル内のデータを、S3へエクスポートして、Athenaでクエリを投げられるようにしたい！

# 本記事で出来るようになること

AWS RDS(MySQL)のテーブル内のデータをS3へエクスポートする

## EC2サーバーを経由して、S3へエクスポートする方法

例)
ユーザー名：testuser
ホスト名：fugafuga
パスワード：hogehoge
DB：test_db
テーブル名：test_table

## mysqldump

```shell:mysqldumpでのエクスポート
# tsvでのエクスポート
$ mysqldump -utestuser -hfugafuga  -phogehoge --tab=/tmp test_db test_table > ./output/mysqldump_output.tsv

# csvでのエクスポート
$ mysqldump -utestuser -hfugafuga  -phogehoge --tab=/tmp --fields-terminated-by=, test_db test_table > ./output/mysqldump_output.csv

# whereで指定したい場合
$ mysqldump -utestuser -hfugafuga  -phogehoge --tab=/tmp test_db test_table --where 'userid >= 50' > ./output/mysqldump_output.tsv

```


参考)[mysqldumpまとめ](https://qiita.com/PlanetMeron/items/3a41e14607a65bc9b60c)
参考)[MySQLのデータをcsv,tsv形式でダンプする](https://qiita.com/d-dai/items/e56c2e5abf558328373f)

## mysqlコマンド

```shell:mysqlコマンドでのエクスポート
# tsvでのエクスポート
mysql -utestuser -hfugafuga  -phogehoge -D test_db -e "SELECT * from test_table;" > ./output/mysql_output.tsv

# csvでのエクスポート
mysql -utestuser -hfugafuga  -phogehoge -D test_db -e "SELECT * from test_table;" | sed -e 's/\t/,/g' > ./output/mysql_output.csv

```
## SELECT INTO OUTFILE

こちらはRDSに入ってからのコマンドになります。

```sql:SELECT INTO OUTFILEでのエクスポート
-- csvエクスポート
SELECT * FROM test_table
	INTO OUTFILE './output/select_into_outfile_output.csv'
		FIELDS TERMINATED BY ','
		OPTIONALLY ENCLOSED BY '"';

-- tsvエクスポート
SELECT * FROM test_table
　　INTO OUTFILE './output/select_into_outfile_output.tsv'
        FIELDS TERMINATED BY '\t';

```

## 上記の何かしらのやり方でファイルを出力した後、S3へ

```shell:S3へエクスポート
$ gzip output.tsv
$ aws s3 cp ./output.tsv.gz s3://hogehoge/yyyymm=202206/
```

# 直でS3へエクスポートする方法
## RDSのスナップショット→parquet形式でエクスポート

[こちらの大変丁寧に書かれてある記事](https://dev.classmethod.jp/articles/rds-snapshot-s3-export/)を参考にすれば、S3へ直でエクスポートすることができます。
(サボってすみません)


parquet形式でエクスポートできるのですが、csvなどのファイル形式よりもデータスキャン量が圧倒的に少ないのでおすすめです。

# おわりに

調べてみると意外と方法があるのだなぁと実感しました。
書かないと忘れるので、自分の備忘録として書いたつもりではおりますが、
どなたかの役に立てば幸いです。
プロダクトの成長指標としてNSMを設定・運用したときに起こしたしくじり

## この記事で伝えたいこと
* NSMは素晴らしい指標設計のフレームワークです
* ただし使い方を間違えれば宝の持ち腐れとなります
* 運用におけるしくじり体験談をここに記し、これからNSMを設定・運用する人には同じ轍を踏まないでもらえたらと思います
* 俺の屍を超えてゆけ


## NSMとは
以下の記事に詳細が記載されているため、この記事では割愛します。

https://qiita.com/getty104/items/54cba860dbc34eb99c70

上記記事を書いたプロダクトマネージャーがDevトークを掲載していますので、もし良かったら「話したい」をしてみてください！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/3

## NSMを設定した背景
担当している事業において、KGI-KPIの関係性で事業運営をしていたのですが、プロダクトと売上の関係性が示せていないと感じ、NSMに興味を持ち、実際に運用してみようと思ったのがきっかけです。

特に担当していた事業がセールス主導で売上を伸ばしていくというよりも、プロダクトが主導となって成長していく事業だったこともあり、設定したいという気持ちをさらに強くしました。それもあり、もっとプロダクト改善によって直接的である数値を定義しようと試みました。

（新しいもの好きでミーハー、よく言えば好奇心旺盛な性格だったことも大きな理由です。）

## 運用で起こしたしくじり
さて、今回は設定して良かったことに焦点を当てるのではなく、あえて設定した後の運用のしくじりに焦点を当てます。
実際に設定して運用してみて良かったことはたくさんあったのですが、これは避けたかったし避けられた…と思うことを2つ記載します。

#### 1. KPIが多すぎて注力するポイントを決めきれなかった
NSMは1つですが、KPIは「広がり」「深さ」「頻度」「効率」の4軸で設計します。
つまりKPIは最低でも4つ生まれます。さらに1つの軸で2つKPIを設定することもケースとしては存在するため、僕たちも例に漏れず2つ設定している軸が生まれました。

そうなってくると…そうです、KPIが大量に生まれます。
プロダクト改善にも関連した指標が生まれ、本質的な指標が作れた！と思いきや、全てのKPIが重要に見えてきます（重要業績評価指標だから当たり前ですが）。

ここでのしくじりは「確かに全て重要なんだけど、今は特にこれが重要！を決めて示すことができなかった。」これに尽きます。
いろんな指標が生まれてくるのですが、例えば4軸のうち「広がり」にこの1年間は力をかけます、と言ったような、事業状況を鑑みて、今どのKPIに重きを置くことが事業成長の最大化となるのかの選定ができていませんでした。

全てのKPIを伸ばそうと、プロダクト開発もあらゆるKPI成長に合わせてロードマップを設定することになり、いわば「薄く広く」開発することになっていきます。担当していた事業は新規事業だったこともあり、新規事業としては当たり前品質を担保しつつも、これだと言わんばかりの魅力的品質を作る、強みを1点集中でも作り出すことが成長に拍車をかけることになるのですが、これが全くもって出来なかった…。

その結果、当たり障りのないプロダクトが生まれ、KPIも成長しているんだけど、伸びが弱く、NSMも大幅な伸びがない、、、こんなことになってしまいました。

「KPIは4軸設定しても、力を入れるポイントは事業状況とリソースの状況を見て決定する」、つまり戦略を持たなければ成長にはつながらないことに気付かされました。

#### 2. NSM設定プロセスのドキュメントを残していなかった
NSMを設定して説明する、あるいは設定前に随時メンバーに進捗を共有したり、相談しながらNSMを作っていくと、今いるメンバーには納得度も生まれ理解度も高まります。

ただし、これから入社してくださるメンバーに対していきなり「これが追っている指標ね、よろしく」じゃ意味がわかりません。そもそもNSMとは？という方ももちろんいらっしゃいます。
だからこそ設定した結果だけでなく、プロセスを残すことが非常に重要になってきます。

にも関わらず試行錯誤した決定プロセスをドキュメントとして残していませんでした。
これが本当に困りました…。全く残していないことはなかったのですが、紆余曲折あって設定した肝心なポイントや、一部口頭で進めてしまったことをドキュメントとして残さずに歯抜けのものになっていました。

社内メンバーからも「そもそもどういう考えで設定したんだっけ？」といったような質問をもらうこともあります。今の常識を疑うことは重要ですが、立ち返る地点＝ゼロ地点をきちんと定義していなければそもそもが成立しません。

プロセスのドキュメントを残しておくことで、ミッションと目標と指標の整合性などを考えるときにも、例えば目標を修正した際に指標をどう再定義するのか、ゼロから作り直すのではなく、以前のこのポイントからスタートしよう、などと効率化することもできます。

結果だけではなく、プロセスをドキュメントとして残すことの必要性を痛感しました。

## まとめ
* KPIが多すぎて注力するポイントを決めきれなかった
    * KPIは4軸設定しても、力を入れるポイントは事業状況とリソースの状況を見て決定する
* NSM設定プロセスのドキュメントを残していなかった
    * 結果だけではなく、プロセスをドキュメントとして残す

NSMの設定・運用に限らないことだとは思いますが、新しい概念を取り入れるときは、特にこの2点を注意すると効果的に運用できると思います。
NSMを使ってプロダクトを、そして事業を成長させていきましょう！
Demonstrator Design of Functional Cluster Identity and Access Management, No.901, AUTOSAR 21-11 (331) AP

Demonstrator Design of Functional Cluster Identity and Access Management, No.901, 2021-11

https://www.autosar.org/fileadmin/standards/adaptive/20-11/AUTOSAR_EXP_FCDesignIdentityAndAccessManagement.pdf

R21-11, R22-11がダウンロードできない。

AUTOSAR R21-11記事一覧はこちら。

AUTOSAR 21-11,319文書読んだ。2022年6月初初旬にFO, AP, CP 全部到達。

https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR R21-11(0) 仕様ダウンロード一覧。単語帳。参考文献資料作成

https://qiita.com/kaizen_nagoya/items/9b3a1b9b8d1e8d7e288e

# 用語(terms)
no
## 英日
日本語は仮訳

T.B.D.

# 参考(reference)

Specification of Identity and Access Management, No.900, AUTOSAR 21-11 (20) AP

https://qiita.com/kaizen_nagoya/items/23eee760e9ce0a8b324f	

GTest/GMock 1.8.1

RapidJSON 1.1.0

BOOST 1.71.0

POCO C++ Libraries 1.9.0

# 文書履歴(document history)
ver. 0.01 初稿 20220610
マッチングアプリをDjango×Flutterで個人開発した話

# はじめに 

技術力向上を目的にマッチングアプリを開発してみましたのでご紹介します
本番リリースの予定は特にありませんが、ブラッシュアップしていつかリリースしてみたいです
また実装ナレッジも作成していますので、マッチングアプリを作りたい方は参考にしてください


## キャプチャ

以下のようなアプリとなっています

|ホーム画面|ログイン画面|自己プロフィール画面|ドロワー|プロフィール一覧|プロフィール詳細|メッセージ画面|
|---|---|---|---|---|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/0bcddace-1152-9f40-b01f-b7b4ea5aac34.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/2a714f04-3dab-9eec-2a63-7114fcbc9ba3.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/6dbdf70f-858a-dc33-ea56-8483f2c376f1.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/8e7dd5b4-7cc7-e606-0d8b-8f21502826c8.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/6b865222-a9c5-8909-8944-aeb1d549786a.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/7d8343b9-2495-c0fb-79fc-22a182d09eb2.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/18bf9386-64d2-e1a1-556e-817ea748ede3.png)|
||パスワードは表示非表示切り替え可能|登録・更新共通||異性のプロフィールを確認することができる|ハートを押すといいね|マッチングした人とのメッセージのやり取り|



# 作り方

実装ナレッジを全文15万文字で公開しています。
マッチングアプリを自作したいと思っている方は必見です。

https://shinseidaiki.hatenablog.com/entry/2025/03/31/142837



# 要件

MVPとしてリリース可能なマッチングアプリには以下の要件が最低限度必要だと考えました

- 児童でないことを確認することができる
- 自己プロフィールを編集して異性に公開することができる
- 異性のプロフィールを閲覧することが出来る
- 気に入った異性にいいねを送ることができる
- マッチングしたユーザーとメッセージのやり取りができる

なお児童に使わせてはいけないことに関しては法的に定められていることですので、マッチングアプリの制約事項としては必須のものとなります
本アプリではクレジット決済による年齢確認の実装を行いました

> 児童でないことの確認を済ませていない利用者に、インターネット異性紹介事業サイトを利用させた場合、行政処分の対象となります
利用させる前に、本法施行規則第5条に定められた、次に掲げるいずれかの方法を必ず実施し、年齢確認を行ってください。
イ
クレジットカードでの支払い等、児童が通常利用できない方法によって料金を支払う旨の同意を得ること。(注記1)
　
警視庁HPより


なお、法律的用語としてマッチングアプリは「インターネット異性紹介事業」という名前で定義されているようですので、各種法令の内容を調べる場合はこちらの用語で調べた方が検索しやすいかと思います


# 実装した機能

実際に実装した機能に関しては以下です

- アカウント登録機能（仮登録 → アクティベーション）
- ログイン機能（JWT）
- Email認証（Email経由での本人確認）
- クレジットカード決済機能（成人確認とアカウントのアクティベーション）
- 自己プロフィール編集機能
- 異性プロフィール一覧閲覧機能
- いいね・マッチング機能
- メッセージ機能


# 使用技術

【バックエンド】
Django (Django Rest Framework)

【フロントエンド】
Flutter 

【決済機能】
Stripe


# ER図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/4561a749-05dd-a33f-1723-d06fb076e192.png)


# 開発期間

ちょこちょことやっていたので、1年半程度かかりました
ちなみに元々はDjangoのみで作成を試みていたのですが、FlutterとDjangoの知識を半年ほど前にUdemyで習得してから作りなおしています


# 自慢したいポイント

自己満足で作ったアプリのため個人的にすごいと自慢したいところを列挙します

- 1人でフルスタック開発
- 開発需要が大いにあると思われるマッチングアプリの作り方のナレッジを残した
- FireBase以外のバックエンドを使ったFlutter開発について実装して、作り方も紹介している
- 決済機能を実装した


# 難しかったところ

ユーザー仮登録からのアクティベーションの実装に関しては、ブログの実例などが少なく調べるのに苦労しました
また今現在はUUIDでトークンを生成してそのトークンに一致するURLにアクセスするとユーザーをアクティベーションする実装になっていますが、果たしてこれがセキュリティ的に大丈夫なのかどうかが懸念事項ではあります


# 課題や反省点

- リリースしていないため不完全燃焼
- テストを実装していない
- Flutterの状態管理が最近はRiverpodになっているっぽいがそのトレンドを追えていなかった
- メッセージはリアルタイムに更新しないためWebSocketなどでリアルタイム通信を反映させたい
- UIを適当に作っているため作り込みたい（特にチャット画面）


# おわりに

Qiitaでよく見る個人開発記事を自分も書くことができて開発者の仲間入りができた感じがして個人的にうれしいです
今後も研鑽を続けて社会になにかインパクトを与えるプロダクトをいつか作ってみたいですね
Demonstrator Design of Functional Cluster Diagnostics, No.844, AUTOSAR 21-11 (328) AP

Demonstrator Design of Functional Cluster Diagnostics, No.844, 2021-11

https://researchmap.jp/multidatabases/multidatabase_contents/download/231120/7765c7366200e89c69bd9dc9687dff3f/26128?col_no=2&frame_id=576083

AUTOSAR R21-11記事一覧はこちら。

AUTOSAR 21-11,319文書読んだ。2022年6月初初旬にFO, AP, CP 全部到達。

https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR R21-11(0) 仕様ダウンロード一覧。単語帳。参考文献資料作成

https://qiita.com/kaizen_nagoya/items/9b3a1b9b8d1e8d7e288e

# 用語(terms)
|Interface| Deviations|
|:--|:--|
|DiagnosticProtocol CancelProtocol()| at least name change required. GenericUDSService Renaming still open.
|ServiceValidation Validate()| changes in parameters open according to new proposal required.
|ServiceValidation Confirmation()| changes in parameters open according to new proposal required.
|DataIdentifier Read()| PossibleApplicationErrors is still missing.
|DataIdentifier Write()| PossibleApplicationErrors is still missing.
|RoutineService Start()| MetaInfo parameter and PossibleApplicationErrors are still missing.
|RoutineService Stop()| MetaInfo parameter and PossibleApplicationErrors are still missing.
|RoutineService RequestResult()| MetaInfo parameter and Possible ApplicationErrors are still missing.
|DTCInformation |Implementation must be adapted to SWS.
|EnableCondition| Implementation must be adapted to SWS.
|OperationCycle |Implementation must be adapted to SWS.
|DTC| Implementation does not use three-byte values for the dtc Value_ field
|ReadDTCInformation| Uses 4byte dtcValue_ for responses instead of high, middle and low byte structure (see above)
|ReadDTCInformation|Uses 4byte DTC count instead of 2 byte as specified by UDS, cuts off the upper two bytes
|ReadDTCInformation |No support for "DTCStatusAvailabilityMask" as sp

## 英日
日本語は仮訳

T.B.D.

# 参考(reference)

Specification of Diagnostics, No.723, AUTOSAR 21-11 (6) AP

https://qiita.com/kaizen_nagoya/items/ed65d04518231c2df96d	

Boost 1.58.0

GTest/GMock 1.8.0

Code Coverage.cmake

# 文書履歴(document history)
ver. 0.01 初稿 20220610
ノンビン塾～エンジニアとしての成長記録4～

## ノンビン塾について
そもそもノンビン塾ってなに？
→[過去の記事参照](https://qiita.com/kenny_engineer/items/fc3a45ef2c123ce49495)

## 前回の課題提出
### テーマ
　130円の飲み物と160円の飲み物、この２種類しかない自動販売機で、
　お金を入れて飲み物が出てくるまでの動きをフローチャートで示す。
　※お金は小銭のみ！

### 回答
　実際にお金を入れるシーンを想像しながら作成してみた。
　※以下フローチャート内の赤文字はフィードバック
　![5.12_ケニー課題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627323/3ec68771-fee2-1881-ddee-ebcaa6e7d4a8.png)
　私が作ったフローチャートでは、
　おつりが自販機から出てきてから、飲み物がでてくる流れになってしまっている。
　「そうじゃない。実際は、飲み物が自販機からでてから、
　　おつりがチャリンチャリンと出てくる流れやんか！」
　と思いつつも、きれいに示せなかった。。

　ちなみに、ウッチーの作成したフローチャートも拝見したが、
　私と全く違うフローチャートができてて、すごく興味深かった。
### フィードバック（改善すべき点）
* 最初100円を2枚投入ってあるけど、コインって2枚同時には入れられないよね。
* おつりを自販機から出す処理と、最後に未処理の小銭を吐き出す処理がある。どちらかはいらない。
* 未処理の小銭があれば吐き出す処理は、分岐だよね。

## 今回の講義
【テーマ】
　実際にコードを書いてみるぞーー！！！
　前回作成した、閏年を計算するフローチャートをJavaScriptでかいてみよう。
　
【事前準備】
　・Kintoneの開発者ライセンス入手
　　⇒アプリ：プログラム練習作成
　・プラグイン追加：JSEdit for kintone
　・以下の画面（事前準備）
　　![スクリーンショット 2022-06-08 215937.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627323/dec95dc1-6420-81a9-b336-65f0dd8a5fb4.png)

１）まずは、フローチャートに沿って、書かないといけない事を一行ずつ「コメントで」メモしていく
```calc.js
(function() {
    'use strict';
    kintone.events.on(['app.record.create.submit','app.record.edit.submit'], function(event) {
      let str = '';
      let num = Number(event.record.年.value)
      //ここから～
      // 判断４で割り切れるかどうか？
      // 判断100で割り切れるかどうか？
      // 判断100で割り切れるが、400でも割り切れる
      //～ここまで
      event.record.結果.value = str;
      return event;
    });
  })();
```
２）コメントに沿って、条件分岐をかいていく
　`if(条件式){条件式が成り立った場合処理を実行}else{条件式が成り立たなければ処理を実行}`
```calc.js
//ここから～
// 判断４で割り切れるかどうか？
if (num%4 ===0){
  // 4で割り切れた
  // 判断100で割り切れるかどうか？
  if (num%100 ===0) {
    // 100で割り切れる 
    // 判断100で割り切れるが、400でも割り切れる
    if (num%400 ===0){
      // 100で割り切れるが、400でも割り切れる
      str = '閏年です'
    } else {
      // 100で割り切れるが、400で割り切れない 
      str = '平年です'
    }
  } else {
    // 100で割り切れない 
    str = '閏年です'
  }
} else {
  // 4で割り切れなかった
  str = '平年です'
}
//～ここまで
```

３）一度保存し、実際に機能するか確認
　①年のところに、2000を入力し、保存
![スクリーンショット 2022-06-10 231207.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627323/41cb59ab-ab1f-76a9-6350-9798ee9bbaa4.png)
　↑機能してるっぽい！？
　続いて他の年も入力してみる。
![スクリーンショット 2022-06-10 230930.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627323/aeff0d1a-d31a-0a55-0630-7308b5df5855.png)
　↑機能してるーーーーー！！

初めて何もない状態から実装したコードで、無事に機能した。

短いシンプルなコードだけど、無事に機能したということもあり、ただただ嬉しかった。

夜にキャッキャワイワイしながらこの日のノンビン塾は無事に終わった。

### 次回ノンビン塾までの課題
　閏年のコードを`elseif` を使って簡略化する


## 感想
今回の学び・気づきは、
* いきなりコードをかくのは、駆け出しの頃は絶対NG
* フローチャートに沿って、実装する内容をコメントで残してからコードをかいていく
* あとで見返して思ったが、ネストが深くなっており、読みにくかった。
→ネストが深く読みにくいと初めて実感した。←非常に重要な経験だと思う。
→今後スキルアップしていきながら、シンプルな見やすいコードを書くようにすればよい。