OmniAICreator/Qiita-1.07M huggingface dataset:
ggplotを試す

```

$ cat test1.py
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

plt.style.use('ggplot')

df = pd.read_csv("dummy.csv")


print(df.info)
print(df['num_of_days'])

plt.figure(figsize=(14, 7))

df['num_of_days'].plot(kind="hist", bins=len(df), alpha=0.5)
df['num_of_days'].plot(kind="kde", secondary_y=True)

plt.title("Test for using style ggplot")
plt.legend()

plt.show()
```

CSVデータ：

```
$ cat dummy.csv
id,num_of_days
1,20
2,250
3,20
4,2902
5,2980
6,2952
7,2920
8,25022
9,2480
10,32220
```
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/ef3834fb-2aed-9941-a34d-3e5301acb32d.png)

こちらは、plotlineを使った例：

https://plotnine.readthedocs.io/en/stable/index.html

```python
#!/usr/bin/env python3

import pandas as pd
import numpy as np
from pandas.api.types import CategoricalDtype
from plotnine import *
from plotnine.data import mpg

print(mpg)
"""
    manufacturer   model  displ  year  cyl  ... drv cty  hwy  fl    class
0           audi      a4    1.8  1999    4  ...   f  18   29   p  compact
1           audi      a4    1.8  1999    4  ...   f  21   29   p  compact
2           audi      a4    2.0  2008    4  ...   f  20   31   p  compact
3           audi      a4    2.0  2008    4  ...   f  21   30   p  compact
4           audi      a4    2.8  1999    6  ...   f  16   26   p  compact
..           ...     ...    ...   ...  ...  ...  ..  ..  ...  ..      ...
229   volkswagen  passat    2.0  2008    4  ...   f  19   28   p  midsize
230   volkswagen  passat    2.0  2008    4  ...   f  21   29   p  midsize
231   volkswagen  passat    2.8  1999    6  ...   f  16   26   p  midsize
232   volkswagen  passat    2.8  1999    6  ...   f  18   26   p  midsize
233   volkswagen  passat    3.6  2008    6  ...   f  17   26   p  midsize

[234 rows x 11 columns]
"""

g = (ggplot(mpg)     # defining what data to use
     + aes(x='class')    # defining what variable to use
     + geom_bar(size=20)  # defining the type of plot to use
     )

g.save("test1.png", limitsize=True, verbose=True)

```

![test1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/6a984193-6ca8-0ebe-0a6f-398cded7bd7e.png)
Processing IDEの文字色変更の項目に関するメモ

#Processing IDEをダークテーマにするくだり
[Mac Processing IDE ダークテーマに変更](https://ameblo.jp/hajimeteno-pic/entry-12683203690.html)

文字色変更で「自分はこうしました」っていうのは書いてあるけど、どの項目が何を指しているのかわからないのでメモ

#見た目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/2aa88aca-f228-d51f-226d-9da2acf65dc2.png)

Gitからダウンロードしたまま使うと、選択した箇所が黄色で眩しいので
`theme.txt`を開いて
`editor.selection.color = #0055aa`
に変更しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/d09f84f3-0e64-d870-1d7a-7e4fa6a9099c.png)


#preferences.txtを開く
preferences.txtを**Processingを閉じてから開きます**
場所は設定からパスをクリックすれば開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/bf27cfc2-8eba-49ed-e046-d73d38ff803e.png)

#各項目のメモ
ダークテーマにした時に、自分はこのように設定しました
**`名前`**の前に`editor.token.`がつきますが、省略してます

| 名前 | 対象 | 具体例 | 色 |
|:-:|:-:|:-:|:-:|
|comment1|1行コメント|//a|<font color="#57a64a">#57a64a</font>|
|comment2|複数行コメント|/\*a*/|<font color="#57a64a">#57a64a</font>|
|function1|メソッド（描画系やmath系やコンストラクタ）|backgroundやsqrt|<font color="#ffc66d">#ffc66d</font>|
|function2|メソッド（構造体系？）|distやmag|<font color="#ffc66d">#ffc66d</font>|
|function3|条件分岐や繰り返し|forやif|<font color="#00aadd">#00aadd</font>|
|function4|メソッド（オーバーライド系？）|setupやdraw|<font color="#4488cc">#4488cc</font>|
|invalid|無効な文|"や'が1つだけ|<font color="#ff5500">#ff5500</font>|
|keyword1|クラス関係|newやclassやvoid|<font color="#9876aa">#9876aa</font>|
|keyword2|配列の長さ|.kength|<font color="#33997e">#33997e</font>|
|keyword3|条件分岐|else|<font color="#00aadd">#00aadd</font>|
|keyword4|変数名|widthやmousePressed|<font color="#8e93ff">#8e93ff</font>|
|keyword5|型|intやPVector|<font color="#7daeff">#7daeff</font>|
|keyword6|クラス参照|thisやsuper|<font color="#33b5aa">#33b5aa</font>|
|label|不明|不明|<font color="#666666">#666666</font>|
|literal1|文字|"aa"や'a'|<font color="#e5b255">#e5b255</font>|
|literal2|定数|PIやCENTER|<font color="#819a72">#819a72</font>|
|operator|不明|不明|<font color="#006699">#006699</font>|

不明な箇所の色はデフォルトのままで表記してると思います

#コピペ用
```
editor.token.comment1.style=#57a64a,plain
editor.token.comment2.style=#57a64a,plain
editor.token.function1.style=#FFE16D,plain
editor.token.function2.style=#FFE16D,plain
editor.token.function3.style=#00aadd,plain
editor.token.function4.style=#4488cc,bold
editor.token.invalid.style=#ff5500,bold
editor.token.keyword1.style=#9876aa,plain
editor.token.keyword2.style=#33997e,plain
editor.token.keyword3.style=#00aadd,plain
editor.token.keyword4.style=#8e93ff,plain
editor.token.keyword5.style=#7daeff,plain
editor.token.keyword6.style=#33b5aa,plain
editor.token.label.style=#666666,bold
editor.token.literal1.style=#e5b255,plain
editor.token.literal2.style=#819a72,plain
editor.token.operator.style=#006699,plain
```
OSとは何か

OSは人間でいうとなんだろう。
脳だと思ったがCPUが脳と言った方が正しいらしい。
CPUがパソコンやスマホに搭載されていて、キーボードやマウスからの信号を処理して、パソコン全体を動かしている。
OSはそのCPUがやっていることを人間にわかりやすくしてくれているよう。
てことはOSは脳をサポートするもの。
人間に例えることが難しい。


OSの役割は多く4つあるとのこと。
・ファイル管理
・ディバイス管理
・タスク管理
・メモリ管理

CPUだけだと使い勝手が悪いので、OSがパソコンやスマホを使いやすくしてくれている。
そのOSにも種類がいくつかある。

Windows
Mac
Linux
IOS
Android
などだ。


パソコンやスマホはただのディバイス、機械である。
CPUやメモリ、ハードディスクは搭載しているが、ただの箱。
OSを入れることで私たちが利用できるようになる。
MacbookパソコンにWindowsOSを入れると、WindowsPCになるってこと。
ネットワーク的に正しいアドレス振り分けをしよう

# はじめに
新しいネットワークを作る時に、よく「じゃぁDHCPのアドレス配布範囲は.1 ～ .100にしよう」と無邪気に設定しがちですが、そういうことはやめてきちんとCIDRに沿ってやりましょう、という話です。

# ネットワークアドレスの分割について
IPネットワークにおいてネットワークアドレスとサブネットマスクを用いることで、クラスC以下のネットワークを複数に分割することができます。
たとえば、192.168.0.0/24のネットワークは以下のように2つに分けることができます。

| 1 | 2 |
|:-:|:-:|
| 192.168.0.0/24  |192.168.0.0/25   |
|   |192.168.0.128/25  |

192.168.0.0/25の場合、192.168.0.0はネットワークアドレスなので利用不可、192.168.0.127はブロードキャストアドレスなので同じく利用不可となり、利用可能なのは192.168.0.1 ～ 192.168.0.126となります。
126個のIPアドレスが利用可能です。

これだと少し大きすぎるので、もう少し分割してみましょう。

| 1 | 2 | 3 |
|:-:|:-:|:-:|
| 192.168.0.0/24  | 192.168.0.0/25  |192.168.0.0/26   |
|   |   | 192.168.0.53/26  |
|   |192.168.0.128/25   | 192.168.0.128/26  |
|   |   | 192.168.0.192/26  |

