OmniAICreator/Qiita-1.07M huggingface dataset:
axiosでPOSTした画像をLaravel APIで保存する

タイトルの通りです。画像やファイルのstorage保存の記事はいくつか見かけましたが、jsからPOSTする記事についてはあんまり見かけなかったので書きました。
この記事ではaxios経由で画像をPOST、LaravelのAPI処理に渡しているサンプルコードを簡単に説明します。概要は以下の通りです。

1. canvasに画像を描画し、blobデータを作成
2. blobをformDataにappendして、axiosでPOST
3. POSTされたblobファイルを、Laravel API側で処理・保存


## View側の処理

### データのBLOB化
以下の処理か``toBlob``を使ってCanvasに描画した画像ファイルをblob化します。

```javascript:index.vue
// Canvasのデータをblob化
const type = 'image/png';
const dataurl = this.canvas.toDataURL(type); // this.canvasは用途に合わせて書き換え
const bin = atob(dataurl.split(',')[1]);
const buffer = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) {
    buffer[i] = bin.charCodeAt(i);
}
const blob = new Blob([buffer.buffer], {type: type});
```

`"multipart/form-data`のデータをPOSTするので、blobファイルを`FormData`インタフェースにappendする形でデータを作成します。

```javascript:index.vue
const data = new FormData();
data.append('photo', blob, 'image.png'); //'photo'というkeyで保存
```

blobを格納したdataを`axios.post`の第二引数にセットすれば、POST可能です。

```javascript:index.vue

axios.post('/api/photo', data, {
        headers: { 'content-type': 'multipart/form-data' }
    })
    .then(res => {
        console.log('success')
    }).catch(error => {
        new Error(error)
    });
```

## Laravel API側の処理
api用のControllerで設定した``store``定義内に、受け取ったblobデータをファイルとして保存するための処理を書きます。View側で``FormData``内にappendした``photo``データを``$request``から参照し、``storeAs``メソッドを実行することで簡単に保存が可能です。

```php:IndexController.php
  public function store(Request $request)
  {
      // ファイル名を取得
      $filename = $request->photo->name;

      // blobデータをstorageに保存する
      // diskの指定を特にしなければ、例の場合。`storage/app/images/`に画像が保存される
      $path = $request->photo->storeAs('images', $filename);
  }
```
interface{}型に特定のstructぶっこんでから置き換えってできるの？

できるはずなんだけど... 不安になったので、実験してみた。

結果：できた。

```go
package main

import (
    "fmt"
)

type a struct {
    ID string
    Something interface{}
}

type b struct {
    ID string
}


type c struct {
    ID string
    Param string
}

func main() {
    r := a{
        ID: "test",
        Something: b{
            ID: "hey guy!!",
        },
    }

    other := c{
        ID: "hey girl!!",
        Param: "you are awesome",
    }

    r.Something = other
    fmt.Printf("%+v\n", r)
}
```
https://play.golang.org/p/S7qOWPLt5pF
【Rails】自作WebアプリからMastodonのプロフィール画像を変更

