OmniAICreator/Qiita-1.07M huggingface dataset:
scopeを使ったリファクタリング

リファクタリングって何がベストなのか？　どこから行っていこうか？
初学者からすると難しい。

まだ冗長な箇所や気付けていない箇所もありますが、今回`scope`を使ったので残しておこうと思います。

数年後の自分が見たら、「もっとよくできる箇所はあるだろ..」と言われそうですが。（いや..言える自分になりたい  ^^;）
そのために、コツコツと日々学んでいきます。


#### リファクタリング前：
【画像のメタデータから緯度経度を取得して10進数に変換しているコード】

```
img = Magick::ImageList.new(Rails.root.to_s + "/public#{@post.image.url}")

# 緯度取得
 exif_lat = img.get_exif_by_entry('GPSLatitude')[0][1].split(',').map(&:strip)
# 10進数に変換
 @latitude = (Rational(exif_lat[0]) + Rational(exif_lat[1])/60 + Rational(exif_lat[2])/3600).to_f

# 経度取得
 exif_lng = img.get_exif_by_entry('GPSLongitude')[0][1].split(',').map(&:strip)
# 10進数に変換
 @longitude = (Rational(exif_lng[0]) + Rational(exif_lng[1])/60 + Rational(exif_lng[2])/3600).to_f
```

...（恥）..めちゃくちゃ長ったらしくて読みたく無い程に見難い
showアクションと、confirmアクションに全く同じ記述があるので、更に格好悪い..


# どう切り分けるのか考える
・コントローラの役割とモデルの役割を意識
・10進数に変換する記述は供用する
・緯度経度の取得もscopeして、コントローラ側を短くする

こんな感じでやってみる


## 10進数への変換を共通化させる
`exif_lat`と`exif_lng`で分けてある箇所は引数で与えてやればいいので、`exif`とする
スコープの名前は`get_exif_gps`

```
app/controller/posts_controller:
  @latitude = Post.get_exif_gps(exif_lat)
  @longitude =  Post.get_exif_gps(exif_lng)
```

```
Postモデルに記述：
  scope :get_exif_gps, -> (exif){ (Rational(exif[0]) + Rational(exif[1])/60 + Rational(exif[2])/3600).to_f }
```

## 緯度の取得もscopeさせる
ローカル変数`img`を引数で渡す
スコープの名前は`get_exif_latitude`

```
app/controller/posts_controller:
  exif_lat = Post.get_exif_latitude(img)
```

```
Postモデルに記述：
  scope :get_exif_latitude, -> (img){ img.get_exif_by_entry('GPSLatitude')[0][1].split(',').map(&:strip) }
```

※経度の取得も同様に行う

スコープの名前は`get_exif_longitude`

```
app/controller/posts_controller:
  exif_lng = Post.get_exif_longitude(img)
```

```
Postモデルに記述：
  scope :get_exif_longitude, -> (img){ img.get_exif_by_entry('GPSLongitude')[0][1].split(',').map(&:strip) }
```


# リファクタリング後

```
app/controller/posts_controller:

  img = Magick::ImageList.new(Rails.root.to_s + "/public#{@post.image.url}")
  exif_lat = Post.get_exif_latitude(img)
  @latitude = Post.get_exif_gps(exif_lat)

  exif_lng = Post.get_exif_longitude(img)
  @longitude =  Post.get_exif_gps(exif_lng)

```

```
Postモデル：
  # 緯度の取得
  scope :get_exif_latitude, -> (img){ img.get_exif_by_entry('GPSLatitude')[0][1].split(',').map(&:strip) }

  # 経度の取得
  scope :get_exif_longitude, -> (img){ img.get_exif_by_entry('GPSLongitude')[0][1].split(',').map(&:strip) }

  # 10進数に変換
  scope :get_exif_gps, -> (exif){ (Rational(exif[0]) + Rational(exif[1])/60 + Rational(exif[2])/3600).to_f }
```


コントローラを見た時に多少は目で追いやすくなったかな？..

メソッドに切り出したりしたら、もう少し見やすくできそうな気もしますが、今回はここまでを`scope`の備忘録がてら残しておきます。
今後も更に勉強して吸収していきたいと思います！！

# 参考
https://pikawaka.com/rails/scope


# 最後に
もっとこうすれば良い！というアドバイスございましたら、是非ご指摘ください！ ^^
Kustomizeの依存関係を可視化するツールを作った