4つに分割しました。こうすると1つのセグメントにつき、62個のIPアドレスが利用可能です。
また、192.168.0.0/25、192.168.0.128/26、192.168.0.192/26というように、大きいセグメント1つと他に2つのセグメントといった分割も可能です。
サブネットマスクによる大きさ指定は/32（実用上は/31)まで可能です。
あまり分割しすぎると利用できないIPアドレスやセグメントが大量にでてきますので、その点は注意が必要です。

こうして分割されたセグメント設計をもとに「じゃぁDHCPのアドレス配布範囲は.1 ～　.126にしよう」とやると、より美しいネットワーク設計となるでしょう。

# これはなにが美味しいのか
利点としては2つあります。

* ネットワーク関係の設定、ファイアウォールのフィルタリングの記載などが「192.168.0.0/26」と簡潔に記載できる。
 * 最近は「IPアドレスの範囲指定」ができることがほとんどですが、やはりCIDRで表記できる方が美しいです
* 分かる人が見れば「こいつわかってるな」と思ってもらえる

# まとめ
IPアドレスの振り分けについて、CIDRから見た振り分け方法についてまとめました。
つい人間が見て切りがいい数字にしがちですが、それがネットワーク的には美しいとは限らないのです。
NUXT3×WSL2開発でhot reloadする方法

## 経緯

2021/10/12にnuxt3 betaがreleaseされました。
nuxt2ではソース編集時のhot reloadが非常に遅く、nuxt3ではvite（ヴィータ）同梱ということで、爆速hot reloadに期待していました。
それを**WSL上で**有効にする情報がweb上になかったので共有します。

自分はwindows上IDEで実装、WSL2上でnuxtを実行しているため、ファイル変更watchにはpolling設定が必要です。

NUXT3ドキュメントでは、watcher設定はNUXT2と同じ・・・？と思えたのですが、
https://v3.nuxtjs.org/docs/directory-structure/nuxt.config#watchers
同じにしてもhot reloadしてくれませんでした。

## 設定（nuxt.config.js）

NUXT2での設定

```js
watchers: {
  webpack: {
    poll: true
  }
},
```
NUXT3ではこうすると動きます。

```ts
vite:{
  server: {
    watch: {
      usePolling: true,
    },
  },
},
```
これで、1分以上かかっていたhot reloadが、文字通り秒になりました（実際には0.x秒くらい）。

## おまけ

NUXT2で部分的にvite対応するnuxt-viteというライブラリがあり、
https://vite.nuxtjs.org/getting-started/config/
そこでは`nuxt.config.js`内で「vite」ブロックがあったので、もしや、と思い試したらうまくいきました。
ちなみに、vue3でviteを使う場合には、`vite.config.js`をルートに置くのですが、NUXT3で同様にしたところエラーになりました。
Laravel8でBootstrapを使えるようにする

#はじめに
Laravelで新規プロジェクトを立ち上げるごとにBootstrapを使えるよう設定が必要です。
Composerを既にインストール済の状態からBootstrapを使えるようにする手順を以下にまとめました。


#Laravel8でBootstrapを使えるようにする方法
以下の手順をターミナルで実行します。

①Composerを使ってインストール

```
composer require laravel/ui
```

②artisanコマンドを実行

```
php artisan ui bootstrap
```

③言われた通りコマンドを打ち込み実行

```
npm install && npm run dev
```

※実行できない場合は

```
npm install
```

を事前に実行してから

```
npm run dev
```
を実行する。
これで完了です。

#Bootstrapを実際に使ってみる。
Bootstrapを使いたいファイルにて下記のようにcssとjsを読み込む。

```
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<script src="{{ asset('js/app.js') }}"></script>
```

#おわりに
ターミナルで実行するコマンドをシェルスクリプトにまとめてみてもいいかもしれません。

>
参考にしたページ
https://uedive.net/2019/195/la6fa/
>
ポート開放の方法

以下のコードをターミナルで実行するとポート開放できます。

```
[root@localhost httpd]$sudo firewall-cmd --zone=public --add-port=開放したいポート番号/tcp --permanent
success
[root@localhost httpd]$sudo firewall-cmd --reload
success
[root@localhost httpd]$
```

下記を実行すると開放したポートでプロジェクトを起動できます。

```
[root@localhost httpd]$ php artisan serve --host=IPアドレス --port=開放したポート番号
```

※常時起動時

```
[root@localhost httpd]$ php artisan serve --host=IPアドレス --port=開放したポート番号 &
```
ESP32に書き込めない（Macでの環境, Big Sur）

#MacでESP32に書き込めない。
ESP32をMacに接続して、Arduino IDEで書き込もうとしたら、
エラーが出て、その先、何もできない。
コンパイルエラーみたい。
エラーメッセージをgoogle で検索してみると、

Qiitaの記事が見つかる。
この記事に従って、作業すればOKでした。

https://qiita.com/ashe1098/items/585d6474bd5d4833d39d


あとは、私自身の作業の忘備録としての記録を残しておきます。

#今回の作業内容
Macはpythonのデフォルトが、python２なので、　
python3への切り替えが必要ということで　上のURLの作業を行えば、OKのはずが、

python3がインストールされていないことが判明。
よって、Python3をインストール。

https://tipstour.net/python3-install-on-mac-after-catalina

というか、
https://www.python.org/　 にアクセスして、
Downloadから、最新版（今回は、3.10.0)をダウンロードして、インストール。

ここまで、やっても、arduino IDEでのESP32のコンパイルエラーが消えない。
ターミナルのコマンドプロンプトで、　python3 を入力しても　エラーがでて、python3を認識していないみたい。
（パスが通っていない）

python3をインストールした後は、再起動したほうが、いいみたいです。　で、再起動。

再起動後に python3が　使えるようになりました。
$python３ --version 　　で、3.10.0が表示される。

（python だと　2系のバージョンが表示される。　これは、今のところそのままにしておいた。）

Arduino IDE でコンパイルすると、メッセージが減ったけど、
serialがなんちゃらというエラーが出る。　これも、　先のQiitaの参考ページにある情報どおりで、

pip　を使って、 pyserialをインストールすればよい。

ターミナルで、
pip install pyserial　を　入力するが、

しかし、　pipが見つからないというコマンドが表示される。 

次は、pipのインストール。
参考にしたのが、　こちらのQiitaの記事。　　
https://qiita.com/ohbashunsuke/items/e7c673db606a6dced8a6

もうね、本当ありがたい。　

pipのインストールを済ませ、
pipを使って、　pyserial をインストールしたら、　Arduino IDEでESP32のコンパイルができるようになった。


##でも、まだボードに書き込めない

で、ボードに書き込むけど、エラーが表示されて、書き込めない。　
ESP32の設定はOKのはず。　

次のサイトと同じであることを確認済み。
https://www.indoorcorgielec.com/resources/arduinoide%E8%A8%AD%E5%AE%9A/esp-wroom-32%E6%90%AD%E8%BC%89%E8%A3%BD%E5%93%81/


書き込みができない件を、ググると、

次のサイトがみつかった。
https://dotstud.io/docs/nefrybt-error-handling-2/

書き込み速度を遅くするといいみたい。
４６０８００bpsに設定したら、書き込みできた。

以上。
【JavaScriptのメモ】条件式ifについての注意事項

以下のコードを実行すると、HTMLにどの条件式が実行されるでしょうか？


  ```JavaScript
let hour = 14;
  if (hour > 9) {
    document.write('Good Morning');
  } else if (hour > 11) {
    document.write('Good Afternoon');
  } else if (hour > 17) {
    document.write('Good Evening);
  } else if (hour > 22) {
    document.write('sleepy');
  } else {
    document.write(hour);
  }
```

答えは、最初にtrueになる```if (hour > 9)``` です。

【注意事項】
if文は一番早くtrueとなる処理だけ実行するので、後ろのelse ifでも条件が当てはまるからといって処理が実行されるわけでは無い。
つまり、先に実行されるtrue処理のみ表示する。
先のtrueの処理が完了すれば、処理そのものが終了し、以降の条件式は実行されない。
Dart Sass でよく利用するビルトインモジュール

Dart Sass へ移行すると除算処理とSass関数は、ビルトインモジュールを利用することになります。

というわけで、よく利用していたSass関数をビルトインモジュールへ変更する方法をまとめてみました。

:::note warn
執筆時 gulp-dart-sass@1.0.2 を利用してコンパイルしましたが、Sass関数は利用できていました。今後利用できなくなると思われます。
:::

## 除算する

今まで通りの記述だとコンパイル時に以下のような警告メッセージが表示されます。

```
DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0.
```

詳細は以下で確認できます。

https://sass-lang.com/d/slash-div

Dart Sass で除算する場合はビルトインモジュールの `sass:math` を利用します。

https://sass-lang.com/documentation/modules/math

```scss:変更前
.hoge {
  width: (100px / 2);
}
```

