OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu20.04でWindows10のBootable USBを作る方法

# 方法
## Windows10のISOファイルをダウンロード
ここからWindows10のISOファイルをダウンロードする。言語やバージョンは好きなものを選んで良い。


https://www.microsoft.com/en-in/software-download/windows10ISO

## ソフトウェアのインストール

次にUSBへ書き込むために必要なソフトウェアをインストールする。コンソールに以下のコマンドを入力してインストールする。

```
sudo apt update -y
sudo apt install exfat-fuse exfat-utils gparted

sudo add-apt-repository ppa:tomtomtom/woeusb
sudo apt update -y
sudo apt install woeusb-frontend-wxgtk
```

## 対象のUSBのアンマウント
このままwoeusbを使用してもUSBが見つからないため、gpartedでUSBをアンマウントする。

gpartedを起動し、USBの領域を右クリックしアンマウントを押せば完了。

## USBへの書き込み

woeusbを起動し、FATを指定して書き込みを行う。

# 参考

https://itsfoss.com/bootable-windows-usb-linux/

https://www.virment.com/how-to-mount-exfat-on-ubuntu/

https://www.omgubuntu.co.uk/2017/06/create-bootable-windows-10-usb-ubuntu

http://baker-street.jugem.jp/?eid=174
docker-composeでMySQLデータを永続化する方法

## 引用記事
https://www.yukiiworks.com/archives/378

## 手順
MySQLデータをローカルにコピーする
`docker cp <コンテナID>:/var/lib/mysql <コピー先のパス>`

docker-compose.yamlの書き換え
MySQLコンテナの記述の部分に下記を追加
```
volumes:
　　- <MySQLデータをコピーしたパス>:/var/lib/mysql
```
ローカルのボリュームとコンテナのボリュームをバインドマウントする。
C++ vectorの要素をシャッフルする

### はじめに
vectorの要素をシャッフルには`std::shuffle`という標準ライブラリがあります。
基本的にはこちらを使いましょう。

ですが、自分でロジックを組んでみたかったので、
引数にいれたvector（ここではint型）の要素をシャッフルする関数をつくりました。
中身のデータがランダムに並べ替えられます。

シャッフルの処理ロジックってどんなのだろうってなった方のご参考になれれば幸いです。


### 関数
```C++
void shuffle(std::vector<int> *list)
{
	for (std::vector<int>::reverse_iterator itr = (*list).rbegin(); itr != (*list).rend(); ++itr)		// ①
	{
		int r = rand() % (*list).size();		// ②
		int temp = (*itr);		// ③
		(*itr) = (*list).at(r);		// ④
		(*list).at(r) = temp;		// ⑤
	}
}
```

#### ざっくり説明
vectorの要素をほかの1要素と入れ替える、という処理をvectorの後ろのデータから順に行います。

- reverse_iteratorで並びかえるデータを後ろから順に走査します。①
- 要素の1つをランダムに選びます。②
- いまのforループで走査しているデータを一時保存します。③
- いまのforループで走査しているデータを、ランダムで選んだ要素のデータに上書きします。④
- ランダムで選んだ要素のデータを、いまのforループで走査しているデータに上書きします。⑤

※ランダムに選ぶところrand()を使っているので、あんまりランダムじゃないです。この点でも`std::shuffle`の方が良いです。

### 使用例
```C++
std::vector<int> data = {0, 1, 2, 3, 4};

shuffle(&data);

```
VIX 指数を LINE Notify で通知する。

## 今までの流れ
以下の記事では、LINE にメッセージを送信するというのを説明しました。

https://qiita.com/karaage_0921/items/d7f0a68858eb7e892764

この記事では、VIX 指数を取得するというのを説明しました。

https://qiita.com/karaage_0921/items/96ce652a08f320425eaf

## やりたいこと
上記記事の続きです。
「取得した VIX 指数を LINE Notify でLINEにメッセージを送信する」プログラムを実装します。

### 環境
Windows 10 
Python
Selenium

### コード
LINE Notify のトークンを入力して、これを実行します。以上。コードについては過去記事を見てください。
```
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options 
import time

option = Options()                          
option.add_argument('--headless')           
driver = webdriver.Chrome(ChromeDriverManager().install(),options=option)

URL = r"https://www.bloomberg.co.jp/quote/VIX:IND"
driver.get(URL)

vix_value = driver.find_element_by_xpath(r"/html/body/div[5]/main/div/div/div[1]/div/div[3]/div[2]")
print(vix_value.text)

import requests

url = "https://notify-api.line.me/api/notify"
access_token = 'トークンを入力'
headers = {'Authorization': 'Bearer ' + access_token}

message = vix_value.text
payload = {'message': message}
r = requests.post(url, headers=headers, params=payload,)

driver.quit()



```
結果はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/5fa4eaa9-b583-059e-c401-59b3e61943cb.png)

次の記事では、条件付けをしてみます。
もし、VIX の指数がいくら以上だったら、通知をするという内容です。
JavaScript

1、boolean型
boolean型と＝trueかfalseを代入できる変数の事。

```
let b = false;
if(b){
console.log('はい');
}else{
console.log('いいえ');
}
出力結果→いいえ

console.log(b); →false
console.log(!b); →true
```

２、論理演算子
```
&& 論理AND=AとBがあったら両方trueの場合trunを返す
console.log(true && true);　　→true
console.log(true && false);  →false
console.log(false && true);  →false
console.log(false && false); →false

||論理OR=論理値AとBがあったらどちらかがtrueの場合trueを返す
console.log(true || true);　　→true
console.log(true || false);  →true
console.log(false || true);  →true
console.log(false || false); →false

!論理NOT＝論理値を反転させる
console.log(!true); →false
console.log(!false); →true

優先順位
! && ||
console.log(false && true || true); →true
console.log(false && (true || true))　→false

３、nullとundefined

//undefined
let x;
console.log(x);　→undefined

let item = y;
```

４、三項演算子
```
//条件式? trueの場合:falseの場合
(例題)
let score = 70;
let judgement = (score > 50) ? '合格' : '不合格';
console.log(judgement);　→合格
```

５、コールバック関数
```
function greeting(name){
console.log('Hello' + name + '-san');
}

function inputUserName(callback){
let name = prompt('あなたの名前を入力してください');　　
callback(name);
}

inputUserName(greeting); 
```