# はじめに
先日、こんな記事を書いたのですが、ツールの紹介もしておこうと思います。
[OSSに貢献したくてOSSを自作した](https://qiita.com/hourglasshoro/items/cd8cc1fc986c7dedfcaf)

# TL;DR
Graphmize : https://github.com/hourglasshoro/graphmize

* 探した所、Kustomizeの可視化ツールで人気なものはなさそうだったので作った（もしあったら教えてください）
* このツールのモチベーションはKustomizeのファイル同士の依存関係を木構造で見れたらいいなという所にあります。特に、base, overlaysのようなディレクトリ構成で複雑になってしまった時などに使えると思います。
* 例えばターミナルで実行すると以下のような出力になります。実際のディレクトリ構造は[こちら](https://github.com/hourglasshoro/graphmize/tree/master/docs/example)

```
/
├── overlays/production
│   └── base
│       └── base/a_service
│           ├── deployment.yaml
│           └── service.yaml
└── overlays/staging
    └── base
        └── base/a_service
            ├── deployment.yaml
            └── service.yaml

```

* インストールはgo modulesかhomebrewでできます。

```sh
# homebrew
brew tap hourglasshoro/homebrew-graphmize
brew install graphmize

# go
go get github.com/hourglasshoro/graphmize
```

# 実装について
## 現在
現在のv0.1.1ではresourcesのみ表示することができます。patchなどに関しては今後の機能追加で実装するつもりです。

## 参考にしたもの
https://github.com/jpreese/kustomize-graph
こちらを参考にkustomizeファイルを読み込む部分を作りました。このライブラリは実行するディレクトリにあるkustomization.yamlからしか読み込めません。それだと使いにくいので、ルートディレクトリを指定したら探索して全ての依存関係のツリーを作るよう拡張をしました。

https://github.com/hourglasshoro/graphmize/blob/master/pkg/graph/graph.go#L111
具体的には実装のこのあたりになります。また、すでに出てきた子のツリーに関してはメモリ上に保存し探索効率をあげています。


## 使ったライブラリ
### spf13/cobra
https://github.com/spf13/cobra
もともとCLIツールを作ったことがなかったのですが、おなじみ(?)のcobraのテンプレートを使い簡単に作ることができました

### spf13/afero
https://github.com/spf13/afero
同じ作者のaferoも優秀で、ファイルシステムの抽象化ライブラリです。以下の記事にも書いてありますがos パッケージのファイル系関数や io/ioutil の代わりに使うもので、テスト時にOSのファイルシステムではなくモックのファイルシステムを使うことのできるものです。
https://qiita.com/izumin5210/items/7604f290785bc3f8f86a#afero---spf13afero

たとえば以下のようなディレクトリ構成にしたい場合

```
   /app
   ├── kustomization.yaml
   └── sub
	   ├── kustomization.yaml
	   ├── a.yaml
	   └── b.yaml
```

以下のようにします。

```go
func TestExampleFiles(t *testing.T) {
	fakeFileSystem := afero.NewMemMapFs()
	fakeFileSystem.Mkdir("app", 0755)
	fakeFileSystem.Mkdir("app/sub", 0755)

	fileContents := `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- sub
`
	afero.WriteFile(fakeFileSystem, "app/kustomization.yaml", []byte(fileContents), 0644)

	fileContents = `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- a.yaml
- b.yaml
`
	afero.WriteFile(fakeFileSystem, "app/sub/kustomization.yaml", []byte(fileContents), 0644)

	fileContents = `
apiVersion: apps/v1
kind: Deployment
`
	afero.WriteFile(fakeFileSystem, "app/sub/a.yaml", []byte(fileContents), 0644)
	afero.WriteFile(fakeFileSystem, "app/sub/b.yaml", []byte(fileContents), 0644)
}
```

# まとめ
Graphmizeという自作ツールの紹介でした。もし使えそうであれば活用していただけると幸いです。contributeも歓迎していますので、よろしくお願いします！
AWS Device FarmのホストマシンにAndroid SDKをインストールする

AWS Device FarmのホストマシンでAndroid SDKを利用する方法をメモする。

なお通常Device Farmのホストマシンでは、ビルド済みのapkを端末へインストールする程度のことしか行わないので、基本的にAndroid SDKは必要ない。( `adb` などの platform-tools はプリインストールされているので)

とはいえ、あると便利な場合もまれにある(ホストマシン上でapkのビルドをしたいなど)ので、ここで方法をまとめる。

# はじめに
AWS Device Farmのテスト実行環境は、

* モバイル端末(クライアント)
* そのクライアントと接続されたLinuxサーバー(ホスト)

から構成されている。

今回は、上記のホストマシンにAndroid SDKをインストールする方法をまとめる。

# 方法
Device Farmのカスタムテスト環境の機能を用いる。
適当なスタンダードテスト環境に対して、カスタマイズした `test_spec.yml` をアップロードすれば良い。

```yml:test_spec.yml
phases:
  install:
    commands:
      - mkdir ~/android_sdk
      - cd ~/android_sdk
      # download and install commandline tools
      - curl https://dl.google.com/android/repository/commandlinetools-linux-6858069_latest.zip -o sdk.zip
      - unzip sdk.zip
      # set environment variables for android sdk
      - export ANDROID_HOME_OLD=$ANDROID_HOME
      - export ANDROID_HOME=$HOME/android_sdk
      - export ANDROID_SDK_ROOT=$HOME/android_sdk
      # install android sdk
      - yes | $ANDROID_HOME/cmdline-tools/bin/sdkmanager "build-tools;28.0.3" "platforms;android-29" --sdk_root=$ANDROID_HOME
      # use existing platform-tools (which is a specific build for AWS device farm)
      - rm -rf $ANDROID_HOME/platform-tools
      - ln -s $ANDROID_HOME_OLD/platform-tools $ANDROID_HOME
      - export PATH="$PATH":"$ANDROID_HOME/platfom-tools"
      # return to the previous directory
      - cd -
```


ポイントは下記3点:

### 1. commandline toolsを利用した最小限のインストール
Android Studioをインストールすると必要なものが全部入る認識だが、サイズが大きく不要なものも多いので、今回は利用しない。
`sdkmanager` を利用すると、必要なものだけをインストールできる。[参照](https://developer.android.com/studio/command-line/sdkmanager)

また、Command line toolsのURLは[こちらから](https://developer.android.com/studio#command-tools)入手できる。

### 2. platform-tools は既存の物を使う

新規にインストールされるplatform-toolsを利用すると、端末との通信ができなくなるなどの不具合があった。
もともとインストールされているplatform-toolsは、AWS Device Farm用にカスタマイズされたものらしい。
このため、新しい`$ANDROID_HOME`下にシンボリックリンクを張って、既存のplatform-toolsが参照されるようにする。

### 3. `test_spec.yml` のアップロード方法
文法はこちらを参照: [Working with Custom Test Environments in AWS Device Farm
](https://docs.aws.amazon.com/devicefarm/latest/developerguide/custom-test-environments.html)

アップロードする際は、既存のスタンダードテスト環境をベースに、カスタムされたtest_spec.ymlをアップロードする形になる。

Appium等を用いる場合は、素直に対応する環境を選べば良い。
一方で、Flutter driveを用いる場合は、そもそも対応するスタンダード環境が存在しない。

この場合は、適当な環境(e.g. `APPIUM_PYTHON`)を選んだ上で、テストパッケージもアップロードし、その上で test_spec.yml をアップロードする。
次のStackoverflowに方法がまとめられている: [Running Flutter Integration Tests in AWS Device Farm, Saucelabs, Firebase Test Lab etc](https://stackoverflow.com/a/53328272)

以上です。
パスワード変更ロジック

中にあるconsole.logはjsでは出力することが出来ない
reactになれがリアルタイムで反映することできる、、、はず...?


```js

const Form = document.getElementsByTagName("form");
let PasswordValue = "aaaaa";
const nowPassword = document.getElementById("now_password");
nowPassword.textContent = "現在のパスワードは"+ PasswordValue;


function setPassword() {
    const confirmPassword = document.getElementById("confirm_password").value
    const newPassword = document.getElementById("new_password").value
    console.log(confirmPassword)
    console.log(newPassword)
    alert(PasswordValue)
    if (PasswordValue===confirmPassword) {
        if (PasswordValue != newPassword) {
            let PasswordValue = newPassword;
            alert(PasswordValue)
        }
    }
}
```
ビンゴシートを作成

マスは二次元配列で作成(過去のオセロゲームを参考)
真ん中はfree
ページ更新するたびに中身を更新
bの列には1~15
iの列には16~31
nの列には31~45
gの列には46~60
oの列には61~75
を入れるようにする

```js

const sheet =document.getElementById("field")

function newSheet() {
    for (var x = 0; x < 6; x++){
        const tr = document.createElement("tr")
        sheet.appendChild(tr)

        for (var y = 0; y < 5; y++){
            var td = document.createElement("td");
            if (x === 0) {
                switch (y){
                case 0:
                    td.textContent ="B"
                    break;
                case 1:
                    td.textContent = "I"
                    break;
                case 2:
                    td.textContent = "N"
                    break;
                case 3:
                    td.textContent = "G"
                    break;
                case 4:
                    td.textContent = "O"
                    break;
                }
            } else {
                switch (y){
                    case 0:
                        td.textContent = (Math.floor(Math.random() * 15 + 1))
                        break;
                    case 1:
                        td.textContent = (Math.floor(Math.random() * 15 + 16))
                        break;
                    case 2:
                        td.textContent = (Math.floor(Math.random() * 15 + 31))
                        if (x === 3) {
                            td.textContent = "free"
                        }
                        break;
                    case 3:
                        td.textContent = (Math.floor(Math.random() * 15 + 46))
                        break;
                    case 4:
                        td.textContent = (Math.floor(Math.random() * 15 + 61))
                        break;
                    }
            }
               tr.appendChild(td)
        }
    }
    
}

newSheet()
```
PHPの基礎文法まとめ1~コードの埋め込み、ターミナル出力、変数宣言~

Rubyはある程度学んだところで、他言語として企業で使用頻度の高いPHPの学習をしております。
PHPの基礎文法で学んだことをメモのようにまとめていきます。


```php:基本的なPHPコードの埋め込み
<?php
  // ここにPHPコードを記載
?>
```

上記のように書けば、タグの外にHTMLのコードも書ける。処理の途中でPHPコードに入ったり抜けたり出来る。
ちなみにPHPコードだけやPHPコードが最後の場合は、閉じタグ ?> は省く。
　

```php:文字列の表示にはechoを使う。

<?php
echo 'こんにちは！' . PHP_EOL;
```
```:ターミナル出力
~ $ php main.php
こんにちは！
~ $
```
- .(ピリオド)は文字列に繋げる役割。
- PHP_EOVは文字列の改行を行う。（あくまでターミナル上で。ブラウザで改行処理される訳ではない点に注意）
- ;(セミコロン)は命令の区切りにつける。これを忘れるとエラーが起こる。

　

```php:変数宣言には$を頭に付ける
<?php
  $name = 'mizuno';
```
変数の命名規則は文字か _ (アンダースコア)が使える。数字や - (ハイフン)は使えない。

```:例
$name // OK
$_name // OK
$2020 // NG
$日本語も変数名にできる // OK
$first-name // NG
```

参照元：<a href="https://dotinstall.com/lessons/basic_php_grammer">ドットインストール(PHP基礎文法編)</a>
無限再起動ループの闇に堕ちたCentOS8君をシングルユーザーモードで復旧

#何をやっちゃったのか
1. 毎日夜中にCentOS再起動させよう！
2. 定期実行は『自作systemdを作る』でやろうじゃん！

* 再起動のシェルスクリプトファイル作成ヨシ！
* シェルスクリプトファイルに実行権限与えるヨシ！
* 再起動用systemd（サービス）作成と有効化ヨシ！
* 上記をキックするTimer作成と有効化と実行ヨシ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/2f752f90-206c-65a6-403e-1d8d54eaee0d.png)

#よくねーよ！！
↓これがダメだった。
**再起動用systemd（サービス）作成と有効化ヨシ！**

下記のようなことに…

再起動
↓
再起動用systemd（サービス）が実行されちゃう
↓
再起動
↓
再起動用systemd（サービス）が実行されちゃう
↓
……再起動の無限ループとなってしまった…(´・ω・`)

**起動と同時に有効化されたサービスが走り始める** が頭から抜けてましたです。

#じゃあどうするのか
Linuxには **シングルユーザーモード** というものがあります。
最小限の構成で起動してくれるので、今回のような(ﾉ∀`)ｱﾁｬｰな時のリカバリーができます。

**BIOS** や **Windowsのセーフモード** に似たような機能って感じです。

ただし、シングルユーザーモードはネットワーク越しにはできないです。
マシンの前まで自分の足でテクテク歩いていって直接操作しないとです…。

#シングルユーザーモード起動方法
まず下記のような画面になったら ```e``` を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/70fb20c9-3da3-93b4-4eb9-54081b181a10.png)
すると、こんな画面になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a7de3d11-6a67-9b13-f260-688d2a579561.png)
```rhgb quiet``` の後に ```rd.break``` を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/460bdbf4-bd55-7ba5-f451-5241f1596ad8.png)
そしたら、 Ctl + x でシングルユーザーモード起動できる！

#ファイルを操作できるようにsysrootを再マウント
今回の目的は **間違ったシェルスクリプトファイルの修正** なので、ファイルを操作できる状態にまで持っていく必要あり。
そこでsysrootを再マウントします。

下記コマンド。

```sh:
mount -o remount,rw /sysroot
chroot /sysroot
```

下記は再マウントして ```ls -l``` までやってみた状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6669b0a4-c4dc-ab50-b134-0022af6e3ea6.png)
ここまでくれば **CentOS8を起動して端末を開いた** のとほぼ同じ状態なので、viとかでファイルを修正できますです。

ファイルの修正が済んだのち、2回 ```exit``` したところCentOS8君が無事起動してくれました。
（再マウントしたsysrootからのexitと、シングルユーザーモードからのexitの2回）

#蛇足
今回はおうちの物理サーバーだったから何とかできたけど、AWSで同じようなこと起きたらどう対処するんだろうか？

クラウドに移行する時はシングルユーザーモード的なリカバリ方法できるのかどうか確認しておこうっと…。

#参考サイトさん
https://rin-ka.net/centos-7-8-single-mode-how-to/

#バージョン
CentOS Linux release 8.3.2011
ERROR 2003 (HY000): Can't connect to MySQL server on

# 事象 : RDSのMySQLに接続しようとしたらできなかった
- 環境
    - Windows10 Pro バージョン1909
    - GitBash ※. GitBashを使用しているので`mysql`コマンドの前に`winpty`をつけている

```bash
$ winpty mysql -h db-shikibetushi.abcdefg.region.rds.amazonaws.com -P 3306 -u username -p
Enter password: ************
ERROR 2003 (HY000): Can't connect to MySQL server on 'db-shikibetushi.abcdefg.region.rds.amazonaws.com' (10060)
```

## 原因 : セキュリティグループのインバウンドルールにIPアドレスがないから
> うまく接続できない場合は、RDSの[パブリックアクセシビリティ]またはセキュリティグループの設定が誤っています。
> [RDSでMySQLを作ってみる - ponsuke_tarou’s blog](https://ponsuke-tarou.hatenablog.com/entry/2020/02/19/204649#MySQL%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%97%E3%81%BE%E3%81%99)

同じことに何度も引っかかる自分が憎い・・・

1. AWSコンソール > [RDS] > [データベース] > 対象のDB識別子リンクで詳細画面表示
1. [接続とセキュリティ]タブ > [VPC セキュリティグループ]のリンクで[セキュリティグループ]画面表示 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/1db02a3b-1136-19f8-fc74-36c62be28f0f.png)
1. 対象のセキュリティグループリンクで詳細画面表示 [インバウンドルール]タブ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/da555dae-c5ea-7bde-5d2f-1884d66dcb8e.png)
1. ここに自分が使っているパブリックIPアドレスがないと接続できない

