OmniAICreator/Qiita-1.07M huggingface dataset:
業務自動化のため使用した技術[Dockerのバックアップとスイープ処理を自動化した]

## 概要
業務において、今まで手動でDockerのバックアップとスイープを行っていたものを自動化しました。
その際に行った工程や使用した技術を記載します。それぞれの技術やコード等の解説は詳しくやりません。
当たり前な部分も多いかもしれませんが、年数が浅い人向けと、自分の忘備録のために書きました。
業務自動化を目的としたバッチ処理の実装などのヒントになれば幸いです。
以下の順で説明します。

1. 設計
2. 言語選定
3. 環境構築
4. 実装物
5. 定期実行
6. コードの保存・管理
7. ドキュメント

## 1. 設計
まずは、どのようにして業務を自動化するかを考えます。
当然ですが、自動化するために投資する工数 < 自動化した後の削減された工数
でないと自動化のメリットがないため、それぞれ見積もって自動化するべきかどうか検討します。
その後、入力と出力をどう行うかなど、業務フローに沿った設計を行います。
今回は依頼されたタスクで内容も決まっていたので、この工程は特に自分ではやりませんでした。

Dockerの管理をしているサーバー管理者向けに、Dockerのバックアップと古いバックアップの削除(スイープ)を定期実行できるツールを実装します。

## 2. 言語選定
自動化の大まかな設計が定まったら、使用する技術の選定を行います。
言語選定は、言語の特性を理解して選ぶのが良いですが、個人の得意な言語でもさほど問題ないと思います。
今回はpythonとshellのどちらの言語を使うか迷いましたが、shellに決定しました。
理由は以下です。