６、配列
```
let colors = ['red','green','blue'];
console.log(colors);　　→全ての配列を出力 red,green,blue
console.log(colors[0]); →１つ目の配列を出力 red

//個数
console.log(colors.length); →3
onClickと無限レンダリング【React】

<h1>onClickとは</h1>
クリック時のイベントを実行する

```react
export default function App() {
  return (
    <div>
      <button onClick={() => {console.log("hello")}}>
        hello
      </button>
    </div>
  );
}
```
例えばこうかくと
クリック時にonClick内の関数が実行される

```react
export default function App() {
  return (
    <div>
      <button onClick={function () {console.log("hello")}}>
        hello
      </button>
    </div>
  );
}
```

もちろんこう書いても同じである

ではこう書くとどうだろうか

```react
export default function App() {
  return (
    <div>
      <button onClick={console.log("hello")}>hello</button>
    </div>
  );
}
```

これは、読み込み時にコンソールに【hello】が表示される
クリックしても何も起こらない

この状態で再レンダリングをしてみる
```react
export default function App() {
  const [count, setCount] = useState(0);
  const add = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>{count}</p>
      <button onClick={add}>add</button>
      <button onClick={console.log("hello")}>hello</button>
    </div>
  );
}
```
コンソールに【hello】再表示される

```react
<button onClick={console.log("hello")}>hello</button>
```

つまりこう書くと、レンダリングするごとにhelloが呼ばれてしまうのだ

<h1>onClickと無限レンダリング</h1>
これがconsoleならまだいいが、onClickの中にこう書いてしまったとする

```react
export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={setCount(10)}>カウント10</button>
    </div>
  );
}
```
```react
Error
Too many re-renders. React limits the number of renders to prevent an infinite loop.
```
無限レンダリングが発生してしまう

先ほど例で挙げたように、この書き方だと、レンダリング時にsetCountが呼ばれてしまうので

レンダリング=> setCount=> レンダリング=> setCount=> レンダリング....

という感じになってしまう

正しく、クリック時にイベントを実行するには

```react
export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(10)}>カウント10</button>
    </div>
  );
}
```

こう書くべきである
フルダイブMMORPG ITクエスト

## プロローグ

この文章を目に止めたあなたは、彼の地(IT業界)での長い旅路についていることでしょう。

もしもこれまでの人生で、FF11でもPSOでも『数本』のMMORPGを遊んでいれば、この世界での旅路で起こることの多くを予見することができると思います。

あなたの旅路がよりよいものになるように願いをこめて、すこし語ります。


## 冒険の記憶

右も左も分からない中、高レベルプレイヤーの誘いのままに、遺跡やダンジョンなどの未開の地を冒険したでしょうか。強い敵を高レベルプレイヤーが倒し、経験値のおこぼれに授かり、ドロップアイテムをもらえるウハウハ体験をしたでしょうか。

また、高レベルプレイヤーになってからは、自分が受けた恩を返す、新米冒険者に知識を伝えることで優越感を味わう、などの理由で新米冒険者と旅をすることはあったでしょうか。

一方で、最初は全てが新鮮で、いちいち感謝したり感動していたけれども、何本が遊んでいると体験の質が同じことに気づいたでしょうか。
自分のクエストを優先するようになり、新米冒険者に手を差し伸べなくなっていったでしょうか？

あるいは、充実したチュートリアルをプレイし、ある一定のレベルまでは快適に進める様になったけれども、チュートリアルが終わってもその内容を全く覚えてないということはあったでしょうか？

**他にも色々な記憶があるかと思いますが、それらの記憶を、IT業界の旅路に置き換えてみてください。**

MMORPGの中の人も彼の地で就労している人も同じ人間なのだから、彼の地で就労している高レベルプレイヤーや新米プレイヤーの立ち振舞も想像できてきませんか？

あなたが経歴書を送りまくって面接をしまくってようやく所属したITギルドは、流れの冒険者の集まりです。
それぞれの冒険者がそれぞれのクエストを抱えていて、たまたま新米冒険者に声をかけてくれる優しい人がいたりいなかったりする、そんな世界だと考えると分かりやすいと思います。


## 課金でつよさは買えない

ゲームの世界の記憶と彼の地のルールの違いで忘れてはならないことがあります。
**『課金では簡単につよくならない』** ことです。

スクールなどへの課金は、有料チュートリアルだと考えると分かりやすいと思います。
本当につよくなるには無限に冒険を繰り返して地道に経験値を手に入れてレベルアップしてスキルツリーを伸ばしていくしかないです。
経験値２倍などのチートアイテムは存在しませんが、**「知覚力」** のスキルは何をしても経験値が多めに入りますし、**「タイピング」** のスキルは行動速度1.5倍のバフがかかり続けるので早めに取った方がよいスキルだと思います。


## ポップ・リポップ（モンスターの出現・再出現）

自分のレベルで効率よく経験値を稼げるモンスターを倒して、リポップ待ちして、再度倒して経験値を稼いだことはありますか？
特定の場所でプレイヤー達がこぞってポップ待ちをして、ポップしたらわれこそはと倒し、遠慮しているといつまで経っても経験値を得られなかったことはありますか？

ITクエストにおいては、「案件」がこのモンスターに相当します。
実際には全く同じモンスターは存在しないため、「同程度の難易度の案件」がポップするのを待つことになります。

日本国が運営しているITクエストは、案件の量も難易度も、年々渋くバランス調整されているようです。

昔々あった、10人パーティで遺跡を何年もかけて攻略するといった案件は今ではほとんど存在しません。
モンスターが出現しないのであればギルドも冒険者も不要となってしまいますので、運営には頑張ってほしいものですね。

最近の案件は以下でしょうか。
ローコード・ノーコードの流れから来る、別系統のスキルツリーを伸ばす案件、アイデアを超高速で形にしてサービスをリリースするスタートアップ系案件、止められないレガシーシステムをリプレイスする高難易度マイグレーション案件、正体不明の敵DX案件、どの様な攻撃をされてもサービスを維持する大規模防衛戦SRE案件などなど。

新米冒険者のあなたが倒せそうなモンスターはこの中にいるでしょうか？


## レベル20以降のレベルアップ

多くのゲームでは、レベルが上がる毎に1レベル上げるための経験値が高くなっていきます。あるいは、同じモンスターを倒していると経験値があまりもらえなくなります。更には1レベル上がってもたいしてつよくならなくなっていきます。

これはITクエストでも同じです。

単一の案件を継続すると、経験値が入りにくくなりレベルも上がらず他の案件へ入りにくくなります。
メインのクエストとは別で、死にかけながら効率的な狩り場を探したり、我慢して地道な反復をしたり様々な工夫をしてレベルを上げて、運営が用意する新たな案件への参加条件を獲得しないといけなくなります。

ITクエストの世界では、github を旅して回ると消滅しないちょうどよいつよさのソースを見つけて経験値を稼げるかもしれません。
ただ地図もコンパスもなく github を旅して回るのはとても大変なので、**何か作りたいモノ** など自分なりの課題を決めて、それを達成するための方法を探して回るのがよいかもしれません。

**案件でソースを読みきれないと即死で様々なデスペナルティが発生**しますが、自発的に読んでいるソースは読み切れなくても死なないので安心して読めるのも利点だと思います。


## フルダイブMMORPG ITクエスト

MMORPGは魔王を倒して終わりではなく、その世界での暮らしを楽しむゲームだと思います。
ITクエストは数十年続く人気ゲームですが、ゲームバランスが年々高難易度に調整されている様に思えます。

とは言え、死にかけながら様々な無理難題を攻略した時の達成感はなかなかのものです。
エルデンリングを攻略できるような褪せ人達には、この不条理な世界も楽しめるかもしれないですね。

「…あれ？ログアウトボタンがない？」
Javaの設定がうまくいかない。【javac】

# Javaの学習を昨日始めました

Javaかなるほど。貴様がプログラミング四天王の一人。
ふん。戦闘力三万。まあまあだな。だが！！


#### <font color="Red">くらえ！！！！！</font>




### javacしてみたら

~~~
$ javac Ready.java
bash: javac: command not found
~~~

なに？カリキュラム通りのはず。まさか....デマだと！！！(カリキュラム作成してくださった方すいません)


この俺を騙したな！！！！


ゆるさん！！

しかたない。調べるか。


## 環境変数の設定

どうやら環境変数の設定がうまくいっていないみたいです。
javaをインストールしたあとjavaのフォルダが作成されるらしいのですが、作成されているかわからず、フォルダ検索しても見つかりませんでした。

仕方なく、グーグルの検索欄でこう入力してみると



![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525610/d36530b0-f968-3215-63a7-6ce04dad9dd6.png)


![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525610/3b43968c-734a-651d-202b-f5e2c5bb004c.png)




こんな画面につきました！ほんとに偶然！！


どうやら、この画面のどこかにjavaフォルダがあるらしいです。





......





見つけました！



![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525610/8065fcfc-cca7-92e7-29fd-618f24e68c49.png)



どうやらファイルの設定の名前がうまくいっていなかったらしく、正しい名前に変更したらできました！





## 最後に


ふん地球人め。この俺を騙したつもりか....
いいだろう。命が惜しくないということだな！！









<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>


すいません。
LightGBM + Optunaを試してみる【パラメータチューニング】


## 概要
GBDTをベースにしたLightGBM。
ハイパーパラメータのチューニングにoptunaを試してみたのでまとめる。

## LightGBMとは
**決定木**をベースにした手法。
正確には **GBDT (Gradient Boosting Decision Tree)** という仕組みで動いており、
決定木を直列に繋いで正解との誤差を小さくしていくように学習する。
決定木を使った手法はいろいろあるが、例えば**ランダムフォレスト**は決定木を並列に繋いでアンサンブルを取るという点でGBDTと異なる。
- 参考： https://qiita.com/triwave33/items/aad60f25485a4595b5c8

GBDTを利用した有名な手法として**XGBoost**がある。
一方**LightGBM**は近年Kaggleなどでもよく使われる手法で、XGBoostとほぼ変わらない精度で軽量である点が優れている。


## LightGBMの使い方
- 以下のようにハイパーパラメータを指定する
- ここではmecticsとしてmap@12を指定してるが、必要に応じて変える

``` Python
import lightgbm as lgb

params = {
    'objective': 'lambdarank',
    'metric': 'map',
    'map_eval_at': [12],
    'num_leaves': 63,         # default = 31,
    'learning_rate': 0.01,    # default = 0.1
    'feature_fraction': 0.8,  # default = 1.0
    'bagging_freq': 1,        # default = 0
    'bagging_fraction': 0.8,  # default = 1.0
    'random_state': 0,        # default = None
}
num_round = 100
```
- 以下のようにtrainのときにparameterを渡してあげる
- LightGBMの場合はquery_listを渡す必要がある（本記事では詳細は割愛）
- num_roundは決定木を直列に何本繋ぐかを表している
- 適当に決め打ちで指定してもいいが、この値を大きめに設定しておいてearly stoppingでいい感じのとこで打ち切るのがおすすめ
- 無論trainのメトリクスは学習を続ければ続けるほど良くなるが、これでは過学習に陥ってしまうので、early stoppingではvalidationのメトリクスが変化しなくなったタイミングで止める

``` Python
lgb_train = lgb.Dataset(train_x, train_y, group=query_list_train)
lgb_eval = lgb.Dataset(valid_x, valid_y, group=query_list_valid)

