OmniAICreator/Qiita-1.07M huggingface dataset:
deviseのflashメッセージにbootstrapのアラートを適用

##環境
ruby 2.5.7
rails 5.2.3
**bootstrap導入済み**

![devise_flash2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619712/3ebd1943-df0c-805b-e7e9-323ba41d4cc1.gif)

##実装

#####①helperメソッドを定義
keyをbootstrapように置き換えていきます。
alert→warning , notice→success , error→danger

```ruby:app/helpers/devise_helper.rb
module DeviseHelper
  def bootstrap_alert(key)
    case key
    when "alert"
      "warning"
    when "notice"
      "success"
    when "error"
      "danger"
    end
  end
end
```

####②flashメッセージのテンプレートを作成
置き換えたkeyでclass名が変わるようにします。(３行目)
divタグの中はbootstrapのリファレンスを参照

```ruby:views/layouts/_flashes.html.erb
<% flash.each do |key, value| %>
  <div class="alert alert-<%= bootstrap_alert(key) %> alert-dismissible fade show">
    <span><%= value %></span>
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
<% end %>
```

####③application.html.erbで呼び出す
適当な場所で呼び出しましょう。

```ruby
<body>
  <%= render 'layouts/header' %>
  <%= render 'layouts/flashes' %>
  <%= yield %>
  <%= render 'layouts/footer'%>
</body>
```


参考
https://hachy.github.io/2019/10/15/flashes-with-devise-and-bootstrap.html