- [python](https://www.python.org/)
  - pythonがインストールされている必要がある。(環境によってはインストールされていない場合がある)
  - Version管理がちょっと面倒。もし管理するなら[pyenv](https://github.com/pyenv/pyenv)などのバージョン管理ツールを使う必要がある。

- shell
  - shellはLinuxに標準でついている。
  - 処理の内容的にShellの機能だけで充分。

#### 使用エディタ

エディタは言語に応じて好きなものを使えばいいと思います。
CUIエディタは慣れておくとサーバー扱うときに役に立つかもしれないと思ったため、今回は以下を利用しました。

- [Vim](https://www.vim.org/)

## 3. 環境構築
必要に応じて、実装に必要な環境構築を行います。
今回は以下の設定を行いました。使用OSはUbuntuです。

- [Docker](https://www.docker.com/)
- ネットワーク

## 4. 実装物

正直オープンソースとか見た方がコード綺麗なのでそれらを参考にするのをお勧めします。
https://github.com/mgmgmgmi/BackupDocker
https://github.com/mgmgmgmi/SweepDocker


#### 細々したTips

- 今回使わなかったけど、コマンドライン入力はgetopt/getopts使うと便利かも。
- 引数のオプションで -h 等のオプションでヘルプを表示させてあげると親切そう。
- 圧縮形式はzipよりtar.gzがおすすめ。zipは権限のメタデータなどが保存されないけど、tar.gzは保存される。
- 変数名や関数名は分かりやすく。処理の目的と関数の内容を一致させる。
- 設定ファイルと処理実行のファイルを分ける。ツール利用者は設定ファイルのみ編集すれば良いようにする。

## 5. 定期実行

- cron

Linuxに標準でついているCUIの管理タスクスケジューラです。
Windowsのタスクスケジューラや、Jenkinsの下位互換のようなものです。
cronに実行ファイルを登録すると、その時間に毎回ファイルを実行してくれます。

## 6. コードの保存・管理

- Git

一人で実装を行う際もGitを使用することをお勧めします。
いろいろと試したいときに別のブランチ切ったり、失敗した際に巻き戻したりできます。
また、他人へ公開したり共有することが容易です。

## 7. ドキュメント

- Markdown

Markdownは記法(文章の書き方)の一つです。Qiitaの記事書くときに使うあれです。
gitのREADMEではMarkdownに対応しています。
他の人が見やすい＆分かりやすいように概要や使い方を記載するのにおすすめです。


## 終わりに
以上、業務自動化のための一連の工程や使用した技術の紹介でした。
うまくまとまってない気もするので、アドバイスがあったら是非コメントください。
また、内容に間違いや不明な点があればご指摘ください。
clearfix

#clearfixとは

・指定したい要素の親にクラス指定で書く
・after（疑似要素）を使って書く
・after（疑似要素）はcontent内の文字を表示させる意味を持つ

```css:css
p:after{content: "こんにちは";}
```

上記はpに書かれている要素が表示されたあとに「こんにちは」という一文を表記するというものである

```css:css
.clearfix::after{
  content: "";
  display: block;
  clear: both;
}
```

``上記のように書いてあげると発動する``
[glossで実験] ファン・デル・ポール振動子

ファン・デル・ポール振動子は相空間[^1]にリミットサイクルが存在する微分方程式によって記述される振動子です。

```math
\frac{d^2x}{dt^2} - \mu (1 - x^2)\frac{dx}{dt} + x = 0
```

これをHaskellで実装すると以下のようになるでしょう。

```hs
type Point = (Double, Double)

vanderpol :: Float -> Point -> Point
vanderpol dt (x, x') = let mu = 2.5
                           x'' = mu * (1 - x^2) * x' - x
                       in (x + dt * x', x' + dt * x'')
```

`Point`は`(位置, 速度)`という座標を表すタプルです。微分方程式から2階微分の値を計算し、オイラー法によって次のステップの座標を計算しています。

この微分方程式の時間発展を実際にgloss[^2]で描画して眺めてみましょう。

```hs
main :: IO ()
main = simulate inWindow white 24 initModel draw (\_ -> step)
  where
  inWindow = InWindow "Haskell Day 2018" (640, 480) (100, 100)
  initModel = [(1.0, 0.0)] -- 初期状態
  draw = scale 50 50 . line -- そのままだと小さいので50倍に拡大する
  step dt ps@(p:_) = vanderpol dt p : ps
```

`(1.0, 0.0)`から始めて時間発展を`line`で描画しています。`step`は`vanderpol`によって計算した次のステップの状態を今までの計算履歴のリストの先頭に付け加えています。これを実行すると以下のようなシミュレーションになります。

<img src="https://i.gyazo.com/3c58555e2ed669b4ec0584036834f368.gif" width=400 />

みなさんもぜひ自分で実装してみて初期状態や$\mu$の値を変えたりして遊んでみてください。

[参考] [Wikipedia: ファン・デル・ポール振動子](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%83%B3%E3%83%BB%E3%83%87%E3%83%AB%E3%83%BB%E3%83%9D%E3%83%BC%E3%83%AB%E6%8C%AF%E5%8B%95%E5%AD%90)

[^1]: x軸に位置, y軸に速度を取った空間
[^2]: [glossではじめるグラフィック描画 :: Haskell入門の次に読む記事 - Qiita](https://qiita.com/lotz/items/eb73e62a64bc208c2dd6)
CSSで名刺を作ってみた


こんにちは！[きなこ](https://twitter.com/asukaokochi)だよ〜！
この記事は[Life is Tech! Tokai Mentors Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lit-tokai-mentors)の5日目の記事です．

みなさん、自分の名刺って持ってますか？
私はそろそろリメイクしようか悩み中です:thinking:

ということで今回は名刺を作ろうと思います！
ただ、せっかくだから変わった方法でやってみたいよね？

## CSSで名刺を作ってみた
さて、今回は名刺に以下の要素を入れようと思います。
　・名前
　・連絡先
　・SNS

ざっくりとしたデザインはこんな感じ。
![IMG_4588.JPG](https://qiita-image-store.s3.amazonaws.com/0/216051/00261203-c5a6-5a1c-3448-e24ae0f2efc2.jpeg)

では、早速作っていきましょう！

### HTML
```
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>名刺</title>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
</head>

<body>

    <div class="namecard">
        <p class="name">ほげ 太郎</p>
        <span class="phonetic">hoge taro</span>

        <div class="contact">
            <span><i class="fab fa-twitter"></i>Twitter</span>
            <span><i class="fab fa-facebook"></i>Facebook</span>
            <span><i class="far fa-envelope"></i>MailAddress</span>
        </div>

        <img src="cat.png" alt="ねこちゃん">
    </div>

</body>

</html>
```
↓プレビューするとこんな感じ。↓
![HTMLOnly.png](https://qiita-image-store.s3.amazonaws.com/0/216051/93c024c6-dfaf-8816-0dd9-75d559874b13.png)
猫の画像は「[ハンコでアソブ](http://hankodeasobu.com/)」というサイトの素材を使わせてもらいました。
ここからCSSで名刺っぽくしていきます。

### CSS
```
@import url('https://fonts.googleapis.com/css?family=Sawarabi+Mincho');

* {
    margin: 0;
    padding: 0;

    font-family: 'Sawarabi Mincho', sans-serif;
}

.namecard {
    /*名刺の区切れ目がわかるような線*/
    border: 1px solid #ddd;

    /*名刺の大きさ（縦横比さえ合ってれば良いと思います）*/
    width: 22.75rem;
    height: 11.75rem;

    /*名刺の余白*/
    margin: 2rem;
    padding: 3rem;

    /*装飾*/
    color: #333;
}

.name {
    /*文字の装飾*/
    font-size: 2rem;

    /*微妙にずれてるのを修正*/
    margin-top: -0.5rem;
    margin-left: -0.25rem;
}

.contact {
    /*flexboxにして縦並びにしています*/
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;

    /*余白*/
    margin-top: 3.5rem;

    /*装飾*/
    font-size: 0.8rem;
}

.contact span {
    margin-top: 0.25rem;
}

.contact i {
    /*SNSなどのアイコンの位置調整*/
    width: 1.25rem;
}

.namecard img {
    /*画像のサイズ指定*/
    width: 8rem;

    /*画像の位置指定*/
    position: relative;
    left: 15.25rem;
    bottom: 7rem;
}

```
↓プレビューするとこんな感じ↓
![CSSAdd.png](https://qiita-image-store.s3.amazonaws.com/0/216051/b09e0e63-44db-e8bc-ebce-fd7ce35a20ec.png)
はんこっぽいテイストに寄せていくために[GoogleFonts](https://fonts.google.com/)を使ってみました。
少しシンプルすぎるかなぁと思いますが、名刺ってこんなもんですよね:eyes:

## まとめ
いかがでしたか？
デザインツールを使わずに名刺を作ることのメリットは、情報の変更が容易なことや余白調整などがすぐに出来ることだと思います。

https://github.com/AsukaOkochi-Kinako/Meishi_CSS
こちらに今回のサンプルコードを置いておいたので、ぜひ自分でも作ってみてください。

それでは、きなこからでした！
毎日ペアプロしていて感じる良いところ5つ、困ったところ3つ

この記事は[Classi Advent Calendar 2018](https://qiita.com/advent-calendar/2018/classi)11日目の記事です。

ClassiのCSチームでRailsエンジニアをしている@SoarTec-labです。
CSチームのRailsエンジニアは2人なので毎日ペアプロで開発を行なっています。

この記事では私がこれまでペアプロをしていて感じた良いところ5つ、問題点3つを紹介します。

# 良い所

## 1.  Pull Requestのレビュー待ちで放置がなくなる

チーム開発の中で以下の様な問題は少なからずあると思います。

* 優先度の低いPull Requestはレビュー放置され続け、最悪風化してしまう
* 開発が完了しているのにPull Requestのレビュー待ちでリリースできない
* キチンとレビューする時間が無く、レビューの確度が低いままリリースしてしまう

ペアプロではレビューをしながら進めて開発を進めるのでレビューの時間がほとんど無くなります。
1人で開発した部分もペアプロ開始時に共有を兼ねて、対面レビューするので同様です。
その際、現状のコードになっている経緯までを共有するので確度の高い意味のあるレビューができます。

## 2. 記憶の引き出しが増える

複数プロジェクトを対応していると、記憶が分散され対応の初速が落ちてしまいがちですが、
ペアで対応している場合、どちらかが覚えていることで切り替えがスムーズになり、
**タスク着手の初速が上がります。**

## 3. ボーイスカウトパワーが上がる

技術的負債の返済は基本的にボーイスカウトルールで対応しています。
1人で対応する場合と比べペアの時の方が、**負債初見時のダメージが圧倒的に少ないです。**
その為、ダメージが小さい=モチベーションを高く維持できる為、**より多くの技術的返済ができています。**

## 4. 情報量が多くなる

社内の情報、良かった書籍、ネット上の記事など共有が活性化され得る情報が多い為
共通の認識が確立すると共に、**属人化している知識を引き出す事ができます。**

## 5. なぜそのコードにするかが明確になる

なぜこのコードにするかを会話しながら進めるので、"なんとなく"・”経験から"・"とりあえずコピペ"が無くなります。
**自然とコード、アルゴリズムレベルでの品質が上がります。**

# 困ったところ

## 1. 違和感の解消に時間を使いすぎてしまう

違和感を感じても直ぐに答えが見つからない場面もあります。

タスクの完了を第1と考え、違和感を感じた箇所はメモに残し全体が完成した後にもう1度するというルールにしています。
完成後に確認する事で違和感の正体が分かったり、全体で見たら悪くないなど気づきがあります。

## 2. 休憩を忘れてしまう

コードリーディング、設計、開発、テスト、リファクタリング、レビューを会話しながら繰り返していくので、非常に集中します。
特に慣れるまでは没頭してしまうので、意識的に休憩を取る様にしました。

現在は、ポモドーロテクニックを実践していて、１時間を以下の様に区切り休憩を意識的に取っています。

ペアプロ: 25分
休憩: 5分
-- 交換 --
ペアプロ: 25分
休憩: 5分

## 3.フローに状態入れない

1人で開発する時のフロー状態に入る事はできませんが、ペアプロも集中力をとても使います。
集中力を上げ開発パフォーマンスを上げる為、前述のポモドーロテクニックを実践していたりと工夫をしています。
8946 Take#44

#問題

http://www.hackerschool.jp/hack/take44.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/6f6c8210-ad81-7fcd-fda5-60fed1935eca.png)

#解いてみた

- 下にソースコードが書いています。
- submitしたときにきっとこのソースが待ち受けているんでしょう。
- 「ログインしました」にするにはsuccessをtrueにしなくてはなりません。
- successをtrueにするにはidとpasswordに何らかの値を正しく入れなければなりません。
- が、よく見るとsuccessは初期化されてないので、こちらから引数としてsuccess=trueを渡しておけばいいのでは？

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/8bc76849-1cf6-9308-1124-6041a367288e.png)


- こんな感じでテキストボックスを足して、trueと書いておけばいいんです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/14321274-d745-85cc-efc3-d35e902d7f19.png)
8946 Take#35

#問題

http://www.hackerschool.jp/hack/take35.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/f3031808-5f50-daa6-f484-e2cd21b2c832.png)

#解いてみた

- アクセスしてみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/8a461561-e5fa-4e88-6b01-89ed499560c0.png)

- 謎の縦長画面が出てきました。
- かつdocomoのあとの謎の数字です。
- 数字をgoogle検索してみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/022d1a41-7551-a539-8c8f-498f0c1c2c18.png)

- もしかしてガラケーですか？
- ガラケーって端末番号みたいなやつありましたよね。
- 中の記事を読むとユーザーエージェントでログイン認証していたらしいです。
    - DoCoMo/2.0 P902i(c100;TB;W24H12;serXXXXXXXXXXXXXXX;iccxxxxxxxxxxxxxxxxxxxx)
- xxxxxに前回ログインに使用された数値365079045783623を使用する。
- DoCoMo/2.0 P902i(c100;TB;W24H12;ser365079045783623;iccxxxxxxxxxxxxxxxxxxxx)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/e12b7dfa-6d2d-99da-31ab-15a84d474246.png)

- UAをこんな感じで編集してから、簡単ログインボタンを押します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/5ca2615d-143e-afab-e1a2-961a6682f565.png)

- 答えはBQXJuetS72になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/9e5ce8df-11fd-e5b2-13fd-9639f544884e.png)
TeamSpeak 3 サーバをバックアップする

# TeamSpeak 3 サーバをバックアップする

[Discord](https://discordapp.com/)に喰われつつある[TeamSpeak 3](https://www.teamspeak.com/)のバックアップに関する記事です。
自分がよく手順を忘れるので備忘録がてら投稿します。

## 注意点

- 本記事はLinux版のTeamSpeak 3 サーバを対象としています。
- 本記事におけるバックアップ方法は所謂フルバックアップです。

## バックアップ対象となるファイル

- logs/*
- files/*
- licensekey.dat
- query_ip_whitelist.txt
- query_ip_blacklist.txt
- ts3server.sqlitedb

運用方法によっては不要なものもあるので各自取捨選択してください。
TSDNSを使用している方は設定ファイルも対象に含めておきましょう。

## バックアップ手順

下記条件を前提に記述します。

- TeamSpeak 3 サーバは`/opt/teamspeak3-server/`に設置。
- バックアップファイルの名称は`ts3server_backup.tar.bz2`とする。

1. TeamSpeak 3 サーバを停止する。

    ```console
    # cd /opt/
    # ./teamspeak3-server/ts3server_startscript.sh stop
    ```

1. バックアップ対象となるファイルの圧縮およびアーカイブ化する。

    ```console
    # tar -jcvf ts3server_backup.tar.bz2 \
    teamspeak3-server/logs/ \
    teamspeak3-server/files/ \
    teamspeak3-server/licensekey.dat \
    teamspeak3-server/query_ip_whitelist.txt \
    teamspeak3-server/query_ip_blacklist.txt \
    teamspeak3-server/ts3server.sqlitedb
    ```

おしまい。

## 毎回コピペするの面倒なんだけど

上記バックアップ手順を少しいじってスクリプト化。
`ts3server.sqlitedb`の更新タイムスタンプをバックアップファイルの名称にします。

マサカリ大歓迎です。

```shell:ts3server_backupscript.sh
#!/bin/bash

# アーカイブ保存先ディレクトリを入力
DST_DIR=""
# TeamSpeak 3 サーバ格納ディレクトリを入力
SERVER_PATH=""
# アーカイブ対象のファイルおよびディレクトリをスペース区切りで入力
target=("files/" "logs/" "query_ip_blacklist.txt" "query_ip_whitelist.txt" "ts3server.sqlitedb")


# アーカイブ保存先ディレクトリの存在確認
if [ ! -d "$DST_DIR" ]; then
    echo "Directory not found. ($DST_DIR)"
    exit 1
fi

# TeamSpeak 3 サーバ格納ディレクトリの存在確認
if [ ! -d "$SERVER_PATH" ]; then
    echo "Directory not found. ($SERVER_PATH)"
    exit 1
fi

# pidファイルの存在確認 (ファイルが存在する場合は処理を行わない)
if [ -e "${SERVER_PATH%/}/ts3server.pid" ]; then
    echo "TeamSpeak 3 server is running, Please stop server first."
    exit 1
fi

# ts3server.sqlitedbの更新タイムスタンプを取得 (アーカイブファイル名に使用)
db_file="${SERVER_PATH%/}/ts3server.sqlitedb"
file_name=$(stat -c "%Y" "$db_file")  > /dev/null

if [ $? != 0 ]; then
    echo "Cannot get timestamp. ($db_file)"
    exit 1
fi

# アーカイブファイルの存在確認 (ファイルが存在する場合は処理を行わない)
dst_file="${DST_DIR%/}/$file_name.tar.bz2"
if [ -e "$dst_file" ]; then
    echo "Backup file already exists. ($dst_file)"
    exit 1
fi

# ライセンスキーが存在する場合はアーカイブ対象に追加
if [ -e "${SERVER_PATH%/}/licensekey.dat" ]; then
    target+=("licensekey.dat")
fi

# アーカイブファイルの作成
for ((i = 0; i < ${#target[@]}; i++)); do
    target[i]=$(basename "$SERVER_PATH")/${target[i]}
done

tar -jcf "$dst_file" -C "$(dirname $SERVER_PATH)" "${target[@]}" > /dev/null

if [ $? != 0 ]; then
    echo "Cannot create backup file."
    rm -f "$dst_file"
    exit 1
else
    echo "Backup completed. ($dst_file)"
fi

exit 0
```

## さいごに

TeamSpeak 5っていつリリースするんですか？

## 参考資料

- [I want to move my server to another machine, which files should I copy? – TeamSpeak](https://teamspeak.zendesk.com/hc/en-us/articles/360004426791-I-want-to-move-my-server-to-another-machine-which-files-should-I-copy-)
- [TeamSpeak3 サーバのアップデート方法 - 死者のページ](http://www.arcenserv.info/archives/3834/)
    - 手順を忘れる度に思い出させてくれたページ。著者のharu_arcさんに多謝！
8946 Take#59

#問題

http://www.hackerschool.jp/hack/take59.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/e6070d7d-a0f7-f3b7-50df-7ea6de313c32.png)

#解いてみた

- よくわからないのでgoogle検索してみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/e97d7874-7740-8cf6-efcb-d9cfb7738c7a.png)

- 3つとも村上春樹の1Q84が出てきたのでこれが正解です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/c91e7271-fdec-d32b-2a54-f3a0d18b613f.png)

- この正解率の低さが気になりますね。。。
8946 Take#２６

#問題

http://www.hackerschool.jp/hack/take26.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/43fcdc2b-8eeb-1c1a-1d68-e07a43df970b.png)

#解いてみた

- ソースを見てみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/22884645-2cd2-3360-e532-f84a664b970e.png)

- この長ったらしいjsを攻略しなさいということですね。
- ソースをまるまるコピーして、htmlファイルとして保存します。
- そしてあの長いjsをalert()で囲ってみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/8dc52be8-79af-1205-b15c-da63dc69c047.png)


- こんな感じのものが出てきました。
- 長いのは長いんですが、「document.getElementById("hint").innerHTML="<div 」っていうところに注目します。
- hintってところに右辺のHTMLを入れるってことなので、右辺の内容をそのままHTMLに書き込めばいいのではないか。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/10c07cc1-bac2-a5cc-aad6-a90de02970d6.png)

- ロシア語？が出てきました。
- これはGoogle翻訳するしかないですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/2de2fd60-6fa8-021c-b641-13aff6454372.png)

- ということで02/14です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/00e29c76-f93a-302e-b31a-055633f9a716.png)
【SAPUI5】Shell Controlでデバイスに合わせて幅を調整

##はじめに
これまでに作ったアプリケーションはPCでの表示のみを想定していました。
このため、デバイスの幅が変わると文字が小さくて読めなかったりしました。

**※注**
Fiori Launchpadで実行するアプリの場合、Launchpadに Shell barが含まれるのでアプリ側にShell Controlをつける必要はありません。本記事は、スタンドアロンアプリを想定しています。

**PCで表示した場合**
![WS000022.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/0452a282-182d-fc30-30d5-702fbf89fb5c.jpeg)


**iPoneXで表示した場合**
![WS000026.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/11428955-bfdf-316a-c937-9c21369c7cd8.jpeg)

<img width="487" alt="WS000023.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/276021/e6c2dd07-2f22-cf09-4352-57a6f2e0bfb6.jpeg">
※デバッグツールの"Toggle device tool bar"というボタンを押すと、さまざまなデバイスで実行した結果をシミュレーションできます

##Shell Controlとは
sap.m.Shellというコントロールを使うと、デバイスに合わせて幅を自動調整することができます。
index.htmlファイルのattachInitメソッドの中でShellのインスタンスを作成すると、Shellがアプリケーションの一番外側のコントロールとして機能します。
これにより、ビュー側では幅を意識する必要がありません。

##書き方
[入門編の記事まとめ](https://qiita.com/tami/items/53990a14e5ca919ec35a)で作成したアプリケーションを用意します。
index.htmlファイルのattachInitメソッドを以下のように変更します。

変更前

```javascript
	    <script>
	       sap.ui.getCore().attachInit(function () {
                new sap.ui.core.ComponentContainer({
                    name : "test.helloworld"
              }).placeAt("content");	  
	       })
	    </script>
```

変更後

```javascript
	    <script>
	       sap.ui.getCore().attachInit(function () {
	       		new sap.m.Shell({
				    app : new sap.ui.core.ComponentContainer({
						name : "test.helloworld"
            		})    			
				}).placeAt("content");
	       })
	    </script>

```

もともとあった"new sap.ui.core.ComponentContainer"以降の記述を、sap.m.Shellで囲った形です。

##実行結果
**PCで表示した場合**
あまり違いがわかりませんが、最上部に青いバーが表示されています。
![WS000024.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/5d5802dc-e16d-8934-1a2e-b3826294fc99.jpeg)

**iPoneXで表示した場合**
文字が読める大きさで表示されるようになりました。
![WS000025.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/5f6bdf6f-2c37-fe67-c1ea-a8ce7b76c4d8.jpeg)

##参考にしたページ
[Get Started: Setup and Tutorials-Walkthrough-Step 12: Shell Control as Container](https://sapui5.hana.ondemand.com/#/topic/4df1d914e52d4b1aa0805eb01522537e)
【Ruby】クラスとかインスタンスについて改めて学習してみた

[株式会社diffeasy](https://diffeasy.com/)の[中尾](https://twitter.com/ksk_lack)です。
エンジニアになってもうすぐ半年になります。

アドベントカレンダー4日目で何を書こうか迷いましたが、知識がモヤっとしている事を整理しようと思いました。

そこで、普段Railsを使用しているのですが、クラスとかインスタンスが自分の中でモヤっとしていたので「楽しいruby」で復習してみました。
https://www.amazon.co.jp/dp/4797386290/ref=cm_sw_r_tw_dp_U_x_vesbCbC09HZZV

#イメージ
**クラスが型で、その型から生成したものがインスタンス**と良く書かれてますが、スマートフォンでイメージを整理してみました。

![スクリーンショット 2018-09-16 16.29.42.png](https://qiita-image-store.s3.amazonaws.com/0/286594/ae4335e3-0996-81de-0c05-deaab515555a.png)

スマートフォンクラスに、スマートフォン共通の機能を持たせ、Android・iOSインスタンスでそれぞれ独自の機能を持たせるイメージですかね。

#クラスについて
では、クラスについてです。今回は基本的な以下2点まとめてみました。

- クラスの定義
- 初期処理の定義

##コード

```ruby
class HelloWorld

#　初期処理の定義
    def initialize(myname = "Ruby")
        @name = myname
    end

end
```

##クラスの定義
```ruby
 class クラス名
   クラスの定義
 end
```
- クラス名は必ず大文字スタート
- 今回`HelloWorld`というクラスを定義してます。

##初期処理の定義
```ruby
  def initialize
    処理
  end
```
- **initializeメソッド**は、`new`でインスタンスを生成した際、実行されるメソッド
- 詳しくは、次の**インスタンスについて**に実行例を記載してます。

#インスタンスについて
インスタンスについて、実際にコードを書きながら以下4点まとめてみました。

- インスタンス変数とは
- 初期処理実行
- インスタンス生成
- インスタンスメソッド定義
- インスタンスメソッド実行

##コード

```ruby
class HelloWorld

# ①初期処理実行
    def initialize(myname = "Ruby")
        @name = myname
    end

# ②インスタンス生成
    bob = HelloWorld.new("Bob")
    alice = HelloWorld.new("Alice")
    ruby = HelloWorld.new

# ③インスタンスメソッド定義
    def hello
        puts "Hello, world. I am #{@name}."
    end

# ④インスタンスメソッド実行
    bob.hello
    alice.hello
    ruby.hello

end
```

##実行結果

```
Hello, world. I am Bob.
Hello, world. I am Alice.
Hello, world. I am Ruby.
```

##解説

###インスタンス変数とは
- `@変数名`で、インスタンス変数の宣言可
- インスタンス変数は、インスタンス内であれば、メソッドスコープ関係無く参照可
- インスタンス変数は、インスタンスメソッドから参照可

###①初期処理実行
- インスタンス変数`@name`に初期値`Ruby`を代入しているため、引数が何も無かった場合`@name`は`Ruby`になる

###②インスタンス生成
- **クラス名.new**で生成
- 生成したインスタンスを変数に代入可。今回は変数`bob・alice・ruby`でそれぞれ受取。
- **bob = HelloWorld.new("Bob")の場合**、インスタンス生成時に呼び出されるメソッド`initialize`の引数が`Bob`となり、**@nameは引数のBob**となる。※aliceも同様
- **ruby = HelloWorld.newの場合**、インスタンス生成時に呼び出されるメソッド`initialize`の引数は無いため、**@nameは初期値のRuby**となる。

###③インスタンスメソッド定義
- 定義方法

```ruby
def メソッド名
 処理内容
end
```

###④インスタンスメソッド実行
- **インスタンス.メソッド**で実行


#参考にしたリンク
- (インスタンスオブジェクトについて)http://melborne.github.io/2013/02/07/understand-ruby-object/
- (インスタンスメソッドについて)https://qiita.com/tbpgr/items/56eb65c0ea5882abbb07
ガベージコレクション-その①-

##目的
初学の段階では全く意識しなかったインスタンスの取り回しについて考えるため、まずはガベージコレクションなどのJavaの基本的な仕様を抑える

##ガベージコレクションとは?
プログラム実行時にJVMに割り当てられたメモリ容量を管理し、メモリリークが生じないように適宜メモリ領域を解放する機能

###なんでメモリを解放しなくちゃいけないの?
Javaに限らずプログラミングにおいて、Fig1に示すように、各種変数や命令文などはメモリなどに格納されて、適宜CPUにおいて処理される。格納される際は当然メモリの記憶容量を消費するため、プログラムに割り当てられた容量を超えないように**不必要になった変数や命令を消してやる必要がある。**

→容量を超えたら…(Javaの場合)OutOfMemoryError が出てプログラムが強制終了してしまう
![無題のプレゼンテーション.jpg](https://qiita-image-store.s3.amazonaws.com/0/292905/e3b6dab9-08f1-5348-ad02-b027b3635c4a.jpeg)

この時、C言語などではプログラマ側がコード中に明示的にメモリの領域を解放してやらないといけなかったが、Javaなどのオブジェクト指向言語やHaskell等の関数型プログラミング言語においては、Fig.2で示すように今回話題にするガベージコレクションという機能が備わっており、メモリ管理をほぼ自動で行ってくれる。
![無題のプレゼンテーション (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/292905/5b842522-22aa-2c59-d1e5-0c23288f25bf.jpeg)

###自動的にやってくれるならプログラマは何も気にしなくていいんじゃないの?
ところがどっこい、GCが動作する最中でもプログラムは動いている為、適当に不必要なものを消されてしまっては困る。そのため「不必要」の一定の基準を設け、それに従いGCを機能させており、Javaの場合は下記の要素で判定をしている。

**・他のどの要素からも参照されていない**

したがって、設計によってはメモリリークが生じる可能性もある。
また、GCが動作する頻度などによって下記の不具合がでることがある

**・GCが頻発することで処理が滞る**

GCが動作する最中はアプリケーションは一時的に停止状態になってしまうため、頻繁にGCが起こってしまうと不具合を生じる。また、単純にGCの停止時間が長くなる場合もある。
さらには、これは次回記述する予定だがGCにも種類があり、その仕様によってはGCが動作してもメモリが解放されずメモリリークが生じてしまうこともある。

##次回予告
JavaVMにおけるGCとは
UiPathでOutlookのメールメッセージをフィルタする(Get outlook mail messagesのFilterをLikeで使う)


UiPathでOutlookのメールメッセージをフィルタする方法ですが、
メールを取得したあと、メールの繰り返し処理で、1件ごとに件名で判定する方法の情報がほとんどです。
そもそもメール取得時(Get outlook mail messages)に、フィルターをかけたほうが効率がいいので、その対応方法です。

![[uiPath]メールフィルター.png](https://qiita-image-store.s3.amazonaws.com/0/206716/dda87337-d2d4-027b-9ca4-4ad9fbbafe7d.png)

コミニティに対応方法がのっていました。

[I cant get wildcarts to work on filters in mail messages](https://forum.uipath.com/t/i-cant-get-wildcarts-to-work-on-filters-in-mail-messages/144/5)

上記内の記述をコピペしても、ダブルクオーテーションとシングルクォーテーションが全角なので、エラーになります。
正しくは以下です。

```VB:
"@SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & Chr(34)  & " Like '%検索キーワード%'"
```

上記は"件名"の前後方部分一致の条件になります。


他の日付などの検索条件の設定方法は、以下にサイトにまとめられています。

[Outlookで受信したメールを操作してエクセルに転記する](https://uipath.site/use/receivemail.html#Get_outlook_mail_messages)
→　filterプロパティについて 参照
任意パラメータ


#基本は必須パラメータ

パラメータを指定しないでアクセスをするとエラーになってしまうので、基本的にパラメータが用意されていたら、必ず値を入力しなければならない。

この基本的なパラメータのことを**必須パラメータ**という。

#任意パラメータ

基本的員はパラメータが用意されていたら入力しなければならないが、もちろん、入力しなくてもいいようにすることができる。

これは**任意パラメータ**を使用することでできる。

**任意パラメータ**は、その名前の通り「任意につけて利用できるパラメータ」のこと。

パラメータ名の末尾に「?」をつけて宣言する。

そして、第２引数の関数では、値が渡される仮引数にディフォルト値を指定し、引数が渡されなくとも処理できるようにする。

```例.
Route::get('hello/{msg?}',function ($msg='no message.'){..
```

これで、msgパラメータは任意パラメータになる。

パラメータをつけずにアクセスすると、「no message」と表示される。

---
また、この記事は[PHPフレームワークLaravel入門](https://www.amazon.co.jp/dp/4798052582/ref=asc_df_47980525822542427/?tag=jpgo-22&creative=9303&creativeASIN=4798052582&linkCode=df0&hvadid=295678107984&hvpos=1o2&hvnetw=g&hvrand=15604873734545540909&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1028850&hvtargid=pla-526985037105&th=1&psc=1)のアウトプットとして書いてみました。

**自分がまだ理解していない部分を文字で起こすことによって頭の中を整理する**ことが目的です。

本を読むだけじゃなくて、キータとか、ノートとかに書くことによって、理解のレベルが１段階上がる！

一番いいのは他人に説明できるようになんだけど、ちょっとそれはめんどくさ、、、

終
docker と nvidia-docker2 をインストールする

こんにちは、chlochanです。Ubuntu 18.04 + CUDA10 に移行したのですが、CUDA9.0 の環境が必要な場合もあるので、nvidia-docker2 を使って CUDA9.0 の環境を作ります。

## docker をインストールする
まず docker をインストールします。

```bash
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
```
インストール出来たか確認してみます。

```bash
$ sudo docker container run hello-world
$ sudo docker image
$ sudo docker ps -a
```
問題なければ hello-world のコンテナとdockerイメージを削除します。

```bash
$ sudo docker container rm <hello-worldのコンテナID>
$ sudo docker rmi hello-world
```
## nvidia-docker2 をインストールします。
現在、GPUを使うディープラーニング用のツール類は、CUDAのバージョンに依存しています。たとえば TensorFlow Ver1.12 の コンパイル済みバイナリーイメージ は、CUDA9.0 のライブラリが無いと実行時にエラーとなります。よって、使いたいツールが要求するバージョンの CUDA Toolkit をインストールする必要があります。nvidia-docker2 は、Docker のコンテナランタイムで、これを使うと、ホストOS の CUDA Driver を最新のものにしておけば、コンテナ毎に異なるバージョン の CUDA Toolkit を使う事ができる様になり、運用が非常に楽になります。

以下の Quickstart に従ってインストールします。
https://github.com/NVIDIA/nvidia-docker

```bash
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
$ sudo apt-get update
$ sudo apt-get install -y nvidia-docker2
$ sudo pkill -SIGHUP dockerd
```
以下をみたところ、9.0-cudnn7-devel が CUDA9.0 のすべてをインストールするイメージなので、それで動作確認してみます。
https://hub.docker.com/r/nvidia/cuda/

```bash
$ sudo docker container run --runtime=nvidia --rm nvidia/cuda:9.0-cudnn7-devel nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Sep__1_21:08:03_CDT_2017
Cuda compilation tools, release 9.0, V9.0.176
```
V9.0.176 になっている事を確認します。
RailsでSEO対策もバッチリなIntersection Observer（Lozad.js）を使ったlazyload実装方法

#はじめに

「rails環境で作成したサイトが重すぎるからlazyloadを実装して軽くしたい！」
「でもSEO対策としてはlazyloadってダメなんでしょう？」
「どうにかならないの？」
「Lozad.js? .....めっちゃええやん！！」

という男の挑戦である。

##lazyloadとは
スクロールするときに画像を読み込む事で最初のページ表示を軽く早くしようというものだ。
画像を多用したサイトなどで読み込み速度が気になるときにはおすすめ。
しかし問題点もありSEO上あまりよろしくないのだ。

##Intersection Observerとは
これを使うとSEO対策バッチリになるらしい詳しくは自分で調べてね。

https://qiita.com/ryo_hisano/items/42f5980720bc832e6e09
https://qiita.com/yukagil/items/369a9972fd45223677fd
https://qiita.com/yamanoku/items/027308e23cfc69845d7e

しかし問題点は対応していないブラウザもある事である。
しかしpolyfillを使い解決してしまうのだ。



##Lozad.jsとは？
Intersection Observerをベースにしたlazyloadの素晴らしいライブラリである。
このライブラリだ
[github公式Lozad.jsページ](https://github.com/ApoorvSaxena/lozad.js)

このページを読むとわかりやすい
https://qiita.com/yukagil/items/369a9972fd45223677fd
あくまでこの記事はrailsで使用するための補助である。
こちらを参考に進めていく。

まだまだ新しいため英語を解読する場面が多いけど一緒に頑張ろう。

##1、Lozad.jsを読み込む

headタグ内に読み込みを書くだけ
Lozad.jsとpolyfill

```application.html.erb
<head>
.
.
.
 <!-- lazyload関連 -->
 <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js"></script>
 <script src="https://polyfill.io/v2/polyfill.min.js? features=IntersectionObserver"></script>
.
.
.
</head>
```

これでおけ
公式ライブラリのreadmeに書いてあるよ

##2、rails対応する
railsの場合　<%= image_tag ほにゃらら %>的な感じに画像を呼び出すと思うのでこれをhelperでlazyloadな呼び出しに対応させる

具体的には適用したい箇所のhelperに

```helper.rb
def lazy_image_tag(source, options={})
  options['data-src'] = asset_path(source)
  if options[:class].blank?
    options[:class] = 'lozad'
  else
    options[:class] = "lozad #{options[:class]}"
  end

  image_tag('ダミー.gif', options)
end
```
こいつを付け足す。ダミー.gifのところは適当な軽い画像を貼っておこう。これがlazyloadで読み込まれる前の画像となる。つまり一瞬は見える。あまり変な画像にはしないように。

このhelperメソッドを使いこれからは画像を呼び出すのだ。
とはいえ今までの<%= image_tag ほにゃらら %>を<%= lazy_image_tag ほにゃらら %>にするだけで今回はおけである。でも構造は理解しておこう。

##3、jsで呼びだそう

めちゃくちゃ簡単である。Lozad.js万歳！！

```lazyload.js
const observer = lozad();
observer.observe();
```
これだけ、カスタマイズは自分で調べてね

あぁlazyloadになってるなぁ。。。感動

##4、まとめ
めちゃくちゃ簡単でSEO対策もバッチリ
まだまだ新しいライブラリだけど使いこなそう！！

あと宣伝ですけどよかったら僕の作ったサイトもみてください。
競馬ニュースのまとめサイトです。ウマgleって言います。
http://umagle.com
スマホ版の方がデザイン最近頑張ってます。


##参考記事
https://qiita.com/yukagil/items/369a9972fd45223677fd
https://qiita.com/yamanoku/items/027308e23cfc69845d7e
https://qiita.com/ryo_hisano/items/42f5980720bc832e6e09
お三方ありがとうございます。
##公式githubライブラリ
https://github.com/ApoorvSaxena/lozad.js
JiraボードでSprint内のチケット消化状況を確認する

本記事は[AttlassianAdventCalendar](https://qiita.com/advent-calendar/2018/augj)の4日目の記事です。


Jiraのボードは機能が豊富で、何もしなくてもそれっぽい様々なレポートが出るのが特徴です。
そのレポートの中の1つ「累積フローダイアグラム」を使って、チケットの消化状況を確認する方法を紹介します。

## 累積フローダイアグラムとは

Jiraの課題における各ステータスの枚数を時系列にグラフにまとめたものです。
例えば「レビュー待ち」があるタイミングで広がっているなどがわかることで、レビュータイミングを変えてみる、などの改善に繋がります。

図の読み解き方はカンバンプロセスの説明などの中で紹介されていることが多く、このあたりが参考になるかと思います
http://jp4.scaledagileframework.com/team-kanban/


Jiraが用意してくれている機能では以下のカスタマイズが可能です。

* 表示対象期間を絞る
* 表示対象ステータスを絞る
* 集計対象課題を絞る（クイックフィルター）
  - 優先度が高い
  - 自分の課題のみ　　など


## Sprint単位で状況を確認する

以前からこのレポートには興味があり活用したいと考えていましたが、ふりかえりの時点で「**Sprint期間内**」の状況を可視化したいのに、期間外に作った課題が混ざってしまいうまく活用できていませんでした。

こんな表示です。せつないですね。

![レポート1](https://qiita-image-store.s3.amazonaws.com/0/47589/4fa21a64-af44-341f-59cc-50add06e7589.png)

この画面を前にして、なんて使えないレポートなんだと何度思ったことか・・
差分が見えんと意味ないやん。



ですが、これは「**Sprint内のチケットを絞り込むフィルター**」を作ることで解決できます！

1. ボードの設定から「クイックフィルター」を開く
2. JQLというJiraの課題を絞り込むための記載方法を使い、現在のSprintで有効になっている課題に絞るクイックフィルター　「`スプリント in openSprints()`」　を追加（日本語環境でない場合はカラム名がsprintになるかもしれません。
3. 3. 累積フローダイアグラムのグラフ上に「レポートをさらに絞り込む」という機能から今回追加したカスタムフィルターを適用


![クイックフィルター](https://qiita-image-store.s3.amazonaws.com/0/47589/b23b7281-8dfb-e7ea-8cee-1f92315790bf.png)

これでJiraのスクラムボードでSprint内のチケットの消化状況が見えるようになりました！！　
![レポート2](https://qiita-image-store.s3.amazonaws.com/0/47589/3f93a1f0-0d4e-ca78-cddc-df9cbf35dc33.png)

めでたしめでたし。

（注意） Sprint開発ではプランニング時にタスク出しを行うため、このような表示にはならないのが通常かと思いますが良いサンプルがなかっただけです。ラストスパート感がすごいことも読み取れますねｗ


## 最後に

JQLという存在は以前から知っていましたがボード関連の専用関数があるという認識はなかったため、ここにたどり着くまでにかなり時間がかかりました。

ボードの課題表示/非表示やカードの色などもJQLを活用することで自分たちにあったカスタマイズができます。
使える関数のリファレンスはこちらにありますので興味があればご活用ください。
https://confluence.atlassian.com/jiracoreserver/advanced-searching-functions-reference-939937722.html
[mac]Pipenvで「Too many levels of symbolic links」エラーが出るとき

インストールは
`brew install pipenv`
で行いましょう。

macでは
`OSError: [Errno 62] Too many levels of symbolic links: '/Users/~~/.local/share/virtualenvs/test_pipenv-TBkS7NZ_/bin/python'`
が出まして困りましたが、どうやらすでにvirtualenvsを使っている場合にこの問題が起きるようです。自分はvirtualenvsを使った記憶がなかったが、どうやらpycharmの機能で環境を作ったときにこういうフォルダができてしまったらしいです。

virtualenvを再インストールして、さらにエラーメッセージにある`/.../virtualenvs`フォルダと`~/.virtualenvs`フォルダを削除してから再度`pipenv install`したら無事インストールできました。ちなみにvirtualenvの再インストールは
`python -m pip uninstall virtualenv
python -m pip install virtualenv`
どうも既存のフォルダが悪さをしていたような気がするが、果たしてこの３つの手順が全て必要かどうかは確認していません。

ご参考までに
並列化: マルチコア時代の数値計算

# 動機
せっかく、マルチコアのPC持ってるんだから全力で計算させたい。

# サンプルコード
```python
import multiprocessing
import concurrent.futures


def worker(x):
    for _ in range(100):
        y = x**2

    return y


if __name__ == '__main__':
    ncpu = multiprocessing.cpu_count()

    long_list = [i for i in range(int(1e6))]

    with concurrent.futures.ProcessPoolExecutor(max_workers=ncpu) as executor:
        r = executor.map(
            worker, long_list, chunksize=int(len(long_list) / ncpu))

    print([i for i in r])
```

# やってること
```python
with concurrent.futures.ProcessPoolExecutor(max_workers=ncpu) as executor:
```
論理コア数の限界までプロセス (worker) を作る。

```python
r = executor.map(
            worker, long_list, chunksize=int(len(long_list) / ncpu))
```
第１引数の関数オブジェクトに第２引数のiterableの要素をそれぞれ引数として渡して計算してもらい、結果をジェネレータとして返してもらう。chunksizeをそれっぽく設定しないと激遅になるので注意。ここでは長いリストをworkerの数で割った値を入れてみてる。

この２行だけで並列計算が実行できる。簡単。
AWS Toolkits for Visual Studio Code (Preview)を試す。

# こんな人に目を通してほしい
- AWS Lambdaに興味があって、お気に入りのIDEがVisual Studio Codeである。
- これからAWS Toolkits for Visual Studio Codeを試そうと思っている。

# インストール手順

詳しい事はGitリポジトリに書いてありますが、まとめると以下 ステップです。
https://github.com/aws/aws-toolkit-vscode

1. git clone https://github.com/aws/aws-toolkit-vscode.git
1. cd aws-toolkit-vscode
2. npm install
3. npm run package
4. code --install-extension aws-toolkit-vscode-0.0.1.vsix
→試した当時、ツールのバージョンは0.0.1でした。

# アカウント設定

Lambdaの操作を行いたいアカウントを指定するための設定をします。
AWS CLIの設定が済んでいれば特に意識しない設定です。

以下の記事が参考になります。
https://qiita.com/yuyj109/items/3163a84480da4c8f402c

# 実際に試してみる。

インストールすると、左側のメニューにAWSが追加されます。
割とAzure意識した作りかも。

![インストール後.png](https://qiita-image-store.s3.amazonaws.com/0/36448/709c88a4-1aaf-5dde-123c-88b3108020e3.png)

きちんとアカウント設定が完了していればLambdaの一覧が表示され、Lambdaを選択して右クリックをすると以下のメニューが現れます。
![一覧画面.PNG](https://qiita-image-store.s3.amazonaws.com/0/36448/68da9a33-add6-d4d2-341f-dbfda37a9aa1.png)

これは凄い!!とテンション上がりますが・・・

~~Lambda function policyをクリックしても結果が取得できなかったり、
https://github.com/aws/aws-toolkit-vscode/issues/156~~
現在では解決され、取得できるようになっています。

新規でLambdaを作成するをクリックすると「まだ実装されていません」エラーが出ます・・・潔い。
![未実装.PNG](https://qiita-image-store.s3.amazonaws.com/0/36448/d6aadf6b-0107-88e7-0b2a-1d9f8b0290c1.png)


しばらくWatchしていこうと思います。
ジョブカンの打刻を chatwork に通知する Google Apps Script

# きっかけ

- 勤怠管理にジョブカンを使っている
- チャットルームで勤務開始、勤務終了後を自動投稿したい

フレックスで勤務終了予定時間になってもダラダラ仕事を続けてしまいがちになっている。
エンジニアたるもの、定時にあがって自分のやりたい分野の勉強をして自己研鑽したり、
リフレッシュのために家族との時間に充てて翌営業日も最善のパフォーマンスで業務に取り組みたいモノです。

# つくったもの

- ジョブカン勤怠データの読み取り GAS ライブラリ
    - ジョブカンのモバイルページをスクレイピングする
    - 勤怠データのモデル化とか
- ジョブカンが打刻されたことを判定して通知する GAS アプリケーション

# ジョブカン勤怠データの読み取り GAS ライブラリ

■ JobcanAttendanceReader
https://github.com/yamatomo73/JobcanAttendanceReader

## はじめての GAS スクレイピング

ライブラリを探して、いくつかためしたのですがこれがよさげでした。

Easy data scraping with Google Apps Script in 5 minutes ~ kutil.org
https://www.kutil.org/2016/01/easy-data-scrapping-with-google-apps.html

ジョブカンのスクレイピングも、こんな感じにお手軽に
https://github.com/yamatomo73/JobcanAttendanceReader/blob/master/src/AttendanceRecordParser.gs#L20

スクレイピングという、不安定な実現方法なので最大限力をぬいた実装です。
ちょっとデザインが変わっただけでも破綻するので一切頑張らないと心得よ。

# ジョブカンが打刻されたことを判定して通知する GAS アプリケーション

ジョブカンの勤怠記録をスクレイピングするライブラリはつくりましたが、どのように通知するかは考えなければならない。
勤務開始をトリガーに1度だけChatworkに投稿したいし、勤務終了をトリガーに1度岳Chatworkに投稿したい。

せっかくの GAS なので通知したかしないかの状態をスプレッドシートで管理して、通知していなければ通知するようにします。
失敗したときのリカバリもこちらのほうが容易だとおもいますし。

## 用意したスプレッドシート

![image.png](https://qiita-image-store.s3.amazonaws.com/0/191263/eb13719e-c2f1-de51-8b28-6b8c1eab560e.png)

- 日付
    - 勤怠の日付。これがキーとなる
- ステータス / 勤務開始 / 勤務終了
    - ジョブカンの値をそのまま転記する。ただのコピーなのでいらないのだけど、今後スプレッドシート上でなにか集計したくなるかもとおもっただけ。
- 開始通知 / 退勤予告 / 終了通知
    - 通知したかどうかの状態をここに永続化して判定に使う

## アプリケーション実装

■jobcan_notifier_to_Chatwork
https://github.com/yamatomo73/jobcan_notifier_to_Chatwork

## 使用法

1. 上記のスプレッドシートを用意する
2. `yyyyMM` 形式 (201812) のようなシート名にする
3. 作成したスプレッドシートのスクリプトエディタに良い感じとりこむ（※ライブラリはとくに一般公開してないので）  
[JobcanAttendanceReader](https://github.com/yamatomo73/JobcanAttendanceReader)  
[jobcan_notifier_to_Chatwork](https://github.com/yamatomo73/jobcan_notifier_to_Chatwork)
4. アプリケーションの設定を「スクリプトのプロパティ」に設定する  
https://github.com/yamatomo73/jobcan_notifier_to_Chatwork/blob/master/controller/endpoint.gs#L8-L14

## 業務時間や定時時間の業務ロジックの修正

その辺の実装は [WorkRegulation](https://github.com/yamatomo73/JobcanAttendanceReader/blob/master/src/WorkRegulation.gs) というクラスにまとまっています。
これは自分の勤務形態ごとに実装を変える必要があります。
今の実装は

- 勤務時間は8時間
- 休憩時間は1時間

というだけのルールです。
始業時間固定や稼働時間が15分単位、30分単位の勤務形態であったりするとロジックを変更する必要があります。

# まとめ

公式APIがないサービスと連携しようとすると、スクレイピングという不安定なことをやらざるを得ません。
スクレイピングをやるなら力を抜いて、実装すること、ただ、変更を前提に。
あと、優しくスクレイピングしましょう。大量にアクセスする必要があるなら sleep して、多重度もさげてあげてください🙇
ブロックチェーンとハードウェアマイナー

# 背景と目的

Haskell Advent Calendar 2018 4日目の記事です。
もう少しHaskellの話題に触れたかったので力及ばず申し訳ないです。

話題のブロックチェーンであるビットコインですが、オープンなデータベース上で2重支払いをできないようにするためにみんなの計算機のパワー（POW）で独裁者がでないようにしているところがすごいですね。

実際には10%以上握っているマイナーがいます。特にbitmain社のAntPoolはASICマイナーです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15901/d7cb7af4-fbfc-05a9-2cda-0f9bcfe885fd.png)

最近売り出し中のものはbitmain社の[s9i](https://shop.bitmain.com/promote/antminer_s9i_asic_bitcoin_miner/overview?flag=overview)で14.5TH/sでます。どういうテクノロジーならここまでいけるのか、また超えることはできるのか推測しました。考察の結果51%を大幅に超えることができば2重支払いや新しいコインをほとんど集められることでしょう。

# bitmain社のs9iはASICマイナーでそのパワーは？

bitmain社のs9iはASICマイナーです。ASICがGPUやCPUよりはるかに強いのは命令のためのメモリをもたず、演算器の使用率を100%引き出すことができる点です。
IntelのCPUではCPUに比べメモリは遅いのでハイパースレッディングやマルチコアを利用して演算器が遊ばないように工夫されていますが限界があります。

ASICマイナーは1サイクルに1ハッシュのスループットを出すのが容易です。
bitcoinのハッシュはSHA256ですが、掛算もなくメモリへのアクセスも不要なため回路も小さく作れます。10段程度のパイプラインで作って、雑に見積もると256bit x 3 x 10 x 10 = 76kgate程度でしょうか。これは8bitマイコン程度で大変小さいです。

これを1Ghzで動かすと1GH/sですね。

s9iは一台に[189個のASIC](https://shop.bitmain.com/promote/antminer_s9i_asic_bitcoin_miner/specification)を詰めているそうです。

最新の[AppleのA11では4.3Bトランジスタ](https://pc.watch.impress.co.jp/docs/column/kaigai/1083247.html)だそうなので一チップで14TH/s（下記にて計算）いけそうです。

```
4.3*(1000^3)/(4*76800) = 14 TH/s 
```

# 何チップあれば51%とれるか？

14TH/sでるチップがいくつあれば51%とれるでしょうか、bitcointのhashrateは40EH/sなのでおよそ290万個あればとれそうです。（下記にて計算）

```
(40*1000*1000)/(14)= 290万個
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15901/3efacebe-8358-3e04-727a-f7d6603322c4.png)

290万個なので一チップ千円でつくることができれば29億円で51%とれそうですね。

# どうやってASICつくるの？

ようやく本題でどうやってASICつくるのかです。もちろんHaskellです。
まず、Haskellでbitcoinを既存の実装にならって実装します。

[こちらの記事](https://qiita.com/hidehiro98/items/841ece65d896aeaa8a2a)をみて[Haskell版](https://github.com/junjihashimoto/blockchain-hs/blob/master/src/Lib.hs)をつくります。おそらく本当のbitcoinとはなにかが違う気もしますがこの際気にしないことにします。

次にPOWの肝であるハッシュのプログラムをHaskellで書き直します。
Crypto.HashはC言語で書かれているのでそれを参考にして[Haskell版](https://github.com/junjihashimoto/blockchain-hs/blob/master/src/Sha256.hs)を作成します。

Haskell版のハッシュ計算のプログラムを[Clash](https://clash-lang.org/)にかけ[Verilog版](https://github.com/junjihashimoto/blockchain-hs/tree/master/hdl/verilog/Sha256)をつくります。
これは段数が一段だけなので1GHzで動作することはできないです。高速化は次回の課題にします。

# まとめ

bitcoinのASICマイナーの簡単な紹介とHaskellによるASICマイナー作成のトライアルを行いました。また51%をとるために必要なASICの個数をざっくり見積もってみました。
SharedPreferencesの@Nullableは実質的に@NonNullという話

## SharedPreferences の <span>@</span>Nullable問題
問題の発端は SharedPreferences の getString の処理はこのように定義されていることにある。

```Java:SharedPreferences.java
@Nullable
String getString(String key, @Nullable String defValue);
```
戻り値に <span>@</span>Nullable のアノテーションが指定されているため、getString で取得した値をnullチェックせずに使用するとチェックツールに怒られる。
ところが、時には設計上絶対に null にはならない処理もある。nullチェックを書けばそれはデッドコードになるだろう。しかし書かなければチェックツールに怒られる。

書けば **デッドコード**、書かなければ **規約違反**、さてどうしよう。

## というわけで実験
全部で4x3パターンしかないので、どんなときに null が返却されるのか見てみよう。

```Java:実験.java
SharedPreferences pref = getSharedPreferences("🤔", Context.MODE_PRIVATE);

String key0 = "key0";
String key1 = "key1";
String key2 = "key2";
String key3 = "key3";

// key0はputStringしない
pref.edit().putString(key1, null).commit();
pref.edit().putString(key2, "").commit();
pref.edit().putString(key3, "🎁").commit();

String result00 = pref.getString(key0, "");
String result01 = pref.getString(key0, null);
String result02 = pref.getString(key0, "🎁");
.... 省略 ....
String result11 = pref.getString(key3, "🎁");
```

このプログラムの結果を表にすると以下となる。

|↓デフォルト値/設定値→|なし|null|"" (空文字)|🎁|
|:---|:---|:---|:---|:---|
|"" (空文字)|""|""|""|🎁|
|null|**null**|**null**|""|🎁|
|🎁|🎁|🎁|""|🎁|
おわかりいただけただろうか....

## 結論

デフォルト値に null を指定して、ぬるぽの危険性をわざわざ仕込む必要もないので、
### 第2引数のデフォルト値に null を指定しない限り <span>@</span>NonNull と考えて問題ない



SharedPreferences の get〇〇 メソッドを包むラッパーがいてくれるといいなって。

```Java:SharedPreferencesWrapper.java
@NonNull
public String getString(String key, @NonNull String defValue) {
    .... 省略 ....
}
```

## おまけ 

#### Q. そもそも実験するまでもなくソース見れば一目瞭然ですよね？
A. 全くもってその通りで SharedPreferencesImpl の処理を最初に見ればよかったのです

```Java:SharedPreferencesImpl.java
@Nullable
public String getString(String key, @Nullable String defValue) {
    synchronized (this) {
        awaitLoadedLocked();
        String v = (String)mMap.get(key);
        return v != null ? v : defValue;
    }
}
```

#### Q. SharedPreferencesってinterfaceですよね？
A. はい、そうです。
そのため、自分で実装クラスを書いていて、引数のデフォルト値以外からnullを返すような実装をしている場合はこの限りではありません。
~~まぁ、自分で SharedPreferences を実装している人なんて圧倒的少数だと思いますが....~~
paizaの問題をSwiftでやってみた時に躓いたこと

#【経緯】
社内もくもく会にてSwiftを行ってました。今までは[Progate](https://prog-8.com/)さんでもくもくしていましたが、問題をやり切ってしまったので[paiza](https://paiza.jp/)さんの問題で基礎構文の再確認を行ってました。
その中で、幾つか躓いたポイントがあったので記載しておきます。

# 【1. readLine()の扱い】
競技プログラミングやこういうオンラインでの問題系を全然やってこなかったので、そもそもreadLine()の扱いから躓きました。
値出力・取得サンプルコードのページはあるんですが、Swiftのサンプルは無かったので他言語のサンプルとにらめっこしたり検索しながら四苦八苦するはめに。

~~~Swift:
while let str: String = readLine() {
    print(str)
}
~~~


# 【参考】
・https://www.aipacommander.com/entry/2015/12/23/154814
・http://itnewbie.hatenablog.com/entry/2017/09/07/200451
・https://qiita.com/hirothings/items/9e2d184349c7650d8bbe


# 【2. 文字列分割】
paizaはSwift3なので、String.components(separatedBy:)を使用するとのこと。
が、こういう0ベースからのプログラミングをやってないから「import Foundation」の記述を忘れてエラーと戦ってました。
stackoverflowでドンピシャの記事を見つけて、「確かに・・・」ってなりました。

~~~Swift:
import Foundation
~~~

# 【参考】
・http://itnewbie.hatenablog.com/entry/2017/09/07/200451
・https://qiita.com/keizokeizo3/items/e488869a175371188a73
・https://stackoverflow.com/questions/43642506/swift-3-string-has-no-member-components?noredirect=1&lq=1

# 【3. ログを改行しない（結局使わなかったので豆知識的に）】

~~~Swift:
print("My name is swift.", terminator: "")
 
// 実行結果 : "My name is swift."
~~~
# 【参考】
・https://egg-is-world.com/2015/11/26/swift2-print-newline/


# 【4. C言語スタイルforループについて】
手癖でどうしても書いちゃうC言語スタイルの話があったので

~~~Swift:
for i in (0 ..< 100) {
    print("\(i)")
}
~~~
# 【参考】
・https://qiita.com/codelynx/items/899c26dd2cbdba7d2b00

# 【所感】
やっぱりまだ手が自動で動くレベルでは実装出来ないなーという感じです。調べながらやっていって何とか記載できる感じ。
とはいえランク低いのばっかりやっていたので、ロジック自体に悩むことは無く、ほぼ検索とトライ＆エラーの繰り返しだけで回答出来たので問題の回答時間自体は短くてすみました。
こういうのを何度もやっていくと身につくんだろうなと思いますが、いかんせん触る機会がない・・・。。。
コンピューターがたくさんあっても解けない問題

# コンピューターがたくさんあっても解けない問題

* 問題提起
   * 規模が大きい問題はHadoopを使えば大丈夫、と思っていませんか？
   * 分散コンピューティングをしたとしても、対応できないタイプの問題が存在します。
   * 計算量の観点から、コンピューターで解ける問題と解けない問題を知りましょう。

* コンピューターがたくさんあっても解けない問題の例

   * 問題の説明
      * 5人で2人3脚をする場合(5人6脚)の最も良い並び方を知りたい。
      * 5人の並び方を入力すれば、シミュレーションする機能(関数やクラス)がすでにあるとする。
      * 最も良い並び方を知るには、すべての並び方のパターンでシミュレーションする必要がある。

   * 並び方のパターンはいくつあるだろうか？

      * 3人の場合

         * 以下のようになるので、パターンは全部で6通り

            ```
            A - B - C
              \
                C - B
            B - A - C
              \
                C - A
            C - A - B
              \
                B - A
            ```

      * 4人の場合
         * 以下はAを最初にしたパターン。これがほかに3ケースある。(Bを最初にしたパターン、ｃを最初にしたパターン、Dを最初にしたパターン)。
         * 以下にあるようにAを最初にしたときのパターン数は6通りで、それが4通りあるため、総パターン数は6 × 4 の 24通りとなる。

            ```
            A - B - C - D
                  \
                    D - C
               \
                C - B - D
                  \
                    D - B
               \
                D - B - C
                   \
                    C - D
            ```

      * 5人の場合
         * 4人の場合は、3人のパターン数(6通り) × 4通りの24通りとなった。
         * 5人の場合は、4人のパターン数(24通り) × 5通りなので、24 × 5の120通りとなる。

      * 一般式
         * 3人の場合: 3 × 2 × 1 = 6
         * 4人の場合: 4 × 3 × 2 × 1 = 24
         * 5人乗場合: 5 × 4 × 3 × 2 × 1 = 120
         * n人の場合: n × (ｎ - １) × (n - 2) × ... × 1
            * n! と表記する。

* 問題の規模と計算量の関係を可視化する
   * ![人数とパターン数の関係.png](https://qiita-image-store.s3.amazonaws.com/0/321994/3a7dec08-6485-4b56-dc7b-7f2f3ed3a735.png)
      * 問題の規模(人数)が増えると、パターン数が爆発的に増加する。

* 人数が増えたらどうなるか？
   * 5人のときは、5分で計算ができるとする(120パターンの計算に5分かかる)。10人になったら、どうなるだろうか？
      * 5人のパターン数: 120
      * 10人のパターン数: 3628800(5人のパターン数の30240倍)
      * 5分 × 30240 = 151200分(2520時間)

* こういったものが、コンピュータがたくさんあっても、解けないタイプの問題
   * 計算量が爆発的に増加する問題(計算量のオーダーが、指数関数的な増加傾向を示すもの)
   * 計算量が問題の規模と比例するなら、まだ対応可能
      * その場合、問題の規模が多くなった分だけ、コンピューターを用意すれば良い。(10倍の規模になったら、10倍のコンピュータを用意すれば良い)

* では、例えば、このようなケースはどうだろうか？

   * 問題
      * 10人11脚をする。
      * もっともよい並び方を知りたい
      * 並び方を与えれば、シミュレーションする機能(関数)があるとする。

   * 解法(アルゴリズム)
      * すべての組み合わせを算出し、シミュレーションする。
      * PCで計算すると、それに10分かかるとする。

   * その後、仕様変更が起きたとする。
      * お客さんの要望で、10人から15人になる(15人14脚)。
      * そのかわり、PCの倍の速さで計算できるサーバが10台手に入る。(20倍の速さで計算できるようになったとする)
      * 1日(24時間)で、結果を出さねばならない。

   * 果たして対応できるか？
      * 10人の場合の並び方の総数: 3,628,800
      * 15人の場合の並び方の総数: 1.30767E+12
      * 問題の規模(並び方の総数)は、360360倍になる。
      * 計算時間はどうなるか？
         * pcの場合: 10分の360360倍なので、3603600分。(60060時間)
         * サーバを使えば、pcの20倍の速さで計算できるので、60060時間 ÷ 20 = 30003時間(125日)
      * 結論: 全然無理

   * 結果、どうなるか？
      * 仕様変更となってしまい、設計からテストまで全部やり直し。

* このような例ではどうだろうか？
   * 問題
      * 100の特徴量の候補があり、この中から、最も良い特徴量の組み合わせを知りたい。
   * 条件
      * 抜き出す特徴量の数は3つとする。
      * 3つの特徴量を与えれば、モデルを計算する機能(関数)があるとする。
   * 100の特徴量から3つを抜き出すパターンをすべて算出する場合、1時間かかるとする。
   * 120の特徴量になった場合、実用的な時間で問題を解けるだろうか？
   * あるいは、110ならどうだろうか？ 130なら？
   * またあるいは、抜き出す特徴量の数が変わったら？
Ionic Tips

```bash:新規プロジェクト作成
npx -p ionic ionic start <project-name>
cd <project-name>
npm install -D ionic cordova ios-deploy
```

```bash:実機ビルド
# 新規
npx ionic cordova build ios -- --buildFlag="-UseModernBuildSystem=0"
「MyApp.xcodeproj」をXcodeで開く
Signing > Team > Personal Team
Identity > Bundle Identifier > xxx.xxx.xxx
File > Workspace Settings > Legacy Build System
Run!!

# 更新
vim config.xml
---
<widget id="io.ionic.starter"
↓
# Bundle Identifierと同じにする
<widget id="xxx.xxx.xxx"
---
npx ionic cordova build ios -- --buildFlag="-UseModernBuildSystem=0"
「MyApp.xcodeproj」をXcodeで開く
Run!!
```
C++での擬似的な名前付き引数(c++17以前版)

#はじめに
関数の引数が増えると、デフォルト値が指定してあっても、最後の引数だけ指定できない。そのため、結局デフォルト値を調べながら、指定する必要あります。
kotlinなど名前付き引数がある言語なら、個別にパラメータを指定できてうらやましい。まあ、boostにも名前付き引数があるけど、引数名をマクロを使って指定する必要があって手間がかかる。
ということで、なんとかできないか考えみたら、C++11/14で追加された機能を使っていい感じに実装できたので公開します。

*kazatsuyuさんに、C++2aでは"designated initialization"という機能が規格化される予定であることを教えてもらいました。この機能を使うと、より少ない記述量で擬似的な名前付き引数を実現できます。"designated initialization"は、最新のClangやGCCには実装済みですので、それらが使えない場合の過渡期の記述方法と考えてほしいです。なお、本記事の記述方法を使えば、"designated initialization"に準拠した記述方法に、比較的簡単に書き換え可能です。

参考URL https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers
(追記　2019/2/9)

C++20版を記事にしました。
https://qiita.com/luftfararen/items/1f8c356711f69151e909
(追記　2020/7/3)

#事前準備
まずは、以下のヘッダーファイルを準備。

```C++:named_args.h 

#if !defined(NAMED_ARGS_H_)
#define NAMED_ARGS_H_
#include "functional"

template<class T>
using init_args = std::function<void(T&)>;

#define ARGS [&](auto& _)
#define INIT_ARGS_DEF = [&](){}

#endif
```


#使い方（サンプルコード）

```C++:main.cpp

#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "named_args.h"

//引数のリストは構造体として定義し、デフォルト値を指定
struct to_str_args
{
	int base = 10;
	char fill = ' ';
	int w=0;
	int precision = 5;
	bool fixed = false;
};

//関数１
template<class T>
std::string to_str(T v, const to_str_args& a = to_str_args())
{
	std::stringstream ss;
	ss << std::setfill(a.fill);
	ss << std::setbase(a.base);
	ss << std::setw(a.w);
	if (a.fixed) ss << std::fixed;
	ss << std::setprecision(a.precision);
	ss << v;
	return ss.str();
}

//関数2
template<class T>
std::string to_str(T v, init_args<to_str_args> init)
{
	to_str_args args;
	init(args);
	return to_str(v,args);
}

int main()
{
	std::cout << to_str(12.345) << std::endl;
	std::cout << to_str(12.345, ARGS{_.w = 6; }) << std::endl;
	std::cout << to_str(12.345, ARGS{_.w = 7; _.precision = 3; _.fill = '0'; }) << std::endl;

	//"designated initialization"への移行を前提とする場合、以下は非推奨→詳細は解説を参照のこと
	std::cout << to_str(12.345, ARGS{_.precision = 3; _.fill = '0'; _.w = 7;}) << std::endl;}
```

#結果
12.345
012.345
00012.3
00012.3

#解説
引数は構造体として定義しておく。ポイントは、関数２のようなinit_args<構造体> を引数にもつ関数を定義し、コール時にARGS{\_.XXX=NNN;}といった形で、引数名と値を｛｝内に定義し、これを引数として渡す。これで、擬似的に名前付き引数を実現。{}で値の設定を行わなければ構造体にで指定したデフォルト値が使われます。

ちなみに、関数１のような構造体を引数に持つ関数は必須でないですが、パラメータセットを使い回すときには構造体変数を宣言したほうが便利なので、今回は実装した例をサンプルとしました。関数１を定義しない場合は、関数2の第二引数のデフォルト値にINIT_ARGS_DEFにしておくとよいです。INIT_ARGS_DEFは何もしないラムダ式です。

```cpp
template<class T>
std::string to_str(T v, init_args<to_str_args> init = INIT_ARGS_DEF)
{
	to_str_args args;
	init(args);
	//実装
}
```
c++2aで規格化予定の"designated initialization"への移行を前提とする場合は、関数1を定義し、関数コール時には、構造体変数の定義順で引数を指定しておいてください。"designated initialization"には、指定順に制約があります。


#さいごに
「構造体を定義するなら、名前付きに引数にする必要ない」じゃんというツッコミは、許して下さい。少しは呼び出し側の記述量が減らせるはず。ただ、本質的には、文法レベルでの対応を標準化してほしいところです。あと、標準でプロパティがほしい。
AdView の Height が広告読み込み中にゼロになる件（AdMob）

バナー広告の表示があるアプリで、広告の読み込みに時間がかかってその表示が遅れたとき、
**画面がカクつく現象**のことです。

例えば、ConstraintLayout の最上部にバナー広告のビューAがあって、
そのビューAの下に何らかのビューBがあるとします。
（ビューAの `id` が adView で、ビューBに `layout_constraintTop_toBottomOf="@id/adView"` が設定されている）

①アクティビティの onCreate で、広告の読み込み処理（loadAd）をコール。
　↓
②読み込み処理中はビューAの高さがゼロになる（onWindowFocusChanged で確認済）。
　↓
③ネットワークの問題などで読み込み処理に時間がかかる。
　↓
④読み込み処理が終わる前に画面表示が行われ、レイアウトの最上部にビューBが表示されて見える。
　↓
⑤読み込み処理が終わってビューAの高さがゼロではなくなり、広告の高さの分だけビューBが下にずれる。

結果、画面がカクついてダサいという具合です。
ボタンやリンクなどがずれて押し間違えたりするとイラっとします。

対処方法を考えたので投稿します。

# 前提
`adSize` は `SMART_BANNER` のみで確認しています。
`firebase-ads` のバージョン 17.1.1 を使っています。

どのバージョンでも起きる現象なのかどうかは把握していないです。
少なくとも 17.0.0 と 15.0.1 でも起きていました。
もっと前のバージョンも使ってはいましたが、広告の読み込みが早く終わると気付かない（？）ので、
昔からあったものなのかどうかは、よく分からないまま。
複数種のスマホ実機で見られたので、メーカーや機種へ依存したものではなさそう。

# 対処方法
`loadAd` を呼ぶ前に、`AdView` の `minimumHeight` に対して `SMART_BANNER` の高さの規定値をセットして、ゼロにならないようにする。
こうすると広告の読み込み中でも、`AdView` の表示エリアは潰されずに空白としてそのまま表示されます。

``` MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var mAdView: AdView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        MobileAds.initialize(this, "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX")
        mAdView = findViewById(R.id.adView)

        // AdView の minimumHeight に規定値の高さをセットして広告読み込み中に高さゼロにならないようにする
        mAdView.minimumHeight = AdSize.SMART_BANNER.getHeightInPixels(this)
        // 広告の読み込みに失敗したら AdView の minimumHeight をデフォルトのゼロに戻す
        mAdView.adListener = object : AdListener() {
            override fun onAdFailedToLoad(p0: Int) {
                super.onAdFailedToLoad(p0)
                mAdView.minimumHeight = 0
            }
        }

        // 広告の読み込み処理をコール
        mAdView.loadAd(AdRequest.Builder().build())
    }
}
```

# 補足
上記の対処方法を使ったとしても、広告の読み込みに失敗した場合では注意点が1つあります。
それは広告の表示エリアを高さゼロに戻しているために、読み込み失敗までに時間がかかってしまうと、
広告用の空白エリアが潰れるのが見えて、やっぱり画面をカクつかせてしまうという点です。
ネットにつながらない場合なら対応しようがないので、これはもうしょうがないですね。
広告切れで読み込み失敗が起きる（真偽は不明）というのも聞いたことがあるので、
`onAdFailedToLoad` で別の広告ネットワークに切り替えるのもありかもしれません。

広告を読み込めなかったときに空白エリアを残しておくのが問題ないレイアウトであれば、
`minimumHeight` をゼロに戻さずにそのままにしておいてもいいです。
（そういうレイアウトなら今回紹介した方法自体が不要だと思いますが）

ちなみに、[AdView - REFERENCE](https://firebase.google.com/docs/reference/android/com/google/android/gms/ads/AdView) を見ても `minimumHeight` のデフォルト値についての説明などは見つけられませんでした。