# training
model = lgb.train(params, lgb_train, 
                  num_boost_round=num_round, 
                  valid_names=['train', 'valid'], 
                  valid_sets=[lgb_train, lgb_eval],
                  early_stopping_rounds=20
                 )

# prediction
pred = model.predict(test, num_iteration=model.best_iteration)
                  
```
## Optunaを使ってみる
OptunaにはLightGBM Tunerという機能があり、これを使うと超簡単にハイパーパラメータの探索をやってくれる。
やり方は

``` Python
import lightgbm as lgb
```
を
``` Python
import optuna.integration.lightgbm as lgb
```
にするだけ。
あとはlgb.train()実行時に勝手にハイパーパラメータの探索を行ってくれる
- 参考：https://tech.preferred.jp/ja/blog/hyperparameter-tuning-with-optuna-integration-lightgbm-tuner/

探索後のパラメータは`model.params`で取得できる


## 各種パラメータの意味


#### objective
- 回帰ならregression
- ランク学習ならlambdarank
- などなど
#### metric
- メトリクスとして何を使うか
- ndcg, mapなどを指定できる 

#### ndcg/map_eval_at
  - NDCG/MAP@kのkを設定する 
  - [12, 24]など複数指定も可能

#### num_leaves
- 決定木の最大の葉の数
- 大きいほど複雑なモデルを作れるが、過学習になりやすい
- default: 31

#### learning_rate   
- 学習率
- 学習するたびにどれくらいその結果を強く反映させるか
- 小さいほど細かなチューニングができるが、時間がかかる
- default: 0.1
#### feature_fraction
- Scikit-Learn　APIでの名前: colsample_bytree
- 決定木ごとにランダムに抽出される列の割合
- 値が大きいほど過学習になりやすい
-　default: 1.0

#### bagging_freq
- 設定した値のイテレーション毎にバギング実施する
-　大きいほど過学習になりやすい    
- default: 0

#### bagging_fraction  
- Scikit-Learn　APIでの名前: subsample
- 決定木ごとにランダムに抽出される行（標本）の割合
- 値が大きいほど過学習になりやすい
-　default: 1.0

#### random_state
- default: None


## 参考文献

- https://zenn.dev/megane_otoko/articles/2021ad_09_optuna_optimization
- https://qiita.com/DS27/items/ec6a747977e57bb1837e
MySQL（データベース・テーブル作成）自分用メモ

参考サイト
https://prog-8.com/docs/mysql-database-setup

ターミナルを開いて

#### mysqlのログイン

```terminal
mysql -u root -p
```
パスワードを入れたらログインできる。

#### データベースの確認
```terminal
SHOW databases;
```
( ; )を忘れずに。

#### データベース作成

```terminal
CREATE DATABASE test;
```

`test`がデータベースの名前です。名前はなんでもいいです。

次にデータベースの中身を作っていきます。

#### データベースの選択
```terminal
USE test;
```

#### テーブルの作成

```
CREATE TABLE users (id INT AUTO_INCREMENT, name TEXT, PRIMARY KEY (id));
```
`users`はテーブル名です。

#### テーブルの確認

```terminal
SHOW tables;
```
`users`が入ってるのを確認

#### テーブルの中身を確認

```
DESCRIBE users;
```

#### テーブル取得・挿入・取得

**取得（挿入前確認）**
```
SELECT * FROM users;
```
**挿入**
```
INSERT INTO users(name) VALUES ('ネコこねこ');
```
テーブル名usersの中のnameに`ネコこねこ`が追加されます。

**取得**
```
SELECT * FROM users;
```

#### テーブル削除

テーブル名は`users`なので
```
DROP TABLE users;
```
#### データベースの削除

データベース名は`test`なので
```
DROP DATABASE test;
```
`SHOW databases;`でデータベースが削除されているか確認しましょう。
LINE notify を使ってみる

## やりたいこと
Python と LINE Notify を使ってメッセージを送信してみます。

## LINE Notify とは
LINE Notify を使うと、LINE にメッセージを送ることができます。
https://notify-bot.line.me/ja/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/6822ba17-e68d-7f34-9c96-cc81bf3eca6f.png)
## 今回やりたいこと
とりあえず、「こんにちは」というメッセージをLINEに送信しようと思います。
## 環境
Windows 10
Python
Anaconda Jupyter Lab を使って開発

## 手順 1 : アクセストークンの発行
1. LINE Notify にアクセスして、ログインする。LINEで認証を求められます。

1. マイページ > アクセストークンの発行（開発者向け）に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/8463ade6-b874-8b88-8136-6f191270e221.png)

1. トークン名と送信先の LINE チャットを指定し、「発行する」を押します。
今回は、自分のみに送信してみます。（グループとか他の誰かにも送信できます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/44a4fbc0-0e80-ec8d-4770-7c79d8737914.png)

1. 発行したトークンをどこかに保存しておきます。
[注意] ここを逃すとこのトークンを再度取得できないので、扱いには注意してください。
また、このトークンが誰かに知れ渡ってしまうと、悪用される恐れがある点もお気を付けください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/dc2cb845-fd7d-0791-ea46-4e0cb481eeaf.png)

1. マイページ上では、こんな感じで表示されています。ここで解除もできますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/72ee61c5-1e3a-bdbc-f579-962098a31487.png)

1.以下のコードを実行します。
```
import requests

url = "https://notify-api.line.me/api/notify"
access_token = 'トークン'
headers = {'Authorization': 'Bearer ' + access_token}

message = 'こんにちは。'
payload = {'message': message}
r = requests.post(url, headers=headers, params=payload,)
```
詳細は、LINE Notify の公開情報に記載があります。
https://notify-bot.line.me/doc/ja/

・・・簡単。

1. このコードを実行するとこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269416/d7873085-a6a0-0317-24d5-86ccd299ee28.png)
[トークン名] とメッセージがついてきますね。

今回はこれで終了です。
次は、「Selenium で値を取得する」について解説します。
https://qiita.com/karaage_0921/items/96ce652a08f320425eaf
Kubeflowでのプロファイルによるリソース制限

# はじめに

本記事では、KubeflowでユーザまたはグループごとにGPU等の使用可能なリソースを制限するため、プロファイル機能を利用します。
Kubeflowの導入手順は[こちらの記事](https://qiita.com/shingonagai/items/fee5105613bb83dcaf3f)をご参照下さい。

# 目次

1. [検証環境](#検証環境)
1. [前提条件](#前提条件)
1. [ユーザの作成](#ユーザの作成)
1. [プロファイルの作成](#プロファイルの作成)
1. [Contributorの追加](#contributorの追加)
1. [まとめ](#まとめ)
1. [参考文献](#参考文献)

# 検証環境

以下のKubeflowがデプロイされたKubernetesクラスタにおいて、プロファイル機能を利用します。
![k8s-env.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936643/63351ab9-8f9b-a4bd-130c-2cd01413d4e7.png)

# 前提条件

以下の作業が完了していることを想定しています。

- Kubernetesクラスタが構築済み
- Kubeflowがデプロイ済み

# ユーザの作成

現在のユーザ認証設定をファイルに保存します。
```shell-session
# kubectl get configmap dex -n auth -o jsonpath='{.data.config\.yaml}' > dex-config.yaml
```

作成したいユーザの初期パスワードのハッシュ値を取得します。 (例えば、入力した文字列のハッシュ値を計算してくれるWebサイトを利用することも可能です)

保存したyamlファイルを編集し、ユーザを追記します。(下の例では、user1@example.com, user2@example.comを追加)
```shell-session
# vi dex-config.yaml

- email: user1@example.com
  hash: $2a$12$/5r3glMmYUi0jBFhfhSKCeoRV7rNI3c/06om/OQ2Txr0pyFRc3Zqy
  username: user1
- email: user2@example.com
  hash: $2a$12$/5r3glMmYUi0jBFhfhSKCeoRV7rNI3c/06om/OQ2Txr0pyFRc3Zqy
  username: user2

```

編集したyamlファイルを適用し、ユーザ追加を有効化します。
```shell-session
# kubectl create configmap dex --from-file=config.yaml=dex-config.yaml -n auth --dry-run -o yaml | kubectl apply -f -
# kubectl rollout restart deployment dex -n auth
```

# プロファイルの作成

プロファイルを定義したyamlファイルを作成します。以下の例では、profile1とprofile2を定義しています。各プロファイルで必要なCPU/メモリー/GPU/Volume容量を指定します。
```shell-session
# vi profile.yaml

