OmniAICreator/Qiita-1.07M huggingface dataset:
kleeでパスワードを言い当てる

# はじめに
kleeなるものがあると聞き，パスワードの特定をやってみたので備忘録を残す．具体的なところは全く理解できていないので，とりあえず動いたところまで．

# 解いてみる問題
kleeチュートリアルの[Using symbolic environment](https://klee.github.io/tutorials/using-symbolic/)に紹介されている`check_password()`関数をターゲットにしてみた．
この関数はパスワード`hello`を入力すると1を，それ以外の場合は0を返す．

```c:password.c
#include <stdio.h>

int check_password(char *buf) {
  if (buf[0] == 'h' && buf[1] == 'e' &&
      buf[2] == 'l' && buf[3] == 'l' &&
      buf[4] == 'o')
    return 1;
  return 0;
}

int main(int argc, char **argv) {
  if (argc < 2)
     return 1;
  
  if (check_password(argv[1])) {
    printf("Password found!\n");
    return 0;
  }

  return 1;
}
```

チュートリアルでは，コマンドライン引数を含む形でテストケースを生成することを解説しているが，この記事では実際にパスワードを求めることを目標とした．

# 実際にパスワードを求める
ここからは実際にパスワードをシンボリック実行によって求めていく．

## 実行するコード
今回使うkleeの関数は2つ．

* klee_make_symbolic: 変数をシンボリックとしてマークする
* klee_assert: C言語のassertと同じ．偽ならそこでプログラムを強制終了する．

サンプルコードではコマンドライン引数`char **argv`を取っているが，今回はシンボリック実行ができればいいので`char pass[6]`に書き換えている．

```c:password.c
#include <stdio.h>
#include "klee/klee.h"

int check_password(char *buf) {
    if (buf[0] == 'h' && buf[1] == 'e' &&
        buf[2] == 'l' && buf[3] == 'l' &&
        buf[4] == 'o')
        return 1;
    return 0;
}

int main(void) {
    char pass[6];

    klee_make_symbolic(pass, sizeof(pass[0]) * 6, "pass");
    if (check_password(pass)) {
        printf("Password found!\n");
    	klee_assert(0);
        return 0;
    }
    return 1;
}
```

## 実行方法
clang実行後にkleeコマンドをたたくだけ．
`/home/klee/klee_src/include`の部分は，kleeのパスを各自環境に合わせて指定する．dockerを使っている場合は下の例のままで問題ないと思う．

```bash
$ clang -I /home/klee/klee_src/include -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone password.c
$ klee password.bc
```

## 実行結果とパスワード
　実行すると下のような結果が出てくる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382909/c8608069-82cc-df5a-7843-ea3ff33dbe45.png)

この内容から`klee-out-0`というディレクトリに結果が出力されたことが分かるので覗いてみる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382909/d0f55c83-ca3a-ac8e-6cc1-ba1ccd580c6e.png)

`.ktest`というファイルが複数出力されているが，それぞれが1つ1つのテストケースとなっている．この`.ktest`ファイルを見るには`ktest-tool`コマンドを使う．

　今回実行したコードでは，パスワードが一致したら`klee_assert`で処理を中断している．ということでテストケースの中で`.assert.err`が存在するもの(`test000005.ktest`)を見ればパスワードが得られる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382909/c0139570-728f-111b-7563-4c395c5a3170.png)

# さいごに
最初に聞いた時，kleeはangrのようにバイナリを渡したら解析してくれるツールなのかなと思っていたが，今回の方法ではソースコードに`klee/klee.h`等々を追記する手順が必要らしい．バイナリだけしか手元にないときにも簡単に使える方法はないか探してみたい．
data属性削除

こんなHTMLがあったとしてdata属性を削除したい

<pre><code>&lt;div id=&quot;wrapper&quot;&gt;
	&lt;p id=&quot;target&quot; data-test=&quot;TEST&quot; data-user_a_b_c=&quot;ABC&quot; data-user_c_d_f=&quot;CDF&quot; data-user_g_h_i=&quot;GHI&quot; data-user_j_k=&quot;JK&quot; data-user_l_m=&quot;LM&quot;&gt;ターゲット&lt;/p&gt;
	&lt;p&gt;
		&lt;button id=&quot;dataAttr&quot;&gt;removeAttr&lt;/button&gt;&amp;nbsp;
		&lt;button id=&quot;dataAttrSet&quot;&gt;dataset&lt;/button&gt;
		&lt;button id=&quot;jQ&quot;&gt;jQueryで削除&lt;/button&gt;
	&lt;/p&gt;
&lt;/div&gt;</code></pre>

でdata属性を削除できるパターンを試してみた。

<pre>
var btnRemoveAttr = document.getElementById('dataAttr');
var btnDataset = document.getElementById('dataAttrSet');
var el = document.getElementById('target');

//これだと削除できる
function dataAttrSet(el) {
	if (el.hasAttributes()) {
		var datas = el.dataset;
		if (!!Object.keys(datas).length) {
			for (var i in datas) {
				if (i.indexOf('user_') !== -1) {
					delete el.dataset[i];
				}
				//el.removeAttribute(i);
				console.log(i, datas[i]);
			}
		}
	}	
}
//これだと削除できない。
function dataAttr(el) {
	
	if (el.hasAttributes()) {
		var attrs = el.attributes,
			len = attrs.length;
		
		for (var i = 0; i < len; i++) {
			var attr = attrs[i];
			if (attr.name.indexOf('data-') !== -1) {
				console.log(attr.name);
				el.removeAttribute(attr.name);
			}
		}	
	}
}

btnRemoveAttr.addEventListener('click', function(){
	dataAttr(el);	
}, false);

btnDataset.addEventListener('click', function(e){
	dataAttrSet(el);
}, false);

$(function(){
	
	$('#jQ').click(function(){
		removeHtmlData($(el));
	});
	
	//removeAttrとremoveData両方やればキャッシュも含め削除できる。
	function removeHtmlData($el) {
		console.log($el.data());
		$.each($el.data(), function(key,val) {
			if (key.indexOf('user_') !== -1) {
				$el.removeAttr('data-' + key); //属性を削除
				$el.removeData(key); //cacheも削除
			}
		});
		console.log($el.data());
	}
});

</pre>

データ周りの理解が浅いので色々混乱する。
【PHP】遅延静的束縛　static／self／parent

#はじめに
PHP資格勉強中の備忘録として記事を書きます。
内容は「PHP5技術者認定上級試験問題集」に出てきたものをまとめています。

`static` `self` `parent`が示すスコープで、どのクラスのメソッドが
呼び出されるのか本当にややこしかったのでまとめます。

#まとめ
|         |スコープ                         |
|---------|:------------------------------|
|self   |selfが記載されたクラス          |
|static |非転送コールのクラス               |
|parent |parentが記載されたクラスの親クラス|

- 転送コール
    - self、static、parentによる静的メソッドのコール
- 非転送コール
    - 明示的にクラス名を指定したもの（クラス名::メソッド名）

#self
`self`は**「selfが記載されたクラス」**がスコープとなる。
よって以下の実行結果は**「foo」**となる。

```php:
class Foo {
  public static function who() {
    echo 'foo';
  }

  //selfでwho()の呼び出し
  public static function test() {
    self::who();
  }
}

class Bar extends Foo {
  public static function who() {
    echo 'bar';
  }

//Barクラスでtest()呼びだす
Bar::test();
```

#static
`static`は**「非転送コールのクラス」**がスコープとなる。
よって以下の実行結果は**「bar」**となる。
非転送コールである「Bar::test()」まで遡り、Barのメソッドが呼ばれる。

```php:
class Foo {
  public static function who() {
    echo 'foo';
  }

  //staticでwho()の呼び出し
  public static function test() {
    static::who();
  }
}

class Bar extends Foo {
  public static function who() {
    echo 'bar';
  }

//Barクラスでtest()呼びだす
Bar::test();
```

#parent
`parent`は**「parentが記載されたクラスの親クラス」**がスコープとなる。
よって以下の実行結果は**「foo」**となる。

```php:
class Foo {
  public static function who() {
    echo 'foo';
  }
}

class Bar extends Foo {
  public static function who() {
    echo 'bar';
  }

  //parentでwho()の呼び出し
  public static function test() {
    parent::who();
  }

//Barクラスでtest()呼びだす
Bar::test();
```