```scss:変更後
@use "sass:math";
.hoge {
  width: math.div(100px / 2);
}
```

## 色を利用する

Dart Sass で色を利用する場合はビルトインモジュールの `sass:color` を利用します。

https://sass-lang.com/documentation/modules/color

### rgba()を16進数の値で指定する

:::note warn
第2引数 $alpha の指定方法がSass関数と異なるので注意が必要です。
:::

```scss:変更前
.hoge {
  background-color: rgba(#000, 0.7);
}
```

```scss:変更後
@use "sass:color";
.hoge {
  background-color: color.adjust(#000, $alpha: -0.3);
}
```

### 色を明るくする

:::note warn
Sass関数とは値の算出方法が違うようで、有彩色を指定した場合、以下の変更方法ではSass関数のカラーコードと同じになりません。
:::

```scss:変更前
.hoge {
  background-color: lighten(#000, 50%);
}
```

```scss:変更後
@use "sass:color";
.hoge {
  background-color: color.scale(#000, $lightness: 50%);
}
```

### 色を暗くする

:::note warn
Sass関数とは値の算出方法が違うようで、有彩色を指定した場合、以下の変更方法ではSass関数のカラーコードと同じになりません。
:::

```scss:変更前
.hoge {
  background-color: darken(#fff, 50%);
}
```

```scss:変更後
@use "sass:color";
.hoge {
  background-color: color.scale(#fff, $lightness: -50%);
}
```

## 配列を利用する

Dart Sass で配列を利用する場合はビルトインモジュールの `sass:list` を利用します。

https://sass-lang.com/documentation/modules/list

### 配列のインデックス番号を取得する

```scss:変更前
$z-index: obj, header, overlay;
.header {
  z-index: index($z-index, header);
}
```

```scss:変更後
@use "sass:list";
.hoge {
  z-index: list.index($z-index, header);
}
```

### 配列の要素を取得する

```scss:変更前
$colors: #67c1b8, #4daadf, #2ea014, #f3a600, #ed571d, #cf1a02;
.hoge {
  @for $i from 1 through 6 {
    &.is-level#{$i} {
      background-color: nth($colors, $i);
    }
  }
}
```

```scss:変更後
@use "sass:list";
$colors: #67c1b8, #4daadf, #2ea014, #f3a600, #ed571d, #cf1a02;
.hoge {
  @for $i from 1 through 6 {
    &.is-level#{$i} {
      background-color: list.nth($colors, $i);
    }
  }
}
```

## マップを利用する

Dart Sass でマップを利用する場合はビルトインモジュールの `sass:map` を利用します。

https://sass-lang.com/documentation/modules/map

```scss:変更前
$sns-colors: (
  twitter : #1d9bf0,
  facebook: #1877f2,
  line    : #06c755
);
.hoge {
  &.is-twitter {
    background-color: map-get($sns-colors, twitter)
  }
}
```

```scss:変更後
@use "sass:map";
$sns-colors: (
  twitter : #1d9bf0,
  facebook: #1877f2,
  line    : #06c755
);
.hoge {
  &.is-twitter {
    background-color: map.get($sns-colors, twitter)
  }
}
```

また、Dart Sass では `map.get()` に複数の引数を渡すと、ネストされた値を取得できます。

```scss:ネストされた値を取得
@use "sass:map";
$category-colors: (
  hoge: (
    main: #e866a5,
    bg: #fff
  ),
  fuga: (
    main: #8667e5,
    bg: #fff
  ),
  piyo: (
    main: #36ce9f,
    bg: #fff
  )
);
@debug map.get($category-colors, hoge, main); // #e866a5
```
ReactNativeで作ったアプリのAndroid版がダークモードにすると、アラートの文字が黒いままになってて見にくいので解決する

# Androidでダークモードにするとアラートの文字が黒いままで見にくい現象が起きた
Androidでアラートを出そうとした時、通常はこのようなUIになります。
![スクリーンショット 2021-10-13 14.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/72d37f65-05b7-883e-c6bf-951b45a33671.png)
実装はとても簡単でこんな感じです。

```javascript
import React from 'react';
import {Alert, Button, View} from 'react-native';

export const AlertView = () => {
    const onAlert = () => {
        return Alert.alert('こんにちは')
    }
  return (
    <View>
      <Button title="タップ" onPress={onAlert} />
    </View>
  );
};
```
React Native標準のAlertを使えば簡単に表示できます。
ただ、アラート内の文字にスタイリングを当てることはできないというデメリットもありますが、基本的にアラートを出すときはこれで十分だと考えられます。

しかし、スマホをダークモードにしてしまうと。。。。
![スクリーンショット 2021-10-13 14.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/eeb6446d-341b-b45e-85fb-b433a2c1d531.png)
アラート自体は暗くなるのに文字が黒いままで非常に見にくくなります。
自動的に対応してくれないのかよ！と思いました。

# 解決策
プロジェクト内のandroidディレクトリ内にダークモードでも文字色を黒にするように標準で設定されていました。
その文をなくせば解決します。
プロジェクト名/android/src/main/res/values/styles.xmlに行きます。

```javascript
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="android:textColor">#000000</item> ←問題のコード
    </style>

</resources>
```
`item name="android:textColor">#000000</item>`
これを消しちゃってください。それで問題解決します。

実際に検証してみると、、
![スクリーンショット 2021-10-13 14.13.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/98fd3a51-2ea3-667d-8ca1-f6a94c4b0837.png)
こんな感じになります！

アラートの文字以外にもTextInputのPlaceholderなど文字にカラーを設定していないところはダークモードにしても黒くなってしまいます。
#### ご参考までに！！
AWS:S3からのデータのダウンロードとアップロードについて