apiVersion: kubeflow.org/v1beta1
kind: Profile
metadata:
  name: profile1
spec:
  owner:
    kind: User
    name: user1@example.com

  resourceQuotaSpec:
   hard:
     cpu: "5"
     memory: 10Gi
     requests.nvidia.com/gpu: "1"
     persistentvolumeclaims: "5"
     requests.storage: "40Gi"
---
apiVersion: kubeflow.org/v1beta1
kind: Profile
metadata:
  name: profile2
spec:
  owner:
    kind: User
    name: user2@example.com

  resourceQuotaSpec:
   hard:
     cpu: "10"
     memory: 10Gi
     requests.nvidia.com/gpu: "1"
     persistentvolumeclaims: "5"
     requests.storage: "30Gi"
```

定義したプロファイルを適用します。
```shell-session
# kubectl create -f profile.yaml
```

プロファイルが作成されたかどうか確認します。
```shell-session
# kubectl get profile
NAME                        AGE
kubeflow-user-example-com   9m26s
profile1                    4s
profile2                    4s
```

試しに、プロファイルで定義した以上のリソースを割り当てようとした場合、Notebook ServerをLaunchをクリックした後、ServerがQuota制限により起動できないことを確認できました。
![over-quota-limit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936643/590af73d-a9a8-5fe4-b501-798d79c31d44.png)

# Contributorの追加

作成済みプロファイルに別のユーザをContributorとして追加したい場合、左メニューの**Manage Contributors**を選択し、**Contributors to your namespace**に、追加したいユーザ名を入力します。
![contributor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936643/f6cde9a1-cba9-639d-604b-3be149566cbf.png)


# まとめ

今回はKubeflowのプロファイル機能を使って、ユーザやグループごとの使用可能なリソース制限を行いました。Quotaで設定した以上のリソースが割り当てられないことが確認できました。

# 参考文献
- [Muti-Tenancy](https://www.kubeflow.org/docs/components/multi-tenancy/)
Add Business Logic Trailhead challenge

[Build a Suggestion Box App >Add Business Logic](https://trailhead.salesforce.com/en/content/learn/projects/suggestion_box/suggestion_box_4)

# 数式のエラー

+ [Add Business Logic Trailhead challenge](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Gh7GF)


```
IF(ISBLANK(Implemented_Date__c), 
TODAY() - DATEVALUE(CreatedDate), 
Implemented_Date__c - DATEVALUE(CreatedDate))  
```

:::note alert
Incorrect parameter type for operator '-'. Expected Number, DateTime, received Date
:::

:::note
You most likely created the Implemented_Date__c to be a Date Time field when it should be a Date field instead.

おそらく、Implemented_Date__cをDate Timeフィールドとして作成しましたが、代わりにDateフィールドにする必要があります。
:::

+ [I copied and pasted the formula but there was an error, I tried adding the formulas one by one but the result was the same. still error. I also looked at the tutorial, but they only succeeded by copying and pasting. what do I have to do ?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Rd3B3)

+ [I copied and pasted the formula but there was an error, I tried adding the formulas one by one but the result was the same. still error. I also looked at the tutorial, but they only succeeded by copying and pasting. what do I have to do ?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Rd3B3)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3178987c-0e9d-09f6-001c-ca2339f406b9.png)

:::note
you most likely created the Implemented_Date__c to be a Date Time field when it should be a Date field instead.

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A81TwSAJ 
:::
いらなくなったシュミレーターの掃除

# 背景

Xcodeのバージョンアップや、Macを買い換えるタイミングで不要ファイルを削除する時に、いつも確認するので、自分用に纏め📝
 
Xcodeの`Devices and Simulators` (shift + command + 2)で作成したシュミレーターは削除できる（👇）が、
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30834/0080bfa2-64d2-95b8-5e01-3192ea9e449c.png)

上記で削除を行なっても、`Preferences...`の`Components`からダウンロードした`.simruntime`ファイル（👇）は消えない。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30834/9a32627b-2c6a-4e6f-90a8-af671512beac.png)

`.simruntime`ファイルの方がサイズも大きいので、不要になったら削除したい。
でも、Xcodeのバージョンアップを行なっても自動で削除されない。
いつも削除するフォルダを検索して見つけて対応していたので、自分用のメモとして残しておく。

# 削除方法

下記フォルダにある不要な`iOS xx.x.simruntime`ファイルを削除する。

```
$ open /Library/Developer/CoreSimulator/Profiles/Runtimes
```

削除後、下記コマンドを実行して、Xcodeで作成したシュミレーターから不要なシュミレーターを削除する。

```
$ xcrun simctl delete unavailable
```

例えば、上記フォルダから、`iOS 13.7.simruntime`を削除し、コマンドを実行すれば、Xcodeの`Devices and Simulators`で作成したシュミレーターから、`iOS 13.7`のシュミレーターが削除される。

自分用のメモだが、誰かの参考になれば。

# 参考

`xcode downloaded simulator remove`で検索して見つかった`stack overflow`を参考までに。

* https://stackoverflow.com/questions/30939453/how-to-uninstall-downloaded-xcode-simulator
【Flutter】Card Widgetまとめ

## Card Widgetを使う時ってどんなとき？
Card Widgetは影を設定できたり、constを修飾できるので、Containerでなくても良い時は積極的に利用していく。
### 本記事のCard Widgetまとめ
<img　align="center" width="250" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552610/fc11c518-9789-f4ed-1b51-df60f0021554.png">


### 基本的なプロパティ!

- margin ：外側の余白
- color ：背景色
- child ：子Widget
- elevation: 影の離れ具合
- shadowColor: 影の色
- shape: Widgetの形を調整

### シンプルなCard(Card01)
```dart
return const Card(
      child: Text(
        'Card01',
        style: TextStyle(fontSize: 50),
      ),
      color: Colors.red, // Card自体の色
      margin: EdgeInsets.all(30),
      elevation: 10, // 影の離れ具合
      shadowColor: Colors.red, // 影の色
    );
```
### 形をアレンジしたCard Widget(Card02)
- shape: Cardの形を変更
    - RoundedRectangleBorder : 枠線を調整

```dart
return const Card(
      child: Center(
        child: Text(
          'Card02',
          style: TextStyle(fontSize: 40),
        ),
      ),
      color: Colors.cyan, // Card自体の色
      margin: EdgeInsets.all(30),
      elevation: 10, // 影の離れ具合
      shadowColor: Colors.red, // 影の色
      shape: RoundedRectangleBorder( // 枠線を変更できる
        borderRadius: BorderRadius.only(
          topLeft:Radius.circular(60), // Card左上の角に丸み
          bottomRight: Radius.elliptical(40, 20), //Card左上の角の微調整
          // (x, y) -> (元の角から左にどれだけ離れているか, 元の角から上にどれだけ離れているか)
        ),
      ),
    );
```

### ListTileと併用でおしゃれに(Card03)
外枠はCardで、子WidgetにListTileを取り入れることで簡単におしゃれなWidgetが作れる
```dart
return Card(
      child: Column(
        children: const [
          ListTile(
            leading: Icon(Icons.add),
            title: Text('Card03'),
            subtitle: Text('Card SubTitle'),
          ),
          Text('hello'),
        ],
      ),
      color: Colors.green, // Card自体の色
      margin: const EdgeInsets.all(30),
      elevation: 8, // 影の離れ具合
      shadowColor: Colors.black ,// 影の色
      shape: RoundedRectangleBorder( // 枠線を変更できる
        borderRadius: BorderRadius.circular(10),
      ),
    );
```
### Tapした時の動作を追加(Card04)
- GestureDetector : 
    - onTap(): タップ時の動作を指定
```dart
return GestureDetector(
      child: SizedBox(
        width: 200,
        height: 100,
        child: Card(
          color: Colors.yellow,
          child:  Column(
            children: const [
              Text('Card04'),
              Text('please tap'),
            ],
          ),
          ),
      ),
      onTap: () => print('hello'),
    );
```


### Tapした時の動作を追加(Card04)
- InkWell : スプラッシュ描画してくれる(インクが広がっていく感じ)
    - splashColor:広がっていくインクの色

```dart
return Center(
      child: Card(
        color: Colors.white54,
        child: InkWell(
          splashColor: Colors.blue.withAlpha(30),
          onTap: () {
            debugPrint('Card taped');
          },
          child: SizedBox(
            width: 300,
            height: 100,
            child: Column(
              children: const [
                Text('Card05'),
                Text('please tap'),
                Text('animation'),
              ],
            ),
          ),
        ),
      ),
    );