#ついでに
```php:
class ParentClass {
  //クラス名を返す特殊な定数
  public static function get_class_constant() {
    print __CLASS__;
  }

  //関数を呼び出したクラスのクラス名を返す関数
  public static function get_class_function() {
    print get_called_class();
  }

class ChildClass extends ParentClass {}

//子クラスから両方呼ぶ
ChildClass::get_class_constant();
ChildClass::get_class_function();

```
**実行結果**
>ParentClass
>ChildClass

#まとめ
```php:
class X {
  public static function foo() {
    //staticでwho()を呼ぶ
    //非転送コールを探す
    static::who();
  }

  public static function who() {
    echo __CLASS__;
  }
}

class Y extends X {
  public static function test() {
    //それぞれでfoo()を呼び出す
    X::foo();
    parent::foo();
    self::foo();
  }

  public static function who() {
    echo __CLASS__;
  }
}

class Z extends Y {
  public static function who() {
    echo __CLASS__;
  }
}

//Zでtest()を呼び出す
Z::test();
```
**実行結果**
>X Z Z

#最後に
なんともややこしい。
理解したはずなのに、記事書いてたときにごちゃごちゃしました。笑
間違っていたら教えて下さい。
UbuntuにMicrosoft Teamsをインストールする


## インストール

```bash

curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/ms-teams stable main" > /etc/apt/sources.list.d/teams.list'
sudo apt update
sudo apt install teams
```

## 参考
https://docs.microsoft.com/ja-jp/microsoftteams/get-clients
[Flutter] カウントダウン機能を Stream + StreamBuilder + Providerで実現する。

Stream とStreamBuilder, Provider を使って、簡単なカウントダウン機能を実現してみます。

![Aug-09-2020 23-03-20.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83242/7cd35357-12e5-f107-f861-9973784ff846.gif)


StreamController にロジックを書き、WidgetにProviderで流し込んでます。

StreamBuilderを使うことで、データが変わるとこだけリビルドできるので、Statefull Widget の setStateより効率的です。ロジックとViewも分離できます。

```dart

class CountdownController {
  CountdownController();

  var _controller = StreamController<int>();
  var _count = 10;
  var _max = 10;
  get stream => _controller.stream; // streamにアクセスできるようにする

  Future<void> countdownStart() async {
    _count = _max;
    while (_count > 0) {
      await Future.delayed(Duration(seconds: 1));
      _count--;
      _controller.add(_count); //データを流す。
    }
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Providerでロジックを注入
    return Provider(
      create: (_) => CountdownController(),
      // 同じ階層ではProviderを使えないためBuilderもしくは別のWidgetに切り出す必要がある。
      child: Builder( 
        builder: (context) => Scaffold(
          body: Center(
            child: StreamBuilder(
              stream: Provider.of<CountdownController>(context).stream,
              // snapShot.dataでstreamを取得する。
              builder: (context, snapShot) {
                if (!snapShot.hasData)
                  return Text("Start Timer");
                else
                  return Text(snapShot.data.toString());
              },
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: Provider.of<CountdownController>(context).countdownStart,
            child: Icon(Icons.play_arrow),
          ),
        ),
      ),
    );
  }
}
```

最近知ったのですが、BLoCパターンはStreamを使ってロジックとViewを分離するものなんですね。この実装も簡単ですがBLoCもどきということでしょう。


この記事はブログのクロス投稿です。
https://shuent.qrunch.io/entries/jHL5XPzalsNWZbz2
ImageViewにDataBindingをする方法

# はじめに

今回はImageViewにDataBindingをする方法を解説していきます。

# やりたかったこと

```xml
<ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@{iconId}"/>
```

こんな感じでImageViewにリソースIDをDataBindingをしたかったのですが、なぜか上手くいきませんでした。

# 改善
```xml
<ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:imageResource="@{iconId}"/>
```

これでできました！

なんでできないんだろうって考えていたんですが、公式のBindingAdapterを見て、そりゃできないなって思いました。
ちなみにこちらが既に用意されているBindingAdapterです。

```java:Java
@BindingAdapter("android:src")
public static void setImageUri(ImageView view, String imageUri) { 
    if (imageUri == null) { 
      view.setImageURI(null); 
    } else { 
             view.setImageURI(Uri.parse(imageUri)); |
    } 
} 

@BindingAdapter("android:src")
public static void setImageUri(ImageView view, Uri imageUri) {           
    view.setImageURI(imageUri);
} 

@BindingAdapter("android:src")
public static void setImageDrawable(ImageView view, Drawable drawable) { |
    view.setImageDrawable(drawable);
} 
```

setImageResourceをしてくれるBindingAdapterはなかったんですね(笑)
そりゃできないわけだ、、、

ちなみに自作でBindingAdapterを作っても良さそうですね
作るとしたらこんな感じです

```kotlin:kotlin
@BindingAdapter("android:src")
fun ImageView.setImageResource(resourceId: Int) {
    setImageResource(resourceId)
}
```

というかResourceIdをセットすることを最初から想定しておいてほしいです、Googleさん、、、、

# 最後に
ImageViewがバグって表示されていて、なんでだろうなぁと小1時間くらい消費してしまいました。
想定通りの挙動をしない場合は、裏側で何をやっているかちゃんと確認した方がいいということを学べたのでよかったです（笑）
parallelの並列数の決め方