### 対応 : インバウンドルールにIPアドレスを設定する
1. [インバウンドルール編集]ボタンでダイアログを表示
1. [ルールの追加]ボタンで行を追加して以下を設定
    - タイプ : MySQL/Aurora
    - プロトコル : TCP
    - ポート範囲 : 3306(MySQLのポート)
    - ソース : カスタム / 「{自分のパブリックIPアドレス}/32」
        - 自分のパブリックIPアドレス > [アクセス情報【使用中のIPアドレス確認】](https://www.cman.jp/network/support/go_access.cgi)
    - 説明 : 後でなんのIPアドレスかわかるような説明
1. [ルールを保存]ボタンで保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/7514ff6e-45aa-a44e-00f8-f27f5e051705.png)

```bash:再び接続してみるとつながった
$ winpty mysql -h db-shikibetushi.abcdefg.region.rds.amazonaws.com -P 3306 -u username -p
Enter password: ************
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 458689
Server version: 5.6.40-log Source distribution

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```
バージョンのステータス

バージョンのプロパティ「ステータス」を「終了」にすると、チケットの「対象バージョン」リストボックスから非表示になり、選択する事が出来なくなります。
使用しないアイテムが選択肢に含まれると効率が落ちるので、対象の全作業が完了した時点で、バージョンのステータスを終了にした方が良いです。
ステータスの更新は、「プロジェクト > 設定 > バージョン」画面で可能です。
DX推進企業におけるITマネージャーに求められる役割とは？

#はじめに
企業がDX(デジタル・トランスフォーメーション)を導入するにあたり、IT業界もそれに伴い変化を余儀なくされています。新しい技術やそれらの導入による潜在的な効果への期待は高く、企業はそのペースを維持するために競い合っています。このような急速な変化への欲求に伴い、ITマネージャーは、企業のDXの戦略的な取り組みの一環としてデジタルビジネスのツール、プロセス、モデルを採用しなければという強いプレッシャーに直面しています。これを効果的に実行するために、多くの企業は、ビジネス側の要求に対応し、それに応えるために、社内のITオペレーションを再構築しなければなりませんでした。

日本でもDXに関連するプロジェクトやテクノロジーへの投資は増加しています。こうした状況下でIT部門の役割はイノベーションに向けてより積極的にならざるを得ませんが、変革をリードするためにはどのように取り組んでいけばよいのでしょうか。この記事では、DXを成功させるために、ITマネージャーが注力できる以下の施策について解説します。

#新しいテクノロジーの早期導入
新しいテクノロジーを早期に導入することはリスクのように感じるかもしれませんが、こうした新しいテクノロジーが企業の戦略的な取り組みや目標に合致している場合は、IT部門が先頭に立って変化を訴えていくべきです。

アーリーアダプターは、テクノロジーの開発にも影響を与えることができます。技術開発者と緊密な関係を築くことで、IT 部門は貴重なフィードバックを提供して製品の方向性に影響を与えることができ、その技術が対処すべき問題や解決しうる問題をよりよく理解することができます。

早期導入を推進することは、大きな競争上の優位性にもつながります。業界の他の企業が導入に奔走している間に、IT 部門は製品の初期の問題を解決することができます。ハーバード・ビジネス・レビューの調査によると、アーリーアダプターは「先手必勝の優位性」を経験し、収益成長と市場での地位の両方でリードする可能性が高いことがわかりました。

#デジタルリーダーシップ 
経営陣は、デジタルリーダーシップを育成するための明確な戦略を必要としています。変革的なテクノロジーの導入を成功させるためには、企業が社内のリーダーを特定することが決定的に重要となります。IT部門でそのようなリーダーを育成することで、進歩を加速させることができるでしょう。

IT部門は、新しいテクノロジーの社内チャンピオンとしての役割を果たし、社内部門がDXの準備を行うのを助けることができます。IT部門のリーダーは、部門横断的な取り組みを促進するためのトレーナーやファシリテーターとしての役割を果たし、変化という概念を受け入れるために模範を示してリードすることになります。

スキルを更新し、変化とリスクをより許容する文化を作ることによって、その組織はDXを成功に導くためのデジタルケイパビリティが向上します。ITリーダーは、データマネジメント、分析、顧客中心主義のスキルの構築に重点を置くべきです。

テクノロジーが現在および将来のビジネスニーズを確実に実現するために、企業の経営陣は、ITをビジネスワークフローと戦略的計画の中核的な構成要素とするように努力すべきです。特にITマネージャーは、DXの一環として、この成果を促進する上で中心的な役割を担っています。

#迅速なデリバリーとデプロイメント
デジタル技術は急速に進歩しています。これらのプロジェクトの中には、最短で数週間でデリバリーされるものもあり、ITチームはよりアジャイルなアプローチを必要としています。組織内での進捗基準を確立するために、ITチームは、迅速な開発とプロジェクトの進捗を実現するモデルに移行しなければなりません。

成功のための最初の一歩は、アプローチを定義して最初から障害物を特定し、課題に優先順位をつけるための明確なコミュニケーションのためのプロセスを確立することから始まります。また、不確実性や要求の変化に対応するアジャイル開発手法を取り入れることで、ITチームのスケジュールを遅延なく進めることができます。

IT部門が戦略的価値を維持するためには、技術力にだけ頼っていては、もはや十分ではありません。IT部門は、競争の混乱や急速に進化する社内外の期待に対応できるよう、企業内で俊敏かつ機敏に役割を果たさなければなりません。

#部門を超えた緊密な連携の必要性
IT部門はテクノロジーの進歩を実現するために苦労するかもしれませんが、真のDXとは、単に新しいシステムを導入するだけではありません。それには部門間の垣根を超えて仕事をする従来とは別の方法が必要であり、他の部門のITに対する認識を見直す機会が必要です。

プロジェクトによっては、IT部門がプロジェクトの方向性を決定するインフルエンサーとしての役割を果たす必要がある場合もあれば、技術的な専門知識を共有するオブザーバー的立場としての役割を果たす必要がある場合もありますが、真の意味でのプロジェクトのリーダーシップは他の部門に委ねられることになります。他のチームから得たデータやインサイトを活用することで、企業は最終的に競争力を獲得することができます。