個人開発のWebアプリ**「[まちかどルート](https://machiroute.herokuapp.com/)」**v5.41への実装メモです。

プログラミングに入門して8ヶ月。
今回も **SNS「Mastodon」のAPI** に挑戦してみました。

![profile.png](https://qiita-image-store.s3.amazonaws.com/0/335872/c0bb5b33-929f-9c20-fa3b-f0663d1e74b5.png)

# まえがき

・まちかどルートではMastodonのアカウントでログイン認証するようにしています。

・今回の実装をするまでは、まちかどルートのプロフィール画像を変えるためにわざわざMastodonで変更し、まちかどルートで再ログインする必要がありました。

・画像アップローダーとしてRails 5.2の新機能 **Active Storage** を使い、ファイルをAmazon S3に保管しているのですが`gem 'mastodon-api'`(v2.0)を通してアップロードするとき、その環境のせいでとても苦労しました。

# model

```ruby:user.rb
has_one_attached :image
```
Active Storageを使うのでマニュアルどおりの作法でmodelにこう書きます。バリデーションについては今回、割愛します。

# view

```erb:edit.html.erb
<%= form_with model: @user, multipart: true, local: true do |f| %>
  <%= f.file_field :image %>
<%= button_tag :type => "submit" do %>変更を保存<% end %>
```
プロフィール画像のファイルを選択するためのフォームです。

# controller

```ruby:users_controller.rb
def update

   # 画像の選択の有無を確認
   if params[:image] != nil
 
    # 画像を uploaded_file に格納
    uploaded_file = params[:image]
 
    # 画像を /public にいったん配置するため output_path にパスを設定
    output_path = Rails.root.join('public', uploaded_file.original_filename)


    # Mastodonには2MB制限があるので画像を縮小
 
    ## MiniMagickを使います。まずは画像を入力
    img = MiniMagick::Image.read(uploaded_file)
 
    ## 縮小します
    img.resize "300x300"

    ## 縮小したら /public に書き出します
    img.write output_path


    # MastodonのAPIを通してアップロードします

    ## 配列を用意します。Mastodon指定のパラメーターは avatar です
    user_array = { "avatar": output_path }

    ## APIを叩くためのクライアントを生成します
    domain = '[対象のMastodonインスタンスのドメイン]'
    access_token = '[ユーザーのアクセストークン]'
    client = Mastodon::REST::Client.new(base_url: "https://#{domain}", bearer_token: access_token)

    ## MastodonのAPIを叩きます
    result = client.update_credentials(user_array)


    # 以上でMastodon側のプロフィール画像が変更されます
    # 続いて、まちかどルートにも同じ画像を反映させます
    @user.avatar = result.avatar
    @user.save


    # 最後に、不要となった/publicの画像を削除します
    File.delete(output_path)

   end

   flash[:notice] = "アイコンを変更しました" 
   redirect_to @user
end
```

controllerが一番苦労しました。
解説はコメントアウトにある通りです。

# あとがき

Active Storageはとても簡単に導入できるアップローダーなのですが

```
user_array = { "avatar": @user.image }
```
と書ければ、わざわざ/publicに画像を配置する手間がなくて楽なのに `url_for(@user.image)`とやっても「そんな画像はありません」というエラーが返ってきてしまうんです。

というわけで、いろいろ試行錯誤して上記のようになりました。とくに/publicにいったん配置する方法がわかったので、これから他の画像系APIを使うのに役立ちそうです。今後も学んでいきたいと思います。
【Unity】【Android】ローカルストレージにファイルを出力する

# ローカルストレージにファイルを出力する

※Unity2018.3.3f1を利用しています。

Androidのローカルストレージ内にXMLファイルを出力しようとしたのですが
ファイル自体はできあがるのに、なぜか中身が出力されません。

そういやManifestファイルを作っていなかったと思い、
Unityマニュアルを確認したところ、以下のように記載されていました。

---
Unity は、Player Settings とアプリケーションがスクリプトから呼び出す Unity APIs に基づいて、自動的に必要なパーミッションを加えます。例えば、以下のようなものが含まれます。

- Network クラスにより INTERNET パーミッションを加えます。
- バイブレーションの使用 (Handheld.Vibrate など) により VIBRATE を加えます。
- InternetReachability プロパティーにより ACCESS_NETWORK_STATE を加えます。
- Location APIs (LocationService など) により ACCESS_FINE_LOCATION を加えます。
- WebCamTexture APIs により CAMERA パーミッションを加えます。
- Microphone クラスにより RECORD_AUDIO を加えます。

---

と言うことは、Player Settingsに何らかの設定値がありそうです。
実際、以下のような項目がありました。


- Write Access
  - External(SDCard) に設定すると、SD カードなどの外部ストレージへの書き込みアクセスを有効にし、対応する権限を Android マニフェストに追加します。 開発ビルドではデフォルトで有効になっています。

デフォルトでは「Internal」になっていましたが
SDカードに出力したい訳ではないので、Internalのままで良いだろうと思っていました。

## ところが

ファイルは一向に出力されず・・・。

manifestファイルをPlaginsフォルダに入れることで、
Unityが自動で生成したmanifestを上書きできるようですが
manifestファイル自体は作成してくれないので、ゼロから自作しなくてはなりません。
~~ちょっとそれはめんどくさい~~

## Write PermissionをExternalにしてみる

![その１.png](https://qiita-image-store.s3.amazonaws.com/0/354674/4afdb94a-43aa-a2d6-a67d-fc354c0d7a5b.png)

ものは試しで、Write Permissionの値をExternal設定にしてみたところ
実機の内部ストレージにXMLファイルが出力されていました！
なんてこった。

## 考察

PlayerのWrite Permissionを「External（SDCard）」に設定することで
内部ストレージにXMLファイルを出力することができました。

クラスをそのまま出力したかったので、ファイル出力には
DataContractSerializerを使用したのですが
UnityEngine.PlayerPrefsなるクラスも準備されているようでして。

もしかして、これを使っていたら
Unityが自動的にパーミッションを加えていてくれたのかな？

## おまけ

Unity Editorで動作させる場合と実機で動作させる場合とで
保存先のパスが変わってきます。
その場合、UNITY_EDITORプリプロセッサを使用してパスを切り替えると良いです。

```C#
    var filename = "SaveData.xml";
#if UNITY_EDITOR
    // Unity Editor上
    var filepath = Path.Combine(@"C:\", filename);
#else
    // それ以外
    var filepath = Path.Combine(UnityEngine.Application.persistentDataPath, filename));
#endif

```
Google Apps Script を使って Googleスプレッドシートに目次を作る

# はじめに
Google Spreadsheet でシート切り替えを行う場合、画面下のタブから切り替える必要があります。
７つや８つ程度であれば、そこから切り替えれば良いですが、２０や３０となると切り替えや並び替えが非常に面倒になります。

その点についてはシートを管理する目次用のシートを作れば解決できるでしょう。
ただ、今度はその目次シートの管理が面倒になります。
本記事はそういった問題を Google App Script で解決することを目的としています。


# 要件定義
具体的な機能としては

- 目次シートを作る
- 目次シートに目次シート以外のシートのリンクをまとめる。  
※リンク化することでシートを別タブで開きやすくなるというメリットもあります。
- シートの追加・更新・削除があれば、それを再反映できるようにする。
- 再反映しても、すでにある目次の並び替えは維持する

です。これらの要件を Google App Script で実装します。



# 実装
1.目次を追加したい スプレッドシートを開く。 
2.スプレッドシートの メニュー＞ツール＞スクリプトエディタ をクリックし、スクリプトエディタを開く。 
3.スクリプトエディタに以下のソースコードを貼り付ける。

```js:
function replaceToc(){
  // 任意の値を入れてください。
  var edit_sheet_name = '目次'; // 目次シートの名前
  var edit_start_row = 3; // 目次の記述の開始行
  var edit_start_col = 3; // 目次の記述の開始列
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); //スプレッドシートを取得
  
  // 目次シートがない場合は作り、一番前に挿入する
  var edit_sheet = spreadsheet.getSheetByName(edit_sheet_name); //目次シート取得
  if (edit_sheet === null) { //ない場合
    edit_sheet = spreadsheet.insertSheet(edit_sheet_name, 0); //スプレッドシートの0番目に目次シート生成
  }
  
  // 既存の目次が何行目まで入っているか算出する
  var plus_start_row = edit_sheet.getLastRow() - edit_start_row + 1;
  plus_start_row = plus_start_row <= 0 ? 0 : plus_start_row;
  
  // シート一覧を取得しを目次シートにリンク書き込んでいく　追加は最終行に、更新は上書き、削除・非表示は取り消し線がつく
  var sheet_list = spreadsheet.getSheets(); //シート一覧を取得（非表示も含む）
  var cell_value_list_list = [];
  if (plus_start_row > 0) { // 既存の目次がある場合
    cell_value_list_list = edit_sheet.getRange(edit_start_row, edit_start_col, plus_start_row, 1).getFormulas(); // 既存の目次一覧を取得
    edit_sheet.getRange(edit_start_row, edit_start_col, plus_start_row, 1).setFontLine('line-through'); // 取り消し線を入れる
  }
  for (var i in sheet_list) {
    var sheet = sheet_list[i];
    var sheet_id = sheet.getSheetId();
    var sheet_name = sheet.getName();
    // 目次一覧に記載するシートを選別する（目次シートと非表示シートは排除）
    if (sheet_name !== edit_sheet_name && !sheet.isSheetHidden()) {
      var function_str = '=HYPERLINK("#gid='+sheet_id+'","'+sheet_name+'")'; //リンク用関数を生成
      var edit_row = plus_start_row + edit_start_row; //最終行を指定する
      for (var j in cell_value_list_list) {
        var cell_value = cell_value_list_list[j][0];
        //既存の目次から正規表現でIDを取り出し、そのIDと一致するものがあれば書き込む行をその行に変更する
        var tmp_match_list = cell_value.match(/\#gid=\d*/);
        if (tmp_match_list !== null && '#gid='+sheet_id === tmp_match_list[0]) {
          plus_start_row--;
          edit_row = parseInt(j) + edit_start_row;
          break;
        }
      }
      edit_sheet.getRange(edit_row, edit_start_col).setFormula(function_str); //リンクの書き込み
      edit_sheet.getRange(edit_row, edit_start_col).setFontLine('none'); // 取り消し線の解除
      plus_start_row++;
    }
  }
}
```
4.スクリプトエディタの メニュー＞実行＞関数を実行＞replaceToc をクリックし、スクリプトを実行。 
　※ここで承認が求められる場合があります。 
5.実行すると、スプレッドシート側に「目次」というシートができあがります。

目次シートの目次リンク以外の列は編集して大丈夫です。
また作成したあと、シートの追加・削除、シート名の変更を行っても、本スクリプトを実行することで、

- シートの追加：一番下の行に追加したシートのリンクを追加
- シート名の更新：該当リンクの行のリンク名を修正
- シートの削除・非表示：該当リンクの行のリンクに取り消し線

といった処理の反映がされます。

# まとめ
基本的にはシートを増やしすぎないように、要件単位でスプレッドシートごとに分けることが理想です。
ただ、どうしても分けられない、多くなってしまう、といったことがあると思います。 
そういった場合に本スクリプトを使っていただければと思います。
STSのassumeRoleをLambdaで使うと、２回目以降でAccess Dinedになる件

こんな感じでLambdaに処理を実装する。

```
const AWS = require('aws-sdk')

const arn = 'arn:aws:iam::9999999:role/EXAMPLE'
const sts = new AWS.STS()
sts.assumeRole({
  RoleArn: arn,
  RoleSessionName: 'test'
}).promise().then(data => {

  AWS.config.update({
    credentials: new AWS.Credentials(
      data.Credentials.AccessKeyId,
      data.Credentials.SecretAccessKey,
      data.Credentials.SessionToken
    ),
    region: 'us-west-2'
  })
  const docClient = new AWS.DynamoDB.DocumentClient()
  return docClient.get({
    TableName: 'Test',
    Key: {
      ID: 'hello'
    }
  }).promise()
})
.then(data => console.log(data))
.catch(e => console.log(e))
```

１回目は問題なく動くが、２回目以降にこうなる。

```
{
  "message": "Access denied",
  "code": "AccessDenied",
  "time": "2019-02-18T08:18:27.089Z",
  "requestId": "c44f9f87-3355-11e9-bfa8-451bc09ebb35",
  "statusCode": 403,
  "retryable": false,
  "retryDelay": 20.810919578930864
}
```

## 原因

`AWS.config.update`で切り替えた後の情報でAWS SDKの処理が走るため、1回目と２回目以降では実行しようとしているIAMロールが異なる。
`sts.getCallerIdentity()`でAccountなどの情報を見ると、変わっているのがわかる。

## 対応

`sts.getCallerIdentity()`でどのロールを使おうとしているかわかるので、assumeRoleする必要がないときは何もしないようにすれば良い。

```javascript
const AWS = require('aws-sdk')

const getCallerIdentity = () => {
  return new Promise((resolve, reject) => {
    const sts = new AWS.STS()
    sts.getCallerIdentity((error, data) => {
      if (error) return reject(error)
      return resolve(data)
    })
  })
}

getCallerIdentity()
.then({Account} => {
  if (Account === 'YOUR_ACCOUNT_ID') return Account
  const sts = new AWS.STS()
  return sts.assumeRole({
    RoleArn: 'arn:aws:iam::9999999:role/EXAMPLE',
    RoleSessionName: 'test'
  }).promise()
}).then(data => {
  const credentials = new AWS.Credentials(
      data.Credentials.AccessKeyId,
      data.Credentials.SecretAccessKey,
      data.Credentials.SessionToken
    )
  const docClient = new AWS.DynamoDB.DocumentClient({ credentials })
  return docClient.get({
    TableName: 'Test',
    Key: {
      ID: 'hello'
    }
  }).promise()
})
.then(data => console.log(data))
.catch(e => console.log(e))

```
【学習メモ】ESXi6.0上のWindows10でブラックスクリーン

# 現象
ESXi上のWindows10でブラックスクリーンになりました。<font color="White">(真っ暗/真っ黒で検索しても全然出てこない)</font>
vmware toolsは動いているようで、再起動や停止などvSphere Client上からのコマンドは受け付けます。

vSphere Clientのコンソールでブラックスクリーンは発生します。
セーフモードでは正常に表示されます。
ブラックスクリーンにカーソルは表示されません。

# 環境
ESXiは6.0.0(build 2494585)
WindowsはWindows10 x64、2019-02-18時点のWindowsUpdateをすべて適用した状態。

# 原因
VMware SVGA 3Dのビデオドライバ。
Windows10へアップグレードするとき、互換性の問題があると出てアップデートできない原因になっていたものと同じのようです。
https://www.google.com/search?q=VMware+SVGA+3D+windows10+upgrade

# 解決方法
### Microsoft基本ディスプレイアダプターを使う
セーフモードで起動します。
通常どおり起動し始めて10秒以内にWindowsのロゴが出ている間にリセットx2回くらいすると、自動修復のモードに入ります。

```bash:ESXiコマンドで対象のVIDをリセット
vim-cmd vmsvc/getallvms
vim-cmd vmsvc/power.reset XXX
```

```text:セーフモードまでの道のり
  再起動
→ 詳細オプション

  続行
→ トラブルシューティング
  PCの電源を切る

  このPCを初期状態に戻す
→ 詳細オプション

  システムの復元
  更新プログラムのアンインストール
  イメージでシステムを回復
  スタートアップ修復
  コマンドプロンプト
→ スタートアップ設定 (セーフモード)

(再起動)

  1)デバッグを有効にする
  2)ブートログを有効にする
  3)低解像度ビデオを有効にする
→ 4)セーフモードを有効にする
→ 5)セーフモードとネットワークを有効にする
  6)セーフモードとコマンドプロンプトを有効にする
  7)ドライバー署名の強制を無効にする
  8)起動時マルウェア対策を無効にする
  9)障害発生後の自動再起動を無効にする
```

###### ディスプレイのドライバを変更する場合
ドライバーの更新→コンピューターを参照してドライバーソフトウェアを検索→コンピューター上の利用可能なドライバーの一覧から選択します→Microsoft基本ディスプレイアダプター(次へ)

###### ディスプレイのドライバを削除する場合
Windowsを右クリック→デバイスマネージャーをクリック→
ディスプレイアダプターにVMware SVGA 3Dとあるので、右クリックしデバイスのアンインストールを選択→
このデバイスのドライバーソフトウェアを削除します、も選択

### 新しいドライバ(VMware tools)を使う
6.0.0.のVMware Toolsのバージョンは9、6.5.0のVMwaretoolsはバージョンが10です。
6.5.0に含まれるドライバでは、この現象は起きませんでした。

||ESXi 6.0.0|ESXi 6.5.0|
|:--:|:--:|:--:|
|VMware Tools|9|10|
|VMware SVGA 3D Driver|8.14.1.6|8.15.1.60|

```text:インストーラーの場所
/vmfs/volumes/xxxxxxxx-xxxxxxxx-xxxx-xxxxxxxxxxxx/packages/6.0.0/vmtools/windows.iso
/vmfs/volumes/xxxxxxxx-xxxxxxxx-xxxx-xxxxxxxxxxxx/packages/6.5.0/vmtools/windows.iso
```

ただしVMware Tools 10のインストーラーを使うと、古いドライバが一度すべてアンインストールされるようです。
インストール中に出る選択肢のうち、カスタムを選択してVGAドライバのみ更新させようとしましたが、できませんでした。
VMXNET3ドライバも削除されるため、NICが一度削除され、ネットワークから切断されます。
Mysqlを5.7が入っていたパソコンにMySQL8をHomebrewで再インストールした際に起きたエラー

今回は以前homebrewでMySQL5.7を入れていたパソコンにMySQL8を再インストールした際に起きた悲しいエラー

#環境
Mac
Homebrew2.0.1
MySQL5.7

#悲劇
MySQL8に変更してJSON型のカラムの検証を行おうとしていたため、一旦5.7をアンインストール（ここで安易にコマンドを叩いただけなのが、のちの被害に繋がってしまった。）

```
$ brew remove mysql@5.7 //5.7削除
⇨/usr/local/Cellar/mysql@5.7 削除

$ brew update //アップデート
$ brew info mysql

$ brew install mysql

$ mysql.server.start
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/XXXXnoMacBook-Pro.local.pid).
```

PIDファイルが無いそうなので、エラー文に出ているファイル階層にPIDファイルを作成
そして再び実行...

```
$ mysql.server.start
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/XXXXnoMacBook-Pro.local.pid).
```

...???????????????

エラーに書いてあるファイル階層まで入り中を見てみるとPIDファイルが無い。
訳がわからない状態のままもう一度PIDファイルを作成してコマンドを叩いてみた。。がやはりコマンドを叩くたびにPIDファイルが消えてしまう。

訳がわからないので、先人たちの知恵を借りるべく安直にERROR!とか書いてある部分をコピペして流してみると、同じようなエラーが出ている人たちがたくさんいた。

# 試したこと
###権限をPIDファイルに付与する
一番多い解決方法として書かれていたのが、PIDファイルに権限が付与されていないので、書き込みができないのでエラーが出ているそう。

```
sudo chown -R [ユーザー名] usernoMacBook-Pro.local.pid
```

試しに権限を与えたのですが、やはりコマンドを叩くとPIDファイルさんがお亡くなりになられてしまう。

###mysql.sockファイルを作ってみる
mysql.sockファイルがないとそれも原因で起動しないと書かれていた。
エラー文にはそんなファイル名無いので、ほぼ諦めで作ってみたが、やはり意味がなかった。

-----
PIDファイルさんが生成されては死にを繰り返す状態が１時間続いた。
あーでもないこーでもないと続けていて、冷静に考えてみた。
errファイルがあるってことはエラーログそこに吐かれているのでは？と思い、中身をみてみるとやはり書いてあった

```
mysqld_safe mysqld from pid file /usr/local/var/mysql/usernoMacBook-Pro.local.pid ended
```
なるほど！と思い、これを検索窓へペーストして検索してみるとこのような記事にたどり着いた。
[mysqlがどうしても起動しない](https://qiita.com/_natsu_no_yuki_/items/ae4c94187093e4ab3cdc)
うん。今の僕と同じ状況だ！と思い藁にもすがる思いで読んでみた。

> /usr/local/var/mysql も削除
仕方ない、こちらも削除。DBの実体なんかも含まれているが、丸っと削除（データが無くなると困る場合は、DBと同名のファイルを退避させるなど）

> ```
$ sudo rm -rf /usr/local/var/mysql
$ brew uninstall mysql
$ brew install mysql
```

あ。これもしかしてHomebrewではローカルデータは消してくれないの？とそこで気づき、同じようにローカルデータファイルを削除。
そして起動コマンドを叩いてみると。。。

```
mysql.server start
Starting MySQL
 SUCCESS! 
```

本当に助かりました。。



###### 記事に間違っている部分などありましたらコメントお願いします。
備忘録 : RAD Studio/Delphi/C++Builder のアンインストール

RAD Studio/Delphi/C++Builder で、たとえばトライアル版や Community Edition を製品版と混在させた場合など、環境をクリアするための記事がバージョン毎に用意されています

各バージョンのアンインストール記事へのリンクを備忘録として記しておきます

- [RAD Studio/Delphi/C++Builder 10.3 Rio の手動アンインストール](http://support.embarcadero.com/article/44786)
- [RAD Studio/Delphi/C++Builder 10.2 Tokyo の手動アンインストール](http://support.embarcadero.com/article/44752)
- [RAD Studio/Delphi/C++Builder 10.1 Berlin の手動アンインストール](http://support.embarcadero.com/article/44691)
- [RAD Studio/Delphi/C++Builder 10 Seattle の手動アンインストール](http://support.embarcadero.com/article/44574)
- [RAD Studio/Delphi/C++Builder XE8 の手動アンインストール](http://support.embarcadero.com/article/44399)
- [RAD Studio/Delphi/C++Builder XE7 の手動アンインストール](http://support.embarcadero.com/article/44095)
- [RAD Studio/Delphi/C++Builder XE6 の手動アンインストール](http://support.embarcadero.com/article/43931)
- [RAD Studio/Delphi/C++Builder XE5 の手動アンインストール](http://support.embarcadero.com/article/43392)
- [Delphi/C++ Builder XE4 の手動アンインストール](http://support.embarcadero.com/article/43095)
- [Delphi/C++Builder XE3 の手動アンインストール](http://support.embarcadero.com/article/43028)
- [Delphi/C++Builder XE2 の手動アンインストール](http://support.embarcadero.com/article/43029)
- [Delphi/C++Builder XE の手動アンインストール](http://support.embarcadero.com/article/43030)
- [Delphi/C++Builder/RAD Studio 2010 のアンインストール](http://support.embarcadero.com/article/40533)
- [Delphi/C++Builder/RAD Studio2009 のアンインストール](http://support.embarcadero.com/article/38836)
- [RAD Studio (2007) のアンインストール](http://support.embarcadero.com/article/37469)
Gitのコミット数と行数を確認する

Gitで自分のコミット数を計測したいときありますよね。
そんなときに使ったコマンドを残しておきます。
私のGitのアカウントは、noracornなのでそこは読み替えてください。

## 全体のコミット数を確認するコマンド
リポジトリ内に移動して打ってください。

```
git log --date=iso --pretty=format:"[%ad] %h %an : %s" | grep  "noracorn :" | wc -l
```

## 月ごとのコミットを見るコマンド

```
git log --date=iso --pretty=format:"[%ad] %h %an : %s" | grep  "noracorn :" | grep 2019-01 | wc -l
```

## 修正した行数を見るコマンド（合計行数、追加行数、削除行数）

```
git log --numstat --pretty="%H" --author='noracorn' --since=2013-01-11 --until=2019-01-01 --no-merges | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("%d (+%d, -%d)\n", plus+minus, plus, minus)}'
```
PwC’s サイバーセキュリティ体験イベント

<!--Event_page-->
## 概要
サイバー攻撃は、デジタルビジネスの発展に伴い、複雑化・多様化しており、グローバルで社会的な課題となっています。
本イベントは、PwCのコンサルタントがクライアント向けに提供している、サイバー攻撃を疑似体験する対戦型ゲーム「Game of Threats™」を用い、サイバーセキュリティの重要性、企業のリスク感覚を体感するイベントです。是非、ご参加ください！

### 「Game of Threats™」とは・・

PwCが、CEOやCIO、CISO（最高情報セキュリティ責任者）などの経営層に対して
提供している、サイバー攻撃の脅威を疑似体験できる対戦型ゲームです。
本プログラムを通じて、世界の経営者が経営課題の一つとして捉えている
サイバーセキュリティの重要性を体感頂けます。

[![動画を開くことができませんでした。](https://i.ytimg.com/vi/qAfwCEHLxko/mqdefault.jpg)](https://youtu.be/qAfwCEHLxko)


2016年、学生の皆さま向けに開催したイベントでは、「サイバーセキュリティの難しさ、奥深さ、楽しさが分かり、今後も学びたいと感じた。」「学生にとって情報を守ることを意識する機会が少ないので、とても貴重な経験であった。」「企業の限られた予算の中で見えない敵の攻撃を防ぐことの難しさを体感できた。」など非常に高い評判を頂いています。

※株式会社マイナビの運営する大学生向けキャリアサイトに掲載頂いております。
https://mycampus.jp/2017/05/29/pwc2016_report/

### こんな人にぜひ！
- 社会的に重要な課題の解決に取り組みたい人
- サイバーセキュリティに興味がある人
- テクノロジーに興味がある人
- サイバーセキュリティの仕事を体験してみたい人
- ご自身のテクニカルスキルを試してみたい人

## 実施詳細
- 実施日時：2019年3月6日(水)18:00-21:00 
    - 第一部、第二部、ご都合よい方をお選びください。
    - 座談会は自由参加ですので、途中退席、途中参加が可能です。
    - 第一部：
        - 18:00-19:30（Game of Threats体験）
        - 19:30-21:00（先輩社員との座談会）
    - 第二部：
        - 18:00-19:30（先輩社員との座談会）
        - 19:30-21:00（Game of Threats体験）
- 実施場所：PwCコンサルティング合同会社　丸の内パークビルディング21F（※1）
- 服装：自由（※2）
- 定員：第一部、第二部、それぞれ約10名（※3）
- 参加資格：2020年3月卒業/修了見込みかつ2020年4月/10月入社が可能な方
- 応募方法：当社採用ウェブサイトのマイページに登録後、イベントにエントリー
    - 当社採用ウェブサイトURL：https://job.axol.jp/bw/st/i/pwc_20/login/
- 応募締切：2019年2月27日(水)23:59

（※1）交通費の支給はございませんので、予めご了承ください。 
（※2）ぜひカジュアルな服装でお越しください。
（※3）応募者多数の場合、抽選となります、予めご了承ください。
AWS認定試験 Cloud Practitoner 合格体験記

受験してきたのでまとめてみました。

# 背景・目的 
業務でAWSを利用していたので技術アピールするため 

# AWS実務経験 
3ヶ月

# 勉強期間 
10時間 程度

# 勉強内容 
公式サイトのサンプル問題 
模擬試験 
AWSトレーニング 
 AWS Cloud Practitioner Essentials (Digital) (Japanese) (デジタル) (日本語版)
 https://www.aws.training/learningobject/curriculum?id=17954

# 感想
システム構築経験があれば問題なく合格できると思います。
AWSの想定受験者として、「AWS経験半年」を想定しているが、それ未満でも十分合格可能である。
tmuxで色がおかしいとき

以下のconfファイルを書く

```
vim ~/.tmux.conf
```
```
set -g default-terminal "screen-256color"
set -g terminal-overrides 'xterm:colors=256'
```

fishでヒアドキュメント

```
string trim '
set -g default-terminal "screen-256color"
set -g terminal-overrides 'xterm:colors=256'
' > ~/.tmux.conf
```



# memo 

Hyperターミナルを使っていて、Hyperターミナル側で色を付けているので、vimrc側のhybridカラーをコメントアウトするとよい
proxy_set_header Hostで設定するNginxの変数一覧

備忘です。


`ngx_http_proxy_module` モジュールの
`proxy_set_header Host` で設定するNginxの変数一覧

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">名称</th>
<th scope="col" class="org-left">概要</th>
</tr>
</thead>

<tbody>
<tr>
<td class="org-left">$http_host</td>
<td class="org-left">リクエストヘッダのHTTP_HOSTの値</td>
</tr>


<tr>
<td class="org-left">$host</td>
<td class="org-left">リクエストヘッダのポート番号を除いたHTTP_HOSTの値<br>
もし、HTTP_HOSTが存在しない場合、リクエストを処理したサーバの `server_name` ディレクティブに書かれたサーバ名となる</td>
</tr>



<tr>
<td class="org-left">$proxy_host</td>
<td class="org-left">proxy_passディレクティブに書かれたプロキシされるサーバ名とポート番号</td>
</tr>
</tbody>
</table>

デフォルトは下記

```nginx:nginx.conf
proxy_set_header  Host  $proxy_host;
proxy_set_header  Connection  close;
```
rails mysql2のインストール時のエラー

gemのmysql2をインストールする際にハマったのでメモ

エラーログ

```
Fetching mysql2 0.3.21
Installing mysql2 0.3.21 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /path/to/vendor/bundle/ruby/2.4.0/gems/mysql2-0.3.21/ext/mysql2
/path/to/.rbenv/versions/2.4.1/bin/ruby -I /path/to/.rbenv/versions/2.4.1/lib/ruby/site_ruby/2.4.0 -r ./siteconf20190218-87873-15epx9f.rb extconf.rb
--with-cppflags\=-I/usr/local/opt/openssl/include
checking for ruby/thread.h... yes
checking for rb_thread_call_without_gvl() in ruby/thread.h... yes
checking for rb_thread_blocking_region()... no
checking for rb_wait_for_single_fd()... yes
checking for rb_hash_dup()... yes
checking for rb_intern3()... yes
-----
Using mysql_config at /usr/local/opt/mysql@5.7/bin/mysql_config
-----
checking for mysql.h... yes
checking for errmsg.h... yes
checking for mysqld_error.h... yes
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /usr/local/opt/mysql@5.7/lib
-----
creating Makefile

current directory: /path/to/vendor/bundle/ruby/2.4.0/gems/mysql2-0.3.21/ext/mysql2
make "DESTDIR=" clean

current directory: /path/to/vendor/bundle/ruby/2.4.0/gems/mysql2-0.3.21/ext/mysql2
make "DESTDIR="
compiling client.c
compiling infile.c
compiling mysql2_ext.c
compiling result.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /path/to/vendor/bundle/ruby/2.4.0/gems/mysql2-0.3.21 for inspection.
Results logged to /path/to/vendor/bundle/ruby/2.4.0/extensions/x86_64-darwin-18/2.4.0-static/mysql2-0.3.21/gem_make.out

An error occurred while installing mysql2 (0.3.21), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.3.21' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  mysql2
```

パスが通っていないのが原因

```
bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
```
Numpyで実装する線形代数の行列

自分用のメモも兼ねて、基礎的な行列の足し算と掛け算などをNumpyで実装してみたメモです。

## 行列の足し算

同じ行と列同士の足し算

```math
\begin{pmatrix}
2 & 4 \\
0 & 4 \\
7 & 9 \\
3 & 7 
\end{pmatrix}
+
\begin{pmatrix}
9 & 2 \\
4 & 1 \\
1 & 7 \\
0 & 2 
\end{pmatrix}
=
\begin{pmatrix}
11 & 6 \\
4 & 5 \\
8 & 16 \\
3 & 9 
\end{pmatrix}
```

それぞれが違う行と列では計算はできない
2 x 3の行列と4 x 2の行列の足し算は不可能

```math
\begin{pmatrix}
1 & 3 & 7 \\
2 & 9 & 0 \\
\end{pmatrix}

+

\begin{pmatrix}
9 & 2 \\
4 & 1 \\
1 & 7 \\
0 & 2 
\end{pmatrix}

```

上記の行列の足し算をnumpyで実装すると以下のようになります。

```python
import numpy as np

arr1 = np.array([[2, 4], [0, 4], [7, 9], [3, 7]])
arr2 = np.array([[9, 2], [4, 1], [1, 7], [0, 2]])

print(arr1)
# [[2 4]
#  [0 4]
#  [7 9]
#  [3 7]]

print(arr2)
# [[9 2]
#  [4 1]
#  [1 7]
#  [0 2]]

result = arr1+arr2
print(result)
# [[11  6]
#  [ 4  5]
#  [ 8 16]
#  [ 3  9]]

```

## 行列のスカラー倍
それぞれの値を定数倍する。

```math
6
\times
\begin{pmatrix}
1 & 3 & 7 \\
2 & 9 & 0 \\
\end{pmatrix}

=
\begin{pmatrix}
6 & 18 & 42 \\
12 & 54 & 0 \\
\end{pmatrix}


```

上記の行列のスカラー倍の式をnumpyで実装すると以下のようになります。

```python
import numpy as np

arr1 = np.array([[1, 3, 7], [2, 9, 0]])
print(arr1)
# [[1 3 7]
#  [2 9 0]]

result = arr1 * 6
print(result)
# [[ 6 18 42]
#  [12 54  0]]

```


```math
\begin{pmatrix}
6 & 3 \\
0 & 1 \\
\end{pmatrix}
\div
3
=
\begin{pmatrix}
6 & 3 \\
0 & 1 \\
\end{pmatrix}
\times
\frac{1}{3}
=
\begin{pmatrix}
2 & 1 \\
0 & 1/3 \\
\end{pmatrix}

```

```python
import numpy as np

arr1 = np.array([[6, 3], [0, 1]])
print(arr1)
# [[6 3]
#  [0 1]]

result = arr1 / 3
print(result)
# [[ 2 1]
#  [ 0 0.33333333]]

```


行列の足し算と引き算、スカラー倍を混ぜた計算


```math
5
\times
\begin{pmatrix}
2 \\
1 \\
0 \\
3 \\
\end{pmatrix}
-
\begin{pmatrix}
4 \\
2 \\
3 \\
1 \\
\end{pmatrix}
+
\begin{pmatrix}
6 \\
0 \\
3 \\
12 \\
\end{pmatrix}
\div
6
\\

=
\begin{pmatrix}
10 \\
5 \\
0 \\
15 \\
\end{pmatrix}
-
\begin{pmatrix}
4 \\
2 \\
3 \\
1 \\
\end{pmatrix}
+
\begin{pmatrix}
1 \\
0 \\
1/2 \\
2 \\
\end{pmatrix}
\\
```

上記の行列式の最終的な答えは以下になる。

```math
=
\begin{pmatrix}
7 \\
3 \\
-2.5 \\
16 \\
\end{pmatrix}

```
ショートカット色々

# Visual Stdio Code
* 一般的なエディタ操作等は下記にわかりやすくまとめられている  
  [【Mac版】 VisualStudioCode キーボードショートカット](https://qiita.com/naru0504/items/99495c4482cd158ddca8)

* 個人的にすぐに確認したい用のメモ 
 
|OS|機能|ショートカット|備考|
|---|---|---|---|
|mac|コードフォーマット|shift＋option＋F|【拡張機能】Prettier - Code formatter|
|mac|htmlのライブプレビュー|ctrl＋q,s|【拡張機能】Live HTML Previewer|
|mac|htmlをブラウザで起動|cmd＋L,cmd+O|【拡張機能】Live Server|
|mac|選択行の移動|option+↑または↓||
|mac|選択行のコピペ|shift+option+↑または↓||
Azure のシリアルコンソールを使って Linux OS の ブートメッセージ を見られないときのトラブルシューティング

#はじめに
Azure では[シリアルコンソールを利用してシングルユーザモードになれたりする](https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/serial-console-grub-single-user-mode) のだが、ブートメッセージが出てこなかったため、原因と対策を考える

#事象
過去に作ったCentOS 7.3 を利用して発生。シリアルコンソールを繋ぎながら再起動してもブートメッセージの画面が出てこない。
下記は最新の CentOS 7.5 をマーケットプレイスから作成して同じ操作をして出てくる画面
![image.png](https://qiita-image-store.s3.amazonaws.com/0/125247/22193546-e538-3dd2-30b2-ce1347937f46.png)

#原因
/boot/grub2/grub.cfg を比較すると、新しいマシンの方にいくつか古い方に見られない行があった。

```shell-session
# sdiff grub.cfg_cent75 grub.cfg_cent73

(中略)

serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1  | terminal_output console
terminal_input serial console                                 <
terminal_output serial console                                <

(後略)
```



以下のサイトによると、シリアルデバイスのイニシャライズができていなかったから...？
https://www.gnu.org/software/grub/manual/grub/grub.html#serial

CentOS 7.3 でもシリアルコンソール自体はできるが、起動時にブートメッセージを表示するにはこの行が必要なのかもしれない。

```shell-session
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
```

#対策
当該行を grub.cfg に追記したら無事にブートメッセージが表示されるようになった。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/125247/20bf634b-08fc-cbcc-ccad-9887d763f8c0.png)

参考になれば幸いです。
指定した何れかのURLパラメータのパターンにマッチしていることを検証するスクリプト

Webサイトへのアクセスがあったとき、
URL内のGETパラメータがこちらの指定したパターンの何れかにマッチすればTRUEを返すスクリプト。
変数`TARGET_SEARCH_PATTERN`に目的のパラメータの組み合わせを入力することによって使用する。

## 使用用途
- 特定のGETパラメータを持ってWebサイト訪問したユーザーを識別してポップアップを表示する
- 特定のGETパラメータを持ってWebサイト訪問したユーザーにCookieを付与し、計測対象から除外する

## コード
```js:
(function(){
  // TARGET_SEARCH_PATTERN で指定したパターン配列の何れかがマッチすればTRUEを返す
  var TARGET_SEARCH_PATTERN = [
    {'ref':/^google$/}, // URLのGETパラメータにref=googleを含んでいるならTRUE
    {'utm_medium':/^email$/,'utm_source':/^premium_.*$/}, // パラメータ"utm_medium"が"premium_"で始まればTRUE
    {'utm_medium':/^cpc$/,'utm_source':/^(google|yahoo)$/},  // パラメータ"utm_medium"が"cpc"でかつ、"utm_source"が"google"か"yahoo"であればTRUE
    {'utm_medium':/^cpm$/,'utm_source':/^facebook$/},
  ];

  var searchDic = getSearchDictionary(location.search);
  var flag = false;
  if(Object.keys(searchDic).length > 0){
    for(var i = 0; i < TARGET_SEARCH_PATTERN.length; i++){
      flag = false;
      for(var query in TARGET_SEARCH_PATTERN[i]){
        if(query in searchDic && hasTargetSearchValue(searchDic[query],TARGET_SEARCH_PATTERN[i][query])){
          flag = true;
        }else{
          flag = false;
          break;
        }
      }
      if(flag){return true;}
    }
  }
  return false;

  function getSearchDictionary(queryString){
    var s = queryString.split('&');
    var sDic = {};
    if(s.length > 0){
      s[0] = s[0].slice(1);
      for(var i = 0; i < s.length; i++){
        if(!(s[i].split('=')[0] in sDic)){
          sDic[s[i].split('=')[0]] = [s[i].split('=')[1]];
        }else{
          sDic[s[i].split('=')[0]].push(s[i].split('=')[1]);
        }
      }
    }
    return sDic;
  }
  function hasTargetSearchValue(qVals,valPattern){
    var flag = false;
    for(var i = 0; i < qVals.length; i++){
      if(valPattern.test(qVals[i])){
        flag = true;
      }
    }
    return flag;
  }
})();
```
Gitで一つ前にチェックアウトしていたブランチに移動する`git checkout -`というコマンドに感動したお話

## 背景
最新のmasterを開発中のブランチに取り込んだり、他の人が開発中のブランチを取得する時、一度ブランチをチェックアウトしてすぐ元の作業ブランチに戻る、といった事をすることがあるかと思います。
私は今まで`git checkout master`→`git pull origin master`→`git checkout my_branch`→`git merge master`としていました。
そして、開発中のブランチ名ってなんだったっけ・・？えーと・・・あ、これこれ。となっていたのです。

## `git checkout -`
一つ前のディレクトリに戻る`cd -`コマンドのように、一つ前にチェックアウトしていたブランチに移動する`git checkout -`というコマンドが存在することを10分前に初めて知りました。
上記のコマンドが以下のようになります。
`git checkout master`→`git pull origin master`→`git checkout -`→`git merge master`

## 何が嬉しいのか
「開発中のブランチ名を確認する」という小さなタスクの存在がなくなりました。
こういう小さなワンアクションが消える事に喜びを感じるマンなので軽いパラダイムシフトですね。

みなさんも`git checkout -`で良いGitライフを！
DonkeyCar 教師データを可視化（旧バージョン2.5.8）

#目的
コースを手動で走らせて生成したjpeg画像にスロットルとステアリングのデータを表示する．
緑線の縦の長さがスロットル，左右の長さがステアリングの値．

#準備
ホストPCにopencvが入ってなければインストールする．
(donkey)$ pip install opencv-python

#教師データを加工
加工したいtubフォルダのあるフォルダで以下のプログラムを実行する．

```python:TubVisualize.py
#!/usr/bin/env python3
"""
Usage:
    TubVisualize.py [--src <src>] [--dst <dst>]

Options:
    -h --help
    --src <src> sorce directory [default: ./tub].
    --dst <dst> distination directory [default: ./tub2].
"""

import os
from docopt import docopt
import json
import cv2

if __name__ == '__main__':
    args = docopt(__doc__)

    if args['--src']:
        src = args['--src']
    else:
        src = './tub'

    if args['--dst']:
        dst = args['--dst']
    else:
        dst = './tub2'

    print(src)
    print(dst)

    if not os.path.isdir(dst):
        os.mkdir(dst)

    lineColor = (0,255,0)
    lineThickness = 2
    textOrg = (0,120)
    textFontFace = cv2.FONT_HERSHEY_SIMPLEX
    textFontScale = 1
    textColor = (255,255,255)
    textThickness = 1

    cv2.namedWindow('DonkeyCam', cv2.WINDOW_NORMAL)

    num = 0
    while num < 100000:

        if os.path.exists(src+'/record_'+str(num)+'.json'):
            if os.path.exists(src+'/'+str(num)+'_cam-image_array_.jpg'):

                fp = open(src+'/record_'+str(num)+'.json','r')
                json_data = json.load(fp)
                fp.close()

                fp = open(dst+'/record_'+str(num)+'.json','w')
                json.dump(json_data, fp)
                fp.close()

                throttle = json_data["user/throttle"]
                angle = json_data["user/angle"]
                timestamp = json_data["timestamp"]

                img = cv2.imread(src+'/'+str(num)+'_cam-image_array_.jpg')
                cv2.line(img,(int(round(160/2+160/2*angle)),int(round(120-120*throttle))),(int(160/2),120),lineColor,lineThickness)
                cv2.putText(img, str(num),textOrg,textFontFace,textFontScale,textColor,textThickness)
                cv2.imwrite(dst+'/'+str(num)+'_cam-image_array_.jpg',img)

                cv2.imshow('DonkeyCam',img)
                cv2.waitKey(1)

        num += 1

    if os.path.exists(src+'/meta.json'):
        fp = open(src+'/meta.json','r')
        meta_json = json.load(fp)
        fp.close()

        fp = open(dst+'/meta.json','w')
        json.dump(meta_json, fp)
        fp.close()

    cv2.destroyAllWindows()

```
(donkey)$ python TubVisualize.py
tub2フォルダが出来るのでそれを makemovie する．
【GoogleCloudPlatform】既存のインスタンスにGPUを追加する

東京リージョンでもGPUが使えるようになったけど、新しくインスタンスを立てなおして諸々の設定を最初からやるのは面倒！となったので、既存のインスタンスでGPUを使えるようにどうにか設定しました。
パッケージのバージョンを変更したりなんだかんだあるので、**バックアップ推奨**です。

#環境
CentOS 7.6
python 3.5

# インスタンスのマシン構成を変更する
インスタンスを起動している場合は停止させて、インスタンスの編集画面へ。
編集画面のマシンタイプのところのカスタマイズを選択すると"GPUの数"が選べるようになる。

![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/262969/0c623145-b7fc-0dba-ec88-857b1da50b60.jpeg)

ここで好きなGPU数とタイプを選択し画面一番下の"保存"を選択。
今回は**Tesla-T4**を選択した場合の環境設定手順について書きます。GPUタイプが異なる場合は適宜読み替えてください。
＊現在GPUに対応しているリージョンは限られているので注意。もし対応していないリージョンでインスタンスを立てていたら（GPUの選択項目が出てこなければ非対応の可能性高）一旦ディスクイメージを取ってインスタンスを立て直すのが早いかと思います。

ここまで設定したら、もう一度 "開始"＞"起動" でインスタンスを起動。

# ドライバダウンロード
まずはOSのバージョンを確認。
```$cat /etc/redhat-release```

念のためcuda-9-0が未インストールなことも確認しておきます。
```$rpm -q cuda-9-0```

NVIDIAのページからCUDAtoolkitをダウンロードしてきます。
```$curl -O http://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-repo-rhel7-9.0.176-1.x86_64.rpm```

システムにリポジトリを追加
```$sudo rpm -i --force ./cuda-repo-rhel7-9.0.176-1.x86_64.rpm```

epel-releaseリポジトリをインストール
```$sudo yum install epel-release```

Yumキャッシュ削除
```$sudo yum clean all```

CUDA9.0のインストール
```$sudo yum install cuda-9-0```

CUDA9.0にドライバが含まれるとの記載もあったが、自身の環境ではうまく動かなかったので手動でNVIDIAドライバをダウンロード。（もしかしたら冗長なのかも。）
```$curl -O http://jp.download.nvidia.com/tesla/410.79/NVIDIA-Linux-x86_64-410.79.run
$sudo sh NVIDIA-Linux-x86_64-410.79.run
```

永続モードを有効にする
```$nvidia-smi -pm 1```
＊ここで以下のようなエラーが出た場合はインスタンスの再起動を試してみる
>NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running

ここまででインスタンスでGPUを使うための準備完了。
ここからはtensorflow/kerasでGPUを使うための準備をする。

#cuDNNのダウンロード
以下のサイトでcuDNNをダウンロードする。
今回はlinuxの9.0バージョンを選びました。
https://developer.nvidia.com/rdp/cudnn-download

インスタンス上にダウンロードしたフォルダを配置したらまずは解凍。
```$ tar -xvzf cudnn-9.0-linux-x64-v7.4.2.24.tgz 
```

そんでもってPATHを追加しておきます。
```$export CUDA_ROOT="/usr/local/cuda"```
```$export LIBRARY_PATH=$CUDA_ROOT/lib:$CUDA_ROOT/lib64:$LIBRARY_PATH  ```
```$export LD_LIBRARY_PATH=$CUDA_ROOT/lib64/```
```source ~/.bash_profile```

#tensorflow-gpuの導入
地味にこれが面倒だった。パッケージのバージョンはかなり注意しないとという教訓。
このあたりは各自の環境によってもかなり変わるかと思うので、自身の環境を確認しつつ実行してください。

anacondaを使用の場合は以下のコマンドで今の仮想環境のパッケージを確認出来ます。
```$ conda list```

ここでtensorflowと表示される場合は注意。tensorflow-gpuとは共存出来ないようなので一旦アンインストールする必要がある。（pip経由でインストールした場合はpipコマンドで削除）
```$conda uninstall tensorflow```

そしてtensorflow-gpuをインストール。最新版のtensorflow-gpuだとエラーになったので、バージョン1.8.0のものを取ってきます。
```$conda install tensorflow-gpu==1.8.0
```

#確認
ここまでで準備は全て出来ました。
動作確認したい場合は以下のコードを実行してみてください。keras使ってる人は念のためそちらも確認しておいた方が良さそうです。

```python

import tensorflow as tf
# Creates a graph.
with tf.device('/device:GPU:0'):
  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
  c = tf.matmul(a, b)
# Creates a session with allow_soft_placement and log_device_placement set
# to True.
sess = tf.Session(config=tf.ConfigProto(
      allow_soft_placement=True, log_device_placement=True))
# Runs the op.
print(sess.run(c))
```

参考：https://www.tensorflow.org/guide/using_gpu
【超マニアック資格】WinActorのRPA技術者検定アソシエイト資格試験に合格

RPAの資格って無いんだね。最近流行ってきたから当たり前か。
Qlitaのタグにもあんまない。ロボットというか自動操作の概念時代は存在してるのにね。
それこそマクロの開発タブとか、、、

余談はさておき、日本のIT業界の癌であるNTTデータ様が資格を作ってくれたよ。
http://watest.jp/

ぶっちゃけRPAなんて聞こえの良い言葉で、泥臭くマウスが自動的に動いて業務を代理してくれるやつ。
MouseControllerなんかのフリーソフトでDMMソシャゲのリセマラに便利だな程度しか考えてなかった。
↓便利です。
https://freesoft-100.com/review/mousecontroller.html

なんか資格の合格記これくらいしか無かったからQlitaに書いておく。
上の2つは超参考になる。
https://ciprogram.jp/rpa/learn_rpa_associate/
https://ciprogram.jp/rpa/lern_rpa_2/
https://ciprogram.jp/rpa/get_rpa_associate/

家で書くほどやる気はないが、業務中はコードを書くタイプ。
そういう運用監視オペにはWinActorは最強だと思う。
NTT系列の会社なら何か推してるらしいから多分言えば買ってくれると思う。
ただライセンス料が高いから客との交渉は頑張ってくれ。
UiPathなんて無料なのにね。まぁ英語だけど。これもコード書かなくて良いのは良いね。
ただシナリオ作るよりVBAとかで組んだ方が早いこともあるからRPAは難しい。

そして、
※やったこと※
・eラーニングの動画見る
（最後の模擬問題はまんまでるから全部暗記したほうがいい、正直笑った）
http://watest.jp/standard.html
・ホームページのあらゆるところを読んでおく、トップの動画とかFAQとか、フォーラムとか。
https://winactor.com/
・会社や現場にあるなら実際にいじってみる（あんま必要無いかもしんね）
普段使ってるなら1日でアソシエイトは合格できると思う、操作マニュアルも流し見程度に。
・エキスパートの本とか買うのもありかも知れない（アソシエイト飛び越えてこっちからもあり）
https://ec.athuman.com/products/detail/472

※おわり※

履歴書に書けるのかなこれ…簡単すぎたからなんかどうも…
ただRPA技術者の求人増えてきてるからアリかもしれない。
一応発行元がベンダー資格とはいえNTTデータだから半分国家資格やろ（？）
データ系列の会社だと推奨資格らしい、報奨金チャンス。
Solidityでstructをreturnする

## privateとinternalはそのまま返せる
privateかinternalの修飾詞がついた関数の場合は、特に注意しなくてもstructをreturnできる。

```
struct UserInfo {
  ...
}

mapping(uint256 => UserInfo) internal _userIdToUserInfo;

function getUserInfo(uint256 _userId) internal view returns (UserInfo memory) {
  return _userIdToUserInfo[_userId];
}
```

注意：
solidity 0.5.4でのコードです。
0.4.xの場合は、returnする値にストレージ領域を指定しません。
`returns (UserInfo memory)` -> `returns (UserInfo)`

## externaとpublicは、ABIEncoderV2を指定する
solidity外部にstructを返す場合は、ABIEncoderV2を指定する必要がある。

```
pragma experimental ABIEncoderV2;
```

こうすることでstructを外部にも返せるようになり、web3からも参照できるようになる。

## ABIEncoderV2 を使うことによるWarning
ABIEncoderV2を指定することで、以下の「実験的なやつだからlive deploymentでは使わないで」というWarningが出てしまう。
`Experimental features are turned on. Do not use experimental features on live deployments.`

この注意は何を指しているのか。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">現状、solidityの関数でstructを返す場合ABIEncoderV2を指定する必要があるが、これを指定するとコンパイラに「live deploymentsでは使わないで」と注意される。ただ、これはセキュリティ上の問題ではなく、gasの使用量が多くなることへの注意らしい。<a href="https://t.co/eB7VknHaHL">https://t.co/eB7VknHaHL</a></p>&mdash; こみー / Ryo Komiyama (@ryoheikomy) <a href="https://twitter.com/ryoheikomy/status/1097374389954179072?ref_src=twsrc%5Etfw">2019年2月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

twitterに書いたので引用しますが、これはセキュリティに対するwarningではなく、gasの使用量が増加することに対するwarningだそうです。
そのため、「本番環境では使えないから結局structは要素ごとにreturnするしかないのか」となる必要はなく、「gasかかるっぽいから、どのくらいかかるか試してから使うかどうか決めよう」と考えれば良さそうです。

## まとめ
Solidityでstructをreturnするときは、以下のようにABIEncoderV2を指定しましょう。

```
pragma experimental ABIEncoderV2;
```
Linux初心者がとあるプロジェクトで手順書が無いサーバーの構築を命じられたときに使用したコマンドをまとめた

Linux初心者に突然以下の仕事が振られました．

- 試験環境サーバー構築
- シェルの要所要所でログを出すようにする

今回構築するサーバーはなんと本番環境しかなく，まともな手順書がないっていうもう残念な感じでした．
そんな中でもtry & errorでなんとか構築できたのでその際に使用したコマンドたちを備忘録としてさらします．

### パッケージ管理

#### パッケージインストール

```bash
sudo apt-get install apache2
```

### パッケージ削除

```bash
sudo apt-get remove apache2
```

### パッケージ管理更新

```bash
sudo apt-get update && sudo apt-get upgrade
```

### パッケージ完全削除

- 設定ファイルごと削除する

```bash
sudo apt-get purge apache2
```


### ファイル操作

#### ファイルコピー

- /usr/local に tmpsrc ファイルがごそっと入る

```bash
sudo cp -r /tmp/tmpsrc /usr/local
```

### ディレクトリ操作

#### ディレクトリ作成

- ディレクトリ作成(-pで親ディレクトリがなくてもエラーメッセージを出さずにディレクトリを作る)

```bash
mkdir -p testdir
```

#### カレントディレクトリ表示

```bash
pwd
```

### 解凍

#### tar.gzの解凍

```bash
tar -zxvf xxxx.tar.gz
```

#### .tgzの解凍

```bash
tar xvzf xxxx.tgz -C /tmp/tmpsrc
```

### 所有権変更

```bash
# -Rでディレクトリの中身も含めて再帰的に処理する
# 所有者をtestuserに，所有グループをrootにする
chown -R testuser:root /home/testuser/example01 /home/testuser/example02
```

### ログイン

#### ディレクトリを変えずにログインする

```bash
su testuser
```

#### ディレクトリをユーザーのルートに切り替えてログインする

```bash
su - testuser
```

### ユーザー

#### ユーザー作成

```bash
sudo useradd testuser
```

#### ユーザー削除

```bash
sudo userdel testuser
```

#### ユーザー一覧

```bash
cat /etc/passwd
```

### グループ

#### グループを作成

```bash
sudo groupadd testuser
```

#### グループを削除

```bash
sudo groupdel testuser
```

#### グループ一覧

```bash
cat /etc/group
```

### FW

#### FWインストール

```bash
sudo apt install firewalld
```

#### FWポート開放

```bash
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
```

#### FW設定反映

```bash
sudo firewall-cmd --reload
```

### パーミッション

#### パーミッション設定

| モード(数字) | モード(アルファベット) |権限      |
|--------------|------------------------|----------|
| 4            | r                      | 読み取り |
| 2            | w                      | 書き込み |
| 1            | x                      | 実行     |

「所有者」「所有グループ」「その他」の順に権限をモードの合計値で設定する．

```bash
chmod 777 /tmp/test.txt
```

#### パーミッション確認

```bash
ls -l
```


### cron

コマンドやシェルスクリプトを定期的に自動実行するデーモン．

#### cron.d

- /etc/cron.d 配下に設定を追加する

```bash
sudo cp /etc/crontab /etc/cron.d/cron_test
vi /etc/cron.d/cron_test
```

```bash
# m h dom mon dow user  command
# 10分ごとに実行する
*/10 * * * *   userA echo "hello new world!"
```


### その他

#### スクリーン初期化

``` bash
clear
```

#### 環境変数設定

```bash
export HOGE=aiueo
```

### ロギング

- コマンドの実行履歴をファイルに出力する．

```bash
script /tmp/20190207.log
```

- ロギングをとめる

```bash
exit
```

- 自作ロガー

```bash
#!/bin/bash
#
# 指定したファイルにログを出力します。
#
# Example:
#   . ./logger.sh
#   write_log "/tmp/sample.log" "this is test."
# 
# Args:
#   $1 - ログ出力先
#   $2 - ログメッセージ
#
# Return:
#   0
#
function write_log() {
  nowd=`date '+%Y/%m/%d'`
  nowt=`date '+%H:%M:%S'`
  echo "${nowd} ${nowt}: $2" >> $1
  return 0
}
```
ERC725に関する簡単なまとめ

##ERC725とは？
人物、組織、物質、マシンなど様々なもののアイデンティティーを定義できる。

##なぜERC725が必要なのか？
アイデンティティーの中央集権は、データの漏洩や不当に売られるなどの負の側面があるため、自分自身のアイデンティティーは自分自身でアンリする必要があるため

##ERC725認証と確認の手順 
###認証
1. 様々なIDを管理する箱のようなIdentity Contractデプロイする 
2. 付け足したいIDを認証機関にClaimする 
3. 暗号署名を受け取る 
4. 署名を受け取りID Contractに保存する 

###確認 
1. 署名にある公開鍵が発行元のコントラクトに存在しているかを検証 
2. 確認が取れたらOK

参照URL
https://erc725alliance.org/
https://medium.com/originprotocol/managing-identity-with-a-ui-for-erc-725-5c7422b38c09
https://erc725.originprotocol.com/#/
SORACOM Lagoon の Free プランが出たので、プラン変更するときの注意点

先日 2/14（木） の [if-up 2019](https://if-up2019.soracom.jp/) において、[SORACOM Lagoon](https://soracom.jp/services/lagoon/) の無料利用枠（Free プラン）が発表されましたが、その発表の最中、実はしれっと Maker プランから Free プランへの移行をしていました~~（実況枠の中の人実況しろ）~~

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">流石に下位プランへ変更はできないから、いったんLagoonを終了してからだなー <a href="https://twitter.com/hashtag/ifup2019?src=hash&amp;ref_src=twsrc%5Etfw">#ifup2019</a> <a href="https://twitter.com/hashtag/soracom?src=hash&amp;ref_src=twsrc%5Etfw">#soracom</a> <a href="https://t.co/1L9uomU7mX">pic.twitter.com/1L9uomU7mX</a></p>&mdash; こにゃ (@kuroneko_ko2a) <a href="https://twitter.com/kuroneko_ko2a/status/1095880181904957440?ref_src=twsrc%5Etfw">2019年2月14日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

あれ、Free プランへの選択が表示されていない・・・
ってか、下位プランへ変更するには、今契約しているプランを解約しないとだめなのか？

ってことでユーザーコンソールから Lagoon をいったん削除したらちゃんと表示されるようになりました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ってことでFreeプランへ <a href="https://twitter.com/hashtag/ifup2019?src=hash&amp;ref_src=twsrc%5Etfw">#ifup2019</a> <a href="https://twitter.com/hashtag/soracom?src=hash&amp;ref_src=twsrc%5Etfw">#soracom</a> <a href="https://t.co/ryfHAsqtWx">pic.twitter.com/ryfHAsqtWx</a></p>&mdash; こにゃ (@kuroneko_ko2a) <a href="https://twitter.com/kuroneko_ko2a/status/1095880541004394496?ref_src=twsrc%5Etfw">2019年2月14日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

その直後にソラコムの中の人に話をしたら、やはりいったん解約しないとダメとのことでした。
そして [SORACOM Lagoon の ユーザーガイド](https://dev.soracom.io/jp/lagoon/plans/) にもちゃんと書いてありました。

>プラン変更についての注意事項

>プラン変更については以下についてのご注意ください。
>・Maker プラン、Pro プランを利用した場合、同一Lagoon 契約中でのFree プランへの変更ができなくなります。
Free プランへの変更はLagoon の解約が必要となります。（設定したダッシュボード等の情報は削除されます。）
>・Pro プランからMakerプランへ変更する場合、Pro プランのみで利用できる機能を事前に削除いただく必要があります。
ライセンスパックの削除、ダッシュボード権限のリセット等が必要となります。
>・同月中にLagoon の解約と再契約を行なった場合、同月中の契約内の最大の金額が請求対象となります。

今回、私はたまたま [Sens'it の検証がてら](https://qiita.com/ko2a/items/65d858353f301bbe001b) SORACOM Lagoon を使っていただけなので、さくっと消しても問題ないのですが、既に運用してて消えると困るようなパターンの場合は注意が必要です。

##結論？
新機能はユーザーマニュアルをちゃんと読んでからさわろう！（当たり前
sessionStorageでcheckedの値を保持する

ブラウザを閉じるまでcheckboxのcheckedの値を持っていたい。

```html:index.html
<input type="checkbox" name="q1" data-question="q1-1" class="question_checkbox">
<input type="checkbox" name="q1" data-question="q1-2" class="question_checkbox">
<input type="checkbox" name="q1" data-question="q1-3" class="question_checkbox">
<input type="checkbox" name="q1" data-question="q1-4" class="question_checkbox">
```
クリック時にセッションを登録
ieでquerySelectorAllで取得した値をforeEachでループできない ／(^o^)＼
ie10でdataset使ってカスタムデータ属性取得できない ／(^o^)＼

```javascript:script.js
var targets = document.querySelectorAll('.question_checkbox');
var checkboxClick = function(){
    var self = this;
    sessionStorage.setItem('input[data-question="' + self.getAttribute('data-question') + '"]', self.checked);
};
Array.prototype.forEach.call(targets, function(e){
    e.addEventListener('click', checkboxClick)
})
```

ページ読み込み時にセッションを確認して、'true'の場合、checkedをtrueにする。

```javascript:script.js
var addSessionStorage = function() {
    var session = sessionStorage;
    Object.keys(session).forEach(function(key){
        if(key.indexOf('data-question') !== -1 && this[key] === 'true' && document.querySelector(key) !== null) {
            document.querySelector(key).checked = true;
        }
    }, session)
}
```

windowをloadしたタイミングで実行。

```javascript:script.js
window.addEventListener('load', addSessionStorage);
```
英語ドキュメントを読む上での専門用語

#英語ドキュメントを読む上での専門用語
メモ程度に。

|英語|意味|
|:---|:---|
|contract|契約、義務と権利|
|〃|規約|
|obligations|義務|
|variant|バリエーションの内の一つ|
|invariants|不変条件|
|half-precision floating-point values|単精度少数点数|
|distinguish|区別する|
|Design Goals|(ドキュメントの)目的|
|Conformance|準拠|
|Universal|一般的、普遍的、いついかなる時も|
|BL-type||
EC2起動時にEIPのプールしているIP郡から使ってないIPを選択して割り当てるワンライナー

# 内容
インスタンス立てるときに特定のEIPの中からどれかをつけて立ってほしかったから作ったワンライナー

# 前提
- EC2からEIP触れる権限があたってること。
- 事前にIP確保しておくこと
- 確保したIPにタグをつけておくこと（タグでフィルタします）

# コマンド

```bash:変数
export REGION=ap-northeast-1
export TAG_NAME="hogehoge-tag"
```

```bash:ワンライナー
aws ec2 associate-address \
    --region ${REGION} \
    --instance-id $(curl http://169.254.169.254/latest/meta-data/instance-id) \
    --allocation-id $(aws ec2 describe-addresses \
                        --filters "Name=tag-key,Values=Name" \
                                  "Name=tag-value,Values=${TAG_NAME}" \
                        --query "Addresses[?AssociationId==\`null\`].AllocationId" \
                        --region ${REGION} \
                        --output text | cut -f 1 )
```
python入門(7)~スライス~

#スライス
スライスとはシーケンスの操作ができる機能です．シーケンスとは複数の要素をまとめて扱える型のことです．pythonのシーケンスには「文字列」，「リスト」，「タプル」などがあります．
####スライスは[始めの位置: 終わりの位置: 増加分]というように書くことができます．
また，添字より大きい数字になってもエラーになりません．
##文字列に対するスライス

```python:slice.py
a = '123456789'
print(a[2: 4]) #添字の2つ目から4つ目の手前まで
print(a[: 5]) #添字の最初(0)から5つ目の手前まで
print(a[5:]) #添字の5つ目から最後まで
print(a[-2]) #文字列の後ろから2つ目
print(a[:: -1]) #添字全体を後ろから表示
print(a[2: 7: 2]) #添字の2つ目から7つ目の手前まで1つ飛ばしで
```

```text:実行結果
34
12345
6789
8
987654321
357
```
##リストに対するスライス

```python:slice2.py
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(a[2: 7]) #添字の2つ目から7つ目の手前まで
print(a[: 8]) #添字の最初(0)から8つ目の手前まで
print(a[8:]) #添字の8つ目から最後まで
print(a[:]) #全てを表示
print(a[8: 2: -3]) #添字の8つ目から2つ目の手前まで２つ飛ばしで
print(a[2: 7: 2]) #添字の2つ目から7つ目の手前まで1つ飛ばしで
```

```text:実行結果
[3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 6]
[3, 5, 7]
```
##最後に
スライスを扱うことによってできることが増えます．スライスを利用してたくさんプログラムを組みましょう．
XML 文字列にインデントつき整形を施す（System.Xml.XmlWriter編）

#はじめに
@kobake@github さんの投稿（感謝！）「[C# で XmlDocument からインデント付きの整形文字列を得る](https://qiita.com/kobake@github/items/90f7e20a4a5b5e89ea35)」にお世話になっていましたが、私の最近の環境で [XmlTextWriter](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmltextwriter) クラスがなぜかインテリセンスに上がってこなくなってしまったため、Microsoft オンラインマニュアルに「.NET Framework 2.0 以降では、代わりに [XmlWriter](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmlwriter) クラスを使用することをお勧めします。」と記載されていることもあり、急遽書き換えをしてみました。整形仕様は、[XmlWriteSetting](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmlwritersettings) クラスのオブジェクトで指定します。

#コード
```C#
namespace App
{
    public class Class1
    {
        private static string GetFormattedXmlText(string s)
        {
            var v = new System.Xml.XmlDocument();
            v.LoadXml(s);

            var ws = new System.Xml.XmlWriterSettings();
            ws.Indent = true;
            ws.IndentChars = "  "; // <- インデントの空白数ではなくて、1つ分のインデントとして使う文字列を直接指定します。

            using (var ms = new System.IO.MemoryStream())
            {
                using (var wr = System.Xml.XmlWriter.Create(ms, ws))
                {
                    v.WriteContentTo(wr);
                    wr.Flush();
                    ms.Flush();
                }
                ms.Position = 0;
                using (var rd = new System.IO.StreamReader(ms))
                {
                    return rd.ReadToEnd();
                }
            }
        }
    }
}
```

#参考
- [XMLの書き出し(XmlWriter)](https://devlights.hatenablog.com/entry/20070116/p1) - いろいろ備忘録日記 さん