```
オブザーバパターンでのイベント通知が受け取れない時にまず確認すること

# はじめに
NotificationCenterを使用したオブザーバパターンでのイベント通知を実装したのにオブザーバに設定したメソッドが呼ばれない！そんな時にまず確認したいことを記事にしました。
# 環境
・Swift 5.5.2
・Xcode 13.3.1
# やること
個人開発では全てのコードを自分が書いており、どこに何を書いてるかをある程度把握できていると思うのでこのようなことが起こる確率は低いと思いますが、チーム開発などでいろんな人がコードを書き込んでいるプロジェクトでは比較的起こりやすいのかな思いました。僕は起こりました。
##### 確認事項
・command + Fで検索ウインドウを開き`removeObserver`を検索してみる
`NotificationCenter.default.removeObserver(self)` <- 解除処理

数十分ほど悩んでいたところ、まさかなと思いながら検索するとそのまさかでした。
通知を登録した直後に登録を解除されておりメソッドが呼ばれないということが起きてました。
ちなみに、iOS 9.0・macOS 10.11以降では解除処理が必須ではなくなりました。
https://developer.apple.com/documentation/foundation/nsnotificationcenter/1415360-addobserver

もし同じ現象に陥った方は是非試してみてください。
JavaScriptの基礎

１、変数の記述。

変数colorの中にRedの文字を入れ出力する。
```
let color = 'Red';
console.log(color);
```
・letを記述する事でその後入力した文字を変数として認識される。
・console.log（変数名）;　で変数の値を出力させる。

・letの変わりにvarを記述し変数を認識させる事もできる。（今はあまり使わない）
```
var color = 'Red';
console.log(color);
```

２、定数の記述。

円周率を定数PIの中に入れ出力する。
```
const PI = 3.14;
console.log(PI);
```
・constを記述する事でその後入力した文字を定数として認識させる。

３、データ型の理解。
・動的型付け言語。
プログラムを書くときに変数や関数に何が入ってくるかというのが特に決まっていない形。
(例)PHP、JavaScript
・静的型付け言語。
変数や関数に型を予め定義しておき、その型以外のデータを変数では使えないと認識させる言語。
(例)C#、Java

```
let myName = 'sato'; → string型(文字列型)
let num = 123;       → number型(数値型)
```

４、基本的な演算子
```
let ans = 1 + 2;
console.log(ans); → ３

let x = 20;
let y = 10;
・足し算
let ans1 = x + y ;
console.log(ans1); → 30

・引き算
let ans2 = x - y;
console.log(ans2); →10

・かけ算
let ans3 = x * y;
console.log(ans3); →200

・割り算
let ans4 = x / y;
console.log(ans4); →2

let a = 3;
let b = 2;
・かけ算
let ans5 = a / b;
console.log(ans5); → 1.5(小数点まで出力させる)

・余り計算
let ans6 = a / b;
console.log(ans6); →1
```

５、演算子優先順位
```
let x = 1;
let y = 2;
let z = 3;
let ans1 = x + y * z;
console.log(ans1)　→7

let ans2 = (x + y) * z;
console.log(ans2)　→9

・優先順位
1 = ( )
2 = * /
3 = + -
```

６、文字列結合とテンプレートリテラル
```
let lastName = 'さとう';
let firstName = 'はやと';
let message1 = 'こんにちは' + lastName + ' ' + firstName + 'さん';
console.log (message1) →こんにちは　さとう　はやと　さん

・$をつける
let message2 = `こんにちは ${lastName} ${firstName} さん`;
console.log (message2)　→こんにちは　さとう　はやと　さん
```

７、複合代入演算子
```
let num = 20;
num = num + 10;
console.log(num) → 30

let num1 = 20;
num1 += 10;
console.log(num1) → 30

let num2 = 20;
num2 -= 10;
console.log(num2);　→10

let num3 = 20;
num3 *= 10;
console.log(num3); →200;

let num4 = 20;
num4 /= 10;
console.log(num4); →10;
```

８、型変換をする
```
let st = '1000';（文字列型）
let nu = 20;　　 （数値型）
console.log(st + nu);　→100020（文字列型）
console.log(nu + st);  →201000(文字列型)
```
(例)
文字列　＋　数値　＝　文字列
数値　＋　文字列　＝　文字列
文字列　＋　文字列　＝　文字列
数値　＋　数値　＝　数値

文字列を数値型に変換。
console.log(Number(st) + nu);　→100020

数値型を文字列型に変換。
console.log(string(nu) + '歳'); →20歳
今さら解説するSQL「トランザクション制御」

# トランザクションとは
一連のデータ操作をまとめた論理的な処理単位。
ざっくり言うとUPDATEとかINSERTした後に、コミット（※1）もしくはロールバック(※2)するまでの処理を1トランザクションと考える。

※1 コミット：全ての操作を確定させる。
※2 ロールバック：全ての操作を取り消す。

もしトランザクションの概念がない場合、以下のような事象が起こった場合にデータの不整合が発生する。

`例：AさんからBさんの口座へ５万円の振替処理を行う`
①Aさんの口座残高から5万円をマイナスする。
②Bさんの口座残高に5万円をプラスする予定だったが、障害により処理が失敗した。

①、②のそれぞれの処理を1つのトランザクションで管理していない場合はAさんの口座から5万円差し引かれた状態になるのでデータとして不整合が生じる。

しかし、１トランザクションとして管理していた場合、ロールバックすることで①の処理も取り消すことができるので、データの整合性を担保することができる。

# トランザクションの開始と終了
【開始】
サーバーに接続後、または直前のトランザクションが終了後、「最初のDML(※)文がじっこうされたとき」に自動的にトランザクションが開始される。
※DML：データ操作言語。SELECT、INSERT、UPDATE、DELETEなど。トランザクションは1つ、または複数のDML文で構成される。

【終了】
以下のイベントが発生した場合、終了する。
* COMMIT文、ROLLBACK文の実行時
* DDL、もしくはDCL文の実行時（自動コミット）
* ユーザーによってSQL実行ツールが正常終了した場合（自動コミット）
* ユーザーによってSQL実行ツールが異常終了した場合（自動ロールバック）
* マシン障害やシステムクラッシュが発生した場合（自動ロールバック）

# その他のトランザクション制御処理
トランザクション制御文にはCOMMIT、ROLLBACK以外に「SAVEPOINT」がある。
SAVEPOINT文を実行することにより、トランザクションを継続したまま指定したセーブポイントまでロールバックすることができる。

* SAVEPOINT セーブポイント名
⇨セーブポイントを作成する。トランザクションは継続したまま。
* ROLLBACK TO セーブポイント名
⇨指定したセーブポイントまでロールバックする。複数のセーブポイントを設定した場合、指定したセーブポイント以降のセーブポイントは自動的に破棄される。
UITextFieldのキーボードにUIDatePickerを設定する

# はじめに
プロフィールの誕生日欄(textField)を入力する際に、キーボードをUIDatePickerにしようと思ったので記事にしてみました。
# 環境
・Swift 5.5.2
・Xcode 13.3.1
# 使ってみる
再利用できるようにクラスにしてみました。
```DatePicker.swift
final class DatePicker {

    static let picker = UIDatePicker()
    static let formatter = DateFormatter()

    static func setup(_ vc: UIViewController, action: Selector, for textField: UITextField) {
        picker.datePickerMode = .date
        picker.preferredDatePickerStyle = .wheels
        picker.locale = Locale(identifier: "ja_JP")
        picker.addTarget(vc, action: action, for: .valueChanged)
        formatter.dateFormat  = "yyyy/MM/dd"
        textField.inputView = picker
    }
}
```
Controller側
```ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    DatePicker.setup(self, action: #selector(datePickerValueChanged), for: dateTextField)
}