# なぜ書こうと思ったのか
<!-- 発端や概要を記載 -->
インターン先で、AWSを初めて使うようになり、S3からのデータのダウンロードとアップロードが苦戦したので、整理のために書こうと思いました。
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [そもそもS3とは？](#そもそもS3とは？)
1. [S3への接続とその確認方法](#S3への接続とその確認方法)
1. [S3からのダウンロードとアップロード](#ファイルのダウンロードとアップロード)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
#そもそもS3とは？
Amazon Simple Storage Service、通称S3はオブジェクトストレージサービスであり、様々なユースケースのデータを保存して保護することができる。さらには、データを整理してアクセス制御を細かく調整するために使いやすい機能を提供するサービスである。
S3のメリットについては、以下の記事を参考
- [S3のメリット](https://aws.amazon.com/jp/s3/)

<a id="#Chapter2"></a>
#S3への接続とその確認方法
今回はSagemaker上で行っています。
ローカルで行う場合は、configureの設定を行ってから進める必要があります。
### バケットへの接続
name部分には、抽出したいファイルがあるS3上のバケット名をいれます。

```python
import boto3

#バケットへの接続
s3 = boto3.resource('s3')
bucket = s3.Bucket('name')
```
このときに、jupyter上で

```python
print(bucket)
```
を実行してバケット名が表示されていれば、接続ができていると思われます。

#ファイルのダウンロードとアップロード

### バケットからのダウンロード
1. 対象のファイルをダウンロードしたい場合

```
bucket.download_file(file_path, file_name)
```
file_pathには、s3上での抽出したいファイルのpath
file_pathをきちんと通せているか、確認を忘れないでください。

2. 一度にすべてのファイルをダウンロードしたい場合

```
!aws s3 cp s3://'s3上でのバケット名'(/file_path) 'ダウンロード先のフォルダ' --exclude "" --include "*" --recursive
```
- excludeオプション
  - exclude オプションは、コマンドからオブジェクトのみを除外するようにルールを設定します。
- includeオプション
  include オプションは、指定したオブジェクトのみをコマンドに含めるようにルールを設定します。
- recursiveオプション
  recursiveオプションは、指定のディレクトリ内またはプレフィックス内のすべてのファイルやオブジェクトに対してコマンドが実行されます

### バケットへのアップロード　

```
bucket.upload_file(file_name, file_path)
```
file_nameには、アップロードするファイル名
file_pathには、バケット内のどのフォルダ内にアップロードするかのpathを指定する
colimaでlima+dockerのセットアップを少しシンプルにする

[colima](https://github.com/abiosoft/colima)は最小限のセットアップでmacOS上にコンテナランタイムを構築することを目標としているプロジェクトです。
このプロジェクトを利用することで`lima`+`docker`をシンプルな手順でセットアップすることができます。


## インストール

homebrewを利用して必要なパッケージをインストールした後にcolimaをインストールします。

```zsh
# Homebrewのインストール
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# lima、docker、kubectlのインストール
brew install lima docker kubectl

# colimaのインストール
curl -LO https://github.com/abiosoft/colima/releases/download/v0.2.0/colima-amd64
sudo install colima-amd64 /usr/local/bin/colima

# インストールが成功しているかどうかの確認
colima version

# この記事の内容は以下のバージョンを前提としています
# colima version v0.2.0
```


## VMとコンテナの起動

VMとコンテナを起動して、debianから`echo 'Hello, World!'`を実行してみます。

```zsh
# VMの起動
colima start

# コンテナの起動
docker run --rm debian:10 bash -c 'echo Hello, World!'
```

VMはデフォルトでは以下の設定で起動します。

* cpu: 2
* memory: 2GiB
* disk: 60GiB

以下のようにオプションを指定すると設定を変更して起動することができます。

```zsh
# cpu: 1
# memory: 2GiB
# disk 10GiB
colima start --cpu 1 --memory 2 --disk 10
```


### Volumeマウントの補足

書き込み可能なVolumeに対する`lima`のサポートは実験段階[^1]であるため、デフォルトでは読み取り専用のVolumeとしてマウントされます。
書き込みが必要である場合は、VMの起動時にオプションを付けるようにしましょう。

[^1]: \> https://github.com/abiosoft/colima/blob/305d01fa83e0024738dfd028920cf72858f6a600/README.md#faq <br> > Colima uses Lima for the VM and Lima's support for writable volumes is still experimental. <br> > https://github.com/lima-vm/lima/blob/544d15d5af3ff3eb144148a36c17bc8f62f92a9c/pkg/limayaml/default.yaml#L43 <br> > Setting `writable` to true is possible, but untested and dangerous.

```zsh
# VMの起動（with DocumentsディレクトリをVMにマウント）
colima start --mount $HOME/Documents/:w

# 適当な名前の作業用のディレクトリを作成して移動
mkdir $HOME/Documents/colima_volume/
cd $HOME/Documents/colima_volume/

# カレンディレクトリをマウントし、マウントしたディレクトリ内に新たなディレクトリを作成する
docker run --rm --volume "$(pwd):/opt" -it debian:10 bash -c "mkdir /opt/sample_dir"

# カレントディレクトリの情報を取得
ls
# => sample_dirが作成されているはず
```


## VMの停止

```zsh
# VMの停止
colima stop

# VMの削除
colima delete
```
DX白書2021のサマリを悪戯心でサマってみる


:::note warn
この記事は、明らかに悪戯心的気持ちが含まれておりますので、うのみにするのはご注意。ですが
:::


## さきにまとめ

* 日本の企業は、DXに50%以上が取り組んでいる。コロナとレジ袋のせい。
* 必要な人材は、"コミュニケーション"と"実行力"というふわっとしたスキルセット。
* 海外では、"顧客志向"と"テクノロジーリテラシー"が重視されてて、激しく乖離。
* 人材は、"量"も"質"も大量に不足してると、認識はしている。
* だけど、社内で育成する気はない。検討もしてない。
* IT基盤は、取り組む以前に、"知らない"が全て30%以上。アジャイル開発など知らん。
* データ活用はしたいけど、データ基盤がないため、出来ない。

これまで[SI屋さんに丸投げした](https://qiita.com/saitofjp/items/09c8b4af32e9db97efe9)結果、DXとかデータ活用って言葉は知ってるけど何も出来ないっす。誰かやってくれる人材が欲しいス。

みたいな状況っぽくて変にリアリティがありますね。

## DX白書2021 とは

これ
https://www.ipa.go.jp/ikc/publish/dx_hakusho.html

この記事では、主に下のサマリを読んだ感想です。
> DX白書2021
エグゼクティブサマリー
発行日：2021年10月11日

「またお国のあれ」かと思った方ほど、この界隈をウォッチすると楽しいかもしれません。

IPAのDX界隈は、エンジニアサイドのぶっちゃけベースから始まってる感ありで、「SI屋に丸投げして技術をブラックボックスにし結果、お前らはもうすぐ死ぬ。」という**2025年の崖**とか。「**技術負債**がー」を分かりやすい言葉に直し続けてたりします。

IT基盤のリテラシが低いのは、DXがデータ活用としてしか認識されてない感もあるのかなあと。下手するとエンジニアサイドにさえ浸透してない空気を感じます。アジャイル開発/DevOps/コンテナ/マイクロサービス/とかも、DXに関係するんだよと言われてどう思いますか。

## ここからは、スクショに一言

### 50%以上は、DXに取り組んでいる。

海外には差をつけられてるけど、50%以上はDXに取り組んでます。朗報!!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/74b746f2-2ba5-6024-eec7-a36873c2ab3d.png)


### きっかけは、競争相手ではなく周りの環境

"ディスラプターの出現"のグラフに注目ですね。ライバルの脅威になるわけですが、SDGsの方が脅威に感じてます。
「俺たちは絶対死なないから長生きのほうが大事。まずはレジ袋。」という皮肉にみちゃいけない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/e937e769-1914-ed95-4127-2f5ca3010615.png)

### "実行力/コミュニケーション" vs "テクノロジリテラシー/顧客志向" 

そもそも実行力ってなんだろう。と感じますが、なんかダントツ人気です。
「誰かやってくれ」って言ってないそれ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/0e217596-a291-d0d5-55ae-74cc960ca240.png)


### "量"も"質"も大量に不足

前振り

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/f03fed43-ec99-b7fe-095f-67176b8f8f52.png)

### ただし、社内教育する気は全くない。検討もしてない。

どかーん！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/e97f2242-e9af-965d-f2ee-9ecfb1028c65.png)

### よくわからないけど、ITシステムが出来てないんだと思う。

"どちらとも言えない。"が、多すぎるのは、ピンと来てないな！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/75f3dca9-a097-a080-13e3-daf338e8c979.png)


### アジャイル開発とかDevOpsとかコンテナとかマイクロサービスは、そもそも知らない。

そりゃ、一般社員が知らないのは当然ですよね。

> 26業種（製 造業、非製造業）の経営層またはICT関連事業部門の責任者もしくは担当者

え？あれ、ICT担当。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/e39de26a-5a73-8e6a-04c7-d7d74c88c92f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/b4443d5c-5dbf-a632-6193-5ddc720f427d.png)


### データ活用出来ないのは、システムが対応してないから。

人材もないし、既存システムとか管理システムが対応できてないんだもん。
経営層の理解とIT部門の知識だけ、海外と逆転してます。。それそもそも(ry

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29715/392cddfa-3e09-3cc7-12fa-365feb3cbc49.png)


## ひとこと

頑張っていきましょい！
[WPF]Windows 11 スナップレイアウトに対応する（要修正）

こんにちは。

Windows 11がリリースされて一週間経ちましたが、ウィンドウまわりにスナップレイアウトという機能が実装されましたね。
最大化ボタンまたは元に戻すボタンをホバーすると、下記のようなものが出てきます。
![2021-10-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4734/cf1934a1-612a-2c5a-52a7-80a74fd8708c.png)
で、任意の領域をクリックすると、その領域にウィンドウがジャストフィットするようにレイアウトされます。

この機能、私が開発しているboiler's Graphicsでも使えるのかなー。そう思っておもむろに起動してみましたが、使えませんでした。

Windows 11 上でデスクトップ アプリのスナップ レイアウトをサポート
https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/apply-snap-layout-menu

上記記事によると、WPFアプリには何やら特別な処理が必要だそうです。

というわけで、当記事ではboiler's GraphicsをWindows 11のスナップレイアウトに対応させてみたいと思います。

で、早速ですが以下が変更したコードです。

```csharp:MainWindow.xaml.cs
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;

namespace boilersGraphics.Views
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Loaded += (o, e) =>
            {
                var source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
                source.AddHook(new HwndSourceHook(WndProc));
            };
        }

        const int WM_NCHITTEST = 0x0084;
        const int HTMAXBUTTON = 9;

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_NCHITTEST)
            {
                int x = lParam.ToInt32() & 0xffff;
                int y = lParam.ToInt32() >> 16;
                var maximizeButton = this.MainWindowInstance.Template.FindName("MaximizeButton", this.MainWindowInstance) as Button;
                var rect = new Rect(maximizeButton.PointToScreen(new Point()), new Size(maximizeButton.Width, maximizeButton.Height));
                if (rect.Contains(new Point(x, y)))
                {
                    handled = true;
                }
                return new IntPtr(HTMAXBUTTON);
            }
            return DefWindowProc(hwnd, msg, wParam, lParam);
        }

        [DllImport("user32.dll")]
        static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
        :
    }
}
```

要点は以下の通りです。