このデジタル時代には、チーム間のコラボレーションはすべての部門にとって不可欠なツールになりつつあります。ITチームのリソースへの要求が高まる中、他部門とのコラボレーションによってプロジェクトチームの規模を拡大したり縮小したりすることができれば、より機動的なアプローチが可能になります。企業内のリーダーとして、ITマネージャーは、特にDXプログラムの追求において、このコラボレーションを促進するために積極的な役割を果たす必要があります。

#人材への投資
デジタル技術への取り組みを加速させるためには、適切なITチームを構築することも重要です。データ管理、フロントエンドとバックエンドの開発、クラウドの専門家やシステムインテグレーターなど、特定の専門知識やスキルをもつリソースの力を借りることが、変革を加速させる上で必要になります。

デジタル・ディスラプション（デジタルテクノロジーによる破壊的イノベーション）が当たり前となった時代においては、最新のトレンドに関する知識とアナリティクスのスキルを持った従業員は、ビジネスにもたらす価値が大きいため、人材市場において非常に需要があります。健全な戦略とプランニングのスキルセットを持つ専門家のチームは、テクノロジーの最適な活用を促進し、他の部門間のコミュニケーションギャップを埋めるのにも役立ちます。

変革は内部から始まるものであり、全社的な連携を改善してデジタルツールの力を発揮することに重点を置いた企業は、DXの最前列に立つことになるでしょう。IT部門の人々がビジネス価値とDXの成功を推進する立場になりますが、これは、IT部門の人々が進歩を可能にする技術とプロセスへのアプローチにおいて先見性を持っているかどうかにかかっていると言えるでしょう。