[parallel](https://github.com/grosser/parallel) の並列数の決め方を調べたのでメモしておきます。下記の1から順に評価されて並列数が決定されます。

## 1.システムのプロセッサコア数

`Etc.nprocessors` の返すプロセッサコア数です。1CPU のシステムでは parallel を使っても後述の指定のいずれも行わなかった場合は並列数1になってしまいます。逆にサーバ機で多コアの Xoen などを使っている場合には並列数が多くなりすぎて CPU やメモリを圧迫してしまうこともあり得ます。

## 2. 環境変数 `PARALLEL_PROCESSOR_COUNT`

環境変数 `PARALLEL_PROCESSOR_COUNT` が設定されていると、その値が採用されます。parallel を呼び出す都度に指定する必要がないので、常に同じ並列数でよい場合には便利でしょうか。

## 3. in_processes/in_threads で指定する並列数

map メソッドの in_processes/in_threads オプションで都度並列数を指定できます。ここで指定するケースが一番多いですかね。

## 4. map/each メソッドの source 数

`Parallel.map([1, 2, 3], in_process: 10)...` としても並列数は3にしかならないわけですね。
クラウドにおけるストレージの技術

#ストレージとは？

データやプログラムを保存する場所(記憶装置)のこと。

クラウドサービスにおけるストレージは以下の３つのデータアクセス方式がある。

#ブロックストレージ

- ストレージの理論ボリュームを決まったサイズに分割した、ブロック単位でアクセスできるストレージのこと。

- ストレージへのアクセスにはファイバーチャネル(FC)やiSCSIなどの専用プロトコルを使う。

- サーバーとストレージ間でデータをやり取りする際のオーバーヘッドが小さい為、高速なデータ転送が可能なので、低遅延が求められるデータベースなどで利用されている。

#ファイルストレージ

- ファイル単位でのストレージアクセスが可能な、ファイル共有の機能を備えたストレージのこと。

- 主にファイルサーバーで利用されていて、アクセス制御や属性情報の管理がしやすいとったメリットがある。

#オブジェクトストレージ

- データをオブジェクト単位で扱うストレージのこと。

- オブジェクトには固有のID(URI)が付与される

- オブジェクトストレージへのアクセスには、**HTTPプロトコルをベースとしたREST(REpresentational State Transfer)形式のAPIを利用する。**
npmパッケージ開発中にyarn addしても変更が反映されない場合はyarnのキャッシュに注意

npmパッケージはnpmに公開しなくても、`npm pack`すればパッケージ(tgz)を生成してくれる。
そしてできたtgzのパスを`yarn add`の引数に指定すれば、ふだんライブラリをインストールするような形で追加されてくれる。（たぶん`npm install`でも同じなはず）

```shell
$ cd [developing-peoject-root]
$ npm run build
$ npm pack # プロジェクトルートに[package-name]-[version].tgzが生成される
$ cd [test-project-root]
$ yarn add [your-tgz-path]
```

何か修正して再度`npm pack`した際は、`yarn add`する前に`yarn cache clean`する必要がある。
（ちなみに変更がtgzに反映されているかどうかはtgzを解凍すればわかる）

```shell
$ cd [developing-peoject-root]
$ npm run build
$ npm pack  # 変更を加えたtgzが生成される
$ cd [test-project-root]
$ yarn cache clean # これをしないと、yarnがキャッシュしたバージョンを再度インストールするので変更が反映されない
$ # ちなみに一度yarn removeする必要はなさそう
$ yarn add [your-tgz-path]
```

余談だが、[yarnのドキュメント](https://classic.yarnpkg.com/en/docs/cli/cache)には`yarn cache clean [<module_name...>]`で指定したパッケージだけのcleanができるように書いてあるが、何か間違っているのか、これでは次の`yarn add`で前のバージョンがインストールされてしまった。
何か凡ミスをしてる気もするが、いまのところとりあえず`yarn cache clean`を使っている。
パパ活とプログラマー

パパ活プロデューサーです。
初めましての方も多いと思うので簡単に自己紹介をしますと、パパ活女子の皆さんに無料でアドバイスしている変わり者です。

Twitterではパパ活のリアルなお話をしています。
https://twitter.com/tinder_group

テレビとか雑誌にもちょいちょい出てるので、一応ちゃんとした人です。
​https://abema.tv/video/episode/89-66_s99_p1557

パパ活女子のアドバイスの一環として、パパ活女子の無料情報交換グループもやっていましてそちらには1000名以上の女性にご参加いただいています。
パパ活女子の方ならどなただもご参加いただけますので遠慮なくご連絡ください♪
​https://xn--vck9a3aa4a4f8b6gb7335m.com/%e6%97%a5%e6%9c%ac%e6%9c%80%e5%a4%a7%e7%b4%9a%e3%83%91%e3%83%91%e6%b4%bb%e5%a5%b3%e5%ad%90%e6%83%85%e5%a0%b1%e4%ba%a4%e6%8f%9b%e3%82%b0%e3%83%ab%e3%83%bc%e3%83%97

#パパ活とプログラマー
さて、お気づきの方もいるかと思いますが私はプログラムはほとんど分からない人間です。
CSSを検索しながらちょこっと直したりできる程度です。
なんで私がここで記事を書いているのかと言いますと、パパ活をしている男性の中で独身貴族の高給取りプログラマーが実は結構いるのです。

そして、パパ活女子からの相談でプログラマーのパパは扱いがめんどくさいという話もよく耳にしています。

そこで今回はプログラマー男性がパパ活でモテるためにはどうしたらいいのか？と言うことについてお話ししていきたいと思います。

#モテるプログラマーとモテないプログラマー
まず、プログラマーの中でもモテる人とモテない人がいてそのタイプはわかりやすいです。
モテるプログラマーは、プログラミングも要領よくこなしつつディレクションもできて人を指揮できるタイプの人間です。
こういう人は、プログラミングだけでなく日常生活においても上手に生きているし、人を指揮ができるタイプは他人の気持ちがわかるのでモテます。

逆にモテないプログラマーというのはとにかくパソコンに向かって黙々とコードを書き続けるタイプの人間で、愚直に言われた仕事を淡々とこなす一方クライアントの要望を汲み取れず気が利かないなんてことも言われたりする方も多いです。

そういう方は日常生活においてもなかなかモテないのですが、パパ活を通して素人女性と出会いそしてハマってしまうのです。

しかし、どういうお付き合いをしたらいいのか距離感がわからず女性に言われるがままお手当を渡してお食事だけの関係を続けられたり、女性を好きになりすぎたがために距離感を誤って女性に嫌われてしまったりという失敗をしている話をパパ活女子からよく聞きます。

そもそも、パパ活女子たちは「素敵な年上男性とお知り合いになりたいです♪」なんてことを言っていますがそれは建前です。
本音はお金が欲しいのです。
ただ、お金お金していると男性が引いてしまうからその雰囲気を出さないように気を使ってくれているのです。
なので男性も空気を読んでいかに女性が喜ぶだけのお手当を渡せるかが重要になってきます。
一人１万もするコース料理のレストランも、１泊１０万円の高級ホテルも、数十万する本当に欲しいかどうかわからない高級バッグもいらないのです。
コスパの良いデートをしつつお手当はしっかりと渡すことを意識すれば、パパ活女子もあなたのことを超お金持ちではないけど一緒にいて疲れない異性としてみてくれるようになります。

そんな月５万円でできるパパ活生活についてこちらの記事でも詳しく書いているのでよかったら目を通してみてください。
https://xn--vck9a3aa4a4f8b6gb7335m.com/post-1821
Texで画像がなぜか中央に来ないときの対処法

普段から、wordばかり使っているせいか、いざTexで画像を挿入しようとしたらはまってしまった話。

# 出会ったトラブル
![コメント 2020-08-09 225348.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197285/fd56795d-994d-c8c4-56c5-48ac03943323.png)
画像のように、なぜかキャプションが右寄りになっている。コードは次の通り。

```tex:main.tex
\documentclass[a4paper,titlepage]{jarticle}
\usepackage[dvipdfmx]{graphicx}

%（中略）

\begin{figure}[htbp]
	\begin{tabular}{cc}
		\begin{minipage}[t]{0.45\hsize}
			\centering
			\includegraphics[keepaspectratio, width=0.9\hsize, scale=1.0]{test_a.jpg}
			\caption{自然をイメージした画像}
			\label{fig:1}
		\end{minipage} 
        &
		\begin{minipage}[t]{0.45\hsize}
			\centering
			\includegraphics[keepaspectratio, width=0.9\hsize, scale=1.0]{test_b.jpg}
			\caption{都会をイメージした画像}
			\label{fig:2}
		\end{minipage}
	\end{tabular}
\end{figure}

%（後略）
```

# 調べたこと
- `\begin{tabular}{|c|c|}`に変更した
- `\includegraphics`全体を`\fbox`で囲ってみた

すると、画像のようになっていた。
![コメント 2020-08-09 225239.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197285/c3a7bd43-c809-1fe1-112d-b20eb41a714a.png)
見て分かる通り、`\caption`は正常にテーブルの中央付近に位置していた。一方で、画像が左下に寄っていた。......というよりは、画像の右側と上側に白い余白が勝手に挿入されていた。

# 原因はTexmarker
私は普段、Texの統合環境であるTexmarkerを利用している。Texmarkerをインストールしたのはかなり昔のことであったが、当時、「dvipdfm」の設定を書き換え忘れていた。初期設定では`dvipdfm %.dvi`となっているが、ここを`dvipdfmx %.dvi`と変更するだけで、すべて上手くいった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197285/f4949ab0-f85d-d2d9-2cbf-3826d8c9ceee.png)

自分が書いたコードに何か問題があるのだろうか、あるいは用意したJPEGファイルに問題があるのだろうか、といろいろ調べていて、Texmarker側の問題に気付くのが遅れてしまったところが反省点として挙げられる。



以上。
【入門】iOS アプリ開発　#1【パックマン・ゲーム制作】

#はじめに
新型コロナウィルス(COVID-19)の影響により、外出自粛が続いている。
どこへも出かけない夏休み、この機会に Mac を購入して iOS のプログラミングを勉強してみようと思う。
iPhone のアプリは Swift という言語で作られるようだ。

アップルは Swift を「モダン、安全、高速、インタラクティブ」を特徴として謳っている。
これだけでは全くイメージつかないが、さぞかし簡単にアプリが開発できるに違いない。

昔のゲームぐらいならば、さくっと作れて、軽快にサクサク動作するのであろう。
さらにタッチパネルやセンサーで操作できると面白そうだ。

プログラミングすることよりも、何を作るか？どんな仕様するか？、企画や上流設計は悩みどころだ。
またキャラクターのデザインやサウンドなどを作るのも骨が折れる。

色々調べてみるとパックマンの仕様書が公開されている。
これをもとに作ればプログラミングに専念できそうだ。

#パックマンのゲーム仕様書
下記の人工知能学会誌に仕様書が公開されている。

- [人工知能学会誌 Vol.34 No.1 (2019/1)](https://www.ai-gakkai.or.jp/vol34_no1/)
- [ゲームAI の原点『パックマン』はいかにして生み出されたのか？：岩谷 徹インタビュー](https://jsai.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=9670&item_no=1&page_id=13&block_id=23)

![Img0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678332/8db1c1b7-3a7a-77fe-6511-7fc1900b5873.png)

一度、何かを作ってしまえばノウハウが溜まり、自分が作りたいものが簡単にできるはずなので、
まずはパックマンを作ってみようと思う。

仕様書をよく読むと、思ったよりも複雑な仕様になっているが、
高級言語 Swift で書けば、１万行もコーディングせずに出来るのではないか。

# 次の記事
[【入門】iOS アプリ開発　#2【SpriteKit を使う】]
(https://qiita.com/KIKU_CHU/items/35a84464bd3b99a70cda)
混同行列について

## 混同行列とは

何かモデルに通した予測結果と実際の値との正しく判別できた数と誤って判別してしまった数とを表した行列

## 混同行列はどういった時に使用されるか？

一般的には、２値分類。

## 混同行列は何故、使用されるか？

例えば、与えられた画像から、癌であるかそうでないかを予測したい時に、
実際の値が
癌でない人(0)は98/100
癌である人(1)は2/100
であったとする。

この時に、予測を全て０とした場合、正答率は98%。
これは正答率で見ると、良い数値に見えるが、
果たしてこれは良い評価ができていると言えるだろうか？
見逃してしまった２人は致命的なミスではないだろうか？

このような事例でも上手く評価をするために使用されるのが混同行列。

## 混同行列を使ってみよう

一般的には、横軸をモデルの予測結果、縦軸を実際の値として、下表のような 2×2 = 4つの組み合わせでまとめる。
<img width="484" alt="スクリーンショット 2020-08-09 21.02.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677453/a643d77b-663c-63a7-d836-260cbcec3a4f.png">

True   　  ： 正しく予測できた結果
False　    ：間違って予測した結果
positive ： 疾患あり(=1)と判定された結果
negative : 疾患なし(=0)と判定された結果


```python:matrix.py

from sklearn.metrics import confusion_matrix

# 混同行列の作成
cm = confusion_matrix(y_true=y_test, y_pred=y_pred)

# y_trueに渡すのは、評価用の目的変数データ
# y_predに渡すのは、X_testでpredict()関数を使って予測した結果

# 混同行列をデータフレーム化
df_cm = pd.DataFrame(np.rot90(cm, 2), index=["actual_Positive", "actual_Negative"], columns=["predict_Positive", "predict_Negative"])
print(df_cm)

# heatmapによる混同行列の可視化
sns.heatmap(df_cm, annot=True, fmt="2g", cmap='Blues')
plt.yticks(va='center')
plt.show()
```

※上記のコードはデータが無いので、このコード単品では勿論、動きません。

<img width="719" alt="スクリーンショット 2020-08-09 21.10.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677453/e0f1b75a-59ee-20ae-2e1c-b5f66aebc89a.png">


ここからモデルの性能を測る評価指標について考慮

# 解率・正確さ(Accuracy)

まずは全体のデータの中でどれだけ正しく分類できたかを確認

$Accuracy = \dfrac{TP + TN}{TP + FP + FN + TN}$

# 精度・適合率(Precision)

ポジティブ（１）という結果が得られた上で、実際に正解しているかを確認

$Presision=\dfrac{TP}{TP + FP}$

# 再現率・真陽性率(Recall, True Positive Rate)

実際のデータはポジティブ（１）で、どれだけ
予測したデータが正しくポジティブと推測できているか。
この値が高いほど性能が良く、間違ったPositiveの判断が少ない。

$Recall=\dfrac{TP}{TP + FN}$

# 真陰性率(True Negative Rate)

実際のデータはネガティブ（０）で、どれだけ
予測したデータが正しくネガティブと推測できているか。
この値が高いほど性能がよく、間違ったNegativeの判断が少ない。

$Recall=\dfrac{TN}{FP + TN}$

# 偽陰性率(False Negative Rate)

実際のデータはポジティブ（1）で、どれだけ
予測したデータが間違えてネガティブと推測されたか。
この値は低いほど性能が良く、間違ったPositiveの判断が少ない。

$False\ Negative\ Rate=\dfrac{FN}{TP + FN}$

# 偽陽性率(False Positive Rate)

実際のデータはネガティブ（０）で、どれだけ
予測したデータが間違えてポジティブと推測されたか。
この値は低いほど性能が良く、間違ったNegativeの判断が少ない。

$False\ Positive\ Rate=\dfrac{FP}{FP + TN}$

# 「混同行列は何故、使用されるか？」の章で扱った例で真陽性率、真陰性率を計測

| 　       |       positiveな予測結果 |   negativeな予測結果    |
|:---------------------|------------------:|:------------------:|
| 実際のpositiveな結果  |         98     |        0        |
| 実際のnegativeな結果  |            2 |       0       |

$Accuracy = \dfrac{98 + 0}{98 + 2 + 0 + 0}=0.98$

98％の正答率

$Recall=\dfrac{98}{98 + 0}=1$

100%＝＞これはpositiveは全て正しく分類されたと判断している

$Recall=\dfrac{0}{2 + 0}=0$

0%＝＞これはnegativeは全て間違えて分類されたと判断している

# まとめ
2 値分類の機械学習モデルをビジネスで利用するには性能を測る指標を算出し、
目的にあった指標値を理解して使用するのが重要
【Laravel】ミドルウェアの基本

Laravelミドルウェアは、アプリへのリクエストをフィルタリングするメカニズムのことです。図に表すと以下のような処理をします。

HTTPリクエストがコントローラアクションに届くまでに、`グローバルミドルウェア` → `ルートミドルウェア` → `コンストラクタ内のミドルウェア` の順に通っていきます。コントローラアクションまでに3層のフィルターを通過している感覚です。
![ミドルウェア図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106716/6f1764ef-3659-edb6-ddfb-cdc0c9607fa0.jpeg)
レスポンスを返す際は、リクエストとは真逆の順を追っていきます。ミドルウェアは、ユーザー認証やCSRF保護など、多く用意されています。これらのミドルウェアは`APP/Http/Middleware`ディレクトリに設置されています。

### グローバルミドルウェア
特徴
・ルーターに登録されたコントローラクラスが動作する前に実行

### ルートミドルウェア
特徴
・デフォルトで、Webミドルウェアグループが適応される

### 名前付きミドルウェア
・ルーターへの登録または、コントローラのコンストラクタ等で名前を指定して利用
Gridsome入門 SPAを作ってみよう 【2日目 環境構築編】

# スケジュール
- [1日目 要件定義編](https://qiita.com/Dev-kenta/items/b5c8ea6b432fe3594282)
- [2日目 環境構築編](https://qiita.com/Dev-kenta/items/6ae251a648e04b9cf026)←今ここ
- [3日目 ドーナッツグラフ編](https://qiita.com/Dev-kenta/items/9e141767c42deee743c8)
- [4日目 棒グラフ編](https://qiita.com/Dev-kenta/items/780c3cb4a4d0cf813824)
- [5日目 GraphQL編](https://qiita.com/Dev-kenta/items/1d08ef27aa877cfb6771)
- [6日目 GraphQL編2](https://qiita.com/Dev-kenta/items/e4281380da38f57495b6)
- [7日目 GraphQL編3](https://qiita.com/Dev-kenta/items/1bf6dc021ec08932233c)
- [8日目 GraphQL編4](https://qiita.com/Dev-kenta/items/fcc65b0106ba29626db7)
- [9日目 デプロイ編](https://qiita.com/Dev-kenta/items/14ae9fdc6eec76f63ba1)

# 前提条件
- node.js v8.3以上
- yarn or npmが入っている(Document見るとyarnの方が推奨とのこと)

# 環境構築手順
## CLI入れる
まずはGridsomeのCLIを入れます。vue-cliを使ったことある人ならほぼ一緒なのですぐできちゃいそう。
直感的でわかりやすいです。cli便利ー。

```
// GridsomeのCLIを入れる
yarn global add @gridsome/cli
// project作成
gridsome create asset-management-app
// projectのフォルダに移動
cd asset-management-app/
// ローカルサーバーの立ち上げ
gridsome develop
```

```gridsome develop```でlocalhost:8080で確認することができます。しかもhot reloadなので変更したらすぐ反映される便利。
![image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402204/ae75f349-7c6f-2632-9578-bba5a59bd71d.png)
こんな画面が表示されます。

## 今回他に入れるライブラリを追加
```
// 今回必要なライブラリとか入れる(随時追加)
yarn add csv-parse 
yarn add vue-chartjs chart.js
```
csv-parseはcsvを扱うためのライブラリで、vue-chart.jsはグラフを扱うライブラリです。
今回データソースをCSVにしたのは使ってるネット証券会社から、自分の投資しているものをCSV形式でダウンロードできるのでそれを使おうかなーと思ったためです。
gridsomeは色んなデータソースを使えるので(markdown・jsonやAPIなど)、他の形式使いたい方はこちらを参照
https://gridsome.org/docs/fetching-data/

## ページの追加とメニューの変更
新しい静的なページなど追加するにはpagesディレクトリに追加していきます。
<img width="305" alt="image02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402204/d1c66bfb-ec8d-7017-9d91-46f0584be646.png">
お次は共通のLayoutsを変更

```vuejs:src/layouts/Default.vue
<template>
  <div class="layout">
    <header class="header">
      <strong>
        <g-link to="/">{{ $static.metadata.siteName }}</g-link>
      </strong>
      <nav class="nav">
        <g-link class="nav__link" to="/portfolio/">Portfolio</g-link>
        <g-link class="nav__link" to="/asset-allocation/">Asset allocation</g-link>
        <g-link class="nav__link" to="/asset-transition/">Asset transition</g-link>
      </nav>
    </header>
    <slot/>
  </div>
</template>
```
g-linkはgridsomeが用意してくれているページリンク用のコンポーネントで、このコンポーネントのおかげでgridsomeは高速にページ遷移することを可能しています。以下はdocumentから引用
> \<g-link>は、リンクが表示されているときにIntersectionObserverを使用してリンクされたページをプリフェッチします。これにより、クリックしたページが既にダウンロードされているため、Gridsomeサイトの閲覧が非常に高速になります。

![image03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402204/07fe1669-62db-989d-d818-7101831d0fb7.png)
こんな感じでメニューとか変更しました。あとは中身を作ってかないと。

# あとがき
やっぱhot reload便利。
そして調べてるうちにlive reloadとhot reloadの違いを初めて知った。。
> ライブリロードは、ファイルが変更されたときにアプリケーション全体をリロードまたはリフレッシュします。たとえば、ナビゲーションに4つのリンクがあり、変更を保存した場合、ライブの再読み込みによってアプリが再起動され、アプリが最初のルートに戻されます。
ホットリロードは、アプリケーションの状態を失うことなく変更されたファイルのみをリフレッシュします。たとえば、ナビゲーションに4つのリンクがあり、一部のスタイリングに変更を保存した場合、状態は変更されませんが、新しいスタイルはページ上に表示されます。同じページにいてください。

あと全然関係ない話ですが、半沢直樹は面白いけど顔芸が濃すぎて話しが入ってこなくなると思った日曜日でした。
あと一週間なのでGridsomeをどんどん学んでいこう。
Docker書き方メモ

# Dockerの書き方メモ
## dockercompose
```
version: '3'
services:
    test1:
        build: ./build
        container_name: test1
        ports:
            - 8080:80
            
    test2:
        image:
        container_name: test2
        volumes:
            - ./test:/var
        ports:
            - 8000:8000
```
```
docker-compose up -d
```
## Dockerコマンド
#### Docker内へ入る

```
docker exec -it test /bin/bash
exit
```

#### コンテナ一覧を表示

```
docker ps
docker ps -a
```

#### コンテナを停止

```
docker stop test
```

#### コンテナを起動

```
docker start test
```

#### コンテナを削除

```
docker rm test
```

#### 停止コンテナ、タグ無しイメージ、未使用ボリューム、未使用ネットワーク一括削除

```
docker system prune
```

#### すべてのコンテナを停止

```
docker stop $(docker ps -q)
```

#### すべてのコンテナを削除
```
docker rm $(docker ps -q -a)
```

#### すべてのイメージを削除する
```
docker rmi $(docker images -q) -f
```
openaigym

```
import gym
import numpy as np
env = gym.make('Breakout-v0')
print('observation space:', env.observation_space)
print('action space:', env.action_space)

obs = env.reset()
#env.render()
print('initial observation:', obs)

action = env.action_space.sample()
obs, r, done, info = env.step(action)
print('next observation:', obs)
print('reward:', r)
print('done:', done)
print('info:', info)

# Start virtual display
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1024, 768))
display.start()

frames = []
for i in range(3):
    obs = env.reset()
    done = False
    R = 0
    t = 0
    while not done and t < 200:
        frames.append(env.render(mode = 'rgb_array'))
        obs, r, done, _ = env.step(env.action_space.sample())
        R += r
        t += 1
    print('test episode:', i, 'R:', R)
 
env.render()

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from IPython.display import HTML

plt.figure(figsize=(frames[0].shape[1] / 72.0, frames[0].shape[0] / 72.0), dpi = 72)
patch = plt.imshow(frames[0])
plt.axis('off')
animate = lambda i: patch.set_data(frames[i])
ani = matplotlib.animation.FuncAnimation(plt.gcf(), animate, frames=len(frames), interval = 50)
HTML(ani.to_jshtml())
```

```
import gym
from IPython import display
import matplotlib.pyplot as plt
%matplotlib inline

env = gym.make('CartPole-v0')
env.reset()
for _ in range(50):
    plt.imshow(env.render(mode='rgb_array'))
    display.clear_output(wait=True)
    display.display(plt.gcf())
    env.step(env.action_space.sample())
    plt.close()
```

動画保存

```
import numpy as np
import gym

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

env = gym.make('CartPole-v1')
desired_state = np.array([0, 0, 0, 0])
desired_mask = np.array([0, 0, 1, 0])

P, I, D = 0.1, 0.01, 0.5
env = gym.wrappers.Monitor(env, 'video/',video_callable=lambda episode_id: True,force = True)
for i_episode in range(20):
    state = env.reset()
    integral = 0
    derivative = 0
    prev_error = 0
    for t in range(500):
        env.render()
        error = state - desired_state

        integral += error
        derivative = error - prev_error
        prev_error = error

        pid = np.dot(P * error + I * integral + D * derivative, desired_mask)
        action = sigmoid(pid)
        action = np.round(action).astype(np.int32)

        state, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break

env.close()
```

動画保存

```
#https://github.com/TTitcombe/docker_openai_gym
import gym
import torch

env_to_wrap = gym.make("BankHeist-ram-v0")
env = gym.wrappers.Monitor(env_to_wrap, "someDir2")
frame = env.reset()
is_done = False
while not is_done:
  action = env.action_space.sample()
  _, _, is_done, _ = env.step(action)
env.close()
env_to_wrap.close()
```

https://gist.github.com/HenryJia/23db12d61546054aa43f8dc587d9dc2c
http://korechipostit.hatenablog.com/entry/2018/11/05/190000
https://colab.research.google.com/drive/1GLlB53gvZaUyqMYv8GmZQJmshRUzV_tg#scrollTo=ZAcCvXYJlJ8I
〇〇/〇〇.rb:1: Invalid char `\x08' in expression が出てきたけど、速攻で解決した。

#本題
Rubyを再学習してる時に、謎のエラーが出てきた。
見たこともないエラーなので良く調べたが、一瞬で解決・・・

#解決方法
**該当の行をもう一度打ち直そう！！**

#内容

エラー分を翻訳してみると・・・
test/gate_test.rb:1: Invalid char \x08' in expression
→式に無効な文字 \ x08 'があります


・
・
・

？

といったところで勘付きました。また誤字しているんだなと。

そんでもって、該当行を書き直したところ・・・エラーは出なくなりました。

他の方のサイトを拝見させていただいたところ、**不可視文字**が原因のようです。
このエラーについては、速攻で打ち直すのが吉ですね。

#参考にさせていただいたサイト

https://tattaka-s.hatenablog.com/entry/2019/07/06/153703
かな〜り詳しく書いていただいているので気になる方はご覧ください🙆🏻‍♂️
Node.jsでmysqlのDate型が勝手にDatetime型で取得される問題を解決する


<h2>はじめに</h2>
Node.jsドドド初心者です。ローカルで動くDBの情報を表示する簡単なアプリを作成しようと思い立って作ったのですが、思わぬところで落とし穴があったので、それについての覚え書きです。
Node.js Expressで、mysqlを操作している際に発生した事象です。

<h2>DATE型がDATETIME型として取得されてしまう</h2>
今回表示するテーブルは非常にシンプルな情報で構成されていました。

```
table名 : youtube
+----+------------+-----------------------------------------------------------------+
| id | date       | title                                                           |
+----+------------+-----------------------------------------------------------------+
|  1 | 2020-08-08 | 【絶対解けない】答えが「見たことない字」になる合体漢字クイズ          |
|  2 | 2020-08-07 | 数学の図形を使った共通点当てゲームで爆笑連発！【VENN'S CODE】        |
|  3 | 2020-03-27 | 伊沢vs伊沢vs伊沢vs伊沢                                            |
+----+------------+-----------------------------------------------------------------+
```

（中身は、すきなYoutuberさんの動画の情報を拝借しました。）

しかし、実際に情報をNode.jsで表示すると、DATE型のdateカラムが勝手にDATETIME型になってしまう問題が発生しました。
コードは以下の通りです。

```javascript:app.js
/*（中略）*/
app.get("/youtube_list",(req,res) =>{
    connection.query(
      'SELECT * FROM youtube',
      (error,results) =>{
        res.render("youtube_list.ejs",{items: results});
   )};
});
```
```html:youtube_list.ejs
  <% items.forEach((item) => { %>
    <li>
      <div class="item-data">
         <span class="id-column"><%= item.id %></span>
         <span class="first-column"><%= item.date %></span>
         <span class="second-column"><%= item.title %></span>
      </div>
    </li>
<% }); %>
```

調べた際に、同様の事象が発生している方が何人かいました。JSONの仕様では？という話もあったので、おそらくその影響でしょうか。


<h2>シンプルな解決策：connection option</h2>
最初は、関数を作ってDATETIME型の情報をこねくり回す方法を取ったのですが、その後改めて調べてみたら、とても単純な話で、「connectionの際にoptionを付与するだけ」でした。

```javascript:app.js
const connection = mysql.createConnection({
  host:'localhost',
  user:'root',
  password:'password',
  database:'quizknock',
  dateStrings: 'date' /*または'true'*/
});
connection.connect();
```

このdateStringsで、mysqlから取得するデータを文字列として取得することができます。
知ってしまえばめちゃくちゃ簡単ですね・・・
参考：[mysql Git](url:https://github.com/mysqljs/mysql)
jamf pro の拡張属性をSelf Serviceから変更できるようにさせる




## 拡張属性を追加する
歯車アイコン→コンピュータ管理→拡張属性をクリック
![2020-08-09_22h24_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48100/6349e678-1960-2d7f-637d-a3bd33a654df.png)

新規をクリック
登録したい内容を設定し、保存をクリック
![2020-08-09_22h26_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48100/2d902d83-3771-9392-f9de-9879d8ea4885.png)



## スクリプトを準備する
下記コードを記載し、Jamf Proの設定→スクリプトに登録します

```shell
#!/bin/bash

auth_token=$(printf $4:$5 | iconv -t ISO-8859-1 | base64 -i -)

# Get JSS ID for current computer. 
#get serial number and look up JSS ID  
serial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $NF}')
echo "the computers serial is $serial"
computerID=$(curl -s -k -X GET $6/JSSResource/computers/serialnumber/$serial -H "authorization: Basic $auth_token" | xmllint --xpath '/computer/general/id/text()' -)
echo "the computers JSS ID is $computerID"

# Create xml
    cat << EOF > /private/tmp/ea.xml
<computer>
    <extension_attributes>
        <extension_attribute>
            <name>$7</name>
            <value>$8</value>
        </extension_attribute>
    </extension_attributes>
</computer>
EOF

curl -s -k -X PUT $6/JSSResource/computers/id/$computerID -H "authorization: Basic $auth_token" -H "content-type: application/xml" -T /private/tmp/ea.xml

exit 0
```

## API呼び出し用ユーザーを作成する
以下の権限を持ったユーザーを作成します

- コンピュータ　読み取り・アップデート
- コンピュータの拡張属性　読み取り・アップデート
- ユーザー　読み取り・アップデート
- ユーザー拡張属性　読み取り・アップデート

なぜかユーザーに対する権限を与えないとエラーになります・・・
jamf nationでも触れられていてこれは報告する案件だとか書かれてました

## ポリシーを定義する
作成したスクリプトを実行するポリシーを定義します
コンピュータ　→　ポリシー　→　新規をクリック
作成したスクリプトを選択し、パラメータに下記内容を登録します

| パラメータ4      |      作成したユーザー名 | 
|:-----------------|------------------:|
|パラメータ5 |作成したユーザーのパスワード|
|パラメータ6|Jamf ProのURL|
|パラーメタ7|拡張属性名|
|パラメータ8|設定したい拡張属性の値|

Scope等々も必要に応じて設定してください



## Self Service のボタンを押してみる
ポリシーでSelf Serviceに表示させ、ボタンを押します
Jamf Proインベントリの拡張属性が変更されたことを確認します
WHILE文で無限ループにはまった(SQL SEVERの話)

#SQLのWHILE文で無限ループにはまった。
##投稿の経緯
SQLでカーソルを使用して、カーソル内のデータについて処理する際に、
While文を用いて繰返し処理をしているのですが、そこで無限ループを起こしました
解決はしたものの、１時間以上つまずいくことに・・・
自戒を込めて原因と対処法について投稿します

※記事の間違い、もっと良いやり方があると言う方は教えていただけると嬉しいです

##WHILE文とは
指定した条件が"True"を返す場合、処理を繰り返すことができる
基本構文は以下のとおりである

```sql:qiita.rb
WHILE "条件式"
BEGIN
  "繰り返したい処理"
TRY
```
WHILE "条件式" の下に繰返しの処理を"BEGIN"と"TRY"で書く。
このことを理解していれば、無限ループにはまることはなかっただろう。

##環境
使用したDB
　・SQL Sever Express 2016 
　　※DBはサーバにあり、それをクライアントPCより操作していた。

##無限ループが発生したWHILE文
以下が問題のSQLである。
目的の処理は
TableAからSelectした項目”A”をカーソルとして定義。（処理①）
定義したカーソルを開く（処理②）
処理①で取得したカーソルの1行目のデータをTableBへInesrtする（処理③）
ループ終了後、カーゾルを閉じて中身を消去する（処理④）
である。

```sql:qiita.rb
--処理➀
DECLARE Cur  CURSOR FOR
SELECT
 A --カラム名
FROM
  TableA

OPEN Cur --カーソルオープン

FETCH NEXT FROM Cur　--処理➁
INTO
  @a

--処理③
WHILE @@FETCH_STATUS = 0
  --INSERT処理
BEGIN
    INSERT INTO
	TableB
	(
        A
	)
	VALUES
	(
	    @a
	)
END	
BEGIN 
  FETCH NEXT FROM Cur
    INTO
        @a
    ;
 END
END

CLOSE Cur--処理④
;
DEALLOCATE Cur
;
```
＃結果
試しにSQLを実行してみたが、３０分たっても終了しない
いくらカーソルを使用して繰り返しをしているとはいえ、
処理時間が長すぎる
そこで、無限ループしていることに気づいた

＃原因
結論から言うとWhile文でループする範囲の指定を間違えたことにあった。
このSQLではWhileの下にあるBEGINがInsert文下のENDに対応しており、
次の行の取得がないため、
WHILE @@FETCH_STATUS = 0（カーソルの中身を取得できた場合０が返る）
を満たしつづけるため無限ループになっていた

```sql:qiita.rb
--処理③
WHILE @@FETCH_STATUS = 0
  --INSERT処理
BEGIN           --ここから
    INSERT INTO
	TableB
	(
        A
	)
	VALUES
	(
	    @a
	)
END	            --ここまでループ
BEGIN 
  FETCH NEXT FROM Cur
    INTO
        @a
    ;
END
```

ので、正しくは以下の通りに BEGINとENDを
正しく指定すればよい

```sql:qiita.rb
--処理③
WHILE @@FETCH_STATUS = 0
  --INSERT処理
BEGIN           --ここから
    INSERT INTO
	TableB
	(
        A
	)
	VALUES
	(
	    @a
	)

  FETCH NEXT FROM Cur
    INTO
        @a
    ;
END             --ここまでループ

```

＃最後に
SQLを書く際には何も考えずに処理単位でBEGIN ENDを張っていたが
ちゃんと構文の形を理解しないと
思わぬところでハマると言う教訓になった出来事でした
MinGWにプルリクエストを送ってlibgrのバージョンをアップデートした話

## はじめに

こんにちは。MinGWのパッケージをアップデートしたので記事にします。

https://github.com/msys2/MINGW-packages

### どうしてMinGWのパッケージのアップデートしなきゃならないの？

パッケージマネージャーって、みんな利用していると思うんですけど、そのメンテナンスに関わったことがある人は意外と少ないと思います。私もMinGWのパッケージをアップデートするのははじめてです。

1年程前から趣味と実益を兼ねてRuby向けのグラフ描出ソフト[GR.rb](https://github.com/red-data-tools/GR.rb)を作っています。
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/6a9c3e62-2cdc-f450-dc2f-82f2c7566997.png)](https://qiita.com/kojix2/items/456259f40d5563005cd1)

* [Rubyでグラフを描画するツール GR.rb の紹介](https://qiita.com/kojix2/items/456259f40d5563005cd1)

GR.rbは`libgr`のバインディングです。私は普段Windowsを使っていません。しかし、ありがたいことに是非Windowsに対応してほしいという要望があって、[詳しい方](https://github.com/kou)にPKGBUILDの作成からMinGWにlibgrのパッケージ登録まで全部やって頂きました。

それから少し時間が流れて、本家libgrのバージョンも少しずつ上がっていくので、そろそろアップデートしないといけないなと思い、重い腰を上げて 0.50.0 → 0.51.2 にアップデートしました。

MingGWのパッケージのアップデート、結果的には難しくなかったのですが、MinGWのパッケージをアップデートした日本語の体験記事が全然なくてとても心細い思いをしました。誰かの役に立つようにQiita記事を書きます。

## やり方

基本的な方法はhomebrewなどと変わりません。

MSYS2公式ページ
https://www.msys2.org/wiki/Creating-Packages/

に必要な情報が載っていますので、Google翻訳などを使ってざっと目を通すと良いと思われます。

### pacmanアップデート

```
pacman -Syu
```

一応作業に入る前にパッケージ群をアップデートしておきましょう。

### git clone

あとから `origin` を変更してもいいのですが、最初からForkしてしまった方が作業が楽ですね。

```
git clone https://github.com/kojix2/MINGW-packages # kojix2を各自のidに変更
cd MINGW-packages/mingw-w64-gr
```

### PKGBUILDの編集

パッケージのバージョン番号を更新します。

```sh:PKGBUILD
pkgver=0.51.2
```

[ソースコード `tar.gz` ファイル](https://github.com/sciapp/gr/releases) のsha256sumを更新します。
sha256sum はWindowsの場合、右クリック->プロパティ->ハッシュ のタブを開いてコピーします。

```sh:PKGBUILD
sha256sums=("E6A3D0ED911F6E59CC2293B5694EE18A0620849E666143870A9EDA71C02BB833")
```

また、今回は、前回適応されていたパッチが不要のようだったので取り除きました。

### ビルドとインストール

i686もビルドする場合は以下。

```
pacman -S mingw-w64-i686-toolchain
```

そして

```
MINGW_ARCH=mingw64 makepkg-mingw -sLf
pacman -U mingw-w64-*-gr-*-any.pkg.tar.xst
```

でできます。

### プルリクエストを送る

大丈夫そうだったらブランチを切って[プルリクエスト](https://github.com/msys2/MINGW-packages/pulls)を送りましょう。
忘れずに

```
git pull --rebase
```

ブランチの名前はなんでも良さそうですが、`gr-0.51.2` としました。`update-gr` とかでも大丈夫です。
プルリクエストのコミットは、皆さん大文字、小文字が入り乱れていますが、
`gr: Update to 0.51.2` もしくは `gr: update to 0.51.2` とすればよいようです。

プルリクエストを提出したら、ちゃんとCIが通過しているか確認しましょう。
通過していればメンテナンスをされている方がチェックしてマージしてくれるはずです。

今回のPRは数時間のうちに無事にmergeされました。かなり活発にメンテナンスが行われているようです。

## おわりに

MinGWもバージョンをアップデートするだけなら怖くない！

この記事は以上です。
DockerHubタグ一覧取得

# 言い訳
[DockerHub Dockerイメージのタグ一覧を取得するコマンドを作る](https://qiita.com/ucan-lab/items/a261e692678e6c2923b0)と、ほぼ同じ内容だったことに気づいたが…  
面倒だと言いながら毎回検索してた自分への自戒を込めてアップしておく。

# 内容
DockerHubのタグ検索するのが面倒だったので、コマンドにした。

## curl と grep でやると
```bash
$ curl -s https://registry.hub.docker.com/v1/repositories/php/tags | grep -o "\"name\":[^}]*" | grep 5.6.9
"name": "5.6.9"
"name": "5.6.9-apache"
"name": "5.6.9-cli"
"name": "5.6.9-fpm"
```

## bash においておくなら
```bash
function docker_search_tags {
  curl -s https://registry.hub.docker.com/v1/repositories/$1/tags | grep -o "\"name\":[^}]*"
}
```
で、

```bash
$ docker_search_tags php | grep 8.0.0alpha3
"name": "8.0.0alpha3"
"name": "8.0.0alpha3-alpine"
"name": "8.0.0alpha3-alpine3.12"
"name": "8.0.0alpha3-apache"
"name": "8.0.0alpha3-apache-buster"
"name": "8.0.0alpha3-buster"
"name": "8.0.0alpha3-cli"
"name": "8.0.0alpha3-cli-alpine"
"name": "8.0.0alpha3-cli-alpine3.12"
"name": "8.0.0alpha3-cli-buster"
"name": "8.0.0alpha3-fpm"
"name": "8.0.0alpha3-fpm-alpine"
"name": "8.0.0alpha3-fpm-alpine3.12"
"name": "8.0.0alpha3-fpm-buster"
"name": "8.0.0alpha3-zts"
"name": "8.0.0alpha3-zts-buster"
```
な感じ。
AutomationAnywhereA2019でローカルデバイスへの接続設定について

# Bot Agentについて
ローカルPC上でのボット実行は、ローカルPCにインストールしたBot Agentによって行う。
このため、クラウド上のControlRoomから、ボットを実行するローカルPCに接続できる必要がある。

# ローカルデバイス接続状態確認
しかし、以下のように、画面右上のPCアイコンに赤い！マークがついていると、Control Roomから、ローカルデバイス（PC）に接続できていない状態であることを指している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/f807db48-60c2-999c-2d21-769741ada81a.png)


# ローカルデバイス接続設定手順
上記の状態の場合、以下手順で、ローカルデバイス（PC)への接続設定を行う。

1. デバイス接続　押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/a8336fc3-a3b6-7f4e-0e46-844654c53d84.png)


1. コンピューターに接続　押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/baee349d-71a9-4d1d-f228-667108d35e69.png)

1. すでにBot AgentをローカルPCにインストールしている場合は、以下の表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/4dbf86cd-4847-de4b-8a16-8f9973c3fd2f.png)
※Bot Agentのインストール方法は以下

1. PCのログインユーザー名・パスワード（WindowsのローカルユーザーのID・パスワード）も正しいか確認し更新
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/3cf7e6c1-b445-9447-445f-12ed36cb8075.png)

1. PCアイコンが、緑になっていれば、OK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/05a0c436-331b-92f3-8bbd-42d540c1d789.png)

1. 設定が成功していれば、デバイス画面に対象PCと接続できていることを確認できる。
どうしてもうまくいかなければ、ここから削除して再接続しなおすのも手。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/790761f4-bc7e-424a-4c3f-7876dccc20d1.png)


# 参照（Enterpriseの説明だがCommunity Editionでも同様）
デバイスの登録と Bot Agent のインストール
https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/control-room/devices/cloud-add-local-device.html?_LANG=jpjp
RailsにVue.jsを導入する準備

# はじめに

バージョン
Ruby   '2.6.5'
Rails  '6.0.3'
Vue.js '2.6.11'

Railsは6.0以降。

# Vue.jsの導入
Webpackerを用いてインストール

```:ターミナル
rails webpacker:install:vue
```
Vue.jsを読み込む

```erb:app/view/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Title</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all' %>
    <%= javascript_pack_tag 'application' %>
　　<%# 以下の一行を追加 %>
    <%= javascript_pack_tag 'hello_vue' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

```
localhost:3000へアクセスして、"Hello Vue!"と表示されていれば、
導入と読み込みは上手くいっています。
ECSなコンテナにSSM Parameter Storeの値を渡して保持させる

# はじめに
ECSの環境変数機能のちょっとニッチな使い方。
コンテナに固め込んで起動することから、動的に変更することができなくなるので注意。環境情報はコンテナから切り離すというプラクティスから離れるアンチパターンであることを意識して、コンテナ化するプロダクトがクラウドにリフトするだけのケース等やむを得ない場合だけ利用することを推奨。

# SSM Parameter Storeの参照方法
コンテナのアプリケーションからSDKを使って参照するという方法もあるが、もっとお手軽に実装するのが、ECSの(正確にはタスク定義の)環境変数を使うのが良い。

[以前の記事](https://qiita.com/neruneruo/items/ff6747a4129a5b52e6c6#ecs%E3%81%A7%E3%82%82%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)で書いた「コンテナの編集」⇒「環境変数」から設定可能だ。プルダウンで「ValueFrom」を選択して、Parameter StoreのARNを指定する。

TerraformでIaCで記述するのであれば、```aws_ssm_parameter```リソースを

```HCL
resource "aws_ssm_parameter" "test" {
  name        = "/${var.environment}/teststring"
  description = "Test for SSM Parameter Store"
  type        = "SecureString"
  value       = "this-is-test-string"

  tags = {
    environment = var.environment
  }
}
```

な感じで定義し、これを```aws_ecs_task_definition```リソースの中で

```HCL
resource "aws_ecs_task_definition" "ecsfargate" {
  :
(中略)
  :
  container_definitions = <<EOF
  [
    {
      "name" : "${local.container_name}",
      "image": "${data.aws_ecr_repository.my_image.repository_url}:latest",
      "cpu": 0,
      "memoryReservation": 256,
      "secrets": [
        {
          "name": "TESTSTRING",
          "valueFrom": "${aws_ssm_parameter.test.arn}"
        }
      ],
  :
(以下略)
```

として参照する。

あとは、アプリケーションの中で環境変数で参照するなり、Dockerの起動コマンドの中で参照するなりしてあげれば期待通りのことができるようになる。

ただし、上記の通り、```aws_ssm_parameter```の```type```プロパティが```SecureString```であるにもかかわらず、.tfファイル中の文字列は平文になってしまっている。チームで作業する場合なんかは、非常によろしくないのではなかろうか……。
ちなみに、[Terraformの公式ドキュメント](https://www.terraform.io/docs/state/sensitive-data.html?_ga=2.102664257.1968678985.1596853187-175406154.1590201164)では、「Terraform Cloud使うかリモートステートでちゃんと暗号化してね！」と書いてある。terraform.stateファイルはともかくとして、ローカル情報を暗号化したまま渡すことはできないのだろうか……。
Jenkins + GitLab 連携のパイプライン

Jenkinsパイプラインの中からGitLabリポジトリのソースコードをクローンする方法について、ポイントのみを記載した忘備録である。 GitLabはGitHubと異なり、sshによるアクセスとなるため、GitHubとは異なる方法の `git clone` が必要なためだ。


## 必要なプラグイン GitLab Plugin

GitLabリポジトリにアクセスするための認証情報を処理するために、GitLab プラグインが必要となる。「Jenkins の管理」->「プラグインマネージャー」から「利用可能」の中から `GitLab`を検索してインストールする。 今回利用した GitLab のバージョンは、1.5.13 である。

参考資料 GitLab プラグインページ,https://plugins.jenkins.io/gitlab-plugin/


## GitLabのAPI取得

GitLabとJenkinsが連携するためには、GitLabのAPIキーをJenkinsの認証情報にセットする必要がある。APIキーの取得方法は、GitLabのウェブ画面の右上隅のアカウントのメニューを展開して、Settings を開く。次はSettingsの画面である。この右サイドのメニューの**Access Tokens** を選択する。次の例のように、名前、有効期限、権限をチェックして、**Create personal access token** をクリックすると、キーが表示されるのでコピーしておく。

![ss-3-api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/9c5cb830-c377-2dd4-57a4-a7f7ff8af1a7.png)

## Jenkinsfileの取り込み

再びJenkinsに戻って、「新規ジョブの作成」->「パイプライン」からジョブのスペックを設定する。パイプラインに移動して、「Pipeline script from SCM」と SCMにGitを選択する。

リポジトリURLは、GitLabでクローンする時と同じように、プロトコルに ssh を指定する。`ssh://git@gitlab.labs.local:2224/takara/test-internal.git` 

「認証情報」を「ビルドするブランチ」を設定する。

![ss-1-pipeline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/46030bbc-5880-afd5-2582-652571fd98d5.png)


## 認証情報の取り込み

認証情報を追加する際に、次のように **GitLab API token** を選択して、先に取得したGitLabで生成したAPIをセットする。

![ss-2-credential.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/132f092f-6ace-0846-d184-68ca7bd7ae06.png)


## パイプライン Jenkinsfile

GitLabリポジトリに登録してあるJenkinsfileを、ここに掲載しておく。このパイプラインは、GitLabのリポジトリからクローンして、コンテナをビルド、Harborのコンテナレジストリへ登録、Kubernetesクラスタへマニフェストをデプロイする。

checkoutの説明は、https://github.com/jenkinsci/gitlab-plugin#pipeline-jobs にある。


~~~Jenkinsfile:
pipeline {
    environment {
	registry = "harbor.labs.local/library/myweb"
	dockerImage = ""
	KUBECONFIG = credentials('kubeconfig')
    }
    
    agent any
    stages {
        stage("gitlabからのクローン") {
          steps {
            checkout([$class: 'GitSCM',
                      branches: [[name: '*/master' ]],
                      extensions: scm.extensions,
                      userRemoteConfigs: [[
			        url: "$GIT_URL",
                        credentialsId: 'gitlab-sshkey2'
                       ]]
                     ])
          }
        }
        stage("test") {
          steps {
                sh 'ls -al'
		        sh 'env'
          }
        }
	stage('コンテナイメージのビルド') {
	    steps {
		script {
		    dockerImage = docker.build registry + ":$BUILD_NUMBER"
		}
	    }
	}
	stage('コンテナレジストリへプッシュ') {
	    steps {
		script {
		    docker.withRegistry("https://harbor.labs.local/v1/","harborproj1") {
			dockerImage.push()
		    }
		}
	    }
	}
	stage('K8sクラスタへのデプロイ') {
	    steps {
		script {
		   sh 'kubectl cluster-info --kubeconfig $KUBECONFIG'
		   sh 'sed s/__BUILDNUMBER__/$BUILD_NUMBER/ myweb.yaml > deploy_myweb.yaml'
		   sh 'kubectl apply -f deploy_myweb.yaml --kubeconfig $KUBECONFIG'
		}
	    }
	}
    }
}
~~~

## まとめ

これで、GitLabとJenkinsの連携の難関を超えて、Jenkins, Harbor, GitLab, Kubernetesを連携させて、GitOpsパイプラインを作ることができる。
Base64エンコードされたProtocol Bufferバイナリデータの中身を表示する

Protocol Buffer のデータの中身をログに出したい時Base64エンコードして出すことがあるのですが、Base64から戻す方法を時々忘れるのでメモ。

```
echo $BINARY_DATA_BASE_64 | base64 -D | od -t x1 -An | tr -d '\r\n ' | xxd -r -p | protoc --decode_raw
```

Hex String でログに出してるときは

```
echo $HEX_DATA | xxd -r -p | protoc --decode_raw
```
SQL Server 2014 Express ダウンロード・インストール手順

# はじめに
SQL Server 2014 の無償版、Expressのインストール手順について説明する。

注）ちょっと古いバージョンですが。。過去にインストールした際の手順です。
　　あくまで私が使用する際の手順のため、用途によってはこの限りではありませんので、
　　インストール作業の雰囲気を知るための参考程度でお願いします。

# ダウンロード
以下からダウンロードする。
DOWNLOAD MICROSOFT® SQL SERVER® 2014 EXPRESS FROM OFFICIAL MICROSOFT DOWNLOAD CENTER HTTPS://WWW.MICROSOFT.COM/JA-JP/DOWNLOAD/DETAILS.ASPX?ID=42299

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/a951d714-2915-84d5-b596-9f5333a92608.png)

64bit 版を選ぶ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/b218dea4-a876-694c-06f8-fb2fb187545e.png)

# インストール

1. ダウンロードしたSQLEXPRADV_x64_JPN.exe 実行を実行し、解凍されたフォルダの「SETUP.EXE」実行


1. インストールセンターで、SQL Serverの新規スタンドアロン　インストール～　を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/f22523c5-2690-2c07-bd70-34a57b443989.png)

1. ライセンス条項に同意します。　にチェックして、次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/09bd40bb-eb11-d8b5-cff0-b83a724cb102.png)

1. 必要機能にチェックを入れて、次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/0a452103-be44-874e-3a12-8c1d77d277ce.png)

1. 特に理由が無い限り、そのまま次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/caf2e648-108f-a485-70c4-3165f5537475.png)

1. そのまま次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/0bde424b-c57c-b115-7065-afab53abc3c4.png)

1. 混合モードを選択。
管理者のユーザーを選択。また、SQL Server認証用ユーザーID・パスワードを設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/500e67a1-8668-269f-b316-dd3e980df470.png)

1. SSRS そのまま次へ　※Reporting Servicesをインストールしない場合は、当画面は出ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/a2e02077-22f8-6fd2-fc53-c9b67d88fd3c.png)

1. 内容に問題なければ、インストール押下
（画面採取を失念...）

1. しばらく待つ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/5d461892-fdfa-e442-b985-96707b0c0564.png)

1. 完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217757/1c53064a-c5a1-4dbc-ca69-948a5d4d9056.png)

以上！