@objc private func datePickerValueChanged(sender: UIDatePicker) {
     dateTextField.text = DatePicker.formatter.string(from: sender.date)
}
```
これでdatePickerの値を変更するたびにtextFieldのテキストも変更されていきます。
datePickerのスタイルや、フォーマット等はお好みで変更してください。
VSCode練習

## 基本操作
[VSCodeのマルチカーソル練習帳](https://qiita.com/TomK/items/3b1f5be07d708d7bd6c5)

## さらなる高みへ

### ケースの変換

CTRL + SHIFT + p (Mac: CMD + SHIFT + p)
-> transform と入力
-> uppercase, lowercase, snake case, TitleCaseを選択
[How to switch text case in visual studio code - StackOverFlow](https://stackoverflow.com/questions/30265978/how-to-switch-text-case-in-visual-studio-code)

### 数字操作
[Inori/vscode-InsertNumbers - GitHub](https://github.com/Inori/vscode-InsertNumbers/)

### 複数行について、一気に文字列の連結をしたい。
VSCodeではうまくできないのでSpreadSheet, Excelの文字列連結を利用すると早い。
Windows10 エクスプローラーの「OneDrive」を非表示にする方法

# 何のため？
Windows10のエクスプローラーでは，左側（ナビゲーションウィンドウ）に「OneDrive」や「Dropbox」などが勝手に作られてしまう．
組織のアカウントでは，ここが「OneDrive-(組織名)」の表記となり，原則この表示名は変えられない．
画面共有した際にうっかり所属がバレるのが怖い．

そこで，この勝手に作られる「OneDrive」や「Dropbox」などを**消す方法**，**名前だけ変える方法**を紹介する．

# 手順
**※レジストリを編集するのでバックアップ等自己責任でお願いします※**


1. レジストリエディタを起動

2. 以下のレジストリフォルダを開く
**HKEY_CLASSES_ROOT\CLSID**

3. 展開するとフォルダが大量に出てくるが，「編集」→「検索」で「System.IsPinnedToNameSpaceTree」を検索し，このキーがあるフォルダだけを見つけ出す．
右側の画面の「(既定)」のデータの部分に消したいものが出てくるまで次々と検索していく．
※「編集」→「次を検索 (F3)」で次々と検索することができて楽．
![20220423131952.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638738/73945b1c-69c4-8171-c5b2-9fcc9366cbba.png)

4.以下の操作を行う

（表示を消したい場合）
右側の画面で「**System.IsPinnedToNameSpaceTree**」を開き，「値のデータ」を「1」から「**0**」に変更する．

（表示名を変えたい場合）
右側の画面で「**(既定)**」を開き，「値のデータ」を好きな表示名に変更する．

![20220423132554.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638738/b18229c7-2644-6ba0-9f54-765e59fbe195.png)

5.レジストリエディタを閉じる



# 参考
https://answers.microsoft.com/ja-jp/windows/forum/all/windows10%e3%81%8b%e3%82%89/362b54e9-8aaf-48c2-b1e5-9b35098f7cdd
ブラウザゲームを作ってみよう(その7:当たり判定)

# はじめに
[その6](https://qiita.com/noji505/items/3679c0e86bb0e1b1d413)では画像表示を行いました。
今回は当たり判定を行いたいと思います。

# 当たり判定とは
二つのオブジェクトが重なっているか？をチェックして判定します。
言葉で説明しても分かりにくいと思うので、画像で説明します。

・当たり判定のイメージ
![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/ddf94fa9-d979-8404-6014-1870115fc085.png)
![img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/1aa1b3b5-87a6-751e-63fd-7318e929d14b.png)


1枚目はお互いが離れているので当たっていない状態で、2枚目は重なっているので当たっているということになります。
プログラムで判定すると以下のようになります。

```javascript
//-----------------------------------------------------------
// hitCheck : 当たり判定チェック
//     引数 : 物体1のX座標,物体1のY座標,物体1の横幅,物体1の縦幅
//     引数 : 物体2のX座標,物体2のY座標,物体2の横幅,物体2の縦幅
//   戻り値 : 当たっている・・true、当たっていない・・false
//-----------------------------------------------------------
function hitCheck( x, y, w, h, x2, y2, w2, h2 )
{
	if( x <= (x2 + w2) && x2 <= (x + w) && y <= (y2 + h2) && y2 <= (y + h) ){
		return true;
	}
	return false;
}
```


上記のプログラムをイメージで表すと以下のようになります。
![img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/5c46dd4f-bb70-3454-9e61-40c8ec9973e6.png)
# サンプル
当たり判定が確認出来るサンプルプログラムを作成しました。
青色の矩形が赤色の矩形に重なっている時に当たったと判定しています。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="PoEZYjd" data-user="noji505" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/noji505/pen/PoEZYjd">
  Qiita18_sample1(当たり判定)</a> by nojima (<a href="https://codepen.io/noji505">@noji505</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 最後に
当たり判定が出来たので、キャラが当たったら何かアクションさせるといったことが出来るようになりました。

今までから今回で
■タイマー処理
■文字表示
■キー入力
■図形表示
■画像表示
■当たり判定

上記が作れるようになったので、次はこれらを組み合わせて簡単なゲームを作ってみたいと思います。
Laravelのキャッシュクリアコマンド集

# キャッシュとは
アプリケーションのパフォーマンスを向上するために
使われる一時的にデータの保存をするやり方です。
データベースクエリの結果や計算結果など、よく使われるデータや処理の結果を一時的に保存しておき、次に同じデータや処理が必要になった時に高速にアクセスできるようにします。

# キャッシュクリアとは
Laravelでは再起動しても内キャッシュが残っててしまって、
更新したプログラムをうまく反映してくれない時があリます。

# artisanのキャッシュクリアコマンド

***アプリケーションのキャッシュのクリア***でよく使います。
```
$ php artisan cache:clear
```
***設定ファイル(config)のキャッシュクリア***
```
$ php artisan config:clear
```
***ルートのキャッシュをクリア***で***ルーティングの変更時***に使います。
```
$ php artisan route:clear
```
***viewのキャッシュをクリア***で
```
$ php artisan view:clear
```
***一括キャッシュ***
```
$ php artisan optimize:clear
```

***キーの作り直し***で.env ファイルにある
APP_KEY を作り直し、完全に前のキャッシュを無効にします。
```
$ php artisan key:generate
```
***オートローディングをしなおしキャッシュを作り直す***
```
$ php composer dump-autoload
$ php artisan clear-compiled
$ php artisan optimize
```
その後これもやるみたいです。

```
$ php artisan config:cache
```

# 参考資料

https://grune.co.jp/blog/laravel-cache-clear-command/

https://qiita.com/Ping/items/10ada8d069e13d729701

https://laraweb.net/environment/3224/
ディレクトリ内のディレクトリ数の上限【Google Compute Engine】

# TL;DR
10GBの場合、約57万個(575444)ディレクトリを作成できる。30GBならその3倍作成できる。
![Screenshot from 2022-04-20 07-13-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/88f839c2-5375-6b91-4fcb-fa894b90ca9d.png)
`us-west1`の`e2-micro`で試しました

### `/dev/sda1`の**IFree**で残りのディレクトリ数(**575308**)の上限を確認できる。

```bash
$ df -i
Filesystem     Inodes IUsed  IFree IUse% Mounted on
udev           123900   297 123603    1% /dev
tmpfs          126223   374 125849    1% /run
/dev/sda1      647168 71858 575310   12% /
tmpfs          126223     1 126222    1% /dev/shm
tmpfs          126223     3 126220    1% /run/lock
tmpfs          126223    17 126206    1% /sys/fs/cgroup
/dev/sda15          0     0      0     - /boot/efi
tmpfs          126223    10 126213    1% /run/user/1000
```

### 575444個目までは問題なくディレクトリを作成できる

2時間ほど実行にかかります

```bash
for i in `seq 575444`; do mkdir $i; done
```

### ファイル作成後

```bash
$ df -i
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
udev           123900    297 123603    1% /dev
tmpfs          126223    379 125844    1% /run
/dev/sda1      647168 647168      0  100% /
tmpfs          126223      1 126222    1% /dev/shm
tmpfs          126223      3 126220    1% /run/lock
tmpfs          126223     17 126206    1% /sys/fs/cgroup
/dev/sda15          0      0      0     - /boot/efi
tmpfs          126223     10 126213    1% /run/user/1000
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/00f166bf-c563-e891-30d8-abf4b24dc12d.png)


### 575445個目を作成しようとすると`No space left on device`になる

```bash
$ mkdir 575445
mkdir: cannot create directory ‘575445’: No space left on device
```
DWHを構成する大量のSQLからデータリネージを可視化するdatalineage-analyzer

# 概要
データウェアハウスにおいて、データを整備する際に「あるテーブル」から「他方のテーブル」へ投入するSQLを用意し、バッチで運用するケースはしばしば見られます。このような仕組みを開発していく中で、互いのテーブルの関係性を設計し、ドキュメントとして整理しながら取り組めれば良いのですが、どうしてもビジネスニーズが先行し、ドキュメントが追いつかないケースも多々あるでしょう。このような状態を続けていくと、ソースにしかデータフローの仕様がなく、毎度毎度grepしてSQLの山からフローを読み解いていくことになります。