1. Loadedイベントでグローバルフックを使う
1. グローバルフック内でWM_NCHITTESTメッセージを捕捉したらHTMAXBUTTONを返すようにする
1. 2はマウスポインタが最大化ボタンの上に存在する（ホバーしている）時のみ、handled = trueにする

上記の記事内（英語）には、"For Win32 apps, make sure you are responding appropriately to WM_NCHITTEST (with a return value of HTMAXBUTTON for the maximize/restore button)."と書いてあります。つまりWM_NCHITTESTメッセージが来た時ははHTMAXBUTTONを返せということです。

これで、boiler's Graphicsはどのような挙動をするか確認しました。

![Windows11_SnapLayout.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4734/2044adfa-b460-ca64-6e74-12d8a4668545.gif)

おおースナップレイアウトはちゃんと動きます。
しかし、最大化ボタンをクリックしても反応しなくなってしまいました。最小化ボタンと閉じるボタンは正しく反応するのですが。どうしたら良いんだろう...。

（下記2021/10/13 14:17追記）
ソースコードを載せ忘れました。
ここに置いときます。

boiler's Graphics
https://github.com/dhq-boiler/boiler-s-Graphics
ブランチ：feature/windows11
【電話番号抽出】英数全角記号特殊文字が入り混じった文字列から数字だけを抽出する。ついでに全角数字は半角数字に変換する。

## あらすじ
先日、Amazonから出品者情報を取得する必要があったので、データを見て見たところ、電話番後がこのような形になっていた。

```
※個人情報保護の為電話番号は０でマスキングしてあります。

000−0000−０００
+8190-００００-z００００
03 0000 0000 です。
0000−00−0000
電話番号はこちら　→ ０００　　0000 ００００
00−0000−0000
〇〇宛　000−0000−000
```
どうやらAmazonでは出品者の情報(本人によるCSV入力だと思われる)はちゃんとしたバリデートが行われていないっぽい。

## 要件
・とりあえず数字だけを取得する。
・全角数字は半角数字に変換して、電話番号の一部と数える。

## 実際のコード

Paizaに実際に動かしたコードがあるので、コード見るのだるい人は確認してみてください。
https://paiza.io/projects/TwekAfnexAUCixptI7Sn3g

```PHP

//文字変換を行うメソッド
function mbTrim($pString)
{
   $pString = preg_replace('/[\D*$]/u', '', $pString); //数字だけ（半角全角問わず）抽出
   $pString = mb_convert_kana($pString, "n"); //全角の値を半角に変換
   $pString = preg_replace('/^81/u', 0, $pString); //国際電話番号表記（+81）は先頭を「０」に修正

   return $pString;
}

//テストデータ格納してるだけのメソッド
function getData(){
    $data = 
"000−0000−０００
+8190-００００-z００００
03 0000 0000 です。
0000−00−0000
電話番号はこちら　→ ０００　　0000 ００００
00−0000−0000
〇〇宛　000−0000−000";

    $data_array = explode("\n", $data);

    return $data_array;
}

$telNums = getData();
foreach($telNums as $telNum){
    $telNum = mbTrim($telNum);
    $convertedTelNums[] = $telNum;
}

var_dump($convertedTelNums);
/* 結果
array(7) {
  [0]=>
  string(10) "0000000000"
  [1]=>
  string(11) "09000000000"
  [2]=>
  string(10) "0300000000"
  [3]=>
  string(10) "0000000000"
  [4]=>
  string(11) "00000000000"
  [5]=>
  string(10) "0000000000"
  [6]=>
  string(10) "0000000000"
}
*/
```
AWSから突然$52.92(6031円)の請求が来たときの話

##はじめに
最近、pythonでAWSでのいくつかのAIサービスの学習をスタート


