OmniAICreator/Qiita-1.07M huggingface dataset:
optunaの設定方法（探索空間の書き方）

#Optunaでハイパーパラメーターを設定する方法をメモします。

ハイパーパラメータを最適化するフレームワークのOptunaの使い方。これは Preferred Networks が作ったものです。

公式チュートリアル
https://optuna.readthedocs.io/en/stable/tutorial/first.html
APIリファレンス
https://optuna.readthedocs.io/en/stable/reference/index.html

目的関数と探索空間を定義します。
次に`study`インスタンスを建て、`optimize`メソッドで最適化を行います。

```
import optuna

#目的関数の定義
def objective(trial):
    #ここに探索空間を記載


    return ***目的関数**最大化でも最小化でも良い***

```

探査空間は、
`trial.suggest_`  で設定します。
整数、カテゴリーなどで、以下のように渡します。

`suggest_categorical(name, choices)`では、例では、'kernel'というパラメーターに３つを選んで入ります。
`suggest_int(name, low, high, step=1, log=False)`では、整数パラメータの値を与えます。
`suggest_uniform(name, low, high)`では、`low`、`high`の間で、線形で連続値を与えます
`suggest_loguniform(name, low, high)`では、対数区間での連続値を与えます。
`suggest_float(name：str、low：float、high：float、*、step：Optional [float] = None)`では、浮動小数点パラメーターの値が入ります。
`suggest_discrete_uniform(name, low, high, q)`で,値は`low`、`high`の範囲からサンプリングされ、離散化の数値はステップqで与えられます。

```
def objective(trial):
#探索空間の与え方
    # Categorical parameter
    kernel = trial.suggest_categorical('kernel', ['linear', 'poly', 'rbf'])

    # Int parameter
    num_layers = trial.suggest_int('num_layers', 1, 3)

    # Uniform parameter
    dropout_rate = trial.suggest_uniform('dropout_rate', 0.0, 1.0)

    # Loguniform parameter
    learning_rate = trial.suggest_loguniform('learning_rate', 1e-5, 1e-2)

    # Discrete-uniform parameter
    drop_path_rate = trial.suggest_discrete_uniform('drop_path_rate', 0.0, 1.0, 0.1)
```



```
# ハイパーパラメータの自動最適化
study = optuna.create_study()
#n_trials で探索する繰り返し回数を設定します。
study.optimize(objective, n_trials = 100)

```
【Redmine】チケット編集画面の「説明」を初期表示で開くカスタマイズ

## できること
Redmineでチケット編集画面を開いた際、[編集]のリンクをクリックしないと説明の編集欄が展開されません。
<img width="1076" alt="チケット編集画面の説明編集リンク" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293128/c1e6250c-d573-a7bb-82cd-ec25b4241957.png">

この説明の編集欄を、編集画面を開いた直後から展開された状態にするカスタマイズです。
<img width="1073" alt="チケット編集画面の説明編集欄" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293128/878b8272-6be9-f55f-2f49-f2769b3830eb.png">

社内にて、「説明を編集したいのにどこからやれば良いか分からない」という意見が上がったため対応しました。


## コード
```js:view_customize
/*
Path pattern: issues/[0-9]+
Type: JavaScript

説明の編集欄を初期表示から展開する。
*/
$(function() {
  $('#issue_description_and_toolbar').show()
    .prev().hide();
})
```

## 補足
私もRedmine使い始めたとき疑問だったんですが、説明の編集欄ってなぜ初期表示で展開されないんでしょう… 編集頻度が高くないから？
なにか理由ありそうなので、時間があれば調べてみたいです。
Ruby と Python で解く AtCoder ABC172 C 累積和 二分探索