このように既存の仕組みから「データの流れを知りたい、管理したい」というニーズは高まってきており、DMBOKをはじめとする「データマネジメント」と呼ばれる管理体系に基づいた運用が期待されるようになってきました。本稿では、その中でも「データリネージ」に着目し、大量のSQLを解析して、テーブルのIN(SOURCE)とOUT(TARGET)の関係性をシンプルに可視化する方法を解説します。

![スクリーンショット 2022-04-23 12.08.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121442/ca1b5b9d-cbdc-955f-5a9e-34a2e651a01f.png)

# 課題
何かOSSで良い物がないかと探してみると、[sqllineage](https://github.com/reata/sqllineage)という、SQL解析から可視化までオールインワンで対応しているツールが見つかりました。
早速試してみたところ、「階層関係が多すぎて可視化できない」問題にぶつかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121442/c7a15277-be75-d6b0-09cc-5036ef8805d0.png)
> ツールがハングして戻ってこないな...

その他にも、DBベンダー固有の処理で解析が止まったりと少しずつ課題が見えてきました。

* 全てを可視化しようとして破綻しているため、構造化と可視化のフェーズに分ける
* 確認したいテーブルを指定して、そこを起点に可視化する
* 可視化をシンプルにテキストベースで確認する
* DBベンダー固有処理をスキップできる汎用的な機能を用意する

上記の点を踏まえながら、sqllineageをベースに一つツールを開発してみることにしました。

# datalineage-analyzer
## 仕組み
このツールはSQLファイルを探索し、データリネージを解析して、その構造を表示します。
ツールのアーキテクチャは以下の通りです。

![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121442/ed52029e-76c6-edd6-8c85-8ade5fbc0d3c.png)

1. analyzerはSQLファイルを検索します。
2. SQLファイルのベンダー固有の処理を変換します。ReplaceHandlerと呼ばれる汎用的に変換する仕組みを有しています。
3. ツリー構造のデータ構造を生成し、ファイルに出力します（pickle形式）。
4. visualizerを使用してツリー構造をテキスト形式で出力します。

> データ（カラム）までは対応しておらず、一旦テーブルのみ対応しています

## 実行サンプル  

sampleディレクトリからSQLファイルを探索して、pklファイルを生成します
```
python analyzer.py -i sample
```
テーブルの流れを解析した木構造を持つdata_lineage.pklを生成します。

確認したい対象のテーブルを指定し、そのテーブルの先(OUT/TARGET)となったテーブルのリストをテキストベースで表示します。
```
python visualizer.py -k target -t persons
```

output:
```
persons
├── city_stat
└── members
    └── address_stat
```

確認したい対象のテーブルを指定し、そのテーブルの元(IN/SOURCE)となったテーブルのリストをテキストベースで表示します。
```
python visualizer.py -k source -t members
```

output:
```
members
├── address_of_member
└── persons
```