[AWSでAIサービスを使ってみる〜第11回Personalize編〜](https://qiita.com/AInosukey/items/1939cbac0ac5085f6463)

ちょうどPersonalizeの試しの学習を終え、Qiitaへの記事投稿もひと段落した


約一週間後、、、、、、その通知は届き来ました。


![スクリーンショット 2021-10-13 10.44.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1658175/30888628-f8c6-9134-1427-a921418b0e78.png)

ハイ！？


####$52.92?




#####一体これはどういうことなんだってばよ！？


##気づいたときは
時すでに遅し
9月末からpersonalizeの請求が入っており、気づいたのが10月であったため10月分の請求も含まれていました。。。

####Cost Explorer
![スクリーンショット 2021-10-13 10.57.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1658175/def4a351-92b8-c387-a080-43efb69176d6.png)

##何が起こっていたのか
実際の請求の内容はpersonalizeの学習の後、データセットを停止させずにそのままACTIVE状態のまま翌月まで起動させていたため(気づけよ)、無料枠の請求を超えて通常の請求が入ったようですね。
使用していなかったためpersonalizeのデータセットは削除しました。削除も順番があり、作成したキャンペーンやソリューションから削除する必要があるので注意です。


無料枠を超えたメールが来ていました。
![スクリーンショット 2021-10-13 11.14.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1658175/a4dfea32-daa1-c621-f01e-35af0655b9ae.png)



##終わりに
AWSのAIサービスは将来的なWebサービスの中核として期待されていますが、ご利用には注意が必要ですね。
personalizeのみでなくForcastもいくらか請求額があるため、検証する事柄やデータは事前に調整して必要なデータのみ利用することをオススメします。
[Azure] VMのManagedIDを利用したAzure PowerShellの認証方法

Azure VMでマネージドIDを使用して、Azure PowerShellの認証を行う方法を調べたので、
備忘としてまとめます。

## VMのマネージドID有効化方法

https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm

## マネージドIDを使用した認証方法

調べたところ、認証方法には下記2種類がありました。
①　アクセストークンを取得する
②　"Connect-AzAccount -identity"コマンドを実行する

#### ■ 方法①：アクセストークンを取得する
Microsoftの[こちら](https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-azure-powershell)のサイトに記載の方法です。
こちらは都度トークンを取得する形となるため、PowerShellターミナルを終了すると再認証が必要となります。


#### ■ 方法②："Connect-AzAccount -identity"コマンドを実行する
Microsoftの[こちら](https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-sign-in#azure-powershell)のサイトに記載の方法です。
このコマンドを実行すると、PowerShellターミナルを閉じてもOS再起動しても、再認証は不要となるようです。

仕組みとして、コマンドを実行すると下記ファイルが作成され、認証済み情報が格納されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2139241/14aef1ca-13ae-a46c-5d8a-f11951b7e244.png)
ファイルの中身はこんな感じで、マネージドIDを使用した認証済み情報が記述されます。

``` ruby:Connect-AzAccount後のAzureRMContext.json
{
  "DefaultContextKey": "サブスクリプション (<subscription id>) - <tenant id> - <managed id>",
  "EnvironmentTable": {},
  "Contexts": {
    "サブスクリプション (<subscription id>) - <tenant id> - <managed id>": {
      "Account": {
        "Id": "<managed id>",
        "Credential": null,
        "Type": "ManagedService",
        "TenantMap": {},
        "ExtendedProperties": {
          "Subscriptions": "<subscription id>",
          "Tenants": "<tenant id>"
        }
      },
      "Tenant": {
        "Id": "<tenant id>",
・・・
```

`Disconnect-AzAccount`コマンドを実行すれば、ファイル内の認証済み情報が削除されます。
ファイルをリネームしても認証不可（再認証必要）になります。

``` ruby:Disconnect-AzAccount後のAzureRMContext.json
{
  "DefaultContextKey": "Default",
  "EnvironmentTable": {},
  "Contexts": {},
  "ExtendedProperties": {}
}
```

## 余談
Azureサポートによると、マネージドIDを有効化したVMに不正アクセスされる
リスクを考慮し、以下を徹底して下さいとのこと。
・第一に不正アクセスされないようデバイスを保護する
・不正アクセスされてしまった場合を考慮し、マネージド ID に付与するアクセス許可 (IAM) を最小限のロールにしておくこと

以上です。
numpy.ndarrayとstd_msgs/MultiArrayの相互変換


# はじめに
ROSでpythonを使う際，numpy arrayをpublish/subscribeしたいときに変換する関数をまとめておきました．

# numpy ⇔ MultiArray変換
ポイントとしては，[std_msgs/MultiArrayLayout](http://docs.ros.org/en/api/std_msgs/html/msg/MultiArrayLayout.html)を変換したnumpy.ndarrayにあわせて変更する必要がある点です．

```python:converter.py
#!/usr/bin/env python

from functools import partial

from std_msgs.msg import MultiArrayDimension, Float32MultiArray

def _numpy2multiarray(multiarray_type, np_array):
    """Convert numpy.ndarray to multiarray"""
    multiarray = multiarray_type()
    multiarray.layout.dim = [MultiArrayDimension("dim%d" % i, np_array.shape[i], np_array.shape[i] * np_array.dtype.itemsize) for i in range(np_array.ndim)]
    multiarray.data = np_array.reshape(1, -1)[0].tolist()
    return multiarray

def _multiarray2numpy(pytype, dtype, multiarray):
    """Convert multiarray to numpy.ndarray"""
    dims = map(lambda x: x.size, multiarray.layout.dim)
    return np.array(multiarray.data, dtype=pytype).reshape(dims).astype(dtype)

numpy2f32multi = partial(_numpy2multiarray, Float32MultiArray)
f32multi2numpy = partial(_multiarray2numpy, float, np.float32)
```

`partial()`の部分を`Int8MultiArray`等で定義することで他のデータ型にも対応させることができます．

# Publish/Subscribe

```python:talker.py
#!/usr/bin/env python

import numpy as np
import rospy
from std_msgs.msg import Float32MultiArray

from converter import numpy2f32multi


def talker():
    pub = rospy.Publisher('chatter', Float32MultiArray, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    r = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        arr = np.random.rand(2, 2, 2).astype(np.float32)
        arr_msg = numpy2f32multi(arr)
        pub.publish(arr_msg)
        r.sleep()
 
if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException: pass
```

```python:listener.py
#!/usr/bin/env python

import numpy as np
import rospy
from std_msgs.msg import Float32MultiArray

from converter import f32multi2numpy


def callback(msg):
    arr = f32multi2numpy(msg)
    rospy.loginfo(arr)
    rospy.loginfo(type(arr))
    rospy.loginfo(arr.shape)


def listener():
    rospy.init_node('listener', anonymous=True)
    rospy.Subscriber('chatter', Float32MultiArray, callback)
    rospy.spin()

if __name__ == '__main__':
    listener()
```
Grundy数を使って1次元ドミノ置きゲームを解く（その２）

その１は[こちら](https://qiita.com/masa0599/items/020b9ed3acb575ec89ac)

### ドミノ置きゲーム

**【問題】1次元のマス目（1xN）に交互にドミノ（1x2）を置いて行って置けなくなった方が負けというゲームで、先手が必ず負けになるN<100をリストせよ**

この問題をGrundy数を求めた結果を再びN＝7まで表にします。

|N|mex|G(N)|
|:---:|:---|:--:|
|N=0||0|
|N=1||0|
|N=2|$mex(G(0))$|1|
|N=3|$mex(G(1))$|1|
|N=4|$mex(G(1),G(2))=mex(0,1)$|2|
|N=5|$mex(G(3),G(1)\oplus G(2))=mex(1,1)$|0|
|N=6|$mex(G(4),G(1)\oplus G(3),G(2)\oplus G(2))=mex(2,1,0)$|3|
|N=7|$mex(G(5),G(1)\oplus G(4),G(2)\oplus G(3))=mex(0,2,0)$|1|

これから推測されるように、任意のNの時のGrundy数は以下の式で表せます。

```math 
\begin{align}
G(N) &= mex(\\\ 
&G(0)\oplus G(N-2),\\\ 
&G(1)\oplus G(N-2-1),\\\ 
&...\\\ &G(k)\oplus G(N-2-k))
\end{align}
```
  
ここで$0\leqq k \leqq floor(N/2)$

これをそのままPythonのプログラムにします。まずmex関数を定義します。単純に0からリストの最大値まで見ていって、ない数があったらそれを返し、もし全部あった場合は最大値+1を返します。

```python
def mex(gl):
  for i in range(max(gl)+2):
    if i not in gl: return i
  return ("error")
```
これを使って$G(N)$の計算を行います。2つ前までのGrundy数のリストを逆順にしてXORを取り、mexを見つけてGrundy数のリストに加えるのを繰り返せばOKです。
(XORを取るのは半分までで良いのですがコードを簡単にするために全部取っています)

```python
import numpy as np
n = 100

GL = np.array([0, 0])  # G(0), G(1)
for i in range(2, n+1):
  GL = np.append(GL, mex(GL[:-1]^GL[-2::-1]))

print(list(*np.where(GL==0)))
# [0, 1, 5, 9, 15, 21, 25, 29, 35, 39, 43, 55, 59, 63, 73, 77, 89, 93, 97]
```

これでオンライン整数列大辞典に掲載されていた数列のN<100が計算できました。

（開発環境：Google Colab）

この考え方はProject Euler, Problem 306: Paper-strip Gameを解くのに役に立ちます
Grundy数を使って1次元ドミノ置きゲームを解く（その１）

オンライン整数列大辞典にある[ドミノ置きゲームの問題](https://oeis.org/A215721)をプログラムで解くことを考えます。

### ドミノ置きゲームて先手が負ける場合

**【問題】1次元のマス目（1xN）に交互にドミノ（1x2）を置いて行って置けなくなった方が負けというゲームで、先手が必ず負けになるN<100をリストせよ**

例えばN=4の時、先手は以下のように対称性を考慮すると2通りの置き方があり、(1)では先手の勝ち、(2)では後手の勝ちとなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/34ccb6cd-f372-a86b-9ad0-76eff79e8219.png" width=30%>

N=5の時も2通りの置き方がありますが、どちらの場合も後手が置くと次はもう置けなくなるので先手の負けとなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/e0801cbe-bd8e-684a-e214-ab88f0bf3bd6.png" width=36%>

### Grundy数で勝敗の判定

どうやらこの問題を解くためにはGrundy数というのが関係しそうだということで、こちらの説明を参考にさせていただきました。
> [組み合わせゲーム理論の基礎とGrundy数での勝敗判定アルゴリズム](https://algo-logic.info/combinatorial-games/#toc_id_5)

Grundy数$G(P)$とは

>* 負けが確定した状態$P_{lost}$のとき$G(P_{lost})=0$
>* $P$から1手で遷移できる状態が$P'_1, P'_2,..., P'_k$だとすると
> $G(P)=mex(G(P'_1), G(P'_2),..., G(P'_k))$
>* ここでmex(Minimum excludant)は引数に含まれない最小の非負整数で、例えば$mex(0,1,3) = 2$となります

このゲームの場合N=0,1の時、先手は明らかに負けなので$G(0),G(1)=0$,
N=2の時は1手で$G(0)$となるので$G(2)=mex(G(0))=mex(0)=1$
N=4のときはG(1)とG(2)に移行できるので、それぞれの値(0,1)に対してmexが2となります。これを表にすると、

|N|mex|G(N)|
|:---:|:---:|:--:|
|N=0||0|
|N=1||0|
|N=2|$mex(G(0))$|1|
|N=3|$mex(G(1))$|1|
|N=4|$mex(G(1),G(2))=mex(0,1)$|2|

この表によりN=0,1では先手の負け、N=2,3,4では先手の勝ちと言うことが分かります。

### スプレイグ・グランディの定理
しかしN=5の(1)の例になると、次の空きのマスが1と2にの部分ゲーム分かれてしまうので、それぞれのGrundy数を求めて結合する必要が出てきます。ここで使うのが**スプレイグ・グランディの定理**で、簡単に言うと以下のようになります。

> N個の部分ゲームに対するGrundy数を求めてXORを取ったものが全体のGrundy数となる

すなわちN=5の(1)の場合のGrundy数は$G(1)\oplus G(2)=1$となり,(2)の$G(3)$と合わせると、$mex(G(3),G(1)\oplus G(2))=mex(1,1)=0$となります。同様にしてN=5以降のGrundy数を求めると。

|N|mex|G(N)|
|:---:|:------:|:--:|
|N=5|$mex(G(3),G(1)\oplus G(2))=mex(1,1)$|0|
|N=6|$mex(G(4),G(1)\oplus G(3),G(2)\oplus G(2))=mex(2,1,0)$|3|
|N=7|$mex(G(5),G(1)\oplus G(4),G(2)\oplus G(3))=mex(0,2,0)$|1|

これを見ると規則性が見えてきたようです。[次回](https://qiita.com/masa0599/items/c85e3a5a1b80910f8e51)ではこれをプログラムにしたいと思います。
Android SDK packages as some licences have not been accepted エラーが出たときの対処方法



# licence error

```
> Failed to install the following Android SDK packages as some licences have not been accepted.    
```

こんなエラーが出ることがある。

```
$ cd ~/Library/Android/sdk/tools/bin
$ ./sdkmanager --licenses
Accept? (y/N): y
・
・
All SDK package licenses accepted
```
【RSpec】実行日時によってテストの挙動が変わってしまうテストはtravel_toを使おう

##環境
Ruby 3.0.2
Rails 6.1.4.1


##travel_toメソッド

travel_toブロックの中だけは指定した日時でテストを実行できる。

rails_helperの設定も忘れずに

```rails_helper.rb
RSpec.configure do |config|
  config.include ActiveSupport::Testing::TimeHelpers
end
```

```ruby
context 'travel_toメソッドテスト' do
  travel_to Time.zone.local(2021, 1, 1) do
    p Date.today #=> Fri, 01 Jan 2021
  end
end
```

##参考

https://api.rubyonrails.org/v5.1.7/classes/ActiveSupport/Testing/TimeHelpers.html
MacOSのProcessingでP3Dを使いたい！

# きっかけ
Processingで、以下のように書いた

```java
void setup() {
    size(600, 600, P3D);
}

void draw() {
    background(255, 0, 0);
}
```

そしたら、こんな感じの謎のwarningを吐かれ、正常に動作しなかった
(ちなみに自分のwarningメッセージをメモしてなかったので、同じ状況である他の人のメッセージを拝借した)

```
WARNING: NSWindow drag regions should only be invalidated on the Main Thread! This will throw an exception in the future. Called from (
	0   AppKit                              0x00007fff3105d2e3 -[NSWindow(NSWindow_Theme) _postWindowNeedsToResetDragMarginsUnlessPostingDisabled] + 386
	1   AppKit                              0x00007fff3105a68c -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1488
	2   AppKit                              0x00007fff3105a0b6 -[NSWindow initWithContentRect:styleMask:backing:defer:] + 45
	3   libnativewindow_macosx.jnilib       0x000000012d0c53fe Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0 + 398
	4   ???                                 0x0000000114224a88 0x0 + 4632758920
)
```

調べたところによると、どうやらJOGLのバージョンが問題らしい

https://twitter.com/hau_kun/status/1332983730739105792


# 解決までの手順
Applicationフォルダ内のProcessing.appを右クリックし、「パッケージの内容を表示」を選択する

![スクリーンショット 2021-10-13 12.16.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354215/0e3b6b3a-1adb-dcba-5472-c6a84b19e3a9.png)

`Contents/Java/core/library/`を開くと、色々入っている

![スクリーンショット 2021-10-13 12.18.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354215/2045331d-9937-0b84-e813-7093dd8a768c.png)

この中の、4つの`.jar`ファイル

+ `gluegen-rt.jar`
+ `gluegen-rt-natives-macosx-universal.jar`
+ `jogl-all.jar`
+ `jogl-all-natives-macosx-universal.jar`

を新たなバージョンに置き換えたい

## 置き換えるファイルのダウンロード
JOGL(https://jogamp.org/deployment/archive/rc/ )のv2.4.0を選ぶ

![スクリーンショット 2021-10-13 12.28.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354215/54128050-50b6-b118-5436-25f1f40bcab2.png)

`jar/`を選択するとファイルがたくさんあるので、そこから欲しい4つのファイル

+ `gluegen-rt.jar`
+ `gluegen-rt-natives-macosx-universal.jar`
+ `jogl-all.jar`
+ `jogl-all-natives-macosx-universal.jar`

をダウンロードし、それぞれを`Contents/Java/core/library/`に入っている既存のファイルと置き換えれば解決！

# 参考
Twitter(@ Hau_Kun さん): https://twitter.com/hau_kun/status/1332983730739105792
GitHubのissue: https://github.com/processing/processing/issues/5676
Kotlin firstOrNullの使い方について


実務でfirstOrNullのメソッド使う時があったため備忘録としてここにメモしておきます

```
//以下のようなlistがあった場合に頭の1を取得したい場合に`firstOrNull`や`first`を使います

val list = listOf("1", "2", "3","1")
list.firstOrNull { 1 == it.1}
```

`fist`,`firstOrNull`の違いについて

```
val list = listOf("1", "2", "3","1")
list.first {2 == it.4}
//listの中に4がないのでnullになりおちます

list.firstOrNull {2 == it.4}
//listのなかに4はありませんが、該当する値がない場合はnullをあつかってくれるので、あらかじめnull許容にしておけば問題ありません

```
タスクキルしたときにForeground Serviceの通知が消えない時の対処方法

※Pixel 5 Android 12 betaでほぼ確実に発生することを確認しましたが、他の端末・バージョンだと発生するかどうかはまちまちです。

Foreground Serviceを実行している間にアプリをタスクキル（タスクリストからActivityをスワイプして消す）すると、Serviceの`onDestroy`は呼ばれず、Foreground Serviceの通知が残り続けます。

LogCatを見ていると

```
ActivityManager: Scheduling restart of crashed service 
```

のような行が見えます。おそらくタスクキルの操作により一度Serviceが強制停止されるが、システムにより自動的にServiceが再起動されているのでしょう。

以下のようにログを仕込んで、タスクキル時にServiceに何が起こっているかを調べてみました。

```kotlin
class MyService : Service() {

  override fun onCreate() {
    Log.d("HOGE", "onCreate")
    super.onCreate()
  }

  override fun onDestroy() {
    Log.d("HOGE", "onDestroy")
    super.onDestroy()
  }

  override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    Log.d("HOGE", "onStartCommand")
    // Serviceで行う処理
  }
}
```

すると、タスクキル操作をした後に以下のログが出ていました

```
10-13 11:46:34.649  1741  3928 W ActivityManager: Scheduling restart of crashed service my.app/my.app.MyService in 1000ms for start-requested
10-13 11:46:35.661  1741  1892 I ActivityManager: Start proc 28886:my.app/u0a522 for service {my.app/my.app.MyService}
10-13 11:46:37.281 28886 28886 D HOGE: onCreate
```

このログから、以下のことがわかります。

* タスクキル操作により`onDestroy`は呼ばれない
* Serviceがシステムにより再起動され`onCreate`が呼ばれる
* 再起動時は`onStartCommand`は呼ばれない

タスクキルをしてもForeground Serviceは動き続ける（一旦止まるがシステムにより再起動される）ので、通知が消えないようです。

## 解決方法

シンプルにタスクキル操作時にServiceを止めたいという場合は、AndroidManifest.xmlに`android:stopWithTask="true"`を付ければ良いです。

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="my.app"
    >

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    <application>
        <service
            android:name=".MyService"
            android:exported="false"
            android:foregroundServiceType="microphone"
            android:stopWithTask="true"
            />
    </application>
</manifest>
```

Serviceを止めるだけでなく、なんらかの処理を行いたい場合は`android:stopWithTask="true"`**を付けずに**（または`"false"`を付ける）Serviceで[onTaskRemoved](https://developer.android.com/reference/android/app/Service#onTaskRemoved(android.content.Intent))をオーバーライドします。

```kotlin
class MyService : Service() {
  override fun onTaskRemoved(rootIntent: Intent?) {
    // タスクキル時の処理
    // Serviceを止めたいならstopSelf()する
    // super.onTaskRemovedは空なので、呼ばなくても大丈夫そう。将来仕様が変わる可能性を考慮して一応呼んでおいたほうが安全かも？
  }
}
```

ただし、`onTaskRemoved`が呼ばれるのはServiceがシステムにより再起動された後です。すなわち、一度Serviceは強制停止された後、新しいServiceが開始され、そのインスタンスで`onTaskRemoved`が呼ばれます。ちょっと直感的ではない動き方なので気をつけましょう。

1. タスクキルする
1. Serviceが強制停止される（onDestroyは呼ばれない）
1. システムによりServiceが再開される（onCreateが呼ばれる）
1. onTaskRemovedが呼ばれる

`onTaskRemoved`が呼ばれる時点ではServiceのインスタンスが作り直されているので、注意しましょう。「Serviceのインスタンスは一つだけ」というつもりでコードを書きがちなので…

Foreground Serviceを使うときは、タスクキルに要注意です。
Android DIフレームワークのトレンドについて調査

Androidプロジェクトに新規参加することになり、
利用されているDependency Injection(以下、DI)について調査しました。

プロジェクトで使われているDIがなぜ選択されたのか、
他との比較をした上で良い点、悪い点も把握するため調査した内容になります。

# DIとは？
`依存性の注入`、`依存関係インジェクション` と表記されます。

```
依存関係インジェクション（DI）はプログラミングで広く使用されている手法で、Android 開発にも適しています。
DI の原則に従うことで、優れたアプリ アーキテクチャの土台を築くことができます。

依存関係インジェクションを実装すると、次のようなメリットがもたらされます。

・コードを再利用できる
・リファクタリングが容易になる
・テストが容易になる
```
引用：https://developer.android.com/training/dependency-injection?hl=ja


# Android DI フレームワーク一覧
* ★Dagger
* ★Hilt
* ★Koin
* Kodein
* Katana
* RoboGuice
* Proton

調べたところ多数見つけることが出来ましたので絞って更に調査を行うことにしました。
ただしDaggerとHiltはAndroid Developersに記載されている為、無条件で対象とします。

| |更新状況|スター数|
|---|---|---|
|Koin|継続中|7k|
|Kodein|継続中|2.6k|
|Katana|継続中|180|
|RoboGuice|最終更新2016年|-|
|Proton|最終更新2014年|-|

## Dagger
* Java、Kotlin、Android 向けの完全に静的なコンパイル時依存性注入フレームワークになります。
* 元々はSquare社が開発したものをGoogleがforkした形になります。
* この時に呼び名が変わっており、明確にはSquare社のv0.9.0~1.2.1をDagger、
* Googleのv2.0.0~v2.3.6をDagger2と呼ばれています。
* 導入方法については[Android Developers](https://developer.android.com/training/dependency-injection/dagger-basics?hl=ja)に記載されています。
* ただし現在(2021年10月)はHiltの方を推奨しているようです。

## Hilt
* HiltはAndroid Dev Summit 2019にて発表されました。
* 2020年5月にalphaバージョン、2021年5月に1.0.0がリリースされています。

* HiltはDaggerの上に構築されているため下記のDaggerの恩恵を受けられます。
  * コンパイル時の正確性
  * 実行時のパフォーマンス
  * スケーラビリティ
  * Android Studioのサポート

* こちらも導入方法については[Android Developers](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja)に記載されています。

## Koin
* Kotlin開発者向けの実用的で軽量な依存性注入フレームワークになります。
* Android Kotlinだけではなく、Android Java、Ktorでも利用可能です。
* 使い方がかなり簡易であり以下の操作で使うことが出来ます。
  * injectしたいモジュールの宣言
  * Koinの開始
  * 利用箇所でinject

### Koinを使ってみて
Android DIへの入りとして学習コストが易しそうなKoinを触ってみました。
以下サンプルではActivityにViewModelを注入する事としました。

まずはViewModelの定義を行います。
このViewModelでは2つのUseCaseを利用するので定義します。

```SampleViewModel.kt
internal class SampleViewModel(
    private val hogeUseCase: HogeUseCase,
    private val fugaUseCase: FugaUseCase
)
```

次にViewModelを注入する為、モジュールに定義します。
この時、依存関係のネストである2つのUseCaseは明確に定義する必要がなく、
 `get()` のみで判別してくれる為大変楽でした。

```myModule.kt
val myModule = module {
    viewModel { SampleViewModel(get(), get()) }
}
```

次に定義したモジュールをKoinに読み込ませます。
読み込ませるにはKoinを開始する時に定義するだけで大丈夫です。

```App.kt
startKoin {
    androidContext(this@App)
    modules(myModule)
}
```

最後にViewModelを利用する箇所でViewModelを注入します。

```SampleActivity.kt
private val sampleViewModel: SampleViewModel by viewModel()
```

わずか数行で依存性の注入を実装することが出来ました。
また、Daggerのようなアノテーションベースではない為大変分かりやすかったです。

# まとめ
* 現在選択肢に上がるのはHiltかKoin。
* ただしAndroid Developersで推している為、スタンダードはHilt。
* 以下コストから(個人的に)Koinも選択肢として有り。
  * 導入のしやすさ
  * 記述の見やすさ
  * 学習コスト

# 参考
https://developer.android.com/?hl=ja
https://insert-koin.io/
[AWS,APIGateway,SAM]InvokeRoleのCALLER_CREDENTIALSについて

AWS SAMでtemplate.yamlを書いており、APIGatewayのリソースを作成しようとした際に迷ったので記事にしておきます。
AWS公式の記事は少し読みづらいです。
とても限定的な記事なのでほとんど読まれないと思いますが、同じような疑問を思っている人の助けになれば。

## InvokeRoleでは何を設定するのか
InvokeRokeに設定するのはずばり__「APIGatewayの権限」__になります。
IAMロールのARNを入れれば、APIGatewayの権限は指定したIAMロールと同等の権限をもつことになります。


https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-api-apiauth.html#sam-api-apiauth-invokerole

公式ドキュメントによると、InvokeRoleに設定できるのは以下の値です。
`CALLER_CREDENTIALS, NONE, IAMRoleArn`
何も設定しない場合、CALLER_CREDENTIALSが適用されます。

さて、ここで`CALLER_CREDENTIALS`についてです。
一見すると意味が分かりません。

## CALLER_CREDENTIALSとは
`CALLER_CREDENTIALS`とは、APIGatewayを呼び出す際に渡した認証情報をそのまま使うということです。CALLERのCREDENTIALSですので、呼び出し側の認証情報です。
実際にマネジメントコンソールのヘルプにも、以下のように表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2055433/00c246e5-7454-7399-00fb-2996255c1079.png)

ここで、「APIGatewayによって受信された認証情報ってなんじゃい！」という話になってきます。

具体例を見ていきましょう。
APIGatewayを呼び出す際に、以下のように__IAMロールの認証情報__を一緒に送ることが出来ます。
以下のソースではaws_requests_authというライブラリを利用していますので、詳しい実装を知りたい場合は[こちら](https://github.com/DavidMuller/aws-requests-auth)を参考にしてください。

```python
    credentials = get_credentials() # stsからIAMロールのcredentialsを取得
    auth = AWSRequestsAuth(
        aws_access_key=credentials['AccessKeyId'],
        aws_secret_access_key=credentials['SecretAccessKey'],
        aws_host=aws_host,
        aws_region=REGION_NAME,
        aws_service='execute-api'
    )
    headers = {'x-amz-security-token': credentials['SessionToken']}

    response = requests.post(
        url, json={"foo": "bar"}, auth=auth, headers=headers)
```

この時、APIGatewayでは__IAMロールの認証情報__が受信されています。
というわけで、このような形で「受信された認証情報」をつかうことになるわけです。

なので、ここで指定しているIAMロールの権限と同等の権限をAPIGatewayが行使することになります。APIGatewayの呼び先がLambdaである場合、IAMロールにはLambdaの実行権限を付けてあげないと実行できなくなるということです。
Xcode13でiOSアプリの代替アイコンを簡単に追加できます（3つの簡単なステップで）

アイコンのカスタマイズは、新しい機能ではありません。
しかし、Xcode 13のリリース前は、その作業は一筋縄ではいきませんでした。

Xcode 13では、簡単にアプリアイコンを追加し、ユーザーがその中から選択して使用できるようにしています。

## まず、追加となるアイコンカタログを追加します

以前と同様に、アセットフォルダー内の`AppIcon`フォルダーにアプリアイコンを追加します。

デフォルトのアプリアイコンを追加したら、下のバーにある「+」アイコンをクリックし、`iOS`を選択し、`iOS App Icon`を選んで、新しいiOSアイコンパックを作成します。

![スクリーンショット 2021-10-09 15.02.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/e04fe90f-938b-fd54-fd46-857cea8379a5.png)

そして、新しいアイコンをアプリのバンドルに入れてください。

次に、新たに作成したアイコンパックにアイコンを追加する必要があります。

![スクリーンショット 2021-10-12 20.12.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/7087faf4-fdab-b8ea-c451-7b074a02a0b7.png)

1つのiOSアプリに複数のアイコンを追加できます。

上記の画像では、5つのアイコンが追加されたことがお分かりいただけると思います。

## そして、新しいアイコンをアプリのバンドルに入れてください。

次に、Xcodeに新しいアイコンを知らせる必要があります。

まずプロジェクトのターゲットページに移動し、`Build Settings`をクリックしてください。次に`Alternate App Icon Sets`（配列）を検索し、項目をダブルクリックして、カスタムアイコンパックの名前を入力します。

![スクリーンショット 2021-10-12 20.16.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/3bba9ada-042e-661f-c7bf-27be81cd2c79.png)

## ユーザーがお気に入りのアイコンを選択できるようにしましょう

```swift
UIApplication.shared.setAlternateIconName(iconBundleName) { error in
    print(error)
}
```

アイコンバンドルの名称（上記の例では、可能な1つの値として`NekoIcon`が挙げられます）を`setAlternateIconName`引数に指定する必要があります。

アプリアイコンをデフォルトのものに復元したければ、`nil`を引数に指定する必要があります。

```swift
UIApplication.shared.setAlternateIconName(nil) { error in
    print(error)
}
```

---

:relaxed: [Twitter @MszPro](https://twitter.com/MszPro)

:sunny: [私の公開されているQiita記事のリストをカテゴリー別にご覧いただけます。](http://mszpro.com/ioskiji/)
<img width="150" src="https://cdn.mszmagic.com/static-web-content/AppClipImage_small.png">