[bootstrap 4.3 alert](https://getbootstrap.jp/docs/4.5/components/alerts/)
UserDefaultってすっごくシンプル！？（追加と取得）

#UserDefaultの書込み
って本当は簡単なのかもしれない。と思い、簡略化して書いてみました。

```ruby:View1Controller.swift
import UIKit
class ViewController: UIViewController,UITextFieldDelegate {

    @IBOutlet weak var emailTextField: UITextField!
    var emailTextField = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        emailTextField.delegate = self
    }
    
    @IBAction func ButtonAction(_ sender: Any) 
        
        UserDefaults.standard.set(emailTextField.text, forKey: "userMail")

```
UserDefault.standard.set で保存（キー値はここでは"userMail"）
これだけ

#UserDefaultの取得も全然簡単！？

```ruby:View2Controller.swift
import UIKit
class View2Controller: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {

    @IBOutlet weak var acountEmail: UILabel!
    var userMail = String()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        userMail = UserDefaults.standard.object(forKey: "userMail") as! String
        acountEmail.text = userMail
    }
```

取得もこれだけ！
ちゃんと理解しようとせず、難しそうなもんだと決め付けていました。。
もちろん応用していこうと思うと、ここから複雑になってはいきますが苦手意識が少しでもなくなればなと思います！
ローカル環境をなるべく汚さずにNginxでBasic認証

# TL;DR

Dockerの`httpd`イメージを利用して`htpasswd`コマンドを実行し、得られた行をコピペしましょう

# やり方詳細

Basic認証をするには、`.htpasswd`ファイルを作成する必要があります。しかし、Nginxにはそのためのツールがついてきません。
かといって、そのためだけにApacheやそれ由来のツールをインストールするのは癪ですし、

一時的に特定のツールが使いたいということなので、Dockerの出番です。Apacheのイメージ、`httpd`を利用します。これには`htpasswd`コマンドがついてきます。次のようなコマンドで起動します。`--rm`をつけることで、セッションを閉じるとコンテナが破棄されるようになります。

```bash
docker run -it --rm httpd bash
```

セッションが起動したら、お待ちかね`htpasswd`コマンドを実行します。コマンド1回毎に生成されるのは1行なので、`-n`オプションをつけて標準出力に吐かせます。下のコマンドのどちらかを実行します。違いはパスワードを後から入力するか、引数として最初から渡すかの違いです。

```bash
htpasswd -n <ユーザ名>
htpasswd -nb <ユーザ名> <パスワード>
```


```
<ユーザ名>:<ハッシュ値>

```

のような行が出るのでコピーし、テキストエディタに貼り付けて保存します。Nginxでは`.htpasswd`以外の名前でも構いません。
また、最後の空行は無視して構いません。複数ユーザの認証を行う際には、

```
<ユーザ名1>:<ハッシュ値>
<ユーザ名2>:<ハッシュ値>
<ユーザ名3>:<ハッシュ値>
```

のように並べます。少なくともUbuntu 18.04付属のNginxでは強固なBCrypt(`-B`オプション)が使用不可なので注意してください。


後は`nginx.conf`や各サイトの設定ファイルの`location`節内に以下の2行

```
auth_basic "<Basic認証時のメッセージ>"
auth_basic_user_file "<.htpasswdファイルのパス>"
```

を追加します。Nginxのリロード(`nginx -s reload` or `systemctl reload nginx`)もお忘れなく。
ゼロから始めるLeetCode Day78 「206. Reverse Linked List」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day77「1502. Can Make Arithmetic Progression From Sequence」](https://qiita.com/KueharX/items/83bdea821a828b914c4e)

今はTop 100 Liked QuestionsのMediumを優先的に解いています。
Easyは全て解いたので気になる方は目次の方へどうぞ。

[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！

# 問題
[206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/)
難易度はEasy。

問題としては、与えられた単方向の連結リストをそのままひっくり返すというものです。

>Example:

>Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL


# 解法

とりあえずiterativeなものを。

```python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre,cur = None,head
        while cur != None:
            nex = cur.next
            cur.next = pre
            pre = cur
            cur = nex
        return pre
# Runtime: 44 ms, faster than 26.15% of Python3 online submissions for Reverse Linked List.
# Memory Usage: 15.3 MB, less than 67.33% of Python3 online submissions for Reverse Linked List.
```

`pre`,`cur`,`nex`という三つの変数を用意して一つ前、現在、一つ後の要素を保持してそれぞれ入れ替えていきます。
変数を用意してそれぞれの一時的な逃げ場所を作って上げるようなイメージで考えてみれば良いと思います。

ただ、これだとこの規模ならともかく、もっと変数が増えるようなケースだとなかなか処理の量が増えて書くのが面倒臭くなります。
やっぱり楽したいですよね。


では今度はstackを使ってみた解答です。

```python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head:
            return None
        
        stack = []
        
        while head.next:
            stack.append(head)
            head = head.next
            
        while stack:
            cur = stack.pop()
            cur.next.next = cur
            cur.next = None
            
        return head
# Runtime: 40 ms, faster than 46.28% of Python3 online submissions for Reverse Linked List.
# Memory Usage: 15.1 MB, less than 96.42% of Python3 online submissions for Reverse Linked List.
```

こちらですとゴチャゴチャせずに割とスッキリ書けるので僕はこちらの方が好きです。
それに少しですが、速度も改善されています。

二つの回答例を書いてみましたが、いかがでしょうか？

もっとこっちの方がスマートだし良くない？という意見をお持ちの方は是非コメントくださると嬉しいです。
jupyterをdocker-composeで起動2

# はじめに
[前回](https://qiita.com/va034600/items/9ceb36821a3a12a34b3a)は、jupyterのdockerイメージ(scipy-notebook)をベースにjupyter pluginも入れて、
docker-composeを使ってイメージの作成と起動しました。

今回は、dockerのpythonイメージをベースにjupyterとdjangoをインストールして、jupyterとdjangoのサーバを起動することを確認しました。

ソースは [github](https://github.com/va034600/python-jupyter-docker) にあげてあります。


# ディレクトリ構成

フォルダはdockerの配下にmainのDockerfileとjupyterのdockerファイルが存在し、
jupyterのdockerファイルはmainに依存して作成されます。
Pipfileとmain_projectはmain元となるプロジェクトになります。

```
└── docker
    ├── jupyter
        ├── .jupyter
            └── jupyter_notebook_config.py
        ├── Dockerfile
        └── docker-compose.yml
    └── main
        ├── Dockerfile
        └── docker-compose.yml
└── main_project/*
└── Pipfile
```

# ファイル

## docker/main/docker-compose.yml

buildするとmain-project という名前でイメージを作成します。

``` docker-compose.yml
version: '3'  
services:  
  main:
    image: main-project:1.0.0
    build:
      context: ../../
      dockerfile: ./docker/main/Dockerfile
    ports:  
      - "8000:8000"  
    volumes:  
      - ../../main_project:/usr/src/app/main_project
```

## docker/main/Dockerfile

元となるプロジェクトのdockerイメージのコードです。

``` Dockerfile
# jupyter lab      : 2.1.3
FROM python:3.6.8

WORKDIR /usr/src/app

RUN pip install --upgrade pip && pip install pipenv
COPY ./Pipfile /usr/src/app/Pipfile
RUN pipenv install --system --skip-lock

CMD python main_project/manage.py runserver 0.0.0.0:8000

EXPOSE 8000
```

## docker/jupyter/docker-compose.yml

``` docker-compose.yml
version: '3'  
services:  
  jupyter:  
    image: main-project-jupyter:1.0.0
    build:
      context: .
    ports:  
      - "8888:8888"  
      - "8000:8000"  
    volumes:  
      - ./.jupyter:/root/.jupyter
      - ./notebook:/usr/src/app/notebook
      - ../../main_project:/usr/src/app/main_project
```

## docker/jupyter/Dockerfile

上記で作成したmain-projectに依存してdockerイメージのコードを作成していきます。
djangoとjupyterの両方を起動します。

``` Dockerfile
FROM main-project:1.0.0

WORKDIR /usr/src/app

COPY .jupyter /usr/src/app/.jupyter

# jupyter
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install -y nodejs npm
RUN pip install jupyterlab
RUN jupyter labextension install \
  @lckr/jupyterlab_variableinspector \
  @krassowski/jupyterlab-lsp \
  @axlair/jupyterlab_vim
RUN pip install jupyter-lsp python-language-server[all]
RUN jupyter lab build

# library
RUN pip install pandas lxml html5lib beautifulsoup4 matplotlib

CMD python main_project/manage.py runserver 0.0.0.0:8000 & jupyter lab --allow-root

EXPOSE 8888
EXPOSE 8000
```

## docker/jupyter/jupyter_notebook_config.py
``` python
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.notebook_dir = './notebook'
c.NotebookApp.open_browser = False
c.NotebookApp.token = ''
```

# 起動
```
$ cd python-jupyter-docker/docker/main
$ docker-compose build
$ cd python-jupyter-docker/docker/jupyter
$ docker-compose up -d
```

# アクセス
jupyter
http://127.0.0.1:8888
django
http://127.0.0.1:8000

# 終わりに
既存のアプリにjupyterをくっつけるみたいな使い方をしました。
dev環境にjupyterを置くことで既存のアプリのライブラリを使いつつ使い捨てのコードを作成できるのではと思います。
1か月後の日付をkintoneの標準機能で計算

#1か月後の日付とは
##例1
日付
7月6日
↓
1か月後の日付
8月6日

##例2
ただし、月末などで1か月後の同じ日がない場合は、翌々月の1日とします。

日付
1月31日
↓
1か月後の日付
3月1日

##参考
[翌月末の日付をkintoneの標準機能で計算](https://qiita.com/t0ru/items/b917bc9e72ba214d821d "翌月末の日付をkintoneの標準機能で計算")

#考え方
##1.日付に31日をたす
kintoneでは日時や日付を秒単位で扱うため、計算式でも秒単位で指定します。
（日付+31*24*60*60）

##2.元の日(日付の年月日の「日」)＝後の日(1か月後の年月日の「日」)ならOK
日は、DATE_FORMAT(日付,"d","Etc/GMT")で求められます。

##3.元の日＜後の日なら、後の日＝元の日とする
月数が31日未満の4月など、4月10日の31日後が5月11日になるので、
（11日-10日）*24*60*60を後の日から差し引いて、5月10日にします。

##4.元の日＞後の日なら、後の日＝1とする
月末の31日後が翌々月になる1月など、1月31日の31日後が3月3日になるので、
（3日-1日）*24*60*60を後の日から差し引いて、3月1日にします。

※計算式のIF関数をシンプルにするために、先に上記4の条件式で判定して、
満たさない場合に上記3の計算をし、上記2も兼ねます（同じ日なら0を差し引くことになるので）。

#kintoneのアプリ
※フィールドコードはフィールド名と同じにします。
##完成イメージ
![翌月の同じ日.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152073/1593e5fd-76ca-cb3b-c668-0210c516ad94.gif)
##元の日付
・日付 [日付フィールド]
##計算用
・日1 [計算フィールド]
　計算式 : `DATE_FORMAT(日付,"d","Etc/GMT")`
　表示形式 : 数値

・日付2 [計算フィールド]
　計算式 : `日付+31*24*60*60`
　表示形式 : 日付

・日2 [計算フィールド]
　計算式 : `DATE_FORMAT(日付2,"d","Etc/GMT")`
　表示形式 : 数値
##1か月後の日付
・翌月の同じ日 [計算フィールド]
　計算式 : `IF(日1>日2,日付2-(日2-1)*24*60*60,日付2-(日2-日1)*24*60*60)`
　表示形式 : 日付
【解決済み】今更ながら rails + wercker + codecov をやってみたが上手くいかない

# 解決しました
少し間が空いたので改めて色々と試してみた結果、プログラム側の問題でした（2021/2/13）。

```ruby
# 某所のサーバが古く、標準 cipher だと接続できない
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] = "DES-CBC3-SHA"
```

このコードが悪さをして  [codecov](https://codecov.io/) への接続に支障が出ていたため、これを以下のように修正し、結果が反映されるようになりました。

```ruby
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] = "ALL"
```

※ ALL は宜しくないですが、イントラネットで動かしているシステムなので許容することとしました。

また以下のコードは codecov の gem を使う場合は不要でした。

```yaml:wercker.yml抜粋
       - script:
           name: post coverage to codecov
           code: |
               bash <(curl -s https://codecov.io/bash) -t $CODECOV_TOKEN
```


# はじめに

rails + wercker は数年やっていたのですが [codecov](https://codecov.io/) を知らなかったので連携してみた（けど上手くいかない）、というだけの記事です。

# 環境

- Rails 5.2.4 系
- SimpleCov 0.18.5
- SimpleCov-Html 0.12.2
- CodeCov 0.1.17

注： Rails 以外の gem のバージョンは 2020/7 現在の最新だと思います。

# 設定

変更したファイルは 2つだけ。

- Gemfile
- test/test_helper.rb

```Ruby:Gemfile抜粋
# テスト環境 限定
group :test do
  gem 'codecov', :require => false
（以下省略）
end
```

```Ruby:test/test_helper.rb抜粋
require 'simplecov'
SimpleCov.start 'rails'

if ENV['WERCKER'] == 'true'
  require 'codecov'
  SimpleCov.formatter = SimpleCov::Formatter::Codecov
end
```

あ、設定ファイルも対象か。

```Ruby:codecov.yml
# cf. https://qiita.com/kent-hamaguchi/items/d4d3696a34350fd97991
codecov:
  notify:
    require_ci_to_pass: yes

coverage:
  status:
    project:
      default:
        target: 95%
        threshold: 1%
```

# ポイントだと思ったところ

適当にググって始めたのが良くなかったのですが、最初は ```wercker.yml``` に以下のような記述だけ入れていました。

```yaml:wercker.yml抜粋
       - script:
           name: post coverage to codecov
           code: |
               bash <(curl -s https://codecov.io/bash) -t $CODECOV_TOKEN
```

が、上手く行かないのでドキュメントを見ていたら [Supported Languages](https://docs.codecov.io/docs/supported-languages) から [Codecov Ruby Example](https://github.com/codecov/example-ruby) へたどり着けました。

# ...が、上手くいかない

これで手元では動くのですが wercker で実際に回してみると **SSL_CTX_set_cipher_list: no cipher match** のエラーで止まってしまいます。何故？

```bash

  _____          _
 / ____|        | |
| |     ___   __| | ___  ___ _____   __
| |    / _ \ / _\` |/ _ \/ __/ _ \ \ / /
| |___| (_) | (_| |  __/ (_| (_) \ V /
 \_____\___/ \__,_|\___|\___\___/ \_/
                               Ruby-0.1.17
==> Wercker CI detected
x> No CI provider detected.
/upload/v1?token=secret&flags&service=wercker&branch=fix_1061&build=1594041715&slug=bsdmad%2Fmiyabi&commit=c3030c15474859c1fa0046e113fe979d10851864
    -> Pinging Codecov
Error uploading coverage reports to Codecov. Sorry
SSL_CTX_set_cipher_list: no cipher match
```

使っている docker image が [Docker Official image(ruby 2.6.6)](https://hub.docker.com/_/ruby/)  なので、そっちの問題かな…

# 参考にした記事

上手くいってないのに参考にしたと書くと語弊がありそうですが、上手く行かないのはあくまで私の問題です。ご了承下さい。

- https://qiita.com/nicchi__1985/items/8c3b65b054cb483c35cb
オブジェクト・クラス・インスタンスの勉強

#はじめに
クラス・インスタンス・オブジェクトの概念について復習しました。

#オブジェクトとは？
オブジェクトとは、関連する変数（値）とメソッド（動作）をまとめたものに名前を付けたものになります。
JavaScriptであれば、

```
const person = {
 name: 'Yuki',
 gender: '男性'
};
```
という形でオブジェクトの中にkeyとvalueをセットします。
ここで述べているkeyはnameとgenderを指し、valueはYukiと男性を指します。

#クラスとは？
クラスとは、オブジェクトの設計図になります。
クラスの中で変数やメソッドを定義し、関連する変数やメソッドはこの時点で決まります。

日本語を例にクラスを作ると、

```
スライムクラス

＊スライムの状態
・color（スライムの色）
・level（スライムのレベル）

＊スライムの機能
・attack（攻撃）
・defend（防御）
```
という感じで、スライムのクラス（設計図）の中に変数とメソッドを定義しています。
これがクラスと呼ばれるものです。

#インスタンスとは？
インスタンスとは、オブジェクトの実物であり、クラス（設計図）から生成されるものになります。

先ほど作ったスライムクラスからインスタンスを生成すると、

```
＊スライムクラスのインスタンス（その１）
色：青、レベル：１、攻撃：１、防御：１

＊スライムクラスのインスタンス（その２）
色：黄色、レベル：２、攻撃：２、防御：２
```
という感じです。
これが、１つ１つのスライムがクラスから作られたインスタンスに当たります。

#最後に
クラスやインスタンスのような概念はどこで役に立つかが分からない知識を他人に分かりやすく説明することが難しいと気付かされました。
明日も頑張ります。
Visual Studio CodeでFlutterのIconのサンプルイメージを表示する備忘録

Flutterでアイコンを表示させたいときに、アイコン候補のサンプルイメージも同時に表示されるが、私のVisual Codeは言うことを聞いてくれなかったため、どうすれば解決できるのか調べたので、そのログを残す目的で書きます。

前提
・Visual Studio Codeを利用している。
・Flutterの拡張機能をインストールしている。


Icons.で候補が表示されるが、下の画像のようにサンプルイメージは表示されない。

<img width="824" alt="スクリーンショット 2020-07-06 22.36.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204100/6672ffb9-cc96-119a-0308-009681f15167.png">

画像をよく見るとIcon...>と表示されている部分があるので、そこをクリックする。
（そもそもここが表示されていない場合は、該当箇所までマウスカーソルを持ってくると表示される。）

<img width="825" alt="スクリーンショット 2020-07-06 22.36.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204100/80aa1bf4-51fc-40a7-0450-7f6ed6b55238.png">

するとサンプルイメージが表示される。
非常に簡単ですね。
ConfluenceのPython APIでページ作成＆ページ移動してみた

# やりたいこと

Confluence（以下、コンフル）を使って会議の議事録などを取っていると、
下図のようにタイトルに日付がついたページがいくつも作成されることがあります。
ここでは、Python APIを使って、タイトルが「202006」ではじまるページをとあるページの下に移動させてみます。

![move_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329888/789c5825-aa3a-4d18-ad93-b320d48cc84d.png)

# 環境

### Confluence

https://www.atlassian.com/ja/software/confluence
今回はクラウド版の無料トライアルを利用します。
申し込みの方法などは省略します。
以下コンフルの画面は2020年7月5日時点のものになります。

### Python実行環境

```
$sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G13035
```

```
$python3 --version
Python 3.7.4
```

# 準備

## APIトークンの発行

最初にConfluenceをプログラムから使用するため、APIトークンを発行します。
コンフルにログイン後、ブラウザの右上にある自分のアイコンマークをクリックし、Settingsを表示します。

![api_settings_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329888/8f18793f-3b28-107a-1792-3776884e61c6.png)

下図にあるように、Passwordをクリック。

![api_settings_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329888/b8385a9e-5171-19ef-910f-99e8701d6bf2.png)

下図にあるようにAPI tokenの段落にある「Create and manage API tokens」をクリック。
遷移先の画面でAPIトークンを作成します。
トークン作成時に表示される文字列をあとで使用するので、どこかに保存しておきます。

![api_settings_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329888/5e4b24f5-8675-cf00-b9ee-fb295c02e6fc.png)

## ライブラリのインストール

Python APIのページ（ https://pypi.org/project/atlassian-python-api/ ）にあるように、``pip``でインストールします。
特にエラーもなくインストールできました。

```
pip install atlassian-python-api
```

# PythonによるAPI操作

上記のPython APIのページにもAPIを紹介しているDocumentページが分かりにくいため、
Githubのページ（ https://github.com/atlassian-api/atlassian-python-api )を参照して、以下のプログラムを作りました。

```move.py
from atlassian import Confluence

if __name__ == '__main__':

    space = "TESTSPACE0"
    parent_page_id = 33023 # "[テスト] ページ移動" ページのID
    archive_page_title = '202006_会議A'

    target_str = '202006'

    # Auth
    confluence = Confluence(
        url='https://XXXX.atlassian.net',
        username=<username / mail address>,
        password=<API Token>)

    # Create archive page
    confluence.create_page(space, archive_page_title, '', parent_page_id)
    archive_page_id = confluence.get_page_id( space, archive_page_title )

    # Get page list & move 
    for i_page in confluence.get_child_pages(parent_page_id):
        if target_str in i_page['title'] and i_page['id'] != archive_page_id:
            confluence.move_page( space, i_page['id'], archive_page_id )

```

ここでは、実行している内容は次の通りです。

1. コンフルインスタンスを作成。URLはコンフルページのURLを参照。ユーザネームとAPIトークンを引数に渡します。
2. コンフル上の「[テスト] ページ移動」のページ配下に「202006_会議A」というページを作成し、ページIDを取得
3. 「[テスト] ページ移動」以下にあるページに対して、「202006」という文字列を含むページ（1.で作成したページを除く）は直前に作成したページ以下に移動

これを``python move.py``と実行します。
その結果、下図のように「202006」を含むページをまとめて移動することができました。

![move_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329888/3c99f78b-abfb-fd01-f5b0-e018d99d711f.png)

# まとめ

Python APIを使って、コンフルのページをまとめて移動してみました。
設定方法やプログラムの書き方ももっとうまくかけると思います。
プログラム内容をもう少し変更して、定期実行するようにすればコンフルページの整理が自動化できる...はず
Ruby学習要点(基礎)

- 文字列はクォーテーション（ ' もしくは " ）で囲う。また、クォーテーションは必ず半角で記述する。

- putsの後には半角スペースをあける必要がある。

- コメントアウトは「#」を行の先頭に記述
※複数行のコメントアウト
mac：「command + /」
windows：「ctlr + /」

- 変数を使うのは、必ず変数を定義（変数名 = 値）した後でなければならない。（プログラムが上から順に実行されるため）

- 変数名は自由に決めることができるが、Rubyではいくつか命名のルールがある。特に、2語以上を組み合わせた変数名をつけるときは、アンダーバー（_）を用いる。

- 変数の値を文字列の中に含める方法がある。文字列の中で、#{変数名}とすることで、変数を代入している値に置き換えて、文字列に含めることができる。これを「変数展開」と呼ぶ。

- ダブルクォーテーションを使った文字列の場合しか変数展開はされない。シングルクォーテーションの場合は変数展開が行われず、そのまま文字列として出力されてしまうので注意する。

- 配列も1つの値なので、変数に代入することができる。配列を代入する変数名は慣習上、複数形にすることが多い。

- 繰り返し処理には、each文を使う。each文を使うと、配列の要素を順番に取り出して処理を行うことができる。each文は、「配列.each do |変数名|」と書き、「end」までの間に実行したい処理を書く。
each文は配列の要素の数だけ繰り返し処理を行う。「|」で囲まれた変数に配列の要素が1つずつ入っていき、その上でeach文の中の処理が実行されていく。each文内の変数名（name）は好きな名前をつけられるが、配列の変数名（names）の単数形にすることが慣習上多い。

- それぞれの変数の使用できる範囲のことをスコープと呼ぶ。

- ハッシュは以下の図のように、キーの部分を文字列ではなく、先頭にコロン「:」を付けた書き方をすることもできる。この「:name」という書き方をシンボルと言う。シンボルとは、文字を「"」や「'」で囲む代わりに、先頭に「:」をつけた書き方をいう。文字列とシンボルは厳密には異なるが、基本的には同じように使用することができる。

- ハッシュのキーにシンボルを用いるときには、省略した書き方をすることができる。具体的には「:key =>」を「key:」というように省略することができる。省略した書き方の場合でも、あくまでキーはシンボルなので、要素を取得する場合には puts user[:name] のようにシンボルを用いる必要がある。

- インスタンスメソッド内で、「self」はそのインスタンス自身を指す。

- メソッドを呼び出すには明示的なレシーバが必要になる。クラスメソッドの場合はレシーバとしてselfが指定されている。

- 各インスタンスで値が固有：インスタンス変数
  各インスタンスで値が共通：クラス変数
Azure VMをVS Code Remote Containers開発環境として使う

# はじめに
最近はもっぱらVS Code Remote Containersを開発環境として使っています。が、のっぴきならない事情でローカルマシンにDockerが入れられず使えない、という場合もあると思います[^1]。

そういう場合に、WindowsのAzure Virtual MachinesにHyper-VとDocker Desktop for Windowsをインストールし、開発環境として使ってみたいと思います。


構成は以下の通りです。ローカルPCはRDP接続元としてしか使わず、Azure上のWindows 10上ですべて開発をする構成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227999/5c852fdc-e60d-eb3c-1794-102c5e59e695.png)

※開発環境自体はリモートにあったとしても、VSCode Remote Containersを使用するにはローカルにもDockerを入れる必要があります

# Azure VMでDockerは動くのか？
Azureの一部のVMは、「ネストされた仮想化」をサポートしています。
これにより、Azure VM上でHyper-Vを有効化しDocker Desktop for Windowsを動かすことが可能です。

参考：[Nested Virtualization in Azure | Azure Blog and Updates | Microsoft Azure](https://azure.microsoft.com/en-us/blog/nested-virtualization-in-azure/)


ちなみに、AWSはおそらく不可です。Hyper-Vを有効にできませんし、そもそもWindows 10のVMを作成できません。Windows ServerにはDocker Desktop for Windowsをインストールできないので、VS Code Remote Containersが使えません。

# Windows10 VMの作成方法
Azureポータルから以下の順で選択していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227999/49b0ed2a-50a2-32de-409c-e9107c87fb0f.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227999/f52553a3-2391-e6c8-e769-b28bc92145e1.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227999/57981f80-804c-1d21-d53d-d26e6866809a.png)

Windows 10のイメージを選択してください。

また、サイズは以下の***が付いているものから選択してください。
参考：[Azure コンピューティング ユニットの概要 - Azure Virtual Machines | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/virtual-machines/acu)


## 注意点
ネストされた仮想化未対応のVMでは、Docker Desktop for Windowsが以下のようなエラーを吐いて起動できません。

```
Docker.Core.HttpBadResponseException:
Unhandled exception: シーケンスに要素が含まれていません
```

対応VMは結構お高くつくので、私は毎日定時に自動でシャットダウン＋グローバルIP固定設定にしています。


# 試してみる
作成したVMにVS CodeとDocker Desktop for Windowsをインストールし、諸々の設定を行います。

詳細は以下を参照お願いします。
参考：[Developing inside a Container using Visual Studio Code Remote Development](https://code.visualstudio.com/docs/remote/containers)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227999/fa1530be-c5a0-aebe-c00a-29091cc58b4a.png)

無事VS Codeでコンテナに入ることができました。


# おわりに
この結論に至るまでに色々と試行錯誤したので記しました。VS Code Remote Containersは本当に最高なので使ってみてください。


[^1]: そんなことない？あるんです。
gulp エラー対応：SyntaxError: Cannot use import statement outside a module

#環境
・MacOS
・gulp v4.0.2
・node.js v14.4.0

#エラー発生タイミング
package.json作成、npm iコマンドでモジュールインストール後にgulp実行でエラー（SyntaxError: Cannot use import statement outside a module）発生

```:コンソール　エラー
[21:29:01] Requiring external module babel-register
/Applications/MAMP/htdocs/fuelphp/gulpfile.babel.js:1
import gulp from 'gulp';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:1116:16)
    at Module._compile (internal/modules/cjs/loader.js:1164:27)
    at loader (/Applications/MAMP/htdocs/fuelphp/node_modules/babel-register/lib/node.js:144:5)
    at Object.require.extensions.<computed> [as .js] (/Applications/MAMP/htdocs/fuelphp/node_modules/babel-register/lib/node.js:154:7)
    at Module.load (internal/modules/cjs/loader.js:1049:32)
    at Function.Module._load (internal/modules/cjs/loader.js:937:14)
    at Module.require (internal/modules/cjs/loader.js:1089:19)
    at require (internal/modules/cjs/helpers.js:73:18)
    at requireOrImport (/usr/local/lib/node_modules/gulp/node_modules/gulp-cli/lib/shared/require-or-import.js:19:11)
    at execute (/usr/local/lib/node_modules/gulp/node_modules/gulp-cli/lib/versioned/^4.0.0/index.js:37:3)
```

#原因
ディレクトリ配下に.babelrcを作成していなかった

```:.babelrc
{
  "presets": ["env"]
}
```

#対策
.babelrc作成後、再度gulpコマンド実行で問題なく動作した
初心者が機械学習をやってみたら（その０）


Python初心者である私が、

機械学習というキーワードにひかれ手を出してしまった。

これが全ての間違いだった。。。


# 1.なぜここに？
機械学習を学びたいと思い、色々情報を集め学び、試行錯誤してきました。
その、学んだことを忘れないために、とりあえずまとめることにしました。
まとめると言っても、たいしたことないですが・・・
同じような気持ちの人がいればチャレンジして欲しいと思い。

# 2.なぜ機械学習なの？
昨今、世間で騒がれている機械学習を知りたいと思ってしまった。
遅すぎるかも。

# 3.機械学習といっても何をすればいいの？
多くのデータが必要ということは知っている。
そこで、機械学習を学ぶためにお題を探していたところ、
ボートレース（旧競艇）は過去のレース情報が取得可能と知り、今回のお題にしました。
また、私はギャンブルは嫌いではない方なので。あわよくば・・・です。

なんとボートレースは毎日、日本全国１０箇所くらいで開催されているため、
学習（機械学習も含め）ちょうど良いと、判断した！！
ちなみに、ボートレースの会場は、日本に２４箇所あります。

# 4.今回の環境
## 4.1.環境（ハードウェア）
■メインとなるコンピュータ
・Jetson Nano（ヘッドレス）
　ご存知の方も多いと思いますが、AIを学ぶために適したボードコンピュータです。
　https://www.nvidia.com/ja-jp/autonomous-machines/embedded-systems/jetson-nano/

■Jetson Nanoへの接続用
・Jetson Nano用クライアントPC（WindowsでもMacでもOK）
　開発時はSSH接続可能であれば何でもOKです。

## 4.2.環境（ソフトウェア）
■開発言語
・Python3
　機械学習といえば、Python？
　こちらが学習のメインかと。
　https://www.python.jp/

■機械学習プラットフォーム・ライブラリ
・TensorFlow
　言わずと知れた？機械学習用ライブラリ。
　こちらが学習のメインかと。
　https://www.tensorflow.org/

■データベース（DBMS）
・MongoDB
　NoSQLデータベースを使用したく、こちらも学習のためにチョイス。
　https://www.mongodb.com/

■WEBアプリフレームワーク（WEB参照用）
・Flask
　予想した結果をビジュアル的にブラウザで確認するため、こちらも学習のためにチョイス。
　https://flask.palletsprojects.com/en/1.1.x/

# 5.最後に
こんな構成で機械学習を学んでいきます。
おはつの技術要素をあえてたっぷり入れました。

今後、不定期に更新していきたいと思っています。

記載の不備はご指摘ください。
投稿も技術も初心者ですのであたたかく迎えてください。
初投稿でした。

#関連（連載）

[初心者が機械学習をやってみたら（その１）](https://qiita.com/tosikazu-s/items/6a575482db44f19b6fff)
[初心者が機械学習をやってみたら（その２）](https://qiita.com/tosikazu-s/items/410b30e5fbdce0ce2675)
[初心者が機械学習をやってみたら（その３）](https://qiita.com/tosikazu-s/items/e443a58a8e3725269e99)
[初心者が機械学習をやってみたら（その４）](https://qiita.com/tosikazu-s/items/7dd6cd6c3f4fc2e21743)
[初心者が機械学習をやってみたら（その５）](https://qiita.com/tosikazu-s/items/78be7bafd4258543b144)
jupyterをdocker-composeで起動1

# はじめに
今回は、jupyterのdockerイメージ(scipy-notebook)をベースにjupyter pluginも入れて、
docker-composeを使ってイメージの作成と起動しました。

ソースは [github](https://github.com/va034600/jupyter-docker) にあげてあります。

# ファイル
## docker-compose.yml
``` docker-compose.yml
version: '3'  
services:  
  jupyter:  
    build:
      context: .
    environment:  
      JUPYTER_ENABLE_LAB: "yes" 
    ports:  
      - "8888:8888"  
    volumes:  
      - ./.jupyter:/home/jovyan/.jupyter
      - ./notebook:/home/jovyan/notebook
```

## Dockerfile

``` Dockerfile
# jupyter lab      : 2.1.3
FROM jupyter/scipy-notebook:54462805efcb

RUN jupyter labextension install \
  @lckr/jupyterlab_variableinspector \
  @krassowski/jupyterlab-lsp \
  @axlair/jupyterlab_vim

# pd.read_html
RUN pip install lxml html5lib beautifulsoup4

# code completion
RUN pip install jupyter-lsp python-language-server[all]

RUN jupyter lab build
```

## jupyter_notebook_config.py
``` jupyter_notebook_config.py
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.notebook_dir = './notebook'
c.NotebookApp.open_browser = False
c.NotebookApp.token = ''
```

# アクセス
http://127.0.0.1:8888

# 終わりに
jupyterですぐ試してみたい場合などで便利でした。
jupyter plugin周りは全般にメンテナンスがされていない感じがして、
かなり地雷がありました。

[次回](https://qiita.com/va034600/items/b2c988a885e9b239bf54)はdockerのイメージをpythonにしてjupyter lab環境を構築していきたいと思います。
【SwiftUI で作る macOS アプリ】CoreData サンプル

# 完成イメージ

![macosNavi.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/1854e472-1791-b7e5-32ca-8b7d56b6077c.gif)

# Entity

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/09663187-54c5-c84f-cf21-e330b4c5fef6.png)

# Code

```swift:ContentView.swift
import SwiftUI

func getAllStudents() -> NSFetchRequest<Student> {
  let request: NSFetchRequest<Student> = Student.fetchRequest()
  request.sortDescriptors = []
  return request
}

struct ContentView: View {
    
    @Environment(\.managedObjectContext) var moc
    
    @FetchRequest(fetchRequest: getAllStudents()) var students: FetchedResults<Student>
    
    var body: some View {
        VStack {
            Text("Student List")
            List {
                ForEach(students, id: \.id) { student in
                    HStack {
                        Text(student.name ?? "Unknown")
                        Button("delete", action: {
                            self.removeStudent(student: student)
                        })
                    }
                }
            }
            Button("add") {
                let names = ["taro", "yuki", "ken", "bob", "john"]
                let student = Student(context: self.moc)
                student.id = UUID()
                student.name = names.randomElement()
                try? self.moc.save()
            }
        }
    }
    
    func removeStudent(student: Student) {
        moc.delete(student)
        do {
            try moc.save()
        } catch {
            // handle error
        }
    }
}
```
Clean Architecture 第3章, 第4章のまとめ

# これはなに

Clean Architectureを読んで自分なりにまとめたものです。

---

# 第II部 構成要素から始めよ: プログラミングパラダイム

- プログラミングには様々な革命が起きてきた
- その中でも重要なのは、プログラミングパラダイムの革命
    - パラダイム
        - プログラミングの方法のこと
        - 言語とは比較的関係のないもの
    - パラダイムは、どのプログラミング構造を使うべきか、いつ使うべきかを教えてくれる
    - 現在、パラダイムは3つ存在している

---

## 第3章 パラダイムの概要

3つのパラダイム

- 構造化プログラミング
- オブジェクト指向プログラミング
- 関数型プログラミング

---

### 構造化プログラミング

- 制限のないジャンプ（goto文）🙅
    - if / then / else や do / while/ until などの構文に置き換えた

↓

構造化プログラミングは、直接的な制御の移行に規律を課すものである。

---

### オブジェクト指向プログラミング

- コンストラクタ、インスタンス変数、メソッド、ポリモーフィズムの発見

↓

オブジェクト指向プログラミングは、間接的な制御の移行に規律を課すものである。

---

### 関数型プログラミング

- 代入をすることを制限→不変

↓

関数型プログラミングは、代入に規律を課すものである。

---

### 考えるべきこと

- 3つのプログラミングパラダイムは、プログラマから能力を"削除"している
    - 何をすべきかを教えてくれるわけではない
    - 何をすべきでないかを教えてくれている

---

### まとめ

- これらの3つが、アーキテクチャの大きな関心事に対応している
    - コンポーネントの分離
    - データ管理
    - 機能

---

## 第4章 構造化プログラミング

- モジュールやコンポーネントなど、機能ごとに分割するのがベストプラクティスである

---

数学と科学の証明

- 数学
    - 真であることを証明する
- 科学
    - 真でないことを証明する
    - 反証

---

テスト

- テストはバグが存在しないことではなく、バグが存在することを示すものである
    - テストによって正しくないことは証明できる
    - どれだけ最善を尽くしても、正しくないことを証明できない → 正しいとする
        - 科学的証明

goto文は反証することができない

---

## まとめ

- 構造化プログラミングの価値を高めるのは、反証可能なプログラミングの単位を作成する能力
- ソフトウェアアーキテクトは、簡単に反証できるモジュール、コンポーネントなどを定義しようとする
- アーキテクチャレベルで、機能分割するのがベストプラクティスと考えられている
極方程式で花の曲線を描いてみた

```python

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

def pcf_to_graph2(pcf, last):
    start = 0 #定義域の左端
    
    def here_function2(f, th): 
        r = f(th)
        x = r * np.cos(th) # 極座標からの変換(x座標の抽出)
        y = r * np.sin(th) # 極座標からの変換(y座標の抽出)
        return x, y

    th = np.arange(start,last, 0.01)
    x, y = here_function2(pcf, th)

    fig = plt.figure(figsize=(5,5)) # サイズを均等に
    ax = fig.add_subplot(1,1,1) 
    #ax.set_aspect('equal')

    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.spines['bottom'].set_position('zero')
    ax.spines['left'].set_position('zero')
    #ax.axis([-1.2,1.2,-1.2,1.2]) # コメントアウト
    ax.grid() # グラフにグリッドを追加

    ax.plot(x, y) # 描画
    #ax.legend(bbox_to_anchor=(1, 1), loc='upper right', borderaxespad=0, fontsize=10) # ラベルの反映

    plt.show()

last = 10 * np.pi # 周期の定義

n = 6
k = 5

def rose(th):
    r = np.sin((n/k)*th)
    return r
pcf_to_graph2(rose, last)
```

<strong>実行結果</strong><br>
![1922077_李鳳桐_G2(データと数理II_6月26日課題5_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667877/c2474df3-1965-28c8-ecda-52b44c893804.png)
PyCharmが起動しなくなったら

しょっちゅう死ぬpycharm。起動しなくなったらこれ。

ただしindexingはし直しです。


```
 mv ~/Library/Preferences/PyCharm2019.2/workspace/* /tmp
```

> https://intellij-support.jetbrains.com/hc/en-us/community/posts/360006741780-IntelliJ-2019-3-Ultimate-not-opening-after-MacOs-upgrade-to-Catalina


2019.3でひどい目にあって以来、まだ2019.2のまま。いまのプロジェクトが終わったら2020にしたい
Python Tips

## .gitignore

- [gitignore.io](https://www.gitignore.io/ )
  - テキストボックスで "Django" を入力後、"Create" ボタンをクリックする 


## Python3.8 for Mac

```
# Homebrew update
$ brew update

# Pythone3.8 install
$ brew install python@3.8

# Python3.8 update
$ brew upgrade python@3.8

# venv
$ /usr/local/opt/python@3.8/bin/python3 -m venv ~/.venv/3.8
$ source ~/.venv/3.8/bin/activate
(3.8) $ python -V
Python 3.8.3
```

## 資料

- [brew python@3.8](https://formulae.brew.sh/formula/python@3.8)
【RPGツクールMV】【JavaScript】初学者向け解説：公式プラグイン「TitleCommandPosition.js」から分かる構造

##目的
コアスクリプトの理解のため、シンプルにまとまっている公式プラグイン「TitleCommandPosition.js」を読み解いてみました。

RPGツクールMVの主要コード（コアスクリプト）はJavScriptで書かれています。
はじめてプラグインを制作する方の参考になれば幸いです。
本稿では変数、無名関数、prototypeメソッドが登場します。

##「TitleCommandPosition.js」とは
タイトルコマンドウィンドウの位置を変更する公式プラグインです。
新規プロジェクトの中に同梱されています。

##コード
プラグインパラメーターはマークアップ記法だと崩れるので、省略します。
ES2015前の記法で書かれているため、変数はvarを使用しています。

```javascript
 (function(){

    var parameters = PluginManager.parameters('TitleCommandPosition');
    var offsetX = Number(parameters['Offset X'] || 0);
    var offsetY = Number(parameters['Offset Y'] || 0) ;
    var width = Number(parameters['Width'] || 240);
    var background = Number(parameters['Background'] || 0);

    var _Window_TitleCommand_updatePlacement =
            Window_TitleCommand.prototype.updatePlacement;
    Window_TitleCommand.prototype.updatePlacement = function(){
        _Window_TitleCommand_updatePlacement.call(this);
        this.x += offsetX;
        this.y += offsetY;
        this.setBackgroundType(background);
    };

    Window_TitleCommand.prototype.windowWidth = function(){
        return width;
    }

 })();
```
・即時関数((function(){})();)でオリジナルコアスクリプトの浸食を防いでいる
・パラメーターvar parameters、offsetX、offsetY 、width 、background の値を受けとり、
再定義することでコアスクリプトを改変している。

```javascript
    var parameters = PluginManager.parameters('TitleCommandPosition');
```
TitleCommandPositionはプラグイン名。
プラグイン名をリネームするとパラメーターを受けとれず、正しく動作しない理由はここ。

```javascript
    var _Window_TitleCommand_updatePlacement =
            Window_TitleCommand.prototype.updatePlacement;
```
rpg_window.jsの5746行目、Window_TitleCommand.prototype.updatePlacementを
_Window_TitleCommand_updatePlacementという名前で定義。

Title.Commandのプロパティを参照して、updatePlacementというプロパティを作っていたものを、プラグインの_Window_TitleCommand_updatePlacementで置き換えているのですね。

関数の中身は自分自身を呼び出して、パラメーターで追加された処理を実行しています。
コアスクリプトではthis.x(X座標)this.y(Y座標)のみを取得してたのを……

コアスクリプト：

```javascript
Window_TitleCommand.prototype.updatePlacement = function() {
    this.x = (Graphics.boxWidth - this.width) / 2;
    this.y = Graphics.boxHeight - this.height - 96;
};
```

プラグインではパラメーターからX座標、Y座標を受けとり、ウィンドウ背景まで定義できます。
変数backgroundは0:通常、1:暗い 、2:透明です。

プラグイン：

```javascript
    Window_TitleCommand.prototype.updatePlacement = function() {
        _Window_TitleCommand_updatePlacement.call(this);
        this.x += offsetX;//変数offsetXに入っているパラメーターの値か0を採用する
        this.y += offsetY;//変数offsetYに入っているパラメーターの値か0を採用する
        this.setBackgroundType(background);//変数background入っているパラメーターの値を採用する
    };
```

コアスクリプト：

```javascript

    Window_TitleCommand.prototype.windowWidth = function() {
        return 240;//固定
    };
```

プラグイン：

```javascript

    Window_TitleCommand.prototype.windowWidth = function() {
        return width;//変数widthに入っているパラメーターの値を採用する
    };
```

##終わりに
これから始める方の役に立てば幸いです。
お気づきの点がありましたら、コメントを頂けますと幸いです。
ワードプレステーマ the sonicを３ヶ月使ってみて、結論、最高すぎる！

皆さん、ブログの執筆をしていますでしょうか？
本日は、特に、自分でサーバーを借りてワードプレスでブログを書いている方におすすめのテーマをご紹介したいと思います。
今年、2020年3月に発売された「the sonic」です。

本記事では、the sonicを３ヶ月使ってみた感想を述べつつ、the sonicがどんなテーマなのかをご紹介したいと思います。

# the sonicとは？
2020年3月に発売された新しいテーマです。
ノビタさん、マサオカさん、クマさん、ハルシカさん、やよいさんというトップアフィリエイター、プログラマーの皆さんが集結して作られた、今年最注目のワードプレステーマといっても過言ではないでしょう。

# the sonicはとにかく速い！
the sonicの最大の特徴は、なんと言っても表示速度が速いことでしょう。
試しに、私が運営しているブログ「[ノビログ](https://nobilog.tokyo)」を表示してみてください。
きっと、その速度に驚かれることと思います。

ちなみに、サーバーはconohaです。

実は、ブログの表示速度というのは、SEO上もとても重要な要素なんです。
なぜなら、表示速度が遅ければ、読者は諦めて離脱してしまい、結果、googleからの当該サイトの評価が下がってしまうためです。

ですから、ブログを運営する際には、ぜひ速度が速いテーマを使用することをおすすめします。

# the sonicはサイト設計の柔軟性が高い
次の特徴として、サイト設計の柔軟性が高く、自由度が高いことが挙げられます。
同じく私が運営しているサイト「[冷凍食品ドットコム](https://reitoushokuhin.com)」をぜひ見てみてください。

ブログというと、記事が投稿日順にズラズラと並んでいるのを思い浮かべる方も多いのではないでしょうか？

the sonicでは、上記サイトのように、トップページを自由に作り込むことができ、あたかもコーポレートサイトのようなサイト設計をすることも可能です。
個人ブログだけでなく、法人のサイトにも良いのではないでしょうか？

#the sonicは複数サイトで利用可能
３点目の特徴として、the sonicは同一料金で複数サイトに使えることが挙げられます。
例えば、私が運営している[投資系のサイト](https://nobilog.tokyo/cfd)でもワードプレステーマthe sonicを使っていますが、実は、私は１ライセンスしか購入していません。
the sonicは、１ライセンスだけ購入すれば、複数のサイトに使い回すことが可能なのです。
複数サイトを運営する方にとっては、非常におトクなワードプレステーマと言えるのではないでしょうか？

#cocoonからの移行も簡単
私は、the sonicを使う前は、無料のワードプレステーマ「cocoon」を使っていました。
先ほどからご紹介している各サイトは、いずれもcocoonから移行したものですが、しっかりと問題なく移行できていることがご確認いただけるかと思います。
一方、同じく私が運営しているサイト「[バリ島サヌール大人旅](https://nobilog.tokyo/bali)」は、いまだにcocoonのままで、まだthe sonicに移行していない状態です。
このサイトについても、これから、近日中にthe sonicに移行していきたいと思いますので、どのように変わっていくか、ぜひ注目していただければ嬉しいです。

# まとめ
以上のように、the sonicは、発売間もない新しいワードプレステーマでありながら、魅力がたっぷりの内容となっています。
もしご興味があれば、ぜひ一度使ってみてはいかがでしょうか？
HelixのEisuキーでIMEオフ、KanaキーでIMEオンをしたい

## 実現したいこと
![](https://i.imgur.com/5szQzS7.jpg)

HelixのFW(QMK)はデフォルトだと、`Eisu`、`Kana`キーが英語、日本語モードに対応しています。
Mac OSXではそのまま`Eisu`キーが英語モード、`Kana`キーで日本語モードに切替できます。
ところがWindowsでは`Eisu`、`Kana`キー共に``ALT + ` ``に割り当てられていて、どちらを押してもトグル式に英語/日本語が切り替わってしまいます。これは半角/全角での切替と同じですね。

![](https://i.imgur.com/Ij04Bit.png)

トグル式の切替ですと入力ミスが増えるので、通常私はWindowsではIMEの設定を変更して`無変換`、`変換`キーを英語(IMEオフ)/日本語(IMEオン)に割り当てて使っています。
Helixの`Eisu`、`Kana`キーにそれぞれ`無変換`、`変換`をマッピングして、同じように切替をできるようにしたいです。

## TL;DR

`Eisu`キーに`無変換`、`Kana`キーに`変換` を割り当てても意図した動きにできませんでした。
なので次の表の動きとなるように設定しました。

| Helixの物理キー | Windowsが認識するキー | IMEの動作 | 結果|
| :-- | :-- | :-- | :-- |
| Eisu | Shift + F1 | IMEオフ | 英語モード |
| Kana | Shift + F2 | IMEオン　| 日本語モード |

次から設定内容を記載します。

### Windowsの変更箇所
WindowsのIMEの詳細設定で`Shift + F1`、`Shift + F2`を`IME オフ`、`IME オン`に割り当てます。

![](https://i.imgur.com/q1mq2TN.png)


### QMK Firmwareの変更箇所

(編集ソースはqmk_firmware/keyboards/helix/rev2/keymaps/default ディレクトリをmwlとしてコピーしたものとなります)

次のようにkeymap.cを修正することで、Helixの`Eisu`キーを入力すると`Shift + F1`が、`Kana`キーを入力すると`Shift + F2`がWindows上で入力されるようになります。

ビルド方法・FWの焼き込み方法などは割愛します。([公式ビルドガイド](https://github.com/MakotoKurauchi/helix/blob/master/Doc/firmware_jp.md)を参照ください)

```diff
mbp:qmk_firmware msrx9$ git diff
diff --git a/keyboards/helix/rev2/keymaps/mwl/keymap.c b/keyboards/helix/rev2/keymaps/mwl/keymap.c
index c575287ee..546bc4870 100644
--- a/keyboards/helix/rev2/keymaps/mwl/keymap.c
+++ b/keyboards/helix/rev2/keymaps/mwl/keymap.c
@@ -430,7 +430,10 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
         if(keymap_config.swap_lalt_lgui==false){
           register_code(KC_LANG2);
         }else{
-          SEND_STRING(SS_LALT("`"));
+          register_code(KC_LSFT);
+          register_code(KC_F1);
+          unregister_code(KC_F1);
+          unregister_code(KC_LSFT);
         }
       } else {
         unregister_code(KC_LANG2);
@@ -442,7 +445,10 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
         if(keymap_config.swap_lalt_lgui==false){
           register_code(KC_LANG1);
         }else{
-          SEND_STRING(SS_LALT("`"));
+          register_code(KC_LSFT);
+          register_code(KC_F2);
+          unregister_code(KC_F2);
+          unregister_code(KC_LSFT);
         }
       } else {
         unregister_code(KC_LANG1);
```

以上です。

---

## 当初の目的通り、無変換、変換キーじゃダメだったの？

実現したいことの部分にも記載している通り、最初は`無変換`、`変換`を使うようにマッピングしてみました。
ですがHelixで`無変換`、`変換`を使うことができませんでした。
正確に言うならば`無変換`、`変換`キーのスキャンコードを送ってもWindowsが認識しませんでした。

原因はUSキーボードとJISキーボードでは対応するスキャンコードが変わるからです。つまりOSがUS/JISどちらのキーボードとしてHelixを認識しているかに影響されるわけです。
HelixはWindowsではUSキーボードとして認識されます。

**`変換`、`無変換`キーはJISキーボードにしか存在しないキーのため、WindowsがUSキーボードと認識している状態で`変換`、`無変換`キーのスキャンコードを送っても無視されるわけです。**

F13、F14をIME切替に割り当てるという記事もあったので試してみましたが、F13はPrintScreenに、F14はScrollRockキーとして動作してしまったので私の環境では使うことができませんでした。

ですので、一般的には使うことのない`Shift + F1`、`Shift + F2`を`IMEオフ`、`IMEオン`に割り当る方式にしました。
画像フォーマットの種類

# はじめに
パソコンに保存してある画像を開こうとする際、その画像には.jpg, .png, .bmpなどの拡張子がついていますよね。この記事では、そのような画像データの拡張子（画像フォーマット）の種類とそれぞれの特徴について説明していきます。（まだ途中）

# ビットマップ画像とベクター画像
コンピュータ上の画像は、大きく分けて「ビットマップ画像」と「ベクター画像」の2種類に分かれます。この後紹介するBMP, JPEG, PNG, GIF といった画像フォーマットは全て ビットマップ画像に属します。そこで、まずはビットマップ画像とベクター画像の違いについて見ていきます。

## ビットマップ画像とは
ビットマップ画像：**画像を格子点上の細かい点（画素）に分割**し、画素ごとにRGBなどの表色系に基づいた色・濃度値を与えることで表現。

ビットマップ画像の画質は、1 inch (= 2.54 cm) あたりに存在する画素数、すなわち解像度[dpi=Dots per Inch]によって決まります。長さ当たりであって、面積当たりでないことに注意！

細かいことをいうと、解像度にも**相対解像度**と**絶対解像度**があり、dpiは相対解像度に等しく、絶対解像度はディスプレイの画像の大きさを表します（ex: 4Kは$3840px\times 2160px$）。

### 利点
* グラデーションのような色変化のある画像、連続的に複雑に色変化する画像に向く。 

###欠点
* 画像の拡大に弱い ← 拡大すると、画素のサイズも大きくなるので、画像がギザギザになってしまう。

## ベクター画像とは
ベクター画像：画像の色や曲線が計算式によって表現され、画像を「図形」として扱う。

### 利点
* 画像の拡大縮小に強い ← 画像を計算式で表現するため、拡大縮小をしても計算式の値だけ変えればよいので、正確に描写可能（直線と曲線の集まりの文字やイラストには向く）。

### 欠点
* 複雑な画像の描写には向かない ← 複雑な画像を計算式で図形として扱うのは難しい。

これらビットマップ画像、ベクターマップ画像の特徴から、よく見るBMP, JPEG, PNG, GIF等の画像形式を含め、一般的なコンピュータ上の画像はビットマップ画像となっている。

次に、BMP, JPG, GIF, PNGの画像フォーマットについて説明していきます。

# BMP（Microsoft Windows Bitmap Image）
MS-DOS, Windows標準の画像ファイルフォーマット。フルカラーサポートで、基本、無圧縮で利用。

## 特徴
* 無圧縮のため、画像の劣化がほとんどない。
* 1 bit（白黒）から 24 bit（フルカラーの 16,777,216色）まで表現可能
* 無圧縮なので、データ容量おおきい
* 透過処理はできない
* 1画素ごとに色情報を保持するため、解像度（dpi）とビット深度（1画素当たりのビット数）が同じなら、単純な画像も複雑な画像もデータ容量は同じ。

## 用途
〇 編集時の中間フォーマット（無圧縮より編集しても劣化無し）
X 印刷に使われるCMYK方式は対応していない
X 容量が大きいのでメール添付や配布用に適さない

# 参考
* https://michisugara.jp/archives/2012/img_format.html
* http://www7b.biglobe.ne.jp/~blue-jaywalker/frgform.html
スキルのアップデート情報を起動時にお知らせする方法

# はじめに
スキル内で、スキルのアップデート情報をユーザにお知らせするやり方についてです。

スマホのAlexaアプリやブラウザでは、更新情報が確認できます。
しかし、それらを開いてまで確認する人は少ないと思います。
スキルを起動したタイミングで、お知らせ（アップデート後の一回だけ）できれば良いなと思うのでやってみました。

# 概要

1. ユーザーの最後のスキル起動日時（`lastLaunch`）を記録する
1. お知らせするメッセージと時間（`lastUpdate`）を静的ファイルなどに書いておく
1. `lastLaunch < lastUpdate` の場合は、メッセージをお知らせする。

という仕組みです。




`1.`に関しては、[ask-utils](https://www.npmjs.com/package/ask-utils) の[SetLaunchCountInterceptor](https://github.com/ask-utils/ask-utils/blob/31588079bf7bb2e143f952e4ccfb61f104135ef1/packages/handlers/libs/requestInterceptors/LaunchCount.ts#L13)を使って実現します。

# コード


```index.ts

import moment from 'moment';
import updateInfo from './updateInfo.json';

const s3PersistenceAdapter = new Adapter.S3PersistenceAdapter({
  bucketName: `${process.env.SERVICE_NAME}-${process.env.ENV}`,
});


export const alexa = Ask.SkillBuilders.custom()
  .addRequestHandlers(
    LaunchRequestHandler
  )
  .addRequestInterceptors(SetLaunchCountInterceptor) // 1. ユーザーの最後のスキル起動日時を記録する
  .withApiClient(new Ask.DefaultApiClient())
  .withPersistenceAdapter(s3PersistenceAdapter)
  .lambda();


const LaunchRequestHandler = {
  canHandle(handlerInput: Ask.HandlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'LaunchRequest';
  },
  async handle(handlerInput: Ask.HandlerInput) {
      // 3. メッセージをお知らせする。
      if (moment(updateInfo.lastUpdate).isAfter(moment.unix(lastLaunch))) {
        progressiveResponse(handlerInput, updateInfo.message.join('<break time="300ms"/>')); //progressiveResponse関数は省略
      }
    }
    return handlerInput.responseBuilder
      .speak('ハローワールド')
      .getResponse();

```



```updateInfo.json
// 2. お知らせするメッセージと時間を静的ファイルなどに書いておく
{
    "lastUpdate": "2020-07-06T09:00:00",
    "message": [
        "アップデート情報のお知らせです。",
        "アップデートの内容はほげほげになります。"
    ]
}

```
 

# その他
日付（`updateInfo.lastUpdate`）を未来にしておくと、その時刻までずっとお知らせすることが出来ます。
期間限定のキャンペーンなどにも応用できそうです。
[RubyOnRails] active_hashはどんなデータに使うべきなのか

# はじめに

Railsでアプリケーション開発を行う際に、ある程度実世界に存在するであろうレベル間のフォームを実装しようとすると必然的にactive_hashの存在にたどり着くと思います。

僕もまんまと辿りつき「便利やな〜」って思ってたんですが、色々作業を進める内に使うべき時とそうじゃない時の考え方が少しずつ定まってきたので、備忘として残しておく物です。

# 環境
以下の環境で行っています。

ruby 2.6.5
rails 6.0.3


# active_hashを使うべきデータ

結論からいうと以下の考え方でいいのかなと。
**①あまり重要ではないデータに使う**
**②静的なデータに使う**
**③複雑な構造を持たないデータに使う**

結論から言うと上の二つだよねって感じでどこにでも書いてあるのですが、僕は②の認識が甘かったり、③をそもそも考えてなかったりだったなーと開発を進めてく中で学んでいった形です。詳しくは後述します。


# そもそもactive_hashとは

[こちらの記事](https://qiita.com/ryoff/items/88670edb3a656ca69d7b)や[こちらの記事](https://qiita.com/Toman1223/items/8633142312bfa886d50b)が非常にわかりやすいです。おかげさまであまり困らず導入できました。(いつもいつも先人には頭があがりません)

gem active_hashを利用することで、テーブルを作らなくともアクティブレコードの様に使える静的データを作っておくことが出来るというもの。
(ちなみにgemの最新バージョンは許容する記載方法が減っているとのことで導入時には注意が必要です)

よく例に出されるのだと都道府県データとかがありますね。実際に記載すると以下の様になります。

```ruby:prefecture.rb
class Prefecture < ActiveHash::Base
  self.data = [
      {id: 1, name: '北海道'}, {id: 2, name: '青森県'}, {id: 3, name: '岩手県'},
      {id: 4, name: '宮城県'}, {id: 5, name: '秋田県'}, {id: 6, name: '山形県'},
      {id: 7, name: '福島県'}, {id: 8, name: '茨城県'}, {id: 9, name: '栃木県'},
      {id: 10, name: '群馬県'}, {id: 11, name: '埼玉県'}, {id: 12, name: '千葉県'},
      {id: 13, name: '東京都'}, {id: 14, name: '神奈川県'}, {id: 15, name: '新潟県'},
      {id: 16, name: '富山県'}, {id: 17, name: '石川県'}, {id: 18, name: '福井県'},
      {id: 19, name: '山梨県'}, {id: 20, name: '長野県'}, {id: 21, name: '岐阜県'},
      {id: 22, name: '静岡県'}, {id: 23, name: '愛知県'}, {id: 24, name: '三重県'},
      {id: 25, name: '滋賀県'}, {id: 26, name: '京都府'}, {id: 27, name: '大阪府'},
      {id: 28, name: '兵庫県'}, {id: 29, name: '奈良県'}, {id: 30, name: '和歌山県'},
      {id: 31, name: '鳥取県'}, {id: 32, name: '島根県'}, {id: 33, name: '岡山県'},
      {id: 34, name: '広島県'}, {id: 35, name: '山口県'}, {id: 36, name: '徳島県'},
      {id: 37, name: '香川県'}, {id: 38, name: '愛媛県'}, {id: 39, name: '高知県'},
      {id: 40, name: '福岡県'}, {id: 41, name: '佐賀県'}, {id: 42, name: '長崎県'},
      {id: 43, name: '熊本県'}, {id: 44, name: '大分県'}, {id: 45, name: '宮崎県'},
      {id: 46, name: '鹿児島県'}, {id: 47, name: '沖縄県'}
  ]
end
```

modelの中にこの様なファイルを作るだけです。非常にシンプル。id:やname:がテーブルでいうカラム名ですね。
あとはアソシエーションをactive_hash用の記載で書いておくだけで簡単に使えます。

```ruby:item.rb
class Item < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :prefecture
end
```

今回はitemテーブルにprefecture_idを持たせたかったので、モデルに上記の様に記載します。
アクティブハッシュ側にはアソシエーションの記載は不要です。
これでテーブルを作った場合とある程度同様に使える様になります。お手軽で便利。


# 静的なデータ、複雑じゃないデータって？

### 静的なデータ
静的なデータと聞いて、僕は最初**クライアントサイドが増やさず、サーバーサイドで用意しておくデータ**くらいの認識でいました。

ただ、進めてる内にこの認識は不十分だなーと思って行った次第です。
具体的にいうと、例えサーバーサイド側で用意しておくデータであろうと、それが使用変更でどんどん増えて行ったり、後から値が変わる様なものなら**それは静的とは言えないな、と**

上記の書き方を見ても分かる通り、アクティブハッシュの各値はファイルにベタ内なので、これの更新行為ってめんどいやらリスクあるやらなんですよね(アナログ作業)

そこまで考えて、active_hashの使用例にやたら都道府県が出てくる理由をようやく理解しました。
都道府県って、クライアントサイドの都合でもサーバーサイドの都合でも増えないですもんね。

### 複雑なデータ

これは最初に知った時に少し思い当たる節がありました。僕は多対多のアソシエーションをくみたかったのですが、それってアクティブハッシュでは困難とのことだったので、あながち間違いじゃない認識だったんだなと。

あとは**階層構造を持つテーブル**とかも複雑なのでアクティブハッシュは使えないみたいですね。
そこらへんの認識が抜け落ちてました。


# 終わりに

「静的なデータ」と言う語の意味を正確に捉えられてなかったんだな〜と言う感想を開発を進めていく中で持った次第です。
やっぱ基本やってみないとわからないですね何事も。手を動かすあるのみ。
【Flutter/Dart】error: The argument type 'dynamic Function()' can't be assigned to the parameter type 'String Function(String)'.  の対処法

## はじめに

Flutterで関数を引数として渡した時、次のようなエラーが出ることがあります。

```dart
class CustomTextFormField extends StatelessWidget{
  const CustomTextFormField({
    Key key,
    this.validator
  })

  final Function() validator;

  @override 
  Widget build(BuildContext context){
    return TextFormField(
      validator: validator, // <- ここでエラーが出る
    );
  }
}
```

```
error: The argument type 'dynamic Function()' can't be assigned to the parameter type 'String Function(String)'. 
```

メッセージ通り、`String Function(String)`型な関数が必要なのに、`dynamic Function()`型として関数を受け取っているためエラーがでています。

## 対処方法
関数の引数・返り値を指定してあげれば、エラーが解消します。

```dart
class CustomTextFormField extends StatelessWidget{
  const CustomTextFormField({
    Key key,
    this.validator
  })

  final String Function(String) validator;// <- 返り値と引数を指定する

  @override 
  Widget build(BuildContext context){
    return TextFormField(
      validator: validator, 
    );
  }
}
```

## 参考文献

[Diagnostic messages | Dart](https://dart.dev/tools/diagnostic-messages#argument_type_not_assignable)
CPS（サイバーフィジカルシステム）

まだ執筆中ではありますが、書いていく。
間違いがあることはご容赦ください。

Society5.0の中心的な概念でもある。

これまではサイバー空間とフィジカル（現実）空間とを分けて考え、処理を行ってきたが、
その両者を分けず、融合させて新たな価値想像を創出する。
クラウドAI開発講座 Microsoftと高専キャリアがコラボ #1

# クラウドAI開発講座
[マイクロソフトと高専キャリア教育研究所が共催するAI開発プログラム](https://online.kosen-career.tech/ai)
**無料**で参加でき、困ったときにはメンターに相談ができるオンラインプログラム



## ミッション
- [Azure for studens](https://azure.microsoft.com/ja-jp/free/students/?WT.mc_id=azureforstudents-docs-nosuzuk)に登録する
- [de:code2020](https://www.microsoft.com/ja-jp/events/decode/2020/default.aspx)のコンテンツを視聴して学習する
 - [学生諸君！ Azure であそぼう！ ～Microsoft の AI を自作アプリに取り入れるまで～](https://www.microsoft.com/ja-jp/events/decode/2020session/detail.aspx?sid=Z01)
 - [Azure Bot Services を使って Teams bot を開発する](https://www.microsoft.com/ja-jp/events/decode/2020session/detail.aspx?sid=A02)
- [Microsoft Learn for Students](https://docs.microsoft.com/ja-jp/learn/roles/student?WT.mc_id=BlendedCurriculum-MSLearn-nosuzuk)で学習する
- レッスンを消化する　
 - [ちょまどさん](https://qiita.com/chomado/items/6bda10abde0551f25723)
 - [おーちょさん](https://qiita.com/miokawa/items/6f1a3e480580e1e29abc)

## 進歩
- [Azure for studens](https://azure.microsoft.com/ja-jp/free/students/?WT.mc_id=azureforstudents-docs-nosuzuk)登録（完了）
- [de:code2020](https://www.microsoft.com/ja-jp/events/decode/2020/default.aspx)のコンテンツ視聴（完了）

## 高専キャリアONLINEの提供コンテンツ（高専キャリア教育研究所）
[高専キャリアONLINE](https://online.kosen-career.tech/)の提供コンテンツ（[高専キャリア教育研究所](https://kosen-career.tech/)）

- [Business Design Lab](https://online.kosen-career.tech/business-design-lab)
- [クラウドAI開発講座](https://online.kosen-career.tech/ai)（本記事）
- [【高専生/編入生限定】特許活用ビジネスプランコンテスト](https://online.kosen-career.tech/bizdev-weekend)
python OCRで画像の文字読み取り

#tesseractのインストール

```
$ brew install tesseract
```

#tessetacを動かすライブラリをインストール

```
$ pip3 install pyocr
```


#日本語読み取り設定

``` 
$ curl -L -o /usr/local/share/tessdata/jpn.traineddata 'https://github.com/tesseract-ocr/tessdata/raw/master/jpn.traineddata'
```

```
$ tesseract --list-langs

List of available languages (4):
eng
jpn
osd
snum
```

#OCR実装

```python
from PIL import Image
import sys
import pyocr
import pyocr.builders

tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("No OCR tool found")
    sys.exit(1)
# The tools are returned in the recommended order of usage
tool = tools[0]

txt = tool.image_to_string(
    Image.open('{path}'),
    lang="jpn",
    builder=pyocr.builders.TextBuilder(tesseract_layout=6)
)
print(txt)
```
【Ruby】小数点同士の計算結果がズレる、違う、意図したものにならない

詳細は下記。

https://qiita.com/yusabana/items/fd4a0185c1f120403a74

BigDecimalを設定しておかないとだめって話なのだが、
インスタンス宣言元では使ってるのに対応されないってのが一つと、恐らくBigDecimal使うとインスタンス元と同じ桁数になるから、
.add、.sub、.mult、.divを使って第2引数に桁数指定して計算しないといけない可能性がある。


しかもこれ既存不具合で潜在してた。
それ以前に今回の変更箇所が不明になったので優先的では無いが、
何故か試験で精度を求められるようなので追加で報告相談して対応方針をクライアントに決めてもらう流れになるだろう。(勝手に決めてはいけない)

まーやらんといけんだろうが、
一度対応方針確認して了承得てると補足しておく。

既存仕様からの差分変更対応の落とし穴として
変更ないところで最終的にひっくり返されることになるのは勉強した。。。

もう二度とヤダ。。。