## ソース一式
ソースコードとサンプルの一式をgithubに上げているので、よろしければ参照されてください。
* [datalineage-analyzer
](https://github.com/tkeneix/datalineage-analyzer/tree/main)

## 今後の改善
コマンド＋テキスト＋ツリー形式、というかなり古典的な可視化方法でしたが、それなりの規模でも動作すると思われるので、課題感は達成できたと考えています。
有償ツールの導入は敷居が高いですし、無償ツールの活用でも予算を確保しての開発は難しいと思われたので、日曜大工の感覚で開発してみました。
今後は、より便利に使えるようにブラウザベースで出力できるようなUIを開発してみようかなと思っています。

こんな感じで可視化して、クリックしたら関連資料に飛ぶようにできたらなと。
![graph.pn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121442/78398ca3-bd30-1f6a-8b72-7526e10383ad.png)

Dashベースのテーブル検索＆表示サーバーを追加しました。
![dash_ui.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121442/76855b06-497e-c7dd-87b8-9cf2c72ae67d.png)
統計的推定と検定をPythonで解く「統計的仮説検定（1標本の平均の検定）」(2022.4.23)

# 背景
前回、谷合棋士の本を参考に統計的仮説検定を行いました。今回は、たまたま見つけたts0818さんのブログ（[ts0818(2020.4)、Pythonでt検定するには、Scipyを使うのが便利らしい](https://ts0818.hatenablog.com/entry/2021/04/30/204114)）を参考に記事にさせてもらっています。

前回の記事
[統計的仮説検定(2020.4.22)
](https://qiita.com/tan0ry0shiny/items/6a67783d01ffae079302)

# 目的
統計的仮説検定に慣れる事とPythonで解ける様になることを目的にしています。

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/063cc54f-0252-ccd4-544a-3d9e2fd8b480.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/c81f2285-19b4-3e48-fa77-e37c2d8b29a2.png)

# 解答
## どういう問題か（問題の分類）
今回は、母平均の検定です。確率分布としてはt分布を想定します。標本分布とt分布を比べる様なイメージをしています。求めたいのは母平均$\mu$が50.2かどうかです。
## どのように解けるか(Python)
まずはライブラリをインポートします
```Python
import numpy as np
import scipy as sp
import scipy.stats as stats
from matplotlib import pyplot as plt
```
データを読み込みます。
```Python
height = np.array([
    51.0, 45.9, 48.8, 54.0, 53.5,
    48.0, 44.5, 46.0, 50.3, 48.0
])
```
標本から検定統計量を算出します。これはt値を求める際、必要になります。
```Python
# 検定統計量
n = len(height)                            # サンプル数
k = n -1                                   # 自由度
u_var = np.var(height, ddof=1)             # 不偏分散
statistical_sample_mean = np.mean(height)  # 標本平均
```
さきほど求めた検定統計量からt値とp値を算出します。
```Python
# 仮説
statistical_population_mean = 50.2         # 母平均
 
t, p = stats.ttest_1samp(height, popmean=statistical_population_mean)
 
print(f"母平均が{statistical_population_mean}のt値：{t}")
print(f"母平均が{statistical_population_mean}である確率(p値)：{p}")
```
t値は-1.19、p値は0.27、
自由度9のt分布の両側5％点（棄却域）は2.26$\leq |t|$だから、帰無仮説を有意水準5％で棄却できません。最後に、図示します。

```Python
# グラフ描画
x = np.linspace(-4, 4, 200)
flg, ax = plt.subplots(1, 1)
 
# t分布を描画
ax.plot(x, stats.t.pdf(x, k), linestyle="-", label="k="+str(k))
 
# t分布に今回の確率分布を表示させる
ax.plot(t, p, "x", color="red", markersize=7, markeredgewidth=2, alpha=0.8, label="experiment")
 
# t分布の95%信頼区間から外れた領域を描画する
bottom, up = stats.t.interval(alpha=0.95, loc=0, scale=1, df=9)
plt.fill_between(x, stats.t.pdf(x, k), 0, where=(x>=up)|(x<=bottom), facecolor="black", alpha=0.1)
 
plt.xlim(-6, 6)
plt.ylim(0, 0.4)
 
plt.legend()
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/1f163447-9e09-c7ad-0a3c-a33de1895f6f.png)

# どのように解けるか（解法）
有意水準5%が基準になります。今回は両側検定なので、棄却域が半分ずつに分かれます。これはt分布表に従い、臨界値はPythonでは```scipy.stats.t.interval(0.95, df)```で求められます。今回は自由度dfが9です。臨界値は上側と下側が出ますが、それぞれ-2.26,2.26になります。

次にt値を求めます。```stats.ttest_1samp(height,popmean)```でt値とp値がそれぞれ算出されます。今回は-1.18でした。

さきほどの臨界値とｔ値を比べて、結論を出します。-2.26<t(-1.18)なので棄却できません。

# 参考
[ts0818のブログ](https://ts0818.hatenablog.com/entry/2021/04/30/204114)

# 感想
今回は1標本の平均の検定を行いました。今回は標本分布とt分布を比べているという認識です。仮説検定には母平均を使っています。まだまだ慣れないためか記事に書こうとすると全く進みません。今は質より量で雑な記事を量産して後で修正出来ればと思います。
CloudWatchアラームを自動有効化・無効化する方法

# はじめに
こんにちは、山田です。
今回はCloudWatchアラームを特定の時間、無効化する方法について記載していきます。

# 全体構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/401869b0-7010-e4b8-c7e4-9ffd7431e28b.png)
①：EventBridgeで、CloudWatchアラームを無効化する時間、CloudWAtchアラームを有効化する時間を設定します。
②：LambdaでCloudWatchアラームを無効化・有効化します。

# Lambda作成
CloudWacthアラームを有効化するコードは通りです。

```python:StartAction
import boto3

def lambda_handler(event, context):
    cloudwatch = boto3.client('cloudwatch')
    nt = ""
    while True:
        response = cloudwatch.describe_alarms(MaxRecords=100,NextToken=nt)
        alarms = response['MetricAlarms']
        for alarm in alarms:
            cloudwatch.enable_alarm_actions(
                AlarmNames=[alarm['AlarmName']],
            )
        try:
            nt = response['NextToken']
        except:
            print('error')
            break
```

CloudWacthアラームを無効化するコードは通りです。
```python:StopAction
import boto3

def lambda_handler(event, context):
    cloudwatch = boto3.client('cloudwatch')
    nt = ""
    while True:
        response = cloudwatch.describe_alarms(MaxRecords=100,NextToken=nt)
        alarms = response['MetricAlarms']
        for alarm in alarms:
            cloudwatch.disable_alarm_actions(
                AlarmNames=[alarm['AlarmName']],
            )
        try:
            nt = response['NextToken']
        except:
            print('error')
            break
```

# EventBridge作成
EventBridgeにて、スケジューリングを組みます。
今回は毎日8:00にCloudWAtchアラーム有効化、22:00に無効化するように設定します。

## CloudWatchアラーム有効化スケジューリング
cron式でCloudWAtchアラームを有効化する時間帯を指定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/9bce4a19-6431-b73e-1549-b809dfba9126.png)
ターゲットタイプにLambda関数を選択し、作成したStartActionを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/587f0105-3dbd-b500-91c1-1671f49437db.png)

## CloudWatchアラーム無効化スケジューリング
cron式でCloudWAtchアラームを無効化する時間帯を指定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/3e32a274-12ba-95d7-fab9-d40c7de86f25.png)
ターゲットタイプにLambda関数を選択し、作成したStopActionを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/760226f4-b76e-af7c-66b0-01d71c6b6ba5.png)

# 動作確認
指定した時間帯にCloudWatchアラームが有効化・無効化になっていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/53168f8a-2fe5-42e4-3dcc-00970b73d71b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/75bf0871-4e2d-b4ee-b775-db4c70835d41.png)
Flutter Webデバッグできない問題

最近パソコン買い替えたため、前のプロジェクトのソースをデバッグしたいとするところ、前は問題なかったげと、突然デバッグできなくて、何日間ハマってしまった。

# 現象
browser_client.dartの"completer.complete(StreamedResponse("とところ行ってしまい、breakpointsが効かなくなってしまった。
```dart
  unawaited(xhr.onLoad.first.then((_) {
      var body = (xhr.response as ByteBuffer).asUint8List();
      completer.complete(StreamedResponse(
          ByteStream.fromBytes(body), xhr.status!,
          contentLength: body.length,
          request: request,
          headers: xhr.responseHeaders,
          reasonPhrase: xhr.statusText));
    }));
```

# 原因
原因はパソコンを買い替えて、最新バージョンのChromeをインストールしてしまった、100.xバージョンだと、どうやらChromiumはデバッガプロトコルのCallFrame.urlフィールドを非推奨にしたようだ。
# 解決策
## Chromeをバージョンダウン
https://google-chrome.jp.uptodown.com/mac/versions

上記のURLにてChromeをバージョンダウンする、私の場合は99.0.4844.151にダウンしたら、解決できた。

## Flutterをバージョンアップ
Flutterをfvmを利用して、バージョンを2.10.5までバージョンアップしたら、問題解決できる

# 参考
https://github.com/flutter/flutter/issues/101224

https://github.com/flutter/flutter/issues/101139
markdownで書いたメモをMarpでスライドショー化する


読んだ論文の内容など、メモはメモアプリで録りたい。けどいろんな機会で報告するためにスライドショーに直すのが面倒くさい！！

というわけでMarpを導入してみた。
https://marp.app/

コマンドラインでも変換できるし、[vscodeの拡張機能](https://github.com/marp-team/marp-vscode)を使えば、プレビューしながら編集したり、クリック2回でpdfやpptxにexportしたりできる。

![スクリーンショット 2022-04-23 11.54.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83663/d4d95352-a726-948a-e3eb-a48d9e690d30.png)


## 見た目にちょっとだけこだわる

こだわりたいならいつも通りkeynoteを使って編集せよ、ということで、ここでは最低限整えることにする。

冒頭に、

```markdown
---
marp: true   # vscode上でスライドショーview
theme: gaia  # テーマ
$size: 9:16　　　　# スライドサイズ (3:4も可)
---
```

と記載。

色とフォントサイズの指示をcssで、ファイル末尾に追記。

```css
<style>
    :root {
    --color-background: #fff;
    --color-foreground: #333;
    --color-highlight : #f96;
    --color-dimmed    : #888;
    }

    h1 {
    font-size  : 1.2rem;
    text-align : center;
    }

    h2 {
    font-size  : 1.0rem;
    font-weight: bold;
    }
</style>
```
Github Actions で openvpn 接続

# ■openvpn接続

:::note info
・前提として、認証ファイルを配置
・ubuntuを利用しての実施
:::

```yaml
jobs:
  create:
    runs-on: ubuntu-latest

    steps:
      - name: test
        run: |
          FILE_OVPN=/tmp/test.ovpn
          # openvpnのインストール
          sudo apt-get -qq -y install openvpn
          sudo openvpn --config ${FILE_OVPN}
```

# ■ openvpnの実行ログでエラーが発生（route add）

:::note alert
接続先のVPNのIPアドレスとgithub actions 側で設定されている route が重複している可能性があります。
重複でエラーが発生した場合、削除する必要があります。
※ github actions 上で routeコマンド を実行して、設定を確認してください
:::

```diff_yaml
jobs:
  create:
    runs-on: ubuntu-latest

    steps:
      - name: test
        run: |
          FILE_OVPN=/tmp/test.ovpn
          # openvpnのインストール
          sudo apt-get -qq -y install openvpn

+          # 10.x.x.x で重複している場合は削除する
+          sudo route del -net 10.1.0.0 gw 0.0.0.0 netmask 255.255.0.0 dev eth0

          sudo openvpn --config ${FILE_OVPN}
```


# ■関連記事

https://qiita.com/error484/items/fb192f981776cfae9a92
【go】インストールしたライブラリで command not foundになるときの対処法

# 対処法
```
export PATH=$PATH:$HOME/go/bin
```
でパスを通す

# 問題
```
go get -u github.com/swaggo/swag/cmd/swag
```
をインストールして、
```
swag -v
```
をすると
```
command not found
```
エラーになる
1日１企業紹介　株式会社 PKSHA Technology

１日１企業を紹介していく。

やる気がある限りは続ける。

株式会社 PKSHA Technology

2012年創業

従業員数
（単独）	76人	従業員数（連結）	361人
平均年齢	34.2歳	平均年収	6,850千円

深層学習などＡＩアルゴリズムをＳａａＳで提供。駐車場管理システムなどＡＩ活用領域拡

主な事業はアルゴリズムライセンス事業

アルゴリズムライセンス事業。。。。

アルゴリズムライセンス事業？？？？

よくわからないので調査してみた。

最新テクノロジーを駆使したアルゴリズム・モジュールを開発し、それをライセンスすることで収益をゲットする構造

とのこと。しっくりこないがライセンスを取得して
パッケージの組み込みなどは共同でどこかしらとやっていそう。（あるいはライセンスだけ提供してるのかも）

・インベスターズクラウド
・NTTドコモ
・LINE

などが協業を開始している

2354社の導入企業数
研究開発したアルゴリズムを、多くの企業のソフトウエア・オペレーションに導入済み
との記載があることから上記の可能性が高そう

澪標アナリティクスも同じようなビジネススキームだったはず
このライセンス供与型は利益率が高いので例にもれず
この会社も利益率が高い。

以下利益率についての文章を引用
「2012年の創業から4年あまりで売上は4.6億円、経常利益1.6億円ほどに達しています。
経常利益率は34％」

最後に肝心のアルゴリズムについて調査
7つくらいあるのでわかりやすい奴だけ列挙

予測モジュール ＜Predictor＞

時系列情報に対して未来予測を行う。利用用途はECサイトのユーザーの購買予測や、金融機関での与信スコアの構築など。

対話モジュール ＜Dialogue_2＞

自然言語処理技術での対話・応答の制御を行う。チャットボットやロボットとの自動対話に使える。

アルゴリズムについては中身をがっつり見ないとふーんって感じ

また採用基準に以下のような項目があることからAI、機械学習におけるサイエンス力特化集団なことが想定される。
加えて会社の中にビジネス展開できるような人たちがるのだろうなと思った。

・関連分野での論文誌もしくは国際会議での発表経験
・関連分野での特許取得の経験・実績

HEROZやALBERTも良く名前を聞くので今後はその辺と合わせてこれらのAI事業を主として
やっている会社の関係性、立ち位置を整理したい。