# はじめに
*[AtCoder Beginner Contest 172](https://atcoder.jp/contests/abc172)* に参加しました。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

# 今回のお題
*[AtCoder Beginner Contest C - Tsundoku](https://atcoder.jp/contests/abc172/tasks/abc172_c)*
<font color="green">Difficulty: 878</font>

今回のテーマ、累積和 + 二分探索

最初は、動的計画法と考え解いていましたが`TLE`を貰い~~大幅な時間のロス~~、二分探索に切り替えました。
入力例1ですと、次の表の各行で、机Aと机Bの累積和がK分を超えない本数の最大値を求めます。

|1|2|3|4|5|6|7|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|60|90|120|80|150|80|150|
|60|90|80|150|80|150|
|60|80|150|80|150|
|80|150|80|150|
# Ruby
```ruby.rb
n, m, k = gets.split.map(&:to_i)
a = gets.split.map(&:to_i)
b = gets.split.map(&:to_i)
c = Array.new(n + 1, 0)
n.times do |i|
  c[i + 1] = c[i] + a[i]
end
d = Array.new(m + 1, 0)
m.times do |i|
  d[i + 1] = d[i] + b[i]
end
cnt = 0
0.upto(n) do |i|
  break if c[i] > k
  e = d.bsearch_index{_1 > k - c[i]}
  if e.nil?
    cnt = i + m if cnt < i + m
  else
    cnt = i + e - 1 if cnt < i + e - 1
  end
end
puts cnt
```
```ruby.rb
c = Array.new(n + 1, 0)
n.times do |i|
  c[i + 1] = c[i] + a[i]
end
d = Array.new(m + 1, 0)
m.times do |i|
  d[i + 1] = d[i] + b[i]
end
```
累積和です。

```ruby.rb
  e = d.bsearch_index{_1 > k - c[i]}
  if e.nil?
    cnt = i + m if cnt < i + m
  else
    cnt = i + e - 1 if cnt < i + e - 1
  end
```
二分探索です。配列の最大値を超えた場合、`nil`を返しますので、その処理が入っています。
# Python
```python.py
from sys import stdin
import bisect

def main():
    input = stdin.readline
    n, m, k = map(int, input().split())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    c = [0] * (n + 1)
    for i in range(n):
        c[i + 1] = c[i] + a[i]
    d = [0] * (m + 1)
    for i in range(m):
        d[i + 1] = d[i] + b[i]
    cnt = 0
    for i in range(n + 1):
        if c[i] > k:
            break
        e = bisect.bisect_right(d, k - c[i])
        if cnt < i + e - 1:
            cnt = i + e - 1
    print(cnt)
main()
```
```python.py
        e = bisect.bisect_right(d, k - c[i])
        if cnt < i + e - 1:
            cnt = i + e - 1
```
二分探索です。配列の最大値を超えた場合、配列の`要素数+1`を返します。

||Ruby|Python|
|:--:|:--:|:--:|
|コード長 (Byte)|433|570|
|実行時間 (ms)|349|246|
|メモリ (KB)|44860|47636|
# まとめ
+ ABC 172 C を解いた
+ Ruby に詳しくなった
+ Python に詳しくなった

参照したサイト
*[bisect --- 配列二分法アルゴリズム](https://docs.python.org/ja/3/library/bisect.html)*
[Google Colab] 複数の画像をタイル状に並べてサムネイルの様に表示したい

Google Colaboratory で画像系の処理を行う際、複数の画像を表示して比較したいときがあります。単純にループの中で一枚一枚表示させると縦にスペースを使いスクロールが大変なので、なるべく横に並べてスペースを有効活用したい。

確認はしてませんが、Jupyter Lab/Notebookでも動作するかもです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599028/6ae2f3f6-db6a-2947-70f0-9a1418d1f16b.png)


# Numpy.ndarrayとして読み込んだ画像の一括表示

## 必要パケージのインポート(コピペ用)

```python
import matplotlib.pyplot as plt
```

## 関数として定義(コピペ用)

```python
def show_images(images, figsize=(20,10), columns = 5):
  plt.figure(figsize=figsize)
  for i, image in enumerate(images):
      plt.subplot(len(images) / columns + 1, columns, i + 1)
      plt.imshow(image)
```

## 画像読み込み例

今回は、Kerasを利用して読み込めるCIFAR-100のデータセットを利用します。

```python
from keras.datasets import cifar100

(x_train, y_train), (x_test, y_test) = cifar100.load_data(label_mode='fine')
images = x_train[:10]
```

## 呼び出し例

```shell
show_images(images)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599028/d2896f05-7df3-efb8-6945-9ff1d8de80cb.png)


```shell
show_images(x_train[:100], figsize=(10,15), columns = 10)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599028/0e93f470-d4f9-84ed-5b58-bed17e88de32.png)

パラメータは多少調整が必要ですね。


# Googleドライブやアップロードした画像ファイルの一括表示

## Googleドライブをマウント

ファイルを直接Colabにアップロードした場合はこのステップは不要です。

```
from google.colab import drive
MOUNT_DIR = '/content/drive' #マウントする場所を指定
drive.mount(MOUNT_DIR)
```

実行すると、`Go to this URL in a browser: ` にリンクが表示されるのでこれを開き、マウントするGoogleDriveのあるアカウントを選択肢し、アクセスを許可すると、コードが表示されます。

このコードを `Enter your authorization code:` に入力します。

```bash
ls /content/drive/MyDrive/PATH_TO_IMAGE_DIRECTORY/
```

中身を確認します。
※ PATH_TO_IMAGE_DIRECTORYはGoogleDrive上のパスです。

## 必要パケージのインポート(コピペ用)

```python
import cv2
from glob import glob
import matplotlib.pyplot as plt
import os
```

## 関数として定義(コピペ用)

```python
def show_images_glob(images, figsize=(20,10), columns = 5):
  plt.figure(figsize=figsize)
  for i, image in enumerate(images):
      plt.subplot(len(images) / columns + 1, columns, i + 1)
      plt.imshow(cv2.imread(image))
```

## ファイル読み込み例

```
SOURCE_IMAGES = "/content/drive/MyDrive/PATH_TO_IMAGE_DIRECTORY"
FILE_PATTERN = "*.jpeg" #ワイルドカードでフィルタリング
images = glob(os.path.join(SOURCE_IMAGES, FILE_PATTERN))
```

`SOURCE_IMAGES` には画像が存在するColab上のディレクトリパスを指定
`FILE_PATTERN` はワイルドカードですべてのjpeg画像を指定しています。

## 呼び出し例

```shell
show_images_glob(images)
```

![example_glob_thumbnail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599028/6674ce16-e3a5-c46a-f9c3-cb434043fbb6.png)

縦横比が違っていても表示できたようです。

# 参考

* [Keras CIFAR-100](https://keras.io/ja/datasets/)
* https://stackoverflow.com/questions/19471814/display-multiple-images-in-one-ipython-notebook-cell
* [OpenCV(cv2) imread](http://opencv.jp/opencv-2.1/cpp/reading_and_writing_images_and_video.html#cv-imread)
環境を汚さずに Composer を使いたい

# 要約

* Docker には Composer イメージがあって Docker Compose から使うと便利
* [使い方とサンプルコード](https://github.com/SnowCait/docker-compose-composer-example)

# Composer どうやって実行してますか？

PHP 開発に [Composer](https://getcomposer.org/) は必須です。
ではどうやって実行しているでしょうか。

* ローカルで composer コマンドを使う
    * ローカルにインストールする
    * composer.phar をコミットする
* Docker コンテナで composer コマンドを使う
    * PHP コンテナにインストールする
        * 自前インストール
        * Composer イメージを使ってインストール
    * コミットされた composer.phar を PHP コンテナ内で使う
    * Composer コンテナを使う
        * Docker で使う
        * Docker Compose で使う **← 今回はこれ**
* GitHub Actions で composer コマンドを使う

様々な実行方法があると思います。
ローカルで composer コマンドを使うには PHP もインストールしないといけません。
ローカルに環境を構築するのは大変です。チームメンバー全員の面倒なんて見たくありません。
そこで Docker コンテナの出番です。
よく見かけるのは PHP コンテナに Composer をインストールする方法です。
ですが Composer を使うのはライブラリのインストール（復元）時だけです。
稼働中の PHP コンテナに果たして必要なものでしょうか？
そこで今回は独立した Composer コンテナでコマンドを実行する方法を紹介します。

# Composer コンテナ

[composer - Docker Hub](https://hub.docker.com/_/composer)

`docker` コマンドで直接使用する方法は [ComposerをDockerコンテナで動かす - Qiita](https://qiita.com/PitPat/items/dc1ad09f7936b8825473) を、
PHP コンテナにインストールする方法は [Docker に Composer をインストールするベストプラクティス（と解説） - Qiita](https://qiita.com/yatsubashi/items/02bbbebbfe7e5a5976bc) を参考にしてください。
この記事では独立した Composer コンテナを `docker-compose` コマンドで使用する方法を紹介します。
PHP コンテナは不要なので Composer だけ使いたい方にもおすすめです。

## Docker Compose で定義する

```yml:docker-compose.yml
version: "3.8"

services:
  composer:
    image: composer
    command: "composer install"
    volumes:
      - ./:/app
```

`./:/app` は `:` の前がローカルのディレクトリパス、後が composer コンテナ内のパスです。
ローカルは composer.json, composer.lock を作成したい場所、 composer コンテナは `/app` を指定します。

## ライブラリのインストール (composer require)

```bash
docker-compose run composer composer require --dev phpunit/phpunit
```

`composer` が 2 つあるのは 1 つ目がコンテナ名（変更可）で 2 つ目がコマンド名です。

## ライブラリの復元 (composer install)

docker-compose.yml に `command: "composer install"` を定義しておけば `docker-compose up -d` する際に自動的に `composer install` が実行されます。定義しなくても良いです。

もちろんコマンドでも実行できます。

```bash
docker-compose run composer composer install
```

## ライブラリのバージョンアップ

`composer.lock` の更新。

```bash
docker-compose run composer composer update
```

## その他のコマンド

他のコマンドも同様に `docker-compose run composer` から実行できます。
どんなコマンドがあるかは [PHP開発でComposerを使わないなんてありえない！基礎編 - Qiita](https://qiita.com/niisan-tokyo/items/8cccec88d45f38171c94) を参照してみてください。

## サンプルコード
[SnowCait/docker-compose-composer-example](https://github.com/SnowCait/docker-compose-composer-example) にサンプルコードを置いています。
Docker がインストールされていれば git clone して気軽に試せると思うので良かったら試してみてください。

## 参考にした記事

[Docker環境でcomposerのimageつかってupdateしてみる - Qiita](https://qiita.com/yuya_sega/items/a8f2c3c58ae3762c0458)
補足：リンク先では `command: "composer update"` となっていますが起動する度にバージョンが変わるのはよろしくないので `command: "composer install"` にしておいた方がいいのではないかと思います。

# 余談
(Docker) Compose と Composer が似ていて間違えそう。
COCOONでElementorの見出し２にグラデーション付ける

WordPressの無料のテーマ「COCOON」で、見栄えのするページを投稿できるElementorというプラグインを使うとき、見出し２でグラデーションの設定が出来ないです。
どうやらCOCOONのテーマの見出し２H2が、競合してしまうようです。

そのため、私は、ElementorのウィジットのHTMLを使い、下記のソースコードでグラデーションを実現しました。
![スクリーンショット 2020-06-28 7.56.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/fa0bd9cf-2179-7fef-df57-10498bf43720.png)


```html
<style>
.h2_org{
    background: rgb(9,121,29);
background: -moz-linear-gradient(90deg, rgba(9,121,29,1) 0%, rgba(81,200,224,1) 100%);
background: -webkit-linear-gradient(90deg, rgba(9,121,29,1) 0%, rgba(81,200,224,1) 100%);
background: linear-gradient(90deg, rgba(9,121,29,1) 0%, rgba(81,200,224,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#09791d",endColorstr="#51c8e0",GradientType=1);
color:#ffffff;
}
</style>
<h2 class="h2_org">テスト</h2>
```
styleでcssのコードをHTMLの中に、書いています。
classの名前を指定して、COCOONのテーマのh2と競合しないようにしました。
見出し２で指定する文字の色も、必要ならstyleの中で書くと良いと思います。

グラデーションのコードは、下記のグラデーションジェネレーターを使いました。
[https://cssgradient.io/](https://cssgradient.io/)


![スクリーンショット 2020-06-28 8.08.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/eaaae32b-523a-fbbf-1904-905ae5c72f65.png)
Rustの型推論のおかげで逆にデバッグに苦労した。

RustでAtCoderに挑み始めて2週間弱の初心者です。
Rustは型に厳密なおかげでバグにも気づきやすくて便利だなーと思っていたら、なかなか解けないバグに遭遇したので紹介します。

# 問題
AtCoderの過去問を解いていたら、こんなのに出会いました。[^3]

[ABC159 D - Banned K](https://atcoder.jp/contests/abc159/tasks/abc159_d)

解き方は会っているはずなのに、なぜか提出すると幾つかのケースでWAになってしまう。TLEじゃなくてWA、ということでかなり悩みました。ついでにJavaScriptで書いてみたら簡単にパスするし、ロジックは正しい筈…。

[^3]: 実はこの問題に最初に遭遇したのはこちらじゃなくて、[A - Zero-Sum Ranges](https://atcoder.jp/contests/agc023/tasks/agc023_a)でした。こちらではRustでの回答者自体が他にいなかったため、ACコードを参考にすることもできず、とりあえずJavaScriptでACすることだけ確認できたので、原因不明のままいったん諦めました……。

かなり悩んだのですが、こういう時は他人のコードを参考にするに限ります。少しずつACのコードとの差分を縮めていったところ、ついに通るコードとダメなコードの差分を発見しました。[^1]
[^1]: 見やすくするために実際に提出したコードよりちょっと整理してます。
さて、下記のコードの何が問題だったでしょう？

## ダメなコード

```Rust
use std::collections::HashMap;
fn main() {
    proconio::input! {
        n:usize, A:[usize;n]
    }
    let mut B = HashMap::new();
    for i in 0..n {
        *B.entry(A[i]).or_insert(0) += 1;
    }
    let mut sum = 0;
    for (_, &v) in B.iter() {
        sum += v * (v - 1) / 2; // <----注目
    }
    for i in 0..n {
        let val = B.get(&A[i]).unwrap();
        let ans = sum + 1 - val;
        println!("{}", ans);
    }
}
```

## OKなコード

```Rust
use std::collections::HashMap;
fn main() {
    proconio::input! {
        n:usize, A:[usize;n]
    }
    let mut B = HashMap::new();
    for i in 0..n {
        *B.entry(A[i]).or_insert(0) += 1;
    }
    let mut sum = 0;
    for (_, &v) in B.iter() {
        sum += combination(v); // <----注目
    }
    for i in 0..n {
        let val = B.get(&A[i]).unwrap();
        let ans = sum + 1 - val;
        println!("{}", ans);
    }
}
 
fn combination(v: usize) -> usize {
    v * (v - 1) / 2
}
```

見てわかるように、2つ目のfor文の中で、${}_n\mathrm{C}_2$を計算する際、インラインで処理しているか関数を呼び出しているかという、ただそれだけの違いです。
ここから小一時間悩んで、漸く原因に思い当たりました。

# 原因判明
一言でいうと、

- vとsumがi32で扱われるためオーバーフローが発生する

というのが原因です。[^2]
[^2]: 最初は容量を宣言していないHashMapあたりが原因かと思っていたのですが、問題はそこじゃありませんでした。HashMapの定義時に型を宣言していないために気付きにくかったという点では、無関係とも言えませんが…。

一方、OKな例では、combination関数の引数と戻り値が usize であるため、コンパイル時に行われる型推論によって、vとsumも usizeになります。これは実質的にu64です。

実際、それぞれの最大値を考えてみると下記のようになります。

- i32の場合: $2^{32-1}-1 \risingdotseq  2 \times 10^9$
- u64の場合: $2^{64}-1 \risingdotseq 16 \times 10^{18}$

一方この問題の制約では、$N$は$2\times 10^5$(20万)以下となっています。したがって$A_i$がすべて同じ値の時に$v=N$となり、$v^2$は最大で$N^2=4 \times 10^{10}$になるので、確かにi32だとオーバーフローしてしまいます。

というわけで、型推論の手がかりさえ与えてあげれば、関数呼び出しを行う必要はありません。
下記のコードでもACになります。この場合、sumの型がi32ではなくusizeと推論され、そこからvもusizeと推論されるため、オーバーフローは発生しません。

```Rust
use std::collections::HashMap;
fn main() {
    proconio::input! {
        n:usize,  A:[usize;n]
    }
    let mut B = HashMap::new();
    for i in 0..n {
        *B.entry(A[i]).or_insert(0) += 1;
    }
    let mut sum = 0usize;   // <--型を指定
    for (_, &v) in B.iter() {
        sum += v * (v - 1) / 2;
    }
    for i in 0..n {
        let val = B.get(&A[i]).unwrap();
        let ans = sum + 1 - val;
        println!("{}", ans);
    }
}
```

# まとめ
Rustの型推論は強力ですが、手がかりの無い数値がi32になることを忘れると痛い目に遭う、というお話でした。[^5]

[^5]: まあ競プロじゃなければ入力値もわかるため、もう少し早めに気付いた気もしますが……。
Python 3 エンジニア認定基礎試験に合格した方法

#資格を取得した背景
去年までIT業界以外の分野で働いていました。
#成績
![20200628_041422.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577830/272828e4-4708-d321-d687-0ddd878c3a90.jpeg)

新宿で受けて、
試験自体は20分程度で終わりました。
試験結果は画面に速攻で出てきました。

#勉強法（主に3つ!）
##①atcoder（競技アルゴリズムコンテスト）
**コードをただ書くだと本当に続かない**ので友達に聞いたサイトで問題を解きながらpythonの文法を覚えました。
下記のリンクでAtCoder Beginner Contest で無料で勉強できます。アカウントは必要
[Atcoderリンク](https://kenkoooo.com/atcoder/#/table/)
下記が答えです。コードを一旦、試したいときはコードテストで実行してみましょう。
PCとネット環境さえあればOK!
下記が問題A108の答え

```
a,b = map(int,input().split())

if a == 2 or b == 2:
    print("No")
else:
    print("Yes")
```


atcoderについて詳しい情報は割愛します。
本サイトのキーワードで調べた方が詳しく知れると思いますので、、、、



##②Pythonチュートリアル 第3版
試験範囲なので買いました。（紙が良かったので）
**これはとにかく読みました。**
下記のリンクでどの章に力を入れて勉強するかを決めて読みました。
[重要項目リンク](https://ccie-go.com/python-exam-study/#toc31)
ただよくわからないところは飛ばしました。


##③模擬試験
下記のリンクで模擬試験が受けられます。全て無料で行えました。
確かアカウントが必要だったと思います。
[無料模擬試験リンク](https://exam.diveintocode.jp/exam#exam-list)
チュートリアルを読んで6回目くらいで合格ラインまで行きました。

#まとめ
多分、急いで資格が必要な人には向いていない勉強方法です。
pythonの文法をできるだけ楽しく、問題を解きながら勉強していました。
次はデータ分析の方へチャレンジしていきます。
UdemyのPythonコースをやってみる〜

# きっかけ
最近もう一度Pythonを勉強し直そうと思ったからちょっと前に購入していたUdemyのPythonコースを最初からやってみました。

# とりあえず始めよう
久しぶりにPythonを触るので初歩の初歩から

```python:test.py
print("Hello World")
```

そんでもって変数

```python:test.py
a = 12
b = 14

total = a + b
# 26が出力されるよ
print(total)
```
次はString
ここで初めてf""の存在を知る。。
(お前は本当にかつてPythonを学んだのか？？という疑問はさておき)

```python:test.py
name = "Bob"
greeting = f"Hello,{name}"
# Hello Bobが出力されるよ
print(greeting)

name = "Tom"

print(f"Hello,{name}")
# Hello Tomが出力されるよ
```

そしたら次はInput
なんとなくcm⇛inchに変換するようにしてみる

```python:test.py
size_input = input("How tall you are in cm? : ")
hight_cm = int(size_input)
hight_inc = hight_cm * 0.39
print(f"{hight_cm} cm is {hight_inc: .2f} inches.")

#出力
# How tall you are in cm? : 178
# 178 cm is  69.42 inches.

```

で、最後にまとめ
さっきのコードをちょっといじって入力された年数を月に変換するようにしてみたよ

```python:test.py
age_input = int(input("How old are you?"))
age_month = age_input * 12
print(f"You are {age_input} old then {age_month} months.")

#出力
#How old are you?33
#You are 33 old then 396.
```

#今回は一旦ここまで
本当に初歩の初歩過ぎて記事をアップすることも恥ずかしいけどとりあえず忘備録兼自分のモチベアップのために上げていきます。
次はList,Tuple,setあたりから忘備録をつけていこう。
セグ木と似たようなことが出来るアルゴリズムまとめ

# セグ木と似たようなことが出来るアルゴリズムまとめ

セグ木(区分木 / Segment tree)は前処理と引き換えにある種の区間クエリが *O*(*N*) ではなく *O*(log<i>N</i>) で出来る競プロ界隈でよく見かけるアルゴリズムである. 似たようなことが出来るアルゴリズムがいくつかあるので、違いをまとめてみた.

## Segment tree

*O*(*N*<sup>2</sup>) は通らないけど、*O*(<i>N</i>log<i>N</i>) は通るという制約の問題は多いので、何かと頼りになる.

* 対応している操作: 結合則が成り立つ操作、+, Min/Max, GCD, Bitwise Xor/Or 等
* 必要なメモリ量: *O*(2<i>N</i>)～*O*(4<i>N</i>)
* 前計算の計算量: *O*(<i>N</i>)
* 更新の計算量: *O*(log<i>N</i>)
* クエリの計算量: *O*(log<i>N</i>)

## BIT (Binary indexed tree) / Fenwick tree

制約がきついが実装は簡単で、定数倍も軽め.

* 対応している操作: + のみ
* 必要なメモリ量: *O*(*N*)
* 前計算の計算量: *O*(0)
* 更新の計算量: *O*(log<i>N</i>)、加算のみで指定の値に更新とかは出来ない
* クエリの計算量: *O*(log<i>N</i>)

## Sparse table

更新ができず、操作に冪等性が必要と制約が厳しいが、クエリの計算量 *O*(1) は魅力.

* 対応している操作: 結合則が成り立ち冪等性を持つ操作、Min/Max, GCD, Bitwise Or 等
* 必要なメモリ量: *O*(<i>N</i>log<i>N</i>)
* 前計算の計算量: *O*(<i>N</i>log<i>N</i>)
* 更新の計算量: 更新は不可能
* クエリの計算量: *O*(1)

## Disjoint sparse table

Sparse table の上位互換? まだ調査/実装してないのでよく分からない.

* 対応している操作: 結合則が成り立つ操作、+, Min/Max, GCD, Bitwise Xor/Or 等
* 必要なメモリ量: *O*(<i>N</i>log<i>N</i>)
* 前計算の計算量: *O*(<i>N</i>log<i>N</i>)
* 更新の計算量: 更新は不可能
* クエリの計算量: *O*(1)

## Sqrt tree

今見つけたところなのでほとんど分からないけど、今まで聞いたことなかったということは有名ではない?

* 対応している操作: 結合則が成り立つ操作、+, Min/Max, GCD, Bitwise Xor/Or 等
* 必要なメモリ量: *O*(<i>N</i>loglog<i>N</i>)
* 前計算の計算量: *O*(<i>N</i>loglog<i>N</i>)
* 更新の計算量: *O*(√N)
* クエリの計算量: *O*(1)
アコーディオンの開閉時にアイコンを変える

# プログラミングの勉強日記
2020年6月28日　Progate Lv.148
ポートフォリオ作成中
前回作成したwebページの調整をしている

##目標物
　[こちらの記事](https://qiita.com/mzmz__02/items/27210fb86167e4f6473a)でアコーディオン機能について説明している。（今回はアコーディオン機能については触れない）
　アコーディオンメニューで以下のようにアイコンを切り替えたい。アコーディオン機能を利用して写真のようにアコーディオンが閉じているときはメニューバーのFont Awesomeを表示して、アコーディオンが開いているときは「×」のFont Awesomeを表示したい。

<img width="460" alt="0628.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/43f24aa3-7d07-931a-e20f-a9f0ab333cc1.png">

<img width="469" alt="0628-1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/4cbda6ea-1058-f8b8-88d5-22de5cf589f5.png">

##コード

```html:HTMLファイル
<div class="navigation">
  <span class="fas fa-bars naviTop"></span>
    <nav>
      <ul>
        <li><a href="#iceland">Iceland</a></li>
        <li><a href="#aurora">Aurora</a></li>
        <li><a href="#blueLagoon">BLUE LAGOON</a></li>
        <li><a href="#london">London</a></li>
        <li><a href="#paris">Paris</a></li>
        <li><a href="#iceland">Iceland</a></li>
        <li><a href="#spain">Spain</a></li>
        <li><a href="#map">Map</a></li>
        <li><a href="#food">Foods</a></li>
      </ul>
    </nav>
</div>
```

<b>childrenメソッド</b>：指定したセレクタが持つ子要素（1階層だけ下）の中から指定したセレクタに合致した要素を取得したいときに使う。

<b>removeClassメソッド</b>：指定した要素から指定したクラスを取り除ける。
　　HTML：`<p class="text-contents text-active">...</p>`
　　jQuery：`$('.text-contents').removeClass('text-active');`

<b>addClassメソッド</b>：指定した要素にクラスを追加できる。
　　HTML：`<p class="text-contents">...</p>`
　　jQuery：`$('.text-contents').addClass('text-active');`
　　text-contentsクラスのついた要素にtext-activeというクラスを追加する。

　これらを利用すると、アイコンの切り替えができる。
　　1. childrenメソッドで`navigation`クラスの1つ下の階層の中から`span`タグに合う要素を取得する。
　　2. removeClassメソッドでクラスを取り除く。
　　3. addClassメソッドでクラスを追加する。
　　
実際にコードは以下のようになる。


```js:jsファイル(jQuery)
$('.naviTop').click(function(){
    // メニューバーが開かれているなら
    if($('nav').hasClass('open')){
      $('nav').removeClass('open');
      $('nav').slideDown();

      // Font Awesomeを×にする
      $('.navigation').children('span').removeClass().addClass('fas fa-times naviTop');

    }
    // メニューバーが開かれていないなら
    else{
      $('nav').addClass('open');
      $('nav').slideUp();

      // Font Awesomeをメニューバーにする
      $('.navigation').children('span').removeClass().addClass('fas fa-bars naviTop');
    }
});
```

##感想
　classの操作であるのに、最初はhtmlメソッドやtextメソッドで変えようとしてしまって、なかなかうまくいかなかった。この1つの機能をつくのに時間がとてもかかったが、復習をする良い機会になった。
ここが悲しいよ競技プログラミング

#お断り
低パフォガチ冷えで炊いてる心理状態で自分の良くない感情を吐き出すために記載しているだけ、、、
多分この記事を見る人はみんな知ってる特定サイトに関する悲しい点も記載していますが、
殊更に名前を揚げて批判したいわけではないので、伏せておきます……。
みんな少しは悲しくなったことあるのではないでしょうか。。。そうでない人もアンチパターンとして見ていただけると幸いです
AC数100強であまえんなよというのはそのとおりです。。。

#本題
* 数強有利
    * 茶コーダーにとっては競技プログラミングというよりかは競技数学の感が強い。 
    * 数学的思考力(具体的に値を代入して実験してみるとか、変数AとBがあったらAを固定して考えてみるとか)を持たないと茶色で一生詰まる~~っていうか詰まってる~~。
    * 「まず全探索を考える」とよく謳われるが、にも関わらず「全探索するだけでもらえる部分点」が無い等、想定解まで計算量が落ちないと0点の仕組みになっている。そのため、試験中に全探索することや多少計算量を落としてみることにインセンティブを感じることが難しい。~~令和のゲームとしては駄目なのでは？~~
    * 基本的に誘導がサンプル入出力のみ。大学入試問題でも誘導無しは非常に稀なので、一生最高峰の入試問題をやってる気分(競技プログラミングとはそのようなものなのかもしれない)。
    * 詰まる茶コーダーは一生ここで詰まるのに(当方調べ)、ノウハウにアクセスできない…………(だれかオススメの特訓法を教えてほしいです)
    * 思考過程を示す解説は本当に稀(大学入試の解説もそう。)
    * そもそもハードなコーディングを要求される問題が稀にしか出題されず、ゴリゴリ系には不利な問題体系。
* 高度なアルゴリズム/データ構造を練習しても大してレートに反映されない
    * 例えばダイクストラ法を学んでも茶コーダーのレートにはほぼ寄与しない。単にダイクストラ法を適用するだけの問題は出ないから。出題されるのは拡張ダイクストラで、解くためには茶コーダーから抜け出す数学的思考力が必要なため。
    * 競技プログラミング関連記事の多くに、水色になるためにはこのアルゴリズムを学ぼう！　と記載されているが、茶コーダーは適用できず頭の隅で用語だけ覚えてホコリを被っている。
    * (もちろん問題セットと噛み合ったときの爆発力には寄与すると思うので無意味ではないが…)
* 問題難易度に疑問を感じる
    * 問題に対する点数は開催前に決まっているので、『「点数低いけど解けた人数が少ない問題」を解けて「点数高いけど解けた人数が多い問題」を解けてない』ときにはパフォーマンスは低く出る(たぶん)。おかしいのでは…？
    * 点数と難易度(解けた人数が多いをかんたんとすると)を完全一致させるのが不可能なら、動的に点数を出すべきでは……
    * rated範囲をはるかに超える高難易度問題が出題される。rated最大値+800とかの問題が出た際には貴重な問題枠を潰さないでほしいと涙目になる
    * 理想の問題難易度は灰-茶-緑-(緑or水)-水-青または灰-灰-茶-緑-水-青だと個人的には考えるが、「1-3問目は灰だが4問目は水色」、「3問目に水が来て4問目に青が来る」等々、地獄の様相を呈する回や参加しても全く無意味になる回が存在する。(正直もっと難易度調整にコストを掛けてほしい。。。一年かけて作るわけではないから、不安定なのは理解するけど……)  

#最後に
次の色目指して一緒に頑張りましょう。
docker-compose.yml のマイナーバージョンを省略してはいけない

# version
`docker-compose.yml` のサンプルコードでマイナーバージョンが省略されているのをしばしば見かけます。
しかし省略して `version: "3"` と書いた場合 `version: "3.0"` 扱いになってしまいます。
最新のバージョンを使いたい場合はマイナーバージョンまで指定します。

```yml:docker-compose.yml
version: "3.8"
```

## 公式ドキュメント
[Compose file versions and upgrading | Docker Documentation](https://docs.docker.com/compose/compose-file/compose-versioning/#version-3)

>Note: When specifying the Compose file version to use, make sure to specify both the major and minor numbers. If no minor version is given, 0 is used by default and not the latest minor version. As a result, features added in later versions will not be supported. For example:

```yml:docker-compose.yml
version: "3"
```

>is equivalent to:

```yml:docker-compose.yml
version: "3.0"
```
【Java】parallelStreamでプログラムを10倍速にする

## 結論
`parallelStream()` によってJavaプログラムは10倍速くなる可能性がある

## 環境
* CPU：Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz、2208 Mhz、6 個のコア、12 個のロジカル プロセッサ
* メモリ：16GB
* Java：Amazon Corretto-11.0.3.7.1

## 検証内容
### 検証用コード

```Main.java
import java.util.List;
import java.util.ArrayList;

public class Main {
	public static void main(String[] args) {
		List<Integer> n1 = new ArrayList<>();
		List<Integer> n2 = new ArrayList<>();

		for(int i = 0; i < 500; i++) {
			n1.add(i);
			n2.add(i);
		}

		long s1 = System.currentTimeMillis();
		n1.stream().forEach(i -> { try { Thread.sleep(10); } catch(Exception e) { e.printStackTrace(); } });
		long t1 = System.currentTimeMillis();

		long s2 = System.currentTimeMillis();
		n2.parallelStream().forEach(i -> { try { Thread.sleep(10); } catch(Exception e) { e.printStackTrace(); } });
		long t2 = System.currentTimeMillis();

		System.out.printf("n1 exec time: %d [ms]\n", t1 - s1);
		System.out.printf("n2 exec time: %d [ms]\n", t2 - s2);
	}
}

```

取り立てて解説する点はあまりないです。`n1` は順次ストリームで、 `n2` は並列ストリームで500回 `Thread.sleep(10)` を呼び出してい ます。try-catchしているのは `Thread.sleep()` の検査例外に対応するためです。`forEach` の中の`i`は虚空に消えています。

### 実行結果
```
n1 exec time: 5298 [ms]
n2 exec time: 505 [ms]
```

`n2` は `n1` に比べて10倍以上速くなってます！
`n1` は10ms × 500回の結果が如実に現れていますね。

## 補足
[公式ドキュメント](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ForkJoinPool.html)によると、デフォルトの並列スレッド数は、コンピュータで利用できるプロセッサの数と等しいそうです。

> For applications that require separate or custom pools, a ForkJoinPool may be constructed with a given target parallelism level; by default, equal to the number of available processors. 

並列ストリームでの実行時間が順次ストリームのものの1/10以下になっているところを見るに、物理プロセッサ数ではなく論理プロセッサ数がデフォルト値として適用されているようですね。
「10倍速くなる」...って[おま環](https://wa3.i-3-i.info/word18334.html)じゃねーか！！　という大変もっともなツッコミはあると思いますが、最近のPCなら大抵8論理プロセッサくらいはあると思うので許してください。


## 注意
各スレッドで共通して参照しているオブジェクトを更新したり削除したりする操作は、基本的にしないほうがいいです(Listに対するaddなど)。
Activiti 6 のインストール

試したのでメモ

# 前提
- JDK インストール済み
- Tomcat インストール済み

# 手順

1. あらかじめ Activiti 6 の WAR ファイルをサーバに配置しておく

    ```sh
    # curl -LkvOf https://github.com/Activiti/Activiti/releases/download/activiti-6.0.0/activiti-6.0.0.zip
    ```

2. Activiti 6 実行用ユーザを作成する

    ```sh
    # useradd activiti
    ```

3. Activiti 6 用のディレクトリを作成する

    ```sh
    # mkdir /opt/activiti
    ```

4. Tomcat のディレクトリを作成したディレクトリ内に配置する

    ```sh
    # mv /root/apache-tomcat-8.5.56 /opt/activiti/tomcat
    ```

5. デフォルトで配置されている Web アプリを `tomcat/webapps` から削除する

    ```sh
    # rm -rf /opt/activiti/tomcat/webapps/*
    ```

6. Activiti 6 の WAR ファイルを `tomcat/webapps` 配下に配置する

    ```sh
    # cp /root/activiti-*.war /opt/activiti/tomcat/webapps/
    ```

7. `tomcat/bin/setenv.sh` ファイルを作成する

    ```sh
    # vi /opt/activiti/tomcat/bin/setenv.sh
    ```
    
    ```sh
    CATALINA_PID=$CATALINA_HOME/activiti.pid
    
    ### 以下は JDK 11 のときに記載
    CATALINA_OPTS="--add-opens=java.base/java.lang=ALL-UNNAMED \
        --add-opens=java.base/java.io=ALL-UNNAMED \
        --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"
    export CATALINA_OPTS
    ```

8. 所有者を変更する

    ```sh
    # chown -R activiti: /opt/activiti
    ```

9. サービスファイルを作成する

    ```
    [Unit]
    Description=Activiti Service
    
    [Service]
    Type=forking
    User=activiti
    PIDFile=/opt/activiti/tomcat/activiti.pid
    ExecStart=/opt/activiti/tomcat/bin/startup.sh
    ExecStop=/opt/activiti/tomcat/bin/shutdown.sh
    
    [Install]
    WantedBy=multi-user.target
    ```

10. 起動する

    ```sh
    # systemctl daemon-reload && systemctl start actitivi
    ```
【Vue】オブジェクト追加・削除には注意が必要👮‍♂️

# Vueでオブジェクトを変更したい時どうするか？

この記事は[【Vue】配列の追加・削除には注意が必要👮](https://qiita.com/_masa_u/items/f9076777b044673eea2a)のオブジェクト版です。

Vueの`data()`関数で返すステート（オブジェクト）についての話。

取得は通常のJSのオブジェクトの操作と同様にキーを使えば問題なかったが、
追加と削除で嵌ったので備忘録として残しておく。

以下、参考にしたページ

- [リアクティブの探求
](https://jp.vuejs.org/v2/guide/reactivity.html#%E5%A4%89%E6%9B%B4%E6%A4%9C%E5%87%BA%E3%81%AE%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85)

次のようなVueコンポーネントの`data()`で`charaObj`という空のオブジェクトを返すとする。
つまり、このコンポーネントでは、初期ステートとして`charaObj`というオブジェクトが存在することになる。

```js:hoge.vue
// 初期状態のステート
export default {
  data () {
    return {
      charaObj: {}
    }
  }
}
```
## プロパティを追加する
プロパティを追加したい時、通常のJSのオブジェクト同様`obj.key = val`とやってしまいたくなるがこれだとリアクティブにデータが反映されない（＝データ更新しても画面(HTML)上に反映されない）ので、ダメということらしい。

```js:NG
// リアクティブにデータが反映されないのでこの書き方はダメ
this.charaObj.hero = '範馬刃牙'
```

プロパティを追加したい時は`$set`を使う。

慣れない書き方だが、これでリアクティブにプロパティを追加できる。
第１引数にプロパティの追加先のオブジェクトを、第２引数にキー、第３引数に値を渡す。

```js:OK
// リアクティブになるやつ
this.$set(this.charaObj, 'hero', '範馬刃牙')  // => this.charaObj: {hero: '範馬刃牙'}
```

### オブジェクトを追加したい
複数のプロパティをもつオブジェクトを追加したい場合はよくあるだろう。
この場合はスプレッド演算子`...`を使って追加したいプロパティを含むオブジェクトを展開すればOK。


```js:スプレッド演算子を使ったやり方
this.charObj = {...this.charObj, parent: '範馬勇次郎', friend: '烈海王'}
```

または`Object.assign()`を使って新しいオブジェクトを作って代入する方法でもできるらしい。

```js:Object.assign()を使ったやり方
this.charaObj = Object.assign({}, this.charaObj, {parent: '範馬勇次郎', friend: '烈海王'})
```

## プロパティを削除する
追加の時と同じで、いつも通りに削除しようとするとリアクティブにならない。

```js:NG
// リアクティブにデータが反映されないのでこの書き方はダメ
delete this.charaObj.hero
```

プロパティを削除したい時は`$delete`を使う。第１引数に対象のオブジェクトを、第２引数に削除したいプロパティのキーを渡す。

```js:OK
// リアクティブにデータを削除
this.$delete(this.charaObj, 'hero')
```
### 全削除したい

最初、空のオブジェクトを再代入で初期化できないかと考えたが、うまくいかなかった。

```js:NG
// 再代入はうまくいかない
this.obj = {}
```

この場合は、キーの配列を`Object.keys()`で取得してループで`$delete`を使って削除したところうまくいった。

```js:OK
// プロパティを全削除 
Object.keys(this.charObj).forEach(key => {
    this.$delete(this.charObj, key)
})
```

リアクティブにコンポーネントのステートを削除するには先に書いた`$delete`を使う。

### プロパティを全て入れ替えたい

オブジェクトを一度空にしてからまとめて追加すればよい


## オブジェクト自体を削除したい
あまり使うケースは無さそうだが、プロパティではなくステート自体（コンポーネントのトップレベルのプロパティ）を削除したい場合はどうするか？

`$delete`を使いたくなるところだが、トップレベルプロパティを削除する時に`$delete`を使おうとすると警告が出るので使っちゃダメっぽい。

```js:NG
// トップレベルのプロパティを削除しようとエラーが出る
this.$delete(this, 'charObj')

```

この場合は`null`を入れればよいみたい。

```js:OK
// charObjを削除する
this.charObj = null
```
Java: 5種類のstaticをさらっと説明する

# 概要

Javaの「static」には5つの種類がある。しかし、それぞれは似て非なるものである。
本記事では、それぞれのstaticについて、落とし穴にハマらないための要点を説明する。
もっと詳しく知りたい場合は、記事最後の参考資料などを参照されたい。

# 1. staticメソッド

メソッドにstatic修飾子が付与されていると、staticメソッドとなる。

```java
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}
```

staticメソッドは、インスタンスをnewしなくても呼び出すことができるため、一見便利に思える（使いやすそうに見える）。
しかし、[単体テストを書きやすくするためには、「決まりきった処理」のみに利用すべき](https://qiita.com/flyaway/items/34069ca6ad9ada4c0fef#%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E5%8E%9F%E5%89%87%E3%83%AB%E3%83%BC%E3%83%AB)である。

# 2. staticフィールド

フィールドにstatic修飾子が付与されていると、staticフィールドとなる。

```java
public static final double PI = 3.14159265358979323846;
```

上記のように、**final修飾子と一緒に利用する**ことで、定数として利用することができる。
final修飾子と一緒に利用することで、プログラムのどこかで値を書き換えられ、誤った計算結果を出力してしまうなどのバグを防ぐことができる。

なお、システムの設計によっては、キャッシュの保持などにも利用することができる。



# 3. 【中級者向け】staticインポート

外部のクラスのstaticフィールドや staticメソッドを、クラス名を指定せずに呼び出すことができるようになる。

```java
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

public class SampleTest {
    @Test
    public void Test() {
        assertThat("foo", is("foo"));
    }
}
```

上記のサンプルでは、`Assert.assertThat`や`Matchers.is`について、クラス名を省略して記述することができている。

# 4. 【中級者向け】staticインナークラス

インナークラスにstatic修飾子が付与されていると、staticインナークラスとなる。

```java
public class Outer {
  public static class Inner {
    // staticインナークラス
  }
}
```

非staticなインナークラスは親クラスのフィールドやインスタンスメソッドにもアクセスできる。
このため、親クラスへの参照を保持している。

しかし、不必要な親クラスへの参照は、メモリやGCへの悪影響[^1]が懸念される。
**インナークラスをstaticにできる状況であれば、staticにすべき**[^2]である。


# 5. 【中級者向け】staticイニシャライザ

下記のブロック内に記載した処理は、そのクラスに初めてアクセスされる時に呼び出される。

```java
static {
  // 処理
}
```

具体的には、staticフィールドのコレクションの初期化などに利用する[^3]。

```java
public static final List<String> LIST;
static {
    List<String> tmp = new ArrayList<>();
    tmp.add("foo");
    tmp.add("bar");
    LIST = Collections.unmodifiableList(tmp);
}
```

# 参考資料

- [Javaのstaticメソッドを丁寧に解説! 活用例や考え方も一緒に学ぼう!](https://engineer-club.jp/java-static-method)
- [Javaのstaticフィールドの使い方・活用方法! 分かりやすい解説付き!](https://engineer-club.jp/java-static-field)
- [Javaのstaticな話](https://qiita.com/b1ueskydragon/items/2a6e0812a9cee3fc255f)


[^1]: https://spotbugs.readthedocs.io/ja/latest/bugDescriptions.html#sic-static-sic-threadlocal-deadly-embrace
[^2]: https://spotbugs.readthedocs.io/ja/latest/bugDescriptions.html#sic-static-sic-inner-should-be-static
[^3]: [staticイニシャライザの利用は冗長とする意見もある](https://cypher256.hatenablog.com/entry/20080114/p1)ようだが、処理が複雑になる場合は判断が分かれるようにも思う
nvidia-dockerが「許可がありません」で動かない

# 状況
- CentOS7
- 1年ぶりにPCを再起動してnvidia-dockerのプロセスを実行しようと思ったらエラーが出た.

```
$ nvidia-docker images
$ /usr/bin/nvidia-docker: 行 34: /usr/bin/docker: 許可がありません
$ /usr/bin/nvidia-docker: 行 34: /usr/bin/docker: 成功です
```

# 解決策
- これで解決しました. SELinuxのpermission: https://github.com/NVIDIA/nvidia-docker/issues/814

```
$ sudo semanage fcontext -a -t container_runtime_exec_t /usr/bin/nvidia-docker
$ sudo restorecon -v /usr/bin/nvidia-docker
```
子のファイル最終更新日を親ディレクトリの更新日にセットする

# 概要
多量にフォルダ分けされたファイルを管理する際に、フォルダ直下の最新ファイルの更新日が設定してあるとWindowsでソートする場合などで有用なので書いてみました。
1つ作っておけば、分類フォルダを見た時に途方に暮れることもなくなるかも？

# ソース
```py
import os
from pathlib import Path

#現在のパス直下を基準にディレクトリを探し、そのディレクトリ以下にあるファイル最新更新日を適用
p = Path("./")
for d in list(p.glob('*')):
    if d.is_dir :
        filedts = []
        for filep in list(d.glob('*')):
            filedts.append((filep.stat()).st_mtime)
        filedts.sort(reverse=True)
        if len(filedts) > 0 :
            print(d.name + ' ' + str(filedts[0]))
            os.utime(d,(filedts[0],filedts[0]))
```
Linux上にマウントしたNTFSで使用しています。
st_mtimeを使っていますがファイルシステムによって適宜atimeなりctimeなりに読み変えてください。

## 感想
Pathオブジェクトが何にでも使えて便利。どんどん使おう。
go修行11日目　タイプアサーションとか


## タイプアサーション

- 型変換をすること
- interface型で受け取ると型の判断ができないため

### intger型

```golang
package main

import "fmt"

func do(i interface{}){
	// タイプアサーション interface型だとそのまま利用できないのでintergerへ変換する必要がある
	ii := i.(int)
	ii *= 2
	fmt.Println(ii)
}

func main(){
	var i interface{} = 10
	do(i)
}
```

出力

```
20
```


### string型

```golang
package main

import "fmt"

func do(s interface{}){
	ss := s.(string)
	fmt.Println(ss + "!")
}

func main(){
	do("Mike")
}
```

```
Mike!
```

## Switch type

```golang

package main

import "fmt"

func do(i interface{}){
	// いろいろな型に対応できるようにできるswitch type
	switch v := i.(type){
	// intgerの場合
	case int:
		fmt.Println(v * 2)
	// stringの場合
	case string:
		fmt.Println(v + "!")
  // それ以外
	default:
		fmt.Println("I don't know %T%n", v)
	}
}

func main(){
	// string
	do("Mike")
	// integer
	do(10)
	// boolean
	do(true)
}
```

```
Mike!
20
I don't know %T%n true
```


## Stringer

```golang

package main

import "fmt"

type Person struct{
	Name string
	Age int
}

// String()で出力方法を変えられる
func (p Person) String() string{
	// 名前だけ返す(年齢は返さない)
	return fmt.Sprintf("My name is %v", p.Name)
}

func main() {
	mike := Person{"Mike", 22}
	fmt.Println(mike)
}
```

```
My name is Mike
```

## カスタムエラー

```golang

package main

import (
	"fmt"
)

type UserNotFound struct{
	Username string
}

func (e *UserNotFound) Error() string{
	return fmt.Sprintf("User not found: %v", e.Username)
}

func myFunc() error{
	// 何かエラーが出たら
	ok := false
	// okならnil
	if ok {
		return nil
	}
	// ユーザーが見つからなかったら
	return &UserNotFound{Username: "Mike"}
}

func main() {
	if err := myFunc(); err != nil {
		fmt.Println(err)
	}
}
```

```
User not found: Mike
```

## goroutine

- 並列処理

```golang

package main

import (
	"fmt"
	"sync"
)

func goroutine(s string, wg *sync.WaitGroup){
	for i := 0; i < 5; i++{
		// time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
	wg.Done()
}

func normal(s string){
	for i := 0; i < 5; i++{
		// time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main(){
	var wg sync.WaitGroup
	wg.Add(1)
	// 並列処理
	go goroutine("world", &wg)
	normal("hello")
	// time.Sleep(2000 * time.Millisecond)
	wg.Wait()
}
```

```
hello
hello
hello
hello
hello
world
world
world
world
world
```
SikuliXを使って無料でRPAをする方法

## RPA(Robotic Process Automation)とは？
人間が行う反復的で単純なパソコン操作を自動化しようというものです。

## SikuliXとは？
画像認識を利用してRPAを行うものです。
OSSのため無料でRPAを行うことができます。
また、言語はpythonを用いることができます。


## 開発環境の構築

### 最新版のJavaのインストール
SikuliXはjavaを使うため、最新版のjavaをインストールしておく必要があります。
以下のリンクから最新版のjavaを入手できます。

https://www.java.com/ja/download/manual.jsp

__注意点:__ windowsの場合は64bitバージョンを選択してください。

### SikuliXのダウンロード

[https://raiman.github.io/SikuliX1/downloads.html](https://raiman.github.io/SikuliX1/downloads.html)
にアクセスして、上から二番目のリンクである

「Download the ready to use sikulix.jar (SikuliX IDE)」

とその次にある

「The Jython interpreter 2.7.1 for python scripting (the default)」

をクリックしてダウンロードします。

__注意点:__ 新たにフォルダを作成し、ダウンロードした２つのファイルを入れなければなりません。


### 起動
以下のコマンドを実行して起動します。
（windowsならコマンドプロンプト、Mac・Linuxならターミナル）

```
java -jar ＜保存したディレクトリ＞/<sikulixから始まるファイル名>.jar -v -c
```

起動すると次のようなウィンドウが出てきます。

<img width="1430" alt="スクリーンショット 2020-06-28 02.06.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328421/6cf05e61-6151-feb7-221f-697f76774720.png">


## 実行方法　

実行ボタンを押すとプログラムを実行できます。
以下にプログラムを書く際に参考となったリンクを列挙しておきます。

- [youtube動画](https://www.youtube.com/watch?v=VdCOg1bCmGo&list=PL1A2CSdiySGJJNe3WzCezcI7by5SPfJTS)
- [もっといろいろなyoutube動画](https://ameblo.jp/gitarcla/entry-12525978698.html)
- [すべての関数が記載されているページ](https://sikulix-2014.readthedocs.io/en/latest/genindex.html)
- [中身のコード](https://github.com/RaiMan/SikuliX1)


## ちょっとつまずいた点と解決策
- `click()`を実行してもボタンをクリックできない場合は`doubleClick()`に変更すると治るかもです。
- 基本的に`スクリーンショットを撮る`ボタンを押して撮った写真しか認識してくれませんでした。
- 強制終了(Windows: alt-shift-c Mac: cmd-shift-c)
- 長押しする際の処理の書き方がわからなかったので以下のようなプログラムを実装しました。


```
hover("長押ししたいボタンの画像")
mouseDown(Button.MIDDLE)
try:
    wait("全く関係のない<スクリーンショットを撮る>で撮った画像",<長押し時間(秒)>)
except :
    pass
mouseUp(Button.MIDDLE)
```

- スクリーンショットを撮るを実行したときに一部分しか対象とならない場合（windows）

以下の手順でwindowサイズを変更する。

1. 設定を開く
2. システムを開く
3. 拡大縮小とレイアウトのテキスト、アプリ、その他の項目のサイズを変更するを125%に設定する。
![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328421/4cb033e0-bb19-7cda-c015-811d205e43c8.png)

## 参考
- http://sikulix.com/quickstart/
- https://www.youtube.com/watch?v=VdCOg1bCmGo&list=PL1A2CSdiySGJJNe3WzCezcI7by5SPfJTS
- https://ameblo.jp/gitarcla/entry-12525978698.html
- https://sikulix-2014.readthedocs.io/en/latest/genindex.html
- https://sikulix-2014.readthedocs.io/en/latest/genindex.html)
- https://github.com/RaiMan/SikuliX1
- https://raiman.github.io/SikuliX1/downloads.html
- http://marukentokyo.jp/tag/sikulix/
【Flutter】Android StudioのTarget selectorが"loading"で固まり，エミュレータが選択できない問題


# 問題
Android StudioのTarget selectorで "loading" しか表示されなくなる。
エミュレータが起動していても選択ができないため，デバッグができない。
![62770627-b15efb80-ba9b-11e9-9a20-a8ef22f9c0f5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231104/162d3286-6562-8666-26f6-4c1438dccbf7.png)

# 解決法
大抵の場合，Flutterのバージョンに問題があるようです。
Flutterをアップグレードorダウングレードすれば解決する。

問題の発生する v1.17.4 から v1.17.3 に変更する場合は以下のコマンド。

```bash
flutter version 1.17.3
```

# 困ったら
Flutter公式GitHubのissueにスレッドがあるので，おそらく今後もここが更新されていくはず。
issueリンク: https://github.com/flutter/flutter-intellij/issues/3892
MDN の埋め込みサンプルコードの 404 を修正する迄

2020/06/26 の業務中、厳密比較演算子の話になって、たまたまページをみていたらページ内の埋め込み部分と思われる箇所に 404 のエラーを発見。修正することにしました。

## 対象ページ
* [比較演算子 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)

## 事象
埋め込みコードが404

![スクリーンショット_062820_010759_AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43480/17bfe9f0-b17e-b43f-a3d6-dcb626284e2a.jpeg)

## 調査
* [リビジョン 1615485 | 比較演算子 | MDN](https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comparison_Operators$revision/1615485)

```
{{EmbedInteractiveExample("pages/js/expressions-comparisonoperators.html")}}
比較の機能は以下のとおりです。
```

の `pages/js/expressions-comparisonoperators.html` がなくなったのだろう。
英語版が構成変更の影響によって、このサンプルを削除して、日本語版で参照できなくなって 404 かな、と予想。

該当ページのキャッシュをググって元の内容を把握。

[https://interactive-examples.mdn.mozilla.net/pages/js/expressions-comparisonoperators.html のキャッシュ](https://webcache.googleusercontent.com/search?q=cache:EaQCzBByyzAJ:https://interactive-examples.mdn.mozilla.net/pages/js/expressions-comparisonoperators.html+&cd=2&hl=ja&ct=clnk&gl=jp)

これに相当するサンプルコードを 

* [mdn/interactive-examples: Home of the MDN live code editor interactive examples](https://github.com/mdn/interactive-examples)

から調査。
それっぽいのを発見。どうやら、ページ構造自体が変わって、例が分割されたっぽくて2つになってたっぽい。

* [interactive-examples/expressions-equality.js at master · mdn/interactive-examples](https://github.com/mdn/interactive-examples/blob/master/live-examples/js-examples/expressions/expressions-equality.js)
* [interactive-examples/expressions-strict-equality.js at master · mdn/interactive-examples](https://github.com/mdn/interactive-examples/blob/master/live-examples/js-examples/expressions/expressions-strict-equality.js)

## 変更を適用
* [変更内容](https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comparison_Operators$revision/1630575)
* [tbpgr | MDN](https://developer.mozilla.org/ja/profiles/tbpgr)

## 結果
ということで、修正が反映されて 404 が消えました。

* [比較演算子 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)

## 参考情報
* [MDN で始めよう - MDN プロジェクト | MDN](https://developer.mozilla.org/ja/docs/MDN/Getting_started)
TypeScriptのインストールから実行まで

# 目的
細かい設定は後回しにしてとりあえずTypeScriptをインストールして実行する。

# 環境
windows10
node.js v12.13.0
npm v6.12.0
typescript v3.9.5

今回はnode.jsを使ってTypeScriptのインストールを行うため、先にnode.jsをインストールしておく。
node.js（公式サイト） -> https://nodejs.org/ja/

# TypeScriptのインストール準備
TypeScriptのプロジェクトを作りたいディレクトリを初期化する。

```terminal:コマンドプロンプト
npm init
```

初期化時に色々設定を聞かれるがすべてデフォルトでOKなので、Enter連打。
初期化が完了すると、`package.json`が作られる。

```
TS_Project
  └─ package.json
```

# TypeScriptのインストール
次に、package.jsonと同じディレクトリで次のコマンドを実行する。

```
npm install typescript
```
するとpackage.json内にtypescriptが追加されていることが確認できる。

```json:package.json
  "dependencies": {
    "typescript": "^3.9.5"
  }
```

ここまでで、TypeScriptのインストールは終了。
フォルダ構成は以下のようになっている。

```
TS_Project
  ├─ node_modules
  ├─ package-lock.json
  └─ package.json
```

次からはTypeScriptのファイルを作成し、コンパイル、実行までを行う。

# TypeScriptのファイルを作成
TypeScript（以下TS）ファイルを作成（今回はapp.ts）する。
今回はコンソールに文字を出力する簡単なもの。

```typescript:app.ts
console.log('Hello TypeScript');
```

htmlファイルに`<script>`で読み込む（今回はindex.html）。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./app.ts" defer></script> <!-- 追加！！ -->
    <title>初めてのTypeScript</title>
</head>
<body>
    
</body>
</html>
```

ここで注意してほしいところは`<script>`で読み込むファイルは`app.ts`ではなく`app.js`になるというところ。
これはTSファイルはコンパイラ後にJSファイルとして出力される。htmlファイルはそのJSファイルを使うためである。

この時点でのフォルダ構成は以下になる。

```
TS_Project
  ├─ node_modules
  ├─ app.ts
  ├─ index.html
  ├─ package-lock.json
  └─ package.json
```

見ての通り現時点ではまだ`app.js`ファイルはない。

# TypeScriptのコンパイル
`app.ts`があるディレクトリで以下のコマンドを実行する。

```terminal:コマンドプロンプト
npx tsc app.ts
```

※npxはnpm バージョン5.2.0 以降で使えるコマンド
コンパイルが終了すると`app.js`ファイルが生成される。

先ほどのhtmlファイルを実行してコンソールを開くと「Hello TypeScript」が表示されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621838/c254f4fd-c70d-3e31-076b-1a8ff4b0db60.png)

最終的なフォルダ構成は以下。

```
TS_Project
  ├─ node_modules
  ├─ app.js
  ├─ app.ts
  ├─ index.html
  ├─ package-lock.json
  └─ package.json
```

以上がTypeScriptのインストール->コンパイル->実行の流れとなる。
ここまででとりあえずは当初の目的は達成できた。
次からはもう少し細かく設定をしていく。

# TypeScriptのプロジェクトの設定
これまでの手順ではTSファイルが複数存在する場合、各ファイルを指定してコンパイルしていくことになり現実的ではない。
プロジェクトが大きくなるにつれ、よりTypeScriptの細かな設定が必要となる。
そのためTSプロジェクトを設定したいディレクトリで以下のコマンドを実行し、初期化を行う。

```terminal:コマンドプロンプト
npx tsc --init
```

初期化が終わると、`tsconfig.json`が生成される。
今後はこのファイルがあるフォルダ+サブフォルダはTSによって管理されるようになる。

ちなみに`tsconfig.json`にはTSファイルがどのようにコンパイルされるかなどをコントロールする設定が記載されている。
これでコンパイル時にファイルを指定せずに、プロジェクト内にあるTSファイルはすべてコンパイルされるようになる（node_modules内のファイルは除外）。

```terminal:コマンドプロンプト
npx tsc
```

`tsconfig.json`の中身についてはこちらも参考に。
[初期化直後のtsconfig.jsonを翻訳してみた](https://qiita.com/eiji-noguchi/items/32bb304e544eef6149d7)
AWS lightsailでルートディレクトリを変更する

#AWS lightsail + node.jsでルートディレクトリを変更したい

node.jsをインストールしたlinuxベースのAWS lightsailで、
gitクローンしたディレクトリをディレクトリルートに指定します。

laightsailの環境は
・nodejs v12.16.1
・apache v2.4.41(unix)

```
sudo vi /opt/bitnami/apache2/conf/bitnami/bitnami.conf
```
で、viエディタを開きます。

escキーを押してから

```
/DocumentRoot
```
でドキュメントルートを指定している行にジャンプします。
(普通にカーソル移動でもokです。)

ここで、

```
DocumentRoot "gitクローンしたファイルパス"
```
IPアドレスやドメインをたたけば、htmlファイルが表示されます。
laravel-adminの設定をエクスポートしてseederに追加する方法

laravel-adminのMenu設定をエクスポートして、seederに追加することで初期Migration時にデータを戻す方法を考えました。

laravel-adminのメニューやロールの初期設定を開発画面で作っておいて別環境で再現するなど。

## admin:export-seedではMenuやRoleの情報しかExportされない

```
php artisan admin:export-seed
Admin tables seed file was created: /database/seeds/AdminTablesSeeder.php
Use: php artisan db:seed --class=AdminTablesSeeder
```

上記のコマンドで設定が全部エクスポートされたよわーい！と思ってdb:seedしても、管理画面にログインできない。どうやらこのエクスポートされたSeederを見る限り、ユーザー情報が含まれていないように見える。

admin useraのseederは別で作らないといけないようだ。。。

こちらの記事を参考にlaravel-admin初期設定のSeederをコピーします。

https://qiita.com/ntm718/items/5ea29ee70b50320352c4

ファイル名をクラス名をAdminUsersSeederに変更して、// create a user.〜role部分だけ使って以下のように修正。

```:AdminUsersSeeder
<?php

use Illuminate\Database\Seeder;
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Auth\Database\Role;
use Encore\Admin\Auth\Database\Permission;

class AdminUsersSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // create a user.
        Administrator::truncate();
        Administrator::create([
            'username' => 'admin',
            'password' => bcrypt('admin'),
            'name'     => 'Administrator',
        ]);

        // create a role.
        Role::truncate();
        Role::create([
            'name' => 'Administrator',
            'slug' => 'administrator',
        ]);

        // add role to user.
        Administrator::first()->roles()->save(Role::first());

        // 別のユーザー(例:staff）やロールを初期状態で追加しておく場合
        Administrator::create([
            'username' => 'staff',
            'password' => bcrypt('staff'),
            'name'     => 'staff',
        ]);

        // create a role.
        Role::create([
            'name' => 'staff',
            'slug' => 'staff',
        ]);

        // add role to user.
        Administrator::find(2)->roles()->save(Role::find(2));


        
    }
}
```

AdminUsersSeeder, AdminTablesSeederをDatabaseSeederに追加。

```
    public function run()
    {
        $this->call(AdminUsersSeeder::class);
        $this->call(AdminTablesSeeder::class);
    }
```

これで、admin/adminでログインできる初期ユーザーと、GUIで設定したmenu,role,permisson情報がシーダーにエクスポートされました。

```
php artisan migrate:fresh
php artisan db:seed
```

上記のコマンドを実行して、ユーザーとメニューが戻ることを確認。

以後、メニューや権限を編集した場合は、再度

```
php artisan admin:export-seed
```

で、設定がSeederにエクスポートされます。
ユーザーを追加した場合は？手動でファイルに追記してください・・・
iOS アプリ起動時に "The Google Mobile Ads SDK was initialized without an application ID" で強制終了する場合に必要な対応

# 概要

iOS アプリ起動直後に以下のようなログを出力して強制終了する件について、原因と対応方法をまとめました。

```
*** Terminating app due to uncaught exception 'GADInvalidInitializationException', reason: 'The Google Mobile Ads SDK was initialized without an application ID. Google AdMob publishers, follow instructions at 
https://googlemobileadssdk.page.link/admob-ios-update-plist to set a valid application ID. Google Ad Manager publishers, follow instructions at https://googlemobileadssdk.page.link/ad-manager-ios-update-plist.'
```

# 対応方法

ログに含まれている URL を開き、そこに書かれている記載に従い、 `Info.plist` の修正をする必要があります。

## Google AdMob

Google AdMob を利用している場合には、以下リンク先のスタートガイドの記載に従い、 `Info.plist` に `GADApplicationIdentifier ` キーと、それに対応する値（ AdMob アプリ ID ）を追加します。
https://googlemobileadssdk.page.link/admob-ios-update-plist

```xml:追加するキーと値の例
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
```

## Google Ad Manager

Google Ad Manager を利用している場合には、以下リンク先のスタートガイドの記載に従い、 `Info.plist` に `GADIsManagerApp` キーと、それに対応する値 `YES` を追加します。
https://googlemobileadssdk.page.link/ad-manager-ios-update-plist

```xml:追加するキーと値の例
<key>GADIsAdManagerApp</key>
<true/>
```

# この問題の背景

上記2つのスタートガイドの両方に記載されているとおり、 Google Mobile Ads SDK のバージョン `7.42.0` 以降では、 `Info.plist` に必要な値を設定しておかないとアプリが強制終了します。

アプリの `Info.plist` に AdMob アプリ ID を設定する必要があることについては、 Google Mobile Ads SDK のバージョン `7.42.0` の[リリースノート](https://developers.google.com/admob/ios/rel-notes)にも書かれています。