#最後に
もし、自社のDXを推進していく上で、自社のデータ基盤の再構築を検討されているのであれば、ぜひ、**[Xplentyのブログページ](https://www.xplenty.com/jp/blog/)**もチェックしてみてください。
ゲーミングtoio - toio SDK for UnityでLEDを操る

# 概要
toio SDK for UnityでLEDを操ります。フルカラーLEDといえばレインボー（ゲーミングPC風） :rainbow: 

## GitHub repository
https://github.com/zurachu/toio-rainbow-led/

## WebGL sample
toioキューブが必要です。
https://zurachu.github.io/toio-rainbow-led/

## 動画（Twitter）
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ゲーミング <a href="https://twitter.com/hashtag/toio?src=hash&amp;ref_src=twsrc%5Etfw">#toio</a> <a href="https://t.co/SY7y8FkjLZ">pic.twitter.com/SY7y8FkjLZ</a></p>&mdash; ヅラChu (@zurachu) <a href="https://twitter.com/zurachu/status/1348956873773338626?ref_src=twsrc%5Etfw">January 12, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 技術情報
## UnityEngine.Colorをtoioランプ制御で使うカラー値に変換するUtility
[前回のかるた](https://qiita.com/zurachu/items/24b1d141c631cba2dd59)でもそうでしたが、キューブの接続順（どのキューブがプレイヤー1か？2か？）を認識するために画面表示とLEDの色を合わせるのは、良くある手な気がします。

```ToioLedUtility.cs
using UnityEngine;
using toio;

public static class ToioLedUtility
{
    public static void TurnLedOn(Cube cube, Color color, int durationMs, Cube.ORDER_TYPE order = Cube.ORDER_TYPE.Strong)
    {
        cube.TurnLedOn(ColorByteValue(color.r), ColorByteValue(color.g), ColorByteValue(color.b), durationMs, order);
    }

    public static Cube.LightOperation LightOperationOf(Color color, int durationMs)
    {
        return new Cube.LightOperation(durationMs, ColorByteValue(color.r), ColorByteValue(color.g), ColorByteValue(color.b));
    }

    public static byte ColorByteValue(float value)
    {
        return (byte)Mathf.Clamp(value * 255, 0, 255);
    }
}
```

## レインボーグラデーション
`#ff0000`→`#ffff00`→`#00ff00`→`#00ffff`→`#0000ff`→`#ff00ff`→`#ff0000`のグラデーションするUnityEngine.Color配列を作ってから、先ほどのCube.LightOperationに変換して、キューブに送信します。
Cube.TurnOnLightWithScenarioに一度に送れるLightOperationの上限が29
https://toio.github.io/toio-spec/docs/ble_light#operation-%E3%81%AE%E6%95%B0
なので、4<(29÷6)<5より、1色のグラデーションを4段階かけて行います。

```SampleScene.cs
    public async void OnClickConnect()
    {
        var cube = await cubeManager.SingleConnect();
        if (cube == null)
        {
            return;
        }

        var colors = new List<Color>();
        colors.AddRange(Gradation(Color.red, Color.yellow, 4));
        colors.AddRange(Gradation(Color.yellow, Color.green, 4));
        colors.AddRange(Gradation(Color.green, Color.cyan, 4));
        colors.AddRange(Gradation(Color.cyan, Color.blue, 4));
        colors.AddRange(Gradation(Color.blue, Color.magenta, 4));
        colors.AddRange(Gradation(Color.magenta, Color.red, 4));

        cube.TurnOnLightWithScenario(0, colors.ConvertAll(_color => ToioLedUtility.LightOperationOf(_color, 100)).ToArray());
    }

    private List<Color> Gradation(Color fromColor, Color toColor, int division)
    {
        var colors = new List<Color>();
        for (var i = 0; i < division; i++)
        {
            colors.Add(Color.Lerp(fromColor, toColor, (float)i / division));
        }

        return colors;
    }
```
Djangoのrequest.POST['hoge']とrequest.POST.get('hoge')の違い

request.POST['hoge']とrequest.POST.get('hoge')の違いは何か？
今まで何も考えずにrequest.POST['hoge']を使っていましたが（ゴメンナサイ）、どのように使い分ければいいのだろうかと疑問に思ったので調べてみました。

#フォームに入力された値は辞書で返される
フォームに入力された値は辞書で返されます。
`request.POST['hoge']`は、`辞書['key']` で辞書の値を取り出しているのと同じ。
`request.POST.get('hoge')`は、`辞書.get('key')`で辞書の値を取り出しているのと同じです。

#辞書['key']と辞書.get('key')の違い
`辞書['key']`では、存在しないキーを指定したときに`KeyError`が発生します。
`辞書.get('key')`では、存在しないキーを指定したときは`None`が返されます。
`辞書.get('key', 'default')`のように第二引数を設定すると、キーが存在しなかったときに、設定した値をデフォルト値として返してくれます。このため、キーが存在しなくてもエラーが発生しません。

#どう使い分けるか
エラーを発生させたいときは`request.POST['hoge']`、エラーを発生させたくない時は`request.POST.get('hoge')`を使えばいい、ということですね。
これからはちゃんと区別して使います…(' ▽ ')ゞ

#参考
[Pythonの辞書型をマスターしよう！基本的な使い方から応用まで網羅](https://www.tech-teacher.jp/blog/python-dictionary/)
ハッシュ

#ハッシュとは
データとそれに対応する名前をつけて複数の値を管理するものです。
データの部分を「バリュー」、名前の部分を「キー」とよびます。

このようなキーとバリューで管理する考え方を「キーバリューストア」と呼びます。

#####ハッシュは { } (波括弧)を使って生成します。

ハッシュロケット => を用いてキーとバリューをセットにして書きます。
変数 = { キー1 => バリュー1, キー2 => バリュー2, キー3 => バリュー3 }

ハッシュの書き方には複数あり、シンボルという物を使って書かれる書き方もあります。

シンボルは、見た目は文字列のようですが、実際の中身は数値になっています。

シンボルの宣言は、文字列の先頭にコロン:をつけます。
同じ文字列であれば、文字列にクォーテーションをつけてもつけなくても中身は同じ値になります。

```
:"Hello"

:Hello

#どちらも同じ値
```


コンピューターは、文字列を扱うよりも、数値を扱うほうが処理速度は速くなるので、処理速度を速くすることと、文字列としての役割も果たせることから、ハッシュのキーには、文字列よりもシンボルを用いることが多いのです。

##実際にハッシュを生成してみましょう。

```
son = { "name" => "Nick", "age" => 12 }
father = { name: "George", age: 38 }
```

##ハッシュへ要素を追加したい場合
ハッシュ[追加するキー] = 値　とします。

```
son = { "name" => "Nick", "age" => 12 }
father = { name: "George", age: 38 }

father[:hobby] = "fishing" 　　　#キー hobby バリュー fishing を追加

```

##ハッシュの値を取得
ハッシュ[取得したい値のキー]　とします。


```
son = { "name" => "Nick", "age" => 12 }
father = { name: "George", age: 38, hobby: "fishing" }

puts father[:age]  # 38 と出力される
```

##ハッシュの値を変更
ハッシュ[変更したい値のキー] = 値　とします。

```
son = { "name" => "Nick", "age" => 12 }
father = { name: "George", age: 38, hobby: "fishing" }

father[:age] = 40

puts father[:age]  #40と出力される
```

以上です。
Rust の再帰イテレータでサブディレクトリのファイルもすべて取得する (Recursive Directory Iterator in Rust)

## 再帰関数
サブディレクトリも含めて、あるディレクトリ内のすべてのファイルへのパスを取得したい場合、下記のように再帰関数を用いるのが最初に思い付く実装ですね。

```rust:main.rs
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

fn visit_dir<P: AsRef<Path>>(path: P, paths: &mut Vec<PathBuf>) -> io::Result<()> {
    for entry in fs::read_dir(path)? {
        let entry = entry?;
        if entry.file_type()?.is_dir() {
            visit_dir(entry.path(), paths)?;
        }
        paths.push(entry.path());
    }
    Ok(())
}

fn main() -> io::Result<()> {
    let mut paths = vec![];
    visit_dir(".", paths.as_mut())?;

    println!("{:?}", paths);
    Ok(())
}
```

## 動機

上のコードはあまりイケてないですよね。イテレータを使って、↓こんな風に書けたらいいのになぁと思っていました。

```rust:main.rs
struct VisitDir {
    // TODO
}

impl Iterator for VisitDir {
    type Item = io::Result<DirEntry>;
    fn next(&mut self) -> Option<Self::Item> {
        // TODO
    }
}

fn main() -> io::Result<()> {
    let paths = VisitDir::new(".")?
        .filter_map(|e| Some(e.ok()?.path()))
        .collect::<Vec<_>>();

    println!("{:?}", paths);
    Ok(())
}
```

しかし、どんな風に書いたらいいのか分からず…。

そしたら、[This Week in Rust](https://this-week-in-rust.org/blog/2021/01/06/this-week-in-rust-372/) で[この記事](https://fasterthanli.me/articles/recursive-iterators-rust)を見つけて、「これだ！」ということで、次のように書いてみました。

## 再帰イテレータ

```rust:main.rs
use std::fs::{self, DirEntry};
use std::io;
use std::path::Path;

struct VisitDir {
    root: Box<dyn Iterator<Item = io::Result<DirEntry>>>,
    children: Box<dyn Iterator<Item = VisitDir>>,
}

impl VisitDir {
    fn new<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        let root = Box::new(fs::read_dir(&path)?);
        let children = Box::new(fs::read_dir(&path)?.filter_map(|e| {
            let e = e.ok()?;
            if e.file_type().ok()?.is_dir() {
                return VisitDir::new(e.path()).ok();
            }
            None
        }));
        Ok(VisitDir { root, children })
    }

    fn entries(self) -> Box<dyn Iterator<Item = io::Result<DirEntry>>> {
        Box::new(self.root.chain(self.children.flat_map(|s| s.entries())))
    }
}

impl Iterator for VisitDir {
    type Item = io::Result<DirEntry>;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(item) = self.root.next() {
            return Some(item);
        }
        if let Some(child) = self.children.next() {
            self.root = child.entries();
            return self.next();
        }
        None
    }
}

fn main() -> io::Result<()> {
    let paths = VisitDir::new(".")?
        .filter_map(|e| Some(e.ok()?.path()))
        .collect::<Vec<_>>();

    println!("{:?}", paths);
    Ok(())
}
```
やったぜ。
機械学習キーワード

個人的に注目している機械学習関連のキーワードを並べてみます．※随時更新

- **self-supervised Learning（自己教師あり学習）**
- **contrastive learning（対照学習）**
- **GANによる画像適応**
- BERT, GPT-3
- Transformer
- Attention
- 深層強化学習
- 説明可能AI
- relightning
- 半教師あり学習
- 事前学習
- U-net discriminator
- multi-model generator
- 少ないデータ，高速，軽量なGAN
- GAN
- エッジAI
- joint training
- ノイズ
- Dual learning
- Distributed machine Learning
- Meta Learning
- Graph Convolutional Network
- AIセキュリティ
- グラフベース関係性学習
- 知識の蒸留（knowledge distillation）
- 自己蒸留（self disillation）
- continual learning（継続学習）
- Object Tracking（物体検出）
【AT Command】Bearerの設定 (SIMCom: SIM7000G)


# Memo

Bearerの設定方法。
個人的な備忘録なので、わかりにくいことや指摘があれば是非コメントお願いいたします。
それに合わせて更新します。

## 環境

- OS: windows10
- ターミナル: Tera Term

## ハードウェア

- インターフェースモジュール: mini pcie usbアダプタ
- セルラー通信モジュール: SIMCom SIM7000G
- SIM: soracom plan-D

## ログ

```
AT+CGDCONT=1,"IP","soracom.io"

AT+SAPBR=4,1
+SAPBR:
CONTYPE: GPRS
APN:
USER:
PWD:

OK

AT+SAPBR=3,1,"APN","soracom.io"
OK

AT+SAPBR=4,1
+SAPBR:
CONTYPE: GPRS
APN: soracom.io
USER:
PWD:

OK

AT+SAPBR=3,1,"USER","sora"
OK

AT+SAPBR=3,1,"PWD","sora"
OK

AT+SAPBR=4,1
+SAPBR:
CONTYPE: GPRS
APN: soracom.io
USER: sora
PWD: sora

OK

AT+SAPBR=1,1
OK

AT+SAPBR=2,1
+SAPBR: 1,1,"10.224.194.152"

OK

AT+SAPBR=0,1
OK
```
windowsでiverilog その89

#概要　

windowsでiverilogやってみた。
inout使ってみた。

#サンプルコード


```


module gpio(input clk, input rw, input [7:0] inp, output [7:0] outp, inout [7:0] porta);
	reg [7:0] a;
	reg [7:0] b;
	assign porta = rw ? a : 8'bZ;
	assign outp = b;
	always @(posedge clk)
	begin
		b <= porta;
		a <= inp;
	end
endmodule

module test;
	reg clk,
		rw;
	reg [7:0] inp;
	wire [7:0] outp,
		porta;
	gpio u(.clk(clk), .rw(rw), .inp(inp), .outp(outp), .porta(porta));
	assign porta = rw ? 8'bZ : inp;
	initial
	begin
		$display("rw inp outp porta");
		$monitor("%h  %h   %h    %h", rw, inp, outp, porta);
		clk = 0;
		rw = 0;
		inp = 8'h0;
		#2
			rw = 1;
		#2
			inp = 8'h55;
		#2
			rw = 0;
		#2
			inp = 8'haa;
		#2
			$finish;
	end
	always
		#1
			clk = ~clk;
endmodule




```

#実効結果


```


rw inp outp porta
0  00   xx    00
0  00   00    00
1  00   00    00
1  55   00    00
1  55   00    55
0  55   00    55
0  55   55    55
0  aa   55    aa
0  aa   aa    aa


```

以上。
9割以上が知らない！？初心者におススメ！Vue.jsでパンくずリストを作ろう！！

皆さんこんにちは！

今回は初心者さんに必見！パンくずリストの作り方をお教えします！！

HTML、CSSではなくコンポーネントを利用して作成していきます。

パンくずリストはSEO内部対策にも非常に有効で、コンポーネントを使うことでその都度HTML、CSSを記述しなくて済むのでぜひご利用ください！

また、今回の記事を書くにあたって、下記の記事を参考にさせて頂きました。

[【vue.js】nuxt.jsでパンくずリストを作る方法](https://hirakublog.com/code/218/)

ご協力誠にありがとうございます。

それでは、順を追って一緒に説明を見ていきましょう！

#コンポーネントの作成#

componentsディレクトリに``Breadcrumb.vue``を作成し、以下のテンプレートを作成します。

```components/Breadcrumb.vue
<template>
  <div class="l-breadcrumb">
    <div class="l-breadcrumb__inner">
      <ul class="l-breadcrumb__items">
        <li class="l-breadcrumb__item" v-for="breadcrumb in breadcrumbs.data" :key="breadcrumb.name">
          <a v-if="breadcrumb.path" :href="breadcrumb.path" class="l-breadcrumb__text">
            {{ breadcrumb.name }}
            <b-icon pack="fas" icon="chevron-right" class="bread-icon"></b-icon>
          </a>
          <span v-else class="l-breadcrumb__text">{{ breadcrumb.name }}</span>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  props: ['breadcrumbs']
}
</script>

<style scoped>
.l-breadcrumb__items li {
  display: inline-block;
  margin-top: 1rem;
}
.l-breadcrumb__items a {
  color: var(--link-color) !important;
}
.l-breadcrumb__items a:hover {
  text-decoration: underline !important;
}
.l-breadcrumb__items .bread-icon {
  margin: 0 5px;
  color: black;
  opacity: 0.5;
  display: inline;
}
</style>
```

``<b-icon>``はCSSフレームワークBuefyを使うことで、実装できます。詳しくは、僕が書いたこちらの記事を見て下さい。
[初心者必見！サイト制作は楽してなんぼ。CSSフレームワークBuefyの紹介！！](https://qiita.com/akki-memo/items/278ff2982961274955c4)
[効率的にサイト作り！Buefyでアイコンを表示しよう！！](https://qiita.com/akki-memo/items/1fa0d0a9ac6870ba9337)

また、パンくずリストのCSSも載せておくので、ぜひ使ってください！

#コンポーネントの読み込み#

コンポーネントを読み込み、propsでnameとpathと言う名のプロパティを用いて、オブジェクト作成します。

```App.vue
<breadcrumb :breadcrumbs="breadcrumbs" />

<script>
import Breadcrumb from '~/components/Breadcrumb.vue'

export default {
  computed: {
    breadcrumbs: function() {
      return {
        data: [
          {
            name: 'ホーム',
            path: '/'
          },
          {
            name: 'ユーザー情報',
            path: '/user'
          },
          {
            name: 'アカウント情報'
          }
        ]
      }
    }
  }
}
</script>
```

すると、以下のような結果になります。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/cc238a46-0b23-90c3-4205-ae3254bc3f6c.png)

いかがだったでしょうか？

パンくずリストはUXの部分でも非常に有効なので、僕は使えるなら使った方がいいかなと思います。

今使わなくても、いずれは使うときが必ず来るので、その時は今回書いた記事をぜひ参考にして使ってください！！

以上、「9割以上が知らない！？初心者におススメ！Vue.jsでパンくずリストを作ろう！！」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
C#で書くものはRubyでこう書く

# 注意
Rubyのやる気がなかったので更新停止。
次書く時は別の記事として投稿します。


# 標準入出力ストリーム
```C#:C#
// -----標準入力-----
// 値がひとつだけの場合
var single = Console.ReadLine();
// 複数ある場合
var multiple = Console.ReadLine().Split(",");

// -----標準出力-----
Console.Write("改行なし");
Console.WriteLine("改行あり");
```

```Ruby:Ruby
# -----標準入力-----
# 値がひとつだけの場合
single = gets
# 複数ある場合
multiple = gets.split(",")
# 空白のみの場合はこの書き方もできる
multiple = gets.split

# -----標準出力-----
print "改行なし"
puts  "改行あり"
```


# ループ処理


## for文

```C#:C#
for (var i = 0; i < 10; i++) {
    // 処理
}
```

```Ruby:Ruby
for i in 0..9
    # 処理
end
```


## foreach文

```C#:C#
var array = new int[5] {1, 2, 3, 4, 5};     
foreach (var i in array) {
    // 処理
}
```

```Ruby:Ruby
array = (1..5)
array.each do |i|
    # 処理
end
```

## While文

```C#:C#
while (true) {
    // 処理
}
```

```Ruby:Ruby
while true
    # 処理
end
```


# インクリメント / succ
```C#:C#
int num = 1;
num++;  // 結果: 2
```

```Ruby:Ruby
num = 1
apt = "a"
letter = "z"

num.succ     # 結果: 2
apt.succ     # 結果: b
letter.succ  # 結果: aa
```


# デクリメント / pred
```C#:C#
int num = 1;
num--;  // 結果: 0
```

```Ruby:Ruby
num = 1
num.pred     # 結果: 0
```


# 条件分岐


## if文

```C#:C#
string input = Console.ReadLine();

if (input == "test1") 
{
    // 処理
}
else if (input == "test2") 
{
    // 処理
}
else
{
    // 処理
}
```

```Ruby:Ruby
input = gets.split

if    input == "test1"
    # 処理
elsif input == "test2"
    # 処理
else
    # 処理
end
```


## Switch文

```C#:C#
string input = Console.ReadLine();

switch (input)
{
    case "Test1": 
        // 処理  
        break;

    case "Test2": 
        // 処理
        break;

    default:
        // 処理
        break;
}
```

```Ruby:Ruby
input = gets.split

case input

    when "Test1"
        # 処理

    when "Test2"
        # 処理

    else
        # 処理
end
```


## 三項演算子

変化なし
多対多リレーションを修正するストアドプロシージャ

下の画像の右側と左側が多対多のテーブルのレコードで、真ん中の薬のカプセルみたいなやつが、中間テーブルのレコードとします。

具体的にいうと、左側の「LIZ」、「LITA」はアーティストで、右側の「KING」というのは楽曲です。

「KING」という２つのレコードは同じものを意図しているのにもかかわらず、IDが異なるので違うものとして扱われてしまっています。

なので**MAIN**を残し、**SUB**を消すために、以下のように中間テーブルをUPDATEしたのち、いらなくなった**SUB**レコードを削除します。

![IMG_8042.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227791/9741dd95-a8ba-0253-00a1-41b382c85c77.jpeg)

これをするSQLは以下のようになります。

```sql
-- 左側のテーブル : artists
-- 中間テーブル : music_artists
-- 右側のテーブル : music
update music_artists set music_id = {main} where music_id = {sub};
delete from music where id = sub;
```

これでうまくいきそうですが、以下のような場合にうまくいきません。
UPDATEすると複合主キーの主キー制約に反するので、UPDATEできないのです。

![IMG_8043.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227791/4e80540d-4961-ce24-6eb2-ad0f31752a53.jpeg)

上記のパターンが

* UPDATE → DELETE

のパターンが必要であるのに対し、今回のパターンでは

* DELETE → DELETE

する必要があります。

![IMG_8044.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227791/ea90adbf-6175-0460-7420-57fb6ee90ba5.jpeg)

これを振り分けるためには、ストアドプロシージャでカーソル操作する必要があります。
MySQLです。

```sql
CREATE PROCEDURE `join_music`(main INT, sub INT)
BEGIN
  DECLARE current_artist_id INT;
  
  DECLARE done INT DEFAULT FALSE;
  
  DECLARE cur CURSOR FOR SELECT artist_id FROM music_artists WHERE music_id = sub;
  
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;


  cur_loop: LOOP
    IF done THEN
      LEAVE cur_loop;
    END IF;
    
    FETCH cur INTO current_artist_id;
    
    IF EXISTS (SELECT * FROM music_artists WHERE artist_id = current_artist_id AND music_id = main) THEN
		DELETE FROM music_artists WHERE artist_id = current_artist_id AND music_id = sub;
	ELSE
		UPDATE music_artists SET music_id = main WHERE artist_id = current_artist_id AND music_id = sub;
    END IF;
  END LOOP;
  
  CLOSE cur;

  DELETE FROM music WHERE id = sub;
END
```

ちょっとパターンを考慮するだけでこんな複雑になるんですね。
rails _6.0.3_ new hello_myappコマンドでwarningのメッセージが出た

rails _6.0.3_ new hello_myappコマンドでwarningのメッセージが出ました。

そのメッセージは以下のようなもの

warning " > webpack-dev-server@3.10.3" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".

解決策
hello_myappのフォルダの階層で以下のコマンドを実行したことで解決した。

yarn upgrade webpack@^4.0.0


このサイトを参考にさせてもらいました。

https://stackoverflow.com/questions/61565543/rails-webpack-dev-server-has-unmet-peer-dependency
可視化に適したデータマートをつくるプロセス

データ分析基盤の理解を深めるために、[ビッグデータを支える技術](https://amzn.to/3q6n5kY)を学習中。
今回は、データマートの基本について簡単に。

# データマートをつくるプロセス
「可視化に適したデータマートを作る」ことは、「BIツールのための非正規化テーブルを作る」というプロセス。
![datamart-process.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991759/9c9eb5fe-8507-6aed-079e-28b872b6bbcb.png)
MPPデータベースのような列指向ストレージでは、カラム単位でデータが保存され、圧縮もあるので、カラムの数が増えても性能に影響しないため、データマートは**非正規化テーブル**にするのが最も単純で、十分に効率的な方法。

# オープンソースBIツール
|BIツール |特徴 |補足 |
|:--|:--|:--|
|Redash   |SQLによるクエリの実行結果をそのまま可視化   |Python製のダッシュボードツール   |
|Superset   |画面上でマウス操作によってグラフをつくる   |対話的なダッシュボードを作るためのPython製のWebアプリケーション   |
|Kibana   |Elasticsearchのフロントエンドでリアルタイムに作成   |JavaScript製の可視化ツール   |
GCPのUbuntu VM上でUFWを有効化してSSH接続ができなくなった時の解決方法

# 直面した問題
GCPのUbuntu VM上で色々いじっていた所、UFWを有効化したまま切断 => 再起動をしてしまいssh接続等ができなくなった。

# これで解決した
VMインスタンス情報に、カスタムメタデータとして `UFWを無効化する起動スクリプト` を記述する。
その後、VMインスタンスを再起動する。

```UFW無効化.sh
#! /bin/bash
/usr/sbin/ufw disable
```

↓こんな感じ。 `startup-script` をキーにすることで起動スクリプトとして認識される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151736/fc92bbed-20ae-93fe-d6e5-defc4691a128.png)
M1 Macに機械学習環境を最速で構築してみた　（conda, jupyter notebook, tensorflow）

# はじめに
<!-- 発端や概要を記載 -->

M1対応のtensorflowを使うにはApple公式のGithubリポジトリ（[Apple/tensorflow-macos](https://github.com/apple/tensorflow_macos)）からパッケージをダウンロードして一つ一つインストールするなど面倒だったのですが、`conda-forge`にまとまったパッケージがあったのでそれを使ってM1 MacbookにM1対応のtensorflowをjupyter上で実行できる環境を構築する方法をメモします。（1/12/2021 現在）

# この記事では
1. Jupyter Notebook上でM1対応のtensorflowを実行する簡単な方法を紹介します。
2. 実際にM1のGPUを使って学習してみます。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [tensorflowを実行する環境を構築する](#Chapter1)
2. [tensorflowを使ってみる](#Chapter2)
5. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# tensorflowを実行する環境を構築する

### anaconda環境をインストール

まずは下のGitHubページの、OS X arm64 (Apple Silicon) Miniforge3-MacOSX-arm64を選び、Miniforgeのインストーラーをダウンロードします。
[conda-forge/miniforge](https://github.com/conda-forge/miniforge#miniforge3)

ダウンロードした`Miniforge3-MacOSX-arm64.sh`を使ってターミナルからMiniforgeをインストールします。

```bash
$ bash Miniforge3-MacOSX-arm64.sh
```

### 必要なパッケージをインストール


```bash
# m1用tensorflowを含んだconda環境の作成、起動
$ conda create -n python38 tensorflow-addons tensorflow -c isuruf/label/tf -c conda-forge
$ conda activate python38

# Jupyter notebookのインストール
$ conda install -n python38 -c conda-forge notebook
$ conda install -n python38 -c anaconda ipykernel

# Jupyter Notebookに現在のpython環境をセット
$ python -m ipykernel install --user --name=python38
```

Jupyter notebookを起動し、pythonファイルから`tensorflow`がインポートきれば成功です。

```
$ jupyter notebook .
```
```
import tensorflow as tf
```

<a id="#Chapter2"></a>
# tensorflowを使ってみる

Jupyter上でPythonファイルを作り以下のコードを実行します。

```python
import tensorflow.compat.v2 as tf
mnist = tf.keras.datasets.mnist
import time

tf.enable_v2_behavior()

from tensorflow.python.framework.ops import disable_eager_execution
disable_eager_execution()

from tensorflow.python.compiler.mlcompute import mlcompute
mlcompute.set_mlc_device(device_name='gpu')

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test  = x_test.reshape(x_test.shape[0], 28, 28, 1)

model = tf.keras.models.Sequential([
  tf.keras.layers.Conv2D(1024, (3,3), activation='relu', input_shape=(28, 28, 1)),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Conv2D(512, (3,3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(256, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

start = time.perf_counter()
model.fit(x_train, y_train, epochs=5)
end = time.perf_counter()
print("Elapsed time : {0} s.".format(end-start))

model.evaluate(x_test, y_test)
```

20分ほどで学習が終わりました。
`device_name='gpu'`とするのを忘れるとCPUが使われて遅くなってしまいます。

```python
mlcompute.set_mlc_device(device_name='gpu')
```


<a id="#reference"></a>
# 参考文献
- [How to install if I use conda environments? #3](https://github.com/apple/tensorflow_macos/issues?q=conda)
- [Apple Silicon M1 でtensorflow-macosを実行したらめちゃくちゃ速かった。](https://qiita.com/tomoyaeibu/items/46f2f3384a370df71d5e)
Raspberry Pi と Windows を有線LAN接続

# はじめに
`Raspberry Pi` <---> `LANケーブル` <---> `Windows PC`
で、VNC接続がしたい。
理由：無線LANだと外で使いにくいから。
使用するアプリ：VNC Viewer
接続手順は[ここ](https://qiita.com/bouningen98/items/49772e5eab96dc640728)から

# 接続
ラズパイとPCを有線LANで接続。
このとき、PCは無線LANに接続、ラズパイは接続しない。

# 1. 設定 (PC側)
1. WiFiの設定
1. 画面右側**アダプターのオプションを変更する**
1. **WiFi**を右クリック
1. **状態**
1. **プロパティ**
1. **共有**
1. 上の項目にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/963393/408db512-45dc-3f1d-8326-bf2b5297e379.png)



# 2. IPアドレスを確認 (PC側)
コマンドプロンプトで

```
arp -a
```

を実行。

[実行結果]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/963393/82318dbb-bc77-ccfe-8850-24851d943e9e.png)
上の**192.168.11.17**がPCのIPアドレス。
下の**192.168.137.1**は有線接続している方のPCが持つIPアドレス。
（この中の192.168.137.26がラズパイのIPアドレスだったりする。接続のOnOffで確認できるはず。）


# IPアドレスの固定 (ラズパイ側)
今回はIPアドレスを**192.168.137.2**に設定してみる。

## CUIでの方法
`/etc/dhcpcd.conf` に書き込み

```
$ sudo nano /etc/dhcpcd.conf
```
これで開いてみてもよい。

書き込むのは以下のコード。

```
interface eth0
static ip_address = 192.168.137.2/24
static routers = 192.168.137.1
static domain_name_servers = 192.168.137.1
static domain_search = 
```

## GUIでの方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/963393/13749fa3-5a62-594e-94c2-5190e896526d.png)
<ol><li> インターネット設定右クリック
<li> **Wireless & Wires Network Settings**
<li> interface -> **eth0**
<li> **Automatically configure empty options** のチェックを外す
<li> 以下のように入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/963393/ef80d9b9-5f55-d9ec-2c0d-a06036eca6a3.png)
</ol>

# VNC Viewer で接続
PCのVNC Viewerを起動し、IPアドレス検索の部分に**192.168.137.2** （または**raspberrypi.local**）を入力し接続。

# IPアドレスの確認方法
一番楽なのは、ラズパイ画面右上のVNCマークをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/963393/28355291-a021-834a-378d-801137dca92e.png)
Connectivityの下にある数字がラズパイのIPアドレス。
この数字をVNC Viewer上に入力することで接続可。

ターミナル上では、

```
$ ip addr show
```

または、

```
$ ifconfig
```

**wlan0**が無線LANで**eth0**が有線LAN。




# 接続できないとき

**解決方法その1**

1. PC側のWi-Fiを切断
1. LANケーブルを繋ぎ直す
1. PC側のWi-Fiを再接続

**解決方法その2**

2. PC側のWi-Fiを切断
2. LANケーブルを外す
2. Wi-Fiを繋げる
2. LANケーブルを繋げる

**解決方法その3**

3. 待つ。

イーサネットの状態が送信と受信両方できていれば接続できるはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/963393/758d14bc-9f8d-390a-4d29-6de72c22a54c.png)


# まとめ
接続出来るときと出来ないときがあるので、未だに試行錯誤中です。
AWS Data Pipelineってどんなサービス？

## 勉強前イメージ

サービス間のデータの流れをいい感じにするやつ....
よくわからん！

## 調査

### AWS Data Pipelineとは

AWSのサービス間のデータの統合・処理を自動化するサービスです。
オンレプとの連携も可能です。
AWS Data Pipelineは保存場所にあるデータに定期的にアクセスを行い、必要なスケールでのリソースを使って処理を行います。
s3やRDS,EMRなど使用することが出来ます。
指定したスケジュールでの起動も可能で、shellも使用できるためcronの代わりにも使うことが可能です

### 特徴

- マネージドサービスである

データの移行やELT処理(Extract(抽出)/Transform(変換)/Load(データを入れる))などを行う場合、
自前で実現しようとすると、基盤やソフトウェア・管理保守など準備が大変ですが、
AWS Data Pipeline であれば準備をすべてAWSが担ってくれているので、すぐに始めることが出来ます

- GUIでの操作も可能

開発用のGUIが用意されており、簡単なデータ移行であればGUIのみで実行することが出来ます。
複雑な変更や加工が必要な場合でも、自前のプログラムをData Pipelineに食わすことで実行させることができ、
簡単ながら拡張性があります。

- オンプレの処理を行える

クラウドサービスだが、オンプレの処理にも使用できます。

### 構築イメージ

イメージとしては以下の図です。
RDS から s3 にデータを処理して移動させたい場合に Data Pipeline を使用します。
データの移行条件や、フォーマット・スケジュールなどすべて Data Pipeline が行ってくれます。

他にも以下のような選択肢があり、それでData Pipelineが作れます

- どこにデータが有るのか(Data Node) : データの場所やフォーマット
- どう処理するか(Activity) : データ処理のアクティビティ。パッケージ済みのも用意されている
- いつ処理するのか(Schedule) : 処理の実行スケジュール
- 誰が処理するのか(Resource) : 処理や条件をチェックするリソース
- どういう条件で処理するのか(Precondition) : 処理実行の条件
- 通知はどう送ればよいか(Action) : 通知の方法

![RDStos3Untitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/49249399-bfd7-322a-0d70-9419b3dd76ec.png)


## 勉強後イメージ

ニュアンス合ってなくもないw
サービス間で個別にデータの移動とかがめんどくさい！！！から、
AWS Data Pipelineを使えば、一貫の流れを管理できるしわかりやすい。

## 参考

- [ELTとETL：違いの定義](https://www.talend.com/jp/resources/elt-vs-etl/)
- [リソース](https://docs.aws.amazon.com/ja_jp/datapipeline/latest/DeveloperGuide/dp-concepts-resources.html)
- [アクティビティ](https://docs.aws.amazon.com/ja_jp/datapipeline/latest/DeveloperGuide/dp-concepts-activities.html)
- [【AWS】AWS Data Pipeline入門](https://www.st-hakky-blog.com/entry/2020/08/06/084032)
- [AWS Data Pipelineの使い方について](https://www.acrovision.jp/service/aws/?p=2526)
- [AWS再入門 AWS Data Pipeline編](https://dev.classmethod.jp/articles/cm-advent-calendar-2015-getting-started-again-datapipeline/)
- [AWSエンジニア入門：AWS Data Pipelineとは](https://www.yume-tec.co.jp/column/awsengineer/1906)
- [AWS Black Belt Tech シリーズ 2015 - AWS Data Pipeline](https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-tech-2015-aws-data-pipeline-52837923)
- [AWS Data Pipeline とは](https://docs.aws.amazon.com/ja_jp/datapipeline/latest/DeveloperGuide/what-is-datapipeline.html)
- [AWS DataPipelineって何ができるの？](https://qiita.com/uzresk/items/213a34481a3522ce0317)
エンジニア採用で絶望する瞬間【面接官の本音】

## 採用の時に絶望する瞬間は確かにある。
エンジニア・プログラマーに向いてないという以前の話ですが！
~~弊社は未経験歓迎ですが、だいたい９割くらいはこんな感じです。~~
（転職したので現職でどうかは知らん。）
経験3年以上を基準に掲げる会社さんの気持ち、べりぃわかります。

### 会社のカジュアル訪問を無断キャンセル！
えーーー
どんな人だろうってツイッターとか、GitHubとかチェックして
知りたそうな内容調べといたり、
ランチいけそうならどこ行こうかとか考えたり
いろいろしてたのに、無断キャンセル！！！

その後にしれっと書類選考に応募してきたりするのでもう、、、

### 募集要項を全く読んでくれてない
募集要項がわかりにくい！とか、これ具体的にどうなの？
って言われたらむしろ大喜びするんですが！

なんと御社でエンジニアになるためには、何すればいいですか？
って丸投げしてくださる方がいます。。。
募集要項を読んでください！お願いします！
こう言う方、技術に関するドキュメント読めるんですか？本当ですか？？？怖いです。

### どんな経験をしたかわからない
〜〜プロジェクト1年　プログラマー(Java)
〜〜〜プロジェクト半年　リーダー(PHP)
以上
のような箇条書きの職務経歴書、
事実ではあるのですが、その内容ですと技術力やその方の特性がわかりません。
お願いします。
あなたが活躍しているエピソードを書いてください！
いっしょに仲間としてやっていけるか分からないのです。。。

### 技術力を証明する材料をくれない
GitHubリポジトリや技術ブログが欲しいです。
まずは本当に技術力あるの？って確認できるものだけでもいいんです。
超絶大作でなくてもいいので、アウトプットを見せてください。
営業トークだけでは入社できません。。。。

## べりぃ悲しい。そりゃあ実務経験3年以上って書きたくなる。。。
こういう状態での応募の方が正直９割です。
~~いや、弊社が実務未経験の方も歓迎って書いてあるのが問題なのかもしれませんが。。。~~
（転職したので現職は知らん！）
でも、もう少しだけ贅沢言わせてください！

上記の内容をしっかりやっているだけで応募書類の上位１０%です。
そうすれば、やっと中身をみてお互いに良い関係を築けるか検討に入れます！
あえて門前払いを食らわないでほしい。。。

# まとめ
採用側も人間です。とても悲しい日々を送っています。

私はこんな思いやりのない連中とは違う！と言う方の応募
~~弊社もそれ以外の会社も切望しております。~~
業界が！世界が！切望しております
JavaScriptでPythonのenumerate関数を実行するには

# はじめに

Node.jsを使ったWebアプリの開発にて、forEachでリストを回していたのですが、
急遽インデックスの情報も必要になりました。

そこで次のようなソースコードを書いたものの、「もっといい方法がある」と仲間に指摘されました。
実際に試したところ非常に便利だったことと、Pythonのenumerate関数に近いものを感じたので、
**for文でインデックスとバリューを同時に取得する方法**として、記事に残します。

```js
ary = ["bar", "foo", "hoge"]

let i = 0 
ary.forEach(function( value ) {
     console.log(i, value );
     i++
});
// 0 bar
// 1 foo
// 2 hoge
```
# 実行環境
- Node.js v12.16.3

# 検証環境
- Paiza.io(Python 3.8.2)
- Paiza.io(Node.js v12.18.3)

# そもそもenumerate関数とは

引数に指定したリストの、インデックスとバリューを取得する関数です。

```py
ary = ["bar", "foo", "hoge"]
for i, item in enumerate(ary):
    print(i, item)
#  0 bar
#  1 foo
#  2 hoge
```


# for文でインデックスとバリューを同時に取得する

## forEachは、第二引数にインデックスを指定できる

forEach関数において 第一引数はリスト、第二引数はインデックスを取ります。

このインデックスは、ループ回数が増加するごとに自動的にインクリメントされるため、
`i++`や`i += 1`と記述する必要はありません。

```JS
ary = ["bar", "foo", "hoge"]
ary.forEach(function(value, i) {
     console.log(i, value);
});
// 0 bar
// 1 foo
// 2 hoge
```



## `for in`を使う
`for in`はリストのインデックスを取得します。
次のようなソースコードにより、インデックスとバリューを取り出します。

```JS
ary = ["bar", "foo", "hoge"]

for (i in ary){
    console.log(i, ary[i])
}
// 0 bar
// 1 foo
// 2 hoge
```

一方で、`for in`では次のように予期しない挙動を示す場合もあるので、
利用には注意が必要そうです。

```JS
var data = [ 'apple', 'orange', 'banana'];
//配列オブジェクトにhogeメソッドを追加
Array.prototype.hoge = function(){}
  for (var key in data){
   console.log(data[key]);
  }
// apple
// orange
// banana
// function(){}
```

# 参考
- [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
- [Python, enumerateの使い方: リストの要素とインデックスを取得](https://note.nkmk.me/python-enumerate-start/)
- [配列にfor...inはダメと言うけれど、](https://qiita.com/may88seiji/items/2e8fec8391fea0a17dbc)
Unityでオブジェクトの複製と動的削除

　クリックすると、Cubeが生成され、積み上がるサンプルです。Cubeはprefab化し、Asset内に保持してあり、クリックによりInstantiate命令が実行され、シーンに追加されます。下方には、こぼれ落ちたCubeを削除するための平面とスクリプトが設置されています。
![スクリーンショット 2021-01-13 2.01.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/1886d384-82ea-3152-1080-affabd85cc91.png)

０、Edit>ProjectSetting>PhysicsのGravityのyを-50にする
１、sceneにCubeを作成する
２、Cubeにrigidbodyを追加する
３、AssetsにResourcesフォルダを作成する
４、CubeをResourcesフォルダにドラッグ&ドロップし、prefab化する
５、sceneのCubeは削除してしまう
６、Planeで地面groundを作成する
７、新規にスクリプトaddBox.csを作成し、groundに追加する
８、groundからこぼれるCubeを消すため、Planeでdelを作成する
９、新規にスクリプトdelObj.csを作成し、delに追加する

```cs:addBox.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class addBox : MonoBehaviour
{
    void Update(){
        if (Input.GetMouseButtonDown(0)){
            Shot();
        }
    }
    void Shot () {
        GameObject dup = (GameObject)Resources.Load ("Cube");
        Vector3 pos = new Vector3(
            Random.Range(-1f,1f),
            5,
            Random.Range(-1f,1f));
        Instantiate (dup, pos, Random.rotation);
    }
}
```

```cs:delObj.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class delObj : MonoBehaviour
{
    void OnCollisionEnter(Collision c) {
        Destroy(c.gameObject);